def test_update_member_with_link(self): my_entity = create_entity() new_parent = MyEntityParent() new_parent.text = self.UPDATED_TEXT new_parent.id = 2 my_entity.parent = new_parent coll = create_staging_collection(IMyEntity) member = coll.create_member(my_entity) mp = self._make_mapping() attribute_options = { ('parent', ): { WRITE_AS_LINK_OPTION: True }, ('nested_parent', ): { IGNORE_OPTION: True } } mp_cloned = mp.clone(attribute_options=attribute_options) data_el = mp_cloned.map_to_data_element(member) # The linked-to parent needs to be in the root collection. my_entity.parent = None del member del my_entity parent_coll = get_root_collection(IMyEntityParent) parent_coll.create_member(new_parent) my_entity = create_entity() coll = get_root_collection(IMyEntity) context = coll.create_member(my_entity) self.assert_equal(context.parent.text, MyEntity.DEFAULT_TEXT) context.update_from_data(data_el) self.assert_equal(context.parent.text, self.UPDATED_TEXT)
def test_update_member_with_link(self): my_entity = create_entity() new_parent = MyEntityParent() new_parent.text = self.UPDATED_TEXT new_parent.id = 2 my_entity.parent = new_parent coll = create_staging_collection(IMyEntity) member = coll.create_member(my_entity) mp = self._make_mapping() attribute_options = {('parent',):{WRITE_AS_LINK_OPTION:True}, ('nested_parent',):{IGNORE_OPTION:True}} mp_cloned = mp.clone(attribute_options=attribute_options) data_el = mp_cloned.map_to_data_element(member) # The linked-to parent needs to be in the root collection. my_entity.parent = None del member del my_entity parent_coll = get_root_collection(IMyEntityParent) parent_coll.create_member(new_parent) my_entity = create_entity() coll = get_root_collection(IMyEntity) context = coll.create_member(my_entity) self.assert_equal(context.parent.text, MyEntity.DEFAULT_TEXT) context.update_from_data(data_el) self.assert_equal(context.parent.text, self.UPDATED_TEXT)
def __build(self, op, attr_name, attr_value): infos = NoSqlAttributeInspector.inspect(self._entity_class, attr_name) is_nested = len(infos) > 1 parent_type = self._entity_class exprs = [] for info in infos[:-1]: nested_attr_kind, nested_attr_type, nested_attr_name = info root_coll = get_root_collection(parent_type) templ_map = dict(root_collection_name=root_coll.__name__, nested_attr_name=nested_attr_name, ) if nested_attr_kind == RESOURCE_ATTRIBUTE_KINDS.MEMBER: expr = self.__nested_member_query_template % templ_map else: # RESOURCE_ATTRIBUTE_KINDS.COLLECTION # FIXME: Test this. # expr = self.__nested_collection_query_template % templ_map raise NotImplementedError('Not implemented.') # pragma: no cover exprs.insert(0, expr) parent_type = nested_attr_type terminal_attr_name = infos[-1][-1] expr = self.__prepare_criterion(terminal_attr_name, op, attr_value) if is_nested: # FIXME: Need to handle value -> string conversion here. root_coll = get_root_collection(parent_type) templ_map = dict(root_collection_name=root_coll.__name__, terminal_expression=str(expr)) terminal_expr = self.__nested_terminal_query_template % templ_map expr = func_reduce(lambda g, h: h % dict(nested_expression=g), exprs, terminal_expr) return expr
def resource_to_url(self, resource, quote=False): """ Returns the URL for the given resource. :param resource: Resource to create a URL for. :param bool quote: If set, the URL returned will be quoted. :raises ValueError: If the given resource is floating (i.e., has the parent attribute set to `None`) """ ifc = provided_by(resource) if not IResource in ifc: raise TypeError('Can not generate URL for non-resource "%s".' % resource) elif resource.__parent__ is None: raise ValueError('Can not generate URL for floating resource ' '"%s".' % resource) if ICollectionResource in ifc: query = {} if not resource.filter is None: query['q'] = \ UrlPartsConverter.make_filter_string(resource.filter) if not resource.order is None: query['sort'] = \ UrlPartsConverter.make_order_string(resource.order) if not resource.slice is None: query['start'], query['size'] = \ UrlPartsConverter.make_slice_strings(resource.slice) if query != {}: options = dict(query=query) else: options = dict() if not resource.is_root_collection: # For nested collections, we check if the referenced root # collection is exposed (i.e., has the service as parent). # If yes, we return an absolute URL, else a nested URL. root_coll = get_root_collection(resource) if not root_coll.has_parent: url = self.__request.resource_url(resource, **options) else: url = self.__request.resource_url(root_coll, **options) else: url = self.__request.resource_url(resource, **options) else: if not resource.is_root_member: # For nested members, we check if the referenced root # collection is exposed (i.e., has the service as parent). # If yes, we return an absolute URL, else a nested URL. root_coll = get_root_collection(resource) if not root_coll.has_parent: par_url = self.__request.resource_url(resource) else: par_url = self.__request.resource_url(root_coll) url = "%s%s/" % (par_url, resource.__name__) else: url = self.__request.resource_url(resource) if not quote: url = url_unquote(url) return url
def resource_to_url(self, resource, quote=False): """ Returns the URL for the given resource. :param resource: Resource to create a URL for. :param bool quote: If set, the URL returned will be quoted. :raises ValueError: If the given resource is floating (i.e., has the parent attribute set to `None`) """ ifc = provided_by(resource) if not IResource in ifc: raise TypeError('Can not generate URL for non-resource "%s".' % resource) elif resource.__parent__ is None: raise ValueError('Can not generate URL for floating resource ' '"%s".' % resource) if ICollectionResource in ifc: query = {} if not resource.filter is None: query['q'] = \ UrlPartsConverter.make_filter_string(resource.filter) if not resource.order is None: query['sort'] = \ UrlPartsConverter.make_order_string(resource.order) if not resource.slice is None: query['start'], query['size'] = \ UrlPartsConverter.make_slice_strings(resource.slice) if query != {}: options = dict(query=query) else: options = dict() if not resource.is_root_collection: # For nested collections, we check if the referenced root # collection is exposed (i.e., has the service as parent). # If yes, we return an absolute URL, else a nested URL. root_coll = get_root_collection(resource) if not root_coll.has_parent: url = self.__request.resource_url(resource) else: url = self.__request.resource_url(root_coll, **options) else: url = self.__request.resource_url(resource, **options) else: if not resource.is_root_member: # For nested members, we check if the referenced root # collection is exposed (i.e., has the service as parent). # If yes, we return an absolute URL, else a nested URL. root_coll = get_root_collection(resource) if not root_coll.has_parent: url = self.__request.resource_url(resource) else: par_url = self.__request.resource_url(root_coll) url = "%s%s/" % (par_url, resource.__name__) else: url = self.__request.resource_url(resource) if not quote: url = url_unquote(url) return url
def test_initialization(self): colls = [ get_root_collection(IMyEntityParent), get_root_collection(IMyEntity), get_root_collection(IMyEntityChild), get_root_collection(IMyEntityGrandchild), ] for coll in colls: self.assert_equal(len(coll), 1)
def test_set_member(self): my_entity = create_entity() coll = get_root_collection(IMyEntity) mb = coll.create_member(my_entity) txt = 'FROBNIC' new_parent = MyEntityParent(text=txt) parent_coll = get_root_collection(IMyEntityParent) parent_mb = parent_coll.create_member(new_parent) self.assert_not_equal(mb.parent.text, txt) mb.parent = parent_mb self.assert_equal(mb.parent.text, txt)
def create_collection(): my_entity0 = create_entity(entity_id=0, entity_text='foo0') my_entity1 = create_entity(entity_id=1, entity_text='too1') coll = get_root_collection(IMyEntity) my_mb0 = coll.create_member(my_entity0) my_mb1 = coll.create_member(my_entity1) # FIXME: This should really be done automatically. parent_coll = get_root_collection(IMyEntityParent) parent_coll.add(my_mb0.parent) parent_coll.add(my_mb1.parent) children_coll = get_root_collection(IMyEntityChild) children_coll.add(list(my_mb0.children)[0]) children_coll.add(list(my_mb1.children)[0]) return coll
def test_load_from_zipfile(self): member = _make_test_entity_member() strm = StringIO('w') dump_resource_to_zipfile(member, strm) colls = [ get_root_collection(IMyEntityParent), get_root_collection(IMyEntity), get_root_collection(IMyEntityChild), get_root_collection(IMyEntityGrandchild), ] colls = load_into_collections_from_zipfile(colls, strm) self.assert_equal(len(colls[0]), 1) self.assert_equal(len(colls[1]), 1) self.assert_equal(len(colls[2]), 1) self.assert_equal(len(colls[3]), 1)
def test_add(self): coll = get_root_collection(IMyEntity) ent = MyEntity(id=2) mb_add = MyEntityMember.create_from_entity(ent) coll.add(mb_add) transaction.commit() self.assert_equal(len(coll), 2)
def view_collection(app_creator): #pylint:disable=W0613 my_entity1 = create_entity_tree(id=0, text='foo0') my_entity2 = create_entity_tree(id=1, text='too1') coll = get_root_collection(IMyEntity) coll.create_member(my_entity1) coll.create_member(my_entity2) return coll
def test_member_name(self): coll = get_root_collection(IFoo) foo = FooEntity(id=0) mb = coll.create_member(foo) self.assert_equal(mb.__name__, '0') mb.__name__ = 'foo' self.assert_equal(mb.__name__, 'foo')
def test_member_delete(self): coll = get_root_collection(IFoo) foo = FooEntity(id=0) mb = coll.create_member(foo) self.assert_true(mb in coll) coll.remove(mb) self.assert_false(mb in coll)
def test_put_member_raises_error(self, exc_vw_app_creator): coll = get_root_collection(IMyEntity) ent = MyEntity(id=0) coll.create_member(ent) exc_vw_app_creator.put("%s/0" % self.path, params='dummy body', status=500)
def test_get_project(self): coll = get_root_collection(IProject) self.assert_equal(len(coll), 7) mb = coll.get('pond') self.assert_true(isinstance(mb, ProjectMember)) self.assert_equal(mb.name, 'Pond') self.assert_true(isinstance(mb.customer, CustomerMember))
def test_add_remove_same_member(self): coll = get_root_collection(IMyEntity) ent = MyEntity(id=1) mb = MyEntityMember.create_from_entity(ent) coll.add(mb) coll.remove(mb) self.assert_equal(len(coll), 1)
def test_map_to_data_element(self): def _test(mb, cnt_type, parent_repr_name, children_repr_name): mp_reg = get_mapping_registry(cnt_type) mp = mp_reg.find_or_create_mapping(MyEntityMember) de = mp.map_to_data_element(mb) prx = DataElementAttributeProxy(de) self.assert_true(prx.get_data_element() is de) self.assert_equal(prx.id, 0) self.assert_equal(prx.text, 'TEXT') self.assert_equal(prx.number, 1) # The parent and children attributes are links. self.assert_true(isinstance(getattr(prx, parent_repr_name), LinkedDataElement)) children_el = getattr(prx, children_repr_name) if cnt_type is XmlMime: self.assert_is_none(children_el) else: self.assert_true(isinstance(children_el, LinkedDataElement)) # Nonexisting attribute raises error. self.assert_raises(AttributeError, getattr, prx, 'foo') self.assert_raises(AttributeError, setattr, prx, 'foo', 'murks') # Set terminal attribute. prx.id = 1 self.assert_equal(prx.id, 1) # Set nested attribute. setattr(prx, parent_repr_name, None) self.assert_is_none(getattr(prx, parent_repr_name)) self.assert_raises(ValueError, setattr, prx, parent_repr_name, 1) entity = create_entity() coll = get_root_collection(IMyEntity) mb = coll.create_member(entity) _test(mb, XmlMime, 'myentityparent', 'myentitychildren') _test(mb, CsvMime, 'parent', 'children')
def transform_incoming(ent_cls, ent): """ Converts an incoming entity into a SON object. In particular, this involves translating entity references to DB Refs. """ son = SON() son['_id'] = getattr(ent, '_id') # We store the slug for querying purposes. son['slug'] = ent.slug for attr in get_domain_class_attribute_iterator(ent_cls): try: value = getattr(ent, attr.entity_attr) except AttributeError: continue if attr.kind == RESOURCE_ATTRIBUTE_KINDS.TERMINAL: son[attr.entity_attr] = value else: if value is None: son[attr.entity_attr] = None else: root_coll = get_root_collection(attr.attr_type) if attr.kind == RESOURCE_ATTRIBUTE_KINDS.MEMBER: son[attr.entity_attr] = DBRef(root_coll.__name__, getattr(value, '_id')) else: son[attr.entity_attr] = [DBRef(root_coll.__name__, getattr(el, '_id')) for el in value] return son
def test_urls(self): my_entity = create_entity() coll = get_root_collection(IMyEntity) mb = coll.create_member(my_entity) exp_url = '/my-entities/0/' url = resource_to_url(mb) self.assert_true(url.endswith(exp_url)) exp_url = '/my-entity-parents/0/' url = resource_to_url(mb.parent) self.assert_true(url.endswith(exp_url)) exp_url = 'my-entities/0/nested-parent/' url = resource_to_url(mb.nested_parent) self.assert_true(url.endswith(exp_url)) exp_url = '/my-entities/0/children/' url = resource_to_url(mb.children) self.assert_true(url.endswith(exp_url)) mb_child = mb.children['0'] self.assert_equal(mb_child.id, 0) exp_url = '/my-entity-grandchildren/?q=parent:equal-to:' \ 'http://0.0.0.0:6543/my-entities/0/children/0/' url = resource_to_url(mb_child.children) self.assert_true(url.endswith(exp_url)) exp_url = 'my-entity-grandchildren/?q=id:contained:0' url = resource_to_url(mb_child.no_backref_children) self.assert_true(url.endswith(exp_url))
def test_member_delete(self): coll = get_root_collection(IFoo) foo = FooEntity(id=0) mb = coll.create_member(foo) self.assert_true(mb in coll) mb.delete() self.assert_false(mb in coll)
def test_put_member_raises_error(self): coll = get_root_collection(IMyEntity) ent = MyEntity(id=0) coll.create_member(ent) self.app.put("%s/0" % self.path, params='dummy body', status=500)
def test_update_from_entity(self): foo0 = FooEntity(id=0) coll = get_root_collection(IFoo) mb0 = coll.create_member(foo0) foo1 = FooEntity(id=1) mb0.update_from_entity(foo1) self.assert_equal(mb0.id, 1)
def _test_load(self, load_func, fn_func, is_into): member = _make_test_entity_member() tmp_dir = tempfile.mkdtemp() try: dump_resource_to_files(member, directory=tmp_dir) file_names = glob.glob1(tmp_dir, "*.csv") self.assert_equal(len(file_names), 4) for ifc in [IMyEntityParent, IMyEntity, IMyEntityChild, IMyEntityGrandchild]: coll_cls = get_collection_class(ifc) root_coll = get_root_collection(ifc) file_name = get_collection_filename(coll_cls) file_path = fn_func(os.path.join(tmp_dir, file_name)) if not is_into: coll = load_func(coll_cls, file_path) self.assert_equal(len(coll), 1) for mb in coll: root_coll.add(mb) else: load_func(root_coll, file_path) self.assert_equal(len(root_coll), 1) finally: shutil.rmtree(tmp_dir)
def test_update_nested_collection_from_data(self): # Set up member that has one child. root_coll = get_root_collection(IMyEntity) ent = MyEntity(id=1) child0 = MyEntityChild(id=0) ent.children.append(child0) mb = root_coll.create_member(ent) # Set up another member with two children with different IDs. stg_coll = create_staging_collection(IMyEntity) upd_ent = MyEntity(id=1) child1 = MyEntityChild(id=1) child1.parent = upd_ent child2 = MyEntityChild(id=2) child2.parent = upd_ent upd_ent.children.append(child1) upd_ent.children.append(child2) upd_mb = stg_coll.create_member(upd_ent) rpr = as_representer(mb, CsvMime) attribute_options = {('children',):{IGNORE_OPTION:False, WRITE_AS_LINK_OPTION:False}, } rpr.configure(attribute_options=attribute_options) de = rpr.data_from_resource(upd_mb) # mb.update(de) self.assert_equal(set([mb.id for mb in mb.children]), set([1, 2]))
def test_no_backref_collection_url(self): my_entity = create_entity() coll = get_root_collection(IMyEntity) mb = coll.create_member(my_entity) mb_child = mb.children['0'] exp_url = 'my-entity-grandchildren/?q=id:contained:0' url = resource_to_url(mb_child.children) self.assert_true(url.endswith(exp_url))
def test_remove_add_same_member(self): coll = get_root_collection(IMyEntity) mb = iter(coll).next() coll.remove(mb) transaction.commit() coll.add(mb) transaction.commit() self.assert_equal(len(coll), 1)
def test_get_customer(self): coll = get_root_collection(ICustomer) self.assert_equal(len(coll), 3) mb = coll.get('smith-peter') self.assert_true(isinstance(mb, CustomerMember)) self.assert_equal(mb.first_name, 'Peter') self.assert_equal(mb.last_name, 'Smith') self.assert_equal(len(mb.projects), 3)
def _get_member(self, icollection, key=None): if key is None: coll = self._get_collection(icollection, slice(0, 1)) member = list(iter(coll))[0] else: coll = get_root_collection(icollection) member = coll.get(key) return member
def test_patch_unset_location(self, app_creator): rack_bc = '02481966' rsp = app_creator.delete('%s/%s/location' % (self.path, rack_bc), status=HTTPOk.code) assert not rsp is None coll = get_root_collection(ITubeRack) rack = coll[rack_bc] assert rack.get_entity().location_rack is None
def test_get_species(self): coll = get_root_collection(ISpecies) self.assert_equal(len(coll), 6) mb = coll.get('caltha-palustris--l.') self.assert_true(isinstance(mb, SpeciesMember)) self.assert_equal(mb.species_name, 'palustris') self.assert_equal(mb.genus_name, 'Caltha') self.assert_equal(mb.author, 'L.')
def test_get_nested(self): coll = get_root_collection(IProject) mb = coll.get('pond') self.assert_equal(len(mb.sites), 2) site_mb = mb.sites.get('open-water') self.assert_true(isinstance(site_mb, SiteMember)) incidence_mb = site_mb.incidences.get('utricularia-vulgaris--l.') self.assert_true(isinstance(incidence_mb, IncidenceMember))
def test_load_from_zipfile_filename_not_found(self): strm = StringIO('w') zipf = zipfile.ZipFile(strm, 'w') zipf.writestr('foo.foo', '') zipf.close() colls = [get_root_collection(IMyEntity)] colls = load_into_collections_from_zipfile(colls, strm) self.assert_equal(len(colls[0]), 0)
def test_collection_access(self): parent = MyEntityParent(id=0) entity = MyEntity(id=0, parent=parent) coll = get_root_collection(IMyEntity) member = coll.create_member(entity) self.assert_true(isinstance(member.children, Collection)) child_entity = MyEntityChild() member.children.create_member(child_entity) self.assert_equal(len(member.children), 1)
def test_add_remove_same_member(self): coll = get_root_collection(IMyEntity) ent = MyEntity(id=1) mb = MyEntityMember.create_from_entity(ent) coll.add(mb) transaction.commit() coll.remove(mb) transaction.commit() self.assert_equal(len(coll), 1)
def test_make_relationship(self): ent = MyEntity(id=0) coll = get_root_collection(IMyEntity) mb = coll.create_member(ent) attr = get_resource_class_attribute(IMyEntity, 'parent') rel = attr.make_relationship(mb) self.assert_true(isinstance(rel, ResourceRelationship)) parent = MyEntityParent(id=0) parent_coll = get_root_collection(IMyEntityParent) parent_mb = parent_coll.create_member(parent) self.assert_true(ent.parent is None) rel.add(parent_mb) self.assert_true(ent.parent is parent) rel.remove(parent_mb) self.assert_true(ent.parent is None) rel = attr.make_relationship(ent) self.assert_true(isinstance(rel, DomainRelationship)) self.assert_raises(ValueError, attr.make_relationship, None)
def test_add_remove(self): coll = get_root_collection(IMyEntity) mb_rm = iter(coll).next() coll.remove(mb_rm) ent = MyEntity(id=1) mb_add = MyEntityMember.create_from_entity(ent) coll.add(mb_add) transaction.commit() self.assert_equal(len(coll), 1)
def test_make_relationship(self): ent = MyEntity(id=0) coll = get_root_collection(IMyEntity) mb = coll.create_member(ent) attr = get_resource_class_attribute(IMyEntity, "parent") rel = attr.make_relationship(mb) self.assert_true(isinstance(rel, ResourceRelationship)) parent = MyEntityParent(id=0) parent_coll = get_root_collection(IMyEntityParent) parent_mb = parent_coll.create_member(parent) self.assert_true(ent.parent is None) rel.add(parent_mb) self.assert_true(ent.parent is parent) rel.remove(parent_mb) self.assert_true(ent.parent is None) rel = attr.make_relationship(ent) self.assert_true(isinstance(rel, DomainRelationship)) self.assert_raises(ValueError, attr.make_relationship, None)
def test_remove_with_data_element(self): my_entity = create_entity() coll = get_root_collection(IMyEntity) member = coll.create_member(my_entity) mp = self._make_mapping() data_el = mp.map_to_data_element(member) del member coll.remove(data_el) self.assert_equal(len(coll), 0)
def test_load_referenced_entities(self): coll = get_root_collection(IMyEntity) ent = next(iter(coll)).get_entity() parent = ent.parent assert isinstance(parent, MyEntityParent) assert len(ent.children) == 1 assert isinstance(ent.children[0], MyEntityChild) assert len(ent.children[0].children) == 1 assert isinstance(ent.children[0].children[0], MyEntityGrandchild)
def test_abort(self): coll = get_root_collection(IMyEntity) mb = iter(coll).next() OLD_TEXT = mb.text TEXT = 'Changed.' mb.text = TEXT transaction.abort() old_mb = iter(coll).next() self.assert_equal(old_mb.text, OLD_TEXT)
def test_post_collection(self): req_body = '"id","text","number"\n0,"abc",2\n' res = self.app.post("%s" % self.path, params=req_body, content_type=CsvMime.mime_type_string, status=201) self.assert_is_not_none(res) coll = get_root_collection(IMyEntity) mb = coll['0'] self.assert_equal(mb.text, 'abc')
def test_patch_member(self, msg_view_app_creator): #pylint:disable=W0621 coll = get_root_collection(IMyEntity) ent = MyEntity(id=0) mb = coll.create_member(ent) assert mb.__name__ == '0' req_body = b'"number"\n2\n' res = msg_view_app_creator.patch("%s/0" % self.path, params=req_body, content_type=CsvMime.mime_type_string, status=200) assert not res is None
def test_load_from_zipfile_invalid_extension(self): strm = StringIO('w') zipf = zipfile.ZipFile(strm, 'w') coll_name = get_collection_name(get_collection_class(IMyEntity)) zipf.writestr('%s.foo' % coll_name, '') zipf.close() colls = [get_root_collection(IMyEntity)] with self.assert_raises(ValueError) as cm: dummy = load_into_collections_from_zipfile(colls, strm) exc_msg = 'Could not infer MIME type' self.assert_true(cm.exception.message.startswith(exc_msg))