diff --git a/.github/workflows/static_analysis.yml b/.github/workflows/static_analysis.yml index 60fd5c0..878ab43 100644 --- a/.github/workflows/static_analysis.yml +++ b/.github/workflows/static_analysis.yml @@ -31,6 +31,9 @@ jobs: - name: Check formatting run: uvx ruff format --check . + - name: Check statement order + run: uvx ssort --check --diff . + pyright: runs-on: ubuntu-latest steps: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 211ae9c..2effd49 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,6 +4,7 @@ repos: rev: v6.0.0 hooks: - id: check-yaml + - id: check-toml - id: end-of-file-fixer - id: trailing-whitespace - id: check-added-large-files # Prevent giant files from being committed. @@ -11,12 +12,16 @@ repos: exclude: ^(uv\.lock|docs/package-lock\.json)$ # generated lock files - id: check-merge-conflict # Check for files that contain merge conflict strings. - repo: https://github.com/kynan/nbstripout - rev: 0.9.0 + rev: 0.9.1 hooks: - id: nbstripout # strip jupyter notebook output + - repo: https://github.com/bwhmather/ssort + rev: 0.17.0 + hooks: + - id: ssort # order statements so names are defined before they are used - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.9.1 + rev: v0.17.3 hooks: - - id: ruff + - id: ruff-check # lint, including import sorting (the I rules) args: [--fix] - id: ruff-format diff --git a/Makefile b/Makefile index ece9999..acbf9bd 100644 --- a/Makefile +++ b/Makefile @@ -17,9 +17,10 @@ install: ## uv sync with the dev extra, and the pre-commit hooks test: ## pytest with coverage uv run pytest --cov . -lint: ## ruff and pyright +lint: ## ruff, ssort and pyright uv run ruff check . uv run ruff format --check . + uvx ssort --check --diff . uv run pyright src/ readme: ## render README.md from README.qmd with quarto diff --git a/scripts/check_pypi_dependencies.py b/scripts/check_pypi_dependencies.py index 1825bb7..5dcc01a 100644 --- a/scripts/check_pypi_dependencies.py +++ b/scripts/check_pypi_dependencies.py @@ -91,6 +91,13 @@ def is_installable(releases: Releases, requirement: Requirement) -> bool: return False +def _version_key(text: str) -> Version: + try: + return Version(text) + except InvalidVersion: + return Version("0") + + def check(pyproject: dict, fetch: Fetch = fetch_releases) -> list[str]: """Return one message per dependency that PyPI would reject or that cannot be installed.""" project = pyproject.get("project", {}) @@ -139,13 +146,6 @@ def check(pyproject: dict, fetch: Fetch = fetch_releases) -> list[str]: return problems -def _version_key(text: str) -> Version: - try: - return Version(text) - except InvalidVersion: - return Version("0") - - def main(argv: list[str] | None = None) -> int: """Run the check on a pyproject.toml; return the exit status.""" parser = argparse.ArgumentParser(description=__doc__.split("\n\n")[0])