Logo Search packages:      
Sourcecode: bauble version File versions


# species_model.py

import traceback
import xml.sax.saxutils as sax

import gtk
from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.orm.session import object_session
from sqlalchemy.ext.associationproxy import association_proxy

import bauble
import bauble.db as db
import bauble.utils as utils
from bauble.i18n import *
from bauble.utils.log import log, debug
from bauble.types import Enum
from bauble.plugins.plants.geography import Geography#, geography_table

from sqlalchemy.orm.collections import collection

00025 class VNList(list):
    A Collection class for Species.vernacular_names

    This makes it possible to automatically remove a
    default_vernacular_name if the vernacular_name is removed from the
    def remove(self, vn):
        super(VNList, self).remove(vn)
            if vn.species.default_vernacular_name == vn:
                del vn.species.default_vernacular_name
        except Exception, e:

# ***** supported names
# Genus sp
# Genus sp sp_author
# Genus sp_hybrid (cv.) 'infrasp' # not supported any more?
# Genus sp_hybrid sp
# Genus sp sp_hybrid infrasp
# Genus sp infrasp_rank infrasp
# Genus sp (cv.) 'infrasp'
# Genus sp cv_group
# Genus sp (cv.) (cv_group) 'infrasp'

# ***** names we don't support
# Genux sp x sp2 [infrasp_rank] infrasp
# Genus sp infrasp_rank infrasp 'cv'
# eg Rudbeckia fulgida var. sullivantii 'Goldsturm',
# we can't support this without more infrasp and infrasp_rank fields,
# like BGRecorder

# ***** are these even valid
# Genus x sp sp_author
# Genus sp sp_athor x infrasp infrasp_author

# TODO: there is a trade_name column but there's no support yet for editing
# the trade_name or for using the trade_name when building the string
# for the species, for more information about trade_names see,
# http://www.hortax.org.uk/gardenplantsnames.html

