DOC: repo-wide documentation consistency audit - #864
Conversation
|
@oyamad I am working through my review of this so I have left this in draft for now. But it is looking like a good update. |
There was a problem hiding this comment.
Pull request overview
This PR performs a repo-wide documentation consistency pass across Sphinx configuration, the apidoc generator, docstrings/doctest snippets, and repo prose docs, and also introduces a docs build job in CI to prevent future doc drift.
Changes:
- Fixes Sphinx configuration so autodoc imports the in-repo
quantecon(not an installed wheel) and improves cross-references via intersphinx. - Extends
docs/qe_apidoc.pyand committed.rstsources to include thequantecon.timingsAPI, and fixessrccleanto fully remove generated sources. - Adds a docs CI job to regenerate + drift-check committed
.rstsources and build HTML docs.
Reviewed changes
Copilot reviewed 99 out of 99 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| README.md | Updates badges, links, install notes, citation |
| quantecon/util/timing.py | Updates timeit docstring/examples (doctest risk) |
| quantecon/util/notebooks.py | Clarifies docstring parameters/examples |
| quantecon/util/common_messages.py | Removes unused module |
| quantecon/util/combinatorics.py | Fixes doctest imports |
| quantecon/util/array.py | Fixes deprecation directive + doc typos |
| quantecon/timings/timings.py | Adds timings precision examples/output |
| quantecon/tests/util.py | Updates reference URL |
| quantecon/tests/test_inequality.py | Updates reference URL |
| quantecon/robustlq.py | Updates deprecation shim wording |
| quantecon/rank_nullspace.py | Updates deprecation shim wording |
| quantecon/random/utilities.py | Fixes doctests + doc typos/clarifications |
| quantecon/random/init.py | Documents/export draw |
| quantecon/quadsums.py | Updates deprecation shim wording |
| quantecon/quad.py | Fixes doc typos and clarifies parameters/returns |
| quantecon/optimize/tests/test_linprog_simplex.py | Updates reference URL |
| quantecon/optimize/scalar_maximization.py | Clarifies parameter defaults/order |
| quantecon/optimize/nelder_mead.py | Improves docs + doctest stability |
| quantecon/optimize/linprog_simplex.py | Fixes doc inconsistencies (phase flags etc.) |
| quantecon/optimize/lcp_lemke.py | Stabilizes doctest output type |
| quantecon/matrix_eqn.py | Updates deprecation shim wording |
| quantecon/markov/utilities.py | Fixes doctest imports |
| quantecon/markov/random.py | Fixes doctest formatting/imports |
| quantecon/markov/gth_solve.py | Fixes doc typo (“jit-compiled”) |
| quantecon/markov/estimate.py | Docstring formatting + adds missing parameter docs |
| quantecon/markov/ddp.py | Clarifies max_iter semantics + adds method doc |
| quantecon/markov/core.py | Doc clarifications + adds missing Parameters section |
| quantecon/markov/approximation.py | Fixes parameter order text + doctest stability |
| quantecon/markov/_ddp_linprog_simplex.py | Fixes doc typos/shape docs |
| quantecon/lss.py | Updates deprecation shim wording |
| quantecon/lqnash.py | Updates deprecation shim wording |
| quantecon/lqcontrol.py | Updates deprecation shim wording |
| quantecon/lae.py | Updates deprecation shim wording |
| quantecon/kalman.py | Updates deprecation shim wording |
| quantecon/ivp.py | Updates deprecation shim wording |
| quantecon/inequality.py | Updates deprecation shim wording |
| quantecon/gridtools.py | Updates deprecation shim wording |
| quantecon/graph_tools.py | Updates deprecation shim wording |
| quantecon/game_theory/vertex_enumeration.py | Fixes doctest imports/output stability |
| quantecon/game_theory/support_enumeration.py | Fixes doctest imports |
| quantecon/game_theory/repeated_game.py | Corrects return/shape docs |
| quantecon/game_theory/random.py | Fixes “Returns” section header |
| quantecon/game_theory/pure_nash.py | Fixes tol doc + doctest import |
| quantecon/game_theory/polymatrix_game.py | Replaces placeholder docstring with full docs |
| quantecon/game_theory/normal_form_game.py | Fixes doctest imports/formatting + doc clarity |
| quantecon/game_theory/mclennan_tourky.py | Fixes doctest variable name + formatting |
| quantecon/game_theory/logitdyn.py | Fixes parameter/attribute docs |
| quantecon/game_theory/lemke_howson.py | Fixes doctest imports/output + adds return docs |
| quantecon/game_theory/game_generators/bimatrix_generators.py | Normalizes doctest array formatting/imports |
| quantecon/game_theory/game_converters.py | Adds missing Parameters/Returns blocks |
| quantecon/game_theory/fictplay.py | Fixes doc typos and type docs |
| quantecon/filter.py | Updates deprecation shim wording |
| quantecon/estspec.py | Updates deprecation shim wording |
| quantecon/ecdf.py | Updates deprecation shim wording |
| quantecon/dle.py | Updates deprecation shim wording |
| quantecon/distributions.py | Removes incorrect params + fixes return doc spacing |
| quantecon/discrete_rv.py | Updates deprecation shim wording |
| quantecon/compute_fp.py | Updates deprecation shim wording |
| quantecon/ce_util.py | Updates deprecation shim wording |
| quantecon/arma.py | Updates deprecation shim wording |
| quantecon/_robustlq.py | Fixes return-order docs + type correction |
| quantecon/_rank_nullspace.py | Fixes rank/nullspace definition text |
| quantecon/_quadsums.py | Docstring cleanup + correct reference |
| quantecon/_matrix_eqn.py | Docstring cleanup + default corrections |
| quantecon/_lss.py | Fixes param name + doc typos |
| quantecon/_lqnash.py | Fixes shape docs + typo |
| quantecon/_lqcontrol.py | Fixes incorrect matrix description |
| quantecon/_lae.py | Stabilizes doctest by checking shape |
| quantecon/_kalman.py | Fixes typo + adds missing Returns docs |
| quantecon/_ivp.py | Fixes class name refs + doc formatting |
| quantecon/_inequality.py | Fixes doctest to call correct function |
| quantecon/_gridtools.py | Fixes doctest imports/output stability + typos |
| quantecon/_graph_tools.py | Fixes typo (“these”) |
| quantecon/_filter.py | Fixes typo + wraps lines |
| quantecon/_dle.py | Normalizes parameter names/types in docs |
| quantecon/_compute_fp.py | Fixes docstring quoting typo |
| quantecon/_arma.py | Fixes typo + adds missing Returns docs |
| pyproject.toml | Raises requires-python to >=3.12 |
| MANIFEST.in | Removes unused MANIFEST.in |
| docs/sphinxext/only_directives.py | Removes unused vendored extension |
| docs/sphinxext/ipython_directive.py | Removes unused vendored extension |
| docs/sphinxext/ipython_console_highlighting.py | Removes unused vendored extension |
| docs/source/util/common_messages.rst | Removes docs page for deleted module |
| docs/source/util.rst | Removes common_messages from toctree |
| docs/source/timings/timings.rst | Adds committed timings API page |
| docs/source/timings.rst | Adds timings section to docs |
| docs/source/setup.rst | Updates PyPI + Git docs links |
| docs/source/index.rst | Adds timings section + clarifies util content |
| docs/source/game_theory.rst | Title-case section heading |
| docs/source/contributing.rst | Replaces dead Discourse link with issue tracker |
| docs/source/conf.py | Fixes sys.path import root + intersphinx mappings |
| docs/rtd-requirements.txt | Unpins Sphinx version |
| docs/README.md | Updates doc build instructions |
| docs/qe_apidoc.py | Fixes generator dirs + adds timings section |
| docs/Makefile | Fixes srcclean to remove more generated sources |
| CHANGELOG.md | Fixes dates and removes dead link markup |
| .github/workflows/ci.yml | Adds docs build + docs/source drift gate |
| .github/workflows/ci_np2.yml | Fixes pull_request trigger branch |
| .github/copilot-instructions.md | Updates repo guidance to match CI/docs reality |
Comments suppressed due to low confidence (1)
quantecon/util/timing.py:350
- This
timeit(add_func, runs=2)example prints output but the docstring provides no expected output, so doctest will fail. Make the call silent (or add expected output with ellipsis).
oyamad
left a comment
There was a problem hiding this comment.
I found one issue to comment on while I was just browsing.
Addresses @oyamad's review on #864: seeding a doctest through NumPy's global random state is not a convention we want in the published docs. Replaces the `np.random.seed(1234)` in `draw` and the nine bare-int `random_state=1234` arguments with an explicit `rng = np.random.default_rng(1234)` passed as `random_state=rng`, so every reproducible example in the package now uses the same modern Generator-based pattern already used by `game_theory.random` and `markov.approximation`. `default_rng` seeds PCG64 via SeedSequence rather than the legacy Mersenne Twister, so the streams differ and every expected output was regenerated by running the example rather than by editing the old values. `random.draw` takes no `random_state` argument and draws from the global state, so its example cannot be seeded this way. It now asserts properties of the sample instead of exact values, with a Notes section recording the limitation. Extending `draw` to accept a generator, as suggested in review, is a behaviour change left for separate work. Verified: 600 tests pass; doctests pass for all five modules that use a generator in their examples; flake8 output unchanged from baseline. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The Timer and timeit docstring examples show elapsed times that cannot be reproduced exactly, so presenting them as literal expected output is misleading. Note up front that the values are illustrative and vary with machine and load. Also: - replace the fabricated "Average time: 0.0120 seconds" with a value the example actually produces - show the output of the final timeit(add_func, runs=2) example, which prints but previously displayed nothing, unlike every other example in the same docstring - add the missing "import time" so the snippets are copy-pasteable - drop trailing whitespace on the touched lines Addresses Copilot review feedback on #864. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Systematic audit of the documentation surface (Sphinx sources, the apidoc generator, package docstrings, repo prose, build config and hyperlinks), plus the fixes it turned up. Docs build - conf.py put a cwd-relative path on sys.path. Sphinx runs from docs/, so it resolved to a nonexistent directory and autodoc fell through to whatever quantecon was installed in site-packages rather than the checkout. Read the Docs has therefore been publishing docs built from the installed wheel. Now __file__-relative. - html_static_path = [''] copied the whole confdir (72 .rst files + conf.py) into the published _static/. Now []. - Added numpy/scipy to intersphinx_mapping. Generator - qe_apidoc.py never created source/game_theory/game_generators/, so the documented `make srcclean && python qe_apidoc.py` rebuild crashed with FileNotFoundError; srcclean also skipped source/optimize. - quantecon.timings is a top-level export that was documented nowhere. It now gets a generated section. Docstrings - robust_rule, robust_rule_simple and evaluate_F in _robustlq.py documented return orders that contradict their return statements. - nnash in _lqnash.py had the S1/S2 shapes swapped; the tests miss it because they use k_1 == k_2. - ~90 further parameter/return/default/type corrections, numpydoc structural fixes, and typo corrections across the package. Examples - A --doctest-modules sweep found 31 broken examples (stale pre-NumPy-1.14 array spacing, NumPy 2 scalar reprs, missing imports, and two NameErrors). All 31 fixed and verified by execution. Per module in isolation, 83 of 85 modules are now doctest-clean; the two exceptions need the network and the wall clock, and were left untouched rather than masked with doctest directives. Prose and metadata - CI matrix (was 3.11-3.13, actually 3.12-3.14), test count (was 536, actually 600), the README source-install block (ran flit with no cd, so it failed), the BibTeX entry (carried the Zenodo DOI on a JOSS @Article), and ~10 dead or redirecting URLs including two NXDOMAIN hosts. - The 21 deprecation shims said "will be removed v0.8.0"; v0.8.0 shipped in February 2025. Now version-agnostic. A removal schedule is a separate discussion. Behaviour changes worth calling out in review - requires-python: >=3.7 -> >=3.12, matching the classifiers, CI and RTD. This narrows installability. - Removed quantecon/util/common_messages.py. It was referenced nowhere and described a Numba fallback that no longer exists, but it was importable. Also adds a docs job to CI (nothing built the docs, which is how the conf.py and srcclean breakage survived), fixes the unexpanded $default-branch token in ci_np2.yml, unpins sphinx<=6.2.1 now that #707 is closed, and deletes the dead docs/sphinxext/ and MANIFEST.in. The six autodoc warnings that remain are the open question in #853 and are deliberately untouched here. Refs #853. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Addresses @oyamad's review on #864: seeding a doctest through NumPy's global random state is not a convention we want in the published docs. Replaces the `np.random.seed(1234)` in `draw` and the nine bare-int `random_state=1234` arguments with an explicit `rng = np.random.default_rng(1234)` passed as `random_state=rng`, so every reproducible example in the package now uses the same modern Generator-based pattern already used by `game_theory.random` and `markov.approximation`. `default_rng` seeds PCG64 via SeedSequence rather than the legacy Mersenne Twister, so the streams differ and every expected output was regenerated by running the example rather than by editing the old values. `random.draw` takes no `random_state` argument and draws from the global state, so its example cannot be seeded this way. It now asserts properties of the sample instead of exact values, with a Notes section recording the limitation. Extending `draw` to accept a generator, as suggested in review, is a behaviour change left for separate work. Verified: 600 tests pass; doctests pass for all five modules that use a generator in their examples; flake8 output unchanged from baseline. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The Timer and timeit docstring examples show elapsed times that cannot be reproduced exactly, so presenting them as literal expected output is misleading. Note up front that the values are illustrative and vary with machine and load. Also: - replace the fabricated "Average time: 0.0120 seconds" with a value the example actually produces - show the output of the final timeit(add_func, runs=2) example, which prints but previously displayed nothing, unlike every other example in the same docstring - add the missing "import time" so the snippets are copy-pasteable - drop trailing whitespace on the touched lines Addresses Copilot review feedback on #864. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The Notes block added in 63d784b was wrong in both halves. `draw` does not always draw from NumPy's global random state -- under jit it draws from Numba's separate internal state -- and its output can be made reproducible, from either path: pure Python : np.random.seed(1234) at Python level jitted : np.random.seed(1234) inside the jitted function Both give [0 1 1 1 1 0 0 1 1 1] for size=10, stable across processes. Numba's internal generator is Mersenne Twister, stream-compatible with NumPy's legacy global state, so the two paths agree. Because reproducibility is available, the property-checking example (`draw(cdf) in (0, 1)`, `.shape`) is no longer needed and is replaced with one that shows the values the function actually returns. The scalar draw is wrapped in `int()` because the bare NumPy 2 repr is `np.int64(0)`. `np.random.seed` here is not the convention objected to in review: `draw` accepts no `random_state`, so seeding is the only reproducibility mechanism it has. Extending `draw` to accept a generator is tracked separately.
Adopts the object-repr convention from review as the PR-wide style: all four examples that wrapped a scalar output now show the repr of what the function actually returns. Outputs verified by running each example; doctests pass for all four modules. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Wires the docstring-example sweep from gh-866 into ci.yml so examples cannot silently rot again after the gh-864 fixes. A new quantecon/conftest.py resolves the two blockers raised in gh-866: - An autouse fixture restores NumPy print options after each test, so the game_theory examples that set precision=4 no longer leak process-global state into doctests collected later (previously 8 spurious failures in markov, optimize and random). - collect_ignore excludes util/notebooks.py (fetches over the network) and util/timing.py (prints wall-clock durations), keeping the rendered docs free of `# doctest: +SKIP` directives. The CI step runs on Linux only: one platform is enough to stop drift, and it sidesteps --ignore-glob path-separator issues on Windows. The DeprecationWarning from util/array.py::searchsorted needs no handling since no strict warning filter is configured. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
a99927a to
e7b4038
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 98 out of 98 changed files in this pull request and generated 1 comment.
Suppressed comments (1)
pyproject.toml:25
requires-pythonis raised to ">=3.12", which is a breaking distribution change for users still pinned to Python 3.7–3.11. Please ensure this is clearly called out in the next release notes (and/or whichever release process the project uses) so downstreams understand why resolution/install stopped working on older interpreters.
dynamic = ["description", "version"]
requires-python = ">=3.12"
dependencies = [
- CI docs job: also fail the drift check on untracked generated pages (git diff alone misses a brand-new .rst), drop the no-op --keep-going (only meaningful with -W), and upload the built HTML as an artifact for reviewer preview - game_theory examples: add the missing numpy/function imports so every example is copy-paste runnable, matching the convention applied elsewhere in this PR - _dle.py: document the ts_length default in irf() - test_inequality.py: cite the published article year (2019) to match the AER link, and drop a stray quote - markov/estimate.py: put Returns before Examples (numpydoc order) and make the example self-contained - docs/README.md: fix 'Do to this' typo; mark the manual qe_apidoc step as optional since 'make html' runs it Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
@oyamad I think this is in relatively good shape now. Thanks for your comments -- they were really helpful. Any other pickups? Otherwise I think this is a big improvement. |
Conflict resolution: .github/copilot-instructions.md was deleted upstream in #941 (AGENTS.md now carries that guidance), so the deletion is accepted; quantecon/random/utilities.py keeps the draw docstring introduced upstream in #917, which supersedes this branch's Notes and example; normal_form_game.py keeps the upstream tol wording from #936. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The example had been reduced to checking the shape of mc.simulate's output. The output is deterministic under the seeded generator, and the same example already prints exact state_values drawn from the same stream, so show the values the reader would actually see. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Matches the version the rest of ci.yml already uses after Dependabot's bump on main. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The index page's description of util listed tic, tac and toc alongside Timer and timeit. Those three are being deprecated in #833, so the landing page should not advertise them. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
There was a problem hiding this comment.
🔵 Needs a closer look
It spans 60+ files and includes two intentional behavior changes (an importable-module removal and a requires-python narrowing) plus a new CI drift gate, which merit final human review despite no concrete defects being found.
Review details
- Files reviewed: 97/97 changed files
- Comments generated: 0 new
- Review effort level: Balanced
|
Author review complete. Every docstring correction was re-verified against the code, each changed module's examples run as doctests in isolation, and the apidoc drift gate, Sphinx build and full test suite are green on the merged branch. The removals are listed under "For the release notes" in the description. Ready to merge from my side; the two behaviour changes flagged above are still open for a second maintainer's view. |
|
@oyamad I have done a detailed review this morning. I think this is now in a good state to merge so I will do so. |
Wires the docstring-example sweep from gh-866 into ci.yml so examples cannot silently rot again after the gh-864 fixes. A new quantecon/conftest.py resolves the two blockers raised in gh-866: - An autouse fixture restores NumPy print options after each test, so the game_theory examples that set precision=4 no longer leak process-global state into doctests collected later (previously 8 spurious failures in markov, optimize and random). - collect_ignore excludes util/notebooks.py (fetches over the network) and util/timing.py (prints wall-clock durations), keeping the rendered docs free of `# doctest: +SKIP` directives. The CI step runs on Linux only: one platform is enough to stop drift, and it sidesteps --ignore-glob path-separator issues on Windows. The DeprecationWarning from util/array.py::searchsorted needs no handling since no strict warning filter is configured. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* CI: Run docstring examples via pytest --doctest-modules Wires the docstring-example sweep from gh-866 into ci.yml so examples cannot silently rot again after the gh-864 fixes. A new quantecon/conftest.py resolves the two blockers raised in gh-866: - An autouse fixture restores NumPy print options after each test, so the game_theory examples that set precision=4 no longer leak process-global state into doctests collected later (previously 8 spurious failures in markov, optimize and random). - collect_ignore excludes util/notebooks.py (fetches over the network) and util/timing.py (prints wall-clock durations), keeping the rendered docs free of `# doctest: +SKIP` directives. The CI step runs on Linux only: one platform is enough to stop drift, and it sidesteps --ignore-glob path-separator issues on Windows. The DeprecationWarning from util/array.py::searchsorted needs no handling since no strict warning filter is configured. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * CI: move doctest conftest.py to the repository root qe_apidoc.py discovers Tools pages by globbing quantecon/[a-z0-9]*.py, so an in-package conftest.py would be picked up as a public module and fail the docs-drift check; the root location also keeps a module that imports pytest out of the installed wheel. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * TEST: run docstring examples without comparing output Replaces the `--doctest-modules` CI step and its root `conftest.py` with a single test that executes every docstring example and checks only that it does not raise. Comparing example output is what made the previous design need machinery. Global NumPy print options leak between modules, causing nine spurious failures, and two modules could not pass verbatim at all. Neither applies once output is not compared: leaked print options are invisible, and `util/timing.py`'s wall-clock durations no longer matter, so only `util/notebooks.py`, which fetches over the network, is excluded -- and that module is deprecated for removal in v1.0. What this gives up is drift in the *text* of an example's output, the category that breaks on every NumPy repr change and would commit us to re-pasting expected output indefinitely. What it keeps is every failure that breaks a reader who copies an example: missing imports, renamed functions, changed signatures. Running as an ordinary test rather than a separate CI step means the sweep covers the whole platform matrix, which execution-only tolerates because it has no platform-sensitive output. A collection guard fails if the sweep ever finds nothing, so it cannot silently become a no-op. Closes #866. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * TEST: Report a failing docstring example by file, line and source A failing example was reported only by docstring name and exception: the compiled snippet had no registered source, so the traceback showed '???' and ':1' for every failure, above fifteen lines of harness code. Register each example with linecache under a '<doctest name[n]>' filename, as doctest's own runner does, and re-raise with the source file, exact line, position within the docstring and the example's source, chaining the original exception so a failure inside library code keeps its traceback. The execution loop moves into a helper so a self-test can drive it with a synthetic docstring: the reporting path only runs when an example is broken, and a mistake in its line arithmetic would otherwise surface at the worst moment. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Resolves two docstring conflicts with #864 by keeping this branch's text: the `_sample_without_replacement` docstring (rewritten here; already spells "compiled") and the `_ints_arr_to_bits` example (the 1-D-to-scalar form removed here no longer needs its repr updated). `requires-python` takes main's ">=3.12". Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Summary
A systematic audit of the documentation surface — Sphinx sources, the apidoc generator, every docstring in the package, the repo-level prose docs, build config, and every hyperlink — together with the fixes it turned up. One open question (#853) is deliberately left untouched.
Findings were verified against the code rather than taken at face value, and the resulting diff was reviewed again for regressions before this PR.
Highest-impact fixes
The published docs describe the wrong package.
docs/source/conf.pyput a cwd-relative path onsys.path. Sphinx runs fromdocs/, so it resolved to a directory that does not exist, and autodoc silently fell through to whateverquanteconhappened to be installed in site-packages instead of the checkout. Read the Docs has therefore been publishing API docs generated from the installed wheel. The entry is now__file__-relative. Locally this changed the reported version in the built output from the installed0.12.0to the checkout's version.quantecon.timingswas documented nowhere. It is exported at top level and declares its own__all__, butgrep -r timings docs/returned zero hits. The generator now emits a Timings section, and the generated pages are committed.A documented rebuild path was broken.
qe_apidoc.pynever createdsource/game_theory/game_generators/, so themake srcclean && python qe_apidoc.pysequence indocs/README.mdcrashed withFileNotFoundError.srccleanalso silently skippedsource/optimize, so a "clean" rebuild left stale pages.Docstrings that contradict the code.
robust_rule,robust_rule_simpleandevaluate_Fin_robustlq.pyeach documented a return order that does not match theirreturnstatement.nnashin_lqnash.pyhad theS1/S2shapes swapped — the tests do not catch it because they usek_1 == k_2. Around 90 further parameter, return, default and type corrections follow, plus numpydoc structural fixes (a bare.. deprecated::and a missing blank line before a list were both docutils errors, so those admonitions never rendered).31 broken examples. A
--doctest-modulessweep found examples showing output no supported NumPy produces (pre-1.14 array spacing), NumPy 2 scalar reprs, missing imports, and two outrightNameErrors — includinglorenz(), which does not exist. All 31 were fixed and each verified by running it. Examples that take arandom_statenow use therng = np.random.default_rng(1234)pattern throughout, with every expected output regenerated by running the example.Prose corrected against ground truth. The README source-install block (ran
flit installwith nocd, so it could not work), the BibTeX entry (carried the Zenodo DOI on a JOSS@article), and around ten dead or redirecting URLs — two of which,lectures.quantecon.organddiscourse.quantecon.org, are NXDOMAIN.Please look closely at these two
Both are behaviour changes rather than documentation, and both are reasonable to push back on:
requires-python:>=3.7→>=3.12quantecon/util/common_messages.pygrephits only its own definition), and it describes a graceful Numba fallback that no longer exists, since numba is a hard dependency and__init__.pyhard-raises.Also included
Adds a docs job to CI. Nothing built the docs, which is precisely how the
conf.pyandsrccleanbreakage survived unnoticed. The job runsqe_apidoc.pyand thengit diff --exit-code -- docs/source, because RTD builds the committed.rstfiles and never runs the generator — regenerating without the drift check would pass green while RTD served stale pages. It builds without-Wfor now, since six warnings remain pending #853.Unpins
sphinx<=6.2.1, added in #708 as a temporary workaround for #707, now closed — the pin held the docs on a 2023 Sphinx whose metadata tops out at Python 3.11 while RTD builds on 3.14. Deletes the deaddocs/sphinxext/(three vendored modules, all commented out ofconf.py) andMANIFEST.in(names a nonexistentLICENSE.txt, and flit never reads it). The 21 deprecation shims said "will be removed v0.8.0"; v0.8.0 shipped in February 2025, so the wording is now version-agnostic — an actual removal schedule is a separate discussion.The Sphinx unpin and the
sphinxextdeletion are the first two items of #885 from the technical-debt audit. Its third item, moving the duplicated runtime floors out ofrtd-requirements.txt, is not part of this PR, so #885 stays open for that.Since the last review round (10 September 2026)
Merged
main. Three files conflicted..github/copilot-instructions.mdwas deleted upstream in #941 andAGENTS.mdnow carries that guidance (it makes none of the stale CI-matrix or test-count claims this branch had corrected), so the deletion stands.quantecon/random/utilities.pykeeps thedrawdocstring from #917, which supersedes the seeded example discussed in the review thread —drawnow takes anrngand its example uses the same generator pattern as the rest of the module.normal_form_game.pykeeps thetolwording from #936.The
discrete_varexample shows the simulated path again rather than its.shape. The output is deterministic under the seeded generator, and the same block already prints exactstate_valuesfrom the same stream, so it introduces no new fragility.The docs job now uses
actions/setup-python@v7, matching the rest ofci.ymlafter Dependabot's bump onmain.The
ci_np2.ymltrigger fix that earlier versions of this description mentioned landed separately in #911 and is no longer part of this diff.The index page's description of
utilnow names onlyTimerandtimeitas the user-facing timing tools, so it does not advertisetic/tac/tocahead of their deprecation in #833. That PR merges cleanly onto this branch in either order.For the release notes
Release notes are generated from PR titles at tag time, and this PR's title would hide the removals below. Whoever cuts the next release should carry these into the notes by hand:
requires-pythonis now>=3.12. Users on older interpreters stop resolving new releases.quantecon.util.common_messagesis removed. It held a single string for a Numba-fallback path that no longer exists, and nothing imported it.docs/sphinxext/is removed. It held vendored, Python 2 era copies of the IPython Sphinx directives and numpydoc'sonly_directives; the docs build has used the extensions shipped with IPython and matplotlib for years, and nothing referenced the directory beyond twosys.pathentries inconf.py.MANIFEST.inis removed. It named a nonexistentLICENSE.txt, and flit never read it.sphinx<=6.2.1.Deliberately not addressed
The six autodoc warnings that remain are the open question in #853 and are untouched here. See #853 for new findings on it, including why emptying
ce_util.__all__is not a clean option.Six
game_theorydocstrings callnp.set_printoptions(precision=4)and never restore it. Harmless as rendered documentation, but under a package-wide doctest run it leaks into every module collected later. Left alone; tracked separately.Validation
pytest quanteconon the merged branch — 678 passed, 2 pre-existing warningsflake8 --select=F401,F405,E231 quantecon— cleansphinx-build— succeeds, 6 warnings, all of them Six objects in the deprecated shims' __all__ are missing from the top-level quantecon namespace #853util/timing.py, whose elapsed-time values are illustrative by design, andutil/notebooks.py, which needs the network. Neither is masked with# doctest: +SKIP, which would render visibly in the published docs.qe_apidoc.pyis idempotent and regenerates the committed.rstbyte-for-byte on the merged branch, so the CI drift gate passes.quantecon/, apart from the shim deprecation strings and the removed module.🤖 Generated with Claude Code