Skip to content

Commit

Permalink
Fixed linting with ruff
Browse files Browse the repository at this point in the history
- Fixed issue with old python and typing extensions
  • Loading branch information
madhavajay committed Sep 16, 2024
1 parent 6f3db5d commit b2cca4d
Show file tree
Hide file tree
Showing 9 changed files with 487 additions and 103 deletions.
1 change: 1 addition & 0 deletions .github/workflows/pr-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ jobs:
matrix:
os: [ubuntu-latest, macos-latest]
python-version: ["3.12", "3.11", "3.10"]
fail-fast: false

runs-on: ${{ matrix.os }}
steps:
Expand Down
23 changes: 1 addition & 22 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,30 +28,9 @@ repos:
- id: mixed-line-ending
args: ["--fix=lf"]

- repo: https://github.com/MarcoGorelli/absolufy-imports # This repository has been archived by the owner on Aug 15, 2023. It is now read-only.
rev: v0.3.1
hooks:
- id: absolufy-imports
always_run: true

- repo: https://github.com/pycqa/isort
rev: 5.13.2
hooks:
- id: isort
name: isort
args: [".", "--settings-path .isort.cfg"]
always_run: true

- repo: https://github.com/nbQA-dev/nbQA
rev: 1.8.5
# nbQA has no files attribute
# files: "^notebooks/(api|tutorials|admin)"
hooks:
- id: nbqa-isort

- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: "v0.4.7"
rev: "v0.6.5"
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix, --show-fixes]
Expand Down
9 changes: 9 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ dependencies = [
"uvicorn>=0.30.6",
"apscheduler>=3.10.4",
"jinja2>=3.1.4",
"typing-extensions>=4.12.2",
]

[build-system]
Expand All @@ -33,3 +34,11 @@ pythonpath = ["."]

[project.optional-dependencies]
dev = ["pytest", "pytest-xdist[psutil]", "pytest-cov", "mypy", "uv", "ruff"]


[tool.ruff]
line-length = 88
exclude = ["data", "users", "build", "dist", ".venv"]

[tool.ruff.lint]
extend-select = ["I"]
59 changes: 39 additions & 20 deletions syftbox/client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import types
from dataclasses import dataclass
from pathlib import Path
from typing import Tuple

import uvicorn
from apscheduler.schedulers.background import BackgroundScheduler
Expand Down Expand Up @@ -72,7 +71,8 @@ def search_icon_file():
try:
# cant use other zip tools as they don't unpack it correctly
subprocess.run(
["ditto", "-xk", str(zip_file), str(src_path.parent)], check=True
["ditto", "-xk", str(zip_file), str(src_path.parent)],
check=True,
)

# Try to find the Icon\r file again after extraction
Expand All @@ -84,7 +84,7 @@ def search_icon_file():

# If still not found, raise an error
raise FileNotFoundError(
"Icon file with a carriage return not found, and icon.zip did not contain it."
"Icon file with a carriage return not found, and icon.zip did not contain it.",
)


Expand Down Expand Up @@ -120,7 +120,8 @@ def load_or_create_config(args) -> ClientConfig:

