"""SQLAlchemy-powered model definitions for bones."""
from sqlalchemy import Column
from sqlalchemy import String
from lxml import etree
from ....lib.utils import make_id
from ....lib.i18n import _
from ....models import DBDeclarativeClass, ID_LEN, LABEL_LEN
from ....models.dbbase import DBBaseClass
from ..relaxng import RELAXNG_CIOSKELETON
# =============================================================================
[docs]class DBBone(DBDeclarativeClass, DBBaseClass): # type: ignore
"""SQLAlchemy-powered bone class."""
suffix = 'cioskt'
attachments_dir = 'cioskt'
_settings_tabs = (_('Information'),)
__tablename__ = 'bones'
__table_args__ = {'mysql_engine': 'InnoDB'}
bone_id = Column(String(ID_LEN), primary_key=True)
label = Column(String(LABEL_LEN), nullable=False)
attachments_key = Column(String(ID_LEN + 20))
picture = Column(String(ID_LEN + 4))
# -------------------------------------------------------------------------
[docs] @classmethod
def xml2db(cls, dbsession, bone_elt, error_if_exists=True, kwargs=None):
"""Load a bone from a XML element.
:type dbsession: sqlalchemy.orm.session.Session
:param dbsession:
SQLAlchemy session.
:type bone_elt: lxml.etree.Element
:param bone_elt:
Bone XML element.
:param bool error_if_exists: (default=True)
It returns an error if bone already exists.
:param dict kwargs: (optional)
Dictionary of keyword arguments.
:rtype: :class:`pyramid.i18n.TranslationString` or ``None``
:return:
Error message or ``None``.
"""
# pylint: disable = unused-argument
# Check if already exists
bone_id = make_id(bone_elt.get('id'), 'token', ID_LEN)
dbbone = dbsession.query(cls).filter_by(bone_id=bone_id).first()
if dbbone is not None:
if error_if_exists:
return _('Bone "${s}" already exists.', {'s': bone_id})
return None
# Create bone
record = cls.record_from_xml(bone_id, bone_elt)
error = cls.record_format(record)
if error:
return error
dbsession.add(cls(**record))
return None
# -------------------------------------------------------------------------
[docs] @classmethod
def record_from_xml(cls, bone_id, bone_elt):
"""Convert a bone XML element into a dictionary.
:param str bone_id:
Bone ID.
:type bone_elt: lxml.etree.Element
:param bone_elt:
Bone XML element.
:rtype: dict
"""
namespace = RELAXNG_CIOSKELETON['namespace']
attachments = bone_elt.find('{{{0}}}attachments'.format(namespace))
return {
'bone_id': bone_id,
'label': bone_elt.findtext(
'{{{0}}}label'.format(namespace)) or bone_id,
'attachments_key': attachments is not None and attachments.get(
'key') or None,
'picture': attachments is not None and attachments.findtext(
'{{{0}}}picture'.format(namespace)) or None}
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
[docs] def db2xml(self):
"""Serialize a bone to a XML representation.
:rtype: lxml.etree.Element
"""
bone_elt = etree.Element('{{{0}}}bone'.format(
RELAXNG_CIOSKELETON['namespace']))
bone_elt.set('id', self.bone_id)
etree.SubElement(bone_elt, 'label').text = self.label
if self.attachments_key:
elt = etree.SubElement(
bone_elt, 'attachments', key=self.attachments_key)
if self.picture:
etree.SubElement(elt, 'picture').text = self.picture
return bone_elt