Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .github/workflows/main-workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,15 @@ jobs:

- name: Python Lint Check
run: poetry run ruff check tools

- name: Python Docstring Check
run: poetry run pydocstyle -es --count --config=pyproject.toml tools
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apparently ruff might be able to replace pydocstyle now? It has a plugin, anyway https://docs.astral.sh/ruff/settings/#lint_pydoclint_ignore-one-line-docstrings


- name: Python Security Check
run: poetry run bandit --quiet -r -c pyproject.toml tools

- name: Python Type Check
run: poetry run mypy --config-file=pyproject.toml tools
# Rust lint and format checks ======
rust-checks:
needs: rust-env
Expand Down
12 changes: 12 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,18 @@ py-deps-latest: $(INSTALL_STAMP) ## Checks latest versions in PyPI
py-deps-outdated: $(INSTALL_STAMP) ## Checks for outdated Python packages
$(POETRY) show --outdated $(TOOLS_DIR)

.PHONY: bandit
bandit: $(INSTALL_STAMP) ## Run bandit
$(POETRY) run bandit --quiet -r -c $(ROOT_PYPROJECT_TOML) $(TOOLS_DIR)

.PHONY: mypy
mypy: $(INSTALL_STAMP) ## Run mypy
$(POETRY) run mypy --config-file=$(ROOT_PYPROJECT_TOML) $(TOOLS_DIR)

.PHONY: pydocstyle
pydocstyle: $(INSTALL_STAMP) ## Run pydocstyle
$(POETRY) run pydocstyle -es --count --config=$(ROOT_PYPROJECT_TOML) $(TOOLS_DIR)

# Documentation utilities
.PHONY: doc-install-deps
doc-install-deps: ## Install the dependencies for doc generation
Expand Down
38 changes: 38 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,44 @@ black = "^26.3.1"
bandit = "^1.9.4"
isort = "^8.0.1"

[tool.pydocstyle]
match = ".*\\.py"
convention = "pep257"
# Error Code Ref: https://www.pydocstyle.org/en/stable/error_codes.html
# D212 Multi-line docstring summary should start at the first line
add-select = ["D212"]
# D105 Docstrings for magic methods
# D107 Docstrings for __init__
# D203 as it conflicts with D211 https://github.com/PyCQA/pydocstyle/issues/141
# D205 1 blank line required between summary line and description, awkward spacing
# D400 First line should end with a period, doesn't work when sentence spans 2 lines
add-ignore = ["D105","D107","D203", "D205", "D400"]

[tool.bandit]
# B101: https://bandit.readthedocs.io/en/latest/plugins/b101_assert_used.html
# B104: https://bandit.readthedocs.io/en/latest/plugins/b104_hardcoded_bind_all_interfaces.html
# B105: https://bandit.readthedocs.io/en/latest/plugins/b105_hardcoded_password_string.html — test fixture secrets only
# B106: https://bandit.readthedocs.io/en/latest/plugins/b106_hardcoded_password_funcarg.html — test fixture secrets only
# B311: https://bandit.readthedocs.io/en/latest/blacklists/blacklist_calls.html#b311-random
# B404: https://bandit.readthedocs.io/en/latest/blacklists/blacklist_imports.html#b404-import-subprocess
# B603: https://bandit.readthedocs.io/en/latest/plugins/b603_subprocess_without_shell_equals_true.html — subprocess on trusted internal binary path
skips = ["B101", "B104", "B105", "B106", "B311", "B404", "B603"]

[tool.mypy]
python_version = "3.12"
disable_error_code = "attr-defined"
disallow_untyped_calls = false
follow_imports = "normal"
ignore_missing_imports = true
pretty = true
show_error_codes = true
strict_optional = true
warn_no_return = true
warn_redundant_casts = true
warn_return_any = true
warn_unused_ignores = true
warn_unreachable = true

[build-system]
requires = ["poetry-core>=2.0.0,<3.0.0"]
build-backend = "poetry.core.masonry.api"
1 change: 1 addition & 0 deletions tools/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Tools package for syncstorage-rs utilities and scripts."""
1 change: 1 addition & 0 deletions tools/hawk/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Hawk authentication utilities package."""
46 changes: 23 additions & 23 deletions tools/hawk/poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions tools/hawk/test_make_hawk_token.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""Tests for the make_hawk_token utility script."""

import argparse
import time
from typing import Any
Expand Down
1 change: 1 addition & 0 deletions tools/integration_tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Integration tests package for syncstorage-rs."""
40 changes: 17 additions & 23 deletions tools/integration_tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
"""Pytest configuration and fixtures for integration tests."""

import os
import psutil
import signal
import subprocess
import time
import pytest
import requests
import requests # type: ignore[import-untyped]
import logging

DEBUG_BUILD = "target/debug/syncserver"
Expand All @@ -19,9 +21,7 @@


def _terminate_process(process):
"""
Gracefully terminate the process and its children.
"""
"""Gracefully terminate the process and its children."""
proc = psutil.Process(pid=process.pid)
child_proc = proc.children(recursive=True)
for p in [proc] + child_proc:
Expand All @@ -30,10 +30,10 @@ def _terminate_process(process):


def _wait_for_server_startup(max_attempts=SYNC_SERVER_STARTUP_MAX_ATTEMPTS):
"""
Waits for the __heartbeat__ endpoint to return a 200, pausing for 1 second
between attempts. Raises a RuntimeError if the server does not start after
the specific number of attempts.
"""Wait for the __heartbeat__ endpoint to return a 200.

Pause for 1 second between attempts. Raise a RuntimeError if the server
does not start after the specific number of attempts.
"""
itter = 0
while True:
Expand All @@ -50,10 +50,7 @@ def _wait_for_server_startup(max_attempts=SYNC_SERVER_STARTUP_MAX_ATTEMPTS):


def _start_server():
"""
Starts the syncserver process, waits for it to be running,
and return the process handle.
"""
"""Start the syncserver process, wait for it to be running, and return the handle."""
target_binary = None
if os.path.exists(DEBUG_BUILD):
target_binary = DEBUG_BUILD
Expand All @@ -63,8 +60,7 @@ def _start_server():
raise RuntimeError("Neither {DEBUG_BUILD} nor {RELEASE_BUILD} were found.")

server_proc = subprocess.Popen(
target_binary,
shell=True,
[target_binary],
text=True,
env=os.environ,
)
Expand All @@ -75,9 +71,7 @@ def _start_server():


def _server_manager():
"""
Context manager to gracefully start and stop the server.
"""
"""Gracefully start and stop the server as a context manager."""
server_process = _start_server()
try:
yield server_process
Expand All @@ -86,8 +80,8 @@ def _server_manager():


def _set_local_test_env_vars():
"""
Set environment variables for local testing.
"""Set environment variables for local testing.

This function sets the necessary environment variables for the syncserver.
"""
os.environ.setdefault("SYNC_MASTER_SECRET", "secret0")
Expand All @@ -104,8 +98,8 @@ def _set_local_test_env_vars():

@pytest.fixture(scope="session")
def setup_server_local_testing():
"""
Fixture to set up the server for local testing.
"""Set up the server for local testing.

This fixture sets the necessary environment variables and
starts the server.
"""
Expand All @@ -115,8 +109,8 @@ def setup_server_local_testing():

@pytest.fixture(scope="session")
def setup_server_end_to_end_testing():
"""
Fixture to set up the server for end-to-end testing.
"""Set up the server for end-to-end testing.

This fixture sets the necessary environment variables and
starts the server.
"""
Expand Down
Loading
Loading