@@ -118,48 +118,48 @@ def _get_object_properties_schema(object_schema, objecy_keys=None):
118118
119119 :rtype: ``dict``
120120 """
121- flattened_properties_schema = {}
122-
123- # First, eagerly add the additionalProperties schema for all object_keys to
124- # avoid tracking which keys are covered by patternProperties and properties.
125- # This schema will subsequently be replaced by the more-specific key matches
126- # in patternProperties and properties.
127-
128- additional_properties = object_schema .get ("additionalProperties" , {})
129- # additionalProperties can be a boolean or a dict
130- if additional_properties and isinstance (additional_properties , dict ):
131- # ensure that these keys are present in the object
132- for key in object_keys :
133- flattened_properties_schema [key ] = additional_properties
134-
135- # Second, replace the additionalProperties schemas with any
136- # explicit property schemas in propertiea.
121+ # preserve the order in object_keys
122+ flattened_properties_schema = {key : {} for key in object_keys }
137123
124+ # properties takes precedence over patternProperties and additionalProperties
138125 properties_schema = object_schema .get ("properties" , {})
139126 flattened_properties_schema .update (properties_schema )
140127
141- # Third, calculate which keys are in object_keys but not in properties.
142- # These are the only keys that can be matched with patternnProperties.
128+ # extra_keys has keys that may use patternProperties or additionalProperties
129+ # we remove keys when they have been assigned a schema
130+ extra_keys = set (objecy_keys ) - set (properties_schema .keys ())
143131
144- potential_patterned_keys = set (objecy_keys ) - set (properties_schema .keys ())
145-
146- # Fourth, match the remaining keys with patternProperties,
147- # and replace the additionalProperties schema with the patternProperties schema
148- # because patternProperties is more specific than additionalProperties.
132+ if not extra_keys :
133+ # nothing to check. Don't look at patternProperties or additionalProperties.
134+ return flattened_properties_schema
149135
136+ # match each key against patternPropetties
150137 pattern_properties = object_schema .get ("patternProperties" , {})
151138 # patternProperties can be a boolean or a dict
152139 if pattern_properties and isinstance (pattern_properties , dict ):
153- # update any matching key
154140 for raw_pattern , pattern_schema in pattern_properties .items ():
155- if not potential_patterned_keys :
156- # nothing to check. Don't compile any more patterns
157- break
158141 pattern = re .compile (raw_pattern )
159- for key in list (potential_patterned_keys ):
142+ for key in list (extra_keys ):
160143 if pattern .search (key ):
144+ # update matched key
161145 flattened_properties_schema [key ] = pattern_schema
162- potential_patterned_keys .remove (key )
146+ # don't check matched key against any more patterns
147+ # and don't overwrite with additionalProperties
148+ extra_keys .remove (key )
149+
150+ if not extra_keys :
151+ # nothing to check. Don't compile any more patterns
152+ # and don't look at additionalProperties.
153+ return flattened_properties_schema
154+
155+ # fill in any remaining keys with additionalProperties
156+ additional_properties = object_schema .get ("additionalProperties" , {})
157+ # additionalProperties can be a boolean or a dict
158+ if additional_properties and isinstance (additional_properties , dict ):
159+ # ensure that these keys are present in the object
160+ for key in extra_keys :
161+ flattened_properties_schema [key ] = additional_properties
162+
163163 return flattened_properties_schema
164164
165165 @staticmethod
0 commit comments