WUT_Computer_Science/pyproject.toml
Krzysztof kuhy Rudnicki f58f55f68b
Some checks are pending
md-naming / markdown naming convention (push) Waiting to run
pre-commit / pre-commit (push) Waiting to run
runnability / runnability (push) Waiting to run
ERSMS-project: zero findings, and the SQL is parameterised now
156 ruff findings to 0. That takes the whole archive to 0, from 9,281.

Six of those findings were SQL injection, and they were the real ones. The
connector interpolated a username and an OAuth id straight out of the URL into
f-string SQL. With psycopg2 installed, the difference is not theoretical:

  username = "x'; DROP TABLE users; --"
  old:  select * from users where username='x'; DROP TABLE users; --';
  new:  select * from users where username='x''; DROP TABLE users; --';

The old form is two statements and the second one runs. The new one is a
parameter, so the whole thing stays a string literal. Every query in that file
is parameterised now.

`get_recommendations` also called
`cursor.execute("... oauth_ID='{}'", oauth_ID)`, which is wrong twice over:
psycopg2 wants %s rather than {}, and its second argument must be a sequence,
not a bare string. That route could never have worked.

Ten blind `except Exception` handlers turned every programming error into a
500 with the message hidden. They are now the exceptions each block can
actually raise -- verified against the installed libraries, where
InvalidIdTokenError and ExpiredIdTokenError really are FirebaseError
subclasses -- and the handlers log a traceback instead of printing the
exception's str().

Three services bound `host="localhost"`. Each of them runs in a container with
a published port, on a compose bridge network, so binding loopback makes them
unreachable from both the host and their siblings. All four now read
ERSMS_HOST, which docker-compose sets to 0.0.0.0, and default to loopback when
run outside Docker. Flask's debug console executes arbitrary code, so that is
opt-in via FLASK_DEBUG too.

`movie_recommender.py` fitted the model at import: reading two CSVs and
building a 4803x4803 similarity matrix as a side effect of `import`. It failed
outright here, since the datasets are not committed. It is in `main()` now, and
the module imports cleanly. `error_decorator` was dead code that swallowed its
wrapped function's return value; it is gone.

Verified: all four modules import (the backend still needs its Firebase
credential JSON, which is not committed, exactly as before), the recommender's
helpers still pick the director out of a crew list, trim cast to three, fold
"Tom Hanks" to "tomhanks" and join a soup in the same order, and every route
parameter rename was matched by the URL rule it comes from.

Three of the four services are clean under mypy --strict. The backend keeps
four errors: flask-sqlalchemy builds `db.Model` dynamically, so `--strict`
refuses to subclass it. Migrating to a typed DeclarativeBase would rewrite both
models in an app that cannot be run here, so those four are reported in
TODO-refactor-remaining.md rather than hidden.

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

115 lines
3.8 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.*",
"keras.*",
"tensorflow.*",
"sklearn.*",
"seaborn.*",
"kafka.*",
"pyflink.*",
"pandas.*",
"psycopg2.*",
"firebase_admin.*",
]
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