Skip to content

Commit f9ebe43

Browse files
committed
feat: add PyCharm 2026.1 type hint support for functional dependencies
1 parent dfe253d commit f9ebe43

6 files changed

Lines changed: 38 additions & 13 deletions

File tree

libs/dinkleberg/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "dinkleberg"
3-
version = "2.3.1"
3+
version = "3.0.0"
44
description = "Your friendly neighbour when it comes to dependency management."
55
requires-python = ">=3.12"
66
readme = "README.md"
Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1-
class Dependency:
2-
def __init__(self, **kwargs):
1+
class _Dependency:
2+
def __init__(self, t: type = None, **kwargs):
3+
self._t = t
34
self._kwargs = kwargs
5+
6+
7+
# noinspection PyPep8Naming
8+
def Dependency[T](t: type[T] = None, **kwargs) -> T:
9+
return _Dependency(t, **kwargs)

libs/dinkleberg/src/dinkleberg/dependency_configurator.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from typing import AsyncGenerator, Callable, overload, get_type_hints, Mapping, get_origin, get_args
88

99
from .dependency_scope import DependencyScope
10-
from .dependency import Dependency
10+
from .dependency import _Dependency
1111
from .dependency_resolution_error import DependencyResolutionError
1212
from .descriptor import Descriptor, Lifetime
1313
from .resolution_step import ResolutionStep
@@ -388,6 +388,7 @@ async def _resolve_factory_kwargs(self, factory: Callable, kwargs: dict, generic
388388

389389
return final_kwargs
390390

391+
# noinspection PyProtectedMember
391392
async def _resolve_kwargs(self, signature: Signature, name: str, args: tuple, kwargs: dict,
392393
dep_params: Mapping[str, inspect.Parameter], chain: tuple[ResolutionStep, ...]) -> dict:
393394
bound_args = signature.bind_partial(*args, **kwargs)
@@ -401,13 +402,15 @@ async def _resolve_kwargs(self, signature: Signature, name: str, args: tuple, kw
401402

402403
ann = p_param.annotation
403404
if ann is inspect.Parameter.empty:
404-
raise DependencyResolutionError(chain,
405-
message=f'Parameter "{p_name}" in {name} is missing a type annotation, '
406-
f'which is required for dependency resolution.')
405+
if p_param.default._t is not None:
406+
ann = p_param.default._t
407+
else:
408+
raise DependencyResolutionError(chain,
409+
message=f'Parameter "{p_name}" in {name} is missing a type '
410+
f'annotation, which is required for dependency resolution.')
407411

408412
is_optional, resolve_type = is_type_optional(ann)
409413

410-
# noinspection PyProtectedMember
411414
dep_kwargs = p_param.default._kwargs
412415
merged_kwargs = {**dep_kwargs, **kwargs}
413416

@@ -424,13 +427,13 @@ def _wrap_func(self, func: Callable, chain: tuple[ResolutionStep, ...]) -> Calla
424427
dep_params = MappingProxyType({
425428
param_name: param
426429
for param_name, param in signature.parameters.items()
427-
if isinstance(param.default, Dependency)
430+
if isinstance(param.default, _Dependency)
428431
})
429432

430433
if not dep_params:
431434
return func
432435

433-
if not asyncio.iscoroutinefunction(func):
436+
if not inspect.iscoroutinefunction(func):
434437
raise NotImplementedError('Synchronous functions with Dependency() defaults are not supported.')
435438

436439
@wraps(func)

libs/dinkleberg/src/dinkleberg/typing.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from types import UnionType
66
from typing import Callable, get_origin, get_type_hints, Union, get_args
77

8-
from .dependency import Dependency
8+
from .dependency import _Dependency
99

1010

1111
@lru_cache(maxsize=4096)
@@ -67,7 +67,7 @@ def get_methods_to_wrap(cls: type) -> tuple[str, ...]:
6767

6868
sig = get_signature(attr)
6969
for param in sig.parameters.values():
70-
if isinstance(param.default, Dependency):
70+
if isinstance(param.default, _Dependency):
7171
methods_to_wrap.append(name)
7272
break
7373
except (AttributeError, ValueError):

libs/dinkleberg/tests/test_functions.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,22 @@ async def test(t: Test = Dependency()):
1919
assert result == 'Hello, World!'
2020

2121

22+
@pytest.mark.asyncio
23+
async def test_resolve_function_without_annotation(di):
24+
class Test:
25+
def get_message(self):
26+
return 'Hello, World!'
27+
28+
async def test(t=Dependency(Test)):
29+
return t.get_message()
30+
31+
f = await di.resolve(test)
32+
33+
result = await f()
34+
35+
assert result == 'Hello, World!'
36+
37+
2238
@pytest.mark.asyncio
2339
async def test_resolve_function_with_kwargs(di):
2440
class Test:

uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)