Skip to content

bagof.converters.common

Common converters (any, union, etc.).

Classes

ToAny

ToAny(hint: Any = UNSET, compose: bool = False)

Bases: Converter[TO, FROM]

Converter for Any (no-op, returns the value as-is).

Methods:

__call__
__call__(value: FROM) -> TO

Return the value unchanged.

ToNone

ToNone(hint: Any = UNSET, compose: bool = False)

Bases: Converter[NONE, Any]

Converter for None.

Methods:

like
like(__reentrant: tuple = ()) -> Any

Accept only None.

__call__
__call__(value: Any) -> NONE

Return the value if it is None, otherwise raise a TypeError.

ToType

ToType(hint: Any = UNSET, compose: bool = False)

Bases: Converter[TO, FROM]

Converter for type and Type[T].

Note

This is a validating converter: it does not coerce, it checks that the value is a class (and, for Type[T], a subclass of T).

Methods:

like
like(__reentrant: tuple = ()) -> Any

Accept a class.

__call__
__call__(value: FROM) -> TO

Return the value if it is a (sufficiently specific) type.

ToUnion

ToUnion(hint: Any = UNSET, compose: bool = False)

Bases: Converter[TO, FROM]

Converter for Union.

None is preserved when the union contains a None branch. Otherwise, converters for branches that already match the value are tried before the remaining branches, in declaration order. Matching a container's outer type still runs its element converters.

A narrower branch (a sub hint of a matched branch) with a refining converter (refines=True, e.g. enums and literals) is tried before matched branches. The first successful conversion wins.

Refinement

>>> import enum
>>> from typing import Union
>>> from bagof.converters import get_converter
>>> class Mode(str, enum.Enum):
...     A = "a"
>>> convert = get_converter(Union[Mode, str])
>>> convert("a")        # a str, but refined to the enum member
<Mode.A: 'a'>
>>> convert("zzz")      # not a member: kept as a str
'zzz'
>>> get_converter(Union[bool, int])(1)  # bool does not refine
1

Example

>>> from bagof.converters import get_converter
>>> convert = get_converter(int | str)
>>> convert("5")        # already a str
'5'
>>> convert(5)          # already an int
5
>>> convert(b"5")       # matches neither; the first that converts
5

Methods:

like
like(__reentrant: tuple = ()) -> Any

Return the union of the like hints for each union branch.

__call__
__call__(value: FROM) -> TO

Try each branch of the union in order; raise if none succeeds.

ToLiteral

ToLiteral(hint: Any = UNSET, compose: bool = False)

Bases: Converter[TO, FROM]

Converter for Literal.

Methods:

like
like(__reentrant: tuple = ()) -> Any

Return the literal hint itself.

__call__
__call__(value: FROM) -> TO

Return the matching literal; raise if the value is not one.

ToTypeVar

ToTypeVar(hint: Any = UNSET, compose: bool = False)

Bases: Converter[TO, FROM]

Converter for TypeVar.

Methods:

like
like(__reentrant: tuple = ()) -> Any

Return the like hint for the unwrapped TypeVar bound.

__call__
__call__(value: FROM) -> TO

Delegate to the converter for the unwrapped TypeVar.

ToAnnotated

ToAnnotated(hint: Any = UNSET, compose: bool = False)

Bases: Converter[TO, FROM]

Converter for Annotated.

Note

Annotated converters look for converters in the metadata of an annotated type hint and apply them in sequence (if they are composable).

Attributes

converters property
converters: tuple[Converter, ...]

The chain of converters derived from the Annotated metadata.

Methods:

register_metadata classmethod
register_metadata(*hints: Unpack[tuple[Any, ...]]) -> ClassDecorator

Register a converter class for use as Annotated metadata.

Distinct from Converter.register, which registers a converter for a type hint in the global registry; this one registers it for a piece of Annotated metadata.

Example

@ToAnnotated.register_metadata(re.Pattern)
class ToRegexMatch(ToString):
    ...
like
like(__reentrant: tuple = ()) -> Any

Return the like hint from the first converter in the chain.

__call__
__call__(value: FROM) -> TO

Apply each converter in the chain in sequence.