@_func_wrapper
    def save(self, obj, where="/", cascade=True, lazy=False):
        """ Saves changes of a given object to the file. Saves object as new at
        location "where" if it is not in the file yet. Returns saved node.

        cascade: True/False process downstream relationships
        lazy: True/False process any quantity/ndarray attributes """

        def assign_attribute(obj_attr, attr_name, path, node):
            """ subfunction to serialize a given attribute """
            if isinstance(obj_attr, pq.Quantity) or isinstance(obj_attr, np.ndarray):
                if not lazy:
                    # we need to simplify custom quantities
                    if isinstance(obj_attr, pq.Quantity):
                        for un in obj_attr.dimensionality.keys():
                            if not un.name in pq.units.__dict__ or \
                                    not isinstance(pq.units.__dict__[un.name], pq.Quantity):
                                obj_attr = obj_attr.simplified
                                break

                    # we try to create new array first, so not to loose the
                    # data in case of any failure
                    if obj_attr.size == 0:
                        np_type = obj_attr.dtype if self.array_dtype is None else self.array_dtype
                        atom = tb.Atom.from_dtype(np.dtype((np_type, (1, ))))
                        new_arr = self._data.createEArray(path, attr_name + "__temp", atom, shape=(0,), expectedrows=1)
                    else:
                        new_arr = self._data.createArray(path, attr_name + "__temp", obj_attr)

                    if hasattr(obj_attr, "dimensionality"):
                        for un in obj_attr.dimensionality.items():
                            new_arr._f_setAttr("unit__" + un[0].name, un[1])
                    try:
                        self._data.removeNode(path, attr_name)
                    except:
                        pass # there is no array yet or object is new
                    self._data.renameNode(path, attr_name, name=attr_name + "__temp")
            elif obj_attr is not None:
                node._f_setAttr(attr_name, obj_attr)

        #assert_neo_object_is_compliant(obj)
        obj_type = obj.__class__.__name__
        if self._data.mode != 'w' and hasattr(obj, "hdf5_path"): # this is an update case
            path = str(obj.hdf5_path)
            try:
                node = self._data.getNode(obj.hdf5_path)
            except tb.NoSuchNodeError:  # create a new node?
                raise LookupError("A given object has a path %s attribute, \
                    but such an object does not exist in the file. Please \
                    correct these values or delete this attribute \
                    (.__delattr__('hdf5_path')) to create a new object in \
                    the file." % path)
        else: # create new object
            node = self._data.createGroup(where, self._get_next_name(obj_type, where))
            node._f_setAttr("_type", obj_type)
            path = node._v_pathname
            # processing attributes
         # Initialize empty parent paths
        if 1 > len(getattr(obj, '_single_parent_containers', [])):
            for par_cont in obj._single_parent_containers:
                node._f_setAttr(par_cont, '')
        # we checked already obj is compliant, loop over all safely
        for attr in obj._all_attrs:
            if hasattr(obj, attr[0]): # save an attribute if exists
                assign_attribute(getattr(obj, attr[0]), attr[0], path, node)
            # not forget to save AS, ASA or ST - NEO "stars"
        if hasattr(obj, '_quantity_attr'):
            assign_attribute(obj, obj._quantity_attr, path, node)
        if hasattr(obj, "annotations"): # annotations should be just a dict
            node._f_setAttr("annotations", getattr(obj, "annotations"))
        node._f_setAttr("object_ref", uuid.uuid4().hex)
        if cascade:
            # container is like segments, spiketrains, etc.
            for container in getattr(obj, '_child_containers', []):
                try:
                    ch = self._data.getNode(node, container)
                except tb.NoSuchNodeError:
                    ch = self._data.createGroup(node, container)
                saved = []  # keeps track of saved object names for removal
                for child in getattr(obj, container):
                    new_name = None
                    child_node = None
                    if hasattr(child, "hdf5_path"):
                        if not child.hdf5_path.startswith(ch._v_pathname):
                        # create a Hard Link if object exists already somewhere
                            try:
                                target = self._data.getNode(child.hdf5_path)
                                new_name = self._get_next_name(
                                    child.__class__.__name__, ch._v_pathname)
                                if not hasattr(ch, new_name):  # Only link if path does not exist
                                    child_node = self._data.createHardLink(ch._v_pathname, new_name, target)
                            except tb.NoSuchNodeError:
                                pass
                    if child_node is None:
                        child_node = self.save(child, where=ch._v_pathname)

                    if len(child._single_parent_containers) > 1:
                        child_node._f_setAttr(obj_type.lower(), path)
                    for par_cont in child._multi_parent_containers:
                        parents = []
                        if par_cont in child_node._v_attrs:
                            parents = child_node._v_attrs[par_cont]
                        parents.append(path)
                        child_node._f_setAttr(par_cont, parents)
                    if not new_name:
                        new_name = child.hdf5_path.split('/')[-1]
                    saved.append(new_name)
                for child in self._data.iterNodes(ch._v_pathname):
                    if child._v_name not in saved: # clean-up
                        self._data.removeNode(ch._v_pathname, child._v_name, recursive=True)

        self._update_path(obj, node)
        return node
dataset/ETHPy150Open NeuralEnsemble/python-neo/neo/io/hdf5io.py/NeoHdf5IO.save/swapped operands of `>`