if client_config.sync_folder is None:
sync_folder = get_user_input(
"Where do you want to Sync SyftBox to?", DEFAULT_SYNC_FOLDER
"Where do you want to Sync SyftBox to?",
DEFAULT_SYNC_FOLDER,
)
sync_folder = os.path.abspath(os.path.expanduser(sync_folder))
client_config.sync_folder = sync_folder
Expand Down Expand Up @@ -184,10 +185,14 @@ def load_plugins(client_config: ClientConfig) -> dict[str, Plugin]:
try:
module = importlib.import_module(f"plugins.{plugin_name}")
schedule = getattr(
module, "DEFAULT_SCHEDULE", 5000
module,
"DEFAULT_SCHEDULE",
5000,
) # Default to 5000ms if not specified
description = getattr(
module, "DESCRIPTION", "No description available."
module,
"DESCRIPTION",
"No description available.",
)
plugin = Plugin(
name=plugin_name,
Expand All @@ -202,9 +207,11 @@ def load_plugins(client_config: ClientConfig) -> dict[str, Plugin]:
return loaded_plugins


def generate_key_pair() -> Tuple[bytes, bytes]:
def generate_key_pair() -> tuple[bytes, bytes]:
private_key = rsa.generate_private_key(
public_exponent=65537, key_size=2048, backend=default_backend()
public_exponent=65537,
key_size=2048,
backend=default_backend(),
)
public_key = private_key.public_key()

Expand Down Expand Up @@ -259,12 +266,14 @@ def run_plugin(plugin_name):
def start_plugin(plugin_name: str):
if plugin_name not in app.loaded_plugins:
raise HTTPException(
status_code=400, detail=f"Plugin {plugin_name} is not loaded"
status_code=400,
detail=f"Plugin {plugin_name} is not loaded",
)

if plugin_name in app.running_plugins:
raise HTTPException(
status_code=400, detail=f"Plugin {plugin_name} is already running"
status_code=400,
detail=f"Plugin {plugin_name} is already running",
)

try:
Expand All @@ -284,21 +293,25 @@ def start_plugin(plugin_name: str):
return {"message": f"Plugin {plugin_name} started successfully"}
except Exception as e:
raise HTTPException(
status_code=500, detail=f"Failed to start plugin {plugin_name}: {str(e)}"
status_code=500,
detail=f"Failed to start plugin {plugin_name}: {e!s}",
)


# Parsing arguments and initializing shared state
def parse_args():
parser = argparse.ArgumentParser(
description="Run the web application with plugins."
description="Run the web application with plugins.",
)
parser.add_argument("--config_path", type=str, help="config path")
parser.add_argument("--sync_folder", type=str, help="sync folder path")
parser.add_argument("--email", type=str, help="email")
parser.add_argument("--port", type=int, default=8080, help="Port number")
parser.add_argument(
"--server", type=str, default="http://localhost:5001", help="Server"
"--server",
type=str,
default="http://localhost:5001",
help="Server",
)
return parser.parse_args()

Expand Down Expand Up @@ -354,7 +367,8 @@ def get_client_email():
return JSONResponse(content={"email": email})
except AttributeError as e:
raise HTTPException(
status_code=500, detail=f"Error accessing client email: {str(e)}"
status_code=500,
detail=f"Error accessing client email: {e!s}",
)


Expand Down Expand Up @@ -409,7 +423,8 @@ def kill_plugin(request: PluginRequest):

if plugin_name not in app.running_plugins:
raise HTTPException(
status_code=400, detail=f"Plugin {plugin_name} is not running"
status_code=400,
detail=f"Plugin {plugin_name} is not running",
)

try:
Expand All @@ -421,19 +436,22 @@ def kill_plugin(request: PluginRequest):
return {"message": f"Plugin {plugin_name} stopped successfully"}
except Exception as e:
raise HTTPException(
status_code=500, detail=f"Failed to stop plugin {plugin_name}: {str(e)}"
status_code=500,
detail=f"Failed to stop plugin {plugin_name}: {e!s}",
)


@app.post("/file_operation")
async def file_operation(
operation: str = Body(...), file_path: str = Body(...), content: str = Body(None)
operation: str = Body(...),
file_path: str = Body(...),
content: str = Body(None),
):
full_path = Path(app.shared_state.client_config.sync_folder) / file_path

# Ensure the path is within the SyftBox directory
if not full_path.resolve().is_relative_to(
Path(app.shared_state.client_config.sync_folder)
Path(app.shared_state.client_config.sync_folder),
):
raise HTTPException(
status_code=403,
Expand All @@ -445,7 +463,7 @@ async def file_operation(
raise HTTPException(status_code=404, detail="File not found")
return FileResponse(full_path)

elif operation in ["write", "append"]:
if operation in ["write", "append"]:
if content is None:
raise HTTPException(
status_code=400,
Expand All @@ -462,7 +480,8 @@ async def file_operation(
return JSONResponse(content={"message": f"File {operation}ed successfully"})
except Exception as e:
raise HTTPException(
status_code=500, detail=f"Failed to {operation} file: {str(e)}"
status_code=500,
detail=f"Failed to {operation} file: {e!s}",
)

else:
Expand Down
3 changes: 2 additions & 1 deletion syftbox/client/plugins/init.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@

def register(client_config):
response = requests.post(
f"{client_config.server_url}/register", json={"email": client_config.email}
f"{client_config.server_url}/register",
json={"email": client_config.email},
)
j = response.json()
if "token" in j:
Expand Down
21 changes: 11 additions & 10 deletions syftbox/client/plugins/sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,9 @@ def delete_files(new, deleted_files) -> DirState:


def filter_changes(
user_email: str, changes: list[FileChange], perm_tree: PermissionTree
user_email: str,
changes: list[FileChange],
perm_tree: PermissionTree,
):
valid_changes = []
valid_change_files = []
Expand All @@ -117,12 +119,12 @@ def filter_changes(
user_email in perm_file_at_path.write
or "GLOBAL" in perm_file_at_path.write
) and perm_file_at_path.read != [
user_email
user_email,
]: # skip upload if only we have read perms.
valid_changes.append(change)
valid_change_files.append(change.sub_path)
continue
elif perm_file_at_path.read == [user_email]:
if perm_file_at_path.read == [user_email]:
if change.internal_path[-10:] == "_.syftperm":
# include changes for syft_perm file even if only we have read perms.
valid_changes.append(change)
Expand Down Expand Up @@ -159,7 +161,7 @@ def push_changes(client_config, changes):
written_changes.append(ok_change)
else:
print(
f"> {client_config.email} FAILED /write {change.kind} {change.internal_path}"
f"> {client_config.email} FAILED /write {change.kind} {change.internal_path}",
)
except Exception as e:
print("Failed to call /write on the server", str(e))
Expand Down Expand Up @@ -190,12 +192,12 @@ def pull_changes(client_config, changes):

if response.status_code == 200:
print(
f"> {client_config.email} /read {change.kind} {change.internal_path}"
f"> {client_config.email} /read {change.kind} {change.internal_path}",
)
remote_changes.append((ok_change, data))
else:
print(
f"> {client_config.email} FAILED /read {change.kind} {change.internal_path}"
f"> {client_config.email} FAILED /read {change.kind} {change.internal_path}",
)
except Exception as e:
print("Failed to call /read on the server", str(e))
Expand Down Expand Up @@ -235,9 +237,8 @@ def get_remote_state(client_config, sub_path: str):
if response.status_code == 200:
dir_state = DirState(**state_response["dir_state"])
return dir_state
else:
print(f"> {client_config.email} FAILED /dir_state: {sub_path}")
return None
print(f"> {client_config.email} FAILED /dir_state: {sub_path}")
return None
except Exception as e:
print("Failed to call /dir_state on the server", str(e))

Expand Down Expand Up @@ -355,7 +356,7 @@ def sync_down(client_config) -> int:
remote_dir_state = get_remote_state(client_config, datasite)
if not remote_dir_state:
print(f"No remote state for dir: {datasite}")
return
return None

changes = diff_dirstate(new_dir_state, remote_dir_state)

Expand Down
10 changes: 6 additions & 4 deletions syftbox/lib/lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
from enum import Enum
from pathlib import Path
from threading import Lock
from typing import Any, Self

from typing_extensions import Any, Self

USER_GROUP_GLOBAL = "GLOBAL"

Expand Down Expand Up @@ -199,7 +200,9 @@ def ignore_dirs(directory: str, root: str, ignore_folders=None) -> bool:


def hash_dir(
sync_folder: str, sub_path: str, ignore_folders: list | None = None
sync_folder: str,
sub_path: str,
ignore_folders: list | None = None,
) -> DirState:
state_dict = {}
full_path = os.path.join(sync_folder, sub_path)
Expand Down Expand Up @@ -301,8 +304,7 @@ def validate_email(email: str) -> bool:
# Use the match method to check if the email fits the pattern
if re.match(email_regex, email):
return True
else:
return False
return False


@dataclass
Expand Down
Loading

0 comments on commit b2cca4d

Please sign in to comment.