Author: phd
Date: 2005-08-11 16:08:28 +0000 (Thu, 11 Aug 2005)
New Revision: 900
Added:
trunk/SQLObject/sqlobject/inheritance/tests/test_deep_inheritance.py
Modified:
trunk/SQLObject/sqlobject/inheritance/__init__.py
Log:
Applied a patch made by Evandro Vale Miquelito - fix bugs in deep inheritance.
Reworked the patch to be in sync with sqlmeta changes.
Added a test for deep inheritance.
Modified: trunk/SQLObject/sqlobject/inheritance/__init__.py
===================================================================
--- trunk/SQLObject/sqlobject/inheritance/__init__.py 2005-08-11 16:03:38 UTC (rev 899)
+++ trunk/SQLObject/sqlobject/inheritance/__init__.py 2005-08-11 16:08:28 UTC (rev 900)
@@ -1,6 +1,7 @@
from sqlobject import sqlbuilder
from sqlobject import classregistry
-from sqlobject.main import SQLObject, SelectResults, True, False, makeProperties, getterName, setterName
+from sqlobject.main import sqlmeta, SQLObject, SelectResults, True, False, \
+ makeProperties, getterName, setterName
import iteration
@@ -64,120 +65,128 @@
**ops)
-class InheritableSQLObject(SQLObject):
- _inheritable = True
- SelectResultsClass = InheritableSelectResults
-
- def get(cls, id, connection=None, selectResults=None, childResults=None, childUpdate=False):
-
- val = super(InheritableSQLObject, cls).get(id, connection, selectResults)
-
- #DSM: If we are updating a child, we should never return a child...
- if childUpdate: return val
- #DSM: If this class has a child, return the child
- if hasattr(val, 'childName'):
- childName = val.childName
- if childName is not None:
- return val._childClasses[childName].get(id, connection=connection, selectResults=childResults)
- #DSM: Now, we know we are alone or the last child in a family...
- #DSM: It's time to find our parents
- inst = val
- while inst._parentClass and not inst._parent:
- inst._parent = inst._parentClass.get(id, connection=connection, childUpdate=True)
- inst = inst._parent
- #DSM: We can now return ourself
- return val
-
- get = classmethod(get)
-
- def addColumn(cls, columnDef, changeSchema=False, connection=None, childUpdate=False):
+class InheritableSQLMeta(sqlmeta):
+ def addColumn(sqlmeta, columnDef, changeSchema=False, connection=None, childUpdate=False):
+ soClass = sqlmeta.soClass
#DSM: Try to add parent properties to the current class
#DSM: Only do this once if possible at object creation and once for
#DSM: each new dynamic column to refresh the current class
- if childUpdate or cls._parentClass:
- for col in cls._parentClass.sqlmeta.columnList:
+ if childUpdate or soClass._parentClass:
+ for col in soClass._parentClass.sqlmeta.columnList:
cname = col.name
if cname == 'childName': continue
- setattr(cls, getterName(cname), eval(
+ setattr(soClass, getterName(cname), eval(
'lambda self: self._parent.%s' % cname))
if not col.immutable:
- setattr(cls, setterName(cname), eval(
+ setattr(soClass, setterName(cname), eval(
'lambda self, val: setattr(self._parent, %s, val)'
% repr(cname)))
if childUpdate:
- makeProperties(cls)
+ makeProperties(soClass)
return
if columnDef:
- super(InheritableSQLObject, cls).addColumn(columnDef, changeSchema, connection)
+ super(InheritableSQLMeta, sqlmeta).addColumn(columnDef, changeSchema, connection)
#DSM: Update each child class if needed and existing (only for new
#DSM: dynamic column as no child classes exists at object creation)
- for c in cls._childClasses.values():
- c.addColumn(columnDef, connection=connection, childUpdate=True)
+ for c in soClass._childClasses.values():
+ c.sqlmeta.addColumn(columnDef, connection=connection, childUpdate=True)
addColumn = classmethod(addColumn)
- def delColumn(cls, column, changeSchema=False, connection=None):
- super(InheritableSQLObject, cls).delColumn(column, changeSchema, connection)
+ def delColumn(sqlmeta, column, changeSchema=False, connection=None):
+ soClass = sqlmeta.soClass
+ super(InheritableSQLMeta, sqlmeta).delColumn(column, changeSchema, connection)
#DSM: Update each child class if needed
#DSM: and delete properties for this column
- for c in cls._childClasses.values():
+ for c in soClass._childClasses.values():
delattr(c, name)
delColumn = classmethod(delColumn)
- def addJoin(cls, joinDef, childUpdate=False):
+ def addJoin(sqlmeta, joinDef, childUpdate=False):
+ soClass = sqlmeta.soClass
#DSM: Try to add parent properties to the current class
#DSM: Only do this once if possible at object creation and once for
#DSM: each new dynamic join to refresh the current class
- if childUpdate or cls._parentClass:
- for jdef in cls._parentClass.sqlmeta.joins:
- join = jdef.withClass(cls)
+ if childUpdate or soClass._parentClass:
+ for jdef in soClass._parentClass.sqlmeta.joins:
+ join = jdef.withClass(soClass)
jname = join.joinMethodName
jarn = join.addRemoveName
- setattr(cls, getterName(jname),
+ setattr(soClass, getterName(jname),
eval('lambda self: self._parent.%s' % jname))
if hasattr(join, 'remove'):
- setattr(cls, 'remove' + jarn,
+ setattr(soClass, 'remove' + jarn,
eval('lambda self,o: self._parent.remove%s(o)' % jarn))
if hasattr(join, 'add'):
- setattr(cls, 'add' + jarn,
+ setattr(soClass, 'add' + jarn,
eval('lambda self,o: self._parent.add%s(o)' % jarn))
if childUpdate:
- makeProperties(cls)
+ makeProperties(soClass)
return
if joinDef:
- super(InheritableSQLObject, cls).addJoin(joinDef)
+ super(InheritableSQLMeta, sqlmeta).addJoin(joinDef)
#DSM: Update each child class if needed and existing (only for new
#DSM: dynamic join as no child classes exists at object creation)
- for c in cls._childClasses.values():
- c.addJoin(joinDef, childUpdate=True)
+ for c in soClass._childClasses.values():
+ c.sqlmeta.addJoin(joinDef, childUpdate=True)
addJoin = classmethod(addJoin)
- def delJoin(cls, joinDef):
- super(InheritableSQLObject, cls).delJoin(joinDef)
+ def delJoin(sqlmeta, joinDef):
+ soClass = sqlmeta.soClass
+ super(InheritableSQLMeta, sqlmeta).delJoin(joinDef)
#DSM: Update each child class if needed
#DSM: and delete properties for this join
- for c in cls._childClasses.values():
+ for c in soClass._childClasses.values():
delattr(c, meth)
delJoin = classmethod(delJoin)
+
+class InheritableSQLObject(SQLObject):
+
+ sqlmeta = InheritableSQLMeta
+ _inheritable = True
+ SelectResultsClass = InheritableSelectResults
+
+ def get(cls, id, connection=None, selectResults=None, childResults=None, childUpdate=False):
+
+ val = super(InheritableSQLObject, cls).get(id, connection, selectResults)
+
+ #DSM: If we are updating a child, we should never return a child...
+ if childUpdate: return val
+ #DSM: If this class has a child, return the child
+ if hasattr(val, 'childName'):
+ childName = val.childName
+ if childName is not None:
+ return val._childClasses[childName].get(id, connection=connection, selectResults=childResults)
+ #DSM: Now, we know we are alone or the last child in a family...
+ #DSM: It's time to find our parents
+ inst = val
+ while inst._parentClass and not inst._parent:
+ inst._parent = inst._parentClass.get(id, connection=connection, childUpdate=True)
+ inst = inst._parent
+ #DSM: We can now return ourself
+ return val
+
+ get = classmethod(get)
+
def _notifyFinishClassCreation(cls):
if not cls.sqlmeta.columnList:
# There are no columns - call addColumn to propagate columns
# from parent classes to children
- cls.addColumn(None)
+ cls.sqlmeta.addColumn(None)
if not cls.sqlmeta.joins:
# There are no joins - call addJoin to propagate joins
# from parent classes to children
- cls.addJoin(None)
+ cls.sqlmeta.addJoin(None)
_notifyFinishClassCreation = classmethod(_notifyFinishClassCreation)
def _create(self, id, **kw):
@@ -194,14 +203,16 @@
if self._parentClass:
parentClass = self._parentClass
new_kw = {}
- parent_kw = {'childName': self.__class__.__name__}
+ parent_kw = {}
for (name, value) in kw.items():
- if hasattr(parentClass, name):
- parent_kw[name] = value
- else:
- new_kw[name] = value
+ if hasattr(parentClass, name):
+ parent_kw[name] = value
+ else:
+ new_kw[name] = value
kw = new_kw
self._parent = parentClass(kw=parent_kw, connection=self._connection)
+ self._parent.childName = self.__class__.__name__
+
id = self._parent.id
super(InheritableSQLObject, self)._create(id, **kw)
Added: trunk/SQLObject/sqlobject/inheritance/tests/test_deep_inheritance.py
===================================================================
--- trunk/SQLObject/sqlobject/inheritance/tests/test_deep_inheritance.py 2005-08-11 16:03:38 UTC (rev 899)
+++ trunk/SQLObject/sqlobject/inheritance/tests/test_deep_inheritance.py 2005-08-11 16:08:28 UTC (rev 900)
@@ -0,0 +1,33 @@
+from sqlobject import *
+from sqlobject.tests.dbtest import *
+from sqlobject.inheritance import InheritableSQLObject
+
+########################################
+## Deep Inheritance
+########################################
+
+
+class DIPerson(InheritableSQLObject):
+ firstName = StringCol()
+ lastName = StringCol(alternateID=True)
+ manager = ForeignKey("DIManager", default=None)
+
+class DIEmployee(DIPerson):
+ position = StringCol()
+
+class DIManager(DIEmployee):
+ subdudes = MultipleJoin("DIPerson", joinColumn="manager_id")
+
+def test_deep_inheritance():
+ setupClass(DIManager)
+ setupClass(DIEmployee)
+ setupClass(DIPerson)
+
+ manager = DIManager(firstName='Project', lastName='Manager',
+ position='Project Manager')
+ employee = DIEmployee(firstName='Project', lastName='Leader',
+ position='Project leader', manager=manager)
+ person = DIPerson(firstName='Oneof', lastName='Authors', manager=manager)
+
+ persons = list(DIPerson.select())
+ assert len(persons) == 3
|