Skip to content

Commit 8bffa2f

Browse files
committed
Refactor var/method names for clarity
This documents the properties schema flattening algorithm with code comments. That highlighted some vars and a method that could be renamed to clarify the code even more.
1 parent ba06db4 commit 8bffa2f

File tree

1 file changed

+41
-16
lines changed

1 file changed

+41
-16
lines changed

st2common/st2common/util/config_loader.py

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -100,27 +100,52 @@ def _get_values_for_config(self, config_schema_db, config_db):
100100
return config
101101

102102
@staticmethod
103-
def _get_object_property_schema(object_schema, additional_properties_keys=None):
103+
def _get_object_properties_schema(object_schema, objecy_keys=None):
104104
"""
105105
Create a schema for an object property using all of: properties,
106106
patternProperties, and additionalProperties.
107107
108+
This 'flattens' properties, patternProperties, and additionalProperties
109+
so that we can handle patternProperties and additionalProperties
110+
as if they were defined in properties.
111+
So, every key in objecy_keys will be assigned a schema
112+
from properties, patternProperties, or additionalProperties.
113+
114+
NOTE: order of precedence: properties, patternProperties, additionalProperties
115+
So, the additionalProperties schema is only used for keys that are not in
116+
properties and that do not match any of the patterns in patternProperties.
117+
And, patternProperties schemas only apply to keys missing from properties.
118+
108119
:rtype: ``dict``
109120
"""
110-
property_schema = {}
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+
111128
additional_properties = object_schema.get("additionalProperties", {})
112129
# additionalProperties can be a boolean or a dict
113130
if additional_properties and isinstance(additional_properties, dict):
114131
# ensure that these keys are present in the object
115-
for key in additional_properties_keys:
116-
property_schema[key] = additional_properties
132+
for key in objecy_keys:
133+
flattened_properties_schema[key] = additional_properties
134+
135+
# Second, replace the additionalProperties schemas with any
136+
# explicit property schemas in propertiea.
117137

118138
properties_schema = object_schema.get("properties", {})
119-
property_schema.update(properties_schema)
139+
flattened_properties_schema.update(properties_schema)
120140

121-
potential_patterned_keys = set(additional_properties_keys) - set(
122-
properties_schema.keys()
123-
)
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.
143+
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.
124149

125150
pattern_properties = object_schema.get("patternProperties", {})
126151
# patternProperties can be a boolean or a dict
@@ -133,9 +158,9 @@ def _get_object_property_schema(object_schema, additional_properties_keys=None):
133158
pattern = re.compile(raw_pattern)
134159
for key in list(potential_patterned_keys):
135160
if pattern.search(key):
136-
property_schema[key] = pattern_schema
161+
flattened_properties_schema[key] = pattern_schema
137162
potential_patterned_keys.remove(key)
138-
return property_schema
163+
return flattened_properties_schema
139164

140165
@staticmethod
141166
def _get_array_items_schema(object_schema, items_count=0):
@@ -204,12 +229,12 @@ def _assign_dynamic_config_values(self, schema, config, parent_keys=None):
204229

205230
# Inspect nested object properties
206231
if is_dictionary:
207-
property_schema = self._get_object_property_schema(
232+
properties_schema = self._get_object_properties_schema(
208233
schema_item,
209-
additional_properties_keys=config_item_value.keys(),
234+
objecy_keys=config_item_value.keys(),
210235
)
211236
self._assign_dynamic_config_values(
212-
schema=property_schema,
237+
schema=properties_schema,
213238
config=config[config_item_key],
214239
parent_keys=current_keys,
215240
)
@@ -293,13 +318,13 @@ def _assign_default_values(self, schema, config):
293318
if not config_value:
294319
config_value = config[schema_item_key] = {}
295320

296-
property_schema = self._get_object_property_schema(
321+
properties_schema = self._get_object_properties_schema(
297322
schema_item,
298-
additional_properties_keys=config_value.keys(),
323+
objecy_keys=config_value.keys(),
299324
)
300325

301326
self._assign_default_values(
302-
schema=property_schema, config=config_value
327+
schema=properties_schema, config=config_value
303328
)
304329
elif schema_item_type == "array":
305330
has_items = schema_item.get("items", None)

0 commit comments

Comments
 (0)