API

pyoload is a python module which will help you type check your function arguments and object attribute types on function call and attribute assignment.

It supports the various builtin data types supported by isinstance and adds support for: - typing.GenericAlias - pyoload.PyoloadAnnoation subclasses as:

  • pyoload.Cast

  • pyoload.Values

  • pyoload.Checks

Authors:

ken-morel

Version:

2.0.1

Dedication:

To the pythonista.

exception pyoload.AnnotationError

base exception for most pyoload errors is raised when a non-subclassable error occurs.

exception pyoload.AnnotationResolutionError

Annotations could not be resolved or evaluated.

class pyoload.Any(*args, **kwargs)

Special type indicating an unconstrained type.

  • Any is compatible with every type.

  • Any assumed to have all methods.

  • All values assumed to be instances of Any.

Note that all the above statements are true from the point of view of static type checkers. At runtime, Any should not be used with instance checks.

class pyoload.Cast(type: Any)

Holds a cast object which describes the casts to be performed

creates a casting object for the specified type The object can then be used anywhere for casting, e.g

>>> caster = Cast(dict[str, list[tuple[float]]])
>>> raw = {
...     4: (
...         ['1.5', 10],
...         [10, '1.5'],
...     )
... }
>>> caster(raw)
{'4': [(1.5, 10.0), (10.0, 1.5)]}
Parameters:

type – The type to which the object will cast

Returns:

self

static cast(val: Any, totype: Any) Any

The gratest deal. Recursively casts the given value to the specified structure or type e.g

>>> Cast.cast({ 1: 2}, dict[str, float])
{'1': 2.0}
Parameters:
  • val – the value to cast

  • totype – The type structure to be casted to.

Returns:

An instance of the casting type

class pyoload.CastedAttr(type: Any)

A descriptor class providing attributes which are casted on assignment

>>> class Person:
...     age = CheckedAttr(gt=0)
...     phone = CastedAttr(tuple[int])
...     def __init__(self, age, phone):
...         self.age = age
...         self.phone = phone
...
>>> temeze = Person(17, "678936798")
>>>
>>> print(temeze.age)
17
>>> print(temeze.phone)
(6, 7, 8, 9, 3, 6, 7, 9, 8)
>>> mballa = Person(0, "123456")
Traceback (most recent call last):
  ...
pyoload.Check.CheckError: 0 not gt 0
class pyoload.Check

A class basicly abstract which holds registerred checks in pyoload A new check can be registerred by subclassing whith a non-initializing callable class, the name will be gotten from the classes .name attribute or the basename of the class if not present.

A Check.CheckNameAlreadyExistsError is raised if the check is already registerred.

exception CheckDoesNotExistError

The specified check does not exist

exception CheckError

Error occurring during check call.

exception CheckNameAlreadyExistsError

The check name to be registerred already exists

classmethod check(name: str, params: Any, val: Any) None

Performs the specified check with the specified params on the specified value

Parameters:
  • cls – pyoload.Check class

  • name – One of the registerred name of the check

if preceded by an underscore, it will be negated :param params: The parameters to pass to the check :param val: The value to check

Returns:

None

classmethod register(name: str) Callable[[Callable[[Any, Any], None]], Callable]

returns a callable which registers a new checker method

used as:

>>> @Check.register('integer_not_equal neq') # can register on multiple
... def _(param, val):                      # names seperated by spaces
...     '''
...     :param param: The parameter passed as kwarg
...     :param val: The value passed as argument
...     '''
...     assert param != val  # using assertions
...     if not isinstance(param, int) or isinstance(val, int):
...         raise TypeError()  # using typeError, handles even unwanted
...     if param == val:        # errors in case wrong value passed
...         raise Check.CheckError(f"values {param=!r} and {val=!r} not equal")
...
>>> Checks(neq=3)
<Checks(neq=3)>
>>> Checks(neq=3)(3)
Traceback (most recent call last):
  File "C:\pyoload\src\pyoload\__init__.py", line 172, in check

File “<stdin>”, line 8, in _

AssertionError

