# <div align="center">runtime_generics<br>[](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/)</div>
[](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)<br>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).<br>
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)
<!--
This section was generated from skeleton-ci/skeleton-python@0.0.2rc-244-g52a2805.
Instead of changing this particular file, you might want to alter the template:
https://github.com/skeleton-ci/skeleton-python/tree/0.0.2rc-244-g52a2805/project/README.md.jinja
-->
> [!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).<br/>
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
```
<sub>If you encounter any problems, refer to [the official documentation](https://python-poetry.org/docs/#installation) for the most up-to-date installation instructions.</sub>
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).<br/>
Always happy to accept contributions! ❤️
# Legal Info
© Copyright by Bartosz Sławecki ([@bswck](https://github.com/bswck)).
<br />This software is licensed under the terms of [MIT License](https://github.com/bswck/runtime_generics/blob/HEAD/LICENSE).
Raw data
{
"_id": null,
"home_page": "https://github.com/bswck/runtime_generics",
"name": "runtime-generics",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": null,
"author": "bswck",
"author_email": "bartoszpiotrslawecki@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/b9/34/b1b82a4f623d61fccc21361e402dbee87338bc03a018844d51f5c7eb368c/runtime_generics-3.3.1.tar.gz",
"platform": null,
"description": "# <div align=\"center\">runtime_generics<br>[](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/)</div>\n\n[](https://github.com/bswck/runtime_generics/actions/workflows/test.yml)\n[](https://coverage-badge.samuelcolvin.workers.dev/redirect/bswck/runtime_generics)\n[](https://tidelift.com/subscription/pkg/pypi-runtime-generics?utm_source=pypi-runtime-generics&utm_medium=readme)\n\nHighly into type-safe Python code?\n\n_runtime_generics_ is a niche Python library that allows you to reuse type arguments explicitly passed at runtime\nto generic classes before instantiation.\n\nThe library does four things:\n- exposes utilities that allow to inspect C3-linearized MROs of runtime generics\n and type-check them with variance support: `get_mro()`, `type_check()`;\n- makes it possible to retrieve the type arguments passed to the generic class at runtime\n before the class was instantiated: `get_type_arguments()`, `get_alias()`;\n- offers facilities to find how parent classes are parametrized (\n e.g. if `Foo[T]` inherits from `Dict[str, T]`,\n finds that `Dict[str, int]` is a parent for `Foo[int]`\n ): `get_parents()`;\n- given a parametrized generic class (generic alias),\n makes every class method use generic alias `cls` instead of the origin class\n (unless decorated with `@no_alias`).\n\n# A Simple Example\n3.12+ ([PEP 695](https://peps.python.org/pep-0695) syntax):\n```python\nfrom __future__ import annotations\n\nimport io\nfrom typing import TYPE_CHECKING\n\nfrom runtime_generics import get_alias, get_type_arguments, runtime_generic, type_check\n\nif TYPE_CHECKING:\n from typing import IO, Literal, overload\n\n\n@runtime_generic\nclass IOWrapper[T: str | bytes]:\n data_type: type[T]\n\n def __init__(self, stream: IO[T]) -> None:\n (self.data_type,) = get_type_arguments(self)\n self.stream = stream\n\n if TYPE_CHECKING:\n @overload\n def is_binary(self: IOWrapper[bytes]) -> Literal[True]: ...\n\n @overload\n def is_binary(self: IOWrapper[str]) -> Literal[False]: ...\n\n def is_binary(self) -> bool:\n # alternatively here: `self.data_type == bytes`\n return type_check(self, IOWrapper[bytes])\n\n def __repr__(self) -> str:\n return f\"<{get_alias(self)} object at ...>\"\n\n\nmy_binary_data = IOWrapper[bytes](io.BytesIO(b\"foo\"))\nassert my_binary_data.data_type is bytes\nassert my_binary_data.is_binary()\nassert repr(IOWrapper[str](io.StringIO())) == \"<__main__.IOWrapper[str] object at ...>\"\n```\n\n3.8+:\n\n```python\nfrom __future__ import annotations\n\nimport io\nfrom typing import TYPE_CHECKING, Generic, TypeVar\n\nfrom runtime_generics import get_alias, get_type_arguments, runtime_generic, type_check\n\nif TYPE_CHECKING:\n from typing import IO, Literal, overload\n\nT = TypeVar(\"T\", str, bytes)\n\n\n@runtime_generic\nclass IOWrapper(Generic[T]):\n data_type: type[T]\n\n def __init__(self, stream: IO[T]) -> None:\n (self.data_type,) = get_type_arguments(self)\n self.stream = stream\n\n if TYPE_CHECKING:\n @overload\n def is_binary(self: IOWrapper[bytes]) -> Literal[True]: ...\n\n @overload\n def is_binary(self: IOWrapper[str]) -> Literal[False]: ...\n\n def is_binary(self) -> bool:\n # alternatively here: `self.data_type == bytes`\n return type_check(self, IOWrapper[bytes])\n\n def __repr__(self) -> str:\n return f\"<{get_alias(self)} object at ...>\"\n\n\nmy_binary_data = IOWrapper[bytes](io.BytesIO(b\"foo\"))\nassert my_binary_data.data_type is bytes\nassert my_binary_data.is_binary()\nassert repr(IOWrapper[str](io.StringIO())) == \"<__main__.IOWrapper[str] object at ...>\"\n```\n\n\n# For Enterprise\n\n| [](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)<br>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). |\n| - | - |\n\nTo report a security vulnerability, please use the\n[Tidelift security contact](https://tidelift.com/security).<br>\nTidelift will coordinate the fix and disclosure.\n\n# Installation\nYou might simply install it with pip:\n\n```shell\npip install runtime-generics\n```\n\nIf you use [Poetry](https://python-poetry.org/), then you might want to run:\n\n```shell\npoetry add runtime-generics\n```\n\n## For Contributors\n[](https://python-poetry.org/)\n[](https://github.com/astral-sh/ruff)\n[](https://github.com/pre-commit/pre-commit)\n<!--\nThis section was generated from skeleton-ci/skeleton-python@0.0.2rc-244-g52a2805.\nInstead of changing this particular file, you might want to alter the template:\nhttps://github.com/skeleton-ci/skeleton-python/tree/0.0.2rc-244-g52a2805/project/README.md.jinja\n-->\n> [!Note]\n> 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).\n1. Fork the [runtime_generics repository](https://github.com/bswck/runtime_generics) on GitHub.\n\n1. [Install Poetry](https://python-poetry.org/docs/#installation).<br/>\n Poetry is an amazing tool for managing dependencies & virtual environments, building packages and publishing them.\n You might use [pipx](https://github.com/pypa/pipx#readme) to install it globally (recommended):\n\n ```shell\n pipx install poetry\n ```\n\n <sub>If you encounter any problems, refer to [the official documentation](https://python-poetry.org/docs/#installation) for the most up-to-date installation instructions.</sub>\n\n Be sure to have Python 3.8 installed\u2014if you use [pyenv](https://github.com/pyenv/pyenv#readme), simply run:\n\n ```shell\n pyenv install 3.8\n ```\n\n1. Clone your fork locally and install dependencies.\n\n ```shell\n git clone https://github.com/your-username/runtime_generics path/to/runtime_generics\n cd path/to/runtime_generics\n poetry env use $(cat .python-version)\n poetry install\n ```\n\n Next up, simply activate the virtual environment and install pre-commit hooks:\n\n ```shell\n poetry shell\n pre-commit install\n ```\n\nFor more information on how to contribute, check out [CONTRIBUTING.md](https://github.com/bswck/runtime_generics/blob/HEAD/CONTRIBUTING.md).<br/>\nAlways happy to accept contributions! \u2764\ufe0f\n\n# Legal Info\n\u00a9 Copyright by Bartosz S\u0142awecki ([@bswck](https://github.com/bswck)).\n<br />This software is licensed under the terms of [MIT License](https://github.com/bswck/runtime_generics/blob/HEAD/LICENSE).\n\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Reuse generic class type arguments at runtime.",
"version": "3.3.1",
"project_urls": {
"Coverage": "https://coverage-badge.samuelcolvin.workers.dev/redirect/bswck/runtime_generics",
"Distribution": "https://pypi.org/project/runtime-generics/",
"Documentation": "https://bswck.github.io/runtime_generics",
"Homepage": "https://github.com/bswck/runtime_generics",
"Issues": "https://github.com/bswck/runtime_generics/issues"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "ce5de73ddf67bf269d290413d5805a485856c7abb15fa4a070935fd250f2c3a3",
"md5": "1ee6a6afd6c1bc77fb75e5023adcefc5",
"sha256": "bf9c74a17cece2f874b3e3f6d1857fd5313c789f8f0854ac4f7669f91ad748ad"
},
"downloads": -1,
"filename": "runtime_generics-3.3.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "1ee6a6afd6c1bc77fb75e5023adcefc5",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 10936,
"upload_time": "2024-05-11T00:09:52",
"upload_time_iso_8601": "2024-05-11T00:09:52.223790Z",
"url": "https://files.pythonhosted.org/packages/ce/5d/e73ddf67bf269d290413d5805a485856c7abb15fa4a070935fd250f2c3a3/runtime_generics-3.3.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "b934b1b82a4f623d61fccc21361e402dbee87338bc03a018844d51f5c7eb368c",
"md5": "ea7ff2acc60658d05ce246e74c0e9d6b",
"sha256": "1ea40ad2b735aed3cdf567efac980e4dbc9c9e9e76144c4f73d1dd440583ffb1"
},
"downloads": -1,
"filename": "runtime_generics-3.3.1.tar.gz",
"has_sig": false,
"md5_digest": "ea7ff2acc60658d05ce246e74c0e9d6b",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 13076,
"upload_time": "2024-05-11T00:09:54",
"upload_time_iso_8601": "2024-05-11T00:09:54.130934Z",
"url": "https://files.pythonhosted.org/packages/b9/34/b1b82a4f623d61fccc21361e402dbee87338bc03a018844d51f5c7eb368c/runtime_generics-3.3.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-05-11 00:09:54",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "bswck",
"github_project": "runtime_generics",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "runtime-generics"
}