[Checkins] SVN: megrok.rdb/trunk/src/megrok/rdb/ added polymorphic support to megrok.rdb, see plock for example
Jordan Baker
jbb at scryent.com
Wed May 20 16:37:17 EDT 2009
Log message for revision 100175:
added polymorphic support to megrok.rdb, see plock for example
Changed:
U megrok.rdb/trunk/src/megrok/rdb/__init__.py
U megrok.rdb/trunk/src/megrok/rdb/directive.py
U megrok.rdb/trunk/src/megrok/rdb/meta.py
U megrok.rdb/trunk/src/megrok/rdb/setup.py
A megrok.rdb/trunk/src/megrok/rdb/sorted_inheritance.py
A megrok.rdb/trunk/src/megrok/rdb/tests/polymorphic.py
U megrok.rdb/trunk/src/megrok/rdb/tests/test_rdb.py
-=-
Modified: megrok.rdb/trunk/src/megrok/rdb/__init__.py
===================================================================
--- megrok.rdb/trunk/src/megrok/rdb/__init__.py 2009-05-20 13:14:59 UTC (rev 100174)
+++ megrok.rdb/trunk/src/megrok/rdb/__init__.py 2009-05-20 20:37:16 UTC (rev 100175)
@@ -1,7 +1,8 @@
from megrok.rdb.components import Model, Container, QueryContainer
from megrok.rdb.schema import Fields
from megrok.rdb.directive import (key, metadata, tablename, reflected,
- tableargs)
+ tableargs, polymorphic_on, inherits,
+ polymorphic_identity)
from megrok.rdb.setup import setupDatabase
from megrok.rdb.interfaces import IDatabaseSetupEvent
from megrok.rdb.prop import locatedproperty
Modified: megrok.rdb/trunk/src/megrok/rdb/directive.py
===================================================================
--- megrok.rdb/trunk/src/megrok/rdb/directive.py 2009-05-20 13:14:59 UTC (rev 100174)
+++ megrok.rdb/trunk/src/megrok/rdb/directive.py 2009-05-20 20:37:16 UTC (rev 100175)
@@ -21,6 +21,24 @@
scope = CLASS_OR_MODULE
store = ONCE
+class inherits(Directive):
+ scope = CLASS
+ store = ONCE
+ default = None
+
+class polymorphic_on(Directive):
+ scope = CLASS
+ store = ONCE
+ default = None
+
+ def factory(self, table, column):
+ return table, column
+
+class polymorphic_identity(Directive):
+ scope = CLASS
+ store = ONCE
+ default = None
+
class tableargs(Directive):
scope = CLASS
store = ONCE
Modified: megrok.rdb/trunk/src/megrok/rdb/meta.py
===================================================================
--- megrok.rdb/trunk/src/megrok/rdb/meta.py 2009-05-20 13:14:59 UTC (rev 100174)
+++ megrok.rdb/trunk/src/megrok/rdb/meta.py 2009-05-20 20:37:16 UTC (rev 100175)
@@ -14,8 +14,11 @@
martian.directive(rdb.metadata)
martian.directive(rdb.reflected)
martian.directive(rdb.tableargs)
+ martian.directive(rdb.inherits)
+ martian.directive(rdb.polymorphic_identity)
+ martian.directive(rdb.polymorphic_on)
- def execute(self, class_, tablename, metadata, reflected, tableargs, **kw):
+ def execute(self, class_, tablename, metadata, reflected, tableargs, inherits, polymorphic_identity, polymorphic_on, **kw):
class_.__tablename__ = tablename
if tableargs is not None:
class_.__table_args__ = tableargs
@@ -23,7 +26,14 @@
if reflected:
if not hasattr(metadata, '_reflected_registry'):
metadata._reflected_registry = {}
- metadata._reflected_registry[class_] = None
+
+ metadata._reflected_registry[class_] = dict(
+ inherits=inherits,
+ polymorphic_on=polymorphic_on,
+ polymorphic_identity=polymorphic_identity,
+ )
+
+
# if this table is reflected, don't instrument now but
# manually map later
return True
Modified: megrok.rdb/trunk/src/megrok/rdb/setup.py
===================================================================
--- megrok.rdb/trunk/src/megrok/rdb/setup.py 2009-05-20 13:14:59 UTC (rev 100174)
+++ megrok.rdb/trunk/src/megrok/rdb/setup.py 2009-05-20 20:37:16 UTC (rev 100175)
@@ -1,7 +1,6 @@
from zope import component
from zope.event import notify
-from sqlalchemy.orm import mapper
from sqlalchemy.ext.declarative import instrument_declarative
from sqlalchemy.schema import Table
@@ -40,9 +39,28 @@
metadata.reflect(bind=engine)
if not hasattr(metadata, '_decl_registry'):
metadata._decl_registry = {}
- # now declaratively set up any reflected classes
- for class_ in metadata._reflected_registry.keys():
+
+ # XXX should sort by the inheritance tree
+ for class_ in sorted(metadata._reflected_registry.keys(), key=lambda a: getattr(a, 'megrok.rdb.directive.inherits', 0)):
+ class_args = metadata._reflected_registry[class_]
+ polymorphic_on = class_args['polymorphic_on']
+ polymorphic_identity = class_args['polymorphic_identity']
+ inherits = class_args['inherits']
+ mapper_args = getattr(class_, '__mapper_args__', {})
+
+ if polymorphic_on:
+ tablename, column = polymorphic_on
+ mapper_args['polymorphic_on'] = getattr(metadata.tables[tablename].c, column)
+ if polymorphic_identity:
+ mapper_args['polymorphic_identity'] = polymorphic_identity
+ if inherits:
+ mapper_args['inherits'] = inherits
+
+ if mapper_args:
+ class_.__mapper_args__ = mapper_args
+
instrument_declarative(class_, metadata._decl_registry, metadata)
+
# XXX thread safety?
metadata._reflected_completed = True
Added: megrok.rdb/trunk/src/megrok/rdb/sorted_inheritance.py
===================================================================
--- megrok.rdb/trunk/src/megrok/rdb/sorted_inheritance.py (rev 0)
+++ megrok.rdb/trunk/src/megrok/rdb/sorted_inheritance.py 2009-05-20 20:37:16 UTC (rev 100175)
@@ -0,0 +1,37 @@
+# faasen's proof of concept of a sorting by inheritance
+class C(object):
+ pass
+
+class B(C):
+ pass
+
+class A(B):
+ pass
+
+d = {
+ A: B,
+ B: C,
+ C: None,
+ }
+
+l = [A, B, C]
+
+def sorted_inheritance(x, y):
+ if x is y:
+ return 0
+ if inherits(x, y):
+ return 1
+ else:
+ return -1
+
+def inherits(x, y):
+ if x is y:
+ return True
+ potential_base = d[x]
+ if potential_base is None:
+ return False
+ if potential_base is y:
+ return True
+ return inherits(potential_base, y)
+
+print sorted(l, cmp=sorted_inheritance)
Added: megrok.rdb/trunk/src/megrok/rdb/tests/polymorphic.py
===================================================================
--- megrok.rdb/trunk/src/megrok/rdb/tests/polymorphic.py (rev 0)
+++ megrok.rdb/trunk/src/megrok/rdb/tests/polymorphic.py 2009-05-20 20:37:16 UTC (rev 100175)
@@ -0,0 +1,81 @@
+import unittest
+
+import grok.testing
+
+from megrok import rdb
+
+metadata = rdb.MetaData()
+rdb.metadata(metadata)
+
+class Polymorphic(unittest.TestCase):
+ def setUp(self):
+ grok.testing.grok('megrok.rdb.meta')
+ from megrok.rdb.testing import configureEngine
+ engine = configureEngine()
+
+ from sqlalchemy.sql import text
+ conn = engine.connect()
+ s = text('''
+ create table content (
+ id integer,
+ type char(50),
+ primary key (id))
+ ''')
+ result = conn.execute(s)
+ s = text('''
+ create table person (
+ id integer,
+ name char(50),
+ FOREIGN KEY(id) REFERENCES content (id)
+ )
+ ''')
+ result = conn.execute(s)
+ x = conn.execute
+ x('INSERT INTO content VALUES (1, "person")')
+ x('INSERT INTO person VALUES (1, "Bob")')
+ x('INSERT INTO content VALUES (2, "content")')
+
+ def test_polymorphic_reflection(self):
+ """
+ Could test basic attributes being set but this integration test
+ ensures it continues to work with SQLAlchemy.
+ """
+
+ class Content(rdb.Model):
+ rdb.reflected()
+ rdb.polymorphic_on(table='content', column='type')
+ rdb.polymorphic_identity('content')
+
+ class Person(Content):
+ rdb.tablename('person')
+ rdb.reflected()
+ rdb.inherits(Content)
+ rdb.polymorphic_identity('person')
+
+ grok.testing.grok_component('Content', Content)
+ grok.testing.grok_component('Person', Person)
+
+ # this has to be called after classes are grokked
+ rdb.setupDatabase(metadata)
+ session = rdb.Session()
+
+ results = session.query(Content).all()
+
+ assert results
+ assert isinstance(results[0], Person)
+ # a Person has a name
+ assert results[0].name == 'Bob'
+
+ assert isinstance(results[1], Content)
+ # Content does not have a name
+ assert not hasattr(results[1], 'name')
+
+ def test_polymorphic_declarative(self):
+ """
+ Test that non-reflected works
+ """
+ assert "I am broken!"
+
+def suite():
+ return unittest.makeSuite(Polymorphic)
+
Modified: megrok.rdb/trunk/src/megrok/rdb/tests/test_rdb.py
===================================================================
--- megrok.rdb/trunk/src/megrok/rdb/tests/test_rdb.py 2009-05-20 13:14:59 UTC (rev 100174)
+++ megrok.rdb/trunk/src/megrok/rdb/tests/test_rdb.py 2009-05-20 20:37:16 UTC (rev 100175)
@@ -8,7 +8,7 @@
from z3c.saconfig.interfaces import IEngineFactory, IScopedSession
-from megrok.rdb.tests import tableargs
+from megrok.rdb.tests import tableargs, polymorphic
def moduleSetUp(test):
# using zope.testing.module.setUp to work around
@@ -61,4 +61,5 @@
optionflags=optionflags,
))
suite.addTest(tableargs.suite())
+ suite.addTest(polymorphic.suite())
return suite
More information about the Checkins
mailing list