Application Programming Interface#

Types#

class plum.type.ModuleType(module, name, allow_fail=False)[source]#

A type from another module.

Parameters:
  • module (str) – Module that the type lives in.

  • name (str) – Name of the type that is promised.

  • allow_fail (bool, optional) – If the type is does not exist in module, do not raise an AttributeError.

retrieve()[source]#

Attempt to retrieve the type from the reference module.

Returns:

Whether the retrieval succeeded.

Return type:

bool

class plum.type.PromisedType(name='SomeType')[source]#

A type that is promised to be available when you will you need it.

Parameters:

name (str, optional) – Name of the type that is promised. Defaults to “SomeType”.

plum.type.is_faithful(x)[source]#

Check whether a type hint is faithful.

A type or type hint t is defined _faithful_ if, for all x, the following holds true:

isinstance(x, x) == issubclass(type(x), t)

You can control whether types are faithful or not by setting the attribute __faithful__:

class UnfaithfulType:
    __faithful__ = False
Parameters:

x (type or type hint) – Type hint.

Returns:

Whether x is faithful or not.

Return type:

bool

plum.type.resolve_type_hint(x)[source]#

Resolve all ResolvableType in a type or type hint.

Parameters:

x (type or type hint) – Type hint.

Returns:

x, but with all ResolvableTypes resolved.

Return type:

type or type hint

plum.type.type_mapping = {}#

When running resolve_type_hint(), map keys in this dictionary to the values.

Type:

dict

Signatures#

class plum.signature.Signature(*types: ~typing.Tuple[object, ...], varargs: ~typing.Union[object, ~plum.util._MissingType] = <class 'plum.util.Missing'>, precedence: int = 0)[source]#

Object representing a call signature that may be used to dispatch a function call.

This object differs structurally from the return value of inspect.signature() as it only contains information necessary for performing dispatch.

For example, for the current implementation of Plum, which does not dispatch on keyword arguments, those are left out of this signature object. Similarly, return type information and argument names are not present.

types#

Types of the call signature.

Type:

tuple[TypeHint, …]

varargs#

Type of the variable number of arguments.

Type:

type or util.Missing

has_varargs#

Whether varargs is not util.Missing.

Type:

bool

precedence#

Precedence.

Type:

int

is_faithful#

Whether this signature only uses faithful types.

Type:

bool

compute_distance(values: Tuple[object, ...]) int[source]#

For given values, computes the edit distance between these vales and this signature.

Parameters:

values (tuple[object, ...]) – Values.

Returns:

Edit distance.

Return type:

int

compute_mismatches(values: Tuple) Tuple[Set[int], bool][source]#

For given values, find the indices of the arguments that are mismatched. Also return whether the varargs is matched.

Parameters:

values (tuple[object, ...]) – Values.

Returns:

Indices of invalid values. bool: Whether the varargs was matched or not.

Return type:

set[int]

expand_varargs(n: int) Tuple[object, ...][source]#

Expand variable arguments.

Parameters:

n (int) – Desired number of types.

Returns:

Expanded types.

Return type:

tuple[type, …]

static from_callable(f: Callable, precedence: int = 0) Signature[source]#

Construct a signature from a callable.

Parameters:
  • f (Callable) – Callable.

  • precedence (int, optional) – Precedence. Defaults to 0.

Returns:

Signature for f.

Return type:

Signature

match(values: Tuple) bool[source]#

Check whether values match the signature.

Parameters:

values (tuple) – Values.

Returns:

True if values match this signature and False otherwise.

Return type:

bool

plum.signature.append_default_args(signature: Signature, f: Callable) List[Signature][source]#

Returns a list of signatures of function f, where those signatures are derived from the input arguments of f by treating every non-keyword-only argument with a default value as a keyword-only argument turn by turn.

Parameters:
  • f (function) – Function to extract default arguments from.

  • signature (signature.Signature) – Signature of f from which to remove default arguments.

Returns:

List of signatures excluding from no to all

default arguments.

Return type:

list[signature.Signature]

Methods#

class plum.method.Method(implementation: Callable, signature: Signature, *, function_name: Optional[str] = None, return_type: Optional[object] = None)[source]#

Method.

return_type#

Return type.

Type:

type

implementation#

Implementation.

Type:

function or None

repr_mismatch(mismatches: Set[int] = frozenset({}), varargs_matched: bool = True) str[source]#

Version of __repr__ that can print which arguments are mismatched. This is mainly used in hints.

Parameters:
  • mismatches (set[int], optional) – Indices of the positional arguments which are mismatched. Defaults to no mismatched arguments.

  • varargs_matched (bool, optional) – Whether the varargs are matched. Defaults to True.

Returns:

rich representation of the method showing which arguments are mismatched.

Return type:

list

plum.method.extract_return_type(f: Callable) object[source]#

Extract the return type from a function.

Assumes that PEP563-style already have been resolved.

Parameters:

f (function) – Function to extract return type from.

Returns:

Return type annotation

Return type:

TypeHint

Functions#

class plum.function.Function(f: Callable, owner: Optional[str] = None, warn_redefinition: bool = False)[source]#

A function.

Parameters:
  • f (function) – Function that is wrapped.

  • owner (str, optional) – Name of the class that owns the function.

  • warn_redefinition (bool, optional) – Throw a warning whenever a method is redefined. Defaults to False.

clear_cache(reregister: bool = True) None[source]#

Clear cache.

Parameters:

reregister (bool, optional) – Also reregister all methods. Defaults to True.

dispatch(method: Optional[Callable] = None, precedence=0) Union[Self, Callable[[Callable], Self]][source]#

Decorator to extend the function with another signature.

Parameters:

precedence (int, optional) – Precedence of the signature. Defaults to 0.

Returns:

Decorator.

Return type:

function

dispatch_multi(*signatures: Union[Signature, Tuple[object, ...]]) Callable[[Callable], Self][source]#

Decorator to extend the function with multiple signatures at once.

Parameters:

*signatures (tuple or signature.Signature) – Signatures to register.

Returns:

Decorator.

Return type:

function

invoke(*types: object) Callable[source]#

Invoke a particular method.

Parameters:

*types – Types to resolve.

Returns:

Method.

Return type:

function

property methods: List[Signature]#

All available methods.

Type:

list[signature.Signature]

property owner#

Owner of the function. If None, then there is no owner.

Type:

object or None

register(f: Callable, signature: Optional[Signature] = None, precedence=0) None[source]#

Register a method.

Either signature or precedence must be given.

Parameters:
  • f (function) – Function that implements the method.

  • signature (signature.Signature, optional) – Signature. If it is not given, it will be derived from f.

  • precedence (int, optional) – Precedence of the function. If signature is given, then this argument will not be used. Defaults to 0.

resolve_method(target: Union[Tuple[object, ...], Signature]) Tuple[Callable, object][source]#

Find the method and return type for arguments.

Parameters:

target (object) – Target.

Returns:

  • Method.

  • Return type.

Return type:

tuple[function, type]

Dispatchers#

class plum.dispatcher.Dispatcher(warn_redefinition: bool = False, functions: ~typing.Dict[str, ~plum.function.Function] = <factory>, classes: ~typing.Dict[str, ~typing.Dict[str, ~plum.function.Function]] = <factory>)[source]#

A namespace for functions.

Parameters:

warn_redefinition (bool, optional) – Throw a warning whenever a method is redefined. Defaults to False.

functions#

Functions by name.

Type:

dict[str, function.Function]

classes#

Methods of all classes by the qualified name of a class.

Type:

dict[str, dict[str, function.Function]]

warn_redefinition#

Throw a warning whenever a method is redefined.

Type:

bool

abstract(method: Callable) Function[source]#

Decorator for an abstract function definition. The abstract function definition does not implement any methods.

clear_cache()[source]#

Clear cache.

multi(*signatures: Union[Signature, Tuple[object, ...]]) Callable[[Callable], Function][source]#

Decorator to register multiple signatures at once.

Parameters:

*signatures (tuple or signature.Signature) – Signatures to register.

