
Highly into type-safe Python code?
runtime_generics is a niche Python library that allows you to reuse type arguments explicitly passed at runtime
to generic classes before instantiation.
The library does four things:
- exposes utilities that allow to inspect C3-linearized MROs of runtime generics
and type-check them with variance support:
get_mro()
, type_check()
; - makes it possible to retrieve the type arguments passed to the generic class at runtime
before the class was instantiated:
get_type_arguments()
, get_alias()
; - offers facilities to find how parent classes are parametrized (
e.g. if
Foo[T]
inherits from Dict[str, T]
,
finds that Dict[str, int]
is a parent for Foo[int]
): get_parents()
; - given a parametrized generic class (generic alias),
makes every class method use generic alias
cls
instead of the origin class
(unless decorated with @no_alias
).
A Simple Example
3.12+ (PEP 695 syntax):
from __future__ import annotations
import io
from typing import TYPE_CHECKING
from runtime_generics import get_alias, get_type_arguments, runtime_generic, type_check
if TYPE_CHECKING:
from typing import IO, Literal, overload
@runtime_generic
class IOWrapper[T: str | bytes]:
data_type: type[T]
def __init__(self, stream: IO[T]) -> None:
(self.data_type,) = get_type_arguments(self)
self.stream = stream
if TYPE_CHECKING:
@overload
def is_binary(self: IOWrapper[bytes]) -> Literal[True]: ...
@overload
def is_binary(self: IOWrapper[str]) -> Literal[False]: ...
def is_binary(self) -> bool:
return type_check(self, IOWrapper[bytes])
def __repr__(self) -> str:
return f"<{get_alias(self)} object at ...>"
my_binary_data = IOWrapper[bytes](io.BytesIO(b"foo"))
assert my_binary_data.data_type is bytes
assert my_binary_data.is_binary()
assert repr(IOWrapper[str](io.StringIO())) == "<__main__.IOWrapper[str] object at ...>"
3.8+:
from __future__ import annotations
import io
from typing import TYPE_CHECKING, Generic, TypeVar
from runtime_generics import get_alias, get_type_arguments, runtime_generic, type_check
if TYPE_CHECKING:
from typing import IO, Literal, overload
T = TypeVar("T", str, bytes)
@runtime_generic
class IOWrapper(Generic[T]):
data_type: type[T]
def __init__(self, stream: IO[T]) -> None:
(self.data_type,) = get_type_arguments(self)
self.stream = stream
if TYPE_CHECKING:
@overload
def is_binary(self: IOWrapper[bytes]) -> Literal[True]: ...
@overload
def is_binary(self: IOWrapper[str]) -> Literal[False]: ...
def is_binary(self) -> bool:
return type_check(self, IOWrapper[bytes])
def __repr__(self) -> str:
return f"<{get_alias(self)} object at ...>"
my_binary_data = IOWrapper[bytes](io.BytesIO(b"foo"))
assert my_binary_data.data_type is bytes
assert my_binary_data.is_binary()
assert repr(IOWrapper[str](io.StringIO())) == "<__main__.IOWrapper[str] object at ...>"
For Enterprise
To report a security vulnerability, please use the
Tidelift security contact.
Tidelift will coordinate the fix and disclosure.
Installation
You might simply install it with pip:
pip install runtime-generics
If you use Poetry, then you might want to run:
poetry add runtime-generics
For Contributors

[!Note]
If you use Windows, it is highly recommended to complete the installation in the way presented below through WSL2.
-
Fork the runtime_generics repository on GitHub.
-
Install Poetry.
Poetry is an amazing tool for managing dependencies & virtual environments, building packages and publishing them.
You might use pipx to install it globally (recommended):
pipx install poetry
If you encounter any problems, refer to the official documentation for the most up-to-date installation instructions.
Be sure to have Python 3.8 installed—if you use pyenv, simply run:
pyenv install 3.8
-
Clone your fork locally and install dependencies.
git clone https://github.com/your-username/runtime_generics path/to/runtime_generics
cd path/to/runtime_generics
poetry env use $(cat .python-version)
poetry install
Next up, simply activate the virtual environment and install pre-commit hooks:
poetry shell
pre-commit install
For more information on how to contribute, check out CONTRIBUTING.md.
Always happy to accept contributions! ❤️
Legal Info
© Copyright by Bartosz Sławecki (@bswck).
This software is licensed under the terms of MIT License.