Changeset 308

Show
Ignore:
Timestamp:
03/14/08 16:26:40 (9 months ago)
Author:
johnbywater
Message:

Putting distance between domainmodel and django.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/bin/domainmodel-test

    r228 r308  
    3939        os.environ['DOMAINMODEL_SETTINGS'] = options.config 
    4040     
    41     # import after SETTINGS is set 
    42     from dm.testunit import ApplicationTestSuite 
    43     ApplicationTestSuite.buildApplication() 
     41    import dm.testunit 
     42    dm.testunit.DevApplication() 
    4443 
    4544    (options, args) = parser.parse_args() 
  • trunk/setup.py

    r246 r308  
    1616    # no way to specify the dependency on django as we need a specific revision 
    1717    install_requires = [ 
    18         'SQLObject>=0.6,<=0.7.99', 
     18        'SQLObject>=0.7.1,<=0.7.99', 
    1919        'simplejson', 
    2020        # 'Django>=0.95'  # Django not served on cheese shop 
  • trunk/src/dm/accesscontrol.py

    r246 r308  
    33from dm.dictionarywords import VISITOR_NAME 
    44from dm.strategy import FindProtectionObjects 
     5 
     6moddebug = False 
    57 
    68class BaseAccessController(object): 
     
    5557            self.assertAccessAuthorised() 
    5658        except AccessIsAuthorised, inst: 
    57             if self.debug: 
     59            if moddebug and self.debug: 
    5860                if self.person: 
    5961                    personName = self.person.name 
     
    6971            return True 
    7072        except AccessNotAuthorised, inst: 
    71             if self.debug: 
     73            if moddebug and self.debug: 
    7274                if self.person: 
    7375                    personName = self.person.name 
     
    8587 
    8688    def logAccessAttempt(self, person, actionName, protectedObject): 
    87         if self.debug: 
     89        if moddebug and self.debug: 
    8890            if person: 
    8991                personName = person.name 
     
    130132    def isRoleAuthorised(self, role): 
    131133        if self.isPermissionGranted(role.grants): 
    132             if self.debug: 
     134            if moddebug and self.debug: 
    133135                msg = "Access authorised by '%s' associated role." % ( 
    134136                    role.name 
     
    137139            return True 
    138140        else: 
    139             if self.debug: 
     141            if moddebug and self.debug: 
    140142                msg = "Access not authorised by '%s' associated role." % ( 
    141143                    role.name 
     
    203205    def isPersonBarred(self): 
    204206        if self.isPermissionGranted(self.person.bars): 
    205             if self.debug: 
     207            if moddebug and self.debug: 
    206208                msg = "Access personally barred." 
    207209                self.logger.debug(msg) 
    208210            return True 
    209211        else: 
    210             if self.debug: 
     212            if moddebug and self.debug: 
    211213                msg = "Access not personally barred." 
    212214                self.logger.debug(msg) 
     
    215217    def isVisitorBarred(self): 
    216218        if self.isPermissionGranted(self.getVisitor().bars): 
    217             if self.debug: 
     219            if moddebug and self.debug: 
    218220                msg = "Access barred to visitor." 
    219221                self.logger.debug(msg) 
    220222            return True 
    221223        else: 
    222             if self.debug: 
     224            if moddebug and self.debug: 
    223225                msg = "Access not barred to visitor." 
    224226                self.logger.debug(msg) 
     
    227229    def isPersonAuthorisedPersonally(self): 
    228230        if self.isPermissionGranted(self.person.grants): 
    229             if self.debug: 
     231            if moddebug and self.debug: 
    230232                msg = "Access authorised by personal role." 
    231233                self.logger.debug(msg) 
    232234            return True 
    233235        else: 
    234             if self.debug: 
     236            if moddebug and self.debug: 
    235237                msg = "Access not authorised by personal role." 
    236238                self.logger.debug(msg) 
     
    239241    def isVisitorAuthorisedPersonally(self): 
    240242        if self.isPermissionGranted(self.getVisitor().grants): 
    241             if self.debug: 
     243            if moddebug and self.debug: 
    242244                msg = "Access authorised by visitor personal role." 
    243245                self.logger.debug(msg) 
    244246            return True 
    245247        else: 
    246             if self.debug: 
     248            if moddebug and self.debug: 
    247249                msg = "Access not authorised by visitor personal role." 
    248250                self.logger.debug(msg) 
     
    253255        roleName = getattr(systemRole, 'name', '') 
    254256        if self.isPermissionGranted(systemRole.grants): 
    255             if self.debug: 
     257            if moddebug and self.debug: 
    256258                msg = "Access authorised by '%s' system role." % roleName 
    257259                self.logger.debug(msg) 
    258260            return True 
    259261        else: 
    260             if self.debug: 
     262            if moddebug and self.debug: 
    261263                msg = "Access not authorised by '%s' system role." % roleName 
    262264                self.logger.debug(msg) 
     
    266268        systemRole = self.getVisitorSystemRole() 
    267269        if self.isPermissionGranted(systemRole.grants): 
    268             if self.debug: 
     270            if moddebug and self.debug: 
    269271                msg = "Access authorised by visitor's system role." 
    270272                self.logger.debug(msg) 
    271273            return True 
    272274        else: 
    273             if self.debug: 
     275            if moddebug and self.debug: 
    274276                msg = "Access not authorised by visitor's system role." 
    275277                self.logger.debug(msg) 
  • trunk/src/dm/application.py

    r296 r308  
    11from dm.ioc import * 
    22from dm.builder import ApplicationBuilder 
    3 from dm.testunit import ApplicationBuilder 
    43 
    54class Application(object): 
  • trunk/src/dm/applicationtest.py

    r2 r308  
    22from dm.ioc import * 
    33import unittest 
    4  
    5 features.allowReplace = True 
    64 
    75def suite(): 
  • trunk/src/dm/db.py

    r307 r308  
    416416        return style.pythonAttrToDBColumn(naiveName) 
    417417 
    418     def makeSafeDbName(self, naiveName): 
    419         if naiveName.upper() in self.getReservedNames(): 
    420             naiveName = 'x' + naiveName 
    421             return self.makeSafeDbName(naiveName) 
    422         else: 
    423             return naiveName 
     418    def makeSafeDbName(self, name): 
     419        if name.upper() in self.getReservedNames(): 
     420            name = 'x' + name 
     421            if name != self.makeSafeDbName(name): 
     422                raise Exception, "Can't make this name safe: %s" % name 
     423        return name 
    424424 
    425425    def getReservedNames(self): 
     
    840840                            recordedLen = len(recordedList) 
    841841                            actualLen = len(actualList) 
    842                             print "Checking association list values for changes..." 
    843                             print "Recorded: %s, actual: %s)...." % (recordedLen, actualLen) 
     842                            #print "Checking association list values for changes..." 
     843                            #print "Recorded: %s, actual: %s)...." % (recordedLen, actualLen) 
    844844                            if recordedLen == actualLen: 
    845845                                for i in recordedList: 
    846846                                    if i.recordedValue not in actualList: 
    847                                         print "Missing item: %s" % i.recordedValue 
     847                                        #print "Missing item: %s" % i.recordedValue 
    848848                                        isChangedTemporal = True 
    849849                                        break 
    850                                     else: 
    851                                         print "Found item in record: %s" % i.recordedValue 
     850                                    #else: 
     851                                    #    print "Found item in record: %s" % i.recordedValue 
    852852                                if isChangedTemporal: 
    853853                                    break 
    854854                            else: 
    855                                 print "Length mismatch!" 
     855                                #print "Length mismatch!" 
    856856                                isChangedTemporal = True 
    857857                                break 
     
    864864                                break 
    865865            if isChangedTemporal: 
    866                 print "Is changed!!!!!!! Creating new current version of associate list." 
     866                #print "Is changed!!!!!!! Creating new current version of associate list." 
    867867                loadedList = {self.domainObject: self.domainObject} 
    868868                history = self.domainObject.temporalHistory 
     
    878878                        recordedLen = len(recordedList) 
    879879                        actualLen = len(actualList) 
    880                         print "Checking association list values for changes..." 
    881                         print "Recorded: %s, actual: %s)...." % (recordedLen, actualLen) 
     880                        #print "Checking association list values for changes..." 
     881                        #print "Recorded: %s, actual: %s)...." % (recordedLen, actualLen) 
    882882                        if recordedLen == actualLen: 
    883883                            for i in recordedList: 
    884884                                if i.recordedValue not in actualList: 
    885                                     print "Missing item: %s" % i.recordedValue 
     885                                    #print "Missing item: %s" % i.recordedValue 
    886886                                    isListChanged = True 
    887887                                    break 
    888                                 else: 
    889                                     print "Found item in record: %s" % i.recordedValue 
     888                                #else: 
     889                                #    print "Found item in record: %s" % i.recordedValue 
    890890                        else: 
    891                             print "Length mismatch!" 
     891                            #print "Length mismatch!" 
    892892                            isListChanged = True 
    893893     
    894894                        if isListChanged: 
    895                             print "List is changed...." 
     895                            #print "List is changed...." 
    896896                            for item in actualRegister: 
    897                                 print "Adding list item to temporal record: %s" % item 
     897                                #print "Adding list item to temporal record: %s" % item 
    898898                                key = actualRegister.getRegisterKey(item) 
    899899                                try: 
     
    902902                                        recordedKey=key 
    903903                                    ) 
    904                                     print "Created: %s" % listItem 
     904                                    #print "Created: %s" % listItem 
    905905 
    906906                                except TypeError, inst: 
    907907                                    msg = "Couldn't add item %s with key %s to temporal associate list register %s: %s" % (item, key, recordedRegister, inst) 
    908                                     print msg 
     908                                    #print msg 
    909909                                    raise Exception, msg 
    910                                 print "Recorded register now: %s" % [i for i in recordedRegister] 
     910                                #print "Recorded register now: %s" % [i for i in recordedRegister] 
    911911 
    912912        for metaAttr in self.meta.attributes: 
  • trunk/src/dm/dictionary.py

    r237 r308  
    2525        self.initTimezone() 
    2626        self.validateDictionaryWords() 
     27        self.assertWebkitEnvironment() 
    2728 
    2829    def assertSystemName(self): 
     
    3132         
    3233    def assertSystemEnvironment(self): 
    33         self.environment.assertDjangoSettingsModule() 
     34        pass 
     35 
     36    def assertWebkitEnvironment(self): 
     37        if self[WEBKIT_NAME] == 'django': 
     38            self.environment.assertDjangoSettingsModule() 
    3439         
    3540    def setDefaultWords(self): 
     
    6267        self[DJANGO_SECRET_KEY]   = 'f*(d3d45zetsb3)$&2h5@lua()yc+kfn4w^dmrf_j1i(6jjkq' 
    6368        self[EDITOR]              = 'editor' 
     69        self[WEBKIT_NAME]         = 'django' 
    6470 
    6571    def makeConfigFilePath(self): 
  • trunk/src/dm/dictionarywords.py

    r252 r308  
    4141WWW_PORT = 'www.port' 
    4242IMAGES_DIR_PATH = 'images_dir' 
     43WEBKIT_NAME = 'webkit_name' 
    4344DJANGO_SECRET_KEY = 'django.secret_key' 
    4445DJANGO_TEMPLATES_DIR = 'django.templates_dir' 
     46PYLONS_SECRET_KEY = 'pylons.secret_key' 
     47PYLONS_TEMPLATES_DIR = 'pylons.templates_dir' 
    4548EDITOR = 'editor' 
  • trunk/src/dm/djangotest.py

    r176 r308  
    44 
    55def suite(): 
    6     "Return a TestSuite of dm.db TestCases." 
    76    suites = [ 
    87        dm.django.settingstest.suite(), 
  • trunk/src/dm/dom/meta.py

    r307 r308  
    715715        return self.owner.temporalHistory.getCurrent() 
    716716 
     717 
    717718class AssociateList(DomainObjectAssociation): 
    718719    "Models aquaintance with several domain objects." 
  • trunk/src/dm/dom/registry.py

    r306 r308  
    2222 
    2323    def registerDomainClass(self, domainClass): 
     24        self.log.debug("Registering domain class: %s" % domainClass) 
    2425        baseClass = DomainObject 
    2526        if not issubclass(domainClass, baseClass): 
     
    2728        domainClassName = domainClass.__name__ 
    2829        classRegister = self.getDomainClassRegister() 
     30        #if domainClassName == 'TemporalObjectExampleHist_grants': 
     31        #    raise domainClassName 
    2932        if domainClassName in classRegister: 
     33            existingClass = classRegister[domainClassName] 
    3034            if features.allowReplace: 
    3135                return 
    32             msg = "Domain class '%s' is already defined." % domainClassName 
     36            msg = "Domain class '%s' is already defined: %s" % ( 
     37                domainClassName, existingClass 
     38            ) 
    3339            raise Exception, msg  
    3440 
     
    110116                    'temporalListClassName': temporalListClassName, 
    111117                }) 
    112                 self.generateTemporalAssociateListClass( 
    113                     temporalMeta, metaAttr, temporalListClassName 
    114                
     118                #self.generateTemporalAssociateListClass( 
     119                #    temporalMeta, metaAttr, temporalListClassName 
     120                #
    115121                newAttr = AggregatesMany(temporalListClassName,'id','parent') 
    116122            else: 
  • trunk/src/dm/dom/session.py

    r68 r308  
    55import sys 
    66import mx.DateTime 
     7from dm.dictionarywords import WEBKIT_NAME 
     8from dm.dictionarywords import DJANGO_SECRET_KEY 
     9from dm.dictionarywords import PYLONS_SECRET_KEY 
     10from dm.exceptions import WebkitError 
    711 
    812class Session(SimpleDatedObject): 
     
    2327    def createKey(self): 
    2428        "Returns new session key." 
    25         secretKey = self.dictionary['django.secret_key']  
     29        webkitName = self.dictionary[WEBKIT_NAME] 
     30        if webkitName == 'django': 
     31            secretKey = self.dictionary[DJANGO_SECRET_KEY]  
     32        elif webkitName == 'pylons': 
     33            secretKey = self.dictionary[PYLONS_SECRET_KEY]  
     34        else: 
     35            secretKey = 'soso'  
    2636        randomStr = str(random.randint(0, sys.maxint - 1)) + secretKey 
    2737        return md5.new(randomStr).hexdigest() 
  • trunk/src/dm/exceptions.py

    r236 r308  
    1616 
    1717class MissingPluginSystem(DomainModelApplicationError): pass 
     18 
     19class WebkitError(DomainModelApplicationError): pass 
    1820 
    1921# todo: Rework the KForge exception classes. 
  • trunk/src/dm/logtest.py

    r12 r308  
    3232    def testLogWarning(self): 
    3333        self.log.warning('Warning logging test. Please ignore this message.') 
    34      
    35     def testLogError(self): 
    36         self.log.error('Error logging test. Please ignore this message.') 
    37      
    38     def testLogCritical(self): 
    39         self.log.critical('Critical logging test. Please ignore this message.') 
    4034 
     35# Todo: Fixup not printing log to STDOUT during the tests. 
     36#    def testLogError(self): 
     37#        self.log.error('Error logging test. Please ignore this message.') 
     38#     
     39#    def testLogCritical(self): 
     40#        self.log.critical('Critical logging test. Please ignore this message.') 
     41 
  • trunk/src/dm/migrate.py

    r306 r308  
    2727            classData = {} 
    2828            domainClass = domainClassRegister[className] 
    29             print "Dumping register %s" % className 
     29            #print "Dumping register %s" % className 
    3030            # Dumping class meta data 
    3131            metaClassData = {} 
     
    151151        self.idMap = {} 
    152152        for className in self.importOrder: 
    153             print "Importing %s objects." % className 
     153            #print "Importing %s objects." % className 
    154154            domainClass = self.registry.getDomainClass(className) 
    155155            classRegister = domainClass.createRegister() 
     
    167167            classDataKeys.remove('metaData') 
    168168            classDataKeys.sort() 
    169             print "Iterating over %s %s" % (className, classDataKeys) 
     169            #print "Iterating over %s %s" % (className, classDataKeys) 
    170170            for objectId in classDataKeys: 
    171171                #if objectId == 'metaData': 
     
    176176                    className, objectId, objectData 
    177177                ) 
    178                 print msg 
     178                #print msg 
    179179                strObjectData = {} 
    180180                for attr in domainClass.meta.attributes: 
     
    198198                                        mappedValue, 
    199199                                    ) 
    200                                     print msg 
     200                                    #print msg 
    201201                                    value = mappedValue 
    202202                            if value.__class__ == unicode: 
     
    213213                        if not domainObject: 
    214214                            raise Exception("Manipulator has no domain object.") 
    215                         print "Created %s" % domainObject 
     215                        #print "Created %s" % domainObject 
    216216                        if domainObject.id > objectId: 
    217217                            msg = "Index id %s is ahead of import id %s." % ( 
    218218                                domainObject.id, objectId 
    219219                            ) 
    220                             print "Warning: %s" % msg 
     220                            #print "Warning: %s" % msg 
    221221                            raise Exception, msg 
    222222                            behindWithId = False 
     
    225225                                domainObject.id 
    226226                            ) 
    227                             print msg 
     227                            #print msg 
    228228                            domainObject.delete() 
    229                             print "  -- deleted" 
     229                            #print "  -- deleted" 
    230230                            if hasattr(domainObject, 'purge'): 
    231231                                domainObject.purge() 
    232                                 print "  -- purged" 
     232                                #print "  -- purged" 
    233233                        elif domainObject.id == objectId: 
    234234                            #print "Perfect ID match!" 
     
    238238                            className, strObjectData, inst 
    239239                        ) 
    240                         print '' 
    241                         print msg 
    242                         print '' 
     240                        #print '' 
     241                        #print msg 
     242                        #print '' 
    243243                        raise 
    244244                         
     
    251251                    className, objectId 
    252252                ) 
    253                 print msg 
    254             print "Importing %s objects completed OK." % className 
    255         print "Imported all domain objects records OK." 
     253                #print msg 
     254            #print "Importing %s objects completed OK." % className 
     255        #print "Imported all domain objects records OK." 
    256256 
    257257 
  • trunk/src/dm/test.py

    r296 r308  
    1616import dm.accesscontroltest 
    1717import dm.applicationtest 
     18import dm.migratetest 
    1819import dm.viewtest 
    1920import dm.djangotest 
    20 import dm.migratetest 
     21import dm.pylonstest 
    2122from dm.testunit import ApplicationTestSuite 
    2223 
     
    3738        dm.dictionarytest.suite(), 
    3839        dm.commandtest.suite(), 
    39         #dm.filesystemtest.suite(), 
    4040        dm.accesscontroltest.suite(), 
    4141        dm.viewtest.suite(), 
    42         dm.applicationtest.suite(), 
     42        dm.migratetest.suite(), 
    4343        dm.djangotest.suite(), 
    44         dm.migratetest.suite(), 
     44        dm.pylonstest.suite(), 
     45        #dm.filesystemtest.suite(), 
     46        #dm.applicationtest.suite(), 
    4547    ] 
    4648    return ApplicationTestSuite(suites) 
  • trunk/src/dm/testunit.py

    r305 r308  
    77 
    88import unittest 
    9 import dm.builder 
    109from dm.ioc import * 
    11 import dm.dom.builder 
    12  
    13 features.allowReplace = True 
     10from dm.dom.builder import ModelBuilder 
     11from dm.builder import ApplicationBuilder 
     12from dm.application import Application 
     13from dm.dictionary import SystemDictionary 
     14from dm.dictionarywords import WEBKIT_NAME 
    1415 
    1516 
     
    1819 
    1920 
    20 class ModelBuilder(dm.dom.builder.ModelBuilder): 
     21class DevModelBuilder(ModelBuilder): 
    2122 
    2223    def construct(self): 
    23         super(ModelBuilder, self).construct() 
     24        super(DevModelBuilder, self).construct() 
    2425        self.loadTemporal() 
    2526 
    2627    def loadTemporal(self): 
    2728        from dm.dom.temporaltest import Temporal 
     29        from dm.dom.temporaltest import TemporalObjectExampleGrant 
     30        from dm.dom.temporaltest import TemporalObjectExample 
     31        from dm.dom.temporal import TemporalProperty, BitemporalProperty, BitemporalActual 
    2832        self.registry.registerDomainClass(Temporal) 
    29         from dm.dom.temporaltest import TemporalObjectExampleGrant 
    3033        self.registry.registerDomainClass(TemporalObjectExampleGrant) 
    31         from dm.dom.temporaltest import TemporalObjectExample 
    3234        self.registry.registerDomainClass(TemporalObjectExample) 
    3335        self.registry.temporals = Temporal.createRegister() 
    34         from dm.dom.temporal import TemporalProperty, BitemporalProperty, BitemporalActual 
    3536        self.registry.registerDomainClass(TemporalProperty) 
    3637        self.registry.registerDomainClass(BitemporalProperty) 
     
    3839 
    3940 
    40 class ApplicationBuilder(dm.builder.ApplicationBuilder): 
     41class DevSystemDictionary(SystemDictionary): 
     42 
     43    def setDefaultWords(self): 
     44        super(DevSystemDictionary, self).setDefaultWords() 
     45        #self[WEBKIT_NAME] = 'pylons' 
     46 
     47 
     48class DevApplicationBuilder(ApplicationBuilder): 
    4149 
    4250    def findModelBuilder(self): 
    43         return ModelBuilder() 
     51        return DevModelBuilder() 
     52 
     53    def findSystemDictionary(self): 
     54        return DevSystemDictionary() 
     55 
     56 
     57class DevApplication(Application): 
     58 
     59    builderClass = DevApplicationBuilder 
    4460 
    4561 
    4662class ApplicationTestSuite(unittest.TestSuite): 
    4763 
    48     appBuilderClass = ApplicationBuilder 
     64    #appBuilderClass = DevApplicationBuilder 
    4965 
    50     def buildApplication(self): 
    51         appBuilder = self.appBuilderClass() 
    52         appBuilder.construct() 
    53         registry = RequiredFeature('DomainRegistry') 
    54         if registry != None: 
    55             domBuilder = RequiredFeature('ModelBuilder') 
    56             domBuilder.construct() 
     66    def assertDevMode(self): 
    5767        dictionary = RequiredFeature('SystemDictionary') 
    5868        if dictionary != None: 
     
    6373                raise SystemModeError("The system was built in '%s' mode. The system must be built in '%s' mode for the test suite to be run. Please check the 'system_mode' setting in your configuration file '%s' and rebuild the database." % (currentSystem.mode, requiredSystemModeName, configFilePath)) 
    6474 
    65     buildApplication = classmethod(buildApplication
     75    assertDevMode = classmethod(assertDevMode
    6676  
    6777 
  • trunk/src/dm/util/datastructure.py

    r204 r308  
    1 from django.utils.datastructures import MultiValueDict 
     1# MultiValueDict borrowed from Django 0.95.1, to avoid deep dependency. 
    22 
     3class MultiValueDictKeyError(KeyError): 
     4    pass 
     5 
     6class MultiValueDict(dict): 
     7    """ 
     8    Dict customized to handle multiple values for the same key. 
     9 
     10    >>> d = MultiValueDict({'name': ['Adrian', 'Simon'], 'position': ['Developer']}) 
     11    >>> d['name'] 
     12    'Simon' 
     13    >>> d.getlist('name') 
     14    ['Adrian', 'Simon'] 
     15    >>> d.get('lastname', 'nonexistent') 
     16    'nonexistent' 
     17    >>> d.setlist('lastname', ['Holovaty', 'Willison']) 
     18 
     19    This class exists to solve the irritating problem raised by cgi.parse_qs, 
     20    which returns a list for every key, even though most Web forms submit 
     21    single name-value pairs. 
     22    """ 
     23    def __init__(self, key_to_list_mapping=()): 
     24        dict.__init__(self, key_to_list_mapping) 
     25 
     26    def __repr__(self): 
     27        return "<MultiValueDict: %s>" % dict.__repr__(self) 
     28 
     29    def __getitem__(self, key): 
     30        """ 
     31        Returns the last data value for this key, or [] if it's an empty list; 
     32        raises KeyError if not found. 
     33        """ 
     34        try: 
     35            list_ = dict.__getitem__(self, key) 
     36        except KeyError: 
     37            raise MultiValueDictKeyError, "Key %r not found in %r" % (key, self) 
     38        try: 
     39            return list_[-1] 
     40        except IndexError: 
     41            return [] 
     42 
     43    def __setitem__(self, key, value): 
     44        dict.__setitem__(self, key, [value]) 
     45 
     46    def __copy__(self): 
     47        return self.__class__(dict.items(self)) 
     48 
     49    def __deepcopy__(self, memo=None): 
     50        import copy 
     51        if memo is None: memo = {} 
     52        result = self.__class__() 
     53        memo[id(self)] = result 
     54        for key, value in dict.items(self): 
     55            dict.__setitem__(result, copy.deepcopy(key, memo), copy.deepcopy(value, memo)) 
     56        return result 
     57 
     58    def get(self, key, default=None): 
     59        "Returns the default value if the requested data doesn't exist" 
     60        try: 
     61            val = self[key] 
     62        except KeyError: 
     63            return default 
     64        if val == []: 
     65            return default 
     66        return val 
     67 
     68    def getlist(self, key): 
     69        "Returns an empty list if the requested data doesn't exist" 
     70        try: 
     71            return dict.__getitem__(self, key) 
     72        except KeyError: 
     73            return [] 
     74 
     75    def setlist(self, key, list_): 
     76        dict.__setitem__(self, key, list_) 
     77 
     78    def setdefault(self, key, default=None): 
     79        if key not in self: 
     80            self[key] = default 
     81        return self[key] 
     82 
     83    def setlistdefault(self, key, default_list=()): 
     84        if key not in self: 
     85            self.setlist(key, default_list) 
     86        return self.getlist(key) 
     87 
     88    def appendlist(self, key, value): 
     89        "Appends an item to the internal list associated with key" 
     90        self.setlistdefault(key, []) 
     91        dict.__setitem__(self, key, self.getlist(key) + [value]) 
     92 
     93    def items(self): 
     94        """ 
     95        Returns a list of (key, value) pairs, where value is the last item in 
     96        the list associated with the key. 
     97        """ 
     98        return [(key, self[key]) for key in self.keys()] 
     99 
     100    def lists(self): 
     101        "Returns a list of (key, list) pairs." 
     102        return dict.items(self) 
     103 
     104    def values(self): 
     105        "Returns a list of the last value on every key list." 
     106        return [self[key] for key in self.keys()] 
     107 
     108    def copy(self): 
     109        "Returns a copy of this object." 
     110        return self.__deepcopy__() 
     111 
     112    def update(self, other_dict): 
     113        "update() extends rather than replaces existing key lists." 
     114        if isinstance(other_dict, MultiValueDict): 
     115            for key, value_list in other_dict.lists(): 
     116                self.setlistdefault(key, []).extend(value_list) 
     117        else: 
     118            try: 
     119                for key, value in other_dict.items(): 
     120                    self.setlistdefault(key, []).append(value) 
     121            except TypeError: 
     122                raise ValueError, "MultiValueDict.update() takes either a MultiValueDict or dictionary" 
     123 
  • trunk/src/dm/util/html.py

    r204 r308  
    1 from django.utils.html import escape 
    21 
  • trunk/src/dm/util/http.py

    r204 r308  
    1 from django.http import HttpRequest 
    2 from django.http import HttpResponse 
    3 from django.http import HttpResponseRedirect 
  • trunk/src/dm/util/manipulator.py

    r204 r308  
    1 from django import forms 
    2 from django.core import validators 
  • trunk/src/dm/util/template.py

    r204 r308  
    1 from django.template import Context 
    2 from django.core import template_loader 
    31 
  • trunk/src/dm/view/base.py

    r289 r308  
    1010from dm.strategy import ValidateCookieString 
    1111from dm.util.datastructure import MultiValueDict 
    12 from dm.util.http import HttpResponse 
    13 from dm.util.http import HttpResponseRedirect 
    14 from dm.util.template import Context 
    15 from dm.uti