Update of /cvsroot/webware/Webware/MiddleKit/Core
In directory usw-pr-cvs1:/tmp/cvs-serv32556/Core
Modified Files:
Klasses.py Model.py
Log Message:
implemented brand new feature: model inheritance.
Index: Klasses.py
===================================================================
RCS file: /cvsroot/webware/Webware/MiddleKit/Core/Klasses.py,v
retrieving revision 1.3
retrieving revision 1.4
diff -C2 -d -r1.3 -r1.4
*** Klasses.py 2001/09/29 22:22:05 1.3
--- Klasses.py 2002/01/26 02:13:29 1.4
***************
*** 111,115 ****
supername = klass.supername()
if supername!='MiddleObject':
! klass.setSuperklass(self[supername])
klass.setKlasses(self)
--- 111,115 ----
supername = klass.supername()
if supername!='MiddleObject':
! klass.setSuperklass(self._model.klass(supername))
klass.setKlasses(self)
Index: Model.py
===================================================================
RCS file: /cvsroot/webware/Webware/MiddleKit/Core/Model.py,v
retrieving revision 1.5
retrieving revision 1.6
diff -C2 -d -r1.5 -r1.6
*** Model.py 2001/05/24 04:29:30 1.5
--- Model.py 2002/01/26 02:13:29 1.6
***************
*** 2,5 ****
--- 2,6 ----
from types import ClassType
from MiscUtils.Configurable import Configurable
+ from MiscUtils import NoDefault
***************
*** 11,19 ****
'''
! def __init__(self, filename=None, customCoreClasses={}):
Configurable.__init__(self)
self._filename = None
self._coreClasses = customCoreClasses
self._klasses = None
if filename!=None:
self.read(filename)
--- 12,29 ----
'''
! def __init__(self, filename=None, customCoreClasses={}, rootModel=None):
Configurable.__init__(self)
self._filename = None
self._coreClasses = customCoreClasses
self._klasses = None
+ self._parents = [] # e.g., parent models
+
+ # _allModelsByFilename is used to avoid loading the same parent model twice
+ if rootModel:
+ self._allModelsByFilename = rootModel._allModelsByFilename
+ else:
+ self._allModelsByFilename = {}
+ self._rootModel = rootModel
+
if filename!=None:
self.read(filename)
***************
*** 38,45 ****
if os.path.splitext(filename)[1]=='':
filename += '.mkmodel'
! self._filename = filename
self._name = None
self.klasses().read(os.path.join(filename, 'Classes.csv'))
def coreClass(self, className):
''' For the given name, returns a class from MiddleKit.Core or the custom set of classes that were passed in via initialization. '''
--- 48,132 ----
if os.path.splitext(filename)[1]=='':
filename += '.mkmodel'
! self._filename = os.path.abspath(filename)
self._name = None
+ self.readParents()
self.klasses().read(os.path.join(filename, 'Classes.csv'))
+ # create containers for all klasses, uniqued by name
+ models = list(self._searchOrder)
+ models.reverse()
+ byName = {}
+ inOrder = []
+ for model in models:
+ for klass in model.klasses().klassesInOrder():
+ name = klass.name()
+ if byName.has_key(name):
+ for i in range(len(inOrder)):
+ if inOrder[i].name()==name:
+ inOrder[i] = klass
+ else:
+ inOrder.append(klass)
+ byName[name] = klass
+ assert len(byName)==len(inOrder)
+ for name, klass in byName.items():
+ assert klass is self.klass(name)
+ for klass in inOrder:
+ assert klass is self.klass(klass.name())
+ self._allKlassesByName = byName
+ self._allKlassesInOrder = inOrder
+
+ def readParents(self):
+ """
+ Reads the parent models of the current model, as
+ specified in the 'Inherit' setting.
+
+ The attributes _parents and _searchOrder are set.
+ """
+ for filename in self.setting('Inherit', []):
+ filename = os.path.abspath(os.path.join(os.path.dirname(self._filename), filename))
+ if self._allModelsByFilename.has_key(filename):
+ model = self._allModelsByFilename[filename]
+ assert model!=self._rootModel
+ else:
+ model = self.__class__(filename, self._coreClasses, self)
+ self._allModelsByFilename[filename] = model
+ self._parents.append(model)
+
+ # establish the search order
+ # algorithm taken from http://www.python.org/2.2/descrintro.html#mro
+ searchOrder = self.allModelsDepthFirstLeftRight()
+
+ # remove duplicates:
+ indexes = range(len(searchOrder))
+ indexes.reverse()
+ for i in indexes:
+ model = searchOrder[i]
+ j = 0
+ while j<i:
+ if searchOrder[j] is model:
+ del searchOrder[j]
+ i -= 1
+ else:
+ j += 1
+
+ self._searchOrder = searchOrder
+
+
+ def allModelsDepthFirstLeftRight(self, parents=None):
+ """
+ Returns a list of all models, including self, parents and
+ ancestors, in a depth-first, left-to-right order. Does not
+ remove duplicates (found in inheritance diamonds).
+
+ Mostly useful for readParents() to establish the lookup
+ order regarding model inheritance.
+ """
+ if parents is None:
+ parents = []
+ parents.append(self)
+ for parent in self._parents:
+ parent.allModelsDepthFirstLeftRight(parents)
+ return parents
+
def coreClass(self, className):
''' For the given name, returns a class from MiddleKit.Core or the custom set of classes that were passed in via initialization. '''
***************
*** 60,64 ****
def klasses(self):
! ''' Return an instance that inherits from Klasses, using the base classes passed to __init__, if any. '''
if self._klasses is None:
Klasses = self.coreClass('Klasses')
--- 147,156 ----
def klasses(self):
! """
! Return an instance that inherits from Klasses, using the base
! classes passed to __init__, if any.
!
! See also: klass(), allKlassesInOrder(), allKlassesByName()
! """
if self._klasses is None:
Klasses = self.coreClass('Klasses')
***************
*** 66,71 ****
return self._klasses
! def klass(self, name):
! return self._klasses[name]
--- 158,190 ----
return self._klasses
! def klass(self, name, default=NoDefault):
! """
! Returns the klass with the given name, searching the parent
! models if necessary.
! """
! for model in self._searchOrder:
! klass = model.klasses().get(name, None)
! if klass:
! return klass
! if default is NoDefault:
! raise KeyError, name
! else:
! return default
!
! def allKlassesInOrder(self):
! """
! Returns a sequence of all the klasses in this model, unique by
! name, including klasses inherited from parent models.
!
! The order is the order of declaration, top-down.
! """
! return self._allKlassesInOrder
!
! def allKlassesByName(self):
! """
! Returns a dictionary of all the klasses in this model, unique
! by name, including klasses inherited from parent models.
! """
! return self._allKlassesByName
|