RT-Generic
RT-Generic is a typed python module to make accessing the actual runtime types from a generic module more straight forward. It defines a base class RTGeneric which initializes each subclass (at subclass definition) with a mapping from (Class, TypeVar) to the actual type eventually assigned to that TypeVar. This permits me, for example, when creating `class GenClass[T,U,V](RTGeneric):` to write code which will behave appropriately for when I eventually create `class SubClass1(GenClass[int, float, dict[int, float]]):` and `class SubClass2(GenClass[tuple[str], list[float], dict[tuple[str], list[float]]]):`. [Repository](https://codeberg.org/Pusher2531/rt-generic.git), [PyPI](https://pypi.org/project/rt-generic/).
The process has 4 steps minimum (with a few optional steps along the way):
1. Import RTGeneric from rt_generic. Importing * also brings three Literal types which can be useful.
* all brings in
* class RTGeneric with class methods tv2type (converts TypeVar to actual type), generic_true (tests if Literal type means "True" or "Yes"), generic_false (tests if Literal type means "No" or "False"), and generic_lit_values (which gives a tuple of all literal values a Literal type represents).
* TrueT, a Literal type for True.
* FalseT, a Literal type for False.
* TypeErrorT, a Literal type RTGeneric functions return when an error occured
* function has_anyTypeVar(cls) -> bool, which can be used to check if all types in a class have been defined
2. (Optionally) from rt_generic.type_setup import * for consistent types across python versions
* For all python versions supported by rt_generic, ensures that these are defined:
* TypeAlias, GenericAlias, LiteralGenericAlias
* TypeVar, ClassVar, Generic, Any, Literal, NoneType
* Self
* Union, Tuple, Dict, List, TYPE_CHECKING
* get_args, get_origin, get_original_bases
3. Declare your generic base class, based on Generic and RTGeneric
* Either `class MyClass[T,U,V](RTGeneric):`, (python 3.11 or higher) or
```py
T = TypeVar('T')
U = TypeVar('U')
V = TypeVar('V')
class MyClass(RTGeneric, Generic[T,U,V]) :
```
4. Add self.tv2type (or cls.tv2type) calls in your base class where you need behavior to depend on actual types.
* Just to be clear, self.tv2type(MyClass,T) from an instance method, and cls.tv2type(MyClass,T) from a class method.
* You must specify your base class name for the `cls2` argument to tv2type, since you want to resolve TypeVars specified here. For example, using self.__class__ will attempt to resolve them according to the subclass, where there are no remaining TypeVars.
* This returns a **type**, so for example you might have `self.tv2type(MyClass, U) == List[int]`, but not `self.tv2type(MyClass, U) == [1,2]`.
* You can use Literal types to pass in values when you speciallize your class
* To turn behavior on and off, use actual types `TrueT` or `FalseT`, and check in your code with `self.generic_true(MyClass, U)`
* To set values to be used when you speciallize, for example, try using the actual type `Literal["Hello World"]`, and in your code `print(f"Custom Message: {self.generic_lit_values(self.tv2type(MyClass,V))[0]}")` (note index to select an element from the tuple returned by `generic_lit_values`).
5. (Optionally) add a
```py
def __init_subclass__(cls, **kwargs) :
super().__init_subclass(kwargs)
if not has_anyTypeVars(cls) :
... # do your own setup, for example instantiate class
... # variables of types represented by typevars,
... # now that you know what those types are
```
5. (Optionally) declare subclasses which partially assign types to generics
* For example, `class MyClass2[T](MyClass[list[T], dict[str,T], Literal["mode2"]]):`. Note that in this case `tv2type(MyClass2,T) != tv2type(MyClass,T)`.
5. Declare subclasses which fully assign types (possibly subclasses of other subclasses).
* This is required because RTGeneric works by initializing subclasses, and an anonymous subclass (as in `a = MyClass[int,int,dict[str, float]]()`) does not get initalized.
* instead do
```py
class MyFinalClass(MyClass[int,int,dict[str, float]]) :
pass
# or
class MyFinalClass(MyClass2[str]]) :
pass
a = MyFinalClass()
```
Raw data
{
"_id": null,
"home_page": null,
"name": "rt-generic",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0,>=3.7",
"maintainer_email": null,
"keywords": "generic, run time types, runtime, typed, typing",
"author": null,
"author_email": "Doug Sojourner <doug@sojournings.org>",
"download_url": "https://files.pythonhosted.org/packages/85/cc/0282013f763773007293620a06e2ebffa4c639183103de995f11739bc5dc/rt_generic-0.2.4.tar.gz",
"platform": null,
"description": "RT-Generic\n\nRT-Generic is a typed python module to make accessing the actual runtime types from a generic module more straight forward. It defines a base class RTGeneric which initializes each subclass (at subclass definition) with a mapping from (Class, TypeVar) to the actual type eventually assigned to that TypeVar. This permits me, for example, when creating `class GenClass[T,U,V](RTGeneric):` to write code which will behave appropriately for when I eventually create `class SubClass1(GenClass[int, float, dict[int, float]]):` and `class SubClass2(GenClass[tuple[str], list[float], dict[tuple[str], list[float]]]):`. [Repository](https://codeberg.org/Pusher2531/rt-generic.git), [PyPI](https://pypi.org/project/rt-generic/).\n\nThe process has 4 steps minimum (with a few optional steps along the way): \n\n1. Import RTGeneric from rt_generic. Importing * also brings three Literal types which can be useful. \n * all brings in \n\t * class RTGeneric with class methods tv2type (converts TypeVar to actual type), generic_true (tests if Literal type means \"True\" or \"Yes\"), generic_false (tests if Literal type means \"No\" or \"False\"), and generic_lit_values (which gives a tuple of all literal values a Literal type represents). \n\t * TrueT, a Literal type for True. \n\t * FalseT, a Literal type for False. \n\t * TypeErrorT, a Literal type RTGeneric functions return when an error occured \n\t * function has_anyTypeVar(cls) -> bool, which can be used to check if all types in a class have been defined \n2. (Optionally) from rt_generic.type_setup import * for consistent types across python versions \n * For all python versions supported by rt_generic, ensures that these are defined: \n\t * TypeAlias, GenericAlias, LiteralGenericAlias \n\t * TypeVar, ClassVar, Generic, Any, Literal, NoneType \n\t * Self \n\t * Union, Tuple, Dict, List, TYPE_CHECKING \n\t * get_args, get_origin, get_original_bases \n3. Declare your generic base class, based on Generic and RTGeneric\n * Either `class MyClass[T,U,V](RTGeneric):`, (python 3.11 or higher) or\n ```py\n T = TypeVar('T')\n U = TypeVar('U')\n V = TypeVar('V')\n class MyClass(RTGeneric, Generic[T,U,V]) :\n ```\n4. Add self.tv2type (or cls.tv2type) calls in your base class where you need behavior to depend on actual types. \n * Just to be clear, self.tv2type(MyClass,T) from an instance method, and cls.tv2type(MyClass,T) from a class method. \n * You must specify your base class name for the `cls2` argument to tv2type, since you want to resolve TypeVars specified here. For example, using self.__class__ will attempt to resolve them according to the subclass, where there are no remaining TypeVars. \n * This returns a **type**, so for example you might have `self.tv2type(MyClass, U) == List[int]`, but not `self.tv2type(MyClass, U) == [1,2]`. \n * You can use Literal types to pass in values when you speciallize your class \n\t * To turn behavior on and off, use actual types `TrueT` or `FalseT`, and check in your code with `self.generic_true(MyClass, U)` \n\t * To set values to be used when you speciallize, for example, try using the actual type `Literal[\"Hello World\"]`, and in your code `print(f\"Custom Message: {self.generic_lit_values(self.tv2type(MyClass,V))[0]}\")` (note index to select an element from the tuple returned by `generic_lit_values`). \n5. (Optionally) add a \n ```py\n\t def __init_subclass__(cls, **kwargs) :\n\t\t super().__init_subclass(kwargs)\n\t\t if not has_anyTypeVars(cls) :\n\t\t ... # do your own setup, for example instantiate class\n\t\t ... # variables of types represented by typevars,\n\t\t ... # now that you know what those types are\n ```\n5. (Optionally) declare subclasses which partially assign types to generics \n * For example, `class MyClass2[T](MyClass[list[T], dict[str,T], Literal[\"mode2\"]]):`. Note that in this case `tv2type(MyClass2,T) != tv2type(MyClass,T)`. \n5. Declare subclasses which fully assign types (possibly subclasses of other subclasses). \n * This is required because RTGeneric works by initializing subclasses, and an anonymous subclass (as in `a = MyClass[int,int,dict[str, float]]()`) does not get initalized. \n * instead do \n ```py\n\tclass MyFinalClass(MyClass[int,int,dict[str, float]]) :\n\t\tpass\n\t# or\n\tclass MyFinalClass(MyClass2[str]]) :\n\t\tpass\n\n\ta = MyFinalClass()\n ```\n\n",
"bugtrack_url": null,
"license": "GNU General Public License v3 (GPLv3)",
"summary": "tools to make typing more consistent in older versions of python3, and access generic variables at runtime",
"version": "0.2.4",
"project_urls": {
"repository": "https://codeberg.org/Pusher2531/rt-generic.git"
},
"split_keywords": [
"generic",
" run time types",
" runtime",
" typed",
" typing"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "c6decf4b2afd4328cd965f5b0cd2453c19bc4a720f6b4e0fea3a9fd7c207f2a7",
"md5": "7af0092fad6285090626393c6a340c8a",
"sha256": "99c2253ef2388c1780474d79ecb28369f6fcf991e2c36c6aa6acdb2406a4701c"
},
"downloads": -1,
"filename": "rt_generic-0.2.4-py3-none-any.whl",
"has_sig": false,
"md5_digest": "7af0092fad6285090626393c6a340c8a",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>=3.7",
"size": 9025,
"upload_time": "2025-09-07T16:25:08",
"upload_time_iso_8601": "2025-09-07T16:25:08.408694Z",
"url": "https://files.pythonhosted.org/packages/c6/de/cf4b2afd4328cd965f5b0cd2453c19bc4a720f6b4e0fea3a9fd7c207f2a7/rt_generic-0.2.4-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "85cc0282013f763773007293620a06e2ebffa4c639183103de995f11739bc5dc",
"md5": "9b3878545584d60da5d38e7ebcc16875",
"sha256": "3b3d863891029036743fd4c0357c125de8af29c18e536551a0e48e4d6197c817"
},
"downloads": -1,
"filename": "rt_generic-0.2.4.tar.gz",
"has_sig": false,
"md5_digest": "9b3878545584d60da5d38e7ebcc16875",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0,>=3.7",
"size": 4814,
"upload_time": "2025-09-07T16:25:09",
"upload_time_iso_8601": "2025-09-07T16:25:09.275679Z",
"url": "https://files.pythonhosted.org/packages/85/cc/0282013f763773007293620a06e2ebffa4c639183103de995f11739bc5dc/rt_generic-0.2.4.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-09-07 16:25:09",
"github": false,
"gitlab": false,
"bitbucket": false,
"codeberg": true,
"codeberg_user": "Pusher2531",
"codeberg_project": "rt-generic",
"lcname": "rt-generic"
}