WUT_Computer_Science/pyproject.toml
Krzysztof kuhy Rudnicki 24f800d15a TRAK: zero findings, and a byte-identical render proving it
494 ruff findings to 0, and mypy --strict is clean too -- the first course in
this campaign where that is true of both.

Two real bugs turned up on the way, neither of which ruff can see:

- `main.py` passed `args.environment_map` to `ray_trace`, and argparse only
  ever defined `--environment`. Every `--algorithm ray_tracing0` run died with
  AttributeError before rendering a pixel, so `rendering.py` -- the largest
  file in the course -- had no way to be exercised at all.
- `mouse_button` in the environment-map viewer assigned `mouse_last_x/y`
  without declaring them `global`, so the drag origin went to locals and was
  thrown away. Measured against HEAD: a 10x5 px drag turned the camera by
  11.0/20.5 degrees because it measured from (0, 0); it is 1.0/0.5 now, which
  is what the 0.1 degrees-per-pixel constant says it should be.

Fixing the first one is what made the rest safe. `ray_tracing0` has no RNG
anywhere in it, so it renders byte-identically every time, and the whole
refactor of `rendering.py` is verified by one md5 comparison:
02484bdb6b6c1ddeff317d7e5566580f, 248619 rays, before and after. The
cornell_box path cannot do that -- its ray count drifts by ~20 between
identical runs.

Three files were over the 250-line cap and are now split, geometry away from
the algorithm that uses it: rendering.py 462 -> 137 + raytracer.py,
photon_mapping.py 261 -> 160 + photon_geometry.py, and
code/photonmapping/python/main.py 257 -> 203 + geometry.py. No TRAK source
file is over the cap now.

The two photon mappers do use numpy's legacy global RNG, so NPY002 could not
be bit-identical. Each was done in two steps: restructure first, verified
identical under an external seed (digests 7220370f60206a62 and
21b4771504ab2351, and an identical 828 photon traces), then the swap to
`default_rng` on its own, checked against the before/after distributions.

Verified by running, not by reading:

- cornell_box through `./run.sh run Programming/TRAK`: 24.27s, 13294 rays
- all five scenes build after `from sightpy import *` became explicit imports
- the standalone photon mapper end to end: 81.4s, 38742 photon traces
- the EXR loader byte for byte: a0c3890350ce6101247c6948, 6291456 bytes
- the GLUT viewer under xvfb-run, which drew a real 1024x512 frame

`pyproject.toml` gains a mypy override for Imath, OpenEXR, OpenGL and
matplotlib. Those four ship neither stubs nor py.typed, and without it mypy
cannot import them at all and so reports nothing else about the file.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-29 07:54:51 +02:00

101 lines
3.7 KiB
TOML

# Python tooling for the whole archive. There is no package here to build --
# this file exists so ruff, mypy and coverage read one configuration instead of
# 25 course directories each guessing.
#
# The `exclude` and `omit` lists below are MIRRORS of gates/vendored.txt.
# Edit that manifest and re-run `./run.sh sync-vendored`; never edit a mirror
# on its own, or the gates start disagreeing about what is kuhy's code.
[tool.ruff]
target-version = "py310"
line-length = 88
include = ["*.py", "**/*.py", "*.ipynb", "**/*.ipynb"]
exclude = [
# --- machine-generated, never authored ---
".git",
".venv",
"__pycache__",
"build",
"dist",
"node_modules",
# --- mirrors of gates/vendored.txt ---
"Programming/EGUI/lab2/lab2/wwwroot/lib",
"Programming/E-PSYOPS/theProject/Assets/TextMesh Pro",
"Programming/E-PSYOPS/theProject/Assets/TutorialInfo",
"NotProgramming/EMISY/componentSchematic",
"NotProgramming/EMISY/schematic",
"Programming/EOPSY/lab3/task3/work",
"Programming/EOPSY/lab4/task4/work",
"Programming/TRAK/sightpy",
]
[tool.ruff.lint]
select = ["ALL"]
# The only rules turned off, and why. There are no per-file-ignores: the
# coursework is held to the same bar as the tooling, because git history is
# what preserves the version that was handed in.
ignore = [
# Pairwise-contradictory docstring rules -- ruff ships both halves of each
# pair in ALL and you must pick one. These match the rest of the fleet.
"D203", # ...vs D211, we take D211 (no blank line before class docstring)
"D213", # ...vs D212, we take D212 (summary on the first line)
# Disabled on the formatter's own advice: the formatter already decides
# both of these, and leaving them on makes the two tools fight.
# https://docs.astral.sh/ruff/formatter/#conflicting-lint-rules
"COM812", # missing trailing comma
"ISC001", # single-line implicit string concatenation
# A known false-positive generator: it cannot see that an argument list was
# validated upstream. https://github.com/astral-sh/ruff/issues/4045
"S603", # subprocess call without shell=True
# Ruff began enforcing this outside preview in 0.16; no repo in this fleet
# carries copyright headers, and stamping one onto 137 university
# assignments would be asserting a licence that was never claimed.
"CPY001", # missing copyright notice
]
fixable = ["ALL"]
unfixable = []
[tool.mypy]
strict = true
exclude = [
"^\\.venv/",
"^build/",
"^Programming/EGUI/lab2/lab2/wwwroot/lib/",
"^Programming/E-PSYOPS/theProject/Assets/TextMesh Pro/",
"^Programming/E-PSYOPS/theProject/Assets/TutorialInfo/",
"^NotProgramming/EMISY/componentSchematic/",
"^NotProgramming/EMISY/schematic/",
"^Programming/EOPSY/lab3/task3/work/",
"^Programming/EOPSY/lab4/task4/work/",
"^Programming/TRAK/sightpy/",
]
# Third-party packages that ship neither stubs nor a py.typed marker. This is
# not a suppression of our own code: without it mypy cannot import them at all
# and reports nothing else about the file that uses them.
[[tool.mypy.overrides]]
module = ["Imath.*", "OpenEXR.*", "OpenGL.*", "matplotlib.*"]
ignore_missing_imports = true
[tool.coverage.run]
branch = true
omit = [
"*/.venv/*",
"*/build/*",
"Programming/EGUI/lab2/lab2/wwwroot/lib/*",
"Programming/E-PSYOPS/theProject/Assets/TextMesh Pro/*",
"Programming/E-PSYOPS/theProject/Assets/TutorialInfo/*",
"NotProgramming/EMISY/componentSchematic/*",
"NotProgramming/EMISY/schematic/*",
"Programming/EOPSY/lab3/task3/work/*",
"Programming/EOPSY/lab4/task4/work/*",
"Programming/TRAK/sightpy/*",
]
[tool.coverage.report]
show_missing = true
skip_covered = false