Source code for blueprints.thing.unique

"""
.. note::
	If you found yourself here not being a dev, you should probably :mod:`skip this section <blueprints.utils>` from or 
	look up the correspinging docs page of the Thing you were looking after for which this module only 
	implements its corresponding mirror types. A link to the docs page is to be found in the Types doc 
	string.
"""



import blueprints as blue
from blueprints import restrict
from . import base

import numpy as np
import inspect
import xml.etree.ElementTree as xml
from copy import copy
from collections import defaultdict



[docs] class UniqueThing(blue.UniqueThingType, base.BaseThing): """ Things that have multiple parents and that should not be copied to often can inherit from :class:`UniqueThing`. If the attributes of this Thing should be altered for one parent but stay the same for other parents, a copy is created which then can be altered. If the the Thing has only one parent the attributes are instead altered directly. To do this, parents can call the :meth:`_prepare_for_modification` method passing themselves which returns either a copy of the Thing or the Thing itself which can then be altered. >>> alterable_child = node_thing.unique_thing._prepare_for_modification(node_thing) >>> atterable_child.attr = value This usecase is important if a Thing is modified often, but contains large amounts of data like :class:`blueprints.cache.MeshCache` to avoid redundant copies. Parameters ---------- **kwargs Keyword arguments are passed to ``super().__init__`` Attributes ---------- freeze : bool Setting this attribute freezes the setting of other attributes until it is unset. """
[docs] def __init__(self, **kwargs): """ Parameters ---------- **kwargs Keyword arguments are passed to ``super().__init__`` """ self._references = set() self.freeze = False super().__init__(**kwargs) assert hasattr(self, '_REFERENCE_NAME')
def __setattr__(self, attr, val): """ Parameters ---------- attr : str The name of the attribute val : object The value assigned to the attribute """ if attr == 'freeze' or not hasattr(self, 'freeze') or not self.freeze: super().__setattr__(attr, val) def _remove(self, thing): """ Parameters ---------- thing : ThingType thing is detached as a parent of the :class:`UniqueThing`. """ if thing in self: self._references.remove(thing) def _add(self, thing): """ Parameters ---------- thing : ThingType thing is added as a parent of the :class:`UniqueThing`. """ if thing not in self: if hasattr(thing, self._REFERENCE_NAME): getattr(thing, self._REFERENCE_NAME)._remove(thing) self._references.add(thing) setattr(thing, self._REFERENCE_NAME, self) def _prepare_for_modification(self, parent): """ Parameters ---------- parent : ThingType The parent is given such that if a copy is generated if can be detached from the :class:`UniqueThing` parents. """ assert getattr(parent, self._REFERENCE_NAME) is self assert parent in self #if self.parent is not None: # self.root = self.parent.root if len(self._references) > 1 and not self.freeze:# and (not isinstance(self.root, blue.WorldType) or not self.root._is_built): thing = self.copy() thing._add(parent) def __contains__(self, thing): """ Parameters ---------- thing : ThingType A potential parent of this instance Returns ------- bool Indicates whether thing is a parent of this instance. """ return thing in self._references