Returns:

Decorator.

Return type:

function

plum.dispatcher.clear_all_cache()[source]#

Clear all cache, including the cache of subclass checks. This should be called if types are modified.

plum.dispatcher.dispatch = Dispatcher(warn_redefinition=False, functions={}, classes={})#

A default dispatcher for convenience purposes.

exception plum.resolver.AmbiguousLookupError(f_name: Optional[str], target: Union[Tuple, Signature], methods: MethodList)[source]#

A signature cannot be resolved due to ambiguity.

exception plum.resolver.NotFoundLookupError(f_name: Optional[str], target: Union[Tuple, Signature], methods: MethodList, *, max_suggestions: int = 3)[source]#

A signature cannot be resolved because no applicable method can be found.

This error object is used to display the closest methods to the target signature.

Parametric Classes#

class plum.parametric.CovariantMeta[source]#

A metaclass that implements covariance of parametric types.

class plum.parametric.Kind(*args, **kw_args)#

A default kind provided for convenience.

plum.parametric.kind(SuperClass=<class 'object'>)[source]#

Create a parametric wrapper type for dispatch purposes.

Parameters:

SuperClass (type) – Super class.

Returns:

New parametric type wrapper.

Return type:

object

plum.parametric.parametric(original_class=None)[source]#

A decorator for parametric classes.

When the constructor of this parametric type is called before the type parameter has been specified, the type parameter is inferred from the arguments of the constructor by calling __inter_type_parameter__. The default implementation is shown here, but it is possible to override it:

@classmethod
def __infer_type_parameter__(cls, *args, **kw_args) -> tuple:
    return tuple(type(arg) for arg in args)

After the type parameter is given or inferred, __init_type_parameter__ is called. Again, the default implementation is show here, but it is possible to override it:

@classmethod
def __init_type_parameter__(cls, *ps) -> tuple:
    return ps

To determine which one instance of a parametric class is a subclass of another, the type parameters are compared with __le_type_parameter__:

@classmethod
def __le_type_parameter__(cls, left, right) -> bool:
    # Is `left <= right`?
    ...
plum.parametric.type_nonparametric(q: T) Type[T][source]#

Return the non-parametric type of an object.

plum.parametric produces parametric subtypes of classes. This method can be used to get the original non-parametric type of an object.

See also

plum.type_unparametrized()

A function that returns the non-concrete, but still parametric, type of an object.

Examples

In this example we will demonstrate how to retrieve the original non-parametric class from a plum.parametric() decorated class.

plum.parametric() defines a parametric class of the same name as the original class, and then creates a subclass of the original class with the type parameter inferred from the arguments of the constructor.

>>> from plum import parametric
>>> class Obj:
...     @classmethod
...     def __infer_type_parameter__(cls, *arg):
...         return type(arg[0])
...
...     def __init__(self, x):
...         self.x = x
...
...     def __repr__(self):
...         return f"Obj({self.x})"
>>> PObj = parametric(Obj)
>>> pobj = PObj(1)
>>> type(pobj).mro()
[<class 'plum.parametric.Obj[int]'>, <class 'plum.parametric.Obj'>,
 <class 'plum.parametric.Obj'>, <class 'object'>]

Note that the class Obj appears twice in the MRO. The first one is the parametric class, and the second one is the non-parametric class. The non-parametric class is the original class that was passed to the parametric decorator.

Rather than navigating the MRO, we can get the non-parametric class of an object by calling type_nonparametric function.

>>> type(pobj) is PObj[int]
True
>>> type(pobj) is PObj
False
>>> type(pobj) is Obj
False
>>> type_nonparametric(pobj) is PObj[int]
False
>>> type_nonparametric(pobj) is PObj
False
>>> type_nonparametric(pobj) is Obj
True
plum.parametric.type_parameter(x)[source]#

Get the type parameter of concrete parametric type or an instance of a concrete parametric type.

Parameters:

x (object) – Concrete parametric type or instance thereof.

Returns:

Type parameter.

Return type:

object

