Example #1
0
def is_code_unique(plant, code):
    """
    Return True/False if the code is a unique Plant code for accession.

    This method will also take range values for code that can be passed
    to utils.range_builder()
    """
    # if the range builder only creates one number then we assume the
    # code is not a range and so we test against the string version of
    # code
    codes = map(utils.utf8, utils.range_builder(code))  # test if a range
    if len(codes) == 1:
        codes = [utils.utf8(code)]

    # reference accesssion.id instead of accession_id since
    # setting the accession on the model doesn't set the
    # accession_id until the session is flushed
    session = db.Session()
    count = (
        session.query(Plant)
        .join("accession")
        .filter(and_(Accession.id == plant.accession.id, Plant.code.in_(codes)))
        .count()
    )
    session.close()
    return count == 0
    def test_bulk_plant_editor(self):
        """
        Test creating multiple plants with the plant editor.
        """
        try:
            import gtk
        except ImportError:
            raise SkipTest('could not import gtk')
        # use our own plant because PlantEditor.commit_changes() will
        # only work in bulk mode when the plant is in session.new
        p = Plant(accession=self.accession, location=self.location, code=u'2',
                  quantity=52)
        self.editor = PlantEditor(model=p)
        #editor.start()
        update_gui()
        rng = '2,3,4-6'

        for code in utils.range_builder(rng):
            q = self.session.query(Plant).join('accession').\
                filter(and_(Accession.id==self.plant.accession.id,
                            Plant.code==utils.utf8(code)))
            self.assert_(not q.first(), 'code already exists')

        widgets = self.editor.presenter.view.widgets
        # make sure the entry gets a Problem added to it if an
        # existing plant code is used in bulk mode
        widgets.plant_code_entry.set_text('1,' + rng)
        widgets.plant_quantity_entry.set_text('2')
        update_gui()
        problem = (self.editor.presenter.PROBLEM_DUPLICATE_PLANT_CODE,
                   self.editor.presenter.view.widgets.plant_code_entry)
        self.assert_(problem in self.editor.presenter.problems,
                     'no problem added for duplicate plant code')

        # create multiple plant codes
        widgets.plant_code_entry.set_text(rng)
        update_gui()
        self.editor.handle_response(gtk.RESPONSE_OK)

        for code in utils.range_builder(rng):
            q = self.session.query(Plant).join('accession').\
                filter(and_(Accession.id==self.plant.accession.id,
                            Plant.code==utils.utf8(code)))
            self.assert_(q.first(), 'plant %s.%s not created' % \
                            (self.accession, code))
    def test_range_builder(self):
        """Test bauble.utils.range_builder
        """
        assert utils.range_builder('1-3') == [1, 2, 3]
        assert utils.range_builder('1-3,5-7') == [1, 2, 3, 5, 6 ,7]
        assert utils.range_builder('1-3,5') == [1, 2, 3, 5]
        assert utils.range_builder('1-3,5,7-9')== [1, 2, 3, 5, 7, 8, 9]
        assert utils.range_builder('1,2,3,4') == [1, 2, 3, 4]
        assert utils.range_builder('11') == [11]

        # bad range strings
        assert utils.range_builder('-1') == []
        assert utils.range_builder('a-b') == []
        #self.assertRaises(ParseException, utils.range_builder, '-1')
        self.assertRaises(CheckConditionError, utils.range_builder, '2-1')
Example #4
0
    def test_range_builder(self):
        """Test bauble.utils.range_builder
        """
        assert utils.range_builder('1-3') == [1, 2, 3]
        assert utils.range_builder('1-3,5-7') == [1, 2, 3, 5, 6, 7]
        assert utils.range_builder('1-3,5') == [1, 2, 3, 5]
        assert utils.range_builder('1-3,5,7-9') == [1, 2, 3, 5, 7, 8, 9]
        assert utils.range_builder('1,2,3,4') == [1, 2, 3, 4]
        assert utils.range_builder('11') == [11]

        # bad range strings
        assert utils.range_builder('-1') == []
        assert utils.range_builder('a-b') == []
        #self.assertRaises(ParseException, utils.range_builder, '-1')
        self.assertRaises(CheckConditionError, utils.range_builder, '2-1')
    def commit_changes(self):
        """
        """
        codes = utils.range_builder(self.model.code)
        if len(codes) <= 1 or self.model not in self.session.new \
                and not self.branched_plant:
            change = self.presenter.change
            if self.branched_plant:
                # branch mode
                self.branched_plant.quantity -= self.model.quantity
                change.parent_plant = self.branched_plant
                if not change.to_location:
                    change.to_location = self.model.location
            elif change.quantity is None \
                    or (change.quantity == self.model.quantity and \
                            change.from_location == self.model.location and \
                            change.quantity==self.presenter._original_quantity):
                # if the quantity and location haven't changed then
                # don't save the change
                # UPDATE:
                # TODO: why save the change, what if we want to indicate
                # a change even if the quantity and location hasn't
                # changed?
                utils.delete_or_expunge(change)
                self.model.change = None
            else:
                if self.model.location != change.from_location:
                    # transfer
                    change.to_location = self.model.location
                elif self.model.quantity > self.presenter._original_quantity \
                        and not change.to_location:
                    # additions should use to_location
                    change.to_location = self.model.location
                    change.from_location = None
                else:
                    # removal
                    change.quantity = -change.quantity
            super(PlantEditor, self).commit_changes()
            self._committed.append(self.model)
            return

        # this method will create new plants from self.model even if
        # the plant code is not a range....its a small price to pay
        plants = []
        mapper = object_mapper(self.model)
        # TODO: precompute the _created and _last_updated attributes
        # incase we have to create lots of plants it won't be too slow

        # we have to set the properties on the new objects
        # individually since session.merge won't create a new object
        # since the object is already in the session
        import sqlalchemy.orm as orm
        for code in codes:
            new_plant = Plant()
            self.session.add(new_plant)

            # TODO: can't we user Plant.duplicate here
            ignore = ('changes', 'notes', 'propagations')
            for prop in mapper.iterate_properties:
                if prop.key not in ignore:
                    setattr(new_plant, prop.key, getattr(self.model, prop.key))
            new_plant.code = utils.utf8(code)
            new_plant.id = None
            new_plant._created = None
            new_plant._last_updated = None
            plants.append(new_plant)
            for note in self.model.notes:
                new_note = PlantNote()
                for prop in object_mapper(note).iterate_properties:
                    setattr(new_note, prop.key, getattr(note, prop.key))
                new_note.plant = new_plant
        try:
            map(self.session.expunge, self.model.notes)
            self.session.expunge(self.model)
            super(PlantEditor, self).commit_changes()
        except:
            self.session.add(self.model)
            raise
        self._committed.extend(plants)