Skip to content

Lint: add ruff config (E,F,UP,B,I,NPY201) and replace flake8#302

Open
jeandet wants to merge 131 commits into
SciQLop:mainfrom
jeandet:modernisation/pr11-ruff-config
Open

Lint: add ruff config (E,F,UP,B,I,NPY201) and replace flake8#302
jeandet wants to merge 131 commits into
SciQLop:mainfrom
jeandet:modernisation/pr11-ruff-config

Conversation

@jeandet
Copy link
Copy Markdown
Member

@jeandet jeandet commented May 15, 2026

Summary

Eleventh PR of the modernisation effort. Adds ruff lint configuration (mirroring AstraLint), applies autofixes, and replaces flake8 across CI / Makefile / docs.

Plan: docs/superpowers/plans/2026-05-15-pr11-ruff-config.md.

Stacked on PR #301 (hatchling build backend) and the cassette-migration stack underneath.

What this PR does

  • pyproject.toml: replaces the narrow [tool.ruff.lint] select = ["NPY201"] block with the full configuration — rules E, F, UP, B, I, NPY201, line-length 100, AstraLint-mirrored ignore set (formatter-conflict rules omitted so PR 17's ruff format will land cleanly).
  • Applies ruff check --fix autofixes (590 of 769 initial findings) — dominated by UP (typing-syntax modernization, removing typing.{Dict,List,Optional,Tuple,Union} in favor of PEP 604/585) and I (import sorting).
  • Manually triages the remaining 163 findings (now zero). Bias toward fixing rather than # noqa. Final state: 8 targeted # noqa total across 770 initial findings, all with one-line reason comments (circular-import preservation, B017 numpy exception variants, B028 warnings).
  • Replaces flake8 with ruff in .github/workflows/lint.yml, Makefile, CLAUDE.md, and CONTRIBUTING.rst.
  • Drops the redundant flake8 step from unit.yml.

Notable manual fixes

Category Count Disposition
F401 unused typing imports (post-UP rewrite) 78 Removed; added __all__ to re-export __init__.py files
UP007/UP045 typing.Union| 10 Manual where module-level type aliases needed adjustment
F405/F403 star imports 15 Replaced with explicit name lists
B905 zip without strict 14 Added strict=False (preserves existing behavior)
B026 star-arg after kwarg 5 Reordered
E741 ambiguous names (l, I, O) 2 Renamed
Circular-import preservation 3 __init__.py files reordered back; # noqa: I001 with reason

Diff stat

117 files changed, 927 insertions(+), 770 deletions(-). Most lines are mechanical typing/import rewrites.

What this PR does NOT do

  • No ruff format run — PR 17 of the modernisation handles formatting (this is why the ignore list drops formatter-conflict rules).
  • No basedpyright / type checker yet (PRs 13–15).

Test plan

  • CI: lint.yml green (ruff)
  • CI: unit.yml green (no test behavior changes; same 626 passes locally)
  • Local: make lint exits 0

jeandet and others added 30 commits May 8, 2026 15:55
Captures decisions on UV adoption, hatchling build backend, ruff/basedpyright
tooling, and three-tier test strategy (unit/contract/e2e). Sequences the work
as 17 small PRs ending with a mass reformat.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Per-task implementation plan for the first PR of the modernisation effort.
Covers pyproject.toml updates, uv.lock generation, CI/RTD switch to uv,
deletion of requirements*.txt / tox.ini / setup.cfg, and developer-doc
updates to drop the PYTHONPATH=. pattern.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Add SPEASY_CORE_HTTP_REWRITE_RULES env to PRs.yml non-3.10 pytest step
  (previously only on push/scheduled tests.yml — would have hit a
  non-existent server on PR builds for non-3.10 matrix entries).
- Add --with wheel to PRs.yml build step for parity with tests.yml.
- Scope flake8 to 'speasy tests' in both workflows (matches Makefile
  lint target). Avoids silently broadening lint to docs/conf.py and
  removes the .venv exclusion workaround that was needed when
  flake8 ran from repo root.
Without UV_PROJECT_ENVIRONMENT, uv creates .venv/ inside the project
and RTD's sphinx step (which calls $READTHEDOCS_VIRTUALENV_PATH/bin/python
directly) fails with 'python: not found'. Point uv at RTD's venv so the
install lands where the runner looks for it.
Classified via devtools/apply_test_markers.py:
- 12 files marked unit (pure-logic, no network)
- 19 files marked contract (real-server, will be migrated to cassettes in PRs 4-9)

Reclassifications during manual review:
- test_cache.py: contract -> unit (pure cache-logic, no network or speasy provider use)
- test_file_access.py: unit -> contract (uses HTTP via any_loc_open against live servers)

test_wasm.py was manually adjusted to place pytestmark at module level (the
file's body lives inside a try/except ImportError block, so the script's
naive insertion landed at wrong indentation).
…le path and sample across the inventory

