Commit Graph

3 Commits

Author SHA1 Message Date
faef20dc45 PORR: zero findings, 18 tests still passing after every refactor
598 findings to none, and the suite ran through `./run.sh run` after each step
rather than at the end -- 18 passed, 27s, every time.

The shape of this one was different from the other courses. PORR is four
implementations of the same linear algebra (sequential, threads, processes,
dask), so nearly every finding came in groups of four:

- 229 missing annotations. Rather than `object`, which mypy strict rejects on
  every attribute access, each module declares what these actually are:
  `Matrix = np.ndarray | list[list[float]]` and the vector equivalent. The
  backends really are called with both -- comparing them is the point of the
  course.
- 76 names: `A` -> matrix, `Ab` -> augmented, `Ax` -> product, `I` ->
  identity, `dA` -> dask_matrix, and the two CamelCase functions. Renamed
  through `tokenize`, not regex, so no string or comment was touched.
- 121 missing docstrings, one per method name since the names repeat across
  all four backends.
- Seven functions over the argument limit, all taking the same seven or nine
  loose values. They are two frozen dataclasses now, in a new
  richardson_problem.py: `Problem(matrix, rhs, lambda_min, lambda_max)` and
  `Settings(max_iterations, x0, tol)`. `RichardsonMethod.__init__` also took a
  `size` argument it never read.
- threads_indep_old's iteration did "split into chunks, submit, wait" four
  times by hand (C901 11, PLR0915 54). One `_run_chunked` helper.
- tests.py's two bare asserts became explicit raises, per the no-ignores rule.
  `assert False` was also B011: `python -O` deletes it, so the non-convergence
  branch would have silently passed under optimisation.

Real fixes rather than style: np.random -> Generator, `os.path.exists` ->
Path, an `except Exception` around dask narrowed to the errors it actually
raises, and two runnable modules that logged at INFO without ever calling
basicConfig -- caught by scripts/check_refactor_safety.py, which is now doing
the job it was written for.

Repo-wide: 1,781 findings -> 1,183, all of them in the five courses left.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0172dj34FDpao6wsix8ZuCzE
2026-08-28 21:01:13 +02:00
42007d56e4 PORR runs in 28s, and three checks so the next pass cannot repeat my mistakes
PORR was the last course whose `run` did not work. Four measurements, not
guesses, explain why -- and none of them is the matrix size everyone assumes:

  ProcessingType.PROCESSES   20.9s at n=2, 32.8s at n=5, 78.2s at n=10. That
                             is process-pool setup PER TEST, and it grows.
  matrix_type poli3          densifies a sparse .mat into a 2.3 GB npz cache
                             (nemeth12: 723 MB) -- over the 2G ceiling before
                             any solving happens.
  n=10000                    800 MB matrix, and np.linalg.solve wants a copy.
  n=5000                     spd_5000.npz was a Git LFS pointer whose object
                             404s on GitHub, so it regenerates from scratch.

Remove those and what is left still exercises the whole Richardson
implementation at every size that fits: 18 tests, 28 seconds through the
harness, exit 0. The submitted parameter set is one documented environment
variable away. `main.py` now propagates pytest's status (verified: exit 5 when
nothing is collected) -- it discarded it before, so `run` could not tell a
passing suite from a failing one.

The rest of this commit is scripts/check_refactor_safety.py, which exists
because three regressions got past both ruff and a smoke run during this
campaign, and I would rather they could not get past the next one:

  --signatures      diffs two trees function by function, parameter by
                    parameter, default by default. This is what found the 22
                    EARIN functions whose defaults an annotation pass silently
                    dropped.
  --logging         a module with a __main__ guard that logs at INFO must call
                    basicConfig, or it prints nothing at all. Found two more
                    in PORR just now.
  --print-keywords  refuses to let an automated rewrite near print(x, end="")
                    or print(x, file=sys.stderr); losing those turns a
                    rendered board into one glyph per line, or silently moves
                    error output onto stdout.

All three pass on the whole archive. Also in here: 12 latent TypeErrors mypy
found in EARIN that ruff could not -- call sites still passing positionally to
parameters this campaign had made keyword-only, plus one caller of a function
whose argument I had removed. Every one would have raised at runtime.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0172dj34FDpao6wsix8ZuCzE
2026-08-28 20:50:46 +02:00
f497629ab7 Add 'Programming/PORR/' from commit '0a62d75a828646fb5c8e13f24327fb196fc17c8e'
git-subtree-dir: Programming/PORR
git-subtree-mainline: 9576b25315
git-subtree-split: 0a62d75a82
2026-02-06 22:15:00 +01:00