Skip to content

Commit e847c35

Browse files
committed
Merge branch 'release/4.3.3' into master
2 parents c1cf1bf + 25549d7 commit e847c35

File tree

4 files changed

+53
-13
lines changed

4 files changed

+53
-13
lines changed

docs/main/changelog.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ that were made in every particular version.
77
From version 0.7.6 *Dependency Injector* framework strictly
88
follows `Semantic versioning`_
99

10+
4.3.3
11+
-----
12+
- Fix a bug in ``wiring`` with improper patching of ``@classmethod`` and ``@staticmethod`` decorated methods
13+
(See issue `#318 <https://github.com/ets-labs/python-dependency-injector/issues/318>`_).
14+
1015
4.3.2
1116
-----
1217
- Fix a bug in ``wiring`` with mistakenly initialized and shutdown resource with ``Closing``

src/dependency_injector/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""Top-level package."""
22

3-
__version__ = '4.3.2'
3+
__version__ = '4.3.3'
44
"""Version number.
55
66
:type: str

src/dependency_injector/wiring.py

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import pkgutil
66
import sys
77
from types import ModuleType
8-
from typing import Optional, Iterable, Callable, Any, Tuple, Dict, Generic, TypeVar, cast
8+
from typing import Optional, Iterable, Callable, Any, Tuple, Dict, Generic, TypeVar, Type, cast
99

1010
if sys.version_info < (3, 7):
1111
from typing import GenericMeta
@@ -176,7 +176,7 @@ def wire(
176176
_patch_fn(module, name, member, providers_map)
177177
elif inspect.isclass(member):
178178
for method_name, method in inspect.getmembers(member, _is_method):
179-
_patch_fn(member, method_name, method, providers_map)
179+
_patch_method(member, method_name, method, providers_map)
180180

181181

182182
def unwire(
@@ -195,10 +195,10 @@ def unwire(
195195
for module in modules:
196196
for name, member in inspect.getmembers(module):
197197
if inspect.isfunction(member):
198-
_unpatch_fn(module, name, member)
198+
_unpatch(module, name, member)
199199
elif inspect.isclass(member):
200200
for method_name, method in inspect.getmembers(member, inspect.isfunction):
201-
_unpatch_fn(member, method_name, method)
201+
_unpatch(member, method_name, method)
202202

203203

204204
def _patch_fn(
@@ -210,10 +210,41 @@ def _patch_fn(
210210
injections, closing = _resolve_injections(fn, providers_map)
211211
if not injections:
212212
return
213-
setattr(module, name, _patch_with_injections(fn, injections, closing))
213+
patched = _patch_with_injections(fn, injections, closing)
214+
setattr(module, name, _wrap_patched(patched, fn, injections, closing))
214215

215216

216-
def _unpatch_fn(
217+
def _patch_method(
218+
cls: Type,
219+
name: str,
220+
method: Callable[..., Any],
221+
providers_map: ProvidersMap,
222+
) -> None:
223+
injections, closing = _resolve_injections(method, providers_map)
224+
if not injections:
225+
return
226+
227+
if hasattr(cls, '__dict__') \
228+
and name in cls.__dict__ \
229+
and isinstance(cls.__dict__[name], (classmethod, staticmethod)):
230+
method = cls.__dict__[name]
231+
patched = _patch_with_injections(method.__func__, injections, closing)
232+
patched = type(method)(patched)
233+
else:
234+
patched = _patch_with_injections(method, injections, closing)
235+
236+
setattr(cls, name, _wrap_patched(patched, method, injections, closing))
237+
238+
239+
def _wrap_patched(patched: Callable[..., Any], original, injections, closing):
240+
patched.__wired__ = True
241+
patched.__original__ = original
242+
patched.__injections__ = injections
243+
patched.__closing__ = closing
244+
return patched
245+
246+
247+
def _unpatch(
217248
module: ModuleType,
218249
name: str,
219250
fn: Callable[..., Any],
@@ -276,12 +307,6 @@ def _patch_with_injections(fn, injections, closing):
276307
_patched = _get_async_patched(fn, injections, closing)
277308
else:
278309
_patched = _get_patched(fn, injections, closing)
279-
280-
_patched.__wired__ = True
281-
_patched.__original__ = fn
282-
_patched.__injections__ = injections
283-
_patched.__closing__ = closing
284-
285310
return _patched
286311

287312

tests/unit/wiring/test_wiring_py36.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,20 @@ def test_class_classmethod_wiring(self):
6565
service = module.TestClass.class_method()
6666
self.assertIsInstance(service, Service)
6767

68+
def test_instance_classmethod_wiring(self):
69+
instance = module.TestClass()
70+
service = instance.class_method()
71+
self.assertIsInstance(service, Service)
72+
6873
def test_class_staticmethod_wiring(self):
6974
service = module.TestClass.static_method()
7075
self.assertIsInstance(service, Service)
7176

77+
def test_instance_staticmethod_wiring(self):
78+
instance = module.TestClass()
79+
service = instance.static_method()
80+
self.assertIsInstance(service, Service)
81+
7282
def test_function_wiring(self):
7383
service = module.test_function()
7484
self.assertIsInstance(service, Service)

0 commit comments

Comments
 (0)