plum.parametric.type_unparametrized(q: T) Type[T][source]#

Return the unparametrized type of an object.

plum.parametric produces parametric subtypes of classes. This function can be used to get the un-parametrized type of an object. This function also works for normal, plum.parametric-wrapped classes.

See also

plum.type_nonparametric()

A function to get the non-parametric type of an object.

Examples

In this example we will demonstrate how to retrieve the original non-parametric class from a plum.parametric() decorated class.

plum.parametric() defines a parametric class of the same name as the original class, and then creates a subclass of the original class with the type parameter inferred from the arguments of the constructor.

>>> from plum import parametric
>>> class Obj:
...     @classmethod
...     def __infer_type_parameter__(cls, *arg):
...         return type(arg[0])
...
...     def __init__(self, x):
...         self.x = x
...
...     def __repr__(self):
...         return f"Obj({self.x})"
>>> PObj = parametric(Obj)
>>> pobj = PObj(1)
>>> type(pobj).mro()
[<class 'plum.parametric.Obj[int]'>, <class 'plum.parametric.Obj'>,
 <class 'plum.parametric.Obj'>, <class 'object'>]

Note that the class Obj appears twice in the MRO. The first one is the non-concrete parametric class, and the second one is the non-parametric class. Rather than navigating the MRO, we can get the non-concrete parametric class of an object by calling the type_unparametrized function.

>>> type(pobj) is PObj[int]
True
>>> type(pobj) is PObj
False
>>> type(pobj) is Obj
False
>>> type_unparametrized(pobj) is PObj[int]
False
>>> type_unparametrized(pobj) is PObj
True
>>> type_unparametrized(pobj) is Obj
False

Note that this is still NOT the ‘original’ non-plum.parametric()-wrapped type. This is the type that is wrapped by plum.parametric, but without the inferred type parameter(s).

Promotion and Conversion#

Promotion and conversion functions.

plum.promotion.add_conversion_method(type_from: Type[T], type_to: Type[R], f: _ConversionCallable[T, R]) None[source]#

Add a conversion method to convert an object from one type to another.

Parameters:
  • type_from (type) – Type to convert from.

  • type_to (type) – Type to convert to.

  • f (function) – Function that converts an object of type type_from to type type_to.

plum.promotion.add_promotion_rule(type1, type2, type_to)[source]#

Add a promotion rule.

Parameters:
  • type1 (type) – First type to promote.

  • type2 (type) – Second type to promote.

  • type_to (type) – Type to convert to.

plum.promotion.conversion_method(type_from: Type[T], type_to: Type[R]) Callable[[_ConversionCallable[T, R]], _ConversionCallable[T, R]][source]#

Decorator to add a conversion method to convert an object from one type to another.

Parameters:
  • type_from (type) – Type to convert from.

  • type_to (type) – Type to convert to.

plum.promotion.convert(obj, type_to)[source]#

Convert an object to a particular type.

Parameters:
  • obj (object) – Object to convert.

  • type_to (type) – Type to convert to.

Returns:

obj converted to type type_to.

Return type:

object

plum.promotion.promote(obj1, obj2, *objs)[source]#

Promote objects to a common type.

Parameters:

*objs (object) – Objects to convert.

Returns:

objs, but all converted to a common type.

Return type:

tuple

plum.promotion.promote(obj: object)[source]
plum.promotion.promote()[source]

Union Aliases#

This module monkey patches __repr__ and __str__ of typing.Union to control how typing.Unions are displayed.

Example:

>> plum.activate_union_aliases()

>> IntOrFloat = typing.Union[int, float]

>> IntOrFloat
Union[int, float]

>> plum.set_union_alias(IntOrFloat, "IntOrFloat")

>> IntOrFloat
typing.Union[IntOrFloat]

>> typing.Union[int, float]
typing.Union[IntOrFloat]

>> typing.Union[int, float, str]
typing.Union[IntOrFloat, str]

Note that IntOrFloat prints to typing.Union[IntOrFloat] rather than just IntOrFloat. This is deliberate, with the goal of not breaking code that relies on parsing how unions print.

