def test_iterator_count(self, class_entity_repo, ent0, ent1): agg = class_entity_repo.get_aggregate(IMyEntity) with pytest.raises(StopIteration): next(agg.iterator()) agg.add(ent0) assert next(agg.iterator()) is ent0 # Iterator heeds filtering. agg.filter = eq(id=ent1.id) with pytest.raises(StopIteration): next(agg.iterator()) agg.add(ent1) assert next(agg.iterator()) is ent1 # Iterator heeds ordering. agg.filter = None agg.order = asc('id') assert isinstance(agg.order, AscendingOrderSpecification) assert next(agg.iterator()) is ent0 # Iterator heeds slice. assert len(list(agg.iterator())) == 2 agg.slice = slice(0, 1) assert len(list(agg.iterator())) == 1 # Count ignores slice. assert agg.count() == 2 # Count heeds filtering. agg.filter = eq(id=1) assert agg.count() == 1
def test_basics(self, class_entity_repo): agg = class_entity_repo.get_aggregate(IMyEntity) child_agg = class_entity_repo.get_aggregate(IMyEntityChild) new_child0 = self._make_child(child_agg) new_parent1 = MyEntityParent() new_ent1 = MyEntity() new_ent1.parent = new_parent1 new_child1 = MyEntityChild() child_rel_agg = self._make_rel_agg(class_entity_repo, new_ent1) assert len(list(child_agg.iterator())) == 1 assert len(list(agg.iterator())) == 1 assert len(list(child_rel_agg.iterator())) == 0 # Adding to a relationship aggregate ..... child_rel_agg.add(new_child1) # ....... adds to root aggregates: assert len(list(child_agg.iterator())) == 2 # ....... adds (along the cascade) to parent root aggregate: assert len(list(agg.iterator())) == 2 # ....... appends to children: assert new_ent1.children == [new_child1] # get by ID and slug, filtering. assert child_rel_agg.get_by_id(new_child1.id).id == new_child1.id assert \ child_rel_agg.get_by_slug(new_child1.slug).slug == new_child1.slug child_rel_agg.filter = eq(id=2) assert child_rel_agg.get_by_id(new_child1.id) is None assert child_rel_agg.get_by_slug(new_child1.slug) is None # update. upd_child0 = MyEntityChild(id=0) txt = 'FROBNIC' upd_child0.text = txt child_rel_agg.update(upd_child0) assert new_child0.text == txt
def __get_empty_rack_barcode_params(self, count, tube_rack_specs_matrix): rack_agg = get_root_aggregate(ITubeRack) rack_agg.filter = eq(total_containers=0, specs=tube_rack_specs_matrix) rack_agg.slice = slice(0, count) if count == 1: params = dict(rack=str(next(rack_agg.iterator()).barcode)) else: params = dict([('rack%d' % (cnt + 1, ), str(rack.barcode)) for (cnt, rack) in enumerate(rack_agg.iterator())]) return params
def __get_empty_racks(self, count): rack_specs_agg = get_root_aggregate(ITubeRackSpecs) rs_matrix = rack_specs_agg.get_by_slug('matrix0500') is_managed = get_item_status_managed() rack_agg = get_root_aggregate(ITubeRack) rack_agg.filter = eq(total_containers=0, specs=rs_matrix, status=is_managed) rack_agg.slice = slice(0, count) return list(iter(rack_agg))
def __get_empty_rack_barcode_params(self, count, tube_rack_specs_matrix): rack_agg = get_root_aggregate(ITubeRack) rack_agg.filter = eq(total_containers=0, specs=tube_rack_specs_matrix) rack_agg.slice = slice(0, count) if count == 1: params = dict(rack=str(next(rack_agg.iterator()).barcode)) else: params = dict([('rack%d' % (cnt + 1,), str(rack.barcode)) for (cnt, rack) in enumerate(rack_agg.iterator())]) return params
def run(self): self.add_info('Running molecule design registrar.') self.__check_new_molecule_designs() cs_agg = get_root_aggregate(IChemicalStructure) md_agg = get_root_aggregate(IMoleculeDesign) cs_keys = set() new_css = set() new_mds = set() # Build keys for all new chemical structures. for mdris in self.__new_mdris: # By definition, all mdris for a given hash have the same # structures, so we just take the first. for cs in mdris[0].chemical_structures: cs_keys.add((cs.structure_type_id, cs.representation)) # FIXME: Build a single filtering spec here (see FIXME above). cs_map = {} for cs_key in cs_keys: sti, rpr = cs_key spec = eq(structure_type_id=sti, representation=rpr) cs_agg.filter = spec try: cs = cs_agg.iterator().next() except StopIteration: continue else: cs_map[cs_key] = cs self.add_debug('Creating %d new molecule designs.' % len(self.__new_mdris)) for mdris in self.__new_mdris: md_structs = [] # By definition, all mdris for a given hash have the same # structures, so we just take the first. for struct in mdris[0].chemical_structures: key = (struct.structure_type_id, struct.representation) if not key in cs_map: # New chemical structure - add and use for the design. cs_agg.add(struct) new_css.add(struct) md_structs.append(struct) cs_map[key] = struct else: # Use existing structure for the design. md_structs.append(cs_map[key]) # Create the new design. md = MoleculeDesign.create_from_data( dict(molecule_type=mdris[0].molecule_type, chemical_structures=md_structs)) md_agg.add(md) new_mds.add(md) # Update registration items. for mdri in mdris: mdri.molecule_design = md self.return_value = dict(molecule_designs=new_mds, chemical_structures=new_css)
def from_indices(cls, row_index, column_index): """ Returns a RackPosition from the row index and column index. :Note: Try not to use this method if you can avoid it as it takes as it takes a lot of time if you try to fetch a larger number of rack positions one by one. Use the rack position cache in the :mod:`semiconstants` module instead, if possible. :param row_index: the row of the container (this is 0 based). :type row_index: :class:`int` :param column_index: the column of the container (this 0 based). :type column_index: :class:`int` :return: The wanted rack position. :rtype: :class:`RackPosition` """ agg = get_root_aggregate(IRackPosition) agg.filter = eq(_row_index=row_index) & eq(_column_index=column_index) return list(agg.iterator())[0]
def run(self): rack_agg = get_root_aggregate(IRack) is_agg = get_root_aggregate(IItemStatus) status = is_agg.get_by_slug(self.STATUS) cnt_specs_agg = get_root_aggregate(IContainerSpecs) cnt_specs = cnt_specs_agg.get_by_slug(self.SPECS) tubes = [] for scan_fn in glob.glob("%s/*.txt" % self.__scanfile_directory): strm = open(scan_fn, 'r') try: prs = RackScanningParser(strm, parent=self) prs.run() finally: strm.close() if prs.has_errors(): raise RuntimeError('Could not parse rack scan file "%s". ' 'Error messages: %s' % (scan_fn, self.get_messages())) rack_agg.filter = eq(barcode=prs.rack_barcode) try: rack = rack_agg.iterator().next() except StopIteration: self.add_error('Rack with barcode "%s" does not exist.' % prs.rack_barcode) continue if not rack.specs.has_tubes: self.add_error('Rack with barcode "%s" is not a tube ' 'rack.' % rack.barcode) continue for pos_label, barcode in prs.position_map.iteritems(): if barcode is None: continue pos = get_rack_position_from_label(pos_label) # FIXME: Enable this test once pulling a tube by barcode is # fast. # if tube_agg.get_by_slug(barcode): # self.add_error('Tube with barcode "%s" already ' # 'exists.' % barcode) # continue if not rack.is_empty(pos): self.add_error('Trying to place a tube in an occupied ' 'position (%s on rack %s).' % (pos_label, rack.barcode)) continue tube = Tube.create_from_rack_and_position( cnt_specs, status, barcode, rack, pos) tubes.append(tube) self.add_info('Creating tube with barcode %s at ' 'position %s in rack %s.' % (barcode, pos_label, rack.barcode)) if not self.has_errors(): self.return_value = tubes
def run(self): rack_agg = get_root_aggregate(IRack) is_agg = get_root_aggregate(IItemStatus) status = is_agg.get_by_slug(self.STATUS) cnt_specs_agg = get_root_aggregate(IContainerSpecs) cnt_specs = cnt_specs_agg.get_by_slug(self.SPECS) tubes = [] for scan_fn in glob.glob("%s/*.txt" % self.__scanfile_directory): strm = open(scan_fn, 'r') try: prs = RackScanningParser(strm, parent=self) prs.run() finally: strm.close() if prs.has_errors(): raise RuntimeError('Could not parse rack scan file "%s". ' 'Error messages: %s' % (scan_fn, self.get_messages())) rack_agg.filter = eq(barcode=prs.rack_barcode) try: rack = rack_agg.iterator().next() except StopIteration: self.add_error('Rack with barcode "%s" does not exist.' % prs.rack_barcode) continue if not rack.specs.has_tubes: self.add_error('Rack with barcode "%s" is not a tube ' 'rack.' % rack.barcode) continue for pos_label, barcode in prs.position_map.iteritems(): if barcode is None: continue pos = get_rack_position_from_label(pos_label) # FIXME: Enable this test once pulling a tube by barcode is # fast. # if tube_agg.get_by_slug(barcode): # self.add_error('Tube with barcode "%s" already ' # 'exists.' % barcode) # continue if not rack.is_empty(pos): self.add_error('Trying to place a tube in an occupied ' 'position (%s on rack %s).' % (pos_label, rack.barcode)) continue tube = Tube.create_from_rack_and_position(cnt_specs, status, barcode, rack, pos) tubes.append(tube) self.add_info('Creating tube with barcode %s at ' 'position %s in rack %s.' % (barcode, pos_label, rack.barcode)) if not self.has_errors(): self.return_value = tubes
def create_from_data(cls, data): # We reuse molecule design sets that have the same members. agg = get_root_aggregate(cls) mds = data.pop('molecule_designs') rpr_str = MoleculeDesignPool.make_member_hash_string(mds) agg.filter = eq(member_hash=md5(rpr_str).hexdigest()) md_pools = list(agg.iterator()) if len(md_pools) == 0: # New molecule design pool. md_pool = cls(molecule_designs=mds, **data) else: md_pool, = md_pools # Must be exactly one matching pool here. return md_pool
def test_get_by_id_and_slug(self, class_entity_repo, ent0): agg = class_entity_repo.get_aggregate(IMyEntity) agg.add(ent0) assert agg.get_by_id(0) is ent0 assert agg.get_by_slug('0') is ent0 assert agg.get_by_id(-1) is None assert agg.get_by_slug('-1') is None agg.filter = eq(id=1) assert agg.get_by_id(0) is None assert agg.get_by_slug('0') is None with pytest.raises(ValueError) as cm: agg.add(object()) exp_msg = 'Invalid data type for traversal' assert str(cm.value).startswith(exp_msg)
def test_filter_order_slice(self): ent0 = MyEntity(id=0) ent1 = MyEntity(id=1) ent2 = MyEntity(id=2) cache = EntityCache(entities=[]) cache.add(ent0) cache.add(ent1) cache.add(ent2) filter_expr = EvalFilterExpression(~eq(id=0)) order_expr = EvalOrderExpression(asc('id')) slice_key = slice(1, 2) self.assert_equal(list(cache.retrieve(filter_expression=filter_expr, order_expression=order_expr, slice_key=slice_key)), [ent2])
def test_nested_attribute(self, class_entity_repo, ent0, ent1, ent2): agg = class_entity_repo.get_aggregate(IMyEntity) agg.add(ent0) agg.add(ent1) agg.add(ent2) assert len(list(agg.iterator())) == 3 agg.filter = eq(**{'parent.text':'222'}) assert len(list(agg.iterator())) == 1 agg.filter = None assert len(list(agg.iterator())) == 3 agg.order = asc('parent.text') assert next(agg.iterator()) is ent2 # With nested filter and order. agg.filter = gt(**{'parent.text':'000'}) assert next(agg.iterator()) is ent1 # With nested filter, order, and slice. agg.slice = slice(1, 2) assert next(agg.iterator()) is ent0
def test_filter_order_slice(self, class_configurator): class_configurator.begin() try: ent0 = MyEntity(id=0) ent1 = MyEntity(id=1) ent2 = MyEntity(id=2) cache = EntityCache(entities=[]) cache.add(ent0) cache.add(ent1) cache.add(ent2) filter_expr = EvalFilterExpression(~eq(id=0)) order_expr = EvalOrderExpression(asc('id')) slice_key = slice(1, 2) assert list(cache.retrieve(filter_expression=filter_expr, order_expression=order_expr, slice_key=slice_key)) \ == [ent2] finally: class_configurator.end()
def get_iso(cls, value): agg = get_root_aggregate(IStockSampleCreationIso) agg.filter = eq(label=value) return list(agg.iterator())[0]
def get_iso_request(cls, value): ir_agg = get_root_aggregate(IStockSampleCreationIsoRequest) ir_agg.filter = eq(label=value) return ir_agg.iterator().next()
def test_not(self): spec = ~eq(number_attr=1) self.assert_true(isinstance(spec, NegationFilterSpecification)) self.assert_true(spec.is_satisfied_by(self.candidate))
def test_or(self): spec = eq(number_attr=1) | eq(text_attr='attr') self.assert_true(isinstance(spec, DisjunctionFilterSpecification)) self.assert_true(spec.is_satisfied_by(self.candidate))
def __check_new_supplier_molecule_designs(self): self.add_debug('Checking for new supplier molecule designs.') smd_agg = get_root_aggregate(ISupplierMoleculeDesign) # FIXME: We should really build a single filtering spec here like so: # spec = reduce(or_, # [eq(supplier=sri.supplier, product_id=sri.product_id) # for in in self.sample_registration_items]) # However, this leads to "maximum recursion depth exceeded" # problems with the current everest. exst_smd_map = {} for sri in self.registration_items: smd_spec = eq(supplier=sri.supplier, product_id=sri.product_id, is_current=True) smd_agg.filter = smd_spec try: smd = next(smd_agg.iterator()) except StopIteration: continue else: exst_smd_map[(smd.supplier, smd.product_id)] = smd new_smd_sri_map = {} for sri in self.registration_items: mdpri = sri.molecule_design_pool_registration_item # Set the molecule type. mdpri.molecule_type = sri.molecule_type key = (sri.supplier, sri.product_id) if key in exst_smd_map: # Update sample registration item. smd = exst_smd_map[key] sri.supplier_molecule_design = smd if not smd.molecule_design_pool is None: # Compare found design information against existing design # information. mdris = mdpri.molecule_design_registration_items found_md_hashes = \ sorted([MoleculeDesign.make_structure_hash( mdri.chemical_structures) for mdri in mdris]) exist_mds = smd.molecule_design_pool.molecule_designs exist_md_hashes = sorted([md.structure_hash for md in exist_mds]) if found_md_hashes != exist_md_hashes: msg = 'For product ID "%s" and supplier "%s", a ' \ 'supplier molecule design exists which has ' \ 'different design information than the one ' \ 'included in the current registration.' \ % (sri.product_id, sri.supplier.name) self.add_error(msg) continue else: # FIXME: Should this be a warning instead? msg = 'For product ID "%s" and supplier "%s", a ' \ 'supplier molecule design was found which does ' \ 'not have an associated molecule design pool.' \ % (sri.product_id, sri.supplier.name) self.add_error(msg) continue else: # We use a map here so that multiple sample registration items # with the same supplier molecule design information create # only a single new supplier molecule design. new_smd_sri_map.setdefault(key, []).append(sri) # Store new supplier molecule design registration items for later use. self.__new_smd_sri_map = new_smd_sri_map
def test_not(self, specification_candidate): #pylint: disable=W0621 spec = ~eq(number_attr=NUMBER_VALUE - 1) assert isinstance(spec, NegationFilterSpecification) assert spec.is_satisfied_by(specification_candidate)
def __get_rack(self, barcode): rack_agg = get_root_aggregate(IRack) rack_agg.filter = eq(barcode=barcode) return next(rack_agg.iterator())
def test_eq_generator(self): spec = eq(number_attr=0) & eq(text_attr='attr') self.assert_true(spec.is_satisfied_by(self.candidate))
def view_member(view_collection): #pylint: disable=W0621 view_collection.filter = eq(id=0) return next(iter(view_collection))
def __get_target_rack(self, barcode): rack_agg = get_root_aggregate(IRack) rack_agg.filter = eq(barcode=barcode) return next(rack_agg.iterator())
def test_multiple_keywords(self): spec = eq(number_attr=0, text_attr='attr') self.assert_true(isinstance(spec, ConjunctionFilterSpecification)) self.assert_true(spec.is_satisfied_by(self.candidate))
def test_or(self, specification_candidate): #pylint: disable=W0621 spec = eq(number_attr=NUMBER_VALUE - 1) | eq(text_attr=TEXT_VALUE) assert isinstance(spec, DisjunctionFilterSpecification) assert spec.is_satisfied_by(specification_candidate)
def filter_by(self, **kw): spec = eq(**kw) visitor_cls = get_filter_specification_visitor(self.expression_kind) vst = visitor_cls(self._entity_class) spec.accept(vst) return vst.filter_query(self)