11import inspect
22from abc import ABC , abstractmethod
3- from typing import Pattern , Sequence , Literal
3+ from typing import Pattern , Sequence , Literal , Any
44
5- __version__ = "0.2 "
5+ __version__ = "0.3 "
66
77
88class FuzzyAssert :
@@ -12,7 +12,7 @@ def __init__(self):
1212 self .check_minimum_sequence_length = True
1313 self .fuzzy_sequence_types = False
1414
15- def match (self , data , template ) -> Literal [True ]:
15+ def match (self , data : Any , template : Any ) -> Literal [True ]:
1616 """
1717 Attempt to match the template onto the data.
1818 Each item in a `template` must have a match in the `data`.
@@ -24,7 +24,12 @@ def match(self, data, template) -> Literal[True]:
2424 :return: True if `template` matches the `data`
2525 :rtype: Literal[True]
2626 """
27- if inspect .isfunction (template ):
27+ if isinstance (template , FassertInterface ):
28+ return template .__fassert__ (other = data , matcher = self , as_template = True )
29+ elif isinstance (data , FassertInterface ):
30+ return data .__fassert__ (other = template , matcher = self , as_template = False )
31+
32+ elif inspect .isfunction (template ):
2833 if self .eval_functions and template (data ):
2934 return True
3035 raise AssertionError ("Template function does not match the data" )
@@ -41,8 +46,10 @@ def match(self, data, template) -> Literal[True]:
4146 return True
4247 else :
4348 raise AssertionError ("Template does not match the data" )
44- elif isinstance (data , Sequence ) and isinstance (template , Sequence ) and (
45- self .fuzzy_sequence_types or (type (data ) == type (template ))
49+ elif (
50+ isinstance (data , Sequence )
51+ and isinstance (template , Sequence )
52+ and (self .fuzzy_sequence_types or (type (data ) == type (template )))
4653 ):
4754 if self .check_minimum_sequence_length and len (template ) > len (data ):
4855 raise AssertionError (
@@ -69,7 +76,9 @@ def match(self, data, template) -> Literal[True]:
6976 return True
7077
7178 if type (data ) != type (template ):
72- raise AssertionError (f"Template type `{ type (template )} ` does not match the type of data `{ type (data )} `" )
79+ raise AssertionError (
80+ f"Template type `{ type (template )} ` does not match the type of data `{ type (data )} `"
81+ )
7382 elif isinstance (data , dict ):
7483 for template_key , template_value in template .items ():
7584 for data_key , data_value in data .items ():
@@ -99,9 +108,21 @@ def match(self, data, template) -> Literal[True]:
99108
100109class FassertInterface (ABC ):
101110 @abstractmethod
102- def __fassert__ (self , other , matcher : FuzzyAssert ) -> bool :
111+ def __fassert__ (
112+ self , other : Any , matcher : FuzzyAssert , as_template : bool
113+ ) -> Literal [True ]:
114+ """
115+ Add a support for matching custom defined types in a recursive way
116+
117+ :param other: other data structure to match against
118+ :param matcher: An instance of the FuzzyAssert object
119+ :param as_template: Flag to indicate if you are (self) the template matching the data or the other way around
120+ :raises AssertionError: When `self` does not match the `other`
121+ :return: True if data is matching otherwise an AssertionError is raised
122+ :rtype Literal[True]:
123+ """
103124 ...
104125
105126
106- def fassert (data , template ) -> bool :
127+ def fassert (data : Any , template : Any ) -> Literal [ True ] :
107128 return FuzzyAssert ().match (data , template )
0 commit comments