Skip to content

Commit

Permalink
Merge branch 'release/0.20'
Browse files Browse the repository at this point in the history
  • Loading branch information
xrotwang committed Oct 23, 2014
2 parents 14f02e8 + d1b7adb commit 390f27e
Show file tree
Hide file tree
Showing 34 changed files with 1,525 additions and 1,152 deletions.
8 changes: 8 additions & 0 deletions CHANGES.rst
Expand Up @@ -2,6 +2,14 @@
Changes
-------

0.20
~~~~

- better support for LLOD/datahub.io integration
- new map option base_layer
- refactored clld.db.models.common


0.19.2
~~~~~~

Expand Down
2 changes: 1 addition & 1 deletion clld/__init__.py
Expand Up @@ -5,7 +5,7 @@
from clld import interfaces


__version__ = "0.19.2"
__version__ = "0.20"
_Resource = namedtuple('Resource', 'name model interface with_index with_rdfdump')


Expand Down
42 changes: 41 additions & 1 deletion clld/db/models/__init__.py
@@ -1 +1,41 @@
#
from __future__ import unicode_literals, print_function, division, absolute_import

from ._mixins import (IdNameDescriptionMixin,
DataMixin, HasDataMixin, FilesMixin, HasFilesMixin)

from .config import Config

from .language import (Language_data, Language_files, Language,
LanguageSource,
IdentifierType, Identifier, LanguageIdentifier,
_add_solr_language_info)

from .gloss import GlossAbbreviation

from .source import Source_data, Source_files, Source, HasSourceMixin

from .contributor import Contributor_data, Contributor_files, Contributor

from .contribution import (Contribution_data, Contribution_files, Contribution,
ContributionReference, ContributionContributor)

from .dataset import Dataset_data, Dataset_files, Dataset

from .sentence import Sentence_data, Sentence_files, Sentence, SentenceReference

from .valueset import ValueSet_data, ValueSet_files, ValueSet, ValueSetReference

from .value import Value_data, Value_files, Value, ValueSentence

from .parameter import (DomainElement_data, DomainElement_files, DomainElement,
Parameter_data, Parameter_files, Parameter,
CombinationDomainElement, Combination)

from .unit import Unit_data, Unit_files, Unit

from .unitvalue import UnitValue_data, UnitValue_files, UnitValue

from .unitparameter import (UnitDomainElement_data, UnitDomainElement_files,
UnitDomainElement,
UnitParameter_data, UnitParameter_files, UnitParameter,
UnitParameterUnit)
138 changes: 138 additions & 0 deletions clld/db/models/_mixins.py
@@ -0,0 +1,138 @@
from __future__ import unicode_literals, print_function, division, absolute_import

import os

from sqlalchemy import Column, Integer, String, Unicode, ForeignKey
from sqlalchemy.orm import relationship
from sqlalchemy.ext.declarative import declared_attr

__all__ = [
'IdNameDescriptionMixin',
'FilesMixin', 'HasFilesMixin',
'DataMixin', 'HasDataMixin',
]


class IdNameDescriptionMixin(object):

"""Mixin for 'visible' objects, i.e. anything that has to be displayed.
In particular all :doc:`resources` fall into this category.
.. note::
Only one of :py:attr:`clld.db.models.common.IdNameDescriptionMixin.description`
or :py:attr:`clld.db.models.common.IdNameDescriptionMixin.markup_description`
should be supplied, since these are used mutually exclusively.
"""

id = Column(String, unique=True)
"""A ``str`` identifier of an object which can be used for sorting and as part of a
URL path; thus should be limited to characters valid in URLs, and should not contain
'.' or '/' since this may trip up route matching.
"""

name = Column(Unicode)
"""A human readable 'identifier' of the object."""

description = Column(Unicode)
"""A description of the object."""

markup_description = Column(Unicode)
"""A description of the object containing HTML markup."""


# ----------------------------------------------------------------------------
# We augment mapper classes for basic objects using mixins to add the ability
# to store arbitrary key-value pairs and files associated with an object.
# ----------------------------------------------------------------------------
class FilesMixin(IdNameDescriptionMixin):

"""This mixin provides a way to associate files with instances of another model class.
.. note::
The file itself is not stored in the database but must be created in the
filesystem, e.g. using the create method.
"""

@classmethod
def owner_class(cls):
return cls.__name__.split('_')[0]

ord = Column(Integer, default=1)
"""Ordinal to control sorting of files associated with one db object."""

mime_type = Column(String)
"""Mime-type of the file content."""

@declared_attr
def object_pk(cls):
return Column(Integer, ForeignKey('%s.pk' % cls.owner_class().lower()))

@property
def relpath(self):
"""OS file path of the file relative to the application's file-system dir."""
return os.path.join(self.owner_class().lower(), str(self.object.id), str(self.id))

def create(self, dir_, content):
"""Write ``content`` to a file using ``dir_`` as file-system directory.
:return: File-system path of the file that was created.
"""
p = dir_.joinpath(self.relpath)
p.dirname().makedirs_p()
with open(p, 'wb') as fp:
fp.write(content)
return p


class HasFilesMixin(object):

"""Mixin for model classes which may have associated files."""

@property
def files(self):
"""return ``dict`` of associated files keyed by ``id``."""
return dict((f.id, f) for f in self._files)

@declared_attr
def _files(cls):
return relationship(cls.__name__ + '_files', backref='object')


class DataMixin(object):

"""Provide a simple way to attach key-value pairs to a model class given by name."""

@classmethod
def owner_class(cls):
return cls.__name__.split('_')[0]

key = Column(Unicode)
value = Column(Unicode)
ord = Column(Integer, default=1)

@declared_attr
def object_pk(cls):
return Column(Integer, ForeignKey('%s.pk' % cls.owner_class().lower()))


class HasDataMixin(object):

"""Adds a convenience method to retrieve the key-value pairs from data as dict.
.. note::
It is the responsibility of the programmer to make sure conversion to a ``dict``
makes sense, i.e. the keys in data are actually unique, thus usable as dictionary
keys.
"""

def datadict(self):
"""return ``dict`` of associated key-value pairs."""
return dict((d.key, d.value) for d in self.data)

@declared_attr
def data(cls):
return relationship(cls.__name__ + '_data', order_by=cls.__name__ + '_data.ord')

0 comments on commit 390f27e

Please sign in to comment.