type-analyzer 0.1.3__tar.gz → 0.2.0__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.
@@ -0,0 +1,142 @@
1
+ Metadata-Version: 2.5
2
+ Name: type-analyzer
3
+ Version: 0.2.0
4
+ Summary: Functions for introspecting Python type hints.
5
+ Project-URL: Repository, https://github.com/100nm/type-analyzer
6
+ Author: remimd
7
+ License-Expression: MIT
8
+ License-File: LICENSE
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Natural Language :: English
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3 :: Only
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Programming Language :: Python :: 3.14
19
+ Classifier: Programming Language :: Python :: 3.15
20
+ Classifier: Topic :: Software Development :: Libraries
21
+ Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
22
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
+ Classifier: Typing :: Typed
24
+ Requires-Python: <3.16,>=3.12
25
+ Description-Content-Type: text/markdown
26
+
27
+ # type-analyzer
28
+
29
+ [![PyPI - Version](https://shieldcn.dev/pypi/v/type-analyzer.svg?color=3775A9&size=xs&variant=secondary)](https://pypi.org/project/type-analyzer)
30
+ [![PyPI - Downloads](https://shieldcn.dev/pypi/dm/type-analyzer.svg?color=3775A9&size=xs&variant=secondary)](https://pypistats.org/packages/type-analyzer)
31
+ [![GitHub Stars](https://shieldcn.dev/github/stars/100nm/type-analyzer.svg?size=xs&variant=secondary)](https://github.com/100nm/type-analyzer/stargazers)
32
+ [![CI](https://shieldcn.dev/github/ci/100nm/type-analyzer.svg?size=xs&variant=secondary&workflow=ci.yml)](https://github.com/100nm/type-analyzer/actions/workflows/ci.yml)
33
+ [![Ruff](https://shieldcn.dev/badge/code_style-Ruff-261230.svg?logo=ruff&size=xs&variant=secondary)](https://github.com/astral-sh/ruff)
34
+
35
+ Functions for introspecting Python type hints.
36
+
37
+ ## Installation
38
+
39
+ ⚠️ _Requires Python 3.12 or higher_
40
+
41
+ ```bash
42
+ pip install type-analyzer
43
+ ```
44
+
45
+ ## Usage
46
+
47
+ ### `matching_types`
48
+
49
+ `matching_types` returns every type a type hint matches, without duplicates. Unions
50
+ are unpacked into their members, and `Annotated` metadata is removed:
51
+
52
+ ```python
53
+ from typing import Annotated
54
+
55
+ from type_analyzer import matching_types
56
+
57
+ matching_types(str | int)
58
+ # => (str, int)
59
+
60
+ matching_types(Annotated[str, "metadata"] | None)
61
+ # => (str, NoneType)
62
+
63
+ matching_types(list[Annotated[int, "metadata"]])
64
+ # => (list[int],)
65
+ ```
66
+
67
+ ### Options
68
+
69
+ `MatchingTypesConfig` adds more types to the result. Every option is disabled by
70
+ default:
71
+
72
+ | Option | Effect |
73
+ |-------------------------|----------------------------------------------------------|
74
+ | `ignore_none` | Leaves out `None`. |
75
+ | `with_bases` | Adds the base classes, with their type arguments. |
76
+ | `with_origin` | Adds the origin of generic types (`list[str]` → `list`). |
77
+ | `with_type_alias_value` | Adds the value of type aliases. |
78
+
79
+ ```python
80
+ from type_analyzer import MatchingTypesConfig, matching_types
81
+
82
+ # ----- ignore_none -----
83
+
84
+ config = MatchingTypesConfig(ignore_none=True)
85
+ matching_types(str | None, config)
86
+ # => (str,)
87
+
88
+ # ----- with_bases -----
89
+
90
+
91
+ class A[T]: ...
92
+
93
+
94
+ class B[T]: ...
95
+
96
+
97
+ class C[T1, T2](A[T1], B[T2]): ...
98
+
99
+
100
+ config = MatchingTypesConfig(with_bases=True)
101
+ matching_types(C[str, int], config)
102
+ # => (C[str, int], A[str], B[int])
103
+
104
+ # ----- with_origin -----
105
+
106
+ config = MatchingTypesConfig(with_origin=True)
107
+ matching_types(list[str], config)
108
+ # => (list[str], list)
109
+
110
+ # ----- with_type_alias_value -----
111
+
112
+ type StringOr[T] = str | T
113
+
114
+ config = MatchingTypesConfig(with_type_alias_value=True)
115
+ matching_types(StringOr[int], config)
116
+ # => (StringOr[int], str, int)
117
+ ```
118
+
119
+ Options can be combined: `MatchingTypesConfig(with_bases=True, with_origin=True)`.
120
+
121
+ ### `iter_matching_types`
122
+
123
+ `iter_matching_types` is the lazy counterpart of `matching_types`: it yields the
124
+ types one by one, and keeps the duplicates.
125
+
126
+ ```python
127
+ from type_analyzer import MatchingTypesConfig, iter_matching_types
128
+
129
+
130
+ class Left: ...
131
+
132
+
133
+ class Right: ...
134
+
135
+
136
+ class Both(Left, Right): ...
137
+
138
+
139
+ config = MatchingTypesConfig(with_bases=True)
140
+ list(iter_matching_types(Both, config))
141
+ # => [Both, Left, object, Right, object]
142
+ ```
@@ -0,0 +1,116 @@
1
+ # type-analyzer
2
+
3
+ [![PyPI - Version](https://shieldcn.dev/pypi/v/type-analyzer.svg?color=3775A9&size=xs&variant=secondary)](https://pypi.org/project/type-analyzer)
4
+ [![PyPI - Downloads](https://shieldcn.dev/pypi/dm/type-analyzer.svg?color=3775A9&size=xs&variant=secondary)](https://pypistats.org/packages/type-analyzer)
5
+ [![GitHub Stars](https://shieldcn.dev/github/stars/100nm/type-analyzer.svg?size=xs&variant=secondary)](https://github.com/100nm/type-analyzer/stargazers)
6
+ [![CI](https://shieldcn.dev/github/ci/100nm/type-analyzer.svg?size=xs&variant=secondary&workflow=ci.yml)](https://github.com/100nm/type-analyzer/actions/workflows/ci.yml)
7
+ [![Ruff](https://shieldcn.dev/badge/code_style-Ruff-261230.svg?logo=ruff&size=xs&variant=secondary)](https://github.com/astral-sh/ruff)
8
+
9
+ Functions for introspecting Python type hints.
10
+
11
+ ## Installation
12
+
13
+ ⚠️ _Requires Python 3.12 or higher_
14
+
15
+ ```bash
16
+ pip install type-analyzer
17
+ ```
18
+
19
+ ## Usage
20
+
21
+ ### `matching_types`
22
+
23
+ `matching_types` returns every type a type hint matches, without duplicates. Unions
24
+ are unpacked into their members, and `Annotated` metadata is removed:
25
+
26
+ ```python
27
+ from typing import Annotated
28
+
29
+ from type_analyzer import matching_types
30
+
31
+ matching_types(str | int)
32
+ # => (str, int)
33
+
34
+ matching_types(Annotated[str, "metadata"] | None)
35
+ # => (str, NoneType)
36
+
37
+ matching_types(list[Annotated[int, "metadata"]])
38
+ # => (list[int],)
39
+ ```
40
+
41
+ ### Options
42
+
43
+ `MatchingTypesConfig` adds more types to the result. Every option is disabled by
44
+ default:
45
+
46
+ | Option | Effect |
47
+ |-------------------------|----------------------------------------------------------|
48
+ | `ignore_none` | Leaves out `None`. |
49
+ | `with_bases` | Adds the base classes, with their type arguments. |
50
+ | `with_origin` | Adds the origin of generic types (`list[str]` → `list`). |
51
+ | `with_type_alias_value` | Adds the value of type aliases. |
52
+
53
+ ```python
54
+ from type_analyzer import MatchingTypesConfig, matching_types
55
+
56
+ # ----- ignore_none -----
57
+
58
+ config = MatchingTypesConfig(ignore_none=True)
59
+ matching_types(str | None, config)
60
+ # => (str,)
61
+
62
+ # ----- with_bases -----
63
+
64
+
65
+ class A[T]: ...
66
+
67
+
68
+ class B[T]: ...
69
+
70
+
71
+ class C[T1, T2](A[T1], B[T2]): ...
72
+
73
+
74
+ config = MatchingTypesConfig(with_bases=True)
75
+ matching_types(C[str, int], config)
76
+ # => (C[str, int], A[str], B[int])
77
+
78
+ # ----- with_origin -----
79
+
80
+ config = MatchingTypesConfig(with_origin=True)
81
+ matching_types(list[str], config)
82
+ # => (list[str], list)
83
+
84
+ # ----- with_type_alias_value -----
85
+
86
+ type StringOr[T] = str | T
87
+
88
+ config = MatchingTypesConfig(with_type_alias_value=True)
89
+ matching_types(StringOr[int], config)
90
+ # => (StringOr[int], str, int)
91
+ ```
92
+
93
+ Options can be combined: `MatchingTypesConfig(with_bases=True, with_origin=True)`.
94
+
95
+ ### `iter_matching_types`
96
+
97
+ `iter_matching_types` is the lazy counterpart of `matching_types`: it yields the
98
+ types one by one, and keeps the duplicates.
99
+
100
+ ```python
101
+ from type_analyzer import MatchingTypesConfig, iter_matching_types
102
+
103
+
104
+ class Left: ...
105
+
106
+
107
+ class Right: ...
108
+
109
+
110
+ class Both(Left, Right): ...
111
+
112
+
113
+ config = MatchingTypesConfig(with_bases=True)
114
+ list(iter_matching_types(Both, config))
115
+ # => [Both, Left, object, Right, object]
116
+ ```
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "type-analyzer"
3
- version = "0.1.3"
3
+ version = "0.2.0"
4
4
  description = "Functions for introspecting Python type hints."
5
5
  license = "MIT"
6
6
  license-files = ["LICENSE"]
@@ -19,6 +19,7 @@ classifiers = [
19
19
  "Programming Language :: Python :: 3.12",
20
20
  "Programming Language :: Python :: 3.13",
21
21
  "Programming Language :: Python :: 3.14",
22
+ "Programming Language :: Python :: 3.15",
22
23
  "Operating System :: OS Independent",
23
24
  "Intended Audience :: Developers",
24
25
  "Natural Language :: English",
@@ -81,7 +82,7 @@ skip-magic-trailing-comma = false
81
82
  line-ending = "auto"
82
83
 
83
84
  [tool.ruff.lint]
84
- extend-select = ["I", "N"]
85
+ extend-select = ["F", "I", "N"]
85
86
  fixable = ["ALL"]
86
87
 
87
88
  [tool.uv]
@@ -0,0 +1,154 @@
1
+ from collections.abc import Iterator, Mapping, Sequence
2
+ from dataclasses import dataclass, field
3
+ from types import NoneType, UnionType, get_original_bases
4
+ from typing import (
5
+ Annotated,
6
+ Any,
7
+ Generic,
8
+ Self,
9
+ TypeAliasType,
10
+ TypeVar,
11
+ Union,
12
+ get_args,
13
+ get_origin,
14
+ )
15
+
16
+
17
+ @dataclass(repr=False, eq=False, frozen=True, kw_only=True, slots=True)
18
+ class MatchingTypesConfig:
19
+ ignore_none: bool = field(default=False)
20
+ with_bases: bool = field(default=False)
21
+ with_origin: bool = field(default=False)
22
+ with_type_alias_value: bool = field(default=False)
23
+
24
+
25
+ @dataclass(repr=False, eq=False, frozen=True, slots=True)
26
+ class _TypeHint:
27
+ value: Any
28
+ origin: Any
29
+
30
+ @property
31
+ def args(self) -> tuple[Any, ...]:
32
+ return get_args(self.value)
33
+
34
+ @property
35
+ def generics(self) -> Mapping[TypeVar, Any]:
36
+ parameters = getattr(self.origin, "__parameters__", ())
37
+ return dict(zip(parameters, self.args))
38
+
39
+ @property
40
+ def is_none(self) -> bool:
41
+ return self.value in (None, NoneType)
42
+
43
+ @property
44
+ def is_union(self) -> bool:
45
+ return self.origin is Union or isinstance(self.value, UnionType)
46
+
47
+ @property
48
+ def target(self) -> Any:
49
+ return self.value if self.origin is None else self.origin
50
+
51
+ def apply_generics(self, generics: Mapping[TypeVar, Any]) -> Self:
52
+ if isinstance(self.value, TypeVar):
53
+ return self.from_value(generics.get(self.value, self.value))
54
+
55
+ if self.origin is None:
56
+ return self
57
+
58
+ if self.origin is Annotated:
59
+ return self.from_value(self.args[0]).apply_generics(generics)
60
+
61
+ args = tuple(
62
+ self.from_value(arg).apply_generics(generics).value for arg in self.args
63
+ )
64
+
65
+ if self.is_union:
66
+ return self.from_value(Union[*args])
67
+
68
+ return self.from_value(self.origin[*args])
69
+
70
+ @classmethod
71
+ def from_value(cls, value: Any) -> Self:
72
+ return cls(value, get_origin(value))
73
+
74
+
75
+ _empty_config = MatchingTypesConfig()
76
+
77
+
78
+ def iter_matching_types(
79
+ type_hint: Any,
80
+ /,
81
+ config: MatchingTypesConfig | None = None,
82
+ ) -> Iterator[Any]:
83
+ config = config or _empty_config
84
+ return _iter_matching_types((type_hint,), config, {})
85
+
86
+
87
+ def matching_types(
88
+ type_hint: Any,
89
+ /,
90
+ config: MatchingTypesConfig | None = None,
91
+ ) -> tuple[Any, ...]:
92
+ return tuple(dict.fromkeys(iter_matching_types(type_hint, config)))
93
+
94
+
95
+ def _iter_bases(type_hint: _TypeHint, config: MatchingTypesConfig) -> Iterator[Any]:
96
+ try:
97
+ bases = get_original_bases(type_hint.target)
98
+ except TypeError:
99
+ return
100
+
101
+ yield from _iter_matching_types(bases, config, type_hint.generics)
102
+
103
+
104
+ def _iter_matching_types(
105
+ type_hints: Sequence[Any],
106
+ config: MatchingTypesConfig,
107
+ generics: Mapping[TypeVar, Any],
108
+ ) -> Iterator[Any]:
109
+ for value in type_hints:
110
+ type_hint = _TypeHint.from_value(value)
111
+
112
+ if type_hint.origin is Generic:
113
+ continue
114
+
115
+ yield from _iter_type_hint_matching_types(
116
+ type_hint.apply_generics(generics),
117
+ config,
118
+ )
119
+
120
+
121
+ def _iter_type_alias_value(
122
+ type_hint: _TypeHint,
123
+ config: MatchingTypesConfig,
124
+ ) -> Iterator[Any]:
125
+ type_alias = type_hint.target
126
+
127
+ if not isinstance(type_alias, TypeAliasType):
128
+ return
129
+
130
+ values = (type_alias.__value__,)
131
+ yield from _iter_matching_types(values, config, type_hint.generics)
132
+
133
+
134
+ def _iter_type_hint_matching_types(
135
+ type_hint: _TypeHint,
136
+ config: MatchingTypesConfig,
137
+ ) -> Iterator[Any]:
138
+ if config.ignore_none and type_hint.is_none:
139
+ return
140
+
141
+ if type_hint.is_union:
142
+ yield from _iter_matching_types(type_hint.args, config, {})
143
+ return
144
+
145
+ yield type_hint.value
146
+
147
+ if config.with_origin and type_hint.origin is not None:
148
+ yield type_hint.origin
149
+
150
+ if config.with_bases:
151
+ yield from _iter_bases(type_hint, config)
152
+
153
+ if config.with_type_alias_value:
154
+ yield from _iter_type_alias_value(type_hint, config)
@@ -1,75 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: type-analyzer
3
- Version: 0.1.3
4
- Summary: Functions for introspecting Python type hints.
5
- Project-URL: Repository, https://github.com/100nm/type-analyzer
6
- Author: remimd
7
- License-Expression: MIT
8
- License-File: LICENSE
9
- Classifier: Development Status :: 4 - Beta
10
- Classifier: Intended Audience :: Developers
11
- Classifier: Natural Language :: English
12
- Classifier: Operating System :: OS Independent
13
- Classifier: Programming Language :: Python
14
- Classifier: Programming Language :: Python :: 3
15
- Classifier: Programming Language :: Python :: 3 :: Only
16
- Classifier: Programming Language :: Python :: 3.12
17
- Classifier: Programming Language :: Python :: 3.13
18
- Classifier: Programming Language :: Python :: 3.14
19
- Classifier: Topic :: Software Development :: Libraries
20
- Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
21
- Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
- Classifier: Typing :: Typed
23
- Requires-Python: <3.16,>=3.12
24
- Description-Content-Type: text/markdown
25
-
26
- # type-analyzer
27
-
28
- [![CI](https://github.com/100nm/type-analyzer/actions/workflows/ci.yml/badge.svg)](https://github.com/100nm/type-analyzer)
29
- [![PyPI - Version](https://img.shields.io/pypi/v/type-analyzer.svg?color=blue)](https://pypi.org/project/type-analyzer)
30
- [![PyPI - Downloads](https://img.shields.io/pypi/dm/type-analyzer.svg?color=blue)](https://pypistats.org/packages/type-analyzer)
31
- [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
32
-
33
- ## Installation
34
-
35
- ⚠️ _Requires Python 3.12 or higher_
36
-
37
- ```bash
38
- pip install type-analyzer
39
- ```
40
-
41
- ## Quick start
42
-
43
- ### matching_types
44
-
45
- ```python
46
- from type_analyzer import MatchingTypesConfig, matching_types
47
-
48
- # ----- Union type -----
49
-
50
- matching_types(str | int)
51
- # => (str, int)
52
-
53
- # ----- Generic type alias -----
54
-
55
- type StringOr[T] = str | T
56
-
57
- config = MatchingTypesConfig(with_type_alias_value=True)
58
- matching_types(StringOr[int], config)
59
- # => (StringOr[int], str, int)
60
-
61
- # ----- Generic classes -----
62
-
63
- class A[T]:
64
- ...
65
-
66
- class B[T]:
67
- ...
68
-
69
- class C[T1, T2](A[T1], B[T2]):
70
- ...
71
-
72
- config = MatchingTypesConfig(with_bases=True)
73
- matching_types(C[str, int], config)
74
- # => (C[str, int], A[str], B[int])
75
- ```
@@ -1,50 +0,0 @@
1
- # type-analyzer
2
-
3
- [![CI](https://github.com/100nm/type-analyzer/actions/workflows/ci.yml/badge.svg)](https://github.com/100nm/type-analyzer)
4
- [![PyPI - Version](https://img.shields.io/pypi/v/type-analyzer.svg?color=blue)](https://pypi.org/project/type-analyzer)
5
- [![PyPI - Downloads](https://img.shields.io/pypi/dm/type-analyzer.svg?color=blue)](https://pypistats.org/packages/type-analyzer)
6
- [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
7
-
8
- ## Installation
9
-
10
- ⚠️ _Requires Python 3.12 or higher_
11
-
12
- ```bash
13
- pip install type-analyzer
14
- ```
15
-
16
- ## Quick start
17
-
18
- ### matching_types
19
-
20
- ```python
21
- from type_analyzer import MatchingTypesConfig, matching_types
22
-
23
- # ----- Union type -----
24
-
25
- matching_types(str | int)
26
- # => (str, int)
27
-
28
- # ----- Generic type alias -----
29
-
30
- type StringOr[T] = str | T
31
-
32
- config = MatchingTypesConfig(with_type_alias_value=True)
33
- matching_types(StringOr[int], config)
34
- # => (StringOr[int], str, int)
35
-
36
- # ----- Generic classes -----
37
-
38
- class A[T]:
39
- ...
40
-
41
- class B[T]:
42
- ...
43
-
44
- class C[T1, T2](A[T1], B[T2]):
45
- ...
46
-
47
- config = MatchingTypesConfig(with_bases=True)
48
- matching_types(C[str, int], config)
49
- # => (C[str, int], A[str], B[int])
50
- ```
@@ -1,129 +0,0 @@
1
- from collections.abc import Iterator, Mapping, Sequence
2
- from dataclasses import dataclass, field
3
- from types import NoneType, UnionType, get_original_bases
4
- from typing import (
5
- Annotated,
6
- Any,
7
- Generic,
8
- TypeAliasType,
9
- TypeVar,
10
- Union,
11
- get_args,
12
- get_origin,
13
- )
14
-
15
-
16
- @dataclass(repr=False, eq=False, frozen=True, kw_only=True, slots=True)
17
- class MatchingTypesConfig:
18
- ignore_none: bool = field(default=False)
19
- with_bases: bool = field(default=False)
20
- with_origin: bool = field(default=False)
21
- with_type_alias_value: bool = field(default=False)
22
-
23
-
24
- _empty_config = MatchingTypesConfig()
25
-
26
-
27
- def iter_matching_types(
28
- type_hint: Any,
29
- /,
30
- config: MatchingTypesConfig | None = None,
31
- ) -> Iterator[Any]:
32
- config = config or _empty_config
33
- type_hints = (type_hint,)
34
- return _iter_matching_types(type_hints, config)
35
-
36
-
37
- def matching_types(
38
- type_hint: Any,
39
- /,
40
- config: MatchingTypesConfig | None = None,
41
- ) -> tuple[Any, ...]:
42
- return tuple(dict.fromkeys(iter_matching_types(type_hint, config)))
43
-
44
-
45
- def _get_bases(type_hint: Any, origin: Any) -> tuple[Any, ...]:
46
- target = type_hint if origin is None else origin
47
-
48
- try:
49
- return get_original_bases(target)
50
- except TypeError:
51
- return ()
52
-
53
-
54
- def _get_generics(type_hint: Any, origin: Any) -> Mapping[TypeVar, Any]:
55
- args = get_args(type_hint)
56
- parameters = getattr(origin, "__parameters__", ())
57
- return dict(zip(parameters, args))
58
-
59
-
60
- def _is_type_var(type_hint: Any) -> bool:
61
- return isinstance(type_hint, TypeVar)
62
-
63
-
64
- def _is_none_type(type_hint: Any) -> bool:
65
- return type_hint in (None, NoneType)
66
-
67
-
68
- def _iter_matching_types(
69
- type_hints: Sequence[Any],
70
- /,
71
- config: MatchingTypesConfig,
72
- params: Mapping[TypeVar, Any] | None = None,
73
- ) -> Iterator[Any]:
74
- if params is None:
75
- params = {}
76
-
77
- for type_hint in type_hints:
78
- if config.ignore_none and _is_none_type(type_hint):
79
- continue
80
-
81
- if _is_type_var(type_hint):
82
- yield params.get(type_hint, type_hint)
83
- continue
84
-
85
- origin = get_origin(type_hint)
86
-
87
- if origin is Generic:
88
- continue
89
-
90
- if unpacked_types := _unpack_types(type_hint, origin):
91
- yield from _iter_matching_types(unpacked_types, config, params)
92
- continue
93
-
94
- if origin is None:
95
- yield type_hint
96
-
97
- else:
98
- args = tuple(
99
- next(_iter_matching_types((arg,), _empty_config, params))
100
- for arg in get_args(type_hint)
101
- )
102
- yield origin[*args]
103
-
104
- if config.with_origin:
105
- yield origin
106
-
107
- if config.with_bases and (bases := _get_bases(type_hint, origin)):
108
- generics = _get_generics(type_hint, origin)
109
- yield from _iter_matching_types(bases, config, generics)
110
-
111
- if config.with_type_alias_value:
112
- if isinstance(origin, TypeAliasType):
113
- values = (origin.__value__,)
114
- generics = _get_generics(type_hint, origin)
115
- yield from _iter_matching_types(values, config, generics)
116
-
117
- elif isinstance(type_hint, TypeAliasType):
118
- values = (type_hint.__value__,)
119
- yield from _iter_matching_types(values, config)
120
-
121
-
122
- def _unpack_types(type_hint: Any, origin: Any) -> Sequence[Any]:
123
- if origin is Union or isinstance(type_hint, UnionType):
124
- return get_args(type_hint)
125
-
126
- elif origin is Annotated:
127
- return get_args(type_hint)[:1]
128
-
129
- return ()
File without changes
File without changes