Source code for manim.utils.config_ops

"""Utilities that might be useful for configuration dictionaries."""

from __future__ import annotations

__all__ = [
    "merge_dicts_recursively",
    "update_dict_recursively",
    "DictAsObject",
]


import itertools as it

import numpy as np


[docs]def merge_dicts_recursively(*dicts): """ Creates a dict whose keyset is the union of all the input dictionaries. The value for each key is based on the first dict in the list with that key. dicts later in the list have higher priority When values are dictionaries, it is applied recursively """ result = {} all_items = it.chain(*(d.items() for d in dicts)) for key, value in all_items: if key in result and isinstance(result[key], dict) and isinstance(value, dict): result[key] = merge_dicts_recursively(result[key], value) else: result[key] = value return result
[docs]def update_dict_recursively(current_dict, *others): updated_dict = merge_dicts_recursively(current_dict, *others) current_dict.update(updated_dict)
# Occasionally convenient in order to write dict.x instead of more laborious # (and less in keeping with all other attr accesses) dict["x"]
[docs]class DictAsObject: def __init__(self, dictin): self.__dict__ = dictin
class _Data: """Descriptor that allows _Data variables to be grouped and accessed from self.data["attr"] via self.attr. self.data attributes must be arrays. """ def __set_name__(self, obj, name): self.name = name def __get__(self, obj, owner): return obj.data[self.name] def __set__(self, obj, array: np.ndarray): obj.data[self.name] = array class _Uniforms: """Descriptor that allows _Uniforms variables to be grouped from self.uniforms["attr"] via self.attr. self.uniforms attributes must be floats. """ def __set_name__(self, obj, name): self.name = name def __get__(self, obj, owner): return obj.__dict__["uniforms"][self.name] def __set__(self, obj, num: float): obj.__dict__["uniforms"][self.name] = num