The Register
- class strcs.CreateRegister
The register is a central object that holds knowledge of how to transform data into different types. It is used to get a decorator that is used to add those creators and also used to then do a conversion:
Usage looks like:
import strcs reg = strcs.CreateRegister() creator = reg.make_decorator() # Then the creator may be used as a decorator to add knowledge about custom # transformations # Then objects may be created instance = reg.create(MyKls, some_data)
- create(typ: type[T] | strcs.Type[T], value: object = strcs.NotSpecified, meta: strcs.Meta | None = None, once_only_creator: strcs.ConvertFunction[T] | None = None) T
Create an instance of the specified type by transforming the provided value.
If no
meta
is provided, then an empty meta is created.If
once_only_creator
is provided then it will be used as the entry point for conversion.
- create_annotated(typ: type[T] | strcs.Type[T],, ann: MetaAnnotation | MergedMetaAnnotation | AdjustableMeta | AdjustableCreator | ConvertFunction[T], value: object = strcs.NotSpecified, meta: strcs.Meta | None = None, once_only_creator: strcs.ConvertFunction[T] | None = None) T
This is the same as
reg.create
but the type will be wrapped with the provided annotation.
- make_decorator() strcs.Creator
Return an object that can be used to register Creators:
import attrs import strcs reg = strcs.CreateRegister() creator = reg.make_decorator() @attrs.define class Thing: one: int @creator(Thing) def make_thing(value: object, /) -> strcs.ConvertResponse[Thing]: ... thing = reg.create(Thing, ...)
The decorator is instantiated with the object the creator should be making. As well as optional a boolean called
assume_unchanged_converted
which defaults to True.When
assume_unchanged_converted
is True then the creator is not called if the value is already the desired type. If it is False then it will always be called.
Multiple registers
It is easy to have multiple registers as the creator functions can ask for the
current register with the special _register: strcs.CreateRegister
in the
signature:
import attrs
import strcs
reg = strcs.CreateRegister()
creator = reg.make_decorator()
@attrs.define
class MyKls:
one: int
@creator(MyKls)
def create_mykls(value: object, /, _register: strcs.CreateRegister) -> bool:
assert _register is reg
return True
instance = reg.create(MyKls, {"one": 2})
assert isinstance(instance, MyKls)
Resolving type annotations
There is a limitation whereby unresolved string type annotations will cause
errors as strcs
won’t know what object the string represents. strcs
offers a helper
function based off typing.get_type_hints
for resolving string type
annotations. It will automatically be used on any class that strcs
needs to work with
unless the auto_resolve_string_annotations=False
is given to strcs.CreateRegister
.
- strcs.resolve_types(cls: C, globalns: dict[str, object] | None = None, localns: dict[str, object] | None = None, *, type_cache: Union[CreateRegister, TypeCache]) C
Resolve any strings and forward annotations in type annotations.
This is equivalent to
attrs.resolve_types
except it doesn’t erase Annotations.It is automatically used by
strcs.CreateRegister
unless theauto_resolve_string_annotations=False
option is used when it’s created.Assumes that the string annotations have been defined when you call this function:
import attrs # or ``dataclasses`` equivalent import strcs @attrs.define class One: two: "Two" @attrs.define class Two: ... strcs.resolve_types(One)
Note that if
from __future__ import annotations
is used then all types are strings and require resolution. In that case if auto resolution on the register is turned off thenstrcs.resolve_types
may be used as a decorator in any situation where types are already available at definition:from __future__ import annotations import attrs import strcs @strcs.resolve_types class Stuff: one: int @attrs.define class Thing: stuff: "Stuff" other: "Other" @strcs.resolve_types @attrs.define class Other: thing: Thing | None strcs.resolve_types(Thing)
Note
Calling resolve_types will modify the fields on the class in place.