python-injection 0.8.5__tar.gz → 0.9.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of python-injection might be problematic. Click here for more details.
- {python_injection-0.8.5 → python_injection-0.9.1}/PKG-INFO +3 -5
- {python_injection-0.8.5 → python_injection-0.9.1}/documentation/basic-usage.md +1 -1
- python_injection-0.9.1/injection/__init__.py +29 -0
- {python_injection-0.8.5 → python_injection-0.9.1}/injection/__init__.pyi +65 -46
- {python_injection-0.8.5 → python_injection-0.9.1}/injection/common/event.py +3 -3
- {python_injection-0.8.5 → python_injection-0.9.1}/injection/common/invertible.py +6 -8
- {python_injection-0.8.5 → python_injection-0.9.1}/injection/common/lazy.py +9 -14
- {python_injection-0.8.5 → python_injection-0.9.1}/injection/common/tools/threading.py +4 -4
- python_injection-0.9.1/injection/common/tools/type.py +75 -0
- {python_injection-0.8.5 → python_injection-0.9.1}/injection/core/module.py +150 -110
- {python_injection-0.8.5 → python_injection-0.9.1}/injection/exceptions.py +4 -6
- {python_injection-0.8.5 → python_injection-0.9.1}/injection/integrations/blacksheep.py +5 -7
- python_injection-0.9.1/injection/testing/__init__.py +38 -0
- python_injection-0.9.1/injection/testing/__init__.pyi +22 -0
- {python_injection-0.8.5 → python_injection-0.9.1}/pyproject.toml +4 -3
- python_injection-0.8.5/injection/__init__.py +0 -28
- python_injection-0.8.5/injection/common/tools/type.py +0 -48
- {python_injection-0.8.5 → python_injection-0.9.1}/injection/common/__init__.py +0 -0
- {python_injection-0.8.5 → python_injection-0.9.1}/injection/common/tools/__init__.py +0 -0
- {python_injection-0.8.5 → python_injection-0.9.1}/injection/core/__init__.py +0 -0
- {python_injection-0.8.5 → python_injection-0.9.1}/injection/integrations/__init__.py +0 -0
- {python_injection-0.8.5 → python_injection-0.9.1}/injection/py.typed +0 -0
- {python_injection-0.8.5 → python_injection-0.9.1}/injection/utils.py +0 -0
|
@@ -1,23 +1,21 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: python-injection
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.9.1
|
|
4
4
|
Summary: Fast and easy dependency injection framework.
|
|
5
5
|
Home-page: https://github.com/100nm/python-injection
|
|
6
6
|
License: MIT
|
|
7
7
|
Keywords: dependencies,inject,injection
|
|
8
8
|
Author: remimd
|
|
9
|
-
Requires-Python: >=3.
|
|
9
|
+
Requires-Python: >=3.12,<4
|
|
10
10
|
Classifier: License :: OSI Approved :: MIT License
|
|
11
11
|
Classifier: Programming Language :: Python :: 3
|
|
12
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
14
12
|
Classifier: Programming Language :: Python :: 3.12
|
|
15
13
|
Project-URL: Repository, https://github.com/100nm/python-injection
|
|
16
14
|
Description-Content-Type: text/markdown
|
|
17
15
|
|
|
18
16
|
# Basic usage
|
|
19
17
|
|
|
20
|
-
##
|
|
18
|
+
## Register an injectable
|
|
21
19
|
|
|
22
20
|
> **Note**: If the class needs dependencies, these will be resolved when the instance is retrieved.
|
|
23
21
|
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from .core import Injectable, Module
|
|
2
|
+
from .core import Mode as InjectableMode
|
|
3
|
+
from .core import Priority as ModulePriority
|
|
4
|
+
|
|
5
|
+
__all__ = (
|
|
6
|
+
"Injectable",
|
|
7
|
+
"InjectableMode",
|
|
8
|
+
"Module",
|
|
9
|
+
"ModulePriority",
|
|
10
|
+
"get_instance",
|
|
11
|
+
"get_lazy_instance",
|
|
12
|
+
"inject",
|
|
13
|
+
"injectable",
|
|
14
|
+
"set_constant",
|
|
15
|
+
"should_be_injectable",
|
|
16
|
+
"singleton",
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
_module = Module.default()
|
|
20
|
+
|
|
21
|
+
get_instance = _module.get_instance
|
|
22
|
+
get_lazy_instance = _module.get_lazy_instance
|
|
23
|
+
inject = _module.inject
|
|
24
|
+
injectable = _module.injectable
|
|
25
|
+
set_constant = _module.set_constant
|
|
26
|
+
should_be_injectable = _module.should_be_injectable
|
|
27
|
+
singleton = _module.singleton
|
|
28
|
+
|
|
29
|
+
del _module
|
|
@@ -1,33 +1,34 @@
|
|
|
1
1
|
from abc import abstractmethod
|
|
2
|
-
from collections.abc import Callable
|
|
2
|
+
from collections.abc import Callable
|
|
3
3
|
from contextlib import ContextDecorator
|
|
4
|
-
from enum import
|
|
4
|
+
from enum import StrEnum
|
|
5
5
|
from types import UnionType
|
|
6
6
|
from typing import (
|
|
7
7
|
Any,
|
|
8
8
|
ContextManager,
|
|
9
|
-
Final,
|
|
10
|
-
Literal,
|
|
11
9
|
Protocol,
|
|
12
|
-
|
|
10
|
+
Self,
|
|
13
11
|
final,
|
|
14
12
|
runtime_checkable,
|
|
15
13
|
)
|
|
16
14
|
|
|
17
15
|
from .common.invertible import Invertible
|
|
16
|
+
from .common.tools.type import TypeInfo
|
|
17
|
+
from .core import InjectableFactory
|
|
18
|
+
from .core import ModeStr as InjectableModeStr
|
|
19
|
+
from .core import PriorityStr as ModulePriorityStr
|
|
18
20
|
|
|
19
|
-
|
|
20
|
-
_T_co = TypeVar("_T_co", covariant=True)
|
|
21
|
+
_module: Module = ...
|
|
21
22
|
|
|
22
|
-
|
|
23
|
+
get_instance = _module.get_instance
|
|
24
|
+
get_lazy_instance = _module.get_lazy_instance
|
|
25
|
+
inject = _module.inject
|
|
26
|
+
injectable = _module.injectable
|
|
27
|
+
set_constant = _module.set_constant
|
|
28
|
+
should_be_injectable = _module.should_be_injectable
|
|
29
|
+
singleton = _module.singleton
|
|
23
30
|
|
|
24
|
-
|
|
25
|
-
get_lazy_instance = default_module.get_lazy_instance
|
|
26
|
-
inject = default_module.inject
|
|
27
|
-
injectable = default_module.injectable
|
|
28
|
-
set_constant = default_module.set_constant
|
|
29
|
-
should_be_injectable = default_module.should_be_injectable
|
|
30
|
-
singleton = default_module.singleton
|
|
31
|
+
del _module
|
|
31
32
|
|
|
32
33
|
@final
|
|
33
34
|
class Module:
|
|
@@ -41,6 +42,8 @@ class Module:
|
|
|
41
42
|
|
|
42
43
|
def __init__(self, name: str = ...): ...
|
|
43
44
|
def __contains__(self, cls: type | UnionType, /) -> bool: ...
|
|
45
|
+
@property
|
|
46
|
+
def is_locked(self) -> bool: ...
|
|
44
47
|
def inject(self, wrapped: Callable[..., Any] = ..., /):
|
|
45
48
|
"""
|
|
46
49
|
Decorator applicable to a class or function. Inject function dependencies using
|
|
@@ -48,15 +51,15 @@ class Module:
|
|
|
48
51
|
will be those of the `__init__` method.
|
|
49
52
|
"""
|
|
50
53
|
|
|
51
|
-
def injectable(
|
|
54
|
+
def injectable[T](
|
|
52
55
|
self,
|
|
53
|
-
wrapped: Callable[...,
|
|
56
|
+
wrapped: Callable[..., T] = ...,
|
|
54
57
|
/,
|
|
55
58
|
*,
|
|
56
|
-
cls:
|
|
59
|
+
cls: InjectableFactory[T] = ...,
|
|
57
60
|
inject: bool = ...,
|
|
58
|
-
on:
|
|
59
|
-
mode: InjectableMode |
|
|
61
|
+
on: TypeInfo[T] = ...,
|
|
62
|
+
mode: InjectableMode | InjectableModeStr = ...,
|
|
60
63
|
):
|
|
61
64
|
"""
|
|
62
65
|
Decorator applicable to a class or function. It is used to indicate how the
|
|
@@ -64,14 +67,14 @@ class Module:
|
|
|
64
67
|
injected each time.
|
|
65
68
|
"""
|
|
66
69
|
|
|
67
|
-
def singleton(
|
|
70
|
+
def singleton[T](
|
|
68
71
|
self,
|
|
69
|
-
wrapped: Callable[...,
|
|
72
|
+
wrapped: Callable[..., T] = ...,
|
|
70
73
|
/,
|
|
71
74
|
*,
|
|
72
75
|
inject: bool = ...,
|
|
73
|
-
on:
|
|
74
|
-
mode: InjectableMode |
|
|
76
|
+
on: TypeInfo[T] = ...,
|
|
77
|
+
mode: InjectableMode | InjectableModeStr = ...,
|
|
75
78
|
):
|
|
76
79
|
"""
|
|
77
80
|
Decorator applicable to a class or function. It is used to indicate how the
|
|
@@ -86,37 +89,37 @@ class Module:
|
|
|
86
89
|
registered.
|
|
87
90
|
"""
|
|
88
91
|
|
|
89
|
-
def set_constant(
|
|
92
|
+
def set_constant[T](
|
|
90
93
|
self,
|
|
91
|
-
instance:
|
|
92
|
-
on:
|
|
94
|
+
instance: T,
|
|
95
|
+
on: TypeInfo[T] = ...,
|
|
93
96
|
*,
|
|
94
|
-
mode: InjectableMode |
|
|
95
|
-
) ->
|
|
97
|
+
mode: InjectableMode | InjectableModeStr = ...,
|
|
98
|
+
) -> T:
|
|
96
99
|
"""
|
|
97
100
|
Function for registering a specific instance to be injected. This is useful for
|
|
98
101
|
registering global variables. The difference with the singleton decorator is
|
|
99
102
|
that no dependencies are resolved, so the module doesn't need to be locked.
|
|
100
103
|
"""
|
|
101
104
|
|
|
102
|
-
def resolve(self, cls: type[
|
|
105
|
+
def resolve[T](self, cls: type[T]) -> T:
|
|
103
106
|
"""
|
|
104
107
|
Function used to retrieve an instance associated with the type passed in
|
|
105
108
|
parameter or an exception will be raised.
|
|
106
109
|
"""
|
|
107
110
|
|
|
108
|
-
def get_instance(self, cls: type[
|
|
111
|
+
def get_instance[T](self, cls: type[T]) -> T | None:
|
|
109
112
|
"""
|
|
110
113
|
Function used to retrieve an instance associated with the type passed in
|
|
111
114
|
parameter or return `None`.
|
|
112
115
|
"""
|
|
113
116
|
|
|
114
|
-
def get_lazy_instance(
|
|
117
|
+
def get_lazy_instance[T](
|
|
115
118
|
self,
|
|
116
|
-
cls: type[
|
|
119
|
+
cls: type[T],
|
|
117
120
|
*,
|
|
118
121
|
cache: bool = ...,
|
|
119
|
-
) -> Invertible[
|
|
122
|
+
) -> Invertible[T | None]:
|
|
120
123
|
"""
|
|
121
124
|
Function used to retrieve an instance associated with the type passed in
|
|
122
125
|
parameter or `None`. Return a `Invertible` object. To access the instance
|
|
@@ -126,19 +129,24 @@ class Module:
|
|
|
126
129
|
Example: instance = ~lazy_instance
|
|
127
130
|
"""
|
|
128
131
|
|
|
132
|
+
def init_modules(self, *modules: Module) -> Self:
|
|
133
|
+
"""
|
|
134
|
+
Function to clean modules in use and to use those passed as parameters.
|
|
135
|
+
"""
|
|
136
|
+
|
|
129
137
|
def use(
|
|
130
138
|
self,
|
|
131
139
|
module: Module,
|
|
132
140
|
*,
|
|
133
|
-
priority: ModulePriority |
|
|
134
|
-
):
|
|
141
|
+
priority: ModulePriority | ModulePriorityStr = ...,
|
|
142
|
+
) -> Self:
|
|
135
143
|
"""
|
|
136
144
|
Function for using another module. Using another module replaces the module's
|
|
137
145
|
dependencies with those of the module used. If the dependency is not found, it
|
|
138
146
|
will be searched for in the module's dependency container.
|
|
139
147
|
"""
|
|
140
148
|
|
|
141
|
-
def stop_using(self, module: Module):
|
|
149
|
+
def stop_using(self, module: Module) -> Self:
|
|
142
150
|
"""
|
|
143
151
|
Function to remove a module in use.
|
|
144
152
|
"""
|
|
@@ -147,7 +155,7 @@ class Module:
|
|
|
147
155
|
self,
|
|
148
156
|
module: Module,
|
|
149
157
|
*,
|
|
150
|
-
priority: ModulePriority |
|
|
158
|
+
priority: ModulePriority | ModulePriorityStr = ...,
|
|
151
159
|
) -> ContextManager | ContextDecorator:
|
|
152
160
|
"""
|
|
153
161
|
Context manager or decorator for temporary use of a module.
|
|
@@ -156,8 +164,8 @@ class Module:
|
|
|
156
164
|
def change_priority(
|
|
157
165
|
self,
|
|
158
166
|
module: Module,
|
|
159
|
-
priority: ModulePriority |
|
|
160
|
-
):
|
|
167
|
+
priority: ModulePriority | ModulePriorityStr,
|
|
168
|
+
) -> Self:
|
|
161
169
|
"""
|
|
162
170
|
Function for changing the priority of a module in use.
|
|
163
171
|
There are two priority values:
|
|
@@ -166,27 +174,38 @@ class Module:
|
|
|
166
174
|
* **HIGH**: The module concerned becomes the most important of the modules used.
|
|
167
175
|
"""
|
|
168
176
|
|
|
169
|
-
def unlock(self):
|
|
177
|
+
def unlock(self) -> Self:
|
|
170
178
|
"""
|
|
171
179
|
Function to unlock the module by deleting cached instances of singletons.
|
|
172
180
|
"""
|
|
173
181
|
|
|
182
|
+
@classmethod
|
|
183
|
+
def from_name(cls, name: str) -> Self:
|
|
184
|
+
"""
|
|
185
|
+
Class method for getting or creating a module by name.
|
|
186
|
+
"""
|
|
187
|
+
|
|
188
|
+
@classmethod
|
|
189
|
+
def default(cls) -> Self:
|
|
190
|
+
"""
|
|
191
|
+
Class method for getting the default module.
|
|
192
|
+
"""
|
|
193
|
+
|
|
174
194
|
@final
|
|
175
|
-
class ModulePriority(
|
|
195
|
+
class ModulePriority(StrEnum):
|
|
176
196
|
LOW = ...
|
|
177
197
|
HIGH = ...
|
|
178
198
|
|
|
179
199
|
@runtime_checkable
|
|
180
|
-
class Injectable(Protocol
|
|
181
|
-
def __init__(self, factory: Callable[[], _T_co] = ..., /): ...
|
|
200
|
+
class Injectable[T](Protocol):
|
|
182
201
|
@property
|
|
183
202
|
def is_locked(self) -> bool: ...
|
|
184
203
|
def unlock(self): ...
|
|
185
204
|
@abstractmethod
|
|
186
|
-
def get_instance(self) ->
|
|
205
|
+
def get_instance(self) -> T: ...
|
|
187
206
|
|
|
188
207
|
@final
|
|
189
|
-
class InjectableMode(
|
|
208
|
+
class InjectableMode(StrEnum):
|
|
190
209
|
FALLBACK = ...
|
|
191
210
|
NORMAL = ...
|
|
192
211
|
OVERRIDE = ...
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from abc import ABC, abstractmethod
|
|
2
2
|
from contextlib import ExitStack, contextmanager, suppress
|
|
3
3
|
from dataclasses import dataclass, field
|
|
4
|
-
from typing import ContextManager
|
|
4
|
+
from typing import ContextManager, Self
|
|
5
5
|
from weakref import WeakSet
|
|
6
6
|
|
|
7
7
|
__all__ = ("Event", "EventChannel", "EventListener")
|
|
@@ -36,11 +36,11 @@ class EventChannel:
|
|
|
36
36
|
|
|
37
37
|
yield
|
|
38
38
|
|
|
39
|
-
def add_listener(self, listener: EventListener):
|
|
39
|
+
def add_listener(self, listener: EventListener) -> Self:
|
|
40
40
|
self.__listeners.add(listener)
|
|
41
41
|
return self
|
|
42
42
|
|
|
43
|
-
def remove_listener(self, listener: EventListener):
|
|
43
|
+
def remove_listener(self, listener: EventListener) -> Self:
|
|
44
44
|
with suppress(KeyError):
|
|
45
45
|
self.__listeners.remove(listener)
|
|
46
46
|
|
|
@@ -1,23 +1,21 @@
|
|
|
1
1
|
from abc import abstractmethod
|
|
2
2
|
from collections.abc import Callable
|
|
3
3
|
from dataclasses import dataclass
|
|
4
|
-
from typing import Protocol,
|
|
4
|
+
from typing import Protocol, runtime_checkable
|
|
5
5
|
|
|
6
6
|
__all__ = ("Invertible", "SimpleInvertible")
|
|
7
7
|
|
|
8
|
-
_T_co = TypeVar("_T_co", covariant=True)
|
|
9
|
-
|
|
10
8
|
|
|
11
9
|
@runtime_checkable
|
|
12
|
-
class Invertible(Protocol
|
|
10
|
+
class Invertible[T](Protocol):
|
|
13
11
|
@abstractmethod
|
|
14
|
-
def __invert__(self) ->
|
|
12
|
+
def __invert__(self) -> T:
|
|
15
13
|
raise NotImplementedError
|
|
16
14
|
|
|
17
15
|
|
|
18
16
|
@dataclass(repr=False, eq=False, frozen=True, slots=True)
|
|
19
|
-
class SimpleInvertible(Invertible[
|
|
20
|
-
callable: Callable[[],
|
|
17
|
+
class SimpleInvertible[T](Invertible[T]):
|
|
18
|
+
callable: Callable[[], T]
|
|
21
19
|
|
|
22
|
-
def __invert__(self) ->
|
|
20
|
+
def __invert__(self) -> T:
|
|
23
21
|
return self.callable()
|
|
@@ -1,31 +1,26 @@
|
|
|
1
1
|
from collections.abc import Callable, Iterator, Mapping
|
|
2
2
|
from types import MappingProxyType
|
|
3
|
-
from typing import TypeVar
|
|
4
3
|
|
|
5
4
|
from injection.common.invertible import Invertible
|
|
6
5
|
|
|
7
6
|
__all__ = ("Lazy", "LazyMapping")
|
|
8
7
|
|
|
9
|
-
_T = TypeVar("_T")
|
|
10
|
-
_K = TypeVar("_K")
|
|
11
|
-
_V = TypeVar("_V")
|
|
12
8
|
|
|
13
|
-
|
|
14
|
-
class Lazy(Invertible[_T]):
|
|
9
|
+
class Lazy[T](Invertible[T]):
|
|
15
10
|
__slots__ = ("__cache", "__is_set")
|
|
16
11
|
|
|
17
|
-
def __init__(self, factory: Callable[[],
|
|
12
|
+
def __init__(self, factory: Callable[[], T]):
|
|
18
13
|
self.__setup_cache(factory)
|
|
19
14
|
|
|
20
|
-
def __invert__(self) ->
|
|
15
|
+
def __invert__(self) -> T:
|
|
21
16
|
return next(self.__cache)
|
|
22
17
|
|
|
23
18
|
@property
|
|
24
19
|
def is_set(self) -> bool:
|
|
25
20
|
return self.__is_set
|
|
26
21
|
|
|
27
|
-
def __setup_cache(self, factory: Callable[[],
|
|
28
|
-
def cache_generator() -> Iterator[
|
|
22
|
+
def __setup_cache(self, factory: Callable[[], T]):
|
|
23
|
+
def cache_generator() -> Iterator[T]:
|
|
29
24
|
nonlocal factory
|
|
30
25
|
cached = factory()
|
|
31
26
|
self.__is_set = True
|
|
@@ -38,16 +33,16 @@ class Lazy(Invertible[_T]):
|
|
|
38
33
|
self.__is_set = False
|
|
39
34
|
|
|
40
35
|
|
|
41
|
-
class LazyMapping(Mapping[
|
|
36
|
+
class LazyMapping[K, V](Mapping[K, V]):
|
|
42
37
|
__slots__ = ("__lazy",)
|
|
43
38
|
|
|
44
|
-
def __init__(self, iterator: Iterator[tuple[
|
|
39
|
+
def __init__(self, iterator: Iterator[tuple[K, V]]):
|
|
45
40
|
self.__lazy = Lazy(lambda: MappingProxyType(dict(iterator)))
|
|
46
41
|
|
|
47
|
-
def __getitem__(self, key:
|
|
42
|
+
def __getitem__(self, key: K, /) -> V:
|
|
48
43
|
return (~self.__lazy)[key]
|
|
49
44
|
|
|
50
|
-
def __iter__(self) -> Iterator[
|
|
45
|
+
def __iter__(self) -> Iterator[K]:
|
|
51
46
|
yield from ~self.__lazy
|
|
52
47
|
|
|
53
48
|
def __len__(self) -> int:
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
from collections.abc import Callable, Iterable, Iterator
|
|
2
|
+
from inspect import get_annotations, isfunction
|
|
3
|
+
from types import UnionType
|
|
4
|
+
from typing import (
|
|
5
|
+
Annotated,
|
|
6
|
+
Any,
|
|
7
|
+
NamedTuple,
|
|
8
|
+
Self,
|
|
9
|
+
Union,
|
|
10
|
+
get_args,
|
|
11
|
+
get_origin,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
__all__ = ("TypeInfo", "TypeReport", "analyze_types", "get_return_types")
|
|
15
|
+
|
|
16
|
+
type TypeInfo[T] = type[T] | Callable[..., T] | Iterable[TypeInfo[T]] | UnionType
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class TypeReport[T](NamedTuple):
|
|
20
|
+
origin: type[T]
|
|
21
|
+
args: tuple[Any, ...]
|
|
22
|
+
|
|
23
|
+
@property
|
|
24
|
+
def type(self) -> type[T]:
|
|
25
|
+
origin = self.origin
|
|
26
|
+
|
|
27
|
+
if args := self.args:
|
|
28
|
+
return origin[*args]
|
|
29
|
+
|
|
30
|
+
return origin
|
|
31
|
+
|
|
32
|
+
@property
|
|
33
|
+
def no_args(self) -> Self:
|
|
34
|
+
if self.args:
|
|
35
|
+
return type(self)(self.origin, ())
|
|
36
|
+
|
|
37
|
+
return self
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def analyze_types(*types: type | Any) -> Iterator[TypeReport[Any]]:
|
|
41
|
+
for tp in types:
|
|
42
|
+
if tp is None:
|
|
43
|
+
continue
|
|
44
|
+
|
|
45
|
+
origin = get_origin(tp)
|
|
46
|
+
|
|
47
|
+
if origin is Union or isinstance(tp, UnionType):
|
|
48
|
+
inner_types = get_args(tp)
|
|
49
|
+
|
|
50
|
+
elif origin is Annotated:
|
|
51
|
+
inner_types = get_args(tp)[:1]
|
|
52
|
+
|
|
53
|
+
else:
|
|
54
|
+
yield TypeReport(origin or tp, get_args(tp))
|
|
55
|
+
continue
|
|
56
|
+
|
|
57
|
+
yield from analyze_types(*inner_types)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def get_return_types(*args: TypeInfo[Any]) -> Iterator[type | UnionType]:
|
|
61
|
+
for arg in args:
|
|
62
|
+
if isinstance(arg, Iterable) and not isinstance(
|
|
63
|
+
get_origin(arg) or arg,
|
|
64
|
+
type | str,
|
|
65
|
+
):
|
|
66
|
+
inner_args = arg
|
|
67
|
+
|
|
68
|
+
elif isfunction(arg):
|
|
69
|
+
inner_args = (get_annotations(arg, eval_str=True).get("return"),)
|
|
70
|
+
|
|
71
|
+
else:
|
|
72
|
+
yield arg
|
|
73
|
+
continue
|
|
74
|
+
|
|
75
|
+
yield from get_return_types(*inner_args)
|