https://github.com/bswck/runtime_generics
Reuse type arguments explicitly passed at runtime to a generic class before instantiating.
https://github.com/bswck/runtime_generics
generic-class generic-types generics python-oop
Last synced: 3 months ago
JSON representation
Reuse type arguments explicitly passed at runtime to a generic class before instantiating.
- Host: GitHub
- URL: https://github.com/bswck/runtime_generics
- Owner: bswck
- License: mit
- Archived: true
- Created: 2023-10-25T15:15:07.000Z (about 2 years ago)
- Default Branch: main
- Last Pushed: 2024-06-10T08:48:50.000Z (over 1 year ago)
- Last Synced: 2025-07-12T03:18:29.242Z (4 months ago)
- Topics: generic-class, generic-types, generics, python-oop
- Language: Python
- Homepage: https://bswck.github.io/runtime_generics/
- Size: 1.29 MB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- Funding: .github/FUNDING.yml
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
- Security: SECURITY.md
Awesome Lists containing this project
README
#
runtime_generics
[](https://github.com/skeleton-ci/skeleton-python/tree/0.0.2rc-244-g52a2805) [](https://pypi.org/project/runtime-generics/) [](https://pypi.org/project/runtime-generics/)
[](https://github.com/bswck/runtime_generics/actions/workflows/test.yml)
[](https://coverage-badge.samuelcolvin.workers.dev/redirect/bswck/runtime_generics)
[](https://tidelift.com/subscription/pkg/pypi-runtime-generics?utm_source=pypi-runtime-generics&utm_medium=readme)
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](https://peps.python.org/pep-0695) syntax):
```python
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:
# alternatively here: `self.data_type == bytes`
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+:
```python
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:
# alternatively here: `self.data_type == bytes`
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
| [](https://tidelift.com/subscription/pkg/pypi-runtime-generics?utm_source=pypi-runtime-genericsutm_medium=referral&utm_campaign=readme) | [Available as part of the Tidelift Subscription.](https://tidelift.com/subscription/pkg/pypi-runtime-generics?utm_source=pypi-runtime-generics&&utm_medium=referral&utm_campaign=readme)
This project and the maintainers of thousands of other packages are working with Tidelift to deliver one enterprise subscription that covers all of the open source you use. [Learn more here](https://tidelift.com/subscription/pkg/pypi-runtime-generics?utm_source=pypi-runtime-generics&utm_medium=referral&utm_campaign=github). |
| - | - |
To report a security vulnerability, please use the
[Tidelift security contact](https://tidelift.com/security).
Tidelift will coordinate the fix and disclosure.
# Installation
You might simply install it with pip:
```shell
pip install runtime-generics
```
If you use [Poetry](https://python-poetry.org/), then you might want to run:
```shell
poetry add runtime-generics
```
## For Contributors
[](https://python-poetry.org/)
[](https://github.com/astral-sh/ruff)
[](https://github.com/pre-commit/pre-commit)
> [!Note]
> If you use Windows, it is highly recommended to complete the installation in the way presented below through [WSL2](https://learn.microsoft.com/en-us/windows/wsl/install).
1. Fork the [runtime_generics repository](https://github.com/bswck/runtime_generics) on GitHub.
1. [Install Poetry](https://python-poetry.org/docs/#installation).
Poetry is an amazing tool for managing dependencies & virtual environments, building packages and publishing them.
You might use [pipx](https://github.com/pypa/pipx#readme) to install it globally (recommended):
```shell
pipx install poetry
```
If you encounter any problems, refer to [the official documentation](https://python-poetry.org/docs/#installation) for the most up-to-date installation instructions.
Be sure to have Python 3.8 installed—if you use [pyenv](https://github.com/pyenv/pyenv#readme), simply run:
```shell
pyenv install 3.8
```
1. Clone your fork locally and install dependencies.
```shell
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:
```shell
poetry shell
pre-commit install
```
For more information on how to contribute, check out [CONTRIBUTING.md](https://github.com/bswck/runtime_generics/blob/HEAD/CONTRIBUTING.md).
Always happy to accept contributions! ❤️
# Legal Info
© Copyright by Bartosz Sławecki ([@bswck](https://github.com/bswck)).
This software is licensed under the terms of [MIT License](https://github.com/bswck/runtime_generics/blob/HEAD/LICENSE).