def new(): """ Create an empty I/O data set. Returns: An empty I/O data set adhering to the latest schema version. """ data = dict( version=dict(major=schema.LATEST.major, minor=schema.LATEST.minor)) assert schema.is_valid_latest(data) return data
def to_io(oo_data): """ Convert OO data to I/O data. Args: oo_data: The OO data to convert to I/O data. Returns: The converted I/O data. """ io_data = _to_io(oo_data) assert schema.is_valid_latest(io_data) return io_data
def _obj_list_from_io(oo_data, io_data, obj_list_name): """ Convert I/O data for an object list and all its children to OO data. Args: oo_data: The OO data to output the converted objects into. io_data: The I/O data to get the original objects from. obj_list_name: The name of the object list to convert. """ assert isinstance(oo_data, dict) assert schema.is_valid_latest(io_data) assert isinstance(obj_list_name, str) assert obj_list_name.endswith("s") obj_name = obj_list_name[:-1] child_list_name_list = schema.LATEST.tree[obj_list_name] # Convert all objects in this list, add child map attributes oo_obj_map = { io_obj['id']: NODE_CLASS_MAP.get(obj_list_name, Node)(io_obj, {n + "_": {} for n in child_list_name_list}) for io_obj in io_data.get(obj_list_name, []) } # For each child object list for child_list_name in child_list_name_list: # Convert all child objects _obj_list_from_io(oo_data, io_data, child_list_name) # For each child object for oo_child_id, oo_child in oo_data.get(child_list_name, {}).items(): # Get the child's parent, if we can oo_obj_id = getattr(oo_child, obj_name + "_id") oo_obj = oo_obj_map.get(oo_obj_id, None) # Link parent from child setattr(oo_child, obj_name + "_", oo_obj) # Link child from parent, if any if oo_obj: getattr(oo_obj, child_list_name + "_")[oo_child_id] = oo_child # Output the converted object map, if not empty if oo_obj_map: oo_data[obj_list_name] = oo_obj_map
def merge(target, source, copy_target=True, copy_source=True): """ Merge one I/O data into another. Args: target: The data to merge into. source: The data to merge from. copy_target: True if "target" contents should be copied before upgrading and modifying. False if not. Default is True. copy_source: True if "source" contents should be copied before upgrading and referencing. False if not. Default is True. Returns: The merged data, adhering to the latest schema version. """ assert schema.is_valid(target) assert schema.is_valid(source) # Make sure the data is copied, if requested if copy_target: target = deepcopy(target) if copy_source: source = deepcopy(source) # Upgrade without copying, even if modifications are needed target = schema.upgrade(target, copy=False) source = schema.upgrade(source, copy=False) for obj_list_name in schema.LATEST.tree: if obj_list_name: target[obj_list_name] = \ target.get(obj_list_name, []) + source.get(obj_list_name, []) assert schema.is_valid_latest(target) return target
def is_valid(oo_data): """ Check that OO data is valid. Args: oo_data: The OO data to check. Returns: True if the OO data is valid, false otherwise. """ if not isinstance(oo_data, dict): return False required_keys = set(("version", )) allowed_keys = \ (set(schema.LATEST.tree.keys()) | set(("version",))) - set(("",)) if not set(oo_data.keys()) & required_keys: return False if set(oo_data.keys()) > allowed_keys: return False # pylint: disable=fixme # TODO Validate tree node types and object links return schema.is_valid_latest(_to_io(oo_data))