mirror of
https://github.com/kuhyx/WUT_Computer_Science.git
synced 2026-11-10 20:07:11 +01:00
d5b94cd8a7
10 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
| d5b94cd8a7 |
run.sh runs the program now, and says which one it is running
Reported by kuhy: "I run run.sh and I have no idea where the actual program is
and how to run it". In EPFU that was one `gcc -Wall -Wextra -pedantic main.c`
line and nothing else -- the makefile has no -o, so the binary is an a.out that
nothing mentions, and it was never executed.
Two separate failures, both fixed.
Building is not running. make, cxx, maven and dotnet built and stopped; make,
maven and dotnet did not even print where the output went, while cxx and tex
did. They all execute what they produced now. `make` is the awkward one,
because a makefile need not say what it writes: the runner snapshots the
executables either side of the build and runs whatever is new.
A course is not always one program. Twelve of them are not -- EPFU a game and
a lab, EOOP six binaries, EARIN eight labs, MOM three reports. With no target
named, an interactive run prints a numbered menu and asks; `run <dir> 2`, a
path substring, or `all` skips the prompt. Enumeration deliberately scans the
course root rather than --entry, because EPFU pinning --entry to penguins/src
is precisely why labs/krudnic3_lab1.c had never been compiled. --entry is the
default now, not the only.
Interactive by default: EPFU's penguins and ECOAR's puzzle both read stdin,
and you typed `run`, so you are at the keyboard. --batch (and any
non-terminal stdin) means no prompt, stdin from /dev/null and a 60s cap per
program, so an unattended run cannot wedge. --probe never reaches any of this
and does not even enumerate targets: all 44 probes produce a byte-identical
gates/runnability-local.tsv, and `status` is still seconds long.
Running things immediately found two bugs that could not have surfaced before,
both recorded in TODO-refactor-remaining.md rather than fixed here, since both
mean touching a submitted .c:
- EPFU/labs/krudnic3_lab1.c dies with SIGFPE, integer division by zero.
- ECOAR's puzzle.out writes dest.bmp beside its source, so the tree guard
fails the run. That guard is doing exactly its job.
Verified: EPFU both targets, EOOP under a pty answering the prompt, EADS,
ECOAR, MOM. Full gate green, shellcheck clean on all 44 runners.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0172dj34FDpao6wsix8ZuCzE
|
|||
| 7b019d103f |
Gate the zero, and fix the LaTeX course the run guard exposed
The archive reached zero ruff findings this morning, so the standing rule in
.pre-commit-config.yaml -- a hook lands only once the thing it gates is clean
-- is finally satisfied for ruff. `ruff check` and `ruff format --check` are
hooks now, pinned at v0.16.5 per rules/dependency-freshness, plus
`no-suppressions`, which rejects `# noqa` and `# type: ignore`. CLAUDE.md has
always claimed a hook did that; until now the only thing stopping them was
whoever was reading ruff's output, and I typed `# noqa-free` three times in
this session by accident. mypy stays out: six of its errors are third-party
typing limits rather than our code.
The first attempt used `language: system`, which passed `pre-commit run
--all-files` and then failed the actual commit with "Executable `ruff` not
found" -- git hooks do not get ~/.local/bin on PATH. Taking the hooks from
astral-sh/ruff-pre-commit means pre-commit installs ruff itself, which is also
what makes the pin mean anything.
`ruff format --check` failed the moment it was wired up, on four TRAK files I
wrote today and never formatted. Formatted, and the ray_tracing0 render is
still 02484bdb6b6c1ddeff317d7e5566580f.
Then the run guard from
|
|||
| f58f55f68b |
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>
|
|||
| 74fb46b4ab |
PSD: zero findings, and four modules that no longer run on import
152 ruff findings to 0 across twelve files, and mypy --strict is clean on all of them but one -- see the end. The course is marked unrunnable because it wants Kafka and Flink, so the verification is what can be run without them. Ten of the twelve modules now import cleanly against a venv with confluent-kafka, kafka-python and flask; the two pyflink ones are skipped. That check did not exist before, because four of these files WERE their own side effect: - `kafka/generate_and_send.py` and `kafka/kafka_consumer.py` ran their `while True:` loop at module level. Importing either never returns; I gave up after twelve seconds of rdkafka connection failures. - `zin1/producent.py` built a KafkaProducer at module level and raised NoBrokersAvailable on import. - `flink/anomaly_detector.py` called `env.execute()` at module level. Each is a `main()` behind a `__main__` guard now, so importing one is free and running it is unchanged. `webinterface.py` called `json.loads` and never imported json, so the first message on the topic would have raised NameError. mypy then found three more of the same shape: confluent-kafka's `msg.error()` and `msg.value()` both return Optional, and the code dereferenced them straight away. They are narrowed to locals now, which also stops `msg.error()` being called twice per message. A malformed alarm with no timestamp is skipped with a warning instead of dividing None by 1000. Two SLF001 findings were reads of `KafkaError._PARTITION_EOF`. That leading underscore is confluent-kafka's own naming and there is no public alias, but `KafkaError.name()` is public and returns exactly that string -- checked against the installed library, where code() is -191 and name() is "_PARTITION_EOF". Flask's `debug=True` is now opt-in via FLASK_DEBUG, because the debug console executes arbitrary code. The ten `random` calls are simulation, not crypto, so S311 is not a real vulnerability -- but `secrets.SystemRandom()` is a drop-in with the same methods and no rule to argue with, so that is what they use. Behaviour is checked, not assumed: the sensor still returns a location in 1..10 and a temperature in -20..40, the thresholds still classify -15 as too cold, 40 as too hot and 20 as normal, transactions still carry a four-digit card id, and TemperatureReading survives a to_dict/from_dict round trip. **Two mypy errors remain and are deliberate.** `--strict` implies `disallow_subclassing_any`, and the Flink job must subclass pyflink's MapFunction and KeyedProcessFunction, which ship no types. Fixing it means weakening strict globally or writing an override for our own module. Neither is worth it, so the two are reported in TODO-refactor-remaining.md rather than hidden. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
|||
| 22edc3afb6 |
PBAD: zero findings across three notebooks, outputs bit-for-bit intact
115 ruff findings to 0. All three notebooks' non-source content hashes the same before and after -- c7660e3e5e3b8d4ffc008d7f, b918553ae0cf91cd56fa4091 and 3f09c77e3edae1727e3781e2 -- so every stored output, execution count and piece of metadata is exactly what was submitted. Most of the work was 35 over-long lines, and they are over-long because they are full Polish GUS column descriptions used as dict keys in .rename(). A key like "udziały w podatkach stanowiących dochody budżetu państwa podatek dochodowy od osób fizycznych" cannot be shortened, only wrapped, so a script re-wrapped all of them with implicit concatenation inside parentheses -- the one form both ruff's linter and its formatter accept. A script doing 134 mechanical edits to strings that are database keys is exactly the kind of change that silently drops a space. So it is checked mechanically: an AST pass collects every string dict key in every code cell of both versions and compares the multisets. 120 keys in data.ipynb, 9 in main.ipynb, 5 in pbad.ipynb, all identical. The other 27 findings were commented-out code (ERA001), and deleting it would have thrown away what it recorded: which other operational programmes were run, which axis limits the plots were read at, that MinMaxScaler was tried and made no difference, that an earlier pass dropped a hand-maintained column list. Each is now a sentence of prose saying that, and git history still has the code. Two cells were nothing but commented-out scratch and are now just the note. Also real: five `inplace=True` calls became assignments, `zip()` in three feature-importance loops got `strict=True`, `max(max(a), max(b))` became `max(*a, *b)`, and 1.5 and 7 became DENSE_GMINA_THRESHOLD and TERYT_GMINA_DIGITS -- the latter being "a full TERYT gmina code is seven digits", which is worth saying once rather than leaving as a bare literal. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
|||
| 1fd1de2f82 |
twm_4: zero findings, with the notebook's outputs proved untouched
228 ruff findings to 0 across the notebook, its partial export and twm.py, and mypy --strict is clean on both .py files. A notebook is a deliverable that happens to contain code, so the check that mattered was not "does it still run" -- it needs a GPU, MNIST, CIFAR-10 and a slice of Quick, Draw! to run at all -- but "is anything except the code still exactly as submitted". Hashing every key of the .ipynb EXCEPT cell `source` gives 60242e116d12549d11c93f7f before the first edit and after the last one, across four passes and a `ruff format`. The file also round-trips byte-for-byte through json.dumps(indent=1, ensure_ascii=False), which is what made editing cells programmatically safe rather than a reformat of all 141 of them; the diff touches 38. print() became sys.stdout.write() rather than logging. In a notebook the print IS the output, and a logger with no handler configured would have silently emptied every cell -- the exact regression scripts/check_refactor_safety.py was written for. matprint's `print(x, end=" ")` and bare `print()` are preserved as writes with and without a trailing newline. Both `show_samples` and `show_samples_rgb` took (indices, preds, images, labels, count, names), which is six arguments and a mutable default. They now take a frozen `Samples` holding the last four, which also removed the same four-value tuple from seven call sites. Reviewing that diff is how I caught that I had transcribed `real_score = preds[sample][real_id]` as `samples.labels[sample]` -- a bug I introduced and then fixed before commit. Other real things, not just rule satisfaction: `np.in1d` is removed in NumPy 2 (NPY201) and is now `np.isin(...).ravel()`; `test_model` computed correct_indices and incorrect_indices and used neither; two cells grew `img` inside a loop so it was only bound by the `else` branch; and the Quick, Draw! downloader now builds a URL whose https scheme is a literal, which is what S310 was asking for. The README claimed the .py was "an nbconvert export of that notebook". It is an export of the CIFAR-10 section only -- 28 of 81 code cells -- and has been edited since. It says that now, and says the two are separate artifacts rather than one being regenerable from the other. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
|||
| 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> |
|||
| 70937fbdc3 |
Record where the campaign actually is
1,183 ruff findings left, in five courses. Nine are at zero. The numbers in here were four hours stale. Two things worth reading before the next pass: the notebook branch of scripts/course_run.sh will overwrite tracked notebook outputs the moment it is used (the same bug already found in TRAK and SPD), and eleven .py files are now over the 250-line cap -- several because THIS work added the docstrings and annotations that pushed them over. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0172dj34FDpao6wsix8ZuCzE |
|||
| d76e571400 |
Cap run.sh run at 2G RAM and 2 cores
Running the courses made this machine stutter during a game. That was me: PORR's suite solves systems up to 10000x10000 and takes every core it is given, and the pip installs are not cheap either. A promise to be careful is not a fix, so `run` now executes inside a transient systemd scope -- MemoryMax=2G, MemorySwapMax=0 (OOM-kill rather than thrash swap), CPUQuota=200%, nice -n 19, ionice -c 3. Same mechanism the pre-push hook in testsAndMisc uses. Verified from inside the scope: memory.max reads 2147483648 and cpu.max reads "200000 100000", so the kernel is enforcing it rather than the script hoping. RUN_MEMORY_MAX and RUN_CPU_QUOTA override it for a single deliberate run. Recorded the two courses that still fail: PORR, which will now be OOM-killed under the cap and needs a smaller default parameter set, and ZPOB, where latexmk exits 12 from bibtex despite producing the PDF. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0172dj34FDpao6wsix8ZuCzE |
|||
| badc21d653 |
Record what is left, with measured sizes rather than estimates
The remaining work is much larger than what has landed, and vague about it
would be worse than useless. Numbers are measured, not guessed:
- 9,281 ruff findings under the fleet config (select = ALL). ~3,000 are
auto-fixable and ~6,000 are hand work, dominated by 1,671 missing type
annotations and ~600 missing docstrings.
- 19 tests for ~28k lines of authored code, across 12 languages.
- 73 files still over the 250-line cap, 27 of which are blocked on the
decision parked in TODO-file-length-250.md.
- 22 dependency manifests, none pinned.
Also records the ordering rules that are easy to lose: the dependency upgrade
and its gate must land in the same commit; source files must not be split
before their tests exist; and the file-rewriting hooks are held back so that
touching hundreds of submitted coursework files is its own reviewed change.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0172dj34FDpao6wsix8ZuCzE
|