summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2012-01-22 19:03:06 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2012-01-22 19:03:06 -0500
commit82e4bc2f52f2d420842819d0ffe548ca968bf54e (patch)
tree0edb77b8bff7fe074dd0be4faafd551648901d43 /examples
parent79cf693b05bdd31b2397116f3092e3be9df6baa2 (diff)
downloadsqlalchemy-82e4bc2f52f2d420842819d0ffe548ca968bf54e.tar.gz
- [feature] Simplified the versioning example
a bit to use a declarative mixin as well as an event listener, instead of a metaclass + SessionExtension. [ticket:2313]
Diffstat (limited to 'examples')
-rw-r--r--examples/versioning/__init__.py32
-rw-r--r--examples/versioning/history_meta.py31
-rw-r--r--examples/versioning/test_versioning.py8
3 files changed, 28 insertions, 43 deletions
diff --git a/examples/versioning/__init__.py b/examples/versioning/__init__.py
index 61b8f13c6..990900940 100644
--- a/examples/versioning/__init__.py
+++ b/examples/versioning/__init__.py
@@ -13,12 +13,11 @@ be run via nose::
A fragment of example usage, using declarative::
- from history_meta import VersionedMeta, VersionedListener
+ from history_meta import Versioned, versioned_session
- Base = declarative_base(metaclass=VersionedMeta, bind=engine)
- Session = sessionmaker(extension=VersionedListener())
+ Base = declarative_base()
- class SomeClass(Base):
+ class SomeClass(Versioned, Base):
__tablename__ = 'sometable'
id = Column(Integer, primary_key=True)
@@ -27,6 +26,9 @@ A fragment of example usage, using declarative::
def __eq__(self, other):
assert type(other) is SomeClass and other.id == self.id
+ Session = sessionmaker(bind=engine)
+ versioned_session(Session)
+
sess = Session()
sc = SomeClass(name='sc1')
sess.add(sc)
@@ -44,26 +46,8 @@ A fragment of example usage, using declarative::
all() \\
== [SomeClassHistory(version=1, name='sc1')]
-To apply ``VersionedMeta`` to a subset of classes (probably more typical), the
-metaclass can be applied on a per-class basis::
-
- from history_meta import VersionedMeta, VersionedListener
-
- Base = declarative_base(bind=engine)
-
- class SomeClass(Base):
- __tablename__ = 'sometable'
-
- # ...
-
- class SomeVersionedClass(Base):
- __metaclass__ = VersionedMeta
- __tablename__ = 'someothertable'
-
- # ...
-
-The ``VersionedMeta`` is a declarative metaclass - to use the extension with
-plain mappers, the ``_history_mapper`` function can be applied::
+The ``Versioned`` mixin is designed to work with declarative. To use the extension with
+classical mappers, the ``_history_mapper`` function can be applied::
from history_meta import _history_mapper
diff --git a/examples/versioning/history_meta.py b/examples/versioning/history_meta.py
index 9544451ee..1226a8f62 100644
--- a/examples/versioning/history_meta.py
+++ b/examples/versioning/history_meta.py
@@ -1,8 +1,8 @@
-from sqlalchemy.ext.declarative import DeclarativeMeta
+from sqlalchemy.ext.declarative import declared_attr
from sqlalchemy.orm import mapper, class_mapper, attributes, object_mapper
from sqlalchemy.orm.exc import UnmappedClassError, UnmappedColumnError
from sqlalchemy import Table, Column, ForeignKeyConstraint, Integer
-from sqlalchemy.orm.interfaces import SessionExtension
+from sqlalchemy import event
from sqlalchemy.orm.properties import RelationshipProperty
def col_references_table(col, table):
@@ -80,18 +80,20 @@ def _history_mapper(local_mapper):
cls.__history_mapper__ = m
if not super_history_mapper:
- cls.version = Column('version', Integer, default=1, nullable=False)
-
+ local_mapper.local_table.append_column(
+ Column('version', Integer, default=1, nullable=False)
+ )
+ local_mapper.add_property("version", local_mapper.local_table.c.version)
-class VersionedMeta(DeclarativeMeta):
- def __init__(cls, classname, bases, dict_):
- DeclarativeMeta.__init__(cls, classname, bases, dict_)
- try:
- mapper = class_mapper(cls)
- _history_mapper(mapper)
- except UnmappedClassError:
- pass
+class Versioned(object):
+ @declared_attr
+ def __mapper_cls__(cls):
+ def map(cls, *arg, **kw):
+ mp = mapper(cls, *arg, **kw)
+ _history_mapper(mp)
+ return mp
+ return map
def versioned_objects(iter):
@@ -169,8 +171,9 @@ def create_version(obj, session, deleted = False):
session.add(hist)
obj.version += 1
-class VersionedListener(SessionExtension):
- def before_flush(self, session, flush_context, instances):
+def versioned_session(session):
+ @event.listens_for(session, 'before_flush')
+ def before_flush(session, flush_context, instances):
for obj in versioned_objects(session.dirty):
create_version(obj, session)
for obj in versioned_objects(session.deleted):
diff --git a/examples/versioning/test_versioning.py b/examples/versioning/test_versioning.py
index d91f12037..389dba918 100644
--- a/examples/versioning/test_versioning.py
+++ b/examples/versioning/test_versioning.py
@@ -1,6 +1,6 @@
from unittest import TestCase
from sqlalchemy.ext.declarative import declarative_base
-from history_meta import VersionedMeta, VersionedListener
+from history_meta import Versioned, versioned_session
from sqlalchemy import create_engine, Column, Integer, String, ForeignKey
from sqlalchemy.orm import clear_mappers, sessionmaker, deferred, relationship
from _lib import ComparableEntity, eq_
@@ -13,10 +13,8 @@ class TestVersioning(TestCase):
def setUp(self):
global Base, Session, Versioned
Base = declarative_base(bind=engine)
- class Versioned(object):
- __metaclass__ = VersionedMeta
- _decl_class_registry = Base._decl_class_registry
- Session = sessionmaker(extension=VersionedListener())
+ Session = sessionmaker()
+ versioned_session(Session)
def tearDown(self):
clear_mappers()