The flat_inventories.generic_archive lookup uses module attribute access on
an instance, not a submodule import. Also, the first N parameters in the
flat inventory are clustered by mission, so a fixed time range can miss all
of them; sample across the full list instead.
- test_e2e_smoke.test_generic_archive: fail loudly if every candidate
  raises (was silently skipping, defeating the e2e tier's purpose).
- pyproject.toml: drop dead --ignore=setup.py from addopts and document
  the -m unit override semantics so future contributors don't trip on
  'pytest tests/test_amda.py' silently collecting nothing.
- contract.yml / e2e.yml: add concurrency groups so a manual run can't
  overlap with a cron run hammering the same upstream servers.
- CONTRIBUTING.rst: add a short note explaining the three test tiers
  and how to invoke each from local dev.
CI failure (blocking):
- unit.yml: 'make doctest' was using system Python (no sphinx in scope).
  Prefix with 'uv run' so make uses the project venv.

Reviewer findings:
- wasm_tests.yml: pytest tests/test_wasm.py without -m collected 0 tests
  under the new addopts default (test_wasm.py is contract-marked). Add
  -m '' to override.
- CLAUDE.md: examples like 'uv run pytest tests/test_amda.py' silently
  collected 0 tests under -m unit default. Replaced with tier-aware
  examples and added -m '' for the all-tests case.
- unit.yml: only sync --group docs on the coverage runner that needs it,
  not on every matrix entry.
nbsphinx requires the system pandoc binary (not the Python pandoc
wrapper that's in the docs dependency group). PR 1's tests.yml had
'sudo apt install -y texlive pandoc' before make doctest; my unit.yml
rewrite in PR 2 dropped that line, so the doctest job failed with
'nbsphinx.NotebookError: PandocMissing in examples/AMDA.ipynb'.
Restored as a separate apt step on the coverage runner.
The doctest step's examples reference all data providers (cdpp3dview
included) and live inventories. The job-level
SPEASY_CORE_DISABLED_PROVIDERS='cdpp3dview' makes the inventory tree's
cdpp3dview attribute missing during doctest, surfacing as
'types.SimpleNamespace object has no attribute cdpp3dview' and a chain
of NameErrors for variables defined in earlier doctest blocks.

Original tests.yml overrode SPEASY_CORE_DISABLED_PROVIDERS="" on the
combined pytest+doctest step, plus set HTTP_REWRITE_RULES (re-routes
the placeholder URL used in some examples to LPP's mirror) and
USER_AGENT. My PR 2 rewrite dropped the env block; restoring it on
the doctest step.
Pandas now prints its public name in type() repr ('pandas.DataFrame')
rather than the internal module path ('pandas.core.frame.DataFrame').
The user/numpy.rst doctest was written against the old form.
Surfaced now that uv.lock pins a recent pandas; pip-installed envs
were getting older pandas where the old form still applied.
@sonarqubecloud
Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
9 Security Hotspots
E Security Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

if any("import pytest" in ln for ln in lines):
block = [f"\n{MARKER_LINE_PREFIX}{tier}\n", "\n"]
lines[insert_at:insert_at] = block
path.write_text("".join(lines))


def version_to_str(v: Union[Version, datetime.datetime]) -> str:
def version_to_str(v: Version | datetime.datetime) -> str:
@jeandet jeandet mentioned this pull request May 15, 2026
3 tasks
@codecov
Copy link
Copy Markdown

codecov Bot commented May 15, 2026

Codecov Report

❌ Patch coverage is 95.33333% with 21 lines in your changes missing coverage. Please review.
✅ Project coverage is 74.59%. Comparing base (93ce7a0) to head (3cb5e5b).
⚠️ Report is 44 commits behind head on main.

Files with missing lines Patch % Lines
speasy/core/codecs/bundled_codecs/hapi/codec.py 78.57% 3 Missing ⚠️
speasy/__init__.py 81.81% 2 Missing ⚠️
...ct_archive_downloader/direct_archive_downloader.py 86.66% 2 Missing ⚠️
speasy/data_providers/amda/ws.py 87.50% 2 Missing ⚠️
speasy/core/algorithms.py 85.71% 0 Missing and 1 partial ⚠️
speasy/core/any_files.py 87.50% 1 Missing ⚠️
speasy/core/cache/_providers_caches.py 96.00% 1 Missing ⚠️
speasy/core/cdf/inventory_extractor.py 80.00% 1 Missing ⚠️
...y/core/codecs/bundled_codecs/hapi/binary/reader.py 80.00% 1 Missing ⚠️
...easy/core/codecs/bundled_codecs/hapi/csv/reader.py 80.00% 1 Missing ⚠️
... and 6 more

❗ There is a different number of reports uploaded between BASE (93ce7a0) and HEAD (3cb5e5b). Click for more details.

HEAD has 3 uploads less than BASE
Flag BASE (93ce7a0) HEAD (3cb5e5b)
unittests 3 0
Additional details and impacted files
@@             Coverage Diff             @@
##             main     #302       +/-   ##
===========================================
- Coverage   85.10%   74.59%   -10.52%     
===========================================
  Files          69       82       +13     
  Lines        4834     5077      +243     
  Branches      668      693       +25     
===========================================
- Hits         4114     3787      -327     
- Misses        479     1049      +570     
  Partials      241      241               
Flag Coverage Δ
unit 74.59% <95.33%> (?)
unittests ?

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants