bagof.core.magic
Attributes
UNION_TYPES
module-attribute
The union spellings this package understands.
REAL_TYPES
module-attribute
The real-number types eq_safenan recognises.
UNSET
module-attribute
A value that indicates that an argument was not set.
Note
This is different from None, which may be a valid value.
Classes
MagicHint
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
The type hint that this magic object is bound to.
DEFAULT
class-attribute
instance-attribute
The default type hint for this magic object.
FALLBACK
class-attribute
instance-attribute
UNWRAP
class-attribute
instance-attribute
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.
has_explicit_hint
property
Whether a hint was passed to the constructor.
False when the object fell back to its DEFAULT - which is
not the same as carrying a hint that happens to equal it.
unwrapped
property
origin
property
args
property
Methods:
rebind
Return a copy of this object describing a different hint.
Every other attribute is carried over, so a configured object
keeps its configuration - a threshold, a pattern, a length. The
memoised properties listed in [_CACHED][bagof.core.magic.MagicHint._CACHED] are recomputed.
error
Build a MagicError for the given value and message.
The error is returned, not raised, so that the caller keeps
the raise and its traceback starts where the failure is:
Tip
Subclasses override this to build their own error type.
MultipleCauses
MagicError
Functions:
get_concrete_type
Get a valid concrete type from a type hint.
- If the hint is annotated, the
Annotatedwrapper 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
- the first of its constraints is 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
TypeErroris 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
TypeErroris raised.
Note
A constrained typevar has no single concrete type - it stands for
the union of its constraints - so the first constraint is taken,
the same way get_default takes the first value of a
Literal.
get_default
Get a default value from a type hint.
- If the hint is a
Literal, the first value in the literal is returned (None, ifNoneis one of the literal's values). - If the hint is a
Unionthat containsNoneType,Noneis 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
TypeErroris raised. A factory should then be used.
get_from_registry
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.
Exact matches are by hint equality, so List[int] and list[int]
are different keys, but Union[int, str] and Union[str, int] are the
same one.
issubclassable
is_typeddict
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.
typeddict_required_keys
The required keys of a TypedDict.
Reads __required_keys__ where the class has it -- the only source
that accounts for Required /
NotRequired (in either nesting with
Annotated) and for inheriting from bases
declared with a different total=.
Falls back to __total__ where it does not:
typing.TypedDict gained __required_keys__ only in Python 3.9,
and before that a key's requiredness came from the class's total=
alone -- per-key Required/NotRequired did not exist.
Warning
On older Pythons, a typing.TypedDict that inherits from a
base declared with a different total= reports every
inherited key as required. The stdlib does not record which class
declared a key, nor a usable link back to the base -- a subclass
has no __orig_bases__ and its __mro__ reaches only
dict - so the true answer is not recoverable.
The error is in the safe direction: a required key that is really
optional makes a valid value fail loudly, rather than letting an
invalid one through. Use
typing_extensions.TypedDict, which reimplements
the class precisely to fix this, when it matters.
safe_issubclass
safe_isinstance
Safe isinstance (does not fail if second argument is not a type).
ishintstance
Like isinstance, but the second argument can be a type hint.
- If
hintistypeorType[...], checks thatobjis a type and that it is valid subclass of the hint argument. - If
hintis aLiteral, checks thatobjis one of its values. The value must match in type as well:Trueis not a validLiteral[1], even thoughTrue == 1. - If
hintis aUnion, checksobjagainst each of its members. - Otherwise, returns
issubhint(type(obj), hint).
Warning
A container's item types are not checked: a value carries its
type, and a type carries no arguments, so [1, 2] is a
valid List[str] as far as this function is concerned.
(Python itself refuses isinstance(x, list[int]) for the
same reason.) Checking the items means iterating them, which is
the caller's decision to make - bagof.validators does it.
issubhint
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.
Arguments are compared covariantly, so List[bool] is a
subhint of List[int]. A hint with no arguments is not a
subhint of one that has them - a bare list may hold
anything, so it cannot stand in for a List[int].
Note
An unparametrised Union or Literal asks
a different question: is this hint one of those? So
issubhint(int, Union) is False (an
int is not a union) even though
issubhint(int, Union[int, str]) is True.
This makes them usable as a BOUND, and it is why the
relation is not transitive through a bare Union.
unwrap
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, its (union of) constraints, or its bound -
in that order.
safe_get_origin
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
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 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
Safe version of tx.get_args that unwraps
Annotated hints.
Returns an empty tuple if the input is not a generic type.
eq_safenan
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 all mapped to one
sentinel (so that two NaNs compare equal), while every other value is
returned unchanged.
Note
Only real numbers are recognised. A complex NaN is returned unchanged, and so still compares unequal to itself.
issubscriptable
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.
type2hint
Convert a type to a (subscriptable) type hint.
- If the input is a type, and it does not have
__class_getitem__, we try to find its corresponding type hint. For example, in python 3.8,type2hint(list)returnstyping.List. - Otherwise, the value is returned as is.