/demisauce/demisauce/model/version.py

https://github.com/araddon/demisauce · Python · 107 lines · 104 code · 3 blank · 0 comment · 1 complexity · 6536a2ea0133aa6f5b7214c242c0482c MD5 · raw file

  1. import logging, json
  2. from sqlalchemy import Column, MetaData, ForeignKey, Table, \
  3. func, UniqueConstraint
  4. from sqlalchemy import Integer, String as DBString, DateTime, Boolean, \
  5. Text as DBText
  6. from sqlalchemy import engine, orm
  7. from sqlalchemy.orm import mapper, relation, class_mapper, synonym, dynamic_loader
  8. from sqlalchemy.sql import and_, text
  9. from datetime import datetime
  10. import formencode
  11. import random, hashlib, string
  12. from wtforms import Form, BooleanField, TextField, TextAreaField, \
  13. PasswordField, SelectField, SelectMultipleField, HiddenField, \
  14. IntegerField, validators
  15. from wtforms.validators import ValidationError
  16. from tornado import escape
  17. from tornado.options import options
  18. from demisauce import model
  19. from demisauce.model import meta
  20. from demisauce.model import ModelBase, SerializationMixin
  21. from datetime import datetime
  22. log = logging.getLogger("demisauce")
  23. version = Table('version', meta.metadata,
  24. Column('id', Integer, primary_key=True),
  25. Column("version", Integer, default = 0),
  26. Column('person_id', None, ForeignKey('person.id')),
  27. Column('object_id', Integer,default=0),
  28. Column('object_type', DBString(60)),
  29. Column('value', DBText),
  30. Column("approved", Boolean, default=False),
  31. Column("created", DateTime,default=datetime.now),
  32. )
  33. class Version(ModelBase):
  34. schema = version
  35. def use_version(self,cls):
  36. """"""
  37. try:
  38. _json = escape.json_decode(self.value)
  39. obj = cls.saget(_json['id'])
  40. obj.from_dict(_json)
  41. return obj
  42. except ValueError:
  43. log.error("could not decode json for cls=%s, json=%s" % (cls,self.value))
  44. return None
  45. @classmethod
  46. def create_version(cls,obj,user,expunge=False):
  47. 'creates version of obj'
  48. jsons = obj.to_json()
  49. versionct = 0
  50. v = Version()
  51. v.object_id = obj.id
  52. if expunge:
  53. meta.DBSession.refresh(obj)
  54. #v._session.expunge(obj)'
  55. if obj.version_latest and obj.version_latest.id > 0:
  56. versionct = obj.version_latest.version + 1
  57. cls_name = str(obj.__class__)
  58. cls_name = cls_name[cls_name.rfind('.')+1:cls_name.rfind('\'')].lower()
  59. v.object_type = cls_name
  60. v.person_id = user.id
  61. v.value = jsons
  62. v.version = versionct
  63. v.save()
  64. return v
  65. class VersionMixin(object):
  66. def _set_version(self, version):
  67. if version:
  68. self._version = version
  69. else:
  70. self._version = version
  71. def _get_version(self):
  72. if hasattr(self,'_version'):
  73. return self._version
  74. cls_name = str(self.__class__)
  75. cls_name = cls_name[cls_name.find('.')+1:cls_name.rfind('\'')].lower()
  76. self._version = self._session.query(Version).filter(and_(Version.object_id == self.id,Version.object_type==cls_name)).first()
  77. return self._version
  78. version = property(_get_version, _set_version)
  79. def versionable(cls,name):
  80. """Versionable Mixin/Mutator"""
  81. mapper = class_mapper(cls)
  82. table = mapper.local_table
  83. cls_name = str(cls)
  84. cls_name = cls_name[cls_name.rfind('.')+1:cls_name.rfind('\'')].lower()
  85. mapper.add_property('versions', dynamic_loader(Version,
  86. primaryjoin=and_(table.c.id==version.c.object_id,version.c.object_type==cls_name),
  87. foreign_keys=[version.c.object_id],
  88. backref='%ss' % table.name))
  89. # most recent version
  90. def version_latest(self):
  91. if self.versions is None:
  92. return None
  93. return self.versions.order_by(version.c.version.desc()).first()
  94. setattr(cls, "version_latest", property(version_latest))