Skip to content

Commit

Permalink
Enter/exit sync contextmanagers in aget()
Browse files Browse the repository at this point in the history
Fixes #87

Co-authored-by: Adrian Schneider <[email protected]>
  • Loading branch information
hynek and adrianschneider94 committed Jul 2, 2024
1 parent 914e864 commit a487742
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 0 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ You can find our backwards-compatibility policy [here](https://github.com/hynek/
[#73](https://github.com/hynek/svcs/pull/73)


### Fixed

- `Container.aget()` now also enters and exists synchronous context managers.
[#93](https://github.com/hynek/svcs/pull/93)


## [24.1.0](https://github.com/hynek/svcs/compare/23.21.0...24.1.0) - 2024-01-25

### Fixed
Expand Down
4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,10 @@ ignore_missing_imports = true
module = "tests.*"
ignore_errors = true

[[tool.mypy.overrides]]
module = "conftest"
ignore_errors = true

[[tool.mypy.overrides]]
module = "tests.typing.*"
ignore_errors = false
Expand Down
6 changes: 6 additions & 0 deletions src/svcs/_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -995,6 +995,9 @@ async def aget(self, *svc_types: type) -> object:
Also works with synchronous services, so in an async application, just
use this.
.. versionchanged:: 24.2.0
Synchronous context managers are now entered/exited, too.
"""
rv = []
for svc_type in svc_types:
Expand All @@ -1008,6 +1011,9 @@ async def aget(self, *svc_types: type) -> object:
svc = await svc.__aenter__()
elif isawaitable(svc):
svc = await svc
elif enter and isinstance(svc, AbstractContextManager):
self._on_close.append((name, svc))
svc = svc.__enter__()

self._instantiated[svc_type] = svc

Expand Down
20 changes: 20 additions & 0 deletions tests/test_container.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,26 @@ def scope():
"Container was garbage-collected with pending cleanups.",
) == recwarn.list[0].message.args

@pytest.mark.asyncio()
async def test_aget_enters_sync_contextmanagers(self, container):
"""
aget enters (and exits) synchronous context managers.
"""
is_closed = False

def factory():
yield 42

nonlocal is_closed
is_closed = True

container.registry.register_factory(int, factory)

async with container:
assert 42 == await container.aget(int)

assert is_closed


class TestServicePing:
def test_ping(self, registry, container, close_me):
Expand Down

0 comments on commit a487742

Please sign in to comment.