Changeset 305

Show
Ignore:
Timestamp:
02/03/08 19:36:55 (10 months ago)
Author:
johnbywater
Message:

Added support for temporal associate list attributes.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/src/dm/db.py

    r304 r305  
    1 """KForge Data Mapper. Follows 'Data Mapper (165)', [Fowler, 2003] 
    2      
    3 This module provides relational database persistence to the Domain Model. 
    4  
    5 It is responsible for moving data between domain model objects and database 
    6 objects. SQLObject is used as an object-relational mapper to move data 
    7 between database objects and a relational database management system. 
     1"""Model Persistence Data Mapper. Follows 'Data Mapper (165)', [Fowler, 2003] 
     2     
     3This module provides persistence data mapping services to the domain model. 
     4 
     5Responsible for moving values between domain objects and database objects. 
    86 
    97This module works by using domain model meta data objects to construct data 
     
    1614It also provides various features for making selections from the domain model, 
    1715such as after-before intervals for times, and search for text attributes. 
    18  
    19  
    20     # create facade 
    21     import dm.db 
    22     db = dm.db.DatabaseFacade() 
    23  
    24     # define mapper class 
    25     db.createMapperClass(metaDomainObject) 
    26  
    27     # create records 
    28     project = db.createRecord('Project', name='projekt') 
    29     person = db.createRecord('Person', name='joe') 
    30     member = db.createRecord('Member', project=project, person=person) 
    31  
    32     # read records 
    33     project = db.findRecord('Project', name='projekt') 
    34     person = db.findRecord('Person', name='joe') 
    35     member = db.findRecord('Member', project=project, person=person) 
     16The temporal aspects of domain models are also provided by this module, which 
     17has the opportunity to direct persistence of temporal values to the temporal 
     18model, confusing this with neither the domain model or the ORM. 
     19 
     20At the moment SQLObject is used as an object-relational mapper to move between 
     21database objects and a relational database management system. We want to add 
     22support for other Object Relational Mappers (such as SQLAlchemy and Elixir). 
     23 
    3624""" 
    3725 
     
    555543                self.default = None 
    556544        self.isDomainObjectRef = self.dom.isDomainObjectRef 
     545        self.isValueRef = self.dom.isValueRef 
     546        self.isAssociateList = self.dom.isAssociateList 
    557547 
    558548    def createMapperClassAttribute(self): 
     
    755745        currentVersion = None 
    756746        if self.domainObject.meta.isTemporal: 
    757             r = self.domainObject.meta.createTemporalCollection(self.domainObject) 
    758             loadedList = {self.domainObject: self.domainObject} 
    759             currentVersion = r.findFirstDomainObject(loadedList=loadedList) 
     747            currentVersion = self.domainObject.temporalHistory.getCurrent() 
    760748        self.domainObject.id = self.id 
    761749        for metaAttr in self.meta.attributes: 
     
    777765                #     - we need to look in the temporal model. 
    778766                if self.domainObject.meta.isTemporal: 
    779                     r = self.domainObject.meta.createTemporalCollection(self.domainObject) 
    780                     current = r.findFirstDomainObject(loadedList) 
    781                     if current: 
    782                         mappedValue = getattr(current, domName) 
     767                    if currentVersion: 
     768                        mappedValue = getattr(currentVersion, domName) 
    783769                    else: 
    784770                        mappedValue = metaAttr.dom.createInitialValue( 
     
    786772                        ) 
    787773                else: 
    788                     r = metaAttr.dom.createTemporalCollection(self.domainObject) 
    789                     current = r.findFirstDomainObject(loadedList) 
    790                     if current: 
    791                         mappedValue = current.recordedValue 
     774                    # Temporal property histories are virtual ATM. 
     775                    p = metaAttr.dom.createTemporalCollection(self.domainObject) 
     776                    currentPropertyVersion = p.findFirstDomainObject(loadedList) 
     777                    if currentPropertyVersion: 
     778                        mappedValue = currentPropertyVersion.recordedValue 
    792779                    else: 
    793780                        mappedValue = metaAttr.dom.createInitialValue( 
     
    818805                mappedValue = getattr(self, dbName) 
    819806            setattr(self.domainObject, domName, mappedValue) 
     807 
    820808        if moddebug and debug: 
    821809            message = "Loaded %s from record #%s" % ( 
     
    830818        currentVersion = None 
    831819        if self.domainObject.meta.isTemporal: 
    832             r = self.domainObject.meta.createTemporalCollection(self.domainObject) 
    833             loadedList = {self.domainObject: self.domainObject} 
    834             currentVersion = r.findFirstDomainObject(loadedList=loadedList) 
     820            currentVersion = self.domainObject.temporalHistory.getCurrent() 
    835821            if not currentVersion: 
    836                 currentVersion = r.create(loadedList=loadedList) 
    837822                isChangedTemporal = True 
    838             else: 
     823 
     824            if not isChangedTemporal: 
    839825                for metaAttr in self.domainObject.meta.attributes: 
    840826                    if metaAttr.isTemporal: 
    841                         domName = metaAttr.name 
    842                         recordedValue = getattr(currentVersion, domName) 
    843                         actualValue = getattr(self.domainObject, domName) 
    844                         if actualValue != recordedValue: 
    845                             isChangedTemporal = True 
    846                 if isChangedTemporal: 
    847                     currentVersion = r.create(loadedList=loadedList) 
     827                        if metaAttr.isAssociateList: 
     828                            recordedRegister = getattr(currentVersion, metaAttr.name) 
     829                            recordedList = recordedRegister.getObjectList() 
     830                            actualRegister = getattr(self.domainObject, metaAttr.name) 
     831                            actualList = actualRegister.getObjectList() 
     832                            recordedLen = len(recordedList) 
     833                            actualLen = len(actualList) 
     834                            print "Checking association list values for changes..." 
     835                            print "Recorded: %s, actual: %s)...." % (recordedLen, actualLen) 
     836                            if recordedLen == actualLen: 
     837                                for i in recordedList: 
     838                                    if i.recordedValue not in actualList: 
     839                                        print "Missing item: %s" % i.recordedValue 
     840                                        isChangedTemporal = True 
     841                                        break 
     842                                    else: 
     843                                        print "Found item in record: %s" % i.recordedValue 
     844                                if isChangedTemporal: 
     845                                    break 
     846                            else: 
     847                                print "Length mismatch!" 
     848                                isChangedTemporal = True 
     849                                break 
     850                        else: 
     851                            domName = metaAttr.name 
     852                            recordedValue = getattr(currentVersion, domName) 
     853                            actualValue = getattr(self.domainObject, domName) 
     854                            if actualValue != recordedValue: 
     855                                isChangedTemporal = True 
     856                                break 
     857            if isChangedTemporal: 
     858                print "Is changed!!!!!!! Creating new current version of associate list." 
     859                loadedList = {self.domainObject: self.domainObject} 
     860                history = self.domainObject.temporalHistory 
     861                currentVersion = history.create(loadedList=loadedList) 
     862 
     863                for metaAttr in self.domainObject.meta.attributes: 
     864                    if metaAttr.isTemporal and metaAttr.isAssociateList: 
     865                        isListChanged = False 
     866                        recordedRegister = getattr(currentVersion, metaAttr.name) 
     867                        recordedList = recordedRegister.getObjectList() 
     868                        actualRegister = getattr(self.domainObject, metaAttr.name) 
     869                        actualList = actualRegister.getObjectList() 
     870                        recordedLen = len(recordedList) 
     871                        actualLen = len(actualList) 
     872                        print "Checking association list values for changes..." 
     873                        print "Recorded: %s, actual: %s)...." % (recordedLen, actualLen) 
     874                        if recordedLen == actualLen: 
     875                            for i in recordedList: 
     876                                if i.recordedValue not in actualList: 
     877                                    print "Missing item: %s" % i.recordedValue 
     878                                    isListChanged = True 
     879                                    break 
     880                                else: 
     881                                    print "Found item in record: %s" % i.recordedValue 
     882                        else: 
     883                            print "Length mismatch!" 
     884                            isListChanged = True 
     885     
     886                        if isListChanged: 
     887                            print "List is changed...." 
     888                            for item in actualRegister: 
     889                                print "Adding list item to temporal record: %s" % item 
     890                                key = actualRegister.getRegisterKey(item) 
     891                                try: 
     892                                    listItem = recordedRegister.create( 
     893                                        recordedValue=item, 
     894                                        recordedKey=key 
     895                                    ) 
     896                                    print "Created: %s" % listItem 
     897 
     898                                except TypeError, inst: 
     899                                    msg = "Couldn't add item %s with key %s to temporal associate list register %s: %s" % (item, key, recordedRegister, inst) 
     900                                    print msg 
     901                                    raise Exception, msg 
     902                                print "Recorded register now: %s" % [i for i in recordedRegister] 
     903 
    848904        for metaAttr in self.meta.attributes: 
    849905            domValue = getattr(self.domainObject, metaAttr.domName) 
     
    853909                #     - we need to look in the temporal model. 
    854910                if self.domainObject.meta.isTemporal: 
    855                     if isChangedTemporal: 
    856                         setattr(currentVersion, metaAttr.domName, domValue) 
     911                    setattr(currentVersion, metaAttr.domName, domValue) 
    857912                else: 
    858                     r = metaAttr.dom.createTemporalCollection(self.domainObject) 
     913                    # Temporal property histories are virtual ATM. 
     914                    p = metaAttr.dom.createTemporalCollection(self.domainObject) 
    859915                    loadedList = {self.domainObject: self.domainObject} 
    860                     current = r.findFirstDomainObject(loadedList=loadedList) 
     916                    current = p.findFirstDomainObject(loadedList=loadedList) 
    861917                    if current == None or current.recordedValue != domValue: 
    862                         r.create(recordedValue=domValue, loadedList=loadedList) 
     918                        p.create(recordedValue=domValue, loadedList=loadedList) 
    863919            elif metaAttr.isDomainObjectRef: 
    864920                domainObject = domValue 
     
    871927                    setattr(self, metaAttr.dbName, domRecord) 
    872928                    isChanged = True 
    873             else
     929            elif metaAttr.isValueRef
    874930                dbValue = getattr(self, metaAttr.dbName) 
    875931                if domValue != dbValue: 
    876932                    setattr(self, metaAttr.dbName, domValue) 
    877933                    isChanged = True 
     934 
    878935        if isChangedTemporal: 
    879936            currentVersion.save() 
  • trunk/src/dm/dom/base.py

    r304 r305  
    1919 
    2020 
    21 class AbstractList(DomainBase): 
     21# Todo: Rename as AbstractRegister - this class is NOT a list. :-) 
     22class AbstractList(DomainBase):  
    2223    """ 
    2324    Supertype for domain model registers. 
     
    4243 
    4344    def __contains__(self, key): 
    44         "Supports: if key in register:
     45        "NB: Use item's key to test containment of item in register.
    4546        return self.has_key(key) 
    4647 
    4748    def __getitem__(self, key): 
    48         "Supports: item = register[key]" 
    4949        item = self.find(key) 
    5050        return item 
    5151 
    5252    def get(self, key, default=None): 
    53         "Implements: register[key] if key in register, else default (None)." 
    5453        try: 
    5554            return self.__getitem__(key) 
     
    5857                 
    5958    def has_key(self, key): 
    60         "Tests existence of register entity with key." 
    6159        if self.isCached: 
    6260            if key in self.cache: 
     
    9492    def beginTransaction(self): 
    9593        "Begins a transaction." 
     94        # Commit, commit, commit, rollback, begin, commit, commit. 
    9695        return self.database.beginTransaction() 
    9796         
     
    123122    def __init__(self, typeName='', keyName='id', metaAttr=None, **kwds): 
    124123        super(DomainObjectRegister, self).__init__(**kwds) 
    125         self.typeName = typeName 
     124        # Recorded domain class name. 
     125        self.typeName = typeName   
     126        # Attribute used to key register. 
    126127        self.keyName = keyName 
     128        # Meta object for supported model attribute. 
    127129        self.metaAttr = metaAttr 
     130        # Attributes used in basic search. 
    128131        if 'searchAttributeNames' in kwds: 
    129132            self.searchAttributeNames = kwds['searchAttributeNames'] 
     
    174177 
    175178    def __iter__(self, **kwds): 
    176         "Returns iterator for registered items." 
     179        "Returns iterator for registered items (not keys!)." 
    177180        self.coerceKwds(kwds) 
    178181        self.switchToRecords(kwds) 
     
    629632            raise DomainClassRegistrationError(message) 
    630633        if len(self.meta.attributesDeferred): 
    631             message = "Class '%s' has mismatched attributes: %s" % ( 
     634            message = "Class '%s' has mismatched (deferred) attributes: %s" % ( 
    632635                className, str(self.meta.attributesDeferred)) 
    633636            raise DomainClassRegistrationError(message) 
  • trunk/src/dm/dom/meta.py

    r304 r305  
    1616moddebug = False 
    1717 
    18 # todo: Add Email attribute class. 
     18 
     19 
     20# todo: Add Email attribute meta class. 
    1921 
    2022class NotDefined(object): 
     
    185187        return False 
    186188 
     189    # Todo: Remove; apparently redundant given isAssociateList attribute?. 
    187190    def isList(self): 
    188191        return False 
     
    633636 
    634637 
     638class TemporalRegisterMixin(object): 
     639 
     640    def __iter__(self): 
     641        return iter([]) 
     642 
     643 
    635644class AssociateList(DomainObjectAssociation): 
    636645    "Models aquaintance with several domain objects." 
     
    644653        self.key = key 
    645654        self.owner = owner 
    646      
     655    
     656    # Todo: Remove; apparently redundant given isAssociateList attribute?. 
    647657    def isList(self): 
    648658        return True 
     
    671681 
    672682    def createInitialValue(self, domainObject): 
    673         className = self.typeName 
    674         recordClass = self.registry.getDomainClass(className) 
     683        # Just instantiate a register for this attribute on this object. 
     684        return self.createRegister(domainObject) 
     685 
     686    def createRegister(self, domainObject): 
     687        recordClass = self.registry.getDomainClass(self.typeName) 
    675688        registerClass = recordClass.registerClass 
     689        if self.isTemporal: 
     690            className = "Temporal%s" % registerClass.__name__ 
     691            classBases = (TemporalRegisterMixin, registerClass) 
     692            registerClass = type(className, classBases, {}) 
    676693        register = registerClass( 
    677694            typeName=self.typeName, 
  • trunk/src/dm/dom/registry.py

    r304 r305  
    22from dm.dom.base import * 
    33from dm.dom.stateful import * 
    4 from dm.dom.temporal import TemporalProperty, BitemporalProperty, BitemporalActual, TemporalRevision 
     4from dm.dom.temporal import TemporalProperty 
     5from dm.dom.temporal import BitemporalProperty 
     6from dm.dom.temporal import BitemporalActual 
     7from dm.dom.temporal import TemporalRevision 
     8from dm.dom.temporal import TemporalAssociateList 
    59from dm.ioc import *  
    610from dm.exceptions import *  
     
    3640            if domainClass.dbName: 
    3741                domainClass.meta.dbName = domainClass.dbName 
     42 
     43        if domainClass.isTemporal==True: 
     44            temporalClassName = self.makeTemporalRevisionClassName(domainClass.meta) 
     45            domainClass.temporalHistory = HasMany(temporalClassName, 'id', 'parent') 
    3846 
    3947        # 
     
    6674            for attrMeta in domainClass.meta.attributes: 
    6775                if attrMeta.isTemporal: 
    68                     parentMeta = domainClass.meta 
    69                     self.generateTemporalPropertyClass(parentMeta, attrMeta) 
     76                    if attrMeta.isAssociateList: 
     77                        raise Exception, "No support for independently temporal associate lists at this time. Try setting the class isTemporal to true? %s on %s" % (attrMeta, domainClass.meta) 
     78                    else: 
     79                        parentMeta = domainClass.meta 
     80                        self.generateTemporalPropertyClass(parentMeta, attrMeta) 
     81 
     82    def makeTemporalRevisionClassName(self, classMeta): 
     83        return TemporalRevision.makeTemporalName(classMeta.name) 
    7084 
    7185    def generateTemporalRevisionClass(self, parentMeta, metaAttrs): 
    72         # No support for bitemporal revisions yet! 
     86        # No support for bitemporal object revisions yet! 
    7387        temporalBase = TemporalRevision 
    74         temporalClassName = TemporalRevision.makeTemporalName(parentMeta.name
     88        temporalClassName = self.makeTemporalRevisionClassName(parentMeta
    7589        temporalMeta = temporalBase.metaClass(temporalClassName) 
     90        todoParams = [] 
    7691        for metaAttr in metaAttrs: 
    77             newAttr = metaAttr.duplicateTemporal() 
     92            if metaAttr.isAssociateList: 
     93                temporalListClassName = temporalBase.makeTemporalName( 
     94                    parentMeta.name, metaAttr.name) 
     95 
     96                todoParams.append((temporalMeta, metaAttr, temporalListClassName)) 
     97                newAttr = AggregatesMany(temporalListClassName, 'id', 'parent') 
     98            else: 
     99                newAttr = metaAttr.duplicateTemporal() 
    78100            setattr(temporalMeta, metaAttr.name, newAttr) 
    79101        temporalMeta.parent = HasA(parentMeta.name, isRequired=True) 
    80102        temporalClass = self.createDomainClass(temporalMeta, temporalBase) 
    81103        parentMeta.setTemporalDomainClass(temporalClass) 
     104        for params in todoParams: 
     105            self.generateTemporalAssociateListClass(params[0], params[1], params[2]) 
     106                
     107    def generateTemporalAssociateListClass(self, parentMeta, attrMeta, temporalClassName): 
     108        # No support for bitemporal associate lists yet! 
     109        temporalBase = TemporalAssociateList 
     110        temporalMeta = temporalBase.metaClass(temporalClassName) 
     111        keyMeta = attrMeta.getKeyMetaAttribute() 
     112        if keyMeta: 
     113            temporalMeta.recordedKey = keyMeta.duplicateTemporal() 
     114        else: 
     115            temporalMeta.recordedKey = Integer(isRequired=True) 
     116        temporalMeta.recordedValue = HasA(attrMeta.typeName, isRequired=True) 
     117        temporalMeta.parent = HasA(parentMeta.name, isRequired=True) 
     118        temporalClass = self.createDomainClass(temporalMeta, temporalBase) 
     119        attrMeta.setTemporalDomainClass(temporalClass) 
    82120 
    83121    def generateTemporalPropertyClass(self, parentMeta, attrMeta): 
  • trunk/src/dm/dom/temporal.py

    r304 r305  
    22from dm.dom.meta import DateTime, String, Integer 
    33from dm.ioc import RequiredFeature 
    4 import mx.DateTime 
    54 
     5 
     6# Todo: Constraints regarding stateful requirements of temporal objects. 
    67 
    78class BaseTemporalCollection(DomainObjectRegister): 
     
    1011    timepoint = RequiredFeature('Timepoint') 
    1112 
    12     def getReferenceTime(self): 
     13    def getCreateTime(self): 
     14        return self.timepoint.now() 
     15 
     16    def getFindTime(self): 
    1317        return self.timepoint.recorded 
    1418 
    1519    def create(self, dateCreated=None, loadedList={}, **kwds): 
    1620        if dateCreated == None: 
    17             dateCreated = self.getReferenceTime() 
     21            dateCreated = self.getCreateTime() 
    1822        return super(BaseTemporalCollection, self).create( 
    1923            dateCreated=dateCreated, __loadedList__=loadedList, **kwds 
     
    2125 
    2226    def findFirstDomainObject(self, loadedList={}): 
    23         referenceTime = self.getReferenceTime() 
     27        referenceTime = self.getFindTime() 
    2428        return super(BaseTemporalCollection, self).findFirstDomainObject( 
    2529            __loadedList__=loadedList, 
    2630            __dateCreatedOnOrBefore__=referenceTime 
    2731        ) 
     32 
     33    def getCurrent(self): 
     34        loadedList = {self.owner: self.owner} 
     35        return self.findFirstDomainObject(loadedList=loadedList) 
    2836   
    2937 
     
    4048class BitemporalActualCollection(TemporalCollection): 
    4149 
    42     def getReferenceTime(self): 
     50    def getCreateTime(self): 
     51        return self.timepoint.actual 
     52 
     53    def getFindTime(self): 
    4354        return self.timepoint.actual 
    4455 
     
    141152 
    142153 
     154class TemporalAssociateListCollection(BaseTemporalCollection): 
     155 
     156    def create(self, recordedValue, recordedKey, loadedList={}, dateCreated=None): 
     157        return super(TemporalAssociateListCollection, self).create( 
     158            recordedKey=recordedKey, 
     159            recordedValue=recordedValue, 
     160            loadedList=loadedList, 
     161            dateCreated=dateCreated, 
     162        ) 
     163 
     164 
     165class TemporalAssociateList(BaseTemporal): 
     166 
     167    registerClass = TemporalAssociateListCollection 
     168 
     169 
  • trunk/src/dm/dom/temporaltest.py

    r304 r305  
    22from dm.dom.testunit import TestCase 
    33from dm.exceptions import * 
    4 from dm.dom.stateful import SimpleNamedObject, String, DateTime, HasA 
     4from dm.dom.stateful import SimpleObject, SimpleNamedObject, NamedStatefulObject, StatefulObject, String, DateTime, HasA, HasMany, AggregatesMany 
    55from dm.dom.base import DomainObjectRegister 
    66from dm.ioc import RequiredFeature 
     
    2424 
    2525 
    26 class TemporalObjectExample(SimpleNamedObject): 
     26class TemporalObjectExampleGrant(StatefulObject): 
     27 
     28    example = HasA('TemporalObjectExample', isRequired=True) 
     29    permission  = HasA('Permission', isRequire=True) 
     30 
     31 
     32class TemporalObjectExample(NamedStatefulObject): 
    2733 
    2834    isTemporal = True 
     
    3036    title = String(default='Baby Title', isTemporal=True) 
    3137    address = String(default='Baby Address', isTemporal=True) 
     38    person = HasA('Person', isRequired=False, isTemporal=True) 
     39    grants = AggregatesMany('TemporalObjectExampleGrant', 'permission', 'example', isTemporal=True) 
    3240 
    3341 
     
    4856        self.timepoint.reset() 
    4957 
    50     def test_instance(self): 
     58    def test_title(self): 
     59        self.timepoint.reset() 
    5160        self.instance = self.collection.create() 
    5261        title1 = "Title1" 
     
    8089        self.failUnlessEqual(instance.title, title4) 
    8190 
     91    def _test_grants(self): 
     92        permissions = self.registry.permissions.getSortedList() 
     93        permission1 = permissions[0] 
     94        permission2 = permissions[1] 
     95        permission3 = permissions[2] 
     96        permission4 = permissions[3] 
     97 
     98        self.timepoint.reset() 
     99        self.instance = self.collection.create() 
     100        self.instance.grants.create(permission1) 
     101        self.instance.save() 
     102        revision1 = mx.DateTime.now() 
     103        instance = self.collection[''] 
     104        self.failUnless(permission1 in instance.grants) 
     105        self.failIf(permission2 in instance.grants) 
     106        self.failIf(permission3 in instance.grants) 
     107        self.failIf(permission4 in instance.grants) 
     108        sleep(1) 
     109        del(self.instance.grants[permission1]) 
     110        self.instance.grants.create(permission2) 
     111        self.instance.save() 
     112        self.instance.grants.create(permission3) 
     113        self.instance.save() 
     114        revision3 = mx.DateTime.now() 
     115        sleep(1) 
     116        self.instance.grants.create(permission4) 
     117        self.instance.save() 
     118        revision4 = mx.DateTime.now() 
     119 
     120        print "Sleeping" 
     121        sleep(5) 
     122 
     123        self.timepoint.reset() 
     124        grants = self.getGrants() 
     125        self.failIf(permission1 in grants, grants) 
     126        self.failUnless(permission2 in grants, grants) 
     127        self.failUnless(permission3 in grants, grants) 
     128        self.failUnless(permission4 in grants, grants) 
     129 
     130        self.timepoint.recorded = revision3 
     131        grants = self.getGrants() 
     132        self.failIf(permission1 in grants, grants) 
     133        self.failUnless(permission2 in grants, grants) 
     134        self.failUnless(permission3 in grants, grants) 
     135        self.failIf(permission4 in grants, (permission4, grants)) 
     136 
     137        self.timepoint.recorded = revision1 
     138        grants = self.getGrants() 
     139        self.failUnless(permission1 in grants, grants) 
     140        self.failIf(permission2 in grants, grants) 
     141        self.failIf(permission3 in grants, grants) 
     142        self.failIf(permission4 in grants, grants) 
     143 
     144        self.timepoint.recorded = revision4 
     145        grants = self.getGrants() 
     146        self.failIf(permission1 in grants, grants) 
     147        self.failUnless(permission2 in grants, grants) 
     148        self.failUnless(permission3 in grants, grants) 
     149        self.failUnless(permission4 in grants, grants) 
     150 
     151        self.timepoint.reset() 
     152        grants = self.getGrants() 
     153        self.failIf(permission1 in grants, grants) 
     154        self.failUnless(permission2 in grants, grants) 
     155        self.failUnless(permission3 in grants, grants) 
     156        self.failUnless(permission4 in grants, grants) 
     157 
     158        # Wow! 
     159 
     160 
     161    def getGrants(self): 
     162        return [i.permission for i in self.collection[''].grants] 
    82163 
    83164class TestTemporalProperty(TestCase): 
     
    114195        self.failUnlessEqual(self.property.getSortOnValue(), (self.property.dateCreated, self.property.id)) 
    115196 
    116     def test_getReferenceTime(self): 
     197    def test_getFindTime(self): 
    117198        time1 = mx.DateTime.DateTime(2003, 6, 1) 
    118199        self.timepoint.recorded = time1 
    119         self.failUnlessEqual(self.collection.getReferenceTime(), time1) 
     200        self.failUnlessEqual(self.collection.getFindTime(), time1) 
     201        sleep(0.1) 
     202        self.failUnlessEqual(self.collection.getFindTime(), time1) 
     203 
     204    def test_getCreateTime(self): 
     205        time1 = mx.DateTime.DateTime(2003, 6, 1) 
     206        self.timepoint.recorded = time1 
     207        sleep(0.1) 
     208        self.failUnless(self.collection.getCreateTime() > time1) 
    120209 
    121210 
     
    128217        self.collection = BitemporalActual.createRegister(ownerName='parent') 
    129218        self.property = None 
     219        self.timepoint.reset() 
    130220 
    131221    def tearDown(self): 
     
    175265            property1.delete() 
    176266 
    177     def test_getReferenceTime(self): 
     267    def test_getFindTime(self): 
    178268        time1 = mx.DateTime.DateTime(2003, 6, 1) 
    179269        self.timepoint.actual = time1 
    180         self.failUnlessEqual(self.collection.getReferenceTime(), time1) 
    181          
     270        self.failUnlessEqual(self.collection.getFindTime(), time1) 
     271        self.timepoint.reset() 
     272        self.timepoint.recorded = time1 
     273        self.failIfEqual(self.collection.getFindTime(), time1) 
     274 
     275    def test_getCreateTime(self): 
     276        time1 = mx.DateTime.DateTime(2003, 6, 1) 
     277        self.timepoint.actual = time1 
     278        self.failUnlessEqual(self.collection.getCreateTime(), time1) 
     279        self.timepoint.reset() 
     280        self.timepoint.recorded = time1 
     281        self.failIfEqual(self.collection.getCreateTime(), time1) 
    182282 
    183283 
     
    262362#            property1.delete() 
    263363 
    264     def test_getReferenceTime(self): 
     364    def test_getFindTime(self): 
    265365        time1 = mx.DateTime.DateTime(2003, 6, 1) 
    266366        self.timepoint.recorded = time1 
    267         self.failUnlessEqual(self.collection.getReferenceTime(), time1) 
     367        self.failUnlessEqual(self.collection.getFindTime(), time1) 
     368        sleep(0.1) 
     369        self.failUnlessEqual(self.collection.getFindTime(), time1) 
     370 
     371    def test_getCreateTime(self): 
     372        time1 = mx.DateTime.DateTime(2003, 6, 1) 
     373        self.timepoint.recorded = time1 
     374        sleep(0.1) 
     375        self.failUnless(self.collection.getCreateTime() > time1) 
    268376 
    269377 
  • trunk/src/dm/migrate.py

    r294 r305  
    2727            classData = {} 
    2828            domainClass = domainClassRegister[className] 
     29            print "Dumping register %s" % className 
    2930            # Dumping class meta data 
    3031            metaClassData = {} 
  • trunk/src/dm/testunit.py

    r303 r305  
    2727        from dm.dom.temporaltest import Temporal 
    2828        self.registry.registerDomainClass(Temporal) 
     29        from dm.dom.temporaltest import TemporalObjectExampleGrant 
     30        self.registry.registerDomainClass(TemporalObjectExampleGrant) 
    2931        from dm.dom.temporaltest import TemporalObjectExample 
    3032        self.registry.registerDomainClass(TemporalObjectExample)