@@ -19,6 +19,14 @@ def pattern_keyword(
19
19
self , validator : t .Any , pattern : str , instance : str , schema : t .Any
20
20
) -> t .Iterator [jsonschema .ValidationError ]: ...
21
21
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
+
22
30
23
31
class RegexImplementation :
24
32
"""
@@ -40,6 +48,9 @@ def __init__(self, variant: RegexVariantName) -> None:
40
48
41
49
self .check_format = self ._real_implementation .check_format
42
50
self .pattern_keyword = self ._real_implementation .pattern_keyword
51
+ self .patternProperties_keyword = (
52
+ self ._real_implementation .patternProperties_keyword
53
+ )
43
54
44
55
45
56
class _UnicodeRegressImplementation :
@@ -65,6 +76,27 @@ def pattern_keyword(
65
76
if not regress_pattern .find (instance ):
66
77
yield jsonschema .ValidationError (f"{ instance !r} does not match { pattern !r} " )
67
78
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
+
68
100
69
101
class _NonunicodeRegressImplementation :
70
102
def check_format (self , instance : t .Any ) -> bool :
@@ -89,6 +121,27 @@ def pattern_keyword(
89
121
if not regress_pattern .find (instance ):
90
122
yield jsonschema .ValidationError (f"{ instance !r} does not match { pattern !r} " )
91
123
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
+
92
145
93
146
class _PythonImplementation :
94
147
def check_format (self , instance : t .Any ) -> bool :
@@ -112,3 +165,23 @@ def pattern_keyword(
112
165
yield jsonschema .ValidationError (f"pattern { pattern !r} failed to compile" )
113
166
if not re_pattern .search (instance ):
114
167
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