From 29588eed2b32714a3185c58e616619004967464d Mon Sep 17 00:00:00 2001 From: AlexeyTarasov77 Date: Sat, 15 Feb 2025 19:28:54 +0100 Subject: [PATCH] Fixed default parameters matching to support None as a default parameter value --- punq/__init__.py | 13 +++++++------ tests/test_kwarg_defaults.py | 8 ++++++-- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/punq/__init__.py b/punq/__init__.py index aa6b135..b808e85 100644 --- a/punq/__init__.py +++ b/punq/__init__.py @@ -197,12 +197,13 @@ def _match_defaults(spec): # Defaults for args are just a tuple. We match args with their defaults # by position, starting at the first defaulted arg offset = len(spec.args) - len(spec.defaults) - defaults = ([None] * offset) + list(spec.defaults) + defaults = ([empty] * offset) + list(spec.defaults) - ns = {key: value for key, value in zip(spec.args, defaults) if value is not None} + # filter only args with default value presented + ns = {key: value for key, value in zip(spec.args, defaults) if value is not empty} if spec.kwonlydefaults is not None: - # defaults for kwargs are in a dict, so we just update the result dict. + # defaults for kwargs are in a dict, so we just update the result dict ns.update(spec.kwonlydefaults) return ns @@ -491,7 +492,7 @@ def _build_impl(self, registration, resolution_args, context): args = _match_defaults(spec) args.update({ - k: self._resolve_impl(v, resolution_args, context, args.get(k)) + k: self._resolve_impl(v, resolution_args, context, args.get(k, empty)) for k, v in registration.needs.items() if k != "return" and k not in registration.args and k not in resolution_args }) @@ -516,7 +517,7 @@ def _should_auto_register(self, service_key, registration): return False return registration is None and inspect.isclass(service_key) - def _resolve_impl(self, service_key, kwargs, context, default=None): + def _resolve_impl(self, service_key, kwargs, context, default=empty): context = self.registrations.build_context(service_key, context) if service_key in self._singletons: @@ -532,7 +533,7 @@ def _resolve_impl(self, service_key, kwargs, context, default=None): registration = target.next_impl() - if registration is None and default is not None: + if registration is None and default is not empty: return default if self._should_auto_register(service_key, registration): diff --git a/tests/test_kwarg_defaults.py b/tests/test_kwarg_defaults.py index bd5a25e..6c028c7 100644 --- a/tests/test_kwarg_defaults.py +++ b/tests/test_kwarg_defaults.py @@ -8,9 +8,10 @@ class Dep: class Client: - def __init__(self, a: Dep, b: int = 10): + def __init__(self, a: Dep, b: int = 10, c: str | None = None): self.a = a self.b = b + self.c = c def test_can_create_instance_with_defaulted_kwarg(): @@ -20,6 +21,7 @@ def test_can_create_instance_with_defaulted_kwarg(): client = container.resolve(Client) expect(client.b).to(equal(10)) + expect(client.c).to(equal(None)) def test_defaults_are_superseded_by_registrations(): @@ -30,6 +32,7 @@ def test_defaults_are_superseded_by_registrations(): client = container.resolve(Client) expect(client.b).to(equal(3)) + expect(client.c).to(equal(None)) def test_defaults_are_superseded_by_context(): @@ -37,5 +40,6 @@ def test_defaults_are_superseded_by_context(): container.register(Dep) container.register(Client) - client = container.resolve(Client, b=5) + client = container.resolve(Client, b=5, c="win") expect(client.b).to(equal(5)) + expect(client.c).to(equal("win"))