def check_relations_rules(self, old, new, rules, path): keys = rules.get('relations', []) + rules.get('relinks', []) cls = type(old) mapper = inspect(cls) for key in keys: prop = mapper.get_property(key) remote_cls = prop.mapper.class_ classname = remote_cls.__name__ old_value = getattr(old, key) new_value = getattr(new, key) new_path = "%s.%s" % (path, key) collection_class = duck_type_collection(old_value) if collection_class: self.compare_collections(old_value, new_value, new_path, classname) else: self.compare_objects(old_value, new_value, new_path)
def field_kwargs_from_relationship(cls, key, attr, model): kwargs = {'name': attr.key} prop = attr.property data_type = get_related_class_from_attr(attr) if prop.collection_class: collection_class = duck_type_collection(prop.collection_class) elif prop.uselist: collection_class = list else: collection_class = None kwargs['data_type'] = data_type kwargs['uselist'] = prop.uselist kwargs['editable'] = not prop.viewonly kwargs['nullable'] = True if collection_class: kwargs['collection_class'] = [collection_class] return kwargs
def field_kwargs_from_relationship(cls, key, attr, model): kwargs = {'name': attr.key} prop = attr.property data_type = get_related_class_from_attr(attr) if prop.collection_class: collection_class = duck_type_collection(prop.collection_class) elif prop.uselist: collection_class = list else: collection_class = None kwargs['data_type'] = data_type kwargs['uselist'] = prop.uselist kwargs['editable'] = not prop.viewonly kwargs['nullable'] = True if collection_class: kwargs['collection_class'] = [collection_class] return kwargs
def check_relations_rules(self, old, new, rules, path): keys = rules.get('relations', []) + rules.get('relinks', []) cls = type(old) mapper = inspect(cls) for key in keys: prop = mapper.get_property(key) remote_cls = prop.mapper.class_ classname = remote_cls.__name__ old_value = getattr(old, key) new_value = getattr(new, key) new_path = "%s.%s" % (path, key) collection_class = duck_type_collection(old_value) if collection_class: self.compare_collections(old_value, new_value, new_path, classname) else: self.compare_objects(old_value, new_value, new_path)
def validate_collection(self, data, collection_class=None): if collection_class is None: collection_class = self.collection_class[:] if collection_class == []: # we've drilled down through all collections, now we # check the class type if available if self.related_class and not isinstance(data, self.related_class): raise forms.ValidationError(_("Expected %s, got %s") % (self.related_class, type(data))) return expected_class = collection_class.pop(0) found_class = duck_type_collection(data) if found_class != expected_class: raise forms.ValidationError(_("Expected %s, got %s") % (expected_class, found_class)) values = data.itervalues() if isinstance(data, dict) else iter(data) for v in values: self.validate_collection(v, collection_class)
def field_kwargs_from_proxy(cls, key, attr, model): proxy = getattr(model, key) kwargs = cls.field_kwargs_from_attr(key, attr.remote_attr, model) prop = attr.local_attr.property if prop.collection_class: collection_class = duck_type_collection(prop.collection_class) elif prop.uselist: collection_class = list else: collection_class = None collections = kwargs.get('collection_class', []) if collection_class: collections.insert(0, collection_class) kwargs['collection_class'] = collections kwargs['name'] = key kwargs['proxy'] = True kwargs['nullable'] = True return kwargs
def field_kwargs_from_proxy(cls, key, attr, model): proxy = getattr(model, key) kwargs = cls.field_kwargs_from_attr(key, attr.remote_attr, model) prop = attr.local_attr.property if prop.collection_class: collection_class = duck_type_collection(prop.collection_class) elif prop.uselist: collection_class = list else: collection_class = None collections = kwargs.get('collection_class', []) if collection_class: collections.insert(0, collection_class) kwargs['collection_class'] = collections kwargs['name'] = key kwargs['proxy'] = True kwargs['nullable'] = True return kwargs
def validate_collection(self, data, collection_class=None): if collection_class is None: collection_class = self.collection_class[:] if collection_class == []: # we've drilled down through all collections, now we # check the class type if available if self.related_class and not isinstance(data, self.related_class): raise forms.ValidationError( _('Expected %s, got %s') % (self.related_class, type(data))) return expected_class = collection_class.pop(0) found_class = duck_type_collection(data) if found_class != expected_class: raise forms.ValidationError( _('Expected %s, got %s') % (expected_class, found_class)) values = data.itervalues() if isinstance(data, dict) else iter(data) for v in values: self.validate_collection(v, collection_class)
def normalize_collections(self, old, new): self.assertEqual( type(old), type(new), 'Collections have different classes. (initial=%s, cloned=%s)' % (type(old), type(new))) if type(old) == OrderingList: collection_class = OrderingList else: collection_class = duck_type_collection(old) if collection_class == OrderingList: # ordering is important here, so we pass through unmodified pass elif collection_class == dict: # we want to compare objects with matching keys, so we order # the objects by key self.assertItemsEqual(old.keys(), new.keys(), 'mapped collections have different keys') old = [i[1] for i in sorted(old.items())] new = [i[1] for i in sorted(new.items())] elif collection_class == list: # this is an unordered list, so we need to manually order # related items to prevent future tests from failing new_ = [] for obj in old: ident = identity_key(instance=obj) clone = self.registry[ident] if isinstance(clone, tuple): # this is an identity key idents = {identity_key(instance=i): i for i in new} self.assertIn(clone, idents) new_.append(idents[clone]) else: # this is an actual object self.assertIn(clone, new) new_.append(clone) new = new_ return (old, new)
def normalize_collections(self, old, new): self.assertEqual(type(old), type(new), 'Collections have different classes. (initial=%s, cloned=%s)' % (type(old), type(new))) if type(old) == OrderingList: collection_class = OrderingList else: collection_class = duck_type_collection(old) if collection_class == OrderingList: # ordering is important here, so we pass through unmodified pass elif collection_class == dict: # we want to compare objects with matching keys, so we order # the objects by key self.assertItemsEqual(old.keys(), new.keys(), 'mapped collections have different keys') old = [i[1] for i in sorted(old.items())] new = [i[1] for i in sorted(new.items())] elif collection_class == list: # this is an unordered list, so we need to manually order # related items to prevent future tests from failing new_ = [] for obj in old: ident = identity_key(instance=obj) clone = self.registry[ident] if isinstance(clone, tuple): # this is an identity key idents = {identity_key(instance=i): i for i in new} self.assertIn(clone, idents) new_.append(idents[clone]) else: # this is an actual object self.assertIn(clone, new) new_.append(clone) new = new_ return (old, new)
def clone_collection(self, value, **kwargs): if not value: return value collection_class = duck_type_collection(value) if collection_class == dict: # mapped onetomany or manytomany items = {} for name, item in value.items(): new_item = self.clone_obj(item, **kwargs) items[name] = new_item return items elif collection_class == list: # onetomany or manytomany items = [] for item in value: new_item = self.clone_obj(item, **kwargs) items.append(new_item) return items else: # onetoone or manytoone item = self.clone_obj(value, **kwargs) return item
def clone_collection(self, value, **kwargs): if not value: return value collection_class = duck_type_collection(value) if collection_class == dict: # mapped onetomany or manytomany items = {} for name, item in value.items(): new_item = self.clone_obj(item, **kwargs) items[name] = new_item return items elif collection_class == list: # onetomany or manytomany items = [] for item in value: new_item = self.clone_obj(item, **kwargs) items.append(new_item) return items else: # onetoone or manytoone item = self.clone_obj(value, **kwargs) return item