Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
34 changed files
with
1,525 additions
and
1,152 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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') |
Oops, something went wrong.