Python run-time type checking utility
Author: Yuxuan Zhang | GitHub Repository
The rttc project originates from this post on the python discussion forum.
Usage
Want to do something like this?
>>> isinstance(["hello type check"], list[str])
TypeError: isinstance() argument 2 cannot be a parameterized generic
Just drop-in replace isinstance() with type_check()
from type_check import type_check
type_check(["hello type check"], list[str]) # True
type_check([1], list[str]) # False
And of course you can use type variables!
DataType = list[tuple[float, str]]
type_check([(1.0, "hello rttc")], DataType) # True
type_check([(1, 2), [3.0, "4"]] , DataType) # False
Wondering how far you can go?
These features all work recursively with each other!
-
Union types are supported:
type_check(1 , int | bool) # True type_check(True, int | bool) # True type_check("1" , int | bool) # False
-
Literals are supported:
type_check("alex", Literal["alex", "bob"]) # True type_check("hack", Literal["alex", "bob"]) # False
-
Inherited classes are supported:
class C(list[int]): pass type_check(C([1]) , C) # True type_check(C([1.0]), C) # False
-
Type-hinted classes are supported:
from typing import TypeVar, Generic, Literal from dataclasses import dataclass T = TypeVar("T") P = TypeVar("P") @dataclass class C(Generic[T, P]): x: T y: P z: Literal[1] type_check(C(x=1 , y="y", z=1), C[int, str]) # True type_check(C(x=1.0, y="y", z=1), C[int, str]) # False - C.x = float(1.0) is not int type_check(C(x=1 , y="y", z=2), C[int, str]) # False - C.z = int(2) is not Literal[1]
-
Custom checking hooks:
Examples coming soon...
For now, please refer to type_check/builtin_checks.py.
Other tools in the box
type_assert()
Similar to type_check(), but it raises TypeCheckError instead of returns bool.
The raised TypeCheckError contains debug-friendly information indicating what caused type check to fail (check below for details).
type_guard
This decorator allows you to convert a class or a function into a type-guarded object.
It is analogous to performing a type_assert on function return values or on returned class instances.
from type_check import type_guard
@type_guard
def fn(x) -> int | float | str:
return x
fn(1) # ok
fn([]) # TypeCheckError: list([]) is not int | float | str
from dataclasses import dataclass
@type_guard
@dataclass
class A:
x: int
A(x=1) # ok
A(x=1.0) # TypeCheckError: A.x = float(1.0) is not int
Since 1.0.4, the following is made possible:
@type_guard
@dataclass
class B:
x: int
B[int](x=1) # ok
B[int](x=1.0) # TypeCheckError: A.x = float(1.0) is not int
B[float](x=1) # TypeCheckError: A.x = int(1) is not float
Info-rich return values and exceptions
TypeCheckResult
TypeCheckResult is the return type of type_check() function.
It can be used directly as a bool or compared with a bool.
For example:
from type_check import type_check
result = type_check([1], list[int])
print(bool(result), result == True, result == False)
# True, True, False
print(str(result))
# [1] is list[int] => True
print(repr(result))
# type_check([1] is list[int] => True)
And when a result evaluates to False, you can use TypeCheckResult.reason to know why:
result = type_check(["1"], list[int])
print(result)
# ['1'] is list[int] => False
print(result.reason)
# list[0] = str('1') is not int
TypeCheckError
TypeCheckError is inherited from TypeError, it will be raised by type_assert() and @type_guard when type check fails.
It contains chained attributes and keys to help you locate the data that cause type check to fail:
from type_check import type_assert
type_assert([1, 2, '3', 4], list[int])
Will raise:
TypeCheckError Traceback (most recent call last)
Cell In[47], line 10
6 print(result.reason)
8 from type_check import type_assert
---> 10 type_assert([1, 2, "3", 4], list[int])
File rttc/type_check/core.py:45, in type_assert(obj, t, chain)
43 # Clear traceback to avoid confusion
44 type_check_error = e.with_traceback(None)
---> 45 raise type_check_error
46 except TypeError as e:
47 type_error = e.with_traceback(None)
TypeCheckError: list[2] = str('3') is not int
Testing
Test cases live under tests/ and are grouped by categories. Test results are available at docs/test-results.txt. PRs to add more test cases to it will be deeply appreciated.
Instructions to run tests locally
git clone git@github.com:zhangyx1998/rttc.git
cd rttc && python3 -m pip install -r tests/requirements.txt # termcolor
python3 -m tests
Testing against well-known library typeguard:
pip3 install typeguard
TARGET=typegurad python3 -m tests
Metadata
Release files for rttc 1.0.6
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| rttc-1.0.6.tar.gz | 7.7 kB | Without provenance | Details for rttc-1.0.6.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| rttc-1.0.6-py3-none-any.whl | Python 3 | none | any | Details for rttc-1.0.6-py3-none-any.whl |
Total release size: 17.0 kB
Release files / rttc-1.0.6.tar.gz
| Download URL | rttc-1.0.6.tar.gz |
|---|---|
| Size | 7.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
aa493cd47a22209a90936f3c62bbf8aa0d02f9eaf114b7034a4c4cf2c8dd9e63
|
|
BLAKE2b-256 checksum How to use checksums |
6af6204a7da8929007857b691ad50d0a1f2217772cf4712747597bbce4924c90
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/5.1.1 CPython/3.13.0
|
Release files / rttc-1.0.6-py3-none-any.whl
| Download URL | rttc-1.0.6-py3-none-any.whl |
|---|---|
| Size | 9.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5a5b7140f4c8f379b7f27e546e589b30a2c24a93b6be92dbffb38188efae7f62
|
|
BLAKE2b-256 checksum How to use checksums |
91b5f4032291dd47fa79a147a55566f2575813bc1604b75779f5413823dcb4ec
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/5.1.1 CPython/3.13.0
|
Security for rttc 1.0.6
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.