lasertube-flask/models.py

126 lines
3.3 KiB
Python

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.schema import ForeignKey, PrimaryKeyConstraint
from sqlalchemy.types import TypeDecorator, BLOB, DateTime
from sqlalchemy.orm import relationship
from sqlalchemy import Column, Integer, String
import numbers
import json
# jso: An object which can be encoded in JSON
def attr_spec(k):
if not isinstance(k, basestring):
return k
else:
return k, None
def rgattr_spec(o, spec):
if spec == None:
return ((attr, None) for attr in o)
else:
return (attr_spec(k) for k in spec)
def toJso(o, spec=None):
if isinstance(o, (basestring, numbers.Number)):
return o
if isinstance(o, list):
result = []
for v in o:
result.append(toJso(v, spec))
return result
if isinstance(o, dict):
result = {}
for attr, specNew in rgattr_spec(o, spec):
result[attr] = toJso(o[attr], specNew)
return result
if spec == None and hasattr(o, '__json_spec__'):
spec = o.__json_spec__
if spec != None:
result = {}
for attr, specNew in rgattr_spec(o, spec):
result[attr] = toJso(getattr(o, attr), specNew)
return result
raise Exception("Don't know how to convert " + str(type(o)) + " to json: " + repr(o))
def fromJso(jso, classes, spec=None):
if classes == None:
return jso
if isinstance(classes, type):
classes = (classes,)
if spec == None:
spec = classes[0].__json_spec__
if len(classes) == 1:
if hasattr(classes[0], '__json_classmap__'):
classmap = classes[0].__json_classmap__
else:
classmap = {}
else:
classmap = classes[1]
def set_attr(o, k, v):
if isinstance(o, dict):
o[k] = v
else:
setattr(o, k, v)
if isinstance(jso, dict):
o = classes[0]()
for attr, specNew in (attr_spec(k) for k in spec):
set_attr(o, attr, fromJso(jso[attr], classmap.get(attr), specNew))
return o
if isinstance(jso, list):
return [fromJso(v, spec, classes) for v in jso]
return jso
class JsonSqlType(TypeDecorator):
impl = BLOB
def process_bind_param(self, value, dialect):
if value is not None:
value = json.dumps(value)
return value
def process_result_value(self, value, dialect):
if value is not None:
value = json.loads(value)
return value
Base = declarative_base()
class Disc(Base):
__tablename__ = 'disc'
id = Column(Integer, primary_key=True)
title = Column(String(128))
url = Column(String(256))
ktube = Column(String(10))
class Qte(Base):
__tablename__ = 'qte'
disc_id = Column(Integer, ForeignKey("disc.id"))
ms_trigger = Column(Integer)
ms_finish = Column(Integer)
shape = Column(JsonSqlType)
disc = relationship("Disc", backref="qtes")
__table_args__ = (PrimaryKeyConstraint('disc_id', 'ms_trigger'),)
class EditSession(Base):
__tablename__ = 'editsession'
disc_id = Column(Integer, ForeignKey("disc.id"), primary_key=True)
guid = Column(String(32))
expires = Column(DateTime)
Disc.__json_spec__ = ('id', 'title', 'url', 'ktube', 'qtes')
Disc.__json_classmap__ = {'qtes': Qte}
Qte.__json_spec__ = ('ms_trigger', 'ms_finish', 'shape')