Skip to content

Commit

Permalink
WIP: comparer
Browse files Browse the repository at this point in the history
  • Loading branch information
delfick committed Sep 30, 2023
1 parent a5c9da3 commit 6f22ec7
Show file tree
Hide file tree
Showing 9 changed files with 1,032 additions and 215 deletions.
2 changes: 2 additions & 0 deletions strcs/disassemble/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from ._base import Type
from ._cache import TypeCache
from ._comparer import Comparer
from ._creation import fill, instantiate
from ._extract import IsAnnotated, extract_annotation, extract_optional
from ._fields import (
Expand All @@ -17,6 +18,7 @@
__all__ = [
"Type",
"TypeCache",
"Comparer",
"IsAnnotated",
"extract_annotation",
"extract_optional",
Expand Down
27 changes: 21 additions & 6 deletions strcs/disassemble/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
fields_from_class,
fields_from_dataclasses,
)
from ._instance_check import InstanceCheck, create_checkable
from ._instance_check import InstanceCheck, InstanceCheckMeta, create_checkable
from ._score import Score

if tp.TYPE_CHECKING:
Expand Down Expand Up @@ -173,23 +173,38 @@ def __eq__(self, o: object) -> tp.TypeGuard["Type"]:
if o is Type.Missing:
return True

if isinstance(o, InstanceCheck) and hasattr(o, "Meta"):
if issubclass(type(o), InstanceCheckMeta) and hasattr(o, "Meta"):
o = o.Meta.disassembled

if isinstance(o, Type):
if issubclass(type(o), Type) and hasattr(o, "original"):
o = o.original

if (
o == self.original
or (self.is_annotated and o == self.extracted)
or (self.optional and o is None)
or (self.mro.all_vars and o == self.origin)
or (self.is_union and o in self.nonoptional_union_types)
):
return True

if type(o) in union_types:
return len(set(tp.get_args(o)) - set(self.relevant_types)) == 0
else:
return o in self.relevant_types
for part in self.relevant_types:
disassembled = self.disassemble(object, part)
if o == disassembled.original:
return True
elif disassembled.is_annotated and o == disassembled.extracted:
return True
elif disassembled.optional and o is None:
return True
elif disassembled.is_union and o in disassembled.nonoptional_union_types:
return True
elif disassembled.mro.all_vars and o == disassembled.origin:
return True

return False

def for_display(self) -> str:
"""
Expand Down Expand Up @@ -634,11 +649,11 @@ def func_from(
not considered matches. In the second pass they are.
"""
for want, func in sorted(options, key=lambda pair: pair[0], reverse=True):
if self.checkable.matches(want.checkable):
if self.cache.comparer.matches(want, self):
return func

for want, func in sorted(options, key=lambda pair: pair[0], reverse=True):
if self.checkable.matches(want.checkable, subclasses=True):
if self.cache.comparer.matches(want, self, subclasses=True):
return func

return None
Expand Down
14 changes: 14 additions & 0 deletions strcs/disassemble/_cache.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import typing as tp
from collections.abc import MutableMapping

from ._comparer import Comparer

if tp.TYPE_CHECKING:
from ._base import Type

U = tp.TypeVar("U")


class TypeCache(MutableMapping[object, "Type"]):
"""
Expand Down Expand Up @@ -36,6 +40,16 @@ class TypeCache(MutableMapping[object, "Type"]):

def __init__(self):
self.cache = {}
self.comparer = Comparer(self)

def disassemble(self, expect: type[U], typ: object) -> "Type[U]":
"""
Return a new :class:`strcs.Type` for the provided object using this
type cache
"""
from ._base import Type

return Type.create(typ, expect=expect, cache=self)

def key(self, o: object) -> tuple[type, object]:
return (type(o), o)
Expand Down
Loading

0 comments on commit 6f22ec7

Please sign in to comment.