Source code for clld.db.models.source
from sqlalchemy import Column, Integer, String, Unicode, ForeignKey
from sqlalchemy.orm import relationship
from sqlalchemy.ext.declarative import declared_attr
from zope.interface import implementer
from clld.db.meta import Base, PolymorphicBaseMixin
from clld import interfaces
from clld.lib import bibtex
from clld.lib import coins
from clld.web.util.htmllib import HTML
from . import (
IdNameDescriptionMixin,
DataMixin, HasDataMixin, FilesMixin, HasFilesMixin,
Language, LanguageSource)
__all__ = ('Source', 'HasSourceMixin', 'HasSourceNotNullMixin')
class Source_data(Base, DataMixin):
pass
class Source_files(Base, FilesMixin):
pass
[docs]@implementer(interfaces.ISource)
class Source(Base,
PolymorphicBaseMixin,
IdNameDescriptionMixin,
HasDataMixin,
HasFilesMixin):
"""A bibliographic record, cited as source for some statement."""
glottolog_id = Column(String)
google_book_search_id = Column(String)
#
# BibTeX fields:
#
bibtex_type = Column(bibtex.EntryType.db_type())
author = Column(Unicode)
year = Column(Unicode)
title = Column(Unicode)
type = Column(Unicode)
booktitle = Column(Unicode)
editor = Column(Unicode)
pages = Column(Unicode)
edition = Column(Unicode)
journal = Column(Unicode)
school = Column(Unicode)
address = Column(Unicode)
url = Column(Unicode)
note = Column(Unicode)
number = Column(Unicode)
series = Column(Unicode)
volume = Column(Unicode)
publisher = Column(Unicode)
organization = Column(Unicode)
chapter = Column(Unicode)
howpublished = Column(Unicode)
# typed information we might want to use for searching or sorting:
year_int = Column(Integer)
startpage_int = Column(Integer)
pages_int = Column(Integer)
languages = relationship(
Language, backref='sources', secondary=LanguageSource.__table__)
@property
def gbs_identifier(self):
if not self.jsondata.get('gbs'):
return
if not self.jsondata['gbs']['volumeInfo'].get('industryIdentifiers'):
return
id_ = None
for identifier in self.jsondata['gbs']['volumeInfo']['industryIdentifiers']:
# prefer ISBN_13 over ISBN_10 over anything else
if identifier['type'] == 'ISBN_13':
id_ = 'ISBN:' + identifier['identifier']
if identifier['type'] == 'ISBN_10' and not id_:
id_ = 'ISBN:' + identifier['identifier']
if not id_:
# grab the last one in the list (most probably the only one!)
id_ = identifier['identifier']
return id_
def __bibtex__(self):
return {}
def bibtex(self, exclude={'gbs', 'glottolog_ref_id'}):
kw = {k: v for k, v in self.jsondata.items() if k not in exclude}
kw.update(self.__bibtex__())
return bibtex.Record.from_object(self, **kw)
def coins(self, req):
return HTML.span(
' ',
**coins.ContextObject.from_bibtex(
req.dataset.name, self.bibtex()).span_attrs()
)
#
# Several objects can be linked to sources, i.e. they can have references.
#
class HasSourceMixin(object):
key = Column(Unicode) # the citation key, specific (and unique) within a contribution
description = Column(Unicode) # e.g. page numbers.
@declared_attr
def source_pk(cls): # pragma: no cover
return Column(Integer, ForeignKey('source.pk'))
@declared_attr
def source(cls): # pragma: no cover
return relationship(Source, backref=cls.__name__.lower() + 's')
class HasSourceNotNullMixin(HasSourceMixin):
@declared_attr
def source_pk(cls):
return Column(Integer, ForeignKey('source.pk'), nullable=False)
@declared_attr
def source(cls):
return relationship(Source, innerjoin=True, backref=cls.__name__.lower() + 's')