0
# Typing Inspect
1
2
Runtime inspection utilities for the Python typing module, enabling developers to programmatically analyze and introspect type annotations and generic types at runtime. This library provides comprehensive functions for testing and extracting information from complex type constructs across Python versions 2.7 and 3.5+.
3
4
## Package Information
5
6
- **Package Name**: typing_inspect
7
- **Language**: Python
8
- **Installation**: `pip install typing_inspect`
9
10
## Core Imports
11
12
```python
13
import typing_inspect
14
```
15
16
Common imports for type checking functions:
17
18
```python
19
from typing_inspect import (
20
is_generic_type, is_callable_type, is_union_type, is_optional_type,
21
get_origin, get_args, get_parameters
22
)
23
```
24
25
## Basic Usage
26
27
```python
28
from typing import Generic, TypeVar, Union, List, Optional
29
from typing_inspect import is_generic_type, is_union_type, get_origin, get_args
30
31
T = TypeVar('T')
32
33
# Test if types are generic
34
assert is_generic_type(List[int]) # True
35
assert is_generic_type(Generic[T]) # True
36
assert not is_generic_type(int) # False
37
38
# Test union types
39
assert is_union_type(Union[int, str]) # True
40
assert is_union_type(Optional[int]) # True (Optional[X] = Union[X, None])
41
42
# Extract type information
43
assert get_origin(List[int]) == list # In Python 3.7+
44
assert get_args(Union[int, str]) == (int, str)
45
assert get_args(Optional[int]) == (int, type(None))
46
```
47
48
## Capabilities
49
50
### Type Testing Functions
51
52
Functions to test various properties of types, determining whether a type represents a specific typing construct.
53
54
```python { .api }
55
def is_generic_type(tp):
56
"""
57
Test if the given type is a generic type.
58
59
Includes Generic itself, but excludes special typing constructs
60
such as Union, Tuple, Callable, ClassVar.
61
62
Args:
63
tp: Type to test
64
65
Returns:
66
bool: True if tp is a generic type
67
"""
68
69
def is_callable_type(tp):
70
"""
71
Test if the type is a generic callable type.
72
73
Including subclasses excluding non-generic types and callables.
74
75
Args:
76
tp: Type to test
77
78
Returns:
79
bool: True if tp is a callable type
80
"""
81
82
def is_tuple_type(tp):
83
"""
84
Test if the type is a generic tuple type.
85
86
Including subclasses excluding non-generic classes.
87
88
Args:
89
tp: Type to test
90
91
Returns:
92
bool: True if tp is a tuple type
93
"""
94
95
def is_union_type(tp):
96
"""
97
Test if the type is a union type.
98
99
Args:
100
tp: Type to test
101
102
Returns:
103
bool: True if tp is a union type
104
"""
105
106
def is_optional_type(tp):
107
"""
108
Test if the type is type(None), or is a direct union with it.
109
110
Such as Optional[T]. Does not inspect nested unions or TypeVar bounds.
111
112
Args:
113
tp: Type to test
114
115
Returns:
116
bool: True if tp is an optional type
117
"""
118
119
def is_final_type(tp):
120
"""
121
Test if the type is a final type.
122
123
Args:
124
tp: Type to test
125
126
Returns:
127
bool: True if tp is a final type
128
"""
129
130
def is_literal_type(tp):
131
"""
132
Test if the type is a literal type.
133
134
Args:
135
tp: Type to test
136
137
Returns:
138
bool: True if tp is a literal type
139
"""
140
141
def is_typevar(tp):
142
"""
143
Test if the type represents a type variable.
144
145
Args:
146
tp: Type to test
147
148
Returns:
149
bool: True if tp is a TypeVar
150
"""
151
152
def is_classvar(tp):
153
"""
154
Test if the type represents a class variable.
155
156
Args:
157
tp: Type to test
158
159
Returns:
160
bool: True if tp is a ClassVar
161
"""
162
163
def is_new_type(tp):
164
"""
165
Tests if the type represents a distinct type (NewType).
166
167
Args:
168
tp: Type to test
169
170
Returns:
171
bool: True if tp is a NewType
172
"""
173
174
def is_forward_ref(tp):
175
"""
176
Tests if the type is a typing.ForwardRef.
177
178
Args:
179
tp: Type to test
180
181
Returns:
182
bool: True if tp is a ForwardRef
183
"""
184
```
185
186
### Type Introspection Functions
187
188
Functions to extract information from types, such as origins, arguments, parameters, and other metadata.
189
190
```python { .api }
191
def get_origin(tp):
192
"""
193
Get the unsubscripted version of a type.
194
195
Supports generic types, Union, Callable, and Tuple.
196
197
Args:
198
tp: Type to get origin from
199
200
Returns:
201
The origin type, or None for unsupported types
202
"""
203
204
def get_last_origin(tp):
205
"""
206
Get the last base of (multiply) subscripted type.
207
208
Only supported in Python 3.6. Supports generic types, Union,
209
Callable, and Tuple.
210
211
Args:
212
tp: Type to get last origin from
213
214
Returns:
215
The last origin type, or None for unsupported types
216
217
Raises:
218
ValueError: If called in Python >= 3.7
219
"""
220
221
def get_parameters(tp):
222
"""
223
Return type parameters of a parameterizable type as a tuple.
224
225
Parameters are returned in lexicographic order. Parameterizable types
226
are generic types, unions, tuple types and callable types.
227
228
Args:
229
tp: Type to get parameters from
230
231
Returns:
232
tuple: Type parameters
233
"""
234
235
def get_args(tp, evaluate=None):
236
"""
237
Get type arguments with all substitutions performed.
238
239
For unions, basic simplifications used by Union constructor are performed.
240
In Python >= 3.7, evaluate parameter is ignored and always True.
241
242
Args:
243
tp: Type to get arguments from
244
evaluate (bool, optional): Whether to evaluate type parameters.
245
Only used in Python < 3.7
246
247
Returns:
248
tuple: Type arguments
249
250
Raises:
251
ValueError: If evaluate=False in Python >= 3.7
252
"""
253
254
def get_last_args(tp):
255
"""
256
Get last arguments of (multiply) subscripted type.
257
258
Only supported in Python 3.6. Parameters for Callable are flattened.
259
260
Args:
261
tp: Type to get last arguments from
262
263
Returns:
264
tuple: Last type arguments
265
266
Raises:
267
ValueError: If called in Python >= 3.7
268
"""
269
270
def get_bound(tp):
271
"""
272
Return the type bound to a TypeVar if any.
273
274
Args:
275
tp: TypeVar to get bound from
276
277
Returns:
278
The bound type, or None if no bound
279
280
Raises:
281
TypeError: If tp is not a TypeVar
282
"""
283
284
def get_constraints(tp):
285
"""
286
Returns the constraints of a TypeVar if any.
287
288
Args:
289
tp: TypeVar to get constraints from
290
291
Returns:
292
tuple: Constraint types, or empty tuple if no constraints
293
294
Raises:
295
TypeError: If tp is not a TypeVar
296
"""
297
298
def get_generic_type(obj):
299
"""
300
Get the generic type of an object if possible.
301
302
Otherwise returns runtime class.
303
304
Args:
305
obj: Object to get generic type from
306
307
Returns:
308
The generic type if available, otherwise type(obj)
309
"""
310
311
def get_generic_bases(tp):
312
"""
313
Get generic base types of a type or empty tuple if not possible.
314
315
Args:
316
tp: Type to get generic bases from
317
318
Returns:
319
tuple: Generic base types
320
"""
321
322
def typed_dict_keys(td):
323
"""
324
If td is a TypedDict class, return a dictionary mapping keys to types.
325
326
Args:
327
td: Type to check for TypedDict
328
329
Returns:
330
dict: Mapping of typed keys to types, or None if not a TypedDict
331
"""
332
333
def get_forward_arg(fr):
334
"""
335
If fr is a ForwardRef, return the string representation.
336
337
Args:
338
fr: Object to check for ForwardRef
339
340
Returns:
341
str: Forward reference string, or None if not a ForwardRef
342
"""
343
```
344
345
### Version Compatibility Constants
346
347
Boolean constants indicating feature availability across different Python versions.
348
349
```python { .api }
350
NEW_TYPING: bool
351
# True if Python version >= 3.7.0 (PEP 560)
352
353
WITH_FINAL: bool
354
# True if Final type is available
355
356
WITH_LITERAL: bool
357
# True if Literal type is available
358
359
WITH_CLASSVAR: bool
360
# True if ClassVar type is available
361
362
WITH_NEWTYPE: bool
363
# True if NewType is available
364
365
LEGACY_TYPING: bool
366
# True if using legacy typing module (very old versions)
367
```
368
369
## Examples
370
371
### Working with Generic Types
372
373
```python
374
from typing import List, Dict, Generic, TypeVar
375
from typing_inspect import is_generic_type, get_origin, get_args
376
377
T = TypeVar('T')
378
K = TypeVar('K')
379
V = TypeVar('V')
380
381
class MyContainer(Generic[T]):
382
def __init__(self, item: T):
383
self.item = item
384
385
# Test generic types
386
assert is_generic_type(List[int])
387
assert is_generic_type(Dict[str, int])
388
assert is_generic_type(MyContainer[str])
389
390
# Extract type information
391
assert get_origin(List[int]) == list # Python 3.7+
392
assert get_args(Dict[str, int]) == (str, int)
393
```
394
395
### Analyzing Union and Optional Types
396
397
```python
398
from typing import Union, Optional
399
from typing_inspect import is_union_type, is_optional_type, get_args
400
401
# Union types
402
StringOrInt = Union[str, int]
403
assert is_union_type(StringOrInt)
404
assert get_args(StringOrInt) == (str, int)
405
406
# Optional types (which are Union[T, None])
407
OptionalString = Optional[str]
408
assert is_optional_type(OptionalString)
409
assert is_union_type(OptionalString) # Optional is Union
410
assert get_args(OptionalString) == (str, type(None))
411
```
412
413
### TypeVar Inspection
414
415
```python
416
from typing import TypeVar
417
from typing_inspect import is_typevar, get_bound, get_constraints
418
419
# Unconstrained TypeVar
420
T = TypeVar('T')
421
assert is_typevar(T)
422
assert get_bound(T) is None
423
assert get_constraints(T) == ()
424
425
# Bound TypeVar
426
NumberT = TypeVar('NumberT', bound=int)
427
assert is_typevar(NumberT)
428
assert get_bound(NumberT) == int
429
430
# Constrained TypeVar
431
StringOrBytesT = TypeVar('StringOrBytesT', str, bytes)
432
assert is_typevar(StringOrBytesT)
433
assert get_constraints(StringOrBytesT) == (str, bytes)
434
```
435
436
### Version-Specific Features
437
438
```python
439
from typing_inspect import NEW_TYPING, WITH_FINAL, WITH_LITERAL
440
441
if NEW_TYPING:
442
# Use Python 3.7+ typing features
443
from typing import get_origin as typing_get_origin
444
# typing_inspect.get_origin provides compatibility layer
445
446
if WITH_FINAL:
447
from typing_extensions import Final
448
from typing_inspect import is_final_type
449
450
FinalInt = Final[int]
451
assert is_final_type(FinalInt)
452
453
if WITH_LITERAL:
454
from typing_extensions import Literal
455
from typing_inspect import is_literal_type
456
457
Color = Literal['red', 'green', 'blue']
458
assert is_literal_type(Color)
459
```