Skip to content

Commit

Permalink
Allow factories to have any amount of arguments (#110)
Browse files Browse the repository at this point in the history
  • Loading branch information
hynek authored Oct 26, 2024
1 parent b20f965 commit ba77435
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 14 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ You can find our backwards-compatibility policy [here](https://github.com/hynek/
[#72](https://github.com/hynek/svcs/issues/72)
[#73](https://github.com/hynek/svcs/pull/73)

- `Registry.register_factory()` is now more lenient regarding the arguments of the factory.
It only looks at the first argument (if present) and ignores the rest.
[#110](https://github.com/hynek/svcs/pull/110)


### Fixed

Expand Down
15 changes: 7 additions & 8 deletions src/svcs/_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,9 @@ def register_factory(
Can also be an async callable or an
:class:`collections.abc.Awaitable`; then
:meth:`svcs.Registry.aclose()` must be called.
.. versionchanged:: 24.2.0
*factory* now may take any amount of arguments and they are ignored.
"""
rs = self._register_factory(
svc_type,
Expand Down Expand Up @@ -454,14 +457,10 @@ def _takes_container(factory: Callable) -> bool:
except Exception: # noqa: BLE001
return False

if not sig.parameters:
return False

if len(sig.parameters) != 1:
msg = "Factories must take 0 or 1 parameters."
raise TypeError(msg)

((name, p),) = tuple(sig.parameters.items())
try:
(name, p) = next(iter(sig.parameters.items()))
except StopIteration:
return False # 0 arguments

return name == "svcs_container" or p.annotation in (
Container,
Expand Down
9 changes: 3 additions & 6 deletions tests/test_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -432,17 +432,14 @@ def test_annotation_str(self, module_source, create_module):

assert svcs._core._takes_container(module.factory)

def test_catches_invalid_sigs(self):
def test_ignores_invalid_sigs(self):
"""
If the factory takes more than one parameter, raise an TypeError.
If the first parameter is anything but what we handle, ignore it.
"""

def factory(foo, bar): ...

with pytest.raises(
TypeError, match="Factories must take 0 or 1 parameters."
):
svcs._core._takes_container(factory)
assert not svcs._core._takes_container(factory)

def test_call_works(self):
"""
Expand Down

0 comments on commit ba77435

Please sign in to comment.