From: Mike Bayer Date: Sun, 16 Feb 2014 21:38:09 +0000 (-0500) Subject: - use column.info to detect those cols part of "versioning" X-Git-Tag: rel_0_9_3~27 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4588a0e60358814119655f1af8971ab971812f6c;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - use column.info to detect those cols part of "versioning" - pep8 cleanup - fix tests for "changed" column - document that "changed" is optional - changelog --- diff --git a/doc/build/changelog/changelog_09.rst b/doc/build/changelog/changelog_09.rst index db1079d8a6..624a9dbb22 100644 --- a/doc/build/changelog/changelog_09.rst +++ b/doc/build/changelog/changelog_09.rst @@ -14,6 +14,15 @@ .. changelog:: :version: 0.9.3 + .. change:: + :tags: examples + :pullreq: github:41 + + Added optional "changed" column to the versioned rows example, as well + as support for when the versioned :class:`.Table` has an explicit + :paramref:`~.Table.schema` argument. Pull request + courtesy jplaverdure. + .. change:: :tags: bug, postgresql :tickets: 2946 diff --git a/examples/versioned_history/history_meta.py b/examples/versioned_history/history_meta.py index 20631e3698..c4479d99ef 100644 --- a/examples/versioned_history/history_meta.py +++ b/examples/versioned_history/history_meta.py @@ -1,10 +1,11 @@ """Versioned mixin class and other utilities.""" 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.orm import mapper, attributes, object_mapper +from sqlalchemy.orm.exc import UnmappedColumnError from sqlalchemy import Table, Column, ForeignKeyConstraint, Integer, DateTime from sqlalchemy import event +import datetime from sqlalchemy.orm.properties import RelationshipProperty def col_references_table(col, table): @@ -13,6 +14,9 @@ def col_references_table(col, table): return True return False +def _is_versioning_col(col): + return "version_meta" in col.info + def _history_mapper(local_mapper): cls = local_mapper.class_ @@ -31,7 +35,7 @@ def _history_mapper(local_mapper): if not super_mapper or local_mapper.local_table is not super_mapper.local_table: cols = [] for column in local_mapper.local_table.c: - if column.name == 'version': + if _is_versioning_col(column): continue col = column.copy() @@ -47,17 +51,29 @@ def _history_mapper(local_mapper): if super_mapper: super_fks.append(('version', super_history_mapper.local_table.c.version)) - cols.append(Column('version', Integer, primary_key=True, autoincrement=False)) - cols.append(Column('changed', DateTime, default=datetime.datetime.utcnow)) - else: - cols.append(Column('version', Integer, primary_key=True, autoincrement=False)) - cols.append(Column('changed', DateTime, default=datetime.datetime.utcnow)) + + version_meta = {"version_meta": True} # add column.info to identify + # columns specific to versioning + + # "version" stores the integer version id. This column is + # required. + cols.append(Column('version', Integer, primary_key=True, + autoincrement=False, info=version_meta)) + + # "changed" column stores the UTC timestamp of when the + # history row was created. + # This column is optional and can be omitted. + cols.append(Column('changed', DateTime, + default=datetime.datetime.utcnow, + info=version_meta)) if super_fks: cols.append(ForeignKeyConstraint(*zip(*super_fks))) - table = Table(local_mapper.local_table.name + '_history', local_mapper.local_table.metadata, - *cols, schema=local_mapper.local_table.schema + table = Table(local_mapper.local_table.name + '_history', + local_mapper.local_table.metadata, + *cols, + schema=local_mapper.local_table.schema ) else: # single table inheritance. take any additional columns that may have @@ -106,7 +122,7 @@ def versioned_objects(iter): if hasattr(obj, '__history_mapper__'): yield obj -def create_version(obj, session, deleted = False): +def create_version(obj, session, deleted=False): obj_mapper = object_mapper(obj) history_mapper = obj.__history_mapper__ history_cls = history_mapper.class_ @@ -122,7 +138,7 @@ def create_version(obj, session, deleted = False): continue for hist_col in hm.local_table.c: - if hist_col.key == 'version' or hist_col.key == 'changed': + if _is_versioning_col(hist_col): continue obj_col = om.local_table.c[hist_col.key] @@ -187,4 +203,4 @@ def versioned_session(session): for obj in versioned_objects(session.dirty): create_version(obj, session) for obj in versioned_objects(session.deleted): - create_version(obj, session, deleted = True) + create_version(obj, session, deleted=True) diff --git a/examples/versioned_history/test_versioning.py b/examples/versioned_history/test_versioning.py index 9062805552..73f515ed4b 100644 --- a/examples/versioned_history/test_versioning.py +++ b/examples/versioned_history/test_versioning.py @@ -6,12 +6,11 @@ from .history_meta import Versioned, versioned_session from sqlalchemy import create_engine, Column, Integer, String, ForeignKey from sqlalchemy.orm import clear_mappers, Session, deferred, relationship from sqlalchemy.testing import AssertsCompiledSQL, eq_, assert_raises -from sqlalchemy.testing.entities import BasicEntity, ComparableEntity +from sqlalchemy.testing.entities import ComparableEntity from sqlalchemy.orm import exc as orm_exc engine = None - def setup(): global engine engine = create_engine('sqlite://', echo=True) @@ -184,7 +183,7 @@ class TestVersioning(TestCase, AssertsCompiledSQL): name = Column(String(50)) type = Column(String(20)) - __mapper_args__ = {'polymorphic_on':type, 'polymorphic_identity':'base'} + __mapper_args__ = {'polymorphic_on': type, 'polymorphic_identity': 'base'} class SubClassSeparatePk(BaseClass): __tablename__ = 'subtable1' @@ -193,7 +192,7 @@ class TestVersioning(TestCase, AssertsCompiledSQL): base_id = Column(Integer, ForeignKey('basetable.id')) subdata1 = Column(String(50)) - __mapper_args__ = {'polymorphic_identity':'sep'} + __mapper_args__ = {'polymorphic_identity': 'sep'} class SubClassSamePk(BaseClass): __tablename__ = 'subtable2' @@ -201,7 +200,7 @@ class TestVersioning(TestCase, AssertsCompiledSQL): id = Column(Integer, ForeignKey('basetable.id'), primary_key=True) subdata2 = Column(String(50)) - __mapper_args__ = {'polymorphic_identity':'same'} + __mapper_args__ = {'polymorphic_identity': 'same'} self.create_tables() sess = self.session @@ -214,7 +213,7 @@ class TestVersioning(TestCase, AssertsCompiledSQL): base1.name = 'base1mod' same1.subdata2 = 'same1subdatamod' - sep1.name ='sep1mod' + sep1.name = 'sep1mod' sess.commit() BaseClassHistory = BaseClass.__history_mapper__.class_ @@ -288,14 +287,24 @@ class TestVersioning(TestCase, AssertsCompiledSQL): q = sess.query(SubSubHistory) self.assert_compile( q, - "SELECT subsubtable_history.id AS subsubtable_history_id, " + "SELECT " + + "subsubtable_history.id AS subsubtable_history_id, " "subtable_history.id AS subtable_history_id, " "basetable_history.id AS basetable_history_id, " + "basetable_history.name AS basetable_history_name, " + "basetable_history.type AS basetable_history_type, " + "subsubtable_history.version AS subsubtable_history_version, " "subtable_history.version AS subtable_history_version, " "basetable_history.version AS basetable_history_version, " + + "subsubtable_history.changed AS subsubtable_history_changed, " + "subtable_history.changed AS subtable_history_changed, " + "basetable_history.changed AS basetable_history_changed, " + "subtable_history.base_id AS subtable_history_base_id, " "subtable_history.subdata1 AS subtable_history_subdata1, " "subsubtable_history.subdata2 AS subsubtable_history_subdata2 " @@ -334,12 +343,13 @@ class TestVersioning(TestCase, AssertsCompiledSQL): id = Column(Integer, primary_key=True) name = Column(String(50)) type = Column(String(50)) - __mapper_args__ = {'polymorphic_on':type, 'polymorphic_identity':'base'} + __mapper_args__ = {'polymorphic_on': type, + 'polymorphic_identity': 'base'} class SubClass(BaseClass): subname = Column(String(50), unique=True) - __mapper_args__ = {'polymorphic_identity':'sub'} + __mapper_args__ = {'polymorphic_identity': 'sub'} self.create_tables() sess = self.session @@ -351,21 +361,23 @@ class TestVersioning(TestCase, AssertsCompiledSQL): sess.commit() - b1.name='b1modified' + b1.name = 'b1modified' BaseClassHistory = BaseClass.__history_mapper__.class_ SubClassHistory = SubClass.__history_mapper__.class_ eq_( - sess.query(BaseClassHistory).order_by(BaseClassHistory.id, BaseClassHistory.version).all(), + sess.query(BaseClassHistory).order_by(BaseClassHistory.id, + BaseClassHistory.version).all(), [BaseClassHistory(id=1, name='b1', type='base', version=1)] ) - sc.name ='s1modified' - b1.name='b1modified2' + sc.name = 's1modified' + b1.name = 'b1modified2' eq_( - sess.query(BaseClassHistory).order_by(BaseClassHistory.id, BaseClassHistory.version).all(), + sess.query(BaseClassHistory).order_by(BaseClassHistory.id, + BaseClassHistory.version).all(), [ BaseClassHistory(id=1, name='b1', type='base', version=1), BaseClassHistory(id=1, name='b1modified', type='base', version=2), @@ -375,7 +387,7 @@ class TestVersioning(TestCase, AssertsCompiledSQL): # test the unique constraint on the subclass # column - sc.name ="modifyagain" + sc.name = "modifyagain" sess.flush() def test_unique(self):