def traverse_one(self, attribute, source, target, visitor): """ :param source: source data proxy :type source: instance of `DataTraversalProxy` or None :param target: target data proxy :type target: instance of `DataTraversalProxy` or None """ if __debug__: self.__log_traverse_one(self.__trv_path, attribute, source, target) prx = source or target if prx.do_traverse(): rel_op = RELATION_OPERATIONS.check(source, target) for attr in prx.get_relationship_attributes(): # Check cascade settings. if not bool(attr.cascade & rel_op): continue if not source is None: try: attr_source = source.get_attribute_proxy(attr) except AttributeError: # If the source does not have the attribute set, we # do nothing (as opposed to when the value is None). continue else: attr_source = None if not target is None: attr_target = target.get_attribute_proxy(attr) else: attr_target = None attr_rel_op = RELATION_OPERATIONS.check(attr_source, attr_target) if attr_rel_op == RELATION_OPERATIONS.ADD: if rel_op == RELATION_OPERATIONS.ADD: parent = source else: parent = target elif attr_rel_op == RELATION_OPERATIONS.REMOVE: parent = target else: # UPDATE parent = target card = get_attribute_cardinality(attr) if card == CARDINALITY_CONSTANTS.ONE: if attr_source is None and attr_target is None: # If both source and target have None values, there is # nothing to do. continue if attr_rel_op == RELATION_OPERATIONS.ADD: # if not attr_source.get_id() is None: # # We only ADD new items. # continue src_items = [attr_source] tgt_items = None elif attr_rel_op == RELATION_OPERATIONS.REMOVE: src_items = None tgt_items = [attr_target] else: # UPDATE src_items = [attr_source] tgt_items = [attr_target] src_id = attr_source.get_id() tgt_id = attr_target.get_id() if src_id != tgt_id: if not src_id is None: # If the source ID is None, this is a replace # operation (ADD source, REMOVE target). src_target = attr_target.get_matching(src_id) if not src_target is None: tgt_items.append(src_target) else: src_items = attr_source tgt_items = attr_target self.__trv_path.push(parent, (source, target), attr, rel_op) self.traverse_many(attr, src_items, tgt_items, visitor) self.__trv_path.pop() # path.pop() visitor.visit(self.__trv_path, attribute, source, target)
def test_get_attribute_cardinality(self): self.assert_equal(get_attribute_cardinality(self.member_attr), CARDINALITY_CONSTANTS.ONE) self.assert_raises(ValueError, get_attribute_cardinality, self.terminal_attr)
def test_get_attribute_cardinality(self, attr_name): mb_attr = member_attribute(Member, attr_name) assert get_attribute_cardinality(mb_attr) == CARDINALITY_CONSTANTS.ONE t_attr = terminal_attribute(int, attr_name) with pytest.raises(ValueError): get_attribute_cardinality(t_attr)
def traverse_one(self, attribute, source, target, visitor): """ :param source: source data proxy :type source: instance of `DataTraversalProxy` or None :param target: target data proxy :type target: instance of `DataTraversalProxy` or None """ if __debug__: self.__log_traverse_one(self.__trv_path, attribute, source, target) prx = source or target rel_op = RELATION_OPERATIONS.check(source, target) if prx.do_traverse() \ and (rel_op == prx.relation_operation or attribute is None): for attr in prx.get_relationship_attributes(): # Check cascade settings. if not bool(attr.cascade & rel_op): continue if not source is None: try: attr_source = source.get_attribute_proxy(attr) except AttributeError: # If the source does not have the attribute set, we # do nothing (as opposed to when the value is None). continue else: attr_source = None if not target is None: attr_target = target.get_attribute_proxy(attr) else: attr_target = None attr_rel_op = RELATION_OPERATIONS.check( attr_source, attr_target) if attr_rel_op == RELATION_OPERATIONS.ADD: if rel_op == RELATION_OPERATIONS.ADD: parent = source else: parent = target elif attr_rel_op == RELATION_OPERATIONS.REMOVE: parent = target else: # UPDATE parent = target card = get_attribute_cardinality(attr) if card == CARDINALITY_CONSTANTS.ONE: if attr_source is None and attr_target is None: # If both source and target have None values, there is # nothing to do. continue if attr_rel_op == RELATION_OPERATIONS.ADD: # if not attr_source.get_id() is None: # # We only ADD new items. # continue src_items = [attr_source] tgt_items = None elif attr_rel_op == RELATION_OPERATIONS.REMOVE: src_items = None tgt_items = [attr_target] else: # UPDATE src_items = [attr_source] tgt_items = [attr_target] src_id = attr_source.get_id() tgt_id = attr_target.get_id() if src_id != tgt_id: if not src_id is None: # If the source ID is None, this is a replace # operation (ADD source, REMOVE target). src_target = attr_target.get_matching(src_id) if not src_target is None: tgt_items.append(src_target) else: src_items = attr_source tgt_items = attr_target self.__trv_path.push(parent, (source, target), attr, rel_op) self.traverse_many(attr, src_items, tgt_items, visitor) self.__trv_path.pop() # path.pop() visitor.visit(self.__trv_path, attribute, source, target)