def test_url_to_resource_invalid_traversal_object(self, monkeypatch): monkeypatch.setattr(Service, '__getitem__', classmethod(lambda cls, item: 1)) url = self.app_url + '/foo' with pytest.raises(ValueError) as cm: url_to_resource(url) exc_msg = 'Traversal found non-resource object' assert str(cm.value).startswith(exc_msg)
def convert_string(toks): unquoted = toks[0][1:-1] if len(url_protocol.searchString(unquoted)) > 0: result = [url_to_resource(unquoted)] else: result = [unquoted] return result
def visit_member(self, attribute_key, attribute, member_node, member_data, is_link_node, parent_data, index=None): if is_link_node: url = member_node.get_url() rc = url_to_resource(url) entity = rc.get_entity() else: entity_cls = get_entity_class(member_node.mapping.mapped_class) entity_data = {} nested_entity_data = {} for attr, value in member_data.iteritems(): if '.' in attr.entity_name: nested_entity_data[attr.entity_name] = value else: entity_data[attr.entity_name] = value entity = entity_cls.create_from_data(entity_data) # Set nested attribute values. # FIXME: lazy loading of nested attributes is not supported. for nested_attr, value in nested_entity_data.iteritems(): tokens = nested_attr.split('.') parent = reduce(getattr, tokens[:-1], entity) if not parent is None: setattr(parent, tokens[-1], value) if not index is None: # Collection member. Store in parent data with index as key. parent_data[index] = entity elif len(attribute_key) == 0: # Top level. Store root entity and create resource. mapped_cls = member_node.mapping.mapped_class self.__resource = mapped_cls.create_from_entity(entity) else: # Nested member. Store in parent data with attribute as key. parent_data[attribute] = entity
def test_url_to_resource_with_complex_filter(self): criterion = '(id:equal-to:0 and text:equal-to:"foo0") or ' \ '(id:equal-to:1 and text:equal-to:"too1")' coll_from_url = \ url_to_resource(self.base_url + '?q=%s' % criterion) mbs = list(coll_from_url) assert len(mbs) == 2
def test_url_to_resource_contained_with_simple_collection_link(self): nested_url = self.app_url \ + '/my-entity-parents/?q=id:less-than:1' url = self.app_url + '/my-entities/?q=parent:contained:' \ + '"' + nested_url + '"' coll_from_url = url_to_resource(url) assert len(coll_from_url) == 1
def test_two_urls(self): par_url = self.app_url + '/my-entity-parents/' criteria = 'parent:equal-to:"%s","%s"' \ % (par_url + '0/', par_url + '1/') url = self.base_url + '?q=%s' % criteria coll_from_url = url_to_resource(url) assert len(coll_from_url) == 2
def test_url_to_resource_with_link_and_other(self): criterion1 = 'parent:equal-to:"%s/my-entity-parents/0/"' \ % self.app_url criterion2 = 'id:equal-to:0' coll_from_url = url_to_resource(self.base_url + '?q=%s~%s' % (criterion1, criterion2)) assert len(coll_from_url) == 1
def test_url_to_resource_contained_with_grouped_collection_link(self): url = self.app_url + '/my-entities/' \ + '?q=(parent:contained:"' \ + self.app_url \ + '/my-entity-parents/?q=id:less-than:3") ' \ + 'and text:not-equal-to:"foo0"' coll_from_url = url_to_resource(url) assert len(coll_from_url) == 1
def test_url_to_resource_with_complex_filter(self): criterion = '(id:equal-to:0 and text:equal-to:"foo0") or ' \ '(id:equal-to:1 and text:equal-to:"too1")' coll_from_url = \ url_to_resource(self.base_url + '?q=%s' % criterion) mbs = list(coll_from_url) self.assert_equal(len(mbs), 2) self.assert_equal(getattr(mbs[0], 'id'), 0) self.assert_equal(getattr(mbs[1], 'id'), 1)
def test_url_to_resource_contained_with_complex_collection_link(self, op, crit): nested_url = self.app_url \ + '/my-entity-parents/?q=id:less-than:2' \ + op \ + crit url = self.app_url + '/my-entities/?q=parent:contained:' \ + "'" + nested_url + "'" coll_from_url = url_to_resource(url) assert len(coll_from_url) == 1
def test_url_to_resource_contained_with_complex_collection_link( self, op, crit): nested_url = self.app_url \ + '/my-entity-parents/?q=id:less-than:2' \ + op \ + crit url = self.app_url + '/my-entities/?q=parent:contained:' \ + "'" + nested_url + "'" coll_from_url = url_to_resource(url) assert len(coll_from_url) == 1
def update(self, data): if IDataElement.providedBy(data): # pylint: disable=E1101 # FIXME: This really should be a PATCH operation. prx = DataElementAttributeProxy(data) self_entity = self.get_entity() changed_num_reps = prx.number_replicates != self.number_replicates emt_id = prx.experiment_metadata_type.get('id') changed_em_type = emt_id != self.experiment_metadata_type.id if changed_em_type or changed_num_reps: if changed_num_reps: self_entity.number_replicates = prx.number_replicates if changed_em_type: self_entity.experiment_metadata_type = \ get_experiment_metadata_type(emt_id) if not self_entity.experiment_design is None: # invalidate data to force a fresh upload of the XLS file self_entity.experiment_design.experiment_design_racks = [] self_entity.experiment_design.worklist_series = None if not self_entity.lab_iso_request is None: shape = self_entity.lab_iso_request.rack_layout.shape new_layout = RackLayout(shape=shape) self_entity.lab_iso_request.rack_layout = new_layout self_entity.lab_iso_request.owner = '' changed_sp = self_entity.subproject.id != prx.subproject.get('id') if changed_sp: new_sp = \ url_to_resource(prx.subproject.get('href')).get_entity() self_entity.subproject = new_sp self_entity.label = prx.label # Perform appropriate Trac updates. if not self_entity.lab_iso_request is None: if self.iso_request.owner == STOCKMANAGEMENT_USER: ticket_activator = IsoRequestTicketActivator( experiment_metadata=self_entity) self.__run_trac_tool(ticket_activator, 'Could not update the ticket: %s.') else: if changed_em_type or changed_num_reps: trac_updater = IsoRequestTicketDescriptionRemover( experiment_metadata=self_entity, changed_num_replicates=changed_num_reps, changed_em_type=changed_em_type) else: url = 'http://thelma/public//LOUICe.html#' \ + self.path iso_url = 'http://thelma/public//LOUICe.html#' \ + self.iso_request.path trac_updater = IsoRequestTicketDescriptionUpdater( experiment_metadata=self_entity, experiment_metadata_link=url, iso_request_link=iso_url) self.__run_trac_tool(trac_updater, 'Could not update the ticket: %s.') else: Member.update(self, data)
def __prepare_values(cls, values): prepared = [] for val in values: if cls.__is_empty_string(val): continue elif cls.__is_url(val): # URLs - convert to resource. val = url_to_resource(''.join(val)) if not val in prepared: prepared.append(val) return prepared
def test_workflow( self, app_creator, tube_rack_specs_matrix, # tube_rack_fac, tube_fac, item_status_managed, # organization_cenix, stock_sample_fac, xls_filename, scenario, monkeypatch): repo_mgr = \ app_creator.config.get_registered_utility(IRepositoryManager) repo = repo_mgr.get_default() self.__session = repo.session_factory() # Step 0: Create candidate samples. # self._create_iso_candidates(tube_rack_fac, tube_rack_specs_matrix, # tube_fac, item_status_managed, # organization_cenix, stock_sample_fac) # Step 1: Upload metadata. emd_url = self._upload_metadata(xls_filename, scenario, app_creator) # Step 2: Accept ISO request. emd = url_to_resource(emd_url) self._accept_iso_request(emd.iso_request, app_creator) # Step 3: Generate ISOs. # We need to temporarily reduce the threshold that controls # when to use the Cybio. monkeypatch.setattr(LabIsoPlanner, '_MIN_CYBIO_TRANSFER_NUMBER', 6) self._generate_isos(emd.iso_request, app_creator) # Step 4: Process ISO jobs (if needed). if emd.iso_request.process_job_first: for iso_job in emd.iso_request.iso_jobs: if iso_job.number_stock_racks == 0: continue patch_body = \ self.__get_representation_from_file( 'transfer_to_iso_job.xml') % iso_job.id # self.__make_transfer_to_patch_representation( # emd.iso_request, # 'iso_jobs') self._process_iso_or_iso_job(iso_job, emd.iso_request, 1, patch_body, app_creator, tube_rack_specs_matrix) # Step 5: Process ISOs. for iso_job in emd.iso_request.iso_jobs: for iso in iter(iso_job.isos): patch_body = \ self.__get_representation_from_file( 'transfer_to_iso.xml') % iso.id # self.__make_transfer_to_patch_representation( # emd.iso_request, # 'isos') self._process_iso_or_iso_job(iso, emd.iso_request, 4, patch_body, app_creator, tube_rack_specs_matrix)
def test_url_to_resource_invalid_slice(self): with self.assert_raises(ValueError) as cm: url_to_resource(self.base_url + '?start=0&size=a') exc_msg = 'must be a number.' self.assert_true(cm.exception.message.endswith(exc_msg)) with self.assert_raises(ValueError) as cm: url_to_resource(self.base_url + '?start=a&size=100') self.assert_true(cm.exception.message.endswith(exc_msg)) with self.assert_raises(ValueError) as cm: url_to_resource(self.base_url + '?start=-1&size=100') exc_msg = 'must be zero or a positive number.' self.assert_true(cm.exception.message.endswith(exc_msg)) with self.assert_raises(ValueError) as cm: url_to_resource(self.base_url + '?start=0&size=-100') exc_msg = 'must be a positive number.' self.assert_true(cm.exception.message.endswith(exc_msg))
def make_proxy(self, accessor, relationship_direction, options=None): # Note: We ignore the options; if something was passed here, # it came from a parent data element data traversal proxy. url = self._data.get_url() rc = url_to_resource(url) if ICollectionResource.providedBy(rc): # pylint:disable=E1101 reg = get_current_registry() prx_fac = reg.getUtility(IDataTraversalProxyFactory) prx = prx_fac.make_proxy([mb.get_entity() for mb in rc], accessor, relationship_direction) else: prx = LinkedDomainDataTraversalProxy(rc.get_entity(), accessor, relationship_direction) return prx
def test_workflow(self, app_creator, tube_rack_specs_matrix, # tube_rack_fac, tube_fac, item_status_managed, # organization_cenix, stock_sample_fac, xls_filename, scenario, monkeypatch): repo_mgr = \ app_creator.config.get_registered_utility(IRepositoryManager) repo = repo_mgr.get_default() self.__session = repo.session_factory() # Step 0: Create candidate samples. # self._create_iso_candidates(tube_rack_fac, tube_rack_specs_matrix, # tube_fac, item_status_managed, # organization_cenix, stock_sample_fac) # Step 1: Upload metadata. emd_url = self._upload_metadata(xls_filename, scenario, app_creator) # Step 2: Accept ISO request. emd = url_to_resource(emd_url) self._accept_iso_request(emd.iso_request, app_creator) # Step 3: Generate ISOs. # We need to temporarily reduce the threshold that controls # when to use the Cybio. monkeypatch.setattr(LabIsoPlanner, '_MIN_CYBIO_TRANSFER_NUMBER', 6) self._generate_isos(emd.iso_request, app_creator) # Step 4: Process ISO jobs (if needed). if emd.iso_request.process_job_first: for iso_job in emd.iso_request.iso_jobs: if iso_job.number_stock_racks == 0: continue patch_body = \ self.__get_representation_from_file( 'transfer_to_iso_job.xml') % iso_job.id # self.__make_transfer_to_patch_representation( # emd.iso_request, # 'iso_jobs') self._process_iso_or_iso_job(iso_job, emd.iso_request, 1, patch_body, app_creator, tube_rack_specs_matrix) # Step 5: Process ISOs. for iso_job in emd.iso_request.iso_jobs: for iso in iter(iso_job.isos): patch_body = \ self.__get_representation_from_file( 'transfer_to_iso.xml') % iso.id # self.__make_transfer_to_patch_representation( # emd.iso_request, # 'isos') self._process_iso_or_iso_job(iso, emd.iso_request, 4, patch_body, app_creator, tube_rack_specs_matrix)
def visit_collection(self, attribute_key, attribute, collection_node, collection_data, is_link_node, parent_data): if is_link_node: url = collection_node.get_url() coll = url_to_resource(url) entities = [mb.get_entity() for mb in coll] else: entities = [] for item in sorted(collection_data.items()): entities.append(item[1]) if len(attribute_key) == 0: # Top level. mapped_cls = collection_node.mapping.mapped_class self.__resource = create_staging_collection(mapped_cls) for ent in entities: self.__resource.create_member(ent) else: parent_data[attribute] = entities
def make_proxy(self, accessor, relationship_direction, relation_operation, options=None): # Note: We ignore the options; if something was passed here, # it came from a parent data element data traversal proxy. url = self._data.get_url() rc = url_to_resource(url) if ICollectionResource.providedBy(rc): # pylint:disable=E1101 reg = get_current_registry() prx_fac = reg.getUtility(IDataTraversalProxyFactory) prx = prx_fac.make_proxy([mb.get_entity() for mb in rc], accessor, relationship_direction, relation_operation) else: prx = LinkedDomainDataTraversalProxy(rc.get_entity(), accessor, relationship_direction, relation_operation) return prx
def update_from_data(self, data_element): """ Updates this member from the given data element. :param data_element: data element (hierarchical) to create a resource from :type data_element: object implementing `:class:everest.resources.representers.interfaces.IExplicitDataElement` """ mp = data_element.mapping for attr in mp.attribute_iterator(): if attr.kind == ResourceAttributeKinds.TERMINAL: other_value = data_element.get_terminal(attr) if other_value is None: # Optional attribute - continue. continue else: setattr(self, attr.name, other_value) else: # attr.kind MEMBER or COLLECTION rc_data_el = data_element.get_nested(attr) if rc_data_el is None: # Optional attribute - continue. continue self_rc = getattr(self, attr.name) if ILinkedDataElement in provided_by(rc_data_el): # Found a link. Update if the URL is different. url = rc_data_el.get_url() if not self_rc is None \ and resource_to_url(self_rc) == url: # continue new_rc = url_to_resource(url) setattr(self, attr.name, new_rc) else: if self_rc is None: new_rc = mp.map_to_resource(rc_data_el) setattr(self, attr.name, new_rc) else: self_rc.update_from_data(rc_data_el)
def test_url_to_resource_with_link(self): criterion = 'parent:equal-to:"%s/my-entity-parents/0/"' % self.app_url coll_from_url = url_to_resource(self.base_url + '?q=%s' % criterion) assert len(coll_from_url) == 1
def test_url_to_resource_with_multiple_string_values_one_empty(self): criteria = 'text:starts-with:"foo",""' coll_from_url = url_to_resource(self.base_url + '?q=%s' % criteria) assert len(coll_from_url) == 1
def test_url_to_resource_with_multiple_values_one_empty(self): criteria = 'id:equal-to:0,' coll_from_url = url_to_resource(self.base_url + '?q=%s' % criteria) assert len(coll_from_url) == 1
def test_url_to_resource_with_multiple_criteria_one_empty(self): criteria = 'id:less-than:1~' coll_from_url = url_to_resource(self.base_url + '?q=%s' % criteria) assert len(coll_from_url) == 1
def test_url_to_resource_with_multiple_string_values_one_empty(self): criteria = 'text:starts-with:"foo",""' coll_from_url = url_to_resource(self.base_url + '?q=%s' % criteria) self.assert_equal(len(coll_from_url), 1)
def test_url_to_resource_with_multiple_values(self): criteria = 'id:equal-to:0,1' coll_from_url = url_to_resource(self.base_url + '?q=%s' % criteria) assert len(coll_from_url) == 2
def test_url_to_resource_with_slice(self): coll_from_url = url_to_resource(self.base_url + '?size=1&start=0') # The length is not affected by the slice... self.assert_equal(len(coll_from_url), 2) # ... the actual number of members in the collection is. self.assert_equal(len(list(coll_from_url)), 1)
def test_url_to_resource_with_slice(self): coll_from_url = url_to_resource(self.base_url + '?size=1&start=0') # The length is not affected by the slice... assert len(coll_from_url) == 2 # ... the actual number of members in the collection is. assert len(list(coll_from_url)) == 1
def test_url_to_resource(self, collection): coll_from_url = url_to_resource(self.base_url) assert collection['0'] == coll_from_url['0']
def test_url_to_resource_invalid(self, url, error, msg): with pytest.raises(error) as cm: url_to_resource(url) assert str(cm.value).find(msg) != -1
def test_url_to_resource_with_multiple_criteria_one_empty(self): criteria = 'id:less-than:1~' coll_from_url = url_to_resource(self.base_url + '?q=%s' % criteria) self.assert_equal(len(coll_from_url), 1)
def test_url_to_resource_with_multiple_values_one_empty(self): criteria = 'id:equal-to:0,' coll_from_url = url_to_resource(self.base_url + '?q=%s' % criteria) self.assert_equal(len(coll_from_url), 1)
def test_url_to_resource_nonexisting_collection(self): with self.assert_raises(KeyError) as cm: url_to_resource('http://0.0.0.0:6543/my-foos/') exc_msg = 'has no subelement my-foos' self.assert_true(cm.exception.message.endswith(exc_msg))
def test_url_to_resource_with_multiple_order(self): coll_from_url = url_to_resource(self.base_url + '?sort=id:asc~text:desc') self.assert_equal(len(coll_from_url), 2) self.assert_equal(list(coll_from_url)[-1].id, 1)
def test_url_to_resource_invalid_filter_criterion(self): with self.assert_raises(ValueError) as cm: url_to_resource(self.base_url + '?q=id|foo') exc_msg = 'Expression parameters have errors' self.assert_true(cm.exception.message.startswith(exc_msg))
def _test(criterion, attr, value): coll_from_url = \ url_to_resource(self.base_url + '?q=%s' % criterion) mbs = list(coll_from_url) self.assert_equal(len(mbs), 1) self.assert_equal(getattr(mbs[0], attr), value)
def test_url_to_resource_with_multiple_order(self): coll_from_url = url_to_resource(self.base_url + '?sort=id:asc~text:desc') assert len(coll_from_url) == 2 assert list(coll_from_url)[-1].id == 1
def test_url_to_resource(self): coll_from_url = url_to_resource(self.base_url) self.assert_equal(self.coll['0'], coll_from_url['0'])
def test_url_to_resource_with_multiple_filter(self): criteria = 'id:less-than:1~id:less-than-or-equal-to:1' coll_from_url = url_to_resource(self.base_url + '?q=%s' % criteria) assert len(coll_from_url) == 1
def test_url_to_resource_with_filter(self, criterion, attr, value): coll_from_url = url_to_resource(self.base_url + '?q=%s' % criterion) mbs = list(coll_from_url) assert len(mbs) == 1 assert getattr(mbs[0], attr) == value
def test_url_to_resource_with_link(self): criterion = 'parent:equal-to:"%s/my-entity-parents/0/"' % self.app_url coll_from_url = url_to_resource(self.base_url + '?q=%s' % criterion) self.assert_equal(len(coll_from_url), 1)
def test_url_to_resource_with_multiple_filter(self): criteria = 'id:less-than:1~id:less-than-or-equal-to:1' coll_from_url = url_to_resource(self.base_url + '?q=%s' % criteria) self.assert_equal(len(coll_from_url), 1)
def test_url_to_resource_non_resource_object(self): with self.assert_raises(ValueError) as cm: url_to_resource('http://0.0.0.0:6543/') exc_msg = 'Traversal found non-resource object' self.assert_true(cm.exception.message.startswith(exc_msg))