diff --git a/docs/strcs/changelog.rst b/docs/strcs/changelog.rst index 6fb0695..6687759 100644 --- a/docs/strcs/changelog.rst +++ b/docs/strcs/changelog.rst @@ -3,6 +3,14 @@ Changelog --------- +.. _release-0.4.0: + +0.4.0 - TBD + * Add a ``disassemble`` method to the type cache and implemented ``disassemble`` + on ``strcs.Type`` using it. Note that the signature also changes to no + longer have an "expect" but also it's smarter about the resulting Type + it returns. + .. _release-0.3.0: 0.3.0 - 17 September 2023 diff --git a/docs/strcs/features/disassembled.rst b/docs/strcs/features/disassembled.rst index b809f0c..74e9336 100644 --- a/docs/strcs/features/disassembled.rst +++ b/docs/strcs/features/disassembled.rst @@ -25,6 +25,9 @@ Types :member-order: bysource .. autoclass:: strcs.TypeCache + :members: disassemble + +.. autoprotocol:: strcs.disassemble.Disassembler .. autoclass:: strcs.MRO :members: diff --git a/strcs/annotations.py b/strcs/annotations.py index c2ab191..9d22010 100644 --- a/strcs/annotations.py +++ b/strcs/annotations.py @@ -235,7 +235,7 @@ def adjusted_meta(self, meta: Meta, typ: Type[T], type_cache: TypeCache) -> Meta clone = meta.clone() for field in attrs.fields(self.meta.__class__): # type:ignore if not field.name.startswith("_"): - optional = Type.create(field.type, cache=type_cache).optional + optional = type_cache.disassemble(field.type).optional val = getattr(self.meta, field.name) if not optional or val is not None: clone[field.name] = val diff --git a/strcs/decorator.py b/strcs/decorator.py index 52a8966..ae62e42 100644 --- a/strcs/decorator.py +++ b/strcs/decorator.py @@ -262,11 +262,11 @@ def deal(res: ConvertResponse[T], value: object) -> T: return tp.cast(T, value) else: if not isinstance(res, Mapping) and issubclass( - want.checkable, Type.create(type(res), cache=self.type_cache).checkable + want.checkable, self.type_cache.disassemble(type(res)).checkable ): raise errors.SupertypeNotValid( want=want.checkable, - got=Type.create(type(res), cache=self.type_cache).checkable, + got=self.type_cache.disassemble(type(res)).checkable, reason="A Super type is not a valid value to convert", ) diff --git a/strcs/disassemble/__init__.py b/strcs/disassemble/__init__.py index e02d5e8..e9ab4a2 100644 --- a/strcs/disassemble/__init__.py +++ b/strcs/disassemble/__init__.py @@ -1,4 +1,4 @@ -from ._base import Type +from ._base import Disassembler, Type from ._cache import TypeCache from ._creation import fill, instantiate from ._extract import IsAnnotated, extract_annotation, extract_optional @@ -15,6 +15,7 @@ from ._type_tree import MRO, HasOrigBases __all__ = [ + "Disassembler", "Type", "TypeCache", "IsAnnotated", diff --git a/strcs/disassemble/_base.py b/strcs/disassemble/_base.py index 4f6085c..095c72b 100644 --- a/strcs/disassemble/_base.py +++ b/strcs/disassemble/_base.py @@ -49,6 +49,8 @@ class Type(tp.Generic[T]): typ = strcs.Type.create(int, cache=type_cache) typ2 = strcs.Type.create(int | None, cache=type_cache) + typ3 = type_cache.disassemble(int | None) + typ4 = typ.disassemble(int | None) ... """ @@ -77,6 +79,15 @@ class Missing(MissingType): init=False, factory=lambda: {}, repr=False, order=False, hash=False ) + disassemble: "Disassembler" = attrs.field( + init=False, + default=attrs.Factory(lambda s: s.cache.disassemble, takes_self=True), + repr=False, + order=False, + hash=False, + ) + """Object for creating new Type classes without having to pass around the type cache""" + original: object "The original object being wrapped" @@ -275,13 +286,6 @@ def __gte__(self, other: object) -> bool: return self.score >= other.score - def disassemble(self, expect: type[U], typ: object) -> "Type[U]": - """ - Return a new :class:`strcs.Type` for the provided object using the - type cache on this instance. - """ - return Type.create(typ, expect=expect, cache=self.cache) - def reassemble( self, resolved: object, *, with_annotation: bool = True, with_optional: bool = True ) -> object: @@ -394,7 +398,7 @@ def nonoptional_union_types(self) -> tuple["Type", ...]: for origin in origins: if origin is None: continue - ds.append(self.disassemble(object, origin)) + ds.append(self.disassemble(origin)) union = tuple(sorted(ds, key=lambda d: d.score, reverse=True)) @@ -546,7 +550,7 @@ def is_equivalent_type_for(self, value: object) -> tp.TypeGuard[T]: if isinstance(value, type): subclass_of = value else: - subclass_of = self.disassemble(object, type(value)).checkable + subclass_of = self.disassemble(type(value)).checkable return issubclass(subclass_of, self.checkable) @memoized_property @@ -659,3 +663,37 @@ def checkable(self) -> type[InstanceCheck]: This is memoized. """ return create_checkable(self) + + +class Disassembler(tp.Protocol): + """ + Used to disassemble some type using an existing type cache + """ + + type_cache: "TypeCache" + + @tp.overload + def __call__(self, typ: type[U]) -> "Type[U]": + ... + + @tp.overload + def __call__(self, typ: Type[U]) -> "Type[U]": + ... + + @tp.overload + def __call__(self, typ: object) -> "Type[object]": + ... + + def __call__(self, typ: type[U] | object) -> "Type[U] | Type[object]": + """ + Used to disassemble some type using an existing type cache + + Pass in expect to alter the type that the static type checker sees + """ + + def typed(self, expect: type[U], typ: object) -> "Type[U]": + """ + Return a new :class:`strcs.Type` for the provided object using this + type cache and the expected type. + """ + ... diff --git a/strcs/disassemble/_cache.py b/strcs/disassemble/_cache.py index 5c9e183..e728767 100644 --- a/strcs/disassemble/_cache.py +++ b/strcs/disassemble/_cache.py @@ -2,7 +2,43 @@ from collections.abc import MutableMapping if tp.TYPE_CHECKING: - from ._base import Type + from ._base import Disassembler, Type + +U = tp.TypeVar("U") + + +class _TypeCacheDisassembler: + def __init__(self, type_cache: "TypeCache"): + from ._base import Type + + self.Type = Type + self.type_cache = type_cache + + @tp.overload + def __call__(self, typ: type[U]) -> "Type[U]": + ... + + @tp.overload + def __call__(self, typ: "Type[U]") -> "Type[U]": + ... + + @tp.overload + def __call__(self, typ: object) -> "Type[object]": + ... + + def __call__(self, typ: type[U] | object) -> "Type[U] | Type[object]": + """ + Return a new :class:`strcs.Type` for the provided object using this + type cache + """ + return self.Type.create(typ, expect=object, cache=self.type_cache) + + def typed(self, expect: type[U], typ: object) -> "Type[U]": + """ + Return a new :class:`strcs.Type` for the provided object using this + type cache and the expected type. + """ + return self.Type.create(typ, expect=expect, cache=self.type_cache) class TypeCache(MutableMapping[object, "Type"]): @@ -19,7 +55,7 @@ class TypeCache(MutableMapping[object, "Type"]): type_cache = strcs.TypeCache() - typ = strcs.Type.create(int, cache=type_cache) + typ = type_cache.disassemble(int) assert type_cache[int] is typ assert int in type_cache @@ -34,8 +70,12 @@ class TypeCache(MutableMapping[object, "Type"]): type_cache.clear() """ - def __init__(self): - self.cache = {} + disassemble: "Disassembler" + """Used to create new Types using this type cache""" + + def __init__(self) -> None: + self.cache: dict[tuple[type, object], "Type"] = {} + self.disassemble = _TypeCacheDisassembler(self) def key(self, o: object) -> tuple[type, object]: return (type(o), o) diff --git a/strcs/disassemble/_instance_check.py b/strcs/disassemble/_instance_check.py index 511fbfd..2aaba5a 100644 --- a/strcs/disassemble/_instance_check.py +++ b/strcs/disassemble/_instance_check.py @@ -136,7 +136,7 @@ class Meta(InstanceCheck.Meta): if tp.get_origin(Meta.extracted) in union_types: check_against = tuple( - disassembled.disassemble(object, a).checkable for a in tp.get_args(Meta.extracted) + disassembled.disassemble(a).checkable for a in tp.get_args(Meta.extracted) ) Meta.typ = Meta.extracted @@ -303,7 +303,7 @@ def __subclasscheck__(cls, C: type) -> bool: if not issubclass(C, check_against): return False - want = disassembled.disassemble(object, C) + want = disassembled.disassemble(C) for w, g in zip(want.mro.all_vars, disassembled.mro.all_vars): if isinstance(w, Type) and isinstance(g, Type): if not issubclass(w.checkable, g.checkable): diff --git a/strcs/disassemble/_type_tree.py b/strcs/disassemble/_type_tree.py index 976ff93..075afa0 100644 --- a/strcs/disassemble/_type_tree.py +++ b/strcs/disassemble/_type_tree.py @@ -77,7 +77,7 @@ class MRO: type_cache = strcs.TypeCache() - typ = strcs.Type.create(my_code.my_class, cache=type_cache) + typ = type_cache.disassemble(my_code.my_class) mro = typ.mro """ @@ -108,7 +108,7 @@ def create(cls, start: object | None, type_cache: TypeCache) -> "MRO": mro = () if origin is None or not hasattr(origin, "__mro__") else origin.__mro__ orig_bases = HasOrigBases.determine_orig_bases(origin, mro) - bases = [Type.create(base, expect=object, cache=type_cache) for base in orig_bases] + bases = [type_cache.disassemble(base) for base in orig_bases] return cls( _start=start, _origin=origin, _args=args, _mro=mro, _bases=bases, _type_cache=type_cache @@ -157,7 +157,7 @@ class Two(tp.Generic[U], One[U]): pass type_cache = strcs.TypeCache() - typevars = strcs.Type.create(Two, cache=type_cache).mro.typevars + typevars = type_cache.disassemble(Two).mro.typevars Will result in having: @@ -242,7 +242,7 @@ def all_vars(self) -> tuple[Type | type[Type.Missing], ...]: result: list[Type | type[Type.Missing]] = [] typevars = list(self.typevars.items()) if self.args and not typevars and self.origin not in union_types: - return tuple(Type.create(arg, cache=self.type_cache) for arg in self.args) + return tuple(self.type_cache.disassemble(arg) for arg in self.args) found: set[tuple[type, tp.TypeVar | int]] = set() @@ -258,7 +258,7 @@ def all_vars(self) -> tuple[Type | type[Type.Missing], ...]: typed: Type | type[Type.Missing] if value is not Type.Missing: - typed = Type.create(value, cache=self.type_cache) + typed = self.type_cache.disassemble(value) else: typed = Type.Missing @@ -291,9 +291,9 @@ class Two(tp.Generic[U], One[U]): type_cache = strcs.TypeCache() - typ1 = strcs.Type.create(One, cache=type_cache) - typ2 = strcs.Type.create(One[int], cache=type_cache) - typ3 = strcs.Type.create(Two[str], cache=type_cache) + typ1 = type_cache.disassemble(One) + typ2 = type_cache.disassemble(One[int]) + typ3 = type_cache.disassemble(Two[str]) assert typ1.mro.signature_for_display == "~T" assert typ2.mro.signature_for_display == "int" @@ -321,7 +321,7 @@ class Two(tp.Generic[U], One[U]): if value is Type.Missing: result.append(repr(tv)) else: - result.append(Type.create(value, cache=self.type_cache).for_display()) + result.append(self.type_cache.disassemble(value).for_display()) return ", ".join(result) @@ -340,7 +340,7 @@ def raw_fields(self) -> tp.Sequence[Field]: """ result: list[Field] = [] for cls in reversed(self.mro): - disassembled = Type.create(cls, expect=object, cache=self.type_cache) + disassembled: Type[object] = self.type_cache.disassemble(cls) fields = disassembled.raw_fields for field in fields: @@ -352,7 +352,7 @@ def raw_fields(self) -> tp.Sequence[Field]: f.default = field.default f.kind = field.kind - f.disassembled_type = Type.create(field.type, cache=self.type_cache) + f.disassembled_type = self.type_cache.disassemble(field.type) f.owner = cls found = True break @@ -376,7 +376,7 @@ def fields(self) -> tp.Sequence[Field]: for field in self.raw_fields: field_type = field.type - field_type_info = Type.create(field_type, expect=object, cache=self.type_cache) + field_type_info = self.type_cache.disassemble(field_type) extracted = field_type_info.extracted if isinstance(extracted, tp.TypeVar): @@ -384,7 +384,7 @@ def fields(self) -> tp.Sequence[Field]: if isinstance(field_type, tp.TypeVar): replacement = typevars[ - (Type.create(field.original_owner, cache=self.type_cache).checkable, field_type) + (self.type_cache.disassemble(field.original_owner).checkable, field_type) ] if isinstance(replacement, self.Referal): replacement = replacement.value @@ -394,7 +394,7 @@ def fields(self) -> tp.Sequence[Field]: field_type = object field_type = field_type_info.reassemble(field_type) - fields.append(field.with_replaced_type(Type.create(field_type, cache=self.type_cache))) + fields.append(field.with_replaced_type(self.type_cache.disassemble(field_type))) return fields @@ -433,8 +433,8 @@ class One(tp.Generic[T]): type_cache = strcs.TypeCache() - typ1 = strcs.Type.create(One[B], cache=type_cache) - typ2 = strcs.Type.create(One[C], cache=type_cache) + typ1 = type_cache.disassemble(One[B]) + typ2 = type_cache.disassemble(One[C]) assert typ1.mro.find_subtypes(A) == (B, ) assert typ2.mro.find_subtypes(A) == (C, ) @@ -455,11 +455,11 @@ class One(tp.Generic[T]): f"The type has less typevars ({len(self.typevars)}) than wanted ({len(want)})" ) - typ = Type.create(typevars[(owner, tv)], expect=object, cache=self.type_cache) + typ = self.type_cache.disassemble(typevars[(owner, tv)]) if not issubclass( typ.checkable, - Type.create(wa, cache=self.type_cache).checkable, + self.type_cache.disassemble(wa).checkable, ): raise ValueError( f"The concrete type {typ} is not a subclass of what was asked for {wa}" diff --git a/strcs/hints.py b/strcs/hints.py index 23009c5..b306689 100644 --- a/strcs/hints.py +++ b/strcs/hints.py @@ -305,9 +305,7 @@ class Other: value = tp.ForwardRef(value, is_argument=False, is_class=True) if name in allfields: - from .disassemble import Type - - disassembled = Type.create(value, cache=type_cache, expect=object) + disassembled = type_cache.disassemble(value) resolved = resolve_type(disassembled.extracted, base_globals, base_locals) if value != resolved and value in type_cache: diff --git a/strcs/hooks.py b/strcs/hooks.py index ba32da3..788342b 100644 --- a/strcs/hooks.py +++ b/strcs/hooks.py @@ -134,7 +134,7 @@ def convert(self, value: object, typ: type[T] | Type[T]) -> T: if isinstance(typ, Type): want = typ else: - want = Type.create(typ, cache=self.type_cache) + want = self.type_cache.disassemble(typ) normal_creator = want.func_from(list(self.register.register.items())) @@ -157,10 +157,8 @@ def convert(self, value: object, typ: type[T] | Type[T]) -> T: creator = want.ann.adjusted_creator(creator, self.register, want, self.type_cache) if meta is not self.meta: return self.register.create( - Type.create( - want.without_annotation, - expect=type(want.extracted), - cache=self.type_cache, + self.type_cache.disassemble.typed( + type(want.extracted), want.without_annotation ), value, meta=meta, diff --git a/strcs/meta.py b/strcs/meta.py index 5d4cbe7..2265317 100644 --- a/strcs/meta.py +++ b/strcs/meta.py @@ -7,7 +7,7 @@ import cattrs from . import errors -from .disassemble import Type, TypeCache +from .disassemble import TypeCache T = tp.TypeVar("T") U = tp.TypeVar("U") @@ -208,7 +208,7 @@ def find_by_type( if typ is object: return False, data - disassembled = Type.create(typ, cache=type_cache, expect=object) + disassembled = type_cache.disassemble(typ) optional = disassembled.optional typ = disassembled.checkable available: dict[str, object] = {n: v for n, v in data.items() if isinstance(v, typ)} diff --git a/strcs/register.py b/strcs/register.py index 886f90c..6798625 100644 --- a/strcs/register.py +++ b/strcs/register.py @@ -85,6 +85,7 @@ def __init__( self.last_meta = last_meta self.last_type = last_type self.type_cache = type_cache + self.disassemble = type_cache.disassemble self.skip_creator = skip_creator self.auto_resolve_string_annotations = auto_resolve_string_annotations @@ -107,18 +108,13 @@ def clone( ) def __setitem__(self, specification: type[T] | Type[T], creator: ConvertFunction[T]) -> None: - self.register[Type.create(specification, cache=self.type_cache)] = creator + self.register[self.type_cache.disassemble(specification)] = creator def __contains__(self, typ: type | Type[T]) -> bool: if not isinstance(typ, (type, Type)): raise ValueError("Can only check against types or Type instances") - return ( - Type.create(typ, expect=object, cache=self.type_cache).func_from( - list(self.register.items()) - ) - is not None - ) + return self.type_cache.disassemble(typ).func_from(list(self.register.items())) is not None def make_decorator(self) -> Creator: """ @@ -172,17 +168,17 @@ def __call__( ) -> ConvertDefinition[T] | None: if not isinstance(self.original, Type): - typ: Type[T] = Type.create(self.original, cache=register.type_cache) + typ = register.type_cache.disassemble(self.original) else: typ = self.original self.wrapped = WrappedCreator[T]( - typ, + tp.cast(Type[T], typ), func, type_cache=register.type_cache, assume_unchanged_converted=self.assume_unchanged_converted, ) - self.typ = typ + self.typ = tp.cast(Type[T], typ) self.func = self.wrapped.func register[typ] = self.wrapped @@ -210,7 +206,7 @@ def create( if isinstance(typ, Type): want = typ else: - want = Type.create(typ, cache=self.type_cache) + want = self.type_cache.disassemble(typ) return CreateStructureHook.structure( register=self, @@ -243,7 +239,7 @@ def create_annotated( if isinstance(typ, Type): want = typ else: - want = Type.create(tp.Annotated[typ, ann], cache=self.type_cache) + want = tp.cast(Type[T], self.type_cache.disassemble(tp.Annotated[typ, ann])) return CreateStructureHook.structure( register=self, diff --git a/tests/disassemble/conftest.py b/tests/disassemble/conftest.py new file mode 100644 index 0000000..f7bcfbd --- /dev/null +++ b/tests/disassemble/conftest.py @@ -0,0 +1,13 @@ +import pytest + +import strcs + + +@pytest.fixture() +def type_cache() -> strcs.TypeCache: + return strcs.TypeCache() + + +@pytest.fixture() +def Dis(type_cache: strcs.TypeCache) -> strcs.disassemble.Disassembler: + return type_cache.disassemble diff --git a/tests/disassemble/test_base.py b/tests/disassemble/test_base.py index 48d4230..e8ed151 100644 --- a/tests/disassemble/test_base.py +++ b/tests/disassemble/test_base.py @@ -21,23 +21,7 @@ from .test_helpers import assertParams - -@pytest.fixture() -def type_cache() -> strcs.TypeCache: - return strcs.TypeCache() - - -class Disassembler: - def __init__(self, type_cache: strcs.TypeCache): - self.type_cache = type_cache - - def __call__(self, typ: object) -> strcs.Type: - return Type.create(typ, cache=self.type_cache) - - -@pytest.fixture() -def Dis(type_cache: strcs.TypeCache) -> Disassembler: - return Disassembler(type_cache) +Disassembler = strcs.disassemble.Disassembler class Partial: @@ -759,7 +743,10 @@ def __init__(self, four: str): ((Blah, U), bool), ((Stuff, T), str), ((Thing, T), int), - ((Thing, U), strcs.MRO.Referal(owner=Stuff, typevar=T, value=str)), + ( + (Thing, U), + strcs.MRO.Referal(owner=Stuff, typevar=tp.cast(tp.TypeVar, T), value=str), + ), ] ) assert disassembled.mro.all_vars == (bool, int, str) @@ -1048,7 +1035,7 @@ class Thing: resolve_types(Thing, globals(), locals(), type_cache=type_cache) - disassembled = Type.create(Thing, expect=Thing, cache=type_cache) + disassembled = Dis(Thing) assert disassembled.fields == [ Field(name="stuff", owner=Thing, disassembled_type=Dis(Stuff | None)) ] @@ -1059,7 +1046,7 @@ class Thing: def __init__(self, one: int, /, two: str, *, three: bool = False, **kwargs): pass - disassembled = Type.create(Thing, expect=Thing, cache=type_cache) + disassembled = Dis(Thing) assert disassembled.fields_getter == Partial(fields_from_class, type_cache) assert disassembled.fields_from is Thing assertParams( @@ -1101,7 +1088,7 @@ class Thing: two: str = "one" three: bool = attrs.field(kw_only=True, default=False) - disassembled = Type.create(Thing, expect=Thing, cache=type_cache) + disassembled = Dis(Thing) assert disassembled.fields_getter == Partial(fields_from_attrs, type_cache) assert disassembled.fields_from is Thing assertParams( @@ -1138,7 +1125,7 @@ class Thing: two: str = "one" three: bool = dataclasses.field(kw_only=True, default=False) - disassembled = Type.create(Thing, expect=Thing, cache=type_cache) + disassembled = Dis(Thing) assert disassembled.fields_getter == Partial(fields_from_dataclasses, type_cache) assert disassembled.fields_from is Thing assertParams( @@ -1168,29 +1155,29 @@ class Thing: ) describe "annotations": - it "can return no annotation", type_cache: strcs.TypeCache: - assert Type.create(int, cache=type_cache).ann is None - assert Type.create(int | None, cache=type_cache).ann is None - assert Type.create(int | str, cache=type_cache).ann is None - assert Type.create(int | str | None, cache=type_cache).ann is None - assert Type.create(list[int], cache=type_cache).ann is None - assert Type.create(list[int] | None, cache=type_cache).ann is None + it "can return no annotation", Dis: Disassembler: + assert Dis(int).ann is None + assert Dis(int | None).ann is None + assert Dis(int | str).ann is None + assert Dis(int | str | None).ann is None + assert Dis(list[int]).ann is None + assert Dis(list[int] | None).ann is None class Thing: pass - assert Type.create(Thing, cache=type_cache).ann is None + assert Dis(Thing).ann is None - it "can return an annotation with new creator", type_cache: strcs.TypeCache: + it "can return an annotation with new creator", Dis: Disassembler: def creator(value: object, /, _meta: strcs.Meta): ... - ann = Type.create(tp.Annotated[int, creator], expect=int, cache=type_cache).ann + ann = Dis(tp.Annotated[int, creator]).ann assert isinstance(ann, strcs.Ann) assert ann.creator is creator - it "can return an annotation with new adjustable meta", type_cache: strcs.TypeCache: + it "can return an annotation with new adjustable meta", type_cache: strcs.TypeCache, Dis: Disassembler: class AdjustMeta: @classmethod @@ -1200,50 +1187,50 @@ def adjusted_meta( return meta.clone({"one": 1}) adjustment = AdjustMeta() - ann = Type.create(tp.Annotated[int, adjustment], expect=int, cache=type_cache).ann + ann = Dis(tp.Annotated[int, adjustment]).ann assert ann is adjustment assert isinstance(ann, strcs.AdjustableMeta) meta = strcs.Meta({"two": 2}) - m = ann.adjusted_meta(meta, Type.create(int, cache=type_cache), type_cache) + m = ann.adjusted_meta(meta, Dis(int), type_cache) assert m.data == {"one": 1, "two": 2} assert meta.data == {"two": 2} - it "can return an annotation with new MetaAnnotation", type_cache: strcs.TypeCache: + it "can return an annotation with new MetaAnnotation", type_cache: strcs.TypeCache, Dis: Disassembler: @attrs.define class Info(strcs.MetaAnnotation): three: str info = Info(three="three") - ann = Type.create(tp.Annotated[int, info], expect=int, cache=type_cache).ann + ann = Dis(tp.Annotated[int, info]).ann assert isinstance(ann, strcs.Ann), ann assert ann.creator is None assert ann.meta is info meta = strcs.Meta({"two": 2}) - m = ann.adjusted_meta(meta, Type.create(int, cache=type_cache), type_cache) + m = ann.adjusted_meta(meta, Dis(int), type_cache) assert m.data == {"__call_defined_annotation__": info, "two": 2} assert meta.data == {"two": 2} - it "can return an annotation with new MergedMetaAnnotation", type_cache: strcs.TypeCache: + it "can return an annotation with new MergedMetaAnnotation", type_cache: strcs.TypeCache, Dis: Disassembler: @attrs.define class Info(strcs.MergedMetaAnnotation): three: str info = Info(three="three") - ann = Type.create(tp.Annotated[int, info], expect=int, cache=type_cache).ann + ann = Dis(tp.Annotated[int, info]).ann assert isinstance(ann, strcs.Ann), ann assert ann.creator is None assert ann.meta is info meta = strcs.Meta({"two": 2}) - m = ann.adjusted_meta(meta, Type.create(int, cache=type_cache), type_cache) + m = ann.adjusted_meta(meta, Dis(int), type_cache) assert m.data == {"three": "three", "two": 2} assert meta.data == {"two": 2} - it "can return an annotation with new Ann", type_cache: strcs.TypeCache: + it "can return an annotation with new Ann", type_cache: strcs.TypeCache, Dis: Disassembler: def creator1(args: strcs.CreateArgs[int]) -> int: return 2 @@ -1258,61 +1245,58 @@ def adjusted_meta( return meta.clone({"one": 1}) a = A(creator=creator2) - ann = Type.create(tp.Annotated[int, a], expect=int, cache=type_cache).ann + ann = Dis(tp.Annotated[int, a]).ann assert isinstance(ann, strcs.Ann), ann assert ann is a meta = strcs.Meta({"two": 2}) - m = ann.adjusted_meta(meta, Type.create(int, cache=type_cache), type_cache) + m = ann.adjusted_meta(meta, Dis(int), type_cache) assert m.data == {"one": 1, "two": 2} assert meta.data == {"two": 2} reg = strcs.CreateRegister() - assert ( - ann.adjusted_creator(creator1, reg, Type.create(int, cache=type_cache), type_cache) - == creator2 - ) + assert ann.adjusted_creator(creator1, reg, Dis(int), type_cache) == creator2 describe "equality": - it "matches any Type against Type.Missing", type_cache: strcs.TypeCache: - typ = strcs.Type.create(int, expect=object, cache=type_cache) + it "matches any Type against Type.Missing", Dis: Disassembler: + typ = Dis(int) assert typ == strcs.Type.Missing - typ2 = strcs.Type.create(tp.Annotated[None, 1], expect=object, cache=type_cache) + typ2 = Dis(tp.Annotated[None, 1]) assert typ2 == strcs.Type.Missing class Thing: pass - typ3 = strcs.Type.create(Thing | None, expect=object, cache=type_cache) + typ3 = Dis(Thing | None) assert typ3 == strcs.Type.Missing - it "matches against checkable instances and original type", type_cache: strcs.TypeCache: - typ = strcs.Type.create(int, expect=object, cache=type_cache) + it "matches against checkable instances and original type", Dis: Disassembler: + typ = Dis(int) assert typ == int assert typ == typ.checkable - typ2 = strcs.Type.create(int, expect=object, cache=type_cache) + typ2 = Dis(int) assert typ2 == int assert typ2 == typ.checkable class Thing: pass - typ3 = strcs.Type.create(tp.Annotated[Thing, 1], expect=object, cache=type_cache) + typ3 = Dis(tp.Annotated[Thing, 1]) assert typ3 == Thing assert typ3 == typ3.checkable assert typ3 != typ2.checkable assert typ2 != typ3.checkable - it "matches against optionals", type_cache: strcs.TypeCache: - typ = strcs.Type.create(int, expect=object, cache=type_cache) + it "matches against optionals", Dis: Disassembler: + typ = Dis(int) nun = None assert typ != nun assert typ == int assert typ == typ.checkable - typ2 = strcs.Type.create(int | None, expect=object, cache=type_cache) + typ2 = Dis(int | None) assert typ2 == nun assert typ2 == int assert typ2 == typ.checkable @@ -1320,22 +1304,22 @@ class Thing: class Thing: pass - typ3 = strcs.Type.create(tp.Annotated[Thing | None, 1], expect=object, cache=type_cache) + typ3 = Dis(tp.Annotated[Thing | None, 1]) assert typ3 == Thing assert typ3 == nun assert typ3 == typ3.checkable assert typ3 != typ2.checkable assert typ2 != typ3.checkable - it "matches against unions and partial unions", type_cache: strcs.TypeCache: - typ = strcs.Type.create(int, expect=object, cache=type_cache) + it "matches against unions and partial unions", Dis: Disassembler: + typ = Dis(int) nun = None assert typ != nun assert typ == int assert typ != str assert typ == typ.checkable - typ2 = strcs.Type.create(int | bool | str | None, expect=object, cache=type_cache) + typ2 = Dis(int | bool | str | None) assert typ2 == nun assert typ2 == int assert typ2 == str @@ -1347,9 +1331,7 @@ class Thing: class Thing: pass - typ3 = strcs.Type.create( - tp.Annotated[Thing | bool | None, 1], expect=object, cache=type_cache - ) + typ3 = Dis(tp.Annotated[Thing | bool | None, 1]) assert typ3 == Thing assert typ3 == nun assert typ3 != str @@ -1361,7 +1343,7 @@ class Thing: describe "Finding provided subtype": - it "can find the provided subtype", type_cache: strcs.TypeCache: + it "can find the provided subtype", Dis: Disassembler: class Item: pass @@ -1380,15 +1362,15 @@ class ItemC(Item): class Container(tp.Generic[I]): pass - container_a = strcs.Type.create(Container[ItemA], expect=object, cache=type_cache) - container_b = strcs.Type.create(Container[ItemB], expect=object, cache=type_cache) - container_c = strcs.Type.create(Container[ItemC], expect=object, cache=type_cache) + container_a = Dis(Container[ItemA]) + container_b = Dis(Container[ItemB]) + container_c = Dis(Container[ItemC]) assert container_a.find_generic_subtype(Item) == (ItemA,) assert container_b.find_generic_subtype(Item) == (ItemB,) assert container_c.find_generic_subtype(Item) == (ItemC,) - it "can find multiple subtypes", type_cache: strcs.TypeCache: + it "can find multiple subtypes", Dis: Disassembler: class One: pass @@ -1414,13 +1396,13 @@ class TwoB(Two): class Container(tp.Generic[O, T]): pass - container_a = strcs.Type.create(Container[OneA, TwoB], expect=object, cache=type_cache) - container_b = strcs.Type.create(Container[OneB, TwoB], expect=object, cache=type_cache) + container_a = Dis(Container[OneA, TwoB]) + container_b = Dis(Container[OneB, TwoB]) assert container_a.find_generic_subtype(One, Two) == (OneA, TwoB) assert container_b.find_generic_subtype(One, Two) == (OneB, TwoB) - it "can find a partial number of subtypes", type_cache: strcs.TypeCache: + it "can find a partial number of subtypes", Dis: Disassembler: class One: pass @@ -1446,10 +1428,10 @@ class TwoB(Two): class Container(tp.Generic[O, T]): pass - container_a = strcs.Type.create(Container[OneA, TwoA], expect=object, cache=type_cache) + container_a = Dis(Container[OneA, TwoA]) assert container_a.find_generic_subtype(One) == (OneA,) - it "complains if want too many types", type_cache: strcs.TypeCache: + it "complains if want too many types", Dis: Disassembler: class One: pass @@ -1468,13 +1450,13 @@ class OneB(One): class Container(tp.Generic[O]): pass - container_a = strcs.Type.create(Container[OneA], expect=object, cache=type_cache) + container_a = Dis(Container[OneA]) with pytest.raises( ValueError, match=re.escape("The type has less typevars (1) than wanted (2)") ): container_a.find_generic_subtype(One, Two) - it "complains if want wrong subtype", type_cache: strcs.TypeCache: + it "complains if want wrong subtype", Dis: Disassembler: class One: pass @@ -1493,7 +1475,7 @@ class OneB(One): class Container(tp.Generic[O]): pass - container_a = strcs.Type.create(Container[OneA], expect=object, cache=type_cache) + container_a = Dis(Container[OneA]) with pytest.raises( ValueError, match="The concrete type is not a subclass of what was asked for ", diff --git a/tests/disassemble/test_creation.py b/tests/disassemble/test_creation.py index 4f3a10a..ab1c00c 100644 --- a/tests/disassemble/test_creation.py +++ b/tests/disassemble/test_creation.py @@ -8,34 +8,30 @@ import strcs from strcs.disassemble import fill, instantiate - -@pytest.fixture() -def type_cache() -> strcs.TypeCache: - return strcs.TypeCache() - +Disassembler = strcs.disassemble.Disassembler describe "fill": - it "turns NotSpecified into an empty dictionary", type_cache: strcs.TypeCache: + it "turns NotSpecified into an empty dictionary", Dis: Disassembler: class Thing: pass - want = strcs.Type.create(Thing, expect=object, cache=type_cache) + want = Dis(Thing) assert fill(want, strcs.NotSpecified) == {} - it "complains if res is not a mapping", type_cache: strcs.TypeCache: + it "complains if res is not a mapping", Dis: Disassembler: class Thing: pass - want = strcs.Type.create(Thing, expect=object, cache=type_cache) + want = Dis(Thing) for res in (1, 0, True, False, [], [1], set(), lambda: 1, Thing, Thing()): with pytest.raises(ValueError, match="Can only fill mappings"): fill(want, res) - it "fills in annotated or other objects with NotSpecified", type_cache: strcs.TypeCache: + it "fills in annotated or other objects with NotSpecified", Dis: Disassembler: class Two: pass @@ -48,10 +44,10 @@ class Thing: four: int res = {"four": 1} - want = strcs.Type.create(Thing, expect=object, cache=type_cache) + want = Dis(Thing) assert fill(want, res) == {"one": strcs.NotSpecified, "two": strcs.NotSpecified, "four": 1} - it "doesn't override fields", type_cache: strcs.TypeCache: + it "doesn't override fields", Dis: Disassembler: class Two: pass @@ -65,28 +61,28 @@ class Thing: two = Two() res = {"one": 3, "two": two, "three": True, "four": 1} - want = strcs.Type.create(Thing, expect=object, cache=type_cache) + want = Dis(Thing) assert fill(want, res) == {"one": 3, "two": two, "three": True, "four": 1} describe "instantiate": - it "returns None if the result is optional and res is None", type_cache: strcs.TypeCache: + it "returns None if the result is optional and res is None", Dis: Disassembler: class Thing: pass - want = strcs.Type.create(Thing | None, expect=object, cache=type_cache) + want = Dis(Thing | None) assert instantiate(want, None, cattrs.Converter()) is None - it "returns None if want None and are None", type_cache: strcs.TypeCache: - want = strcs.Type.create(None, expect=object, cache=type_cache) + it "returns None if want None and are None", Dis: Disassembler: + want = Dis(None) assert instantiate(want, None, cattrs.Converter()) is None - it "complains if res is None and we aren't optional or None", type_cache: strcs.TypeCache: + it "complains if res is None and we aren't optional or None", Dis: Disassembler: class Thing: pass - want = strcs.Type.create(Thing, expect=object, cache=type_cache) + want = Dis(Thing) with pytest.raises(ValueError, match="Can't instantiate object with None"): instantiate(want, None, cattrs.Converter()) @@ -174,7 +170,7 @@ def __init__(self, two: Two): thing2 = reg.create(Thing) assert thing2.two == Two(three=True) - it "doesn't care for fields on parents not part of the child", type_cache: strcs.TypeCache: + it "doesn't care for fields on parents not part of the child", Dis: Disassembler: reg = strcs.CreateRegister() class One: @@ -187,24 +183,24 @@ def __init__(self, two: int, three: int): super().__init__(one=2, two=two) self.three = three - want = strcs.Type.create(Two, expect=object, cache=type_cache) + want = Dis(Two) assert want.fields == [ strcs.Field( name="one", - disassembled_type=strcs.Type.create(int, cache=type_cache), + disassembled_type=Dis(int), owner=One, original_owner=One, ), strcs.Field( name="two", - disassembled_type=strcs.Type.create(int, cache=type_cache), + disassembled_type=Dis(int), owner=Two, original_owner=One, ), strcs.Field( name="three", - disassembled_type=strcs.Type.create(int, cache=type_cache), + disassembled_type=Dis(int), owner=Two, original_owner=Two, ), diff --git a/tests/disassemble/test_helpers.py b/tests/disassemble/test_helpers.py index 4e5c3c6..88855f0 100644 --- a/tests/disassemble/test_helpers.py +++ b/tests/disassemble/test_helpers.py @@ -7,7 +7,7 @@ import attrs import pytest -from strcs import Field, Type, TypeCache +import strcs from strcs.disassemble import ( Default, IsAnnotated, @@ -18,26 +18,10 @@ fields_from_dataclasses, ) +Disassembler = strcs.disassemble.Disassembler -class Disassembler: - def __init__(self, type_cache: TypeCache): - self.type_cache = type_cache - def __call__(self, typ: object) -> Type: - return Type.create(typ, cache=self.type_cache) - - -@pytest.fixture() -def type_cache() -> TypeCache: - return TypeCache() - - -@pytest.fixture() -def Dis(type_cache: TypeCache) -> Disassembler: - return Disassembler(type_cache) - - -def assertParams(got: tp.Sequence[Field], want: list[Field]): +def assertParams(got: tp.Sequence[strcs.Field], want: list[strcs.Field]): print("GOT :") for i, g in enumerate(got): print(" ", i, ": ", g) @@ -51,14 +35,14 @@ def assertParams(got: tp.Sequence[Field], want: list[Field]): describe "fields_from_class": - it "finds fields from looking at the init on the class when no init", type_cache: TypeCache: + it "finds fields from looking at the init on the class when no init", type_cache: strcs.TypeCache: class Thing: pass assertParams(fields_from_class(type_cache, Thing), []) - it "finds all kinds of arguments", type_cache: TypeCache, Dis: Disassembler: + it "finds all kinds of arguments", type_cache: strcs.TypeCache, Dis: Disassembler: class Thing: def __init__( @@ -70,31 +54,31 @@ def __init__( assertParams( fields_from_class(type_cache, Thing), [ - Field( + strcs.Field( name="blah", owner=Thing, disassembled_type=Dis(int), kind=inspect.Parameter.POSITIONAL_ONLY, ), - Field( + strcs.Field( name="stuff", owner=Thing, disassembled_type=Dis(str), kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, ), - Field( + strcs.Field( name="", disassembled_type=Dis(str), owner=Thing, kind=inspect.Parameter.VAR_POSITIONAL, ), - Field( + strcs.Field( name="items", disassembled_type=Dis(t), owner=Thing, kind=inspect.Parameter.KEYWORD_ONLY, ), - Field( + strcs.Field( name="", disassembled_type=Dis(bool), owner=Thing, @@ -103,7 +87,7 @@ def __init__( ], ) - it "uses object as type if unknown", type_cache: TypeCache, Dis: Disassembler: + it "uses object as type if unknown", type_cache: strcs.TypeCache, Dis: Disassembler: class Thing: def __init__(self, blah, /, stuff, *args, items, **kwargs): @@ -112,31 +96,31 @@ def __init__(self, blah, /, stuff, *args, items, **kwargs): assertParams( fields_from_class(type_cache, Thing), [ - Field( + strcs.Field( name="blah", disassembled_type=Dis(object), owner=Thing, kind=inspect.Parameter.POSITIONAL_ONLY, ), - Field( + strcs.Field( name="stuff", disassembled_type=Dis(object), owner=Thing, kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, ), - Field( + strcs.Field( name="", disassembled_type=Dis(object), owner=Thing, kind=inspect.Parameter.VAR_POSITIONAL, ), - Field( + strcs.Field( name="items", disassembled_type=Dis(object), owner=Thing, kind=inspect.Parameter.KEYWORD_ONLY, ), - Field( + strcs.Field( name="", disassembled_type=Dis(object), owner=Thing, @@ -145,7 +129,7 @@ def __init__(self, blah, /, stuff, *args, items, **kwargs): ], ) - it "finds defaults", type_cache: TypeCache, Dis: Disassembler: + it "finds defaults", type_cache: strcs.TypeCache, Dis: Disassembler: class Thing: def __init__( @@ -162,34 +146,34 @@ def __init__( assertParams( fields_from_class(type_cache, Thing), [ - Field( + strcs.Field( name="blah", disassembled_type=Dis(int), owner=Thing, default=Default(1), kind=inspect.Parameter.POSITIONAL_ONLY, ), - Field( + strcs.Field( name="stuff", owner=Thing, disassembled_type=Dis(str), default=Default("asdf"), kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, ), - Field( + strcs.Field( name="", owner=Thing, disassembled_type=Dis(str), kind=inspect.Parameter.VAR_POSITIONAL, ), - Field( + strcs.Field( name="items", owner=Thing, disassembled_type=Dis(int | None), default=Default(None), kind=inspect.Parameter.KEYWORD_ONLY, ), - Field( + strcs.Field( name="", owner=Thing, disassembled_type=Dis(int), @@ -198,7 +182,7 @@ def __init__( ], ) - it "doesn't fail on builtin functions", type_cache: TypeCache: + it "doesn't fail on builtin functions", type_cache: strcs.TypeCache: with pytest.raises(ValueError): inspect.signature(str) @@ -206,7 +190,7 @@ def __init__( describe "fields_from_attrs": - it "finds no fields on class with no fields", type_cache: TypeCache: + it "finds no fields on class with no fields", type_cache: strcs.TypeCache: @attrs.define class Thing: @@ -214,7 +198,7 @@ class Thing: assertParams(fields_from_attrs(type_cache, Thing), []) - it "finds keyword only fields", type_cache: TypeCache, Dis: Disassembler: + it "finds keyword only fields", type_cache: strcs.TypeCache, Dis: Disassembler: @attrs.define class Thing: @@ -225,13 +209,13 @@ class Thing: assertParams( fields_from_attrs(type_cache, Thing), [ - Field( + strcs.Field( name="items", owner=Thing, disassembled_type=Dis(t), kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, ), - Field( + strcs.Field( name="stuff", owner=Thing, disassembled_type=Dis(bool), @@ -240,7 +224,7 @@ class Thing: ], ) - it "finds defaults", type_cache: TypeCache, Dis: Disassembler: + it "finds defaults", type_cache: strcs.TypeCache, Dis: Disassembler: @attrs.define class Thing: @@ -251,14 +235,14 @@ class Thing: assertParams( fields_from_attrs(type_cache, Thing), [ - Field( + strcs.Field( name="items", disassembled_type=Dis(t), owner=Thing, default=Default((1, "asdf")), kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, ), - Field( + strcs.Field( name="stuff", disassembled_type=Dis(bool), owner=Thing, @@ -268,7 +252,7 @@ class Thing: ], ) - it "finds default factories", type_cache: TypeCache, Dis: Disassembler: + it "finds default factories", type_cache: strcs.TypeCache, Dis: Disassembler: factory_one = lambda: (1, "asdf") factory_two = lambda: True @@ -282,14 +266,14 @@ class Thing: assertParams( fields_from_attrs(type_cache, Thing), [ - Field( + strcs.Field( name="items", disassembled_type=Dis(t), owner=Thing, default=factory_one, kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, ), - Field( + strcs.Field( name="stuff", disassembled_type=Dis(bool), owner=Thing, @@ -299,7 +283,7 @@ class Thing: ], ) - it "excludes fields that aren't in init", type_cache: TypeCache, Dis: Disassembler: + it "excludes fields that aren't in init", type_cache: strcs.TypeCache, Dis: Disassembler: factory_one = lambda: (1, "asdf") factory_two = lambda: True @@ -314,14 +298,14 @@ class Thing: assertParams( fields_from_attrs(type_cache, Thing), [ - Field( + strcs.Field( name="items", disassembled_type=Dis(t), owner=Thing, default=factory_one, kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, ), - Field( + strcs.Field( name="stuff", disassembled_type=Dis(bool), owner=Thing, @@ -331,7 +315,7 @@ class Thing: ], ) - it "renames private variables", type_cache: TypeCache, Dis: Disassembler: + it "renames private variables", type_cache: strcs.TypeCache, Dis: Disassembler: @attrs.define class Thing: @@ -341,13 +325,13 @@ class Thing: assertParams( fields_from_attrs(type_cache, Thing), [ - Field( + strcs.Field( name="thing", disassembled_type=Dis(str), owner=Thing, kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, ), - Field( + strcs.Field( name="other", disassembled_type=Dis(int), owner=Thing, @@ -360,7 +344,7 @@ class Thing: assert thing._thing == "one" assert thing.other == 4 - it "uses aliases", type_cache: TypeCache, Dis: Disassembler: + it "uses aliases", type_cache: strcs.TypeCache, Dis: Disassembler: if sys.version_info < (3, 11): pytest.skip("pep 681 is from python 3.11") @@ -373,19 +357,19 @@ class Thing: assertParams( fields_from_attrs(type_cache, Thing), [ - Field( + strcs.Field( name="stuff", disassembled_type=Dis(str), owner=Thing, kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, ), - Field( + strcs.Field( name="wat", disassembled_type=Dis(str), owner=Thing, kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, ), - Field( + strcs.Field( name="blah", disassembled_type=Dis(int), owner=Thing, @@ -399,7 +383,7 @@ class Thing: assert thing._thing == "blah" assert thing.other == 3 - it "excludes default factories that take a self", type_cache: TypeCache, Dis: Disassembler: + it "excludes default factories that take a self", type_cache: strcs.TypeCache, Dis: Disassembler: factory_one = lambda: (1, "asdf") factory_two = lambda instance: True @@ -414,14 +398,14 @@ class Thing: assertParams( fields_from_attrs(type_cache, Thing), [ - Field( + strcs.Field( name="items", disassembled_type=Dis(t), owner=Thing, default=factory_one, kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, ), - Field( + strcs.Field( name="stuff", disassembled_type=Dis(bool), owner=Thing, @@ -430,7 +414,7 @@ class Thing: ], ) - it "uses object as type if unknown", type_cache: TypeCache, Dis: Disassembler: + it "uses object as type if unknown", type_cache: strcs.TypeCache, Dis: Disassembler: @attrs.define class Thing: @@ -440,13 +424,13 @@ class Thing: assertParams( fields_from_attrs(type_cache, Thing), [ - Field( + strcs.Field( name="blah", disassembled_type=Dis(object), owner=Thing, kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, ), - Field( + strcs.Field( name="stuff", disassembled_type=Dis(object), owner=Thing, @@ -457,7 +441,7 @@ class Thing: describe "fields_from_dataclasses": - it "finds no fields on class with no fields", type_cache: TypeCache: + it "finds no fields on class with no fields", type_cache: strcs.TypeCache: @dataclasses.dataclass class Thing: @@ -465,7 +449,7 @@ class Thing: assertParams(fields_from_dataclasses(type_cache, Thing), []) - it "finds keyword only fields", type_cache: TypeCache, Dis: Disassembler: + it "finds keyword only fields", type_cache: strcs.TypeCache, Dis: Disassembler: @dataclasses.dataclass class Thing: @@ -476,13 +460,13 @@ class Thing: assertParams( fields_from_dataclasses(type_cache, Thing), [ - Field( + strcs.Field( name="items", owner=Thing, disassembled_type=Dis(t), kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, ), - Field( + strcs.Field( name="stuff", owner=Thing, disassembled_type=Dis(bool), @@ -491,7 +475,7 @@ class Thing: ], ) - it "finds defaults", type_cache: TypeCache, Dis: Disassembler: + it "finds defaults", type_cache: strcs.TypeCache, Dis: Disassembler: @dataclasses.dataclass class Thing: @@ -502,14 +486,14 @@ class Thing: assertParams( fields_from_dataclasses(type_cache, Thing), [ - Field( + strcs.Field( name="items", disassembled_type=Dis(t), owner=Thing, default=Default((1, "asdf")), kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, ), - Field( + strcs.Field( name="stuff", disassembled_type=Dis(bool), owner=Thing, @@ -519,7 +503,7 @@ class Thing: ], ) - it "finds default factories", type_cache: TypeCache, Dis: Disassembler: + it "finds default factories", type_cache: strcs.TypeCache, Dis: Disassembler: factory_one = lambda: (1, "asdf") factory_two = lambda: True @@ -533,14 +517,14 @@ class Thing: assertParams( fields_from_dataclasses(type_cache, Thing), [ - Field( + strcs.Field( name="items", disassembled_type=Dis(t), owner=Thing, default=factory_one, kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, ), - Field( + strcs.Field( name="stuff", disassembled_type=Dis(bool), owner=Thing, @@ -550,7 +534,7 @@ class Thing: ], ) - it "excludes fields that aren't in init", type_cache: TypeCache, Dis: Disassembler: + it "excludes fields that aren't in init", type_cache: strcs.TypeCache, Dis: Disassembler: factory_one = lambda: (1, "asdf") factory_two = lambda: True @@ -565,14 +549,14 @@ class Thing: assertParams( fields_from_dataclasses(type_cache, Thing), [ - Field( + strcs.Field( name="items", disassembled_type=Dis(t), owner=Thing, default=factory_one, kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, ), - Field( + strcs.Field( name="stuff", disassembled_type=Dis(bool), owner=Thing, @@ -582,7 +566,7 @@ class Thing: ], ) - it "doesn't rename private variables", type_cache: TypeCache, Dis: Disassembler: + it "doesn't rename private variables", type_cache: strcs.TypeCache, Dis: Disassembler: @dataclasses.dataclass class Thing: @@ -592,13 +576,13 @@ class Thing: assertParams( fields_from_dataclasses(type_cache, Thing), [ - Field( + strcs.Field( name="_thing", disassembled_type=Dis(str), owner=Thing, kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, ), - Field( + strcs.Field( name="other", disassembled_type=Dis(int), owner=Thing, diff --git a/tests/disassemble/test_instance_check.py b/tests/disassemble/test_instance_check.py index 74109df..48f15d7 100644 --- a/tests/disassemble/test_instance_check.py +++ b/tests/disassemble/test_instance_check.py @@ -8,19 +8,15 @@ import pytest import strcs -from strcs import InstanceCheck, InstanceCheckMeta, Type - -@pytest.fixture() -def type_cache() -> strcs.TypeCache: - return strcs.TypeCache() +Disassembler = strcs.disassemble.Disassembler T = tp.TypeVar("T") describe "InstanceCheck": - it "can find instances and subclasses of basic types", type_cache: strcs.TypeCache: - db = Type.create(int, expect=int, cache=type_cache) + it "can find instances and subclasses of basic types", Dis: Disassembler: + db = Dis(int) assert isinstance(23, db.checkable) assert not isinstance(23.4, db.checkable) assert not isinstance("asdf", db.checkable) @@ -31,29 +27,29 @@ class MyInt(int): assert issubclass(int, db.checkable) assert issubclass(MyInt, db.checkable) - assert issubclass(Type.create(MyInt, cache=type_cache).checkable, db.checkable) + assert issubclass(Dis(MyInt).checkable, db.checkable) class NotMyInt: pass assert not issubclass(NotMyInt, db.checkable) - assert not issubclass(Type.create(NotMyInt, cache=type_cache).checkable, db.checkable) + assert not issubclass(Dis(NotMyInt).checkable, db.checkable) assert not issubclass(float, db.checkable) assert not issubclass(dict, db.checkable) - assert isinstance(db.checkable, InstanceCheckMeta) + assert isinstance(db.checkable, strcs.InstanceCheckMeta) assert isinstance(db.checkable, type) - assert isinstance(db.checkable, Type.create(type, cache=type_cache).checkable) + assert isinstance(db.checkable, Dis(type).checkable) - assert issubclass(db.checkable, InstanceCheck) + assert issubclass(db.checkable, strcs.InstanceCheck) assert not issubclass(db.checkable, type) assert not issubclass(type, db.checkable) - assert not issubclass(Type.create(type, cache=type_cache).checkable, db.checkable) - assert not issubclass(db.checkable, Type.create(type, cache=type_cache).checkable) + assert not issubclass(Dis(type).checkable, db.checkable) + assert not issubclass(db.checkable, Dis(type).checkable) assert not isinstance(db.checkable, int) - assert not isinstance(db.checkable, Type.create(int, cache=type_cache).checkable) + assert not isinstance(db.checkable, Dis(int).checkable) assert not issubclass(db.checkable, NotMyInt) - assert not issubclass(db.checkable, Type.create(NotMyInt, cache=type_cache).checkable) + assert not issubclass(db.checkable, Dis(NotMyInt).checkable) assert db.checkable.Meta.typ == int assert db.checkable.Meta.original == int @@ -61,8 +57,8 @@ class NotMyInt: assert db.checkable.Meta.without_optional == int assert db.checkable.Meta.without_annotation == int - it "can find instances and subclasses of union types", type_cache: strcs.TypeCache: - db = Type.create(int | str, expect=types.UnionType, cache=type_cache) + it "can find instances and subclasses of union types", Dis: Disassembler: + db = Dis(int | str) assert isinstance(23, db.checkable) assert not isinstance(23.4, db.checkable) assert isinstance("asdf", db.checkable) @@ -73,37 +69,37 @@ class MyInt(int): assert issubclass(MyInt, db.checkable) assert issubclass(int, db.checkable) - assert issubclass(Type.create(MyInt, cache=type_cache).checkable, db.checkable) + assert issubclass(Dis(MyInt).checkable, db.checkable) class MyString(str): pass assert issubclass(str, db.checkable) assert issubclass(MyString, db.checkable) - assert issubclass(Type.create(MyString, cache=type_cache).checkable, db.checkable) + assert issubclass(Dis(MyString).checkable, db.checkable) class NotMyInt: pass assert not issubclass(NotMyInt, db.checkable) - assert not issubclass(Type.create(NotMyInt, cache=type_cache).checkable, db.checkable) + assert not issubclass(Dis(NotMyInt).checkable, db.checkable) assert not issubclass(float, db.checkable) assert not issubclass(dict, db.checkable) - assert isinstance(db.checkable, InstanceCheckMeta) + assert isinstance(db.checkable, strcs.InstanceCheckMeta) assert isinstance(db.checkable, type) - assert isinstance(db.checkable, Type.create(type, cache=type_cache).checkable) + assert isinstance(db.checkable, Dis(type).checkable) - assert issubclass(db.checkable, InstanceCheck) + assert issubclass(db.checkable, strcs.InstanceCheck) assert not issubclass(db.checkable, type) assert not issubclass(type, db.checkable) - assert not issubclass(Type.create(type, cache=type_cache).checkable, db.checkable) - assert not issubclass(db.checkable, Type.create(type, cache=type_cache).checkable) + assert not issubclass(Dis(type).checkable, db.checkable) + assert not issubclass(db.checkable, Dis(type).checkable) assert not isinstance(db.checkable, int) - assert not isinstance(db.checkable, Type.create(int, cache=type_cache).checkable) + assert not isinstance(db.checkable, Dis(int).checkable) assert not issubclass(db.checkable, NotMyInt) assert not issubclass(db.checkable, str) - assert not issubclass(db.checkable, Type.create(NotMyInt, cache=type_cache).checkable) + assert not issubclass(db.checkable, Dis(NotMyInt).checkable) assert db.checkable.Meta.typ == int | str assert db.checkable.Meta.original == int | str @@ -111,9 +107,9 @@ class NotMyInt: assert db.checkable.Meta.without_optional == int | str assert db.checkable.Meta.without_annotation == int | str - it "can find instances and subclasses of complicated union type", type_cache: strcs.TypeCache: + it "can find instances and subclasses of complicated union type", Dis: Disassembler: provided = tp.Union[tp.Annotated[list[int], "str"], tp.Annotated[int | str | None, "hello"]] - db = Type.create(provided, expect=types.UnionType, cache=type_cache) + db = Dis(provided) assert isinstance(23, db.checkable) assert not isinstance(23.4, db.checkable) assert isinstance("asdf", db.checkable) @@ -124,37 +120,37 @@ class MyInt(int): assert issubclass(MyInt, db.checkable) assert issubclass(int, db.checkable) - assert issubclass(Type.create(MyInt, cache=type_cache).checkable, db.checkable) + assert issubclass(Dis(MyInt).checkable, db.checkable) class MyString(str): pass assert issubclass(str, db.checkable) assert issubclass(MyString, db.checkable) - assert issubclass(Type.create(MyString, cache=type_cache).checkable, db.checkable) + assert issubclass(Dis(MyString).checkable, db.checkable) class NotMyInt: pass assert not issubclass(NotMyInt, db.checkable) - assert not issubclass(Type.create(NotMyInt, cache=type_cache).checkable, db.checkable) + assert not issubclass(Dis(NotMyInt).checkable, db.checkable) assert not issubclass(float, db.checkable) assert not issubclass(dict, db.checkable) - assert isinstance(db.checkable, InstanceCheckMeta) + assert isinstance(db.checkable, strcs.InstanceCheckMeta) assert isinstance(db.checkable, type) - assert isinstance(db.checkable, Type.create(type, cache=type_cache).checkable) + assert isinstance(db.checkable, Dis(type).checkable) - assert issubclass(db.checkable, InstanceCheck) + assert issubclass(db.checkable, strcs.InstanceCheck) assert not issubclass(db.checkable, type) assert not issubclass(type, db.checkable) - assert not issubclass(Type.create(type, cache=type_cache).checkable, db.checkable) - assert not issubclass(db.checkable, Type.create(type, cache=type_cache).checkable) + assert not issubclass(Dis(type).checkable, db.checkable) + assert not issubclass(db.checkable, Dis(type).checkable) assert not isinstance(db.checkable, int) - assert not isinstance(db.checkable, Type.create(int, cache=type_cache).checkable) + assert not isinstance(db.checkable, Dis(int).checkable) assert not issubclass(db.checkable, NotMyInt) assert not issubclass(db.checkable, str) - assert not issubclass(db.checkable, Type.create(NotMyInt, cache=type_cache).checkable) + assert not issubclass(db.checkable, Dis(NotMyInt).checkable) assert db.checkable.Meta.typ == provided assert db.checkable.Meta.original == provided @@ -162,8 +158,8 @@ class NotMyInt: assert db.checkable.Meta.without_optional == provided assert db.checkable.Meta.without_annotation == provided - it "can find instances and subclasses of optional basic types", type_cache: strcs.TypeCache: - db = Type.create(int | None, expect=int, cache=type_cache) + it "can find instances and subclasses of optional basic types", Dis: Disassembler: + db = Dis(int | None) assert isinstance(23, db.checkable) assert isinstance(None, db.checkable) assert not isinstance(23.4, db.checkable) @@ -173,27 +169,27 @@ class MyInt(int): pass assert issubclass(MyInt, db.checkable) - assert issubclass(Type.create(MyInt, cache=type_cache).checkable, db.checkable) + assert issubclass(Dis(MyInt).checkable, db.checkable) class NotMyInt: pass assert not issubclass(NotMyInt, db.checkable) - assert not issubclass(Type.create(NotMyInt, cache=type_cache).checkable, db.checkable) + assert not issubclass(Dis(NotMyInt).checkable, db.checkable) - assert isinstance(db.checkable, InstanceCheckMeta) + assert isinstance(db.checkable, strcs.InstanceCheckMeta) assert isinstance(db.checkable, type) - assert isinstance(db.checkable, Type.create(type, cache=type_cache).checkable) + assert isinstance(db.checkable, Dis(type).checkable) - assert issubclass(db.checkable, InstanceCheck) + assert issubclass(db.checkable, strcs.InstanceCheck) assert not issubclass(db.checkable, type) assert not issubclass(type, db.checkable) - assert not issubclass(Type.create(type, cache=type_cache).checkable, db.checkable) - assert not issubclass(db.checkable, Type.create(type, cache=type_cache).checkable) + assert not issubclass(Dis(type).checkable, db.checkable) + assert not issubclass(db.checkable, Dis(type).checkable) assert not isinstance(db.checkable, int) - assert not isinstance(db.checkable, Type.create(int, cache=type_cache).checkable) + assert not isinstance(db.checkable, Dis(int).checkable) assert not issubclass(db.checkable, NotMyInt) - assert not issubclass(db.checkable, Type.create(NotMyInt, cache=type_cache).checkable) + assert not issubclass(db.checkable, Dis(NotMyInt).checkable) assert db.checkable.Meta.typ == int assert db.checkable.Meta.original == int | None @@ -201,8 +197,8 @@ class NotMyInt: assert db.checkable.Meta.without_optional == int assert db.checkable.Meta.without_annotation == int | None - it "can find instances and subclasses of annotated types", type_cache: strcs.TypeCache: - db = Type.create(tp.Annotated[int | None, "stuff"], expect=int, cache=type_cache) + it "can find instances and subclasses of annotated types", Dis: Disassembler: + db = Dis(tp.Annotated[int | None, "stuff"]) assert isinstance(23, db.checkable) assert isinstance(None, db.checkable) assert not isinstance(23.4, db.checkable) @@ -212,27 +208,27 @@ class MyInt(int): pass assert issubclass(MyInt, db.checkable) - assert issubclass(Type.create(MyInt, cache=type_cache).checkable, db.checkable) + assert issubclass(Dis(MyInt).checkable, db.checkable) class NotMyInt: pass assert not issubclass(NotMyInt, db.checkable) - assert not issubclass(Type.create(NotMyInt, cache=type_cache).checkable, db.checkable) + assert not issubclass(Dis(NotMyInt).checkable, db.checkable) - assert isinstance(db.checkable, InstanceCheckMeta) + assert isinstance(db.checkable, strcs.InstanceCheckMeta) assert isinstance(db.checkable, type) - assert isinstance(db.checkable, Type.create(type, cache=type_cache).checkable) + assert isinstance(db.checkable, Dis(type).checkable) - assert issubclass(db.checkable, InstanceCheck) + assert issubclass(db.checkable, strcs.InstanceCheck) assert not issubclass(db.checkable, type) assert not issubclass(type, db.checkable) - assert not issubclass(Type.create(type, cache=type_cache).checkable, db.checkable) - assert not issubclass(db.checkable, Type.create(type, cache=type_cache).checkable) + assert not issubclass(Dis(type).checkable, db.checkable) + assert not issubclass(db.checkable, Dis(type).checkable) assert not isinstance(db.checkable, int) - assert not isinstance(db.checkable, Type.create(int, cache=type_cache).checkable) + assert not isinstance(db.checkable, Dis(int).checkable) assert not issubclass(db.checkable, NotMyInt) - assert not issubclass(db.checkable, Type.create(NotMyInt, cache=type_cache).checkable) + assert not issubclass(db.checkable, Dis(NotMyInt).checkable) assert db.checkable.Meta.typ == int assert db.checkable.Meta.original == tp.Annotated[int | None, "stuff"] @@ -240,12 +236,12 @@ class NotMyInt: assert db.checkable.Meta.without_optional == tp.Annotated[int, "stuff"] assert db.checkable.Meta.without_annotation == int | None - it "can find instances and subclasses of user defined classes", type_cache: strcs.TypeCache: + it "can find instances and subclasses of user defined classes", Dis: Disassembler: class Mine: pass - db = Type.create(Mine, expect=Mine, cache=type_cache) + db = Dis(Mine) assert not isinstance(23, db.checkable) assert not isinstance(23.4, db.checkable) assert not isinstance("asdf", db.checkable) @@ -268,19 +264,19 @@ class Other: assert not isinstance(Other(), db.checkable) assert not issubclass(Other, db.checkable) - assert isinstance(db.checkable, InstanceCheckMeta) + assert isinstance(db.checkable, strcs.InstanceCheckMeta) assert isinstance(db.checkable, type) - assert isinstance(db.checkable, Type.create(type, cache=type_cache).checkable) + assert isinstance(db.checkable, Dis(type).checkable) - assert issubclass(db.checkable, InstanceCheck) + assert issubclass(db.checkable, strcs.InstanceCheck) assert not issubclass(db.checkable, type) assert not issubclass(type, db.checkable) - assert not issubclass(Type.create(type, cache=type_cache).checkable, db.checkable) - assert not issubclass(db.checkable, Type.create(type, cache=type_cache).checkable) + assert not issubclass(Dis(type).checkable, db.checkable) + assert not issubclass(db.checkable, Dis(type).checkable) assert not isinstance(db.checkable, int) - assert not isinstance(db.checkable, Type.create(int, cache=type_cache).checkable) + assert not isinstance(db.checkable, Dis(int).checkable) assert not issubclass(db.checkable, Other) - assert not issubclass(db.checkable, Type.create(Other, cache=type_cache).checkable) + assert not issubclass(db.checkable, Dis(Other).checkable) assert db.checkable.Meta.typ == Mine assert db.checkable.Meta.original == Mine @@ -288,8 +284,8 @@ class Other: assert db.checkable.Meta.without_optional == Mine assert db.checkable.Meta.without_annotation == Mine - it "can instantiate the provided type", type_cache: strcs.TypeCache: - checkable = Type.create(dict[str, bool], cache=type_cache).checkable + it "can instantiate the provided type", Dis: Disassembler: + checkable = Dis(dict[str, bool]).checkable made = tp.cast(tp.Callable, checkable)([("1", True), ("2", False)]) assert made == {"1": True, "2": False} @@ -303,7 +299,7 @@ class Thing: def __init__(self, one: int): self.one = one - checkable = Type.create(Thing, cache=type_cache).checkable + checkable = Dis(Thing).checkable made = tp.cast(tp.Callable, checkable)(one=1) assert isinstance(made, Thing) assert made.one == 1 @@ -314,11 +310,11 @@ def __init__(self, one: int): assert checkable.Meta.without_optional == Thing assert checkable.Meta.without_annotation == Thing - constructor: tp.Callable = Type.create(int | str, cache=type_cache).checkable + constructor: tp.Callable = Dis(int | str).checkable with pytest.raises(ValueError, match="Cannot instantiate a union type"): constructor(1) - it "can get repr", type_cache: strcs.TypeCache: + it "can get repr", Dis: Disassembler: class One: one: int @@ -354,68 +350,55 @@ class Three: (One | int, f"{repr(One)} | {repr(int)}"), ] for thing, expected in examples: - checkable = Type.create(thing, cache=type_cache).checkable + checkable = Dis(thing).checkable assert repr(checkable) == expected - it "can get typing origin", type_cache: strcs.TypeCache: + it "can get typing origin", Dis: Disassembler: - assert tp.get_origin(Type.create(str | int, cache=type_cache).checkable) == types.UnionType - assert tp.get_origin(Type.create(dict[str, int], cache=type_cache).checkable) == dict - assert tp.get_origin(Type.create(dict[str, int] | None, cache=type_cache).checkable) == dict - assert ( - tp.get_origin( - Type.create(tp.Annotated[dict[str, int] | None, "hi"], cache=type_cache).checkable - ) - == dict - ) + assert tp.get_origin(Dis(str | int).checkable) == types.UnionType + assert tp.get_origin(Dis(dict[str, int]).checkable) == dict + assert tp.get_origin(Dis(dict[str, int] | None).checkable) == dict + assert tp.get_origin(Dis(tp.Annotated[dict[str, int] | None, "hi"]).checkable) == dict - assert tp.get_origin(Type.create(dict, cache=type_cache).checkable) is None - assert tp.get_origin(Type.create(dict | None, cache=type_cache).checkable) is None - assert ( - tp.get_origin(Type.create(tp.Annotated[dict | None, "hi"], cache=type_cache).checkable) - is None - ) + assert tp.get_origin(Dis(dict).checkable) is None + assert tp.get_origin(Dis(dict | None).checkable) is None + assert tp.get_origin(Dis(tp.Annotated[dict | None, "hi"]).checkable) is None - assert tp.get_origin(Type.create(dict | str, cache=type_cache).checkable) is types.UnionType + assert tp.get_origin(Dis(dict | str).checkable) is types.UnionType class Thing(tp.Generic[T]): pass - assert tp.get_origin(Type.create(Thing, cache=type_cache).checkable) is None - assert tp.get_origin(Type.create(Thing[int], cache=type_cache).checkable) is Thing + assert tp.get_origin(Dis(Thing).checkable) is None + assert tp.get_origin(Dis(Thing[int]).checkable) is Thing - it "can get typing args", type_cache: strcs.TypeCache: + it "can get typing args", Dis: Disassembler: - assert tp.get_args(Type.create(str | int, cache=type_cache).checkable) == (str, int) - assert tp.get_args(Type.create(dict[str, int], cache=type_cache).checkable) == (str, int) - assert tp.get_args(Type.create(dict[str, int] | None, cache=type_cache).checkable) == ( + assert tp.get_args(Dis(str | int).checkable) == (str, int) + assert tp.get_args(Dis(dict[str, int]).checkable) == (str, int) + assert tp.get_args(Dis(dict[str, int] | None).checkable) == ( str, int, ) - assert tp.get_args( - Type.create(tp.Annotated[dict[str, int] | None, "hi"], cache=type_cache).checkable - ) == ( + assert tp.get_args(Dis(tp.Annotated[dict[str, int] | None, "hi"]).checkable) == ( str, int, ) - assert tp.get_args(Type.create(dict, cache=type_cache).checkable) == () - assert tp.get_args(Type.create(dict | None, cache=type_cache).checkable) == () - assert ( - tp.get_args(Type.create(tp.Annotated[dict | None, "hi"], cache=type_cache).checkable) - == () - ) + assert tp.get_args(Dis(dict).checkable) == () + assert tp.get_args(Dis(dict | None).checkable) == () + assert tp.get_args(Dis(tp.Annotated[dict | None, "hi"]).checkable) == () - assert tp.get_args(Type.create(dict | str, cache=type_cache).checkable) == (dict, str) + assert tp.get_args(Dis(dict | str).checkable) == (dict, str) class Thing(tp.Generic[T]): pass - assert tp.get_args(Type.create(Thing, cache=type_cache).checkable) == () - assert tp.get_args(Type.create(Thing[int], cache=type_cache).checkable) == (int,) + assert tp.get_args(Dis(Thing).checkable) == () + assert tp.get_args(Dis(Thing[int]).checkable) == (int,) - it "can get typing hints", type_cache: strcs.TypeCache: - assert tp.get_type_hints(Type.create(int, cache=type_cache).checkable) == {} + it "can get typing hints", Dis: Disassembler: + assert tp.get_type_hints(Dis(int).checkable) == {} class Thing: one: int @@ -447,7 +430,7 @@ class Stuff: want_error = e try: - got_result = tp.get_type_hints(Type.create(thing, cache=type_cache).checkable) + got_result = tp.get_type_hints(Dis(thing).checkable) except Exception as e: got_error = e @@ -459,7 +442,7 @@ class Stuff: assert got_result == want_result, thing assert got_error == want_error, thing - it "allows attrs helpers", type_cache: strcs.TypeCache: + it "allows attrs helpers", Dis: Disassembler: @attrs.define class One: @@ -476,13 +459,13 @@ class Three: two: str for kls in (One, Two, Three): - checkable = Type.create(kls, cache=type_cache).checkable + checkable = Dis(kls).checkable is_attrs = attrs.has(kls) assert is_attrs == attrs.has(checkable) if is_attrs: assert attrs.fields(kls) == attrs.fields(checkable) # type: ignore[arg-type] - it "allows dataclasses helpers", type_cache: strcs.TypeCache: + it "allows dataclasses helpers", Dis: Disassembler: @attrs.define class One: @@ -499,7 +482,7 @@ class Three: two: str for kls in (One, Two, Three): - checkable = Type.create(kls, cache=type_cache).checkable + checkable = Dis(kls).checkable is_dataclass = dataclasses.is_dataclass(kls) assert is_dataclass == dataclasses.is_dataclass(checkable) if is_dataclass: diff --git a/tests/disassemble/test_matching.py b/tests/disassemble/test_matching.py index cc10975..283dfbe 100644 --- a/tests/disassemble/test_matching.py +++ b/tests/disassemble/test_matching.py @@ -6,25 +6,21 @@ from unittest import mock import attrs -import pytest import strcs - -@pytest.fixture() -def type_cache() -> strcs.TypeCache: - return strcs.TypeCache() +Disassembler = strcs.disassemble.Disassembler describe "Matching a Type": def make_functions( - self, types: dict[int | str, object], cache: strcs.TypeCache + self, types: dict[int | str, object], *, Dis: Disassembler ) -> list[tuple[strcs.Type, strcs.ConvertFunction]]: - reg = strcs.CreateRegister(type_cache=cache) + reg = strcs.CreateRegister(type_cache=Dis.type_cache) for name, typ in types.items(): - reg[strcs.Type.create(typ, cache=cache)] = getattr(mock.sentinel, f"function_{name}") + reg[Dis(typ)] = getattr(mock.sentinel, f"function_{name}") return list(reg.register.items()) @@ -36,13 +32,13 @@ def shuffles( random.shuffle(shuffling) yield shuffling - it "finds the basic type", type_cache: strcs.TypeCache: - typ = strcs.Type.create(int, cache=type_cache, expect=int) - available = self.make_functions({0: str, 1: bool, 2: float, 3: int}, cache=type_cache) + it "finds the basic type", Dis: Disassembler: + typ = Dis(int) + available = self.make_functions({0: str, 1: bool, 2: float, 3: int}, Dis=Dis) for ordered in self.shuffles(available): assert typ.func_from(ordered) is mock.sentinel.function_3 - it "finds the matching attrs/dataclass/normal class", type_cache: strcs.TypeCache: + it "finds the matching attrs/dataclass/normal class", Dis: Disassembler: @attrs.define class Thing: @@ -55,20 +51,20 @@ class Stuff: class Blah: pass - available = self.make_functions({0: Stuff, 1: Thing, 2: Blah}, cache=type_cache) + available = self.make_functions({0: Stuff, 1: Thing, 2: Blah}, Dis=Dis) for ordered in self.shuffles(available): - typ = strcs.Type.create(Thing, cache=type_cache, expect=Thing) + typ = Dis(Thing) assert typ.func_from(ordered) is mock.sentinel.function_1 - typ = strcs.Type.create(Stuff, cache=type_cache, expect=Stuff) + typ = Dis(Stuff) assert typ.func_from(ordered) is mock.sentinel.function_0 - typ = strcs.Type.create(Blah, cache=type_cache, expect=Blah) + typ = Dis(Blah) assert typ.func_from(ordered) is mock.sentinel.function_2 - it "finds the matching attrs/dataclass/normal subclass", type_cache: strcs.TypeCache: + it "finds the matching attrs/dataclass/normal subclass", Dis: Disassembler: @attrs.define class Thing: @@ -92,21 +88,21 @@ class Blah: class ChildBlah(Blah): pass - available = self.make_functions({0: Stuff, 1: Thing, 2: Blah}, cache=type_cache) + available = self.make_functions({0: Stuff, 1: Thing, 2: Blah}, Dis=Dis) for ordered in self.shuffles(available): - typ = strcs.Type.create(ChildThing, cache=type_cache, expect=ChildThing) + typ = Dis(ChildThing) assert typ.func_from(ordered) is mock.sentinel.function_1 del typ - typ = strcs.Type.create(ChildStuff, cache=type_cache, expect=ChildStuff) + typ = Dis(ChildStuff) assert typ.func_from(ordered) is mock.sentinel.function_0 del typ - typ = strcs.Type.create(ChildBlah, cache=type_cache, expect=ChildBlah) + typ = Dis(ChildBlah) assert typ.func_from(ordered) is mock.sentinel.function_2 del typ - it "finds the matching child attrs/dataclass/normal", type_cache: strcs.TypeCache: + it "finds the matching child attrs/dataclass/normal", Dis: Disassembler: @attrs.define class Thing: @@ -131,34 +127,34 @@ class ChildBlah(Blah): pass available = self.make_functions( - {0: Stuff, 1: Thing, 2: Blah, 3: ChildThing, 4: ChildStuff}, cache=type_cache + {0: Stuff, 1: Thing, 2: Blah, 3: ChildThing, 4: ChildStuff}, Dis=Dis ) for ordered in self.shuffles(available): - typ = strcs.Type.create(Thing, cache=type_cache, expect=Thing) + typ = Dis(Thing) assert typ.func_from(ordered) is mock.sentinel.function_1 del typ - typ = strcs.Type.create(ChildThing, cache=type_cache, expect=ChildThing) + typ = Dis(ChildThing) assert typ.func_from(ordered) is mock.sentinel.function_3 del typ - typ = strcs.Type.create(Stuff, cache=type_cache, expect=Stuff) + typ = Dis(Stuff) assert typ.func_from(ordered) is mock.sentinel.function_0 del typ - typ = strcs.Type.create(ChildStuff, cache=type_cache, expect=ChildStuff) + typ = Dis(ChildStuff) assert typ.func_from(ordered) is mock.sentinel.function_4 del typ - typ = strcs.Type.create(Blah, cache=type_cache, expect=Blah) + typ = Dis(Blah) assert typ.func_from(ordered) is mock.sentinel.function_2 del typ - typ = strcs.Type.create(ChildBlah, cache=type_cache, expect=ChildBlah) + typ = Dis(ChildBlah) assert typ.func_from(ordered) is mock.sentinel.function_2 del typ - it "finds union type before matching against first function", type_cache: strcs.TypeCache: + it "finds union type before matching against first function", Dis: Disassembler: @attrs.define class Thing: @@ -182,41 +178,37 @@ class Blah: class ChildBlah(Blah): pass - available = self.make_functions({0: Stuff | Thing, 2: Stuff}, cache=type_cache) + available = self.make_functions({0: Stuff | Thing, 2: Stuff}, Dis=Dis) for ordered in self.shuffles(available): - typ = strcs.Type.create(ChildBlah, cache=type_cache, expect=ChildBlah) + typ = Dis(ChildBlah) assert typ.func_from(ordered) is None del typ - typ = strcs.Type.create(Blah, cache=type_cache, expect=Blah) + typ = Dis(Blah) assert typ.func_from(ordered) is None del typ - typ: strcs.Type[Stuff | Thing] = strcs.Type.create(Stuff | Thing, cache=type_cache) + typ = Dis(Stuff | Thing) assert typ.func_from(ordered) is mock.sentinel.function_0 del typ - typ: strcs.Type[ChildStuff | ChildThing] = strcs.Type.create( - ChildStuff | ChildThing, cache=type_cache - ) + typ = Dis(ChildStuff | ChildThing) assert typ.func_from(ordered) is mock.sentinel.function_0 del typ - typ = strcs.Type.create(Stuff, cache=type_cache, expect=Stuff) + typ = Dis(Stuff) assert typ.func_from(ordered) is mock.sentinel.function_2 del typ - typ = strcs.Type.create(Thing, cache=type_cache, expect=Stuff) + typ = Dis(Thing) assert typ.func_from(ordered) is mock.sentinel.function_0 del typ - it "can match a subclass of a filled generic", type_cache: strcs.TypeCache: - available = self.make_functions( - {0: dict, 1: dict[str, dict], 2: dict[str, str]}, cache=type_cache - ) + it "can match a subclass of a filled generic", Dis: Disassembler: + available = self.make_functions({0: dict, 1: dict[str, dict], 2: dict[str, str]}, Dis=Dis) class D(dict[str, str]): pass - typ = strcs.Type.create(D, expect=D, cache=type_cache) + typ = Dis(D) assert typ.func_from(available) is mock.sentinel.function_2 diff --git a/tests/disassemble/test_mro.py b/tests/disassemble/test_mro.py index 98e5f42..876473e 100644 --- a/tests/disassemble/test_mro.py +++ b/tests/disassemble/test_mro.py @@ -9,23 +9,7 @@ import strcs from strcs.disassemble import MRO - -class Disassembler: - def __init__(self, type_cache: strcs.TypeCache): - self.type_cache = type_cache - - def __call__(self, typ: object) -> strcs.Type: - return strcs.Type.create(typ, cache=self.type_cache) - - -@pytest.fixture() -def type_cache() -> strcs.TypeCache: - return strcs.TypeCache() - - -@pytest.fixture() -def Dis(type_cache: strcs.TypeCache) -> Disassembler: - return Disassembler(type_cache) +Disassembler = strcs.disassemble.Disassembler describe "assumptions": diff --git a/tests/disassemble/test_order.py b/tests/disassemble/test_order.py index e020241..6017b08 100644 --- a/tests/disassemble/test_order.py +++ b/tests/disassemble/test_order.py @@ -7,26 +7,23 @@ import strcs - -@pytest.fixture() -def type_cache() -> strcs.TypeCache: - return strcs.TypeCache() +Disassembler = strcs.disassemble.Disassembler class Sorter: @classmethod - def make_fixture(cls) -> tp.Callable[[strcs.TypeCache], "Sorter"]: + def make_fixture(cls) -> tp.Callable[[Disassembler], "Sorter"]: @pytest.fixture - def fixture(type_cache: strcs.TypeCache) -> Sorter: - return cls(type_cache) + def fixture(Dis: Disassembler) -> Sorter: + return cls(Dis) return fixture - def __init__(self, type_cache: strcs.TypeCache): - self.type_cache = type_cache + def __init__(self, Dis: Disassembler): + self.Dis = Dis def make_type(self, original: object | type) -> strcs.Type: - return strcs.Type.create(original, cache=self.type_cache) + return self.Dis(original) def assert_reverse_order(self, *to_sort: object) -> None: types: list[strcs.Type] = [self.make_type(original) for original in to_sort] diff --git a/tests/disassemble/test_score_display.py b/tests/disassemble/test_score_display.py index a92ce9e..6d7c01b 100644 --- a/tests/disassemble/test_score_display.py +++ b/tests/disassemble/test_score_display.py @@ -3,7 +3,6 @@ import itertools import sys import textwrap -import types import typing as tp import attrs @@ -12,10 +11,7 @@ import strcs from strcs import Type - -@pytest.fixture() -def type_cache() -> strcs.TypeCache: - return strcs.TypeCache() +Disassembler = strcs.disassemble.Disassembler T = tp.TypeVar("T") @@ -35,9 +31,9 @@ def assertDisplay(self, disassembled: Type, expected: str) -> None: assert got == want - it "works on None", type_cache: strcs.TypeCache: + it "works on None", Dis: Disassembler: provided = None - disassembled = Type.create(provided, expect=type(None), cache=type_cache) + disassembled = Dis(provided) self.assertDisplay( disassembled, """ @@ -60,9 +56,9 @@ def assertDisplay(self, disassembled: Type, expected: str) -> None: """, ) - it "doesn't overcome python limitations with annotating None and thinks we annotated type of None", type_cache: strcs.TypeCache: + it "doesn't overcome python limitations with annotating None and thinks we annotated type of None", Dis: Disassembler: provided = tp.Annotated[None, 1] - disassembled = Type.create(provided, expect=type(None), cache=type_cache) + disassembled = Dis(provided) self.assertDisplay( disassembled, """ @@ -85,9 +81,9 @@ def assertDisplay(self, disassembled: Type, expected: str) -> None: """, ) - it "works on simple type", type_cache: strcs.TypeCache: + it "works on simple type", Dis: Disassembler: provided = int - disassembled = Type.create(provided, expect=int, cache=type_cache) + disassembled = Dis(provided) self.assertDisplay( disassembled, """ @@ -110,9 +106,9 @@ def assertDisplay(self, disassembled: Type, expected: str) -> None: """, ) - it "works on a union", type_cache: strcs.TypeCache: + it "works on a union", Dis: Disassembler: provided = int | str - disassembled = Type.create(provided, expect=types.UnionType, cache=type_cache) + disassembled = Dis(provided) self.assertDisplay( disassembled, """ @@ -169,11 +165,11 @@ def assertDisplay(self, disassembled: Type, expected: str) -> None: ) @pytest.mark.skipif(sys.version_info < (3, 11), reason="requires python3.11 or higher") - it "works on a complicated union", type_cache: strcs.TypeCache: + it "works on a complicated union", Dis: Disassembler: provided = tp.Union[ tp.Annotated[list[int], "str"], tp.Annotated[int | str | None, '"hello'] ] - disassembled = Type.create(provided, expect=types.UnionType, cache=type_cache) + disassembled = Dis(provided) self.assertDisplay( disassembled, """ @@ -295,9 +291,9 @@ def assertDisplay(self, disassembled: Type, expected: str) -> None: ) @pytest.mark.skipif(sys.version_info < (3, 11), reason="requires python3.11 or higher") - it "works on a typing union", type_cache: strcs.TypeCache: + it "works on a typing union", Dis: Disassembler: provided = tp.Union[int, str] - disassembled = Type.create(provided, expect=types.UnionType, cache=type_cache) + disassembled = Dis(provided) self.assertDisplay( disassembled, """ @@ -369,9 +365,9 @@ def assertDisplay(self, disassembled: Type, expected: str) -> None: """, ) - it "works on an optional union", type_cache: strcs.TypeCache: + it "works on an optional union", Dis: Disassembler: provided = int | str | None - disassembled = Type.create(provided, expect=types.UnionType, cache=type_cache) + disassembled = Dis(provided) self.assertDisplay( disassembled, """ @@ -427,9 +423,9 @@ def assertDisplay(self, disassembled: Type, expected: str) -> None: """, ) - it "works on optional simple type", type_cache: strcs.TypeCache: + it "works on optional simple type", Dis: Disassembler: provided = int | None - disassembled = Type.create(provided, expect=int, cache=type_cache) + disassembled = Dis(provided) self.assertDisplay( disassembled, """ @@ -452,10 +448,10 @@ def assertDisplay(self, disassembled: Type, expected: str) -> None: """, ) - it "works on annotated simple type", type_cache: strcs.TypeCache: + it "works on annotated simple type", Dis: Disassembler: anno = "hello" provided = tp.Annotated[int, anno] - disassembled = Type.create(provided, expect=int, cache=type_cache) + disassembled = Dis(provided) self.assertDisplay( disassembled, """ @@ -478,10 +474,10 @@ def assertDisplay(self, disassembled: Type, expected: str) -> None: """, ) - it "works on optional annotated simple type", type_cache: strcs.TypeCache: + it "works on optional annotated simple type", Dis: Disassembler: anno = "hello" provided = tp.Annotated[tp.Optional[int], anno] - disassembled = Type.create(provided, expect=int, cache=type_cache) + disassembled = Dis(provided) self.assertDisplay( disassembled, """ @@ -504,9 +500,9 @@ def assertDisplay(self, disassembled: Type, expected: str) -> None: """, ) - it "works on builtin container to simple type", type_cache: strcs.TypeCache: + it "works on builtin container to simple type", Dis: Disassembler: provided = list[int] - disassembled = Type.create(provided, expect=list, cache=type_cache) + disassembled = Dis(provided) self.assertDisplay( disassembled, """ @@ -545,9 +541,9 @@ def assertDisplay(self, disassembled: Type, expected: str) -> None: """, ) - it "works on optional builtin container to simple type", type_cache: strcs.TypeCache: + it "works on optional builtin container to simple type", Dis: Disassembler: provided = list[int] | None - disassembled = Type.create(provided, expect=list, cache=type_cache) + disassembled = Dis(provided) self.assertDisplay( disassembled, """ @@ -586,9 +582,9 @@ def assertDisplay(self, disassembled: Type, expected: str) -> None: """, ) - it "works on builtin container to multiple simple types", type_cache: strcs.TypeCache: + it "works on builtin container to multiple simple types", Dis: Disassembler: provided = dict[str, int] - disassembled = Type.create(provided, expect=dict, cache=type_cache) + disassembled = Dis(provided) self.assertDisplay( disassembled, """ @@ -643,9 +639,9 @@ def assertDisplay(self, disassembled: Type, expected: str) -> None: """, ) - it "works on optional builtin container to multiple simple types", type_cache: strcs.TypeCache: + it "works on optional builtin container to multiple simple types", Dis: Disassembler: provided = tp.Optional[dict[str, int]] - disassembled = Type.create(provided, expect=dict, cache=type_cache) + disassembled = Dis(provided) self.assertDisplay( disassembled, """ @@ -700,10 +696,10 @@ def assertDisplay(self, disassembled: Type, expected: str) -> None: """, ) - it "works on annotated optional builtin container to multiple simple types", type_cache: strcs.TypeCache: + it "works on annotated optional builtin container to multiple simple types", Dis: Disassembler: anno = "stuff" provided = tp.Annotated[tp.Optional[dict[str, int]], anno] - disassembled = Type.create(provided, expect=dict, cache=type_cache) + disassembled = Dis(provided) self.assertDisplay( disassembled, """ @@ -758,10 +754,10 @@ def assertDisplay(self, disassembled: Type, expected: str) -> None: """, ) - it "works on optional annotated builtin container to multiple simple types", type_cache: strcs.TypeCache: + it "works on optional annotated builtin container to multiple simple types", Dis: Disassembler: anno = "stuff" provided = tp.Optional[tp.Annotated[dict[str, int], anno]] - disassembled = Type.create(provided, expect=dict, cache=type_cache) + disassembled = Dis(provided) self.assertDisplay( disassembled, """ @@ -816,7 +812,7 @@ def assertDisplay(self, disassembled: Type, expected: str) -> None: """, ) - it "works on an attrs class", type_cache: strcs.TypeCache: + it "works on an attrs class", Dis: Disassembler: @attrs.define class Thing: @@ -824,7 +820,7 @@ class Thing: two: str provided = Thing - disassembled = Type.create(provided, expect=Thing, cache=type_cache) + disassembled = Dis(provided) self.assertDisplay( disassembled, """ @@ -847,7 +843,7 @@ class Thing: """, ) - it "works on an dataclasses class", type_cache: strcs.TypeCache: + it "works on an dataclasses class", Dis: Disassembler: @dataclasses.dataclass class Thing: @@ -855,7 +851,7 @@ class Thing: two: str provided = Thing - disassembled = Type.create(provided, expect=Thing, cache=type_cache) + disassembled = Dis(provided) self.assertDisplay( disassembled, """ @@ -878,7 +874,7 @@ class Thing: """, ) - it "works on a normal class", type_cache: strcs.TypeCache: + it "works on a normal class", Dis: Disassembler: class Thing: def __init__(self, one: int, two: str): @@ -886,7 +882,7 @@ def __init__(self, one: int, two: str): self.two = two provided = Thing - disassembled = Type.create(provided, expect=Thing, cache=type_cache) + disassembled = Dis(provided) self.assertDisplay( disassembled, """ @@ -909,13 +905,13 @@ def __init__(self, one: int, two: str): """, ) - it "works on inherited generic container", type_cache: strcs.TypeCache: + it "works on inherited generic container", Dis: Disassembler: class D(dict[str, int]): pass provided = D - disassembled = Type.create(provided, expect=D, cache=type_cache) + disassembled = Dis(provided) self.assertDisplay( disassembled, """ @@ -974,7 +970,7 @@ class D(dict[str, int]): """, ) - it "works on class with complicated hierarchy", type_cache: strcs.TypeCache: + it "works on class with complicated hierarchy", Dis: Disassembler: class Thing(tp.Generic[T, U]): def __init__(self, one: int, two: str): @@ -998,7 +994,7 @@ def __init__(self, four: str): self.four = four provided = Tree - disassembled = Type.create(provided, expect=Tree, cache=type_cache) + disassembled = Dis(provided) self.assertDisplay( disassembled, """ @@ -1093,7 +1089,7 @@ def __init__(self, four: str): """, ) - it "works on an annotated class", type_cache: strcs.TypeCache: + it "works on an annotated class", Dis: Disassembler: @attrs.define class Thing: @@ -1103,7 +1099,7 @@ class Thing: anno = "blah" provided = tp.Annotated[Thing, anno] - disassembled = Type.create(provided, expect=Thing, cache=type_cache) + disassembled = Dis(provided) self.assertDisplay( disassembled, """ @@ -1126,7 +1122,7 @@ class Thing: """, ) - it "works on an optional annotated class", type_cache: strcs.TypeCache: + it "works on an optional annotated class", Dis: Disassembler: @dataclasses.dataclass class Thing: @@ -1136,7 +1132,7 @@ class Thing: anno = "blah" provided = tp.Annotated[tp.Optional[Thing], anno] - disassembled = Type.create(provided, expect=Thing, cache=type_cache) + disassembled = Dis(provided) self.assertDisplay( disassembled, """ @@ -1159,7 +1155,7 @@ class Thing: """, ) - it "works on an optional annotated generic class", type_cache: strcs.TypeCache: + it "works on an optional annotated generic class", Dis: Disassembler: @dataclasses.dataclass class Thing(tp.Generic[T, U]): @@ -1169,7 +1165,7 @@ class Thing(tp.Generic[T, U]): anno = "blah" provided = tp.Annotated[tp.Optional[Thing[int, str]], anno] - disassembled = Type.create(provided, expect=Thing, cache=type_cache) + disassembled = Dis(provided) self.assertDisplay( disassembled, """ @@ -1228,7 +1224,7 @@ class Thing(tp.Generic[T, U]): """, ) - it "works on an optional annotated generic class without concrete types", type_cache: strcs.TypeCache: + it "works on an optional annotated generic class without concrete types", Dis: Disassembler: @attrs.define class Thing(tp.Generic[T, U]): @@ -1238,7 +1234,7 @@ class Thing(tp.Generic[T, U]): anno = "blah" provided = tp.Annotated[tp.Optional[Thing], anno] - disassembled = Type.create(provided, expect=Thing, cache=type_cache) + disassembled = Dis(provided) self.assertDisplay( disassembled, """ @@ -1281,7 +1277,7 @@ class Thing(tp.Generic[T, U]): """, ) - it "works on an optional annotated generic class with concrete types", type_cache: strcs.TypeCache: + it "works on an optional annotated generic class with concrete types", Dis: Disassembler: @attrs.define class Thing(tp.Generic[T, U]): @@ -1291,7 +1287,7 @@ class Thing(tp.Generic[T, U]): anno = "blah" provided = tp.Annotated[tp.Optional[Thing[int, str]], anno] - disassembled = Type.create(provided, expect=Thing, cache=type_cache) + disassembled = Dis(provided) self.assertDisplay( disassembled, """ diff --git a/tests/test_args_extractor.py b/tests/test_args_extractor.py index a518c80..3b034b1 100644 --- a/tests/test_args_extractor.py +++ b/tests/test_args_extractor.py @@ -1,6 +1,7 @@ # coding: spec import inspect +import typing as tp from unittest import mock import cattrs @@ -8,6 +9,8 @@ import strcs +T = tp.TypeVar("T") + @pytest.fixture() def meta() -> strcs.Meta: @@ -36,13 +39,13 @@ class IsRegister: def __init__( self, reg: strcs.CreateRegister, - last_type: type, + last_type: type[T], last_meta: strcs.Meta, skip_creator: strcs.ConvertDefinition, ): self.reg = reg self.got: object | None = None - self.last_type = strcs.Type.create(last_type, expect=object, cache=reg.type_cache) + self.last_type = reg.disassemble(last_type) self.last_meta = last_meta self.skip_creator = skip_creator @@ -73,7 +76,7 @@ def func() -> strcs.ConvertResponse[object]: extractor = strcs.ArgsExtractor( signature=inspect.signature(func), value=val, - want=strcs.Type.create(mock.Mock, expect=object, cache=creg.type_cache), + want=creg.disassemble(object), meta=meta, converter=cattrs.Converter(), register=creg, @@ -91,7 +94,7 @@ def func(value: object, /) -> strcs.ConvertResponse[object]: extractor = strcs.ArgsExtractor( signature=inspect.signature(func), value=val, - want=strcs.Type.create(mock.Mock, expect=object, cache=creg.type_cache), + want=creg.disassemble(object), meta=meta, converter=cattrs.Converter(), register=creg, @@ -109,7 +112,7 @@ def func(value: object, want: strcs.Type, /) -> strcs.ConvertResponse[object]: extractor = strcs.ArgsExtractor( signature=inspect.signature(func), value=val, - want=strcs.Type.create(mock.Mock, expect=object, cache=creg.type_cache), + want=creg.disassemble(object), meta=meta, converter=cattrs.Converter(), register=creg, @@ -118,7 +121,7 @@ def func(value: object, want: strcs.Type, /) -> strcs.ConvertResponse[object]: assert extractor.extract() == [ val, - strcs.Type.create(mock.Mock, cache=creg.type_cache), + creg.disassemble(object), ] it "can get arbitrary values from meta", meta: strcs.Meta, creg: strcs.CreateRegister: @@ -130,7 +133,7 @@ class Other: def func( value: object, want: strcs.Type, /, other: Other, blah: int, stuff: str - ) -> strcs.ConvertResponse[object]: + ) -> strcs.ConvertResponse[Other]: ... val = mock.Mock(name="val") @@ -142,7 +145,7 @@ def func( extractor = strcs.ArgsExtractor( signature=inspect.signature(func), value=val, - want=strcs.Type.create(Other, expect=object, cache=creg.type_cache), + want=creg.disassemble(Other), meta=meta, converter=cattrs.Converter(), register=creg, @@ -150,7 +153,7 @@ def func( ) assert extractor.extract() == [ val, - strcs.Type.create(Other, cache=creg.type_cache), + creg.disassemble(Other), o, 12, "one", @@ -158,13 +161,13 @@ def func( def func2( value: object, /, other: Other, blah: int, stuff: str - ) -> strcs.ConvertResponse[object]: + ) -> strcs.ConvertResponse[Other]: ... extractor = strcs.ArgsExtractor( signature=inspect.signature(func2), value=val, - want=strcs.Type.create(Other, expect=object, cache=creg.type_cache), + want=creg.disassemble(Other), meta=meta, converter=cattrs.Converter(), register=creg, @@ -172,13 +175,13 @@ def func2( ) assert extractor.extract() == [val, o, 12, "one"] - def func3(other: Other, blah: int, stuff: str) -> strcs.ConvertResponse[object]: + def func3(other: Other, blah: int, stuff: str) -> strcs.ConvertResponse[Other]: ... extractor = strcs.ArgsExtractor( signature=inspect.signature(func3), value=val, - want=strcs.Type.create(Other, expect=object, cache=creg.type_cache), + want=creg.disassemble(Other), meta=meta, converter=cattrs.Converter(), register=creg, @@ -186,13 +189,13 @@ def func3(other: Other, blah: int, stuff: str) -> strcs.ConvertResponse[object]: ) assert extractor.extract() == [o, 12, "one"] - def func4(other: Other) -> strcs.ConvertResponse[object]: + def func4(other: Other) -> strcs.ConvertResponse[Other]: ... extractor = strcs.ArgsExtractor( signature=inspect.signature(func4), value=val, - want=strcs.Type.create(Other, cache=creg.type_cache), + want=creg.disassemble(Other), meta=meta, converter=cattrs.Converter(), register=creg, @@ -209,7 +212,7 @@ def func(_meta) -> strcs.ConvertResponse[object]: extractor = strcs.ArgsExtractor( signature=inspect.signature(func), value=val, - want=strcs.Type.create(mock.Mock, expect=object, cache=creg.type_cache), + want=creg.disassemble(object), meta=meta, converter=cattrs.Converter(), register=creg, @@ -224,7 +227,7 @@ def func2(_meta: strcs.Meta) -> strcs.ConvertResponse[object]: extractor = strcs.ArgsExtractor( signature=inspect.signature(func2), value=val, - want=strcs.Type.create(mock.Mock, expect=object, cache=creg.type_cache), + want=creg.disassemble(object), meta=meta, converter=cattrs.Converter(), register=creg, @@ -239,7 +242,7 @@ def func3(val, /, _meta: strcs.Meta) -> strcs.ConvertResponse[object]: extractor = strcs.ArgsExtractor( signature=inspect.signature(func3), value=val, - want=strcs.Type.create(mock.Mock, expect=object, cache=creg.type_cache), + want=creg.disassemble(object), meta=meta, converter=cattrs.Converter(), register=creg, @@ -257,7 +260,7 @@ class Other: def func( value: object, want: strcs.Type, /, other, blah, stuff - ) -> strcs.ConvertResponse[object]: + ) -> strcs.ConvertResponse[Other]: ... val = mock.Mock(name="val") @@ -268,7 +271,7 @@ def func( extractor = strcs.ArgsExtractor( signature=inspect.signature(func), value=val, - want=strcs.Type.create(Other, expect=object, cache=creg.type_cache), + want=creg.disassemble(Other), meta=meta, converter=cattrs.Converter(), register=creg, @@ -276,7 +279,7 @@ def func( ) assert extractor.extract() == [ val, - strcs.Type.create(Other, cache=creg.type_cache), + creg.disassemble(Other), o, 12, "one", @@ -292,7 +295,7 @@ def func(_converter) -> strcs.ConvertResponse[object]: extractor = strcs.ArgsExtractor( signature=inspect.signature(func), value=val, - want=strcs.Type.create(mock.Mock, expect=object, cache=creg.type_cache), + want=creg.disassemble(object), meta=meta, converter=converter, register=creg, @@ -307,7 +310,7 @@ def func2(_converter: cattrs.Converter) -> strcs.ConvertResponse[object]: extractor = strcs.ArgsExtractor( signature=inspect.signature(func2), value=val, - want=strcs.Type.create(mock.Mock, expect=object, cache=creg.type_cache), + want=creg.disassemble(object), meta=meta, converter=converter, register=creg, @@ -322,7 +325,7 @@ def func3(val, /, _converter: cattrs.Converter) -> strcs.ConvertResponse[object] extractor = strcs.ArgsExtractor( signature=inspect.signature(func3), value=val, - want=strcs.Type.create(mock.Mock, expect=object, cache=creg.type_cache), + want=creg.disassemble(object), meta=meta, converter=converter, register=creg, @@ -333,14 +336,14 @@ def func3(val, /, _converter: cattrs.Converter) -> strcs.ConvertResponse[object] it "can get us the register object", meta: strcs.Meta, creg: strcs.CreateRegister: - def func(_register) -> strcs.ConvertResponse[object]: + def func(_register) -> strcs.ConvertResponse[mock.Mock]: ... val = mock.Mock(name="val") extractor = strcs.ArgsExtractor( signature=inspect.signature(func), value=val, - want=strcs.Type.create(mock.Mock, expect=object, cache=creg.type_cache), + want=creg.disassemble(mock.Mock), meta=meta, converter=cattrs.Converter(), register=creg, @@ -349,13 +352,13 @@ def func(_register) -> strcs.ConvertResponse[object]: assert extractor.extract() == [IsRegister(creg, mock.Mock, meta, func)] - def func2(_register: strcs.CreateRegister) -> strcs.ConvertResponse[object]: + def func2(_register: strcs.CreateRegister) -> strcs.ConvertResponse[mock.Mock]: ... extractor = strcs.ArgsExtractor( signature=inspect.signature(func2), value=val, - want=strcs.Type.create(mock.Mock, expect=object, cache=creg.type_cache), + want=creg.disassemble(mock.Mock), meta=meta, converter=cattrs.Converter(), register=creg, @@ -364,13 +367,13 @@ def func2(_register: strcs.CreateRegister) -> strcs.ConvertResponse[object]: assert extractor.extract() == [IsRegister(creg, mock.Mock, meta, func2)] - def func3(val, /, _register: strcs.CreateRegister) -> strcs.ConvertResponse[object]: + def func3(val, /, _register: strcs.CreateRegister) -> strcs.ConvertResponse[mock.Mock]: ... extractor = strcs.ArgsExtractor( signature=inspect.signature(func3), value=val, - want=strcs.Type.create(mock.Mock, expect=object, cache=creg.type_cache), + want=creg.disassemble(mock.Mock), meta=meta, converter=cattrs.Converter(), register=creg, @@ -397,13 +400,13 @@ def func3(val, /, _register: strcs.CreateRegister) -> strcs.ConvertResponse[obje def func( _register, register, _meta, meta, _converter, converter - ) -> strcs.ConvertResponse[object]: + ) -> strcs.ConvertResponse[mock.Mock]: ... extractor = strcs.ArgsExtractor( signature=inspect.signature(func), value=val, - want=strcs.Type.create(mock.Mock, expect=object, cache=register1.type_cache), + want=register1.disassemble(mock.Mock), meta=meta1, converter=converter1, register=register1, @@ -426,13 +429,13 @@ def func2( meta: strcs.Meta, _converter: cattrs.Converter, converter: cattrs.Converter, - ) -> strcs.ConvertResponse[object]: + ) -> strcs.ConvertResponse[mock.Mock]: ... extractor = strcs.ArgsExtractor( signature=inspect.signature(func2), value=val, - want=strcs.Type.create(mock.Mock, expect=object, cache=register1.type_cache), + want=register1.disassemble(mock.Mock), meta=meta1, converter=converter1, register=register1, @@ -455,13 +458,13 @@ def func3( meta: strcs.Meta, _converter: str, converter: cattrs.Converter, - ) -> strcs.ConvertResponse[object]: + ) -> strcs.ConvertResponse[mock.Mock]: ... extractor = strcs.ArgsExtractor( signature=inspect.signature(func3), value=val, - want=strcs.Type.create(mock.Mock, expect=object, cache=register1.type_cache), + want=register1.disassemble(mock.Mock), meta=meta1, converter=converter1, register=register1, @@ -481,7 +484,7 @@ def func(wat) -> strcs.ConvertResponse[object]: extractor = strcs.ArgsExtractor( signature=inspect.signature(func), value=mock.Mock(name="val"), - want=strcs.Type.create(mock.Mock, expect=object, cache=creg.type_cache), + want=creg.disassemble(object), meta=meta, converter=cattrs.Converter(), register=creg, @@ -502,7 +505,7 @@ def func2(wat: int) -> strcs.ConvertResponse[object]: extractor = strcs.ArgsExtractor( signature=inspect.signature(func2), value=mock.Mock(name="val"), - want=strcs.Type.create(mock.Mock, expect=object, cache=creg.type_cache), + want=creg.disassemble(object), meta=meta, converter=cattrs.Converter(), register=creg, diff --git a/tests/test_hints.py b/tests/test_hints.py index ab2ec57..d9fccb7 100644 --- a/tests/test_hints.py +++ b/tests/test_hints.py @@ -40,7 +40,7 @@ class Thing: assert len(type_cache) == 0 - strcs.Type.create(Thing, expect=object, cache=type_cache) + type_cache.disassemble(Thing) assert len(type_cache) > 0 diff --git a/tests/test_register.py b/tests/test_register.py index b2983e0..0d72c26 100644 --- a/tests/test_register.py +++ b/tests/test_register.py @@ -85,7 +85,7 @@ class Stuff: assert Thing not in creg creg[Thing] = thing_maker assert Thing in creg - assert creg.register == {strcs.Type.create(Thing, cache=creg.type_cache): thing_maker} + assert creg.register == {creg.disassemble(Thing): thing_maker} assert Stuff not in creg creg[Stuff] = stuff_maker @@ -93,8 +93,8 @@ class Stuff: assert Thing in creg assert creg.register == { - strcs.Type.create(Thing, cache=creg.type_cache): thing_maker, - strcs.Type.create(Stuff, cache=creg.type_cache): stuff_maker, + creg.disassemble(Thing): thing_maker, + creg.disassemble(Stuff): stuff_maker, } describe "can use the converters": @@ -111,7 +111,7 @@ class Thing: thing_maker.assert_called_once_with( strcs.CreateArgs( strcs.NotSpecified, - strcs.Type.create(Thing, cache=creg.type_cache), + creg.disassemble(Thing), IsMeta.test(), IsConverter.test(), creg, @@ -128,7 +128,7 @@ class Stuff: stuff_maker.assert_called_once_with( strcs.CreateArgs( strcs.NotSpecified, - strcs.Type.create(Stuff, cache=creg.type_cache), + creg.disassemble(Stuff), IsMeta.test(), IsConverter.test(), creg, @@ -163,7 +163,7 @@ class Thing: thing_maker.assert_called_once_with( strcs.CreateArgs( value, - strcs.Type.create(Thing, cache=creg.type_cache), + creg.disassemble(Thing), IsMeta.test(), IsConverter.test(), creg, @@ -200,7 +200,7 @@ class Other: stuff_maker.assert_called_once_with( strcs.CreateArgs( {"one": 45, "two": 76}, - strcs.Type.create(Stuff, cache=creg.type_cache), + creg.disassemble(Stuff), IsMeta.test(), IsConverter.test(), creg, @@ -299,7 +299,7 @@ class Square(Shape): shape_maker.assert_called_once_with( strcs.CreateArgs( strcs.NotSpecified, - strcs.Type.create(Square, cache=creg.type_cache), + creg.disassemble(Square), meta, IsConverter.test(), creg, @@ -315,7 +315,7 @@ class Square(Shape): shape_maker.assert_called_once_with( strcs.CreateArgs( strcs.NotSpecified, - strcs.Type.create(Triangle, cache=creg.type_cache), + creg.disassemble(Triangle), meta, IsConverter.test(), creg, @@ -331,7 +331,7 @@ class Square(Shape): shape_maker.assert_called_once_with( strcs.CreateArgs( strcs.NotSpecified, - strcs.Type.create(Shape, cache=creg.type_cache), + creg.disassemble(Shape), meta, IsConverter.test(), creg,