Skip to content

Commit

Permalink
Merge branch 'main' into khoa/client-restructure
Browse files Browse the repository at this point in the history
  • Loading branch information
khoaguin committed Oct 16, 2024
2 parents 496e704 + ba440b4 commit 13fd399
Show file tree
Hide file tree
Showing 12 changed files with 361 additions and 58 deletions.
2 changes: 1 addition & 1 deletion .bumpversion.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.1.7
current_version = 0.1.8
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)
serialize =
{major}.{minor}.{patch}
Expand Down
2 changes: 1 addition & 1 deletion docker/syftbox.dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ FROM cgr.dev/chainguard/wolfi-base

ARG PYTHON_VERSION="3.12"
ARG UV_VERSION="0.4.20-r0"
ARG SYFT_VERSION="0.1.7"
ARG SYFT_VERSION="0.1.8"

RUN apk update && apk upgrade && \
apk add --no-cache python-$PYTHON_VERSION uv=$UV_VERSION
Expand Down
2 changes: 1 addition & 1 deletion justfile
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ build:
install:
rm -rf dist
uv build
uv tool install $(ls /Users/madhavajay/dev/syft/dist/*.whl) --reinstall
uv tool install $(ls ./dist/*.whl) --reinstall

# Bump version, commit and tag
[group('build')]
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "syftbox"
version = "0.1.7"
version = "0.1.8"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.9"
Expand Down
2 changes: 1 addition & 1 deletion syftbox/__version__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@
__title__ = "SyftBox"
__description__ = ""
__url__ = "https://openmined.org"
__version__ = "0.1.7"
__version__ = "0.1.8"
15 changes: 7 additions & 8 deletions syftbox/app/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ def run_pre_install(app_config: SimpleNamespace):
)


def run_post_install(app_config: SimpleNamespace):
def run_post_install(app_config: SimpleNamespace, app_path: str):
"""
Runs post-installation commands specified in the application configuration.
Expand Down Expand Up @@ -479,12 +479,11 @@ def run_post_install(app_config: SimpleNamespace):
return

subprocess.run(
app_config.app.post_install,
check=True,
text=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
app_config.app.post_install,
cwd=app_path,
check=True,
text=True,
)


def check_os_compatibility(app_config) -> None:
Expand Down Expand Up @@ -760,7 +759,7 @@ def install(client_config: ClientConfig) -> None | Tuple[str, Exception]:
# Handles: Exceptions from post-install command execution
if app_config:
step = "Running post-install commands"
run_post_install(app_config)
run_post_install(app_config, app_config_path)

# NOTE:
# Updates the apps.json file
Expand Down
16 changes: 14 additions & 2 deletions syftbox/app/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,21 @@ def parse_args():


def main(parser, args_list) -> None:
# Color codes for Error prompts
RED = "\033[38;5;210m"
RESET = "\033[0m"
YELLOW_PASTEL = "\033[38;5;229m"
args, remaining_args = parse_args()
client_config = ClientConfig.load(args.config_path)

try:
client_config = ClientConfig.load(args.config_path)
except Exception:
print(
f"\n{RED}Error:{RESET} Couldn't find the proper client_config.json in: {YELLOW_PASTEL}{args.config_path}{RESET}.\n\n"
+ "Please ensure that:\n"
+ "\t- The configuration file exists at the specified path.\n"
+ f"\t- Provide the proper path by adding the {YELLOW_PASTEL}--config_path /path/to/client_config.json{RESET}"
)
return
commands = make_commands()
# Handle the subcommands as needed
if args.command:
Expand Down
26 changes: 21 additions & 5 deletions syftbox/client/plugins/sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ def diff_dirstate(old: DirState, new: DirState):
changes.append(change)
else:
logger.info(
f"🔥 Skipping delete {file_info}. File change is < 3 seconds ago"
f"🔥 Skipping delete {afile} {file_info}. File change is < {SECS_SINCE_CHANGE} seconds ago"
)
return changes
except Exception as e:
Expand Down Expand Up @@ -210,8 +210,11 @@ def filter_changes(
valid_changes = []
valid_change_files = []
invalid_changes = []
invalid_permissions = []
for change in changes:
if change.kind in [
if perm_tree.has_corrupted_permission(change.full_path):
invalid_permissions.append(change)
elif change.kind in [
FileChangeKind.WRITE,
FileChangeKind.CREATE,
FileChangeKind.DELETE,
Expand All @@ -232,8 +235,9 @@ def filter_changes(
# valid_change_files.append(change.sub_path)
# continue

invalid_changes.append(change)
return valid_changes, valid_change_files, invalid_changes
else:
invalid_changes.append(change)
return valid_changes, valid_change_files, invalid_changes, invalid_permissions


def push_changes(
Expand Down Expand Up @@ -501,7 +505,19 @@ def sync_up(client_config: ClientConfig):
if len(changes) == 0:
continue

val, val_files, inval = filter_changes(client_config.email, changes, perm_tree)
val, val_files, inval_changes, inval_permissions = filter_changes(
client_config.email, changes, perm_tree
)
if len(inval_permissions) > 0:
logger.warning(
f"Filtered {len(inval_permissions)} changes with corrupted permissions"
)
inval_permission_files = [
change.internal_path for change in inval_permissions
]
logger.debug(
f"Filtered changes with corrupted permissions: {inval_permission_files}"
)

# send val changes
results = push_changes(client_config, val)
Expand Down
38 changes: 34 additions & 4 deletions syftbox/lib/lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@ def datasite_default(cls, email: str) -> Self:
write=[email],
)

def has_read_permission(self, email: str) -> bool:
return email in self.read or USER_GROUP_GLOBAL in self.read

def __eq__(self, other):
if not isinstance(other, SyftPermission):
return NotImplemented
Expand Down Expand Up @@ -326,24 +329,51 @@ class PermissionTree(Jsonable):
parent_path: str
root_perm: SyftPermission | None

corrupted_permission_files: list[str] = field(default_factory=list)

@classmethod
def from_path(cls, parent_path) -> Self:
def from_path(cls, parent_path, raise_on_corrupted_files: bool = False) -> Self:
corrupted_permission_files = []
perm_dict = {}
for root, dirs, files in os.walk(parent_path):
for file in files:
if file.endswith(".syftperm"):
path = os.path.join(root, file)
try:
perm_dict[path] = SyftPermission.load(path)
except Exception as e:
print(f"Failed to parse perm file at: {path}. {e}")
except Exception:
corrupted_permission_files.append(path)

root_perm = None
root_perm_path = perm_file_path(parent_path)
if root_perm_path in perm_dict:
root_perm = perm_dict[root_perm_path]

return cls(root_perm=root_perm, tree=perm_dict, parent_path=parent_path)
if corrupted_permission_files:
if raise_on_corrupted_files:
raise ValueError(
f"Found corrupted permission files: {corrupted_permission_files}"
)
logger.warning(
f"Found corrupted permission files: {corrupted_permission_files}"
)

return cls(
root_perm=root_perm,
tree=perm_dict,
parent_path=parent_path,
corrupted_permission_files=corrupted_permission_files,
)

def has_corrupted_permission(self, path: str | Path) -> bool:
path = Path(path).resolve()
corrupted_permission_paths = [
Path(p).parent.resolve() for p in self.corrupted_permission_files
]
for perm_path in corrupted_permission_paths:
if path.is_relative_to(perm_path):
return True
return False

@property
def root_or_default(self) -> SyftPermission:
Expand Down
6 changes: 4 additions & 2 deletions syftbox/server/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,9 @@ async def dir_state(

# get the top level perm file
try:
perm_tree = PermissionTree.from_path(full_path)
perm_tree = PermissionTree.from_path(
full_path, raise_on_corrupted_files=True
)
except Exception as e:
print(f"Failed to parse permission tree: {full_path}")
raise e
Expand All @@ -443,7 +445,7 @@ async def datasites(
server_settings: ServerSettings = Depends(get_server_settings),
) -> ListDatasitesResponse:
datasites = get_datasites(server_settings.snapshot_folder)
if datasites:
if isinstance(datasites, list):
return ListDatasitesResponse(
datasites=datasites,
status="success",
Expand Down
Loading

0 comments on commit 13fd399

Please sign in to comment.