@@ -33,6 +33,10 @@ class PathTypeError(TypeError):
3333 pass
3434
3535
36+ class StrictPathTypeError (PathTypeError ):
37+ pass
38+
39+
3640def path_type (
3741 mapping : Optional [Dict [str , Tuple ["PropertyValueType" , ...]]] = None ,
3842 * ,
@@ -63,7 +67,7 @@ def path_type_matcher(
6367 if isinstance (data , type_to_match ):
6468 return replacer (data , matches )
6569 if strict :
66- raise PathTypeError (
70+ raise StrictPathTypeError (
6771 gettext (
6872 "{} at '{}' of type {} does not "
6973 "match any of the expected types: {}"
@@ -107,3 +111,23 @@ def _path_match(path: str, pattern: str, is_regex: bool) -> "MatchResult":
107111 if not is_regex :
108112 pattern = re .escape (pattern )
109113 return re .fullmatch (pattern , path )
114+
115+
116+ def compose_matchers (* matchers : "PropertyMatcher" ) -> "PropertyMatcher" :
117+ """
118+ Composes 1 or more matchers into a single matcher.
119+ """
120+
121+ def _matcher (
122+ * , data : "SerializableData" , path : "PropertyPath"
123+ ) -> Optional ["SerializableData" ]:
124+ for matcher in matchers :
125+ try :
126+ data = matcher (data = data , path = path )
127+ except StrictPathTypeError :
128+ # ignore strict mode when composing matchers
129+ pass
130+
131+ return data
132+
133+ return _matcher
0 commit comments