plum.alias.activate_union_aliases() None[source]#

When printing typing.Union`s, replace all aliased unions by the aliased names. This monkey patches `__repr__ and __str__ for typing.Union.

plum.alias.deactivate_union_aliases() None[source]#

Undo what alias.activate() did. This restores the original __repr__ and __str__ for typing.Union.

plum.alias.set_union_alias(union: UnionT, alias: str) UnionT[source]#

Change how a typing.Union is printed. This does not modify union.

Parameters:
  • union (type or type hint) – A union.

  • alias (str) – How to print union.

Returns:

union.

Return type:

type or type hint

iPython AutoReload#

plum.autoreload.activate_autoreload()[source]#

Pirate Autoreload’s update_instance function to have Plum work with Autoreload.

plum.autoreload.deactivate_autoreload()[source]#

Disable Plum’s autoreload hack. This undoes what autoreload.activate_autoreload() did.

Other Utilities#

plum.repr.repr_pyfunction(f: Callable) Text[source]#

Create a rich.Text object representation a function, including a link to the source definition created with repr_source_path().

Parameters:

f (Callable) – A function.

Returns:

Representation of f.

Return type:

rich.Text

plum.repr.repr_short(x) str[source]#

Representation as a string, but in shorter form. This just calls typing._type_repr().

Parameters:

x (object) – Object.

Returns:

Shorter representation of x.

Return type:

str

plum.repr.repr_source_path(function: Callable) Text[source]#

Create a rich.Text object with an hyperlink to the function definition.

Parameters:

function (Callable) – A function.

Returns:

Representation with a hyperlink to the source. If the introspection failed, it returns None.

Return type:

rich.Text or None

plum.repr.repr_type(x) Text[source]#

Returns a rich.Text representation of a type or module.

Does some light syntax highlighting mimicking Julia, boldening class names and coloring module names with a lighter color.

Parameters:

x (object) – Type or module.

Returns:

Representation.

Return type:

rich.Text

plum.repr.rich_repr(cls: Optional[Type[T]] = None, str: bool = False) Type[T][source]#

Class decorator defining a __repr__ method that calls rich.

This also sets _repr_mimebundle_ for better rendering in Jupyter.

Parameters:
  • cls (type, optional) – Class to decorate. If None, this function returns a decorator.

  • str (bool, optional) – Also define __str__. Defaults to not defining __str__

Returns:

The decorated class. If cls is None, returns a decorator.

class plum.util.Comparable[source]#

A mixin that makes instances of the class comparable.

Requires the subclass to just implement __le__.

is_comparable(other)[source]#

Check whether this object is comparable with another one.

Parameters:

other (object) – Object to check comparability with.

Returns:

Whether the object is comparable with other.

class plum.util.Missing[source]#

A class that can be used to indicate that a value is missing. This class cannot be instantiated and has no boolean value.

plum.util.TypeHint#

alias of object

plum.util.argsort(seq: Sequence) List[int][source]#

Compute the indices that sort a sequence.

Parameters:

seq (Sequence) – Sequence to sort.

Returns:

Indices that sort seq.

Return type:

list[int]

plum.util.get_class(f: Callable) str[source]#

Assuming that f is part of a class, get the fully qualified name of the class.

Parameters:

f (function) – Method to get class name for.

Returns:

Fully qualified name of class.

Return type:

str

plum.util.get_context(f) str[source]#

Get the fully qualified name of the context for f.

If f is part of a class, then the context corresponds to the scope of the class. If f is not part of a class, then the context corresponds to the scope of the function.

Parameters:

f (function) – Method to get context for.

Returns:

The context of f.

Return type:

str

plum.util.is_in_class(f: Callable) bool[source]#

Check if a function is part of a class.

Parameters:

f (function) – Function to check.

Returns:

Whether f is part of a class.

Return type:

bool

plum.util.wrap_lambda(f: Callable) Callable[source]#

Wrap a callable in a lambda function.

Parameters:

f (Callable) – Function to wrap.

Returns:

Wrapped version of f.

Return type:

function