@@ -19,6 +19,14 @@ def pattern_keyword(
1919 self , validator : t .Any , pattern : str , instance : str , schema : t .Any
2020 ) -> t .Iterator [jsonschema .ValidationError ]: ...
2121
22+ def patternProperties_keyword (
23+ self ,
24+ validator : t .Any ,
25+ patternProperties : dict [str , t .Any ],
26+ instance : dict [str , t .Any ],
27+ schema : t .Any ,
28+ ) -> t .Iterator [jsonschema .ValidationError ]: ...
29+
2230
2331class RegexImplementation :
2432 """
@@ -40,6 +48,9 @@ def __init__(self, variant: RegexVariantName) -> None:
4048
4149 self .check_format = self ._real_implementation .check_format
4250 self .pattern_keyword = self ._real_implementation .pattern_keyword
51+ self .patternProperties_keyword = (
52+ self ._real_implementation .patternProperties_keyword
53+ )
4354
4455
4556class _UnicodeRegressImplementation :
@@ -65,6 +76,27 @@ def pattern_keyword(
6576 if not regress_pattern .find (instance ):
6677 yield jsonschema .ValidationError (f"{ instance !r} does not match { pattern !r} " )
6778
79+ def patternProperties_keyword (
80+ self ,
81+ validator : t .Any ,
82+ patternProperties : dict [str , t .Any ],
83+ instance : dict [str , t .Any ],
84+ schema : t .Any ,
85+ ) -> t .Iterator [jsonschema .ValidationError ]:
86+ if not validator .is_type (instance , "object" ):
87+ return
88+
89+ for pattern , subschema in patternProperties .items ():
90+ regress_pattern = regress .Regex (pattern , flags = "u" )
91+ for k , v in instance .items ():
92+ if regress_pattern .find (k ):
93+ yield from validator .descend (
94+ v ,
95+ subschema ,
96+ path = k ,
97+ schema_path = pattern ,
98+ )
99+
68100
69101class _NonunicodeRegressImplementation :
70102 def check_format (self , instance : t .Any ) -> bool :
@@ -89,6 +121,27 @@ def pattern_keyword(
89121 if not regress_pattern .find (instance ):
90122 yield jsonschema .ValidationError (f"{ instance !r} does not match { pattern !r} " )
91123
124+ def patternProperties_keyword (
125+ self ,
126+ validator : t .Any ,
127+ patternProperties : dict [str , t .Any ],
128+ instance : dict [str , t .Any ],
129+ schema : t .Any ,
130+ ) -> t .Iterator [jsonschema .ValidationError ]:
131+ if not validator .is_type (instance , "object" ):
132+ return
133+
134+ for pattern , subschema in patternProperties .items ():
135+ regress_pattern = regress .Regex (pattern )
136+ for k , v in instance .items ():
137+ if regress_pattern .find (k ):
138+ yield from validator .descend (
139+ v ,
140+ subschema ,
141+ path = k ,
142+ schema_path = pattern ,
143+ )
144+
92145
93146class _PythonImplementation :
94147 def check_format (self , instance : t .Any ) -> bool :
@@ -112,3 +165,23 @@ def pattern_keyword(
112165 yield jsonschema .ValidationError (f"pattern { pattern !r} failed to compile" )
113166 if not re_pattern .search (instance ):
114167 yield jsonschema .ValidationError (f"{ instance !r} does not match { pattern !r} " )
168+
169+ def patternProperties_keyword (
170+ self ,
171+ validator : t .Any ,
172+ patternProperties : dict [str , t .Any ],
173+ instance : dict [str , t .Any ],
174+ schema : t .Any ,
175+ ) -> t .Iterator [jsonschema .ValidationError ]:
176+ if not validator .is_type (instance , "object" ):
177+ return
178+
179+ for pattern , subschema in patternProperties .items ():
180+ for k , v in instance .items ():
181+ if re .search (pattern , k ):
182+ yield from validator .descend (
183+ v ,
184+ subschema ,
185+ path = k ,
186+ schema_path = pattern ,
187+ )
0 commit comments