The above exception was the direct cause of the following exception:

Traceback (most recent call last):

File “<stdin>”, line 1, in <module> File “C:pyoloadsrcpyoload__init__.py”, line 291, in __call__

‘’’

File “C:pyoloadsrcpyoload__init__.py”, line 174, in check

pyoload.Check.CheckError

Parameters:
  • cls – the Check class

  • name – the name to be registerred as.

Returns:

a function which registers the check under the name

class pyoload.CheckedAttr(**checks: dict[str, Callable[[Any, Any], NoneType]])

A descriptor class providing attributes which are checked on assignment

Creates a Checked Attribute descriptor whick does checking on each assignment, E.G

>>> class foo:
...     bar = CheckedAttr(gt=4)
Parameters:

checks – The checks to perform

class pyoload.Checks(*__check_funcs__, **checks: dict[str, Callable[[Any, Any], NoneType]])

Pyoload annotation holding several checks called on typechecking.

crates the check object,e.g

>>> class foo:
...    bar: pyoload.Checks(gt=4)
Parameters:

checks – the checks to be done.

Returns:

self

class pyoload.Values(iterable=(), /)

A tuple subclass which holds several values as possible annotations

pyoload.annotable(func: Callable) Callable

Marks a function to be annotatble by annotate and overload

pyoload.annotate(func: Callable, *, force: bool = False, oload: bool = False) Callable

returns a wrapper over the passed function which typechecks arguments on each call.

Parameters:
  • func – the function to annotate

  • force – annotate force even on unannotatables

  • oload – internal, if set to True, will raise InternalAnnotationError on type mismatch

Returns:

the wrapper function

pyoload.annotate_class(cls: Any, recur: bool = True)

Annotates a class object, wrapping and replacing over it’s __setattr__ and typechecking over each attribute assignment. If no annotation for the passed object found it ignores it till it is found it recursively annotates the classes methods except __pyod_norecur__ attribute is defines

pyoload.is_annotable(func)

Returns if the function posses the unannotable mark.

pyoload.is_annoted(func)

Determines if a function has been annotated.

pyoload.multimethod(func: Callable, name: str = None, force: bool = False) Callable

returns a wrapper over the passed function which typechecks arguments on each call and finds the function instance with same name which does not raise an InternalAnnotationError exception. if func is a string, overload will return another registering function which will register to the specified name.

The decorated function takes some new attributes: - __pyod_annotate__: The raw function - __pyod_dispatches__: The list of the function overloads - multimethod(func: Callable) registers the passed function under the same name.

Parameters:
  • func – the function to annotate

  • name – optional name under which to register.

  • force – overloads even unnanotable functions

Returns:

the wrapper function

pyoload.overload(func: Callable, name: str = None, force: bool = False) Callable

returns a wrapper over the passed function which typechecks arguments on each call and finds the function instance with same name which does not raise an InternalAnnotationError exception. if func is a string, overload will return another registering function which will register to the specified name.

The decorated function takes some new attributes: - __pyod_annotate__: The raw function - __pyod_dispatches__: The list of the function overloads - multimethod(func: Callable) registers the passed function under the same name.

Parameters:
  • func – the function to annotate

  • name – optional name under which to register.

  • force – overloads even unnanotable functions

Returns:

the wrapper function

pyoload.resove_annotations(obj: Callable) None

Evaluates all the stringized annotations of the argument

Parameters:

obj – The object of which to evaluate annotations

Returns:

None

pyoload.type_match(val: Any, spec: Type | PyoloadAnnotation) tuple

recursively checks if type matches

Parameters:
  • val – The value to typecheck

  • spec – The type specifier

Returns:

A tuple of the match status and the optional errors

pyoload.unannotable(func: Callable) Callable

Marks a function to be not annotable, the function will then not be wrapped by annotate or multimethod, except force=True argument specified.

pyoload.unannotate(func: Callable) Callable

Returns the underlying function returned by annotate, if not annotated it returns the passed function.

Parameters:

func – the function to unwrap

Returns:

The unwrapped function