Skip to content

docs: fix factual errors found in review - #547

Merged
lesnik512 merged 1 commit into
mainfrom
docs/fix-facts
Oct 3, 2026
Merged

lesnik512 merged 1 commit into
mainfrom
docs/fix-facts

Conversation

@lesnik512

Copy link
Copy Markdown
Member

Summary

Fixes docs claims that disagree with the code. Each item below names what was wrong and the source that shows it.

Changes

  • troubleshooting/unsupported-creator-parameter-error.md, providers/factories.md: the example creator was positional-only, but for def f(items, /) the kwargs route still raises UnsupportedCreatorParameterError and skip_creator_parsing raises CreatorCallError (types_parser.py:65-76, confirmed by running). Dropped the / from the example and stated that positional-only params need a default.
  • introduction/design-decisions.md: a Factory subclass raises TypeError (resolver_compiler.py:48-57), so the generator-creator advice now points to a plain creator plus CacheSettings(finalizer=). A missing provider is an ArgumentResolutionError from validate() or resolve (factory.py:190), not a declaration-time error. Overrides use one tree-wide registry and the lock is per tree (container.py:116-126). The async and Beta statements are now plain.
  • migration/from-that-depends.md, from-dependency-injector.md: a cached Factory caches one object per container, so the ThreadLocalSingleton workaround now uses an uncached Factory over a module-level threading.local() (tested with 3 threads).
  • migration/to-3.x.md: added the blank line that ends the !!! warning block, and removed the "an earlier version said" note.
  • troubleshooting/max-scope-reached-error.md: uses build_child_container(scope=MyScope.SUBSTEP) with a one-member IntEnum in place of the internal parent_container= (confirmed by running).
  • troubleshooting/circular-dependency.md, missing-provider.md, context-not-set.md: sample output regenerated from real runs, now with the scope column and (module:line) (exceptions/rendering.py:42).
  • index.md: Flask, gRPC and Typer don't close the root container (no shutdown hook), and pytest builds no child per test. Also "smallest example".
  • dev/contributing.md: the gate is report.fail_under = 100 in pyproject.toml. providers/errors-and-exceptions.md: Group(scope=...) also raises InvalidScopeTypeError (group.py:23). recipes/good-and-bad-practices.md: removed the history wording.
  • Integrations, checked against each modern-di-<name> repo:
    • celery: worker_init/worker_shutdown (main.py:37-40), plus the *args/**kwargs TypeError (main.py:68-75).
    • arq: for @inject tasks the wrapper closes the child, and on_job_end only closes it as a safety net (main.py:86-90,188-198).
    • flask: corrected the "as above" reference and the route-order comment (route order only matters for auto_inject, main.py:51-52).
    • grpc: validate() never constructs anything, so the default only matters for resolving outside an RPC (confirmed by running).
    • fastapi: added fetch_di_container to the API table. typer: added action_scope(ctx).
    • faststream: corrected the FromDI signature and dropped "no longer". taskiq: added use_cache, and the child is built lazily via TaskiqDepends.
    • litestar: name collisions with app dependencies, and passing a provider instance to FromDI under autowired_groups raises ImproperlyConfiguredException.
    • pytest: an override set in the test body landed after the fixture had resolved, so the example failed when run. Moved the override into a container fixture that the dependency fixture uses (confirmed with pytest).
    • writing-integrations: the pin is now <4, Typer root lookup goes through context_settings["obj"], decorator integrations do register connection providers, and noted auto_inject/DITask and the extra modules in aiogram and pytest.
  • Checked and left unchanged: providers/scopes.md:16. The FastAPI, Starlette, Litestar and aiohttp integrations do enter SESSION for websockets.

Checklist

  • Lint and format pass (ruff)
  • Type check passes (ty)
  • Tests pass and new behavior is covered
  • Build succeeds (uv build) if packaging or build config changed
  • Repo metadata stays consistent across the three surfaces (GitHub description, pyproject description, profile blurb) if this touches packaging

just lint-ci, just test-ci (100% coverage) and mkdocs build --strict all pass.

- Troubleshooting: positional-only params only fixable with a default;
  MaxScopeReachedError fix uses build_child_container with a one-member
  IntEnum; error samples regenerated from real output.
- factories.md: scope the three escape routes.
- design-decisions.md: generator-creator advice, missing-provider wording,
  tree-wide overrides and lock, plain async and Beta statements.
- Migration: ThreadLocalSingleton workaround, to-3.x warning block and
  correction note.
- Integrations: celery worker_init/worker_shutdown and *args TypeError,
  arq child close timing, flask, grpc, fastapi/typer API rows, faststream
  and taskiq FromDI signatures, litestar collisions, pytest overrides,
  writing-integrations facts.
- index.md, contributing.md, errors-and-exceptions.md, good-and-bad-practices.md.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark

Details
Benchmark suite Current: 8a17acb Previous: 8ce868f Ratio
benchmarks/test_guard_by_type.py::test_g16_resolve_by_type 6860220.469637784 iter/sec (stddev: 1.1350279026376358e-8) 3442054.526547969 iter/sec (stddev: 2.143375745788722e-8) 0.50
benchmarks/test_guard_by_type.py::test_g17_resolve_by_type_large_registry 6634242.910004253 iter/sec (stddev: 1.1118838523911411e-8) 3548434.840392541 iter/sec (stddev: 1.2827232048867815e-8) 0.53
benchmarks/test_guard_cold.py::test_g8_cold_first_resolve 20086.76388833524 iter/sec (stddev: 0.0002127862113507429) 15518.545714422256 iter/sec (stddev: 0.00004698793690022765) 0.77
benchmarks/test_guard_cold.py::test_g8b_cold_first_resolve_cached 18162.24197549022 iter/sec (stddev: 0.000032183694633676134) 13185.693699108479 iter/sec (stddev: 0.00010949077679688568) 0.73
benchmarks/test_guard_concurrency.py::test_g14_concurrent_cached_hit[1] 802.4842572229129 iter/sec (stddev: 0.00009788610786291962) 404.3230311283974 iter/sec (stddev: 0.00007048845657185601) 0.50
benchmarks/test_guard_concurrency.py::test_g14_concurrent_cached_hit[2] 682.3258283587447 iter/sec (stddev: 0.00004926030062943845) 383.4654873688378 iter/sec (stddev: 0.000046998100263502144) 0.56
benchmarks/test_guard_concurrency.py::test_g14_concurrent_cached_hit[4] 603.8768218237799 iter/sec (stddev: 0.00006520483457299476) 352.2463486495161 iter/sec (stddev: 0.00009127243270054909) 0.58
benchmarks/test_guard_concurrency.py::test_g15_concurrent_first_resolve[1] 1992.770097231849 iter/sec (stddev: 0.0001333977483374318) 1626.7073683300935 iter/sec (stddev: 0.0001986442227433345) 0.82
benchmarks/test_guard_concurrency.py::test_g15_concurrent_first_resolve[2] 1625.6971565124065 iter/sec (stddev: 0.00013948311717709868) 1327.7632191013151 iter/sec (stddev: 0.00017288226483966492) 0.82
benchmarks/test_guard_concurrency.py::test_g15_concurrent_first_resolve[4] 970.6024731749375 iter/sec (stddev: 0.001315486110555091) 960.0010675205933 iter/sec (stddev: 0.00017975799786761426) 0.99
benchmarks/test_guard_concurrency.py::test_g15b_concurrent_first_resolve_sibling_children[1] 2163.313434698019 iter/sec (stddev: 0.00013049710007195453) 1407.057453110696 iter/sec (stddev: 0.0010831166068909466) 0.65
benchmarks/test_guard_concurrency.py::test_g15b_concurrent_first_resolve_sibling_children[2] 1439.2394483119317 iter/sec (stddev: 0.00015047467334073196) 1175.7928128429965 iter/sec (stddev: 0.00021455490282242838) 0.82
benchmarks/test_guard_concurrency.py::test_g15b_concurrent_first_resolve_sibling_children[4] 957.3024442464645 iter/sec (stddev: 0.0001566678311087579) 784.9046406926733 iter/sec (stddev: 0.00021119103540343572) 0.82
benchmarks/test_guard_lifecycle.py::test_g6_build_child_container 1268532.4262865619 iter/sec (stddev: 4.743103233469329e-8) 826944.4808698264 iter/sec (stddev: 4.169575359621365e-8) 0.65
benchmarks/test_guard_lifecycle.py::test_g6b_build_child_container_auto_scope 1149102.8781506433 iter/sec (stddev: 3.822966211174696e-8) 754895.2503574233 iter/sec (stddev: 3.0409338412035246e-8) 0.66
benchmarks/test_guard_lifecycle.py::test_g7_request_lifecycle_batch 3171.698285863586 iter/sec (stddev: 0.000007740096462751993) 2421.0815300750833 iter/sec (stddev: 0.000020424490014428993) 0.76
benchmarks/test_guard_lifecycle.py::test_g7c_event_loop_floor_control 93277.60687478787 iter/sec (stddev: 0.00000100094982014164) 58408.76624586848 iter/sec (stddev: 0.0000018447825779836061) 0.63
benchmarks/test_guard_lifecycle.py::test_g13_teardown_at_scale 63873.447433154484 iter/sec (stddev: 0.0000013026365585484084) 43876.32191693938 iter/sec (stddev: 0.0000021012125198676007) 0.69
benchmarks/test_guard_lifecycle.py::test_g13b_teardown_at_scale_async_no_finalizers 806.807827234481 iter/sec (stddev: 0.00004342058717888897) 553.8315819315635 iter/sec (stddev: 0.00011049984251667817) 0.69
benchmarks/test_guard_resolve.py::test_g1_transient_resolve 3751181.5049841 iter/sec (stddev: 3.642543373787177e-8) 2179414.0503717246 iter/sec (stddev: 3.2116689283894473e-8) 0.58
benchmarks/test_guard_resolve.py::test_g2_cached_resolve 6474185.673742138 iter/sec (stddev: 1.1727614617152446e-8) 3331944.800863088 iter/sec (stddev: 1.8996420430089775e-8) 0.51
benchmarks/test_guard_resolve.py::test_g3_deep_chain 1270769.8597294868 iter/sec (stddev: 4.8332149085018514e-8) 728489.2646086639 iter/sec (stddev: 6.251243141025456e-8) 0.57
benchmarks/test_guard_resolve.py::test_g4_wide_resolve 764213.5894289435 iter/sec (stddev: 2.5539878049722226e-7) 468680.21058674285 iter/sec (stddev: 3.2602527219035675e-7) 0.61
benchmarks/test_guard_resolve.py::test_g5_cross_scope 3550509.7289320664 iter/sec (stddev: 2.3962636628665118e-8) 1866879.1921924949 iter/sec (stddev: 3.339221547534178e-8) 0.53
benchmarks/test_guard_resolve.py::test_g9_context_resolve 1768069.582736624 iter/sec (stddev: 1.2523246341256786e-7) 1052288.8650783815 iter/sec (stddev: 1.333290563243788e-7) 0.60
benchmarks/test_guard_resolve.py::test_g12_override_active_resolve 1296090.013971847 iter/sec (stddev: 3.4713002666392195e-8) 720244.7622185523 iter/sec (stddev: 6.1118782837122e-8) 0.56
benchmarks/test_guard_resolve.py::test_g18_alias_hop 4519560.54503975 iter/sec (stddev: 1.5636115066043727e-8) 1889630.0710914063 iter/sec (stddev: 4.658060565489605e-8) 0.42
benchmarks/test_guard_validate.py::test_g10_validate_deep_chain 28760.641820904686 iter/sec (stddev: 0.0000154937778851691) 22333.268360870607 iter/sec (stddev: 0.00003390432019260961) 0.78
benchmarks/test_guard_validate.py::test_g11_validate_wide 18381.735260884343 iter/sec (stddev: 0.000018514738717146934) 14119.363707672732 iter/sec (stddev: 0.000028698284721104412) 0.77

This comment was automatically generated by workflow using github-action-benchmark.

@lesnik512
lesnik512 merged commit 645a3ab into main Oct 3, 2026
10 checks passed
@lesnik512
lesnik512 deleted the docs/fix-facts branch October 3, 2026 09:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant