Skip to content

fix(di): skip auto-wiring unregistered constructor parameters with default values - #134

Merged
alialfostovar merged 2 commits into
Baseryn:release/v0.1.0-rc.3from
dwaddle:fix/ioc-auto-wire-default-params
Oct 18, 2026
Merged

alialfostovar merged 2 commits into
Baseryn:release/v0.1.0-rc.3from
dwaddle:fix/ioc-auto-wire-default-params

Conversation

@dwaddle

@dwaddle dwaddle commented Oct 17, 2026

Copy link
Copy Markdown
Contributor

Fixes #131

Problem

IoCContainer._auto_wire collected all type-annotated constructor parameters into dependencies without checking whether param.default is not inspect.Parameter.empty. When a class constructor declared parameters with default values for primitive or unregistered types (e.g., timeout: int = 30 or client: Any = None), _auto_wire attempted to resolve those types through the container, raising TypeError or unexpected resolution failures.

Solution

  • Add IoCContainer._is_registered to check whether a dependency type is explicitly registered in _singletons, _scoped_definitions, _factories, or active _scoped_instances.
  • In IoCContainer._auto_wire, skip variadic parameters (*args, **kwargs) and parameters that define a default value (param.default is not inspect.Parameter.empty) when their type annotation is not explicitly registered in the container, allowing Python to fall back to the parameter's default value (consistent with background_task._resolve_injections).
  • Add unit tests in tests/test_di.py covering primitive/unregistered defaults, mixed required dependencies + defaults, and explicitly registered dependencies with defaults.

Backward Compatibility

100% backward compatible; all required constructor dependencies and explicitly registered optional dependencies continue to be injected identically.

@alialfostovar

Copy link
Copy Markdown
Contributor

Hi @dwaddle,

First off, thank you so much for this! The PR is super clean and the unit tests you added are spot-on.

The CI test suite ran across 518 tests (516 passed 🎉), but caught two minor regressions on existing lifecycle edge-cases:

  1. tests/test_config.py::test_settings_get_settings_fallback: Settings wasn't tracked in _singletons after resolution.
  2. tests/test_web.py::test_scoped_dependency_middleware_lifecycle: Resolving a scoped dependency (AsyncSession) outside an active scope should raise an error, but didn't.

If you have a few minutes to tweak the auto-wiring logic to let these pass, that would be amazing!

No pressure at all though—if you're short on time, just let me know and I'd be more than happy to push a commit to your branch to patch these two tests and get it merged for v0.1.0-rc.3.

Really appreciate your support for ZCore! 🚀

@dwaddle

dwaddle commented Oct 18, 2026

Copy link
Copy Markdown
Contributor Author

Hi @alialfostovar, thank you for the kind words and for pointing out those two lifecycle edge-cases!

I've pushed 046489e to address both:

  1. BaseSettings singleton tracking: When a BaseSettings subclass (such as Settings) is resolved via _auto_wire, the constructed instance is now registered in self._singletons[target_class] so test_settings_get_settings_fallback and subsequent resolutions share the singleton instance.
  2. Scoped dependency guard outside active scopes: resolve() and _auto_wire() now explicitly raise DIException when attempting to resolve a registered scoped dependency or AsyncSession outside of an active scope (_current_scope_id.get() is None), plus added a unit test in tests/test_di.py.

Verified locally across the full suite (519/519 passing).

@alialfostovar

Copy link
Copy Markdown
Contributor

Hi @dwaddle,

Fantastic turnaround! Thank you for addressing both of those lifecycle edge cases so cleanly—and awesome to see all 519 tests green across the board 🎉

I'll do a final review pass on the full diff shortly and merge this into master for the upcoming v0.1.0-rc.3 release.

Really appreciate your quality contribution! 🚀

@alialfostovar
alialfostovar changed the base branch from master to release/v0.1.0-rc.3 October 18, 2026 15:38
@alialfostovar
alialfostovar merged commit 3c35710 into Baseryn:release/v0.1.0-rc.3 Oct 18, 2026
14 checks passed
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.

bug: IoCContainer _auto_wire ignores default parameter values causing resolution crashes

2 participants