Code Quality Guide
This page distills the durable recommendations from the 1.0.4 code-quality
pass (originally in notes/, now retired) into a living checklist.
Style and linting
- Ruff (in
pyproject.toml) is the single owner of style linting:ruff check datacrafter tests. Line length is 88. - Pylint runs in CI in errors-only mode (
pylint --errors-only datacrafter) for a second opinion on real defects; style issues belong to ruff. - No
print()in package code — useloggingwith lazy%sformatting. - Optional dependencies are guarded with
try/except ImportErrorplus aHAS_*flag, and raise an actionableImportErrornaming the package to install when used while missing.
Error handling
- No bare
except:; noexcept Exception: pass. Cleanup paths may catch narrowly (AttributeError, OSError, IOError) and log at DEBUG. - Shared constants live in
constants.pyonly — and only if something imports them. Dead constants, dead functions, and commented-out code are deleted, not archived in the tree.
Resource management
- Sources and destinations own their streams:
close()closes everything opened (including archive members), is idempotent, and__del__delegates to it. File destinations also work as context managers. - Compressed inputs are opened as decompressed streams and handed to stream-capable sources; formats that need a real file must reject compression explicitly.
Review checklist
- Does the new code path have a test that fails without it?
- Are repeated input grids expressed with
pytest.mark.parametrize? - Do new public exceptions derive from
DataCrafterError? - Would a fresh CI environment (missing optional deps) still collect the
test suite cleanly (
pytest.importorskipfor optional modules)? - Are URLs with query strings logged redacted outside DEBUG?