Skip to main content

Magic Type Introspection And Runtime Parameter Type/Value Checking.

Project description

# Introduction

*magic-constraints* implemented (or hacked) a bunch of [abstract base classes][1] (ABCs for short) to support [type introspection][2], that is, the `isinstance`/`issubclass` operatios in Python. Specialization of ABC is support, i.e. `Sequence[int]` and `Sequence[int]` are specialized versions of `Sequence`.

Also, *magic-constraints* provides several decorators to enable runtime type/value checking on the parameters and return value of user-defined function and method. Especially, thoses decorators fit well with the type annotation feature introduced in Python 3.x:

```python
from magic_constraints import function_constraints, Optional


# foobar should accept either an int object or a None object.
@function_constraints
def function(foobar: Optional[int]) -> float:
if foobar is None:
# should fail the return type checking.
return 42
else:
# good case.
return 42.0
```

Runtime:

```
# ok.
>>> function(1)
42.0

# failed.
# 1.0 is float, while foobar requrie int or type(None).
>>> function(1.0)
Traceback (most recent call last):
...
magic_constraints.exception.MagicTypeError:
MagicTypeError: argument unmatched.
-----------------------------------
argument: 1.0
parameter: Parameter(name='foobar', type_=Optional[int])
-----------------------------------

# failed.
# when foobar is None, the function returns a float,
# leading to unmatched return type error.
>>> function(None)
Traceback (most recent call last):
...
magic_constraints.exception.MagicTypeError:
MagicTypeError: return value unmatched.
---------------------------------------
ret: 42
return_type: ReturnType(type_=float)
---------------------------------------
```

# Quick Start

## Install

```
$ pip install magic-constraints
```

## Usage Of ABCs

*magic-constraints* provides `Sequence/MutableSequence/ImmutableSequence`. You can invoke `isinstance`/`issubclass` operatios on :

```python
from magic_constraints import Sequence, MutableSequence, ImmutableSequence

# True.
isinstance([1, 2, 3], Sequence)
# True.
isinstance([1, 2, 3], MutableSequence)
# True.
isinstance((1, 2, 3), ImmutableSequence)

# True, Sequence with int.
isinstance([1, 2, 3], Sequence[int])
# False, 2.0 is float.
isinstance([1, 2.0, 3], Sequence[int])

# True.
isinstance([(1, 2), (3, 4)], Sequence[ImmutableSequence[int]])
# False, 3.0 is float.
isinstance([(1, 2), (3.0, 4)], Sequence[ImmutableSequence[int]])
# False, [3, 4] is MutableSequence.
isinstance([(1, 2), [3, 4]], Sequence[ImmutableSequence[int]])

# True
issubclass(MutableSequence, Sequence)
# True
issubclass(ImmutableSequence, Sequence)
# False
issubclass(MutableSequence, ImmutableSequence)
# False
issubclass(ImmutableSequence, MutableSequence)
```

More avaliable ABCs:

| name | supported specialization(s) |
| --- | --- |
| Sequence | [ type ] , [ type , ... ] |
| MutableSequence | [ type ] , [ type , ... ] |
| ImmutableSequence | [ type ] , [ type , ... ] |
| Set | [ type ] |
| MutableSet | [ type ] |
| ImmutableSet | [ type ] |
| Mapping | [ type , type ] |
| MutableMapping | [ type , type ] |
| ImmutableMapping | [ type , type ] |
| Iterator | [ type ] , [ type , ... ] |
| Iterable | [ type ] , [ type , ... ] |
| Callable | [ [ type , ... ] , type ] , [ Ellipsis , type ] |
| Any | *not support* |
| Union | [ type , ... ] |
| Optional | [ type ] |
| NoneType | *not support* |


## Usage Of Decorators

Declaration on function parameters and return value:

```python
from magic_constraints import (
function_constraints,
Sequence, Mapping,
)

@function_constraints
def func1(foo: str, bar: Sequence[int]) -> Mapping[str, Sequence[int]]:
return {foo: bar}
```

More decorators:

```python
from magic_constraints.decorator import (
function_constraints,
method_constraints,
class_initialization_constraints,
)
```

## Runtime Type/Value Checking

Exceptoin would be raised if there's something wrong in the invocation of decorated function, i.e. input argument is not an instance of declared type.

Only derived classes of `SyntaxError` and `TypeError` would be raised:

1. anything related to types, such as failing to pass `isinstance`, would raise an exception with derived type of `TypeError`.
2. besides (1), anything related to the promise of interface (function) invocation, would raise an exception with derived type of `SyntaxError`.

Example:

```
# ok.
>>> func1('key', [1, 2, 3])
{'key': [1, 2, 3]}

# failed, bar requires a sequnce.
>>> func1('42 is not a sequence', 42)
Traceback (most recent call last):
...
magic_constraints.exception.MagicTypeError:
MagicTypeError: argument unmatched.
-----------------------------------
argument: 42
parameter: Parameter(name='bar', type_=Sequence[int])
-----------------------------------

# failed, bar requires a sequence of ints.
>>> func1('2.0 is not int', [1, 2.0, 3])
Traceback (most recent call last):
...
magic_constraints.exception.MagicTypeError:
MagicTypeError: argument unmatched.
-----------------------------------
argument: [1, 2.0, 3]
parameter: Parameter(name='bar', type_=Sequence[int])
-----------------------------------
```

# For more...

* [magic_constrains.types][3].
* [magic_constrains.decorator][4].


[1]: https://docs.python.org/3/glossary.html#term-abstract-base-class
[2]: https://en.wikipedia.org/wiki/Type_introspection
[3]: https://github.com/huntzhan/magic-constraints/wiki/magic_constrains.types
[4]: https://github.com/huntzhan/magic-constraints/wiki/magic_constraints.decorator

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

magic_constraints-0.4.0.tar.gz (20.6 kB view details)

Uploaded Source

Built Distribution

magic_constraints-0.4.0-py2.py3-none-any.whl (17.1 kB view details)

Uploaded Python 2 Python 3

File details

Details for the file magic_constraints-0.4.0.tar.gz.

File metadata

File hashes

Hashes for magic_constraints-0.4.0.tar.gz
Algorithm Hash digest
SHA256 1019fa0d601e263ea53e434f6ce5a79652ab0c631408b0f1b8e6d6352e00bab6
MD5 0d9922a13e334ab1eca92afd742d275c
BLAKE2b-256 4bec3b1300c280a17f28cdc3dc0d5875af0868b426fca6e38bf455a4b05ffa29

See more details on using hashes here.

File details

Details for the file magic_constraints-0.4.0-py2.py3-none-any.whl.

File metadata

File hashes

Hashes for magic_constraints-0.4.0-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 d4cd99f628ec566b082d3331848e9e99c1d3c0058d0249d776e14a4c04a824ca
MD5 afd2720e64402674ed0ad9ea93f76a6d
BLAKE2b-256 a84e5ce24d89b0a4c81b2a4f23c108235981df6baf48d4415165e2dc2c2a4d28

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page