conan-1.6-utilities/CLAUDE.md
Ole-Morten Duesund ac5a49ef62 conandeps: add progress output, silence Conan's SyntaxWarnings, allow Python 3.12+
- Progress lines on stderr for each of the three graph resolutions (with
  package/missing counts and timing) so a slow remote no longer looks like
  a hang; -q suppresses them. stdout remains the clean report.
- --verbose now streams Conan's output live via a tee instead of dumping it
  at the end.
- Filter SyntaxWarning/DeprecationWarning before importing conans: Conan 1.x
  modules trip the stricter escape-sequence checks of recent Pythons and
  printed a screenful of noise on 3.14.
- Drop the <3.12 requires-python ceiling. Conan 1.66 falls back to importlib
  where imp is missing; verified working on 3.14. Fix the Containerfile and
  docs that claimed otherwise.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EYNdaGDrpaqDyT8QtrTQbM
2026-08-25 15:07:07 +02:00

4.5 KiB
Raw Blame History

CLAUDE.md

Guidance for working on this repository. It records decisions made when the project was started (August 2026) that are not obvious from the code.

What this is

Small single-file Python utilities for Conan 1.x, targeting 1.66. Not Conan 2. The first (and so far only) tool is conandeps.py; see README.md for what it does and how it is used.

Hard constraints

  • Conan 1.66 only. Use the conans.client.conan_api.ConanAPIV1 API and Conan 1 graph internals (Node.binary, Node.dependencies, conanfile.requires). Do not introduce Conan 2 APIs or a Conan 2 code path.
  • Python 3.8+. Conan 1.66 runs on new Pythons too (it falls back to importlib where imp is gone) verified on 3.14. It does emit SyntaxWarnings from its own modules there, which conandeps.py silences before importing conans; keep conans imports deferred so that filter is in place first. requires-python in pyproject.toml and the PEP 723 header must stay in sync.
  • All development runs inside the container. Use ./dev.sh <cmd> for every python/pytest/ruff/uv invocation. Never run conan against the host's ~/.conan; never pip install on the host. Rebuild the image with ./dev.sh build after touching Containerfile.
  • Never depend on the private remote. The real remote is called knor and only exists on the machine where the tool is used. Tests must use the local conan_server fixture in tests/test_conandeps.py.

Design decisions (and why)

  • Binary availability is computed via Conan's graph, not conan search. The graph is built once per build type through ConanAPIV1.info() and each node's binary status is read. This honours package_id() overrides, options and default_package_id_mode exactly like conan install. Do not replace this with settings-dict matching against conan search output.
  • "Missing" means missing for the exact profile. Not "no binary with that build_type at all".
  • Overrides are parsed from Conan's WARN output. Conan 1 does not record overrides on the graph; Requirements.update() mutates req.ref in place and only emits "<pkg>: requirement <old> overridden by <who> to <new>". conandeps captures the output stream with a non-coloured ConanOutput and matches _OVERRIDE_RE. test_overrides pins this format if a Conan patch release changes the wording, that test is the alarm.
  • Both explicit and implicit overrides are reported. override=True requirements are collected from conanfile.requires to label an override as explicit; everything else parsed from the WARN lines is implicit.
  • range_ref is not a version range after an override. Conan reuses Requirement.range_ref to hold the pre-override reference, so only treat it as a range when req.version_range is truthy.
  • Single file, stdlib + Conan only. No third-party deps beyond Conan. Packaging is hatchling with only-include = ["conandeps.py"]; the PEP 723 header makes the file usable via uv run conandeps.py without a checkout.
  • Exit codes: 0 fine, 1 missing binaries, 2 Conan error. CI relies on this.
  • stdout is the report, stderr is progress. Graph resolution against a remote takes a while; progress lines (_progress) and --verbose live Conan output go to stderr only, so stdout can be redirected to a file.

Workflow

  • Lint/format: ./dev.sh ruff check . and ./dev.sh ruff format . (config in pyproject.toml, target py38, line length 100). Run shellcheck dev.sh after editing the wrapper.
  • Tests: ./dev.sh python -m pytest. The fixture spins up conan_server on a free port with a pre-written server.conf (the port cannot be given on the command line), creates fake packages whose build() does nothing, uploads them, then wipes the cache so binaries can only come from the remote. Fake recipes need --build=missing at create time because dependencies' binaries are deliberately incomplete.
  • Dependencies: uv.lock is committed; regenerate with ./dev.sh uv lock after changing pyproject.toml.
  • Commits: atomic, no --amend; run ruff + pytest + shellcheck before committing. Add a memory of anything a future session could not derive from the repository.

Adding another tool

Follow the conandeps.py pattern: one executable file with a module docstring explaining how and why, a PEP 723 header, a main(argv) that returns an exit code, a [project.scripts] entry, an only-include entry in pyproject.toml, tests under tests/ using the shared conan_env fixture, and a section in README.md.