|
1 |
| -# typeapi |
| 1 | +<p align="center"><img src="https://i.imgur.com/11FvXpa.png"></p> |
2 | 2 |
|
3 |
| -[](https://github.com/NiklasRosenstein/python-typeapi/actions/workflows/python.yml) |
| 3 | +<h1 align="center">python-typeapi</h1> |
4 | 4 |
|
5 |
| - [PEP484]: https://peps.python.org/pep-0484/ |
6 | 5 | [PEP585]: https://peps.python.org/pep-0585/
|
7 | 6 | [PEP604]: https://peps.python.org/pep-0604/
|
| 7 | + [documentation]: https://niklasrosenstein.github.io/python-typeapi/ |
8 | 8 |
|
9 |
| -__Compatibility__: Python 3.8+ |
| 9 | +The `typeapi` package provides a **unified and consistent** API for the reflection Python type hints from |
| 10 | +CPython 3.6.3 onwards. It also allows evaluating string-literal type annotations of more recent Python releases in |
| 11 | +older versions (such as [PEP585][] and [PEP604][] expressions). |
10 | 12 |
|
11 |
| -The `typeapi` package provides an object-oriented interface for introspecting [PEP484][] type hints at runtime, |
12 |
| -including forward references that make use of the more recent [PEP585][] and [PEP604][] type hint features in |
13 |
| -Python versions that don't natively support them. |
| 13 | +To learn more about this package, visit its [documentation][]. |
14 | 14 |
|
15 |
| -The main API of this module is comprised of: |
16 |
| - |
17 |
| -* `typeapi.TypeHint()` – A class to parse low-level type hints and present them in a consistent, object-oriented API. |
18 |
| -* `typeapi.get_annotations()` – Retrieve an object's `__annotations__` with support for evaluating future type hints ([PEP585][], [PEP604][]). |
19 |
| - |
20 |
| -The following kinds of type hints are currently supported: |
21 |
| - |
22 |
| -| Concrete type | Description | Added in | |
23 |
| -|----------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------| |
24 |
| -| `ClassTypeHint` | For any normal or generic type as well as `typing.Any`. Provides access to the underlying type, the type arguments and parameters, if any. | 1.0.0 | |
25 |
| -| `UnionTypeHint` | Represents `Union` type hint and gives access to the union members. | 1.0.0 | |
26 |
| -| `LiteralTypeHint` | Represents a `Literal` type hint and gives access to the literal values. | 1.0.0 | |
27 |
| -| `AnnotatedTypeHint` | Represents an `Annotated` type hint and gives access to the annotated type as well as the metadata. | 1.0.0 | |
28 |
| -| `TypeVarTypeHint` | Represents a `TypeVar` type hint and gives an interface to access the variable's metadata (such as constarints, variance, ...). | 1.0.0 | |
29 |
| -| `ForwardRefTypeHint` | Represents a forward reference. Can be evaluated in Python 3.6+ even if it contains [PEP585][] (3.9+) and [PEP604][] (3.10+) expressions. <sup>1)</sup> | 1.0.0, future support in 1.3.0 | |
30 |
| -| `TupleTypeHint` | Reperesents a `Tuple` type hint, allowing you to differentiate between repeated and explicitly sized tuples. | 1.2.0 | |
31 |
| - |
32 |
| -<sup>1)</sup> New-style type union evaluation will continue to return a `typing.Union`, even if the same syntax |
33 |
| -evaluated natively by Python 3.10+ results in a `types.UnionType`. |
34 |
| - |
35 |
| -## Examples |
36 |
| - |
37 |
| -Inspect a `List[int]` type hint: |
38 |
| - |
39 |
| -```py |
40 |
| -# cat <<EOF | python - |
41 |
| -from typeapi import ClassTypeHint, TypeHint |
42 |
| -from typing import List |
43 |
| - |
44 |
| -hint = TypeHint(List[int]) |
45 |
| -assert isinstance(hint, ClassTypeHint) |
46 |
| -assert hint.type is list |
47 |
| - |
48 |
| -item_hint = hint[0] |
49 |
| -assert isinstance(item_hint, ClassTypeHint) |
50 |
| -assert item_hint.type is int |
51 |
| -``` |
52 |
| - |
53 |
| -Retrieve the metadata from an `Annotated[...]` type hint: |
54 |
| - |
55 |
| -```py |
56 |
| -# cat <<EOF | python - |
57 |
| -from typeapi import AnnotatedTypeHint, ClassTypeHint, TypeHint |
58 |
| -from typing_extensions import Annotated |
59 |
| - |
60 |
| -hint = TypeHint(Annotated[int, 42]) |
61 |
| -assert isinstance(hint, AnnotatedTypeHint) |
62 |
| -assert hint.type is int |
63 |
| -assert hint.metadata == (42,) |
64 |
| - |
65 |
| -sub_hint = hint[0] |
66 |
| -assert isinstance(sub_hint, ClassTypeHint) |
67 |
| -assert sub_hint.type is int |
68 |
| -``` |
69 |
| - |
70 |
| -Parameterize one type hint with the parameterization of a generic alias: |
71 |
| - |
72 |
| -```py |
73 |
| -# cat <<EOF | python - |
74 |
| -from dataclasses import dataclass |
75 |
| -from typeapi import ClassTypeHint, TypeHint |
76 |
| -from typing import Generic, TypeVar |
77 |
| -from typing_extensions import Annotated |
78 |
| - |
79 |
| -T = TypeVar("T") |
80 |
| - |
81 |
| -@dataclass |
82 |
| -class MyGeneric(Generic[T]): |
83 |
| - value: T |
84 |
| - |
85 |
| -hint = TypeHint(MyGeneric[int]) |
86 |
| -assert isinstance(hint, ClassTypeHint) |
87 |
| -assert hint.get_parameter_map() == {T: int} |
88 |
| - |
89 |
| -member_hint = TypeHint(T).parameterize(hint.get_parameter_map()) |
90 |
| -assert isinstance(member_hint, ClassTypeHint) |
91 |
| -assert member_hint.type is int |
92 |
| -``` |
93 |
| - |
94 |
| -Evaluate forward references with `get_annotations()`: |
95 |
| - |
96 |
| -```py |
97 |
| -# cat <<EOF | python - |
98 |
| -from typeapi import get_annotations |
99 |
| -from typing import Optional |
100 |
| -from sys import version_info |
101 |
| - |
102 |
| -class MyType: |
103 |
| - a: "str | None" |
104 |
| - |
105 |
| -annotations = get_annotations(MyType) |
106 |
| - |
107 |
| -if version_info[:2] < (3, 10): |
108 |
| - assert annotations == {"a": Optional[str]} |
109 |
| -else: |
110 |
| - assert annotations == {"a": str | None} |
111 |
| -``` |
112 |
| - |
113 |
| -Evaluating forward references with the `TypeHint` API: |
114 |
| - |
115 |
| -```py |
116 |
| -# cat <<EOF | python - |
117 |
| -from typeapi import ClassTypeHint, ForwardRefTypeHint, TypeHint |
118 |
| - |
119 |
| -MyVector = "list[MyType]" |
120 |
| - |
121 |
| -class MyType: |
122 |
| - pass |
123 |
| - |
124 |
| -hint = TypeHint(MyVector).evaluate(globals()) |
125 |
| -print(hint) # TypeHint(typing.List[__main__.MyType]) |
126 |
| -assert isinstance(hint, ClassTypeHint) |
127 |
| -assert hint.type is list |
128 |
| - |
129 |
| -item_hint = hint[0] |
130 |
| -assert isinstance(item_hint, ClassTypeHint) |
131 |
| -assert item_hint.type is MyType |
132 |
| -``` |
| 15 | +Please file bug reports and feature requests [on GitHub](https://github.com/NiklasRosenstein/python-typeapi/issues). |
0 commit comments