Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
98c91ff
fix: resolve postponed injection annotations
xelandernt Jul 12, 2026
fa0f380
fix: bind injected arguments by signature
xelandernt Jul 12, 2026
e0fdd6d
feat: selector context registration.
xelandernt Jul 13, 2026
e629cda
Merge remote-tracking branch 'origin/main' into selector-contexts
xelandernt Jul 14, 2026
9b7693c
Merge remote-tracking branch 'origin/main' into selector-contexts
xelandernt Jul 14, 2026
212b1c9
Merge remote-tracking branch 'origin/main' into selector-contexts
xelandernt Jul 17, 2026
39323c6
Merge remote-tracking branch 'origin/main' into selector-contexts
xelandernt Jul 27, 2026
f0afbe3
plan: plan for implementation.
xelandernt Jul 27, 2026
9da6b4b
feat: add generic provider resolution contract
xelandernt Jul 28, 2026
9461023
test: prove dynamic provider resolution contract
xelandernt Jul 28, 2026
987e5ac
test: lock down selector resolution semantics
xelandernt Jul 28, 2026
66d866b
test: cover dynamic injection surfaces
xelandernt Jul 28, 2026
282690c
test: assert selector public resolution contract
xelandernt Jul 28, 2026
6d9d874
docs: explain dynamic provider resolution lifecycle
xelandernt Jul 28, 2026
b9cdc68
refactor: remove obsolete context order cache
xelandernt Jul 28, 2026
ee1ed72
perf: preserve static injection fast path
xelandernt Jul 28, 2026
51d2ef1
docs: remove the main decisions change.
xelandernt Jul 28, 2026
05ebd18
docs: removed selector change.
xelandernt Jul 28, 2026
16287d8
misc: removed plan.md
xelandernt Jul 28, 2026
b94dfb8
docs: explain resolution dependency hooks
xelandernt Jul 28, 2026
5ac184c
docs: document provider context traversal
xelandernt Jul 28, 2026
b3ac2cd
perf: minimize static injection branching
xelandernt Jul 28, 2026
d011d56
misc: add site to gitignore
xelandernt Jul 28, 2026
e6a6372
feat: re-write to ProviderWithResolutionContext
xelandernt Aug 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ dist/
.venv
uv.lock
.agents
site
2 changes: 0 additions & 2 deletions tests/providers/test_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,13 +100,11 @@ def test_invalidate_scope_init_order_handles_duplicate_descendants() -> None:
right.add_child_provider(shared)

for provider in (root, left, right, shared):
provider._scope_context_init_order = ()
provider._scope_init_order = ()

root._invalidate_scope_init_order()

for provider in (root, left, right, shared):
assert provider._scope_context_init_order is None
assert provider._scope_init_order is None


Expand Down
40 changes: 40 additions & 0 deletions tests/providers/test_selector.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,46 @@ async def test_selector_with_provider_selector_async() -> None:
assert (await StringProviderSelectorContainer.selector.resolve()) == "Provider 1"


def test_selector_registers_only_its_key_provider_as_static_dependency() -> None:
def _selector_key() -> typing.Iterator[str]: # pragma: no cover
yield "selected"

selector_key = providers.ContextResource(_selector_key)
selected = providers.Object("value")
selector = providers.Selector(selector_key, selected=selected)

assert selector._get_scope_init_order() == (selector_key, selector)
assert selector._get_scope_init_order() == (selector_key, selector)

selector._deregister_arguments()

assert selector._get_scope_init_order() == (selector_key, selector)


def test_selector_resolution_context_exposes_and_pins_selected_provider() -> None:
expected_selection_count = 2
selected_key = "one"
selection_count = 0
one = providers.Object("one")
two = providers.Object("two")

def _select() -> str:
nonlocal selection_count
selection_count += 1
return selected_key

selector = providers.Selector(_select, one=one, two=two)

assert isinstance(selector, providers.ProviderWithResolutionContext)
with selector.resolution_context_sync() as dependencies:
assert dependencies == (one,)
selected_key = "two"
assert selector.resolve_sync() == "one"

assert selector.resolve_sync() == "two"
assert selection_count == expected_selection_count


class InvalidSelectorContainer(BaseContainer):
selector = providers.Selector(
None, # type: ignore[arg-type]
Expand Down
Loading
Loading