Modernize documentation and typing#126
Conversation
Add mt940/_types.py with precise aliases/Protocols (Source, TagDict, PreProcessor, PostProcessor, Processors) and use them to replace the loose Any/Callable[..., Any] signatures in the public API: - parser.parse/parse_statements: src, processors, tags, transaction_boundary - models.Transactions: DEFAULT_PROCESSORS, processors param, self.processors - processors factory return types -> Pre/PostProcessor - Amount/Balance __eq__ take object; drop dead TYPE_CHECKING block Annotation-only; no runtime change. Green on pyright, mypy, pyrefly; 100% tests; ruff/codespell/docs(-W) clean.
- Standardize all docstrings on Google style; convert the reST field-list docstrings in tags.py and parser.py. - Add module docstrings to __init__, models, json, utils, _types. - Document previously-undocumented public surfaces: Model, SumAmount, Transaction, Transactions.__init__/currency, JSONEncoder, the balance/statement tag subclasses, and the non-trivial parse helpers. - Add verified, self-contained doctest examples to the package and json module docstrings. Docs/annotation-only. Green on ruff, pyright, mypy, pyrefly; 162 tests at 100% coverage; docs build clean under sphinx-build -W.
- Rewrite conf.py: drop the 2013 sphinx-quickstart boilerplate and stale 'complexity' header; minimal modern config (furo, napoleon, autodoc_typehints='description', intersphinx, viewcode). - Generate the API reference from conf.py on every build (builder-inited -> sphinx-apidoc), so Read the Docs and local builds always stay current and the generated mt940*.rst no longer need to be committed (now gitignored). - Simplify the tox docs env to a single sphinx-build now that apidoc runs from conf.py. - Rewrite usage.rst from a one-line stub into a real guide; refresh index.rst and installation.rst. Verified: docs build warning-clean under sphinx-build -W from a clean checkout (no committed API rst); tests still 100%.
- Lead with a one-line value statement and an immediate code example. - Add a 'Why mt940' highlights section and a supported-tags reference table. - Restructure usage into focused sections (balances, multiple statements, JSON, opt-in grouping/longer-references/ASN). - Fix the ASN example to point at an existing fixture (mt940_tests/ASNB/mt940.txt); the previous path did not exist. - No emojis; all example snippets verified to run.
There was a problem hiding this comment.
Code Review
This pull request refactors the mt940 library by modernizing its documentation, automating API reference generation via Sphinx, and introducing a dedicated _types.py module to centralize type annotations and protocols. Additionally, extensive docstrings and type hints were added across the codebase. The review feedback highlights two key issues in mt940/models.py: a missing __setstate__ implementation that will cause an AttributeError on unpickled Transactions objects, and a potential AttributeError in the currency property if a Balance object has a None amount.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
There was a problem hiding this comment.
Pull request overview
This PR modernizes the project’s typing and documentation (docstrings, README, and Sphinx docs) while aiming to keep runtime behavior unchanged, and adjusts the docs build so the API reference is generated on every Sphinx build rather than committed.
Changes:
- Introduces shared public typing aliases/protocols (
mt940/_types.py) and applies them across parsing APIs and processor factories. - Rewrites/standardizes docstrings and expands user-facing documentation (README +
docs/usage.rst,docs/index.rst,docs/installation.rst). - Modernizes Sphinx config to regenerate API
.rstpages at build time and stops committing generated API stubs (gitignored).
Reviewed changes
Copilot reviewed 22 out of 23 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| tox.ini | Simplifies docs env to only run sphinx-build (apidoc now generated via Sphinx hook). |
| README.md | Restructures README with new sections/examples and supported-tags table. |
| mt940/utils.py | Adds module docstring for shared helpers. |
| mt940/tags.py | Converts docstrings to Google style; adds/clarifies tag class docstrings and registry docs. |
| mt940/processors.py | Tightens return typing for processor factories using shared protocols/types. |
| mt940/parser.py | Tightens public parse/parse_statements typing and updates docstrings. |
| mt940/models.py | Adds/standardizes docstrings; updates typing for processors and equality signatures. |
| mt940/json.py | Adds module/class docstrings; documents JSON encoder behavior. |
| mt940/_types.py | Adds centralized type aliases and processor Protocols for public API typing. |
| mt940/init.py | Adds package-level docstring with doctest-style example. |
| docs/usage.rst | Replaces stub with a full usage guide and multiple examples. |
| docs/mt940.utils.rst | Removes committed autogenerated API stub (now generated at build time). |
| docs/mt940.tags.rst | Removes committed autogenerated API stub (now generated at build time). |
| docs/mt940.rst | Removes committed autogenerated package stub (now generated at build time). |
| docs/mt940.processors.rst | Removes committed autogenerated API stub (now generated at build time). |
| docs/mt940.parser.rst | Removes committed autogenerated API stub (now generated at build time). |
| docs/mt940.models.rst | Removes committed autogenerated API stub (now generated at build time). |
| docs/mt940.json.rst | Removes committed autogenerated API stub (now generated at build time). |
| docs/modules.rst | Removes committed autogenerated API toctree stub (now generated at build time). |
| docs/installation.rst | Clarifies requirements (Python >= 3.10, no runtime deps). |
| docs/index.rst | Updates landing page copy and points users to installation/usage/modules. |
| docs/conf.py | Replaces legacy config with modern minimal config + builder hook to run sphinx-apidoc. |
| .gitignore | Ignores generated API reference .rst files now produced during docs builds. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
CodeQL's py/unsafe-cyclic-import flagged the new _types module: it imported models/tags under TYPE_CHECKING, which the query counts as starting an import cycle (models <-> _types). Drop those imports and type the processor protocols' transactions/tag parameters as Any instead. The concrete processor functions in processors.py keep their precise Transactions/Tag annotations, so no call-site precision is lost. Green on ruff, pyright, mypy, pyrefly; 162 tests at 100% coverage.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c05546c484
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
- processors: import Pre/PostProcessor at runtime so the public factory return annotations resolve via typing.get_type_hints() again (codex). Safe now that _types is a leaf module. - models.Transactions: add __setstate__ so unpickled instances regain their processors instead of raising AttributeError (gemini); add a pickle round-trip test. - docs/README: make the opt-in snippets self-contained by passing a filename instead of an undefined 'data' variable (Copilot). Green on ruff, pyright, mypy, pyrefly; 163 tests at 100% coverage; docs -W.
Modernizes the project's documentation and typing with no runtime or behavior change (annotation- and docs-only). Backward compatible — Mature library, public API semantics unchanged.
Four phased commits, each independently green against the full gate.
Phase 1 — Typing (pragmatic-strict)
mt940/_types.pywith precise aliases/protocols:Source,TagDict,PreProcessor,PostProcessor,Processors.Any/Callable[..., Any]in the public API:parse/parse_statements(src,processors,tags,transaction_boundary),Transactions(DEFAULT_PROCESSORS,processors), and the processor factory return types.Amount.__eq__/Balance.__eq__takeobject; removed a deadTYPE_CHECKINGblock.dict[str, Any](documented) — the pragmatic ceiling for heterogeneous bank data.json.default(o: Any)left as-is to match the overridden base signature.Phase 2 — Docstrings (Google style, public + meaningful)
tags.py/parser.py.Model,SumAmount,Transaction,Transactions.__init__/currency,JSONEncoder, the balance/statement tag subclasses, the non-trivial parse helpers).jsonmodule docstrings (they run under--doctest-moduleswithfilterwarnings=error).Phase 3 — Sphinx docs
conf.py: dropped the 2013 sphinx-quickstart boilerplate and the stale "complexity documentation" header; minimal modern config (furo, napoleon,autodoc_typehints='description', intersphinx, viewcode).conf.pyon every build (builder-inited→sphinx-apidoc), so Read the Docs and local builds always stay current and the generatedmt940*.rstno longer need to be committed (now gitignored). Previously these were committed-but-stale and RTD never regenerated them.sphinx-build.usage.rstfrom a one-line stub into a real guide; refreshedindex.rst/installation.rst.Phase 4 — README
mt940_tests/ASNB/mt940.txt) — the previous path did not exist.Verification
Full
toxmatrix green: py3.10–3.13, lint (ruff), type-check (pyright + mypy + pyrefly), docs (sphinx-build -W, warning-clean from a clean checkout), 100% coverage, codespell, repo-review.