[Zope] ZODB/PersistentMapping problem

Paul Stevens paul@nfg.nl
16 Dec 1999 12:38:12 +0100


Hi all,

I've been experimenting with the ZODB and Persistence modules
following the ZODB-Howto.

Using the example code I've seem to have encountered a problem in
PersistentMapping.py:

PersistentMapping.keys() does, apparently not support int keys:

    def keys(self):
        try: return self._v_keys
        except: pass
        keys=self._v_keys=filter(
            lambda k: k[:1]!='_',
            self._container.keys())
        keys.sort()
        return keys

will cause

Traceback (innermost last):
  File "./hello.py", line 73, in ?
    myapp.testread()
  File "./hello.py", line 67, in testread
    print self.root.keys()
  File "/usr/lib/zope/lib/python/ZODB/PersistentMapping.py", line 142, in keys
    self._container.keys())
  File "/usr/lib/zope/lib/python/ZODB/PersistentMapping.py", line 140, in <lambda>
    lambda k: k[:1]!='_',
TypeError: unsliceable object

when using int keys. Is this a bug or a feature ?? Using instead:

    def keys(self):
        try: return self._v_keys
        except: pass
        keys=self._v_keys=filter(
#            lambda k: k[:1]!='_',
            lambda k: str(k)[:1]!='_',
            self._container.keys())
        keys.sort()
        return keys

appears to do the job. But I cannot predict unforeseen consequences
from this hack.


------------------------------- hello.py --------------------------------------
#!/usr/bin/python

import Persistence
import ZODB
import ZODB.FileStorage

class Person(Persistence.Persistent,Persistence.PersistentMapping):
    def __init__(self,name='',age=''):
	self.name = name
	self.age = age

    def __repr__(self):
	return """Person(name='%s',age='%s')""" % ( self.name, self.age )

class MySimpleZODBApp:
    """ A simple application object that manages persistent
    object's of the 'Person' class. """

    def __init__(self, file='Data.fs'):
	""" Create a database, connect to it and get the root
	object out of it.  """

	self.db = ZODB.DB(ZODB.FileStorage.FileStorage(file))
	self.connection = self.db.open()
	self.root = self.connection.root()
	self.root.clear()
	if not len(self.root):
	    self.root['billy'] = Person('Billy', 77)

	    # normally Zope will handle transactions,
	    # but in this special case, we need to 
	    # commit the transaction to save the new
	    # persistent object
	    print "get_transaction"
	    get_transaction().commit()


    def addPerson(self, name, age):
	""" Adds a 'Person' to the database """
	if self.root.has_key(name):
	    raise 'PersonAllReadyExists', "They're allready there"
	else:
	    self.root[name] = Person(name, age)
	    get_transaction().commit()

    def delPerson(self, name):
	""" Deletes a 'Person' from the database """
	if self.root.has_key(name):
	    del self.root[name]
	    get_transaction().commit()
	else:
	    raise 'NoSuchPerson', 'Who?'

    def testwrite(self):
	"""lots of silly objects"""
	for x in range(1000):
	    if not (x % 100):
		# every 100 items
		# commit a sub transaction
		get_transaction().commit(1)
	    self.root[x] = Person(str(x), x)
	    # commit all sub-transactions just like normal
	    # sub transactions
	get_transaction().commit()

    def testread(self):
	print self.root.keys()
	print self.root['billy']

if __name__ == '__main__':
    myapp = MySimpleZODBApp()
    myapp.testwrite()
    myapp.testread()

-- 
  ________________________________________________________________
  Paul Stevens                                  mailto:paul@nfg.nl
  NET FACILITIES GROUP                     PGP: finger paul@nfg.nl
  The Netherlands________________________________http://www.nfg.nl