isinstance2
isinstance2 is an experimental module that provides a powerful runtime type checker for Python's built-in generic classes and
generic type hints. It allows you to perform runtime instance type checks on objects that are instances of a generic
class, as well as subclass checks on generic classes, even if you don't know the exact type of the generic parameters.
tl;dr
from isinstance2 import isinstance2, issubclass2
from typing import Iterable
assert isinstance2((1, 2.0, 'three'), tuple[int, float, str])
assert issubclass2(dict[str, int], dict[str, int | float])
assert issubclass2(list[int] | set[int] | tuple[int, ...], Iterable[int])
Features
- Perform runtime instance and subclass checks on generic classes
- Supports built-in generic classes such as
list,tuple,dict,set, andfrozenset, as well asOptionalandLiteral. - Check if an object is an instance of a
tuplewith variadic arguments. - Register custom class or function with
isinstance2's instance checker registry.
Installation
pip install isinstance2
Basic Usage
Instance Checks
from typing import Iterable, Literal
from isinstance2 import isinstance2
# Basic instance checks
assert isinstance2([1, 2, 3], list[int])
assert isinstance2((1, 2.0, 'three'), tuple[int, float, str])
assert isinstance2({1, 2, 3}, set[int])
assert isinstance2({"foo": 1, "bar": 2}, dict[str, int])
assert isinstance2(frozenset([1, 2, 'Hi! 😊', 'literally amazing']), frozenset[int | Literal['Hi! 😊', 'literally amazing']])
# Ellipses in tuples work
assert isinstance2((1, 'two', 3.0, 'four'), tuple[int | float | str, ...])
# You can also check against abstract generic classes
assert isinstance2(range(10), Iterable[int])
assert not isinstance2(range(10), Iterable[float])
Subclass Checks
from typing import Collection, Iterable
from isinstance2 import issubclass2
# Basic subclass checks
assert issubclass2(list[int], list[int | float])
assert issubclass2(tuple[int, float], tuple[int | float, ...])
# Classes without generic parameters are presumed to match
assert issubclass2(list, list[int])
assert issubclass2(list[int], list)
# Abstract generic classes
assert issubclass2(list[int], Iterable[int])
assert issubclass2(Collection[bool], Iterable[int]) # Yes, bool is a subclass of int
Advanced Usage
To check if an object is an instance of a custom generic class, register it with isinstance2's instance checker
from typing import Generic, TypeVar, Any
from isinstance2 import isinstance2, register_instance_checker
T = TypeVar('T')
class MyClass(Generic[T]):
...
@register_instance_checker
def is_instance_of_my_class(obj: Any) -> bool:
return isinstance(obj, MyClass)
assert isinstance2(MyClass(), MyClass)
If you'd prefer not to add your checkers globally, you can use isinstance2's register instead and pass a custom registry (which is just a dict).
from typing import Generic, TypeVar
from isinstance2 import register, instance_checker_registry
from functools import partial
# Copy the default registry
my_registry = instance_checker_registry.copy()
# Make a custom registration function
my_register = partial(register, registry=my_registry)
Now you can use my_register in place of register_instance_checker.
Limitations
- Does not yet support
TypeVarContainer- And likely quite a few other generic classes that I've missed. Please open an issue if you find one.
- Subclass checks for custom classes (instance checks are supported)
- Subclass checks are, in general, unreliable.
- I haven't yet figured out how to deal with things like structural subtyping. For instance,
issubclass2(str, Iterator[int])currently returnsTruewhen it clearly shouldn't - Instance checks are somewhat simpler and shouldn't suffer as much from this problem.
- I haven't yet figured out how to deal with things like structural subtyping. For instance,
- Requires Python 3.11 or later
License
isinstance2 is released under the MIT License.
Metadata
Release files for isinstance2 0.1.8
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| isinstance2-0.1.8.tar.gz | 6.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| isinstance2-0.1.8-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 12.3 kB
Release files / isinstance2-0.1.8.tar.gz
| Download URL | isinstance2-0.1.8.tar.gz |
|---|---|
| Size | 6.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8058f15e8368e76c0acb59fc59ab5d90569d7ddb06ae1f4457fe7f6fca149083
|
|
BLAKE2b-256 checksum How to use checksums |
f88fb09f56f8aeafa9736c4c67428405fa02e5ef2a0968c9d5e5346d3d39aa85
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/1.3.1 CPython/3.11.0 Darwin/22.2.0
|
Release files / isinstance2-0.1.8-py3-none-any.whl
| Download URL | isinstance2-0.1.8-py3-none-any.whl |
|---|---|
| Size | 6.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
871c47197f84772878344969dad13e19f36c0f7ee19645148d34063b2135a575
|
|
BLAKE2b-256 checksum How to use checksums |
e28fadda28eda22a80792f2d092ab643d7f312492288dca9e4d4876378cf2467
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/1.3.1 CPython/3.11.0 Darwin/22.2.0
|