Skip to content

bagof.core.magic

Attributes

UNSET module-attribute

UNSET = Unset()

A value that indicates that an argument was not set.

Note

This is different from None, which may be a valid value.

Classes

MagicHint

MagicHint(hint: Any = UNSET)

Bases: Generic[T]

Base class for magic objects (factories, converters).

Parameters:

Name Type Description Default
hint Any

The type hint to use for this magic object. If not provided, the default hint for the class is used.

UNSET

Attributes

BOUND class-attribute instance-attribute
BOUND = tx.Any

The type hint that this magic object is bound to.

DEFAULT class-attribute instance-attribute
DEFAULT = tx.Any

The default type hint for this magic object.

FALLBACK class-attribute instance-attribute
FALLBACK = UNSET

A concrete fallback type, used when the type hint does not resolve to a concrete class - for example, when it is an abstract class, or a bare typing construct (such as Union or Literal) with no concrete origin of its own.

UNWRAP class-attribute instance-attribute
UNWRAP: Tuple[Any, ...] = (tx.Annotated, tx.TypeVar)

The hints that unwrapped, origin and args transparently unwrap before introspecting [hint][bagof.core.magic.MagicHint.hint].

Note

A TypeVar is resolved to its default, its (union of) constraints, or its bound - in that order - so that a typevar is introspected exactly like the hint it stands for. This matches fallback, which resolves typevars through get_concrete_type.

Set to (tx.Annotated,) to opt out and introspect typevars as-is.

unwrapped property
unwrapped: Any

The unwrapped type hint, with any hint listed in UNWRAP (by default, Annotated wrappers and TypeVars) removed.

origin property
origin: Any

The "safe" origin of the type hint

  • Any hint listed in UNWRAP is removed (by default, Annotated wrappers and TypeVars).
  • If the origin is None, the hint itself is returned.
args property
args: Tuple[Any, ...]

The "safe" arguments of the type hint

  • Any hint listed in UNWRAP is removed (by default, Annotated wrappers and TypeVars).
  • If the origin is None, returns an empty tuple.
fallback property
fallback: Any

A "concrete" fallback type for the type hint, if possible.

Methods:

__call__
__call__(*args, **kwargs) -> T

Do some magic!

Subclasses must implement this method.

error
error(message: str, value: Any = UNSET, **kwargs) -> MagicError

Raise a MagicError with the given value and message.

MultipleCauses

MultipleCauses(causes: Iterable[Exception])

Bases: Exception

A wrapper exception that contains multiple causes.

MagicError

MagicError(*args, **kwargs)

Bases: Exception

An exception raised by magic objects (factories, converters).

Other Parameters:

Name Type Description
this MagicHint

The MagicHint instance that raised the error.

value Any

The value that caused the error.

Methods:

Functions:

get_concrete_type

get_concrete_type(hint: Any, fallback: type = UNSET) -> tx.Type[tx.Any]

Get a valid concrete type from a type hint.

  • If the hint is annotated, the Annotated wrapper is removed.
  • If the hint has an origin, it is used.
  • If the hint is a TypeVar:
    • its default value is used, if it has one; otherwise
    • its constraints are used, if it has any; otherwise
    • its bound is used, if it has one; otherwise
    • the fallback type is used, if it is provided; otherwise
    • a TypeError is raised.
  • If the (resolved) hint is a concrete, non-abstract type, it is returned as is; otherwise
  • The fallback type is used, if it is provided; otherwise
  • A TypeError is raised.

get_default

get_default(hint: Any) -> tx.Any

