Skip to content

Instantly share code, notes, and snippets.

@shauneccles
Created February 21, 2024 04:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shauneccles/8b56f524a2731e14d79f4df7e333296c to your computer and use it in GitHub Desktop.
Save shauneccles/8b56f524a2731e14d79f4df7e333296c to your computer and use it in GitHub Desktop.
Vol healer
def create(self, type, id=None, *args, **kwargs):
"""Loads and creates a object from the registry by type"""
if type not in self._cls.registry():
raise AttributeError(
("Couldn't find '{}' in the {} registry").format(
type, self._cls.__name__.lower()
)
)
id = id or type
# Find the first valid id based on what is already in the registry
dupe_id = id
dupe_index = 1
while id in self._objects:
id = f"{dupe_id}-{dupe_index}"
dupe_index = dupe_index + 1
# Create the new object based on the registry entires and
# validate the schema.
_cls = self._cls.registry().get(type)
_config = kwargs.pop("config", None)
if _config is not None:
try:
_config = _cls.schema()(_config)
except vol.Invalid as e:
broken_config = _config
fixed_config = handle_voluptuous_error(broken_config, self._ledfx.config_dir,e)
broken_config_dict = {"id":id,"type":type,"config":broken_config}
fixed_config_dict = {"id":id,"type":type,"config": fixed_config}
print("Broken config:", broken_config_dict)
print("Fixed config:", fixed_config_dict)
print("Config before update:", self._ledfx.config)
_config = _cls.schema()(fixed_config)
self._ledfx.config = find_and_update_config(self._ledfx.config, broken_config_dict, fixed_config_dict)
print("Config after update:", self._ledfx.config)
obj = _cls(config=_config, *args, **kwargs)
else:
obj = _cls(*args, **kwargs)
# Attach some common properties
setattr(obj, "_id", id)
setattr(obj, "_type", type)
# Store the object into the internal list and return it
self._objects[id] = obj
return obj
def handle_voluptuous_error(malformed_config, config_dir, e):
_LOGGER.warning("Attempting to fix config with best effort.")
create_backup(config_dir, "CREATE_FAIL")
fixed_config = dict(malformed_config) # copy the original config
for error in e.errors:
# get the key from the error message
key_with_error = error.path.pop(0)
match = re.search(r"value must be one of \[(.*)\]", error.error_message)
if match:
value = match.group(1)
# if the value starts with a '[', it's a list of allowed values
if value[0] == "'":
# remove the brackets and split the string into a list
value = value[1:-1].split("', '")
# set the value to the first non-empty string in the list
value = next((v for v in value if v != ""), "")
# if the value does not start with a '[', it's a single allowed value
else:
# strip quotes from the value
value = value.strip("'")
# check if the key exists in the fixed config
_LOGGER.warn(f"Replacing incorrect value {fixed_config[key_with_error]} with {value} for key {key_with_error}")
# set the value in the fixed config
fixed_config[key_with_error] = value
else:
_LOGGER.error(f"Unexpected error message format: {error.error_message}")
return fixed_config
def find_and_update_config(ledfx_config, target_config, fixed_config):
"""
Recursively searches for a target configuration dictionary within the ledfx_config dictionary
and updates it with the fixed_config dictionary.
Args:
ledfx_config (dict): The dictionary to search within.
target_config (dict): The target configuration dictionary to find.
fixed_config (dict): The dictionary to update the target configuration with.
"""
for key, value in ledfx_config.items():
if isinstance(value, dict):
if all(item in value.items() for item in target_config.items()):
# Found the target config, update it with the fixed config
ledfx_config[key] = {**value, **fixed_config}
else:
# Continue the search in the nested dictionary regardless of whether it matches target_config
ledfx_config[key] = find_and_update_config(value, target_config, fixed_config)
return ledfx_config
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment