Repository navigation
docs: rework the wiring, alias, group and kwargs troubleshooting pages - #663
Merged
Merged
Conversation
Quote the real error text on every page, fix examples that hid a DuplicateProviderTypeError, correct the missing-provider and circular-dependency fix advice, and make every Works example build a container so the docs tests catch regressions.
There was a problem hiding this comment.
Benchmark
Details
| Benchmark suite | Current: 5a9bb67 | Previous: 395e8fb | Ratio |
|---|---|---|---|
benchmarks/test_guard_by_type.py::test_g16_resolve_by_type |
4750198.688951317 iter/sec (stddev: 2.3234789889186473e-8) |
6139935.138982263 iter/sec (stddev: 1.8605923146541302e-8) |
1.29 |
benchmarks/test_guard_by_type.py::test_g17_resolve_by_type_large_registry |
5159815.214623165 iter/sec (stddev: 6.54861821200782e-9) |
6205832.315667191 iter/sec (stddev: 1.3805592208773412e-8) |
1.20 |
benchmarks/test_guard_cold.py::test_g8_cold_first_resolve |
32959.5627619044 iter/sec (stddev: 0.000035615743014019225) |
32024.886577255867 iter/sec (stddev: 0.000030238944431934) |
0.97 |
benchmarks/test_guard_cold.py::test_g8b_cold_first_resolve_cached |
26089.773081797834 iter/sec (stddev: 0.00009554265666040005) |
24960.133332489408 iter/sec (stddev: 0.00011886986138363566) |
0.96 |
benchmarks/test_guard_concurrency.py::test_g14_concurrent_cached_hit[1] |
658.0016032234211 iter/sec (stddev: 0.00006042023167463634) |
775.0388204206938 iter/sec (stddev: 0.00004473754687217169) |
1.18 |
benchmarks/test_guard_concurrency.py::test_g14_concurrent_cached_hit[2] |
647.3457622181978 iter/sec (stddev: 0.00002843147166467482) |
764.2436132277375 iter/sec (stddev: 0.0001144571715558005) |
1.18 |
benchmarks/test_guard_concurrency.py::test_g14_concurrent_cached_hit[4] |
618.8227778828133 iter/sec (stddev: 0.00004109459785604703) |
680.0345534095648 iter/sec (stddev: 0.0000803400475442327) |
1.10 |
benchmarks/test_guard_concurrency.py::test_g15_concurrent_first_resolve[1] |
19002.212807836837 iter/sec (stddev: 0.000005392733855465352) |
10419.935559673875 iter/sec (stddev: 0.00001230746171334532) |
0.55 |
benchmarks/test_guard_concurrency.py::test_g15_concurrent_first_resolve[2] |
9737.807899266536 iter/sec (stddev: 0.000015023667747879051) |
5634.100392630293 iter/sec (stddev: 0.00003435893765767916) |
0.58 |
benchmarks/test_guard_concurrency.py::test_g15_concurrent_first_resolve[4] |
4614.2346061544895 iter/sec (stddev: 0.00006300250814986734) |
2968.9836953557647 iter/sec (stddev: 0.000061919224501018) |
0.64 |
benchmarks/test_guard_concurrency.py::test_g15b_concurrent_first_resolve_sibling_children[1] |
12697.28942499804 iter/sec (stddev: 0.000007078833510845157) |
12389.480670083722 iter/sec (stddev: 0.000019500905757513246) |
0.98 |
benchmarks/test_guard_concurrency.py::test_g15b_concurrent_first_resolve_sibling_children[2] |
6074.662461382533 iter/sec (stddev: 0.000015415074775060534) |
4843.535831204409 iter/sec (stddev: 0.00003981695650002605) |
0.80 |
benchmarks/test_guard_concurrency.py::test_g15b_concurrent_first_resolve_sibling_children[4] |
2727.735264381467 iter/sec (stddev: 0.000036021411070600376) |
1868.0290700812566 iter/sec (stddev: 0.00007765838735564648) |
0.68 |
benchmarks/test_guard_concurrency.py::test_g15c_worker_pool_floor_control[1] |
51964.69864875924 iter/sec (stddev: 0.000002363034821420123) |
24896.9783783031 iter/sec (stddev: 0.000017881784016521047) |
0.48 |
benchmarks/test_guard_concurrency.py::test_g15c_worker_pool_floor_control[2] |
22854.64843561566 iter/sec (stddev: 0.000010269317953374485) |
11645.85197075752 iter/sec (stddev: 0.000015482573556939863) |
0.51 |
benchmarks/test_guard_concurrency.py::test_g15c_worker_pool_floor_control[4] |
8631.845323089257 iter/sec (stddev: 0.000022672424357912897) |
5052.235696391264 iter/sec (stddev: 0.000048475453192008314) |
0.59 |
benchmarks/test_guard_lifecycle.py::test_g6_build_child_container |
2206987.3882843857 iter/sec (stddev: 2.1192510241899735e-8) |
2335541.2567186337 iter/sec (stddev: 3.860763352243666e-8) |
1.06 |
benchmarks/test_guard_lifecycle.py::test_g6b_build_child_container_auto_scope |
2377850.9838867686 iter/sec (stddev: 2.1162243024614208e-8) |
2505907.6773532387 iter/sec (stddev: 3.905850495221895e-8) |
1.05 |
benchmarks/test_guard_lifecycle.py::test_g7_request_lifecycle_batch |
4297.152892765896 iter/sec (stddev: 0.000006469049794878834) |
3317.2697581338502 iter/sec (stddev: 0.000052891745120707064) |
0.77 |
benchmarks/test_guard_lifecycle.py::test_g7c_event_loop_floor_control |
75334.51114415422 iter/sec (stddev: 0.0000012633309713723485) |
83100.58991551855 iter/sec (stddev: 0.0000014527703096612033) |
1.10 |
benchmarks/test_guard_lifecycle.py::test_g7b_request_cycle_sync |
533013.965579637 iter/sec (stddev: 5.4035962764772836e-8) |
468518.9908558271 iter/sec (stddev: 8.515899938405845e-8) |
0.88 |
benchmarks/test_guard_lifecycle.py::test_g13_teardown_at_scale |
81661.86882821958 iter/sec (stddev: 0.0000010990419881578487) |
78785.45603292529 iter/sec (stddev: 0.0000017671089125152717) |
0.96 |
benchmarks/test_guard_lifecycle.py::test_g13b_teardown_at_scale_async_no_finalizers |
753.6125139931671 iter/sec (stddev: 0.0009246902143746485) |
586.9668417253587 iter/sec (stddev: 0.0013708543619692236) |
0.78 |
benchmarks/test_guard_resolve.py::test_g1_transient_resolve |
2885809.665850824 iter/sec (stddev: 2.0350585542345523e-8) |
3091773.339921797 iter/sec (stddev: 3.1905368666696455e-8) |
1.07 |
benchmarks/test_guard_resolve.py::test_g2_cached_resolve |
4963779.302433907 iter/sec (stddev: 6.782386687134114e-9) |
5585002.481125255 iter/sec (stddev: 1.7326975696337195e-8) |
1.13 |
benchmarks/test_guard_resolve.py::test_g3_deep_chain |
1008560.9680641184 iter/sec (stddev: 4.209705229620944e-8) |
1053634.7223852123 iter/sec (stddev: 4.376268176758002e-8) |
1.04 |
benchmarks/test_guard_resolve.py::test_g4_wide_resolve |
612874.4701308002 iter/sec (stddev: 3.3833713132520127e-7) |
602475.4027370019 iter/sec (stddev: 3.669391702377282e-7) |
0.98 |
benchmarks/test_guard_resolve.py::test_g5_cross_scope |
2598865.049632129 iter/sec (stddev: 1.5610323403957834e-8) |
2722743.1964451196 iter/sec (stddev: 2.2608711961763022e-8) |
1.05 |
benchmarks/test_guard_resolve.py::test_g9_context_resolve |
2004663.9509149287 iter/sec (stddev: 1.2111169439512558e-7) |
2095884.4060996436 iter/sec (stddev: 1.4539795764318154e-7) |
1.05 |
benchmarks/test_guard_resolve.py::test_g12_override_active_resolve |
1024176.1910789233 iter/sec (stddev: 2.6727729786419252e-8) |
1056924.0255533508 iter/sec (stddev: 4.539064934432262e-8) |
1.03 |
benchmarks/test_guard_resolve.py::test_g18_alias_hop |
4989875.542511868 iter/sec (stddev: 4.6312347992645395e-9) |
5564689.374851157 iter/sec (stddev: 1.595292015837515e-8) |
1.12 |
benchmarks/test_guard_validate.py::test_g10_validate_deep_chain |
54629.205089857984 iter/sec (stddev: 0.000014293526857234689) |
23951.926949647954 iter/sec (stddev: 0.000031960404140896095) |
0.44 |
benchmarks/test_guard_validate.py::test_g11_validate_wide |
30639.952169012224 iter/sec (stddev: 0.000021512660796096633) |
21724.253571453744 iter/sec (stddev: 0.00003130808206721572) |
0.71 |
This comment was automatically generated by workflow using github-action-benchmark.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Reworks the 13 troubleshooting pages for wiring, alias, group and
kwargserrors, the same per-page pass already done for the Quickstart, Introduction and Providers pages. I checked every behavioural claim by running a script against this checkout. The scripts live outside the repo.What was wrong
duplicate-type-error.mdandargument-resolution-error.mddeclared twoFactory(Repository)/Factory(Service)providers in one group. Building a container from either group raisesDuplicateProviderTypeError. Sybil never caught it because neither block built a container.unsupported-creator-parameter-error.mdhad the same latent duplicate (thingandthing2).creator-call-error.md,unknown-factory-kwarg-error.mdandgroup-instantiation-error.md, the Works half either replaced the Broken provider under the same attribute name or never ran, because the block stopped at the first raise.ArgumentResolutionError.ProviderNotRegisteredErrorcomes only from a directresolve(SomeType). The page also saidvalidate()catches a missing group. It catches a missing type only when another registered provider depends on it, so a type you only resolve directly still passesvalidate()(verified:Container().validate()passes, thenresolve(X)raises). Its union cause can only produceArgumentResolutionError, so it moved to that page.kwargsis still a graph edge, andvalidate()still reports the cycle. Only a static value breaks it. Likewise, an interface aliased back to a member of the cycle keeps the cycle (both verified).alias-bound-to-source-error.mdandduplicate-type-error.mdshowed<class 'Implementation'>and<class 'SomeType'>, but the library prints the module-qualified repr. Eight pages had only a paraphrase where the message should be.Dependencies()in a type annotation. Nothing supports that, so I cut it.What was added
myapp.<module>path and line numbers, including the variants: theDid you mean:block (subclass, base class, similar name), the union and unannotated forms ofArgumentResolutionError, bothUnsupportedCreatorParameterErrorreasons, and the plain resolve-timeCircularDependencyErrornext to thevalidate()form.classstatement, byContainer(...)/add_providers, byvalidate()insideValidationFailedError, or at resolve) and lists the attributes you can inspect.creator-call-error.md:validate()cannot catch it underskip_creator_parsing=True, and it also covers a positional-only parameter passed by keyword.unknown-factory-kwarg-error.md: the check is skipped for**kwargscreators, for unreadable signatures and underskip_creator_parsing=True. In that last case a bad key surfaces asCreatorCallErrorat resolve.duplicate-type-error.md: the distinct-subclass fix the recipes already recommend, plus abound_type=Noneexample that builds a container and resolves both pairs.circular-dependency.md: a runnable example of breaking the cycle with an interface whose provider sits outside it.Structure
<!-- raises: X -->block that really raises X. Works examples build aContainerand resolve or validate, so Sybil catches a hidden duplicate from now on.missing-provider.mdH1 is now# ProviderNotRegisteredError, per docs-style.md (the class name describes the symptom well).context-not-set.mdkeeps its sanctioned symptom H1.circular-dependency.md: the top-level "How to detect" section is gone. The runtime-guard text is now an H3 under Cause, and thevalidate()block opens Fix.context-not-set.md: causes 1 and 2 (the same scope-mismatch mechanism, from both directions) are merged. The optional-value cause now links toproviders/context.mdand no longer repeats it.unsupported-creator-parameter-error.md: the "Escape hatches" section is folded into theskip_creator_parsingoption. The default example usestuple[Item, ...] = (), which matches its type.[Title](link): gloss.format of the reworked Providers pages.Anchors kept
circular-dependency.md#the-runtime-cycle-guard-without-validatekeeps its heading text verbatim.providers/errors-and-exceptions.mdandrecipes/good-and-bad-practices.mdlink to it.docs_slugcensus and everySee:URL still match.mkdocs --strictwithanchors: warnis clean).Checks
just test-docs -q -p no:cacheprovider --no-cov: 174 passed, 21 skippedjust docs-build: no WARNING linesjust lint-ci: cleanlychee --offlineoverdocsandREADME.md: 0 errorstests/test_docs_slug_census.py: passedPossible library bugs (not fixed here)
DuplicateProviderTypeErrorwithfirst_provider is second_provider. The message tells you to setbound_type=None"on one of them", but there is only one.providers/scopes.mdsays sharing an instance across groups is allowed, which holds at class-creation time only.Factory(SomeType)attributes in one group both print- Factory (myapp.ioc:4), the creator's line, so the message doesn't show which attributes collide.Factory(Implementation, bound_type=None)plusAlias(Implementation, bound_type=Interface)reportsAlias source type ... is not registered in providers registry, even though a provider exists by reference. The page lists this case as a cause.Needed outside this batch
docs/introduction/resolving.md:71: change the link text "No provider registered for type" to "ProviderNotRegisteredError" to match the new H1.docs/providers/errors-and-exceptions.md:130,156,167: the link texts "Troubleshooting: Missing provider", "Context not set" and "Duplicate type" no longer match their targets' H1s.docs/recipes/multi-group.md:118anddocs/recipes/request-scoped-engine.md:88: change "Duplicate provider type" to "DuplicateProviderTypeError".docs/providers/scopes.md(group-level default scope): "Sharing the same provider instance ... is allowed" should mention bug 1, or bug 1 should be fixed.mkdocs.ymlnav label "Missing provider for type" could become "Provider not registered".