ZODB and COM Server - how to create collection attribute?

Gerhard Kalab kalab at gmx.net
Sun Aug 26 09:38:34 EDT 2001


I'd like to write a COM-Server and use ZODB for persistence.

The following code doesn't work, because the class Person has a
COM-collection (books) which cannot be pickled.
It would be easy to change the books attribute to get and set COM-methods to
get and set the books list. But is it possible to use a COM-attribute?
Is there any way I can change the books list to a list of normal python
objects before it is going to be saved? And can I change it back to a
COM-collection after the list is loaded by ZODB?
Any other ideas?

Thank you,
Gerhard

#server.py
import ZODB, ZODB.FileStorage
import Persistence
import win32com.client
from win32com.server.util import wrap, unwrap

class Book(Persistence.Persistent):
    _public_methods_ = []
    _public_attrs_ = ["title"]
    def __init__(self):
        self.title = ""

class Person(Persistence.Persistent):
    _public_methods_ = ["addBook"]
    _public_attrs_ = ["name", "books"]
    def __init__(self):
        self.name = ""
        self.books = []
    def addBook(self):
        b = Book()
        wrapped = wrap(b)
        self.books.append(wrapped)
        self._p_changed = 1
        return wrapped

class PRoot(Persistence.Persistent):
    def __init__(self):
        self.persons = []
    def addPerson(self):
        p = Person()
        self.persons.append(p)
        self._p_changed = 1
        return wrap(p)

class Root:
    _reg_clsid_ = "{D37DE5DB-EFA6-4135-9B85-250D9F988E35}"
    _reg_desc_ = "Root"
    _reg_progid_ = "Server.Root"
    _public_methods_ = ["setConnection", "addPerson", "save"]
    _public_attrs_ = ["persons"]
    _readonly_attrs_ = ["persons"]
    def __init__(self):
        self.persons = []
    def setConnection(self, storage):
        self.storage = ZODB.FileStorage.FileStorage(storage)
        self.db = ZODB.DB(self.storage)
        self.connection = self.db.open()
        self.root = self.connection.root()
        get_transaction().begin()
        if not self.root.has_key("root"):
            self.rootobj = self
            self.root["root"] = PRoot()
        self.rootobj = self.root["root"]
        for p in self.rootobj.persons:
            self.persons.append(wrap(p))
    def addPerson(self):
        p = self.rootobj.addPerson()
        self.persons.append(p)
        return p
    def __del__(self):
        self.connection.close()
    def save(self):
        get_transaction().commit()

if __name__=='__main__':
    import win32com.server.register
    win32com.server.register.UseCommandLine(Root)

#-----------------

#client.py
from win32com.client import Dispatch
root = Dispatch("Server.Root")
root.setConnection("data.fs")
for name in ["Foo", "Bar"]:
    person = root.addPerson()
    person.name = name
    book = person.addBook()
    book.title = "abc"
persons = root.persons
for person in persons:
    print person.name
    for book in person.books:
        print book.title
root.save() #--> fails





More information about the Python-list mailing list