Skip to main content
# 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

Metadata

Release files for magic_constraints 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for magic_constraints 0.4.0
File Size Uploaded
magic_constraints-0.4.0.tar.gz 20.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for magic_constraints 0.4.0
File Interpreter ABI Platform
magic_constraints-0.4.0-py2.py3-none-any.whl Python 3, Python 2 none any Details

Total release size: 37.7 kB

Release files / magic_constraints-0.4.0.tar.gz

Download URL magic_constraints-0.4.0.tar.gz
Size 20.6 kB
Tags Source
SHA-256 checksum
How to use checksums
1019fa0d601e263ea53e434f6ce5a79652ab0c631408b0f1b8e6d6352e00bab6
BLAKE2b-256 checksum
How to use checksums
4bec3b1300c280a17f28cdc3dc0d5875af0868b426fca6e38bf455a4b05ffa29
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No

Release files / magic_constraints-0.4.0-py2.py3-none-any.whl

Download URL magic_constraints-0.4.0-py2.py3-none-any.whl
Size 17.1 kB
Tags Python 2 Python 3
SHA-256 checksum
How to use checksums
d4cd99f628ec566b082d3331848e9e99c1d3c0058d0249d776e14a4c04a824ca
BLAKE2b-256 checksum
How to use checksums
a84e5ce24d89b0a4c81b2a4f23c108235981df6baf48d4415165e2dc2c2a4d28
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page