Get a default value from a type hint.

  • If the hint is a Literal, the first value in the literal is returned (None, if None is one of the literal's values).
  • If the hint is a Union that contains NoneType, None is returned.
  • Otherwise, if the hint is a Union, we recurse through its sub-hints and return the first default found.
  • If no default value can be found, a TypeError is raised. A factory should then be used.

get_from_registry

get_from_registry(hint: Any, registry: dict) -> tx.Any

Get the best matching value from a registry whose keys are types or type hints.

The best match is the registry key that is the narrowest superclass (or superhint) of hint, following its MRO; exact matches are always preferred. If hint is Annotated and no match is found for it directly, the search is retried against its unwrapped hint.

Example

>>> registry = {int: "number", object: "any"}
>>> get_from_registry(bool, registry)
'number'
>>> get_from_registry(str, registry)
'any'

issubclassable

issubclassable(cls: Any) -> bool

Return true if an object is a type or is TypedDict.

Tip

This function differs from isinstance(cls, type) in that it returns True for TypedDict and its subclasses, even though they are not technically types.

is_typeddict

is_typeddict(cls: Any) -> bool

Return true if an object is a TypedDict or a subclass of it.

Tip

This function differs from typing.is_typeddict in that it returns True for TypedDict itself.

safe_issubclass

safe_issubclass(subcls: Any, cls: Any) -> bool

Safe subclass (does not fail if arguments are not types).

Warning

If cls is a TypedDict, this function looks at subcls's __orig_bases__, instead of its __bases__.

Example

>>> safe_issubclass(bool, int)
True
>>> safe_issubclass(int, "not a type")  # no error
False

safe_isinstance

safe_isinstance(obj: Any, cls: Any) -> bool

Safe isinstance (does not fail if second argument is not a type).

Warning

If cls is a TypedDict, this function looks at the obj's __orig_bases__, instead of its __bases__.

Example

>>> safe_isinstance(1, int)
True
>>> safe_isinstance(1, "not a type")  # no error
False

ishintstance

ishintstance(obj: Any, hint: Any) -> bool

Like isinstance, but the second argument can be a type hint.

  • If hint is type or Type[...], checks that obj is a type and that it is valid subclass of the hint argument.
  • Otherwise, returns issubhint(type(obj), hint).

issubhint

issubhint(hint: Any, superhint: Any) -> bool

Check that a hint is a sub-hint for another hint.

A hint is a valid subhint if all values that are valid for the hint are also valid for the superhint.

Example

>>> from typing import Union
>>> issubhint(bool, int)
True
>>> issubhint(Union[int, str], Union[int, str, bytes])
True
>>> issubhint(int, str)
False

unwrap

unwrap(hint: Any, origin: Any = (tx.Annotated,)) -> tx.Any

Unwrap a type hint from its origin, if it is in the unwrap list.

If TypeVar is one of the origins to unwrap, it will be unwrapped to its default, bound, or (union of) constraints.

Example

>>> from typing import Annotated
>>> unwrap(Annotated[int, "meta"])
<class 'int'>
>>> unwrap(Annotated[Annotated[str, 1], 2])
<class 'str'>
>>> unwrap(int)  # unchanged
<class 'int'>

safe_get_origin

safe_get_origin(hint: Any, unwrap: Any = ()) -> tx.Any

Safe version of tx.get_origin.

Can also unwrap some hints (e.g. Annotated) if asked.

Note

Unlike typing.get_origin, this returns the input hint itself, instead of None, when the hint is not a generic type.

get_origin_uw

get_origin_uw(hint: Any) -> tx.Any

Safe version of tx.get_origin that unwraps Annotated hints.

Returns the input type, instead of None, if the input is not a generic type.

safe_get_args

safe_get_args(hint: Any, unwrap: Any = ()) -> tx.Tuple[tx.Any, ...]

Safe version of tx.get_args.

Returns an empty tuple if the input is not a generic type. Can also unwrap some hints (e.g. Annotated) if asked.

get_args_uw

get_args_uw(hint: Any) -> tx.Tuple[tx.Any, ...]

Safe version of tx.get_args that unwraps Annotated hints.

Returns an empty tuple if the input is not a generic type.

eq_safenan

eq_safenan(x: Any) -> bool

Map a value to a form that compares equal across NaNs.

Since float("nan") != float("nan"), comparing values that may contain NaN with == is unsafe. Apply this function to both operands before comparing them: real NaN values are mapped to the string "NaN" (so that two NaNs compare equal), while every other value is returned unchanged.

issubscriptable

issubscriptable(x: Any) -> bool

Check that an object is subscriptable (i.e. can be used with []).

True if the object is a type and has __class_getitem__, or if it is an instance and has __getitem__. Otherwise, returns False.