Skip to content

Commit 54512dc

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 54512dc

File tree

1 file changed

+41
-14
lines changed

1 file changed

+41
-14
lines changed

st2common/st2common/util/config_loader.py

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -100,28 +100,55 @@ 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)
140+
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.
120143

121-
potential_patterned_keys = set(additional_properties_keys) - set(
144+
potential_patterned_keys = set(objecy_keys) - set(
122145
properties_schema.keys()
123146
)
124147

148+
# Fourth, match the remaining keys with patternProperties,
149+
# and replace the additionalProperties schema with the patternProperties schema
150+
# because patternProperties is more specific than additionalProperties.
151+
125152
pattern_properties = object_schema.get("patternProperties", {})
126153
# patternProperties can be a boolean or a dict
127154
if pattern_properties and isinstance(pattern_properties, dict):
@@ -133,9 +160,9 @@ def _get_object_property_schema(object_schema, additional_properties_keys=None):
133160
pattern = re.compile(raw_pattern)
134161
for key in list(potential_patterned_keys):
135162
if pattern.search(key):
136-
property_schema[key] = pattern_schema
163+
flattened_properties_schema[key] = pattern_schema
137164
potential_patterned_keys.remove(key)
138-
return property_schema
165+
return flattened_properties_schema
139166

140167
@staticmethod
141168
def _get_array_items_schema(object_schema, items_count=0):
@@ -204,12 +231,12 @@ def _assign_dynamic_config_values(self, schema, config, parent_keys=None):
204231

205232
# Inspect nested object properties
206233
if is_dictionary:
207-
property_schema = self._get_object_property_schema(
234+
properties_schema = self._get_object_properties_schema(
208235
schema_item,
209-
additional_properties_keys=config_item_value.keys(),
236+
objecy_keys=config_item_value.keys(),
210237
)
211238
self._assign_dynamic_config_values(
212-
schema=property_schema,
239+
schema=properties_schema,
213240
config=config[config_item_key],
214241
parent_keys=current_keys,
215242
)
@@ -293,13 +320,13 @@ def _assign_default_values(self, schema, config):
293320
if not config_value:
294321
config_value = config[schema_item_key] = {}
295322

296-
property_schema = self._get_object_property_schema(
323+
properties_schema = self._get_object_properties_schema(
297324
schema_item,
298-
additional_properties_keys=config_value.keys(),
325+
objecy_keys=config_value.keys(),
299326
)
300327

301328
self._assign_default_values(
302-
schema=property_schema, config=config_value
329+
schema=properties_schema, config=config_value
303330
)
304331
elif schema_item_type == "array":
305332
has_items = schema_item.get("items", None)

0 commit comments

Comments
 (0)