00072 class Species(db.Base):
    :Table name: species

            Hybrid flag

            Possible values:
                H: A hybrid formula for an Interspecific hybrid

                x: A Nothotaxon name for an Interspecific hybrid

                +: An Interspecific graft hybrid or graft chimaera

            Species qualifier

            Possible values:
                *agg.*: An aggregate species

                *s. lat.*: aggregrate species (sensu lato)

                *s. str.*: segregate species (sensu stricto)

            The infraspecific rank

            Possible values:
                *subsp.*: subspecies

                *variety.*: variety

                *subvar.*: sub variety

                *f.*: form

                *subf.*: subform

                *cv.*: cultivar

            The infraspecific epithet






        The combination of sp, sp_author, sp_hybrid, sp_qual,
        cv_group, trade_name, infrasp, infrasp_author, infrasp_rank,
    __tablename__ = 'species'
    __table_args__ = (UniqueConstraint('sp', 'sp_author', 'sp_hybrid',
                                        'sp_qual', 'cv_group', 'trade_name',
                                        'infrasp', 'infrasp_author',
                                        'infrasp_rank', 'genus_id',
    _mapper_args__ = {'order_by': ['sp', 'sp_author', 'infrasp_rank',

    # columns
    sp = Column(Unicode(64), nullable=False, index=True)
    sp_author = Column(Unicode(128))
    sp_hybrid = Column(Enum(values=['x', '+', 'H', '']), default=u'')
    sp_qual = Column(Enum(values=['agg.', 's. lat.', 's. str.', '']),
    cv_group = Column(Unicode(50))
    trade_name = Column(Unicode(64))
    infrasp = Column(Unicode(50))
    infrasp_author = Column(Unicode(255))
    infrasp_rank = Column(Enum(values=['subsp.', 'var.', 'subvar.', 'f.',
                                       'subf.', 'cv.', '']), default=u'')
    notes = Column(UnicodeText)
    genus_id = Column(Integer, ForeignKey('genus.id'), nullable=False)

    # relations
    synonyms = association_proxy('_synonyms', 'synonym')
    _synonyms = relation('SpeciesSynonym',
                         cascade='all, delete-orphan', uselist=True,
    vernacular_names = relation('VernacularName', cascade='all, delete-orphan',
                                backref=backref('species', uselist=False))
    _default_vernacular_name = relation('DefaultVernacularName', uselist=False,
                                         cascade='all, delete-orphan',
    distribution = relation('SpeciesDistribution',
                            cascade='all, delete-orphan',
                            backref=backref('species', uselist=False))

    def __init__(self, *args, **kwargs):
        super(Species, self).__init__(*args, **kwargs)
        self.__cached_str = {}

00181     def init_on_load(self):
        Called instead of __init__() when an Species is loaded from
        the database.
        self.__cached_str = {}

00189     def __str__(self):
        returns a string representation of this species,
        calls Species.str(self)
        return Species.str(self)

    def _get_default_vernacular_name(self):
        if self._default_vernacular_name is None:
            return None
        return self._default_vernacular_name.vernacular_name
    def _set_default_vernacular_name(self, vn):
        if vn is None:
            del self.default_vernacular_name
        if vn not in self.vernacular_names:
        d = DefaultVernacularName()
        d.vernacular_name = vn
        self._default_vernacular_name = d
    def _del_default_vernacular_name(self):
        del self._default_vernacular_name
    default_vernacular_name = property(_get_default_vernacular_name,

    def distribution_str(self):
        if self.distribution is None:
            return ''
            dist = ['%s' % d for d in self.distribution]
            return unicode(', ').join(sorted(dist))

00225     def markup(self, authors=False):
        returns this object as a string with markup

        @param authors: flag to toggle whethe the author names should be
        return Species.str(self, authors, True)

00236     def str(species, authors=False, markup=False, use_cache=True):
        returns a string for species

        @param species: the species object to get the values from
        @param authors: flags to toggle whether the author names should be
        @param markup: flags to toggle whether the returned text is marked up
        to show italics on the epithets
        if use_cache:
                cached = species.__cached_str[(markup, authors)]
            except KeyError:
                species.__cached_str[(markup, authors)] = None
                cached = None
            session = object_session(species)
            if cached is not None and species not in session.dirty:
                return cached

        genus = str(species.genus)
        sp = species.sp
        infrasp = species.infrasp
        if markup:
            italic = u'<i>%s</i>'
            #genus = italic % species.genus
            genus = italic % utils.xml_safe_utf8(genus)
            if sp is not None: # shouldn't really be allowed
                sp = italic % species.sp
            # the infrasp italic is handled below
            #escape = sax.escape
            escape = utils.xml_safe_utf8
            if species.infrasp_rank not in (u'cv.', 'cv.'):
                infrasp = italic % species.infrasp
            italic = u'%s'
            escape = lambda x: x

        author = None
        isp_author = None
        if authors:
            if species.sp_author:
                author = escape(species.sp_author)
            if species.infrasp_author:
                isp_author = escape(species.infrasp_author)

        if species.sp_hybrid: # is a hybrid
            if species.infrasp is not None:
                if species.infrasp_rank is None:
                    name = [s for s in [genus, sp, author, species.sp_hybrid,
                                        infrasp, isp_author] \
                                if s is not None]
                elif species.infrasp_rank in (u'cv.', 'cv.'):
                    if species.cv_group:
                        cv = "(%s Group) '%s'" % \
                            (species.cv_group, infrasp)
                        cv = "'%s'" % infrasp
                    name = [s for s in [genus, species.sp_hybrid, sp, author,
                                        cv, isp_author] \
                                if s not in (None, '')]
                    name = [s for s in [genus, species.sp_hybrid, sp, author,
                                        species.infrasp_rank, infrasp,
                                        isp_author] \
                                if s not in (None, '')]
                name = [s for s in [genus, species.sp_hybrid, sp, author] \
                        if s not in (None, '')]
        else: # isn't a hybrid
            if species.cv_group:
                if species.infrasp is None:
                    cv = None
                    group = '%s Group' % species.cv_group
                    cv = "'%s'" % infrasp
                    group = '(%s Group)' % species.cv_group
                name = [s for s in [genus, sp, author, group, cv, isp_author] \
                        if s not in (None, '')]
                if species.infrasp is None:
                    isp = None
                    isp_rank = None
                    if species.infrasp_rank == 'cv.':
                        isp_rank = None
                        isp = "'%s'" % (species.infrasp or '')
                        isp_rank = species.infrasp_rank
                        #isp = italic % species.infrasp
                        isp = infrasp
                name = [s for s in [genus, sp, author, isp_rank, isp,
                                    isp_author] if s not in (None, '')]

        if species.sp_qual not in (None, ''):

        s = u' '.join(name)
        species.__cached_str[(markup, authors)] = s
        return s

# TODO: deleting either of the species this synonym refers to makes
# this synonym irrelevant
00340 class SpeciesSynonym(db.Base):
    :Table name: species_synonym
    __tablename__ = 'species_synonym'
    __table_args__ = (UniqueConstraint('species_id', 'synonym_id',

    # columns
    species_id = Column(Integer, ForeignKey('species.id'),
    synonym_id = Column(Integer, ForeignKey('species.id'),

    # relations
    synonym = relation('Species', uselist=False,

    def __init__(self, synonym=None, **kwargs):
        # it is necessary that the first argument here be synonym for
        # the Species.synonyms association_proxy to work
        self.synonym = synonym
        super(SpeciesSynonym, self).__init__(**kwargs)

    def __str__(self):
        return str(self.synonym)

00369 class VernacularName(db.Base):
    :Table name: vernacular_name

            the vernacular name

            language is free text and could include something like UK
            or US to identify the origin of the name

            key to the species this vernacular name refers to


    __tablename__ = 'vernacular_name'
    name = Column(Unicode(128), nullable=False)
    language = Column(Unicode(128))
    species_id = Column(Integer, ForeignKey('species.id'), nullable=False)
    __table_args__ = ((UniqueConstraint('name', 'language',
                                        'species_id', name='vn_index')))

    def __str__(self):
        return self.name

00400 class DefaultVernacularName(db.Base):
    :Table name: default_vernacular_name

    DefaultVernacularName is not meant to be instantiated directly.
    Usually the default vernacular name is set on a species by setting
    the default_vernacular_name property on Species to a
    VernacularName instance

            Integer, primary_key

            foreign key to species.id, nullable=False



    __tablename__ = 'default_vernacular_name'
    __table_args__ = (UniqueConstraint('species_id', 'vernacular_name_id',

    # columns
    species_id = Column(Integer, ForeignKey('species.id'), nullable=False)
    vernacular_name_id = Column(Integer, ForeignKey('vernacular_name.id'),

    # relations
    vernacular_name = relation(VernacularName, uselist=False)

    def __str__(self):
        return str(self.vernacular_name)

00439 class SpeciesDistribution(db.Base):
    :Table name: species_distribution



    __tablename__ = 'species_distribution'

    # columns
    geography_id = Column(Integer, ForeignKey('geography.id'), nullable=False)
    species_id = Column(Integer, ForeignKey('species.id'), nullable=False)

    def __str__(self):
        return str(self.geography)

# late bindings
SpeciesDistribution.geography = relation('Geography',

Generated by  Doxygen 1.6.0   Back to index