Skip to content

Commit 1163ac5

Browse files
committed
Return ABCMeta class for resource classes and add tests for abc
1 parent 4286013 commit 1163ac5

File tree

2 files changed

+78
-30
lines changed

2 files changed

+78
-30
lines changed

src/dependency_injector/resources.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
T = TypeVar('T')
88

99

10-
class Resource(Generic[T]):
10+
class Resource(Generic[T], metaclass=abc.ABCMeta):
1111

1212
@abc.abstractmethod
1313
def init(self, *args, **kwargs) -> T:
@@ -18,7 +18,7 @@ def shutdown(self, resource: T) -> None:
1818
...
1919

2020

21-
class AsyncResource(Generic[T]):
21+
class AsyncResource(Generic[T], metaclass=abc.ABCMeta):
2222

2323
@abc.abstractmethod
2424
async def init(self, *args, **kwargs) -> T:

tests/unit/providers/test_resource_py35.py

Lines changed: 76 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,44 @@ def shutdown(self, _):
145145
self.assertEqual(TestResource.init_counter, 2)
146146
self.assertEqual(TestResource.shutdown_counter, 2)
147147

148+
def test_init_class_generic_typing(self):
149+
# See issue: https://github.com/ets-labs/python-dependency-injector/issues/488
150+
class TestDependency:
151+
...
152+
153+
class TestResource(resources.Resource[TestDependency]):
154+
def init(self, *args: Any, **kwargs: Any) -> TestDependency:
155+
return TestDependency()
156+
157+
def shutdown(self, resource: TestDependency) -> None: ...
158+
159+
self.assertTrue(issubclass(TestResource, resources.Resource))
160+
161+
def test_init_class_abc_definition_is_required(self):
162+
class TestResource(resources.Resource):
163+
...
164+
165+
with self.assertRaises(TypeError) as context:
166+
TestResource()
167+
168+
self.assertEqual(
169+
"Can't instantiate abstract class TestResource with abstract methods init, shutdown",
170+
str(context.exception),
171+
)
172+
173+
def test_init_class_abc_shutdown_definition_is_required(self):
174+
class TestResource(resources.Resource):
175+
def init(self):
176+
...
177+
178+
with self.assertRaises(TypeError) as context:
179+
TestResource()
180+
181+
self.assertEqual(
182+
"Can't instantiate abstract class TestResource with abstract method shutdown",
183+
str(context.exception),
184+
)
185+
148186
def test_init_not_callable(self):
149187
provider = providers.Resource(1)
150188
with self.assertRaises(errors.Error):
@@ -449,6 +487,44 @@ async def shutdown(self, resource_):
449487
self.assertEqual(TestResource.init_counter, 2)
450488
self.assertEqual(TestResource.shutdown_counter, 2)
451489

490+
def test_init_async_class_generic_typing(self):
491+
# See issue: https://github.com/ets-labs/python-dependency-injector/issues/488
492+
class TestDependency:
493+
...
494+
495+
class TestAsyncResource(resources.AsyncResource[TestDependency]):
496+
async def init(self, *args: Any, **kwargs: Any) -> TestDependency:
497+
return TestDependency()
498+
499+
async def shutdown(self, resource: TestDependency) -> None: ...
500+
501+
self.assertTrue(issubclass(TestAsyncResource, resources.AsyncResource))
502+
503+
def test_init_async_class_abc_definition_is_required(self):
504+
class TestAsyncResource(resources.AsyncResource):
505+
...
506+
507+
with self.assertRaises(TypeError) as context:
508+
TestAsyncResource()
509+
510+
self.assertEqual(
511+
"Can't instantiate abstract class TestAsyncResource with abstract methods init, shutdown",
512+
str(context.exception),
513+
)
514+
515+
def test_init_async_class_abc_shutdown_definition_is_required(self):
516+
class TestAsyncResource(resources.AsyncResource):
517+
async def init(self):
518+
...
519+
520+
with self.assertRaises(TypeError) as context:
521+
TestAsyncResource()
522+
523+
self.assertEqual(
524+
"Can't instantiate abstract class TestAsyncResource with abstract method shutdown",
525+
str(context.exception),
526+
)
527+
452528
def test_init_with_error(self):
453529
async def _init():
454530
raise RuntimeError()
@@ -603,31 +679,3 @@ async def _init():
603679

604680
self.assertIs(result2, resource)
605681
self.assertEqual(_init.counter, 1)
606-
607-
608-
class ResourceTypingTest(unittest.TestCase):
609-
# See issue: https://github.com/ets-labs/python-dependency-injector/issues/488
610-
611-
def test_sync_generic_type(self):
612-
class MyDependency:
613-
...
614-
615-
class MyResource(resources.Resource[MyDependency]):
616-
def init(self, *args: Any, **kwargs: Any) -> MyDependency:
617-
return MyDependency()
618-
619-
def shutdown(self, resource: MyDependency) -> None: ...
620-
621-
self.assertTrue(issubclass(MyResource, resources.Resource))
622-
623-
def test_async_generic_type(self):
624-
class MyDependency:
625-
...
626-
627-
class MyAsyncResource(resources.AsyncResource[MyDependency]):
628-
async def init(self, *args: Any, **kwargs: Any) -> MyDependency:
629-
return MyDependency()
630-
631-
async def shutdown(self, resource: MyDependency) -> None: ...
632-
633-
self.assertTrue(issubclass(MyAsyncResource, resources.AsyncResource))

0 commit comments

Comments
 (0)