Implementing IPersistStorage using PythonCOM

Edward Blakes eblakes at drwtrading.com
Fri Dec 8 18:15:41 CET 2000


Thanks for responding Mark. I really appreciate your time (as well as your
work with PythonCOM, in the first place). See my comments inline.

"Mark Hammond" <MarkH at ActiveState.com> wrote in message
news:3A307D8C.10909 at ActiveState.com...
> Edward Blakes wrote:
>
> > CATID_PerspectiveAttributeTypeServer = pythoncom.MakeIID("{a guid}")
> > CLSID_PythonSample = pythoncom.MakeIID("{a guid}")
>
> This is probably a problem - it means a new GUID will be created each
> time it is run - definitely not what you want.  Paste generated GUIDs
> directly into the code.
>

My understanding was that this simply converts a string to a PyIID, not
generates a brand new GUID. As you will see below, I directly placed the
string per your suggestion, but to no avail.

> Also - you _really_ should get my book ;-)  The discussion on debugging
> is what you need the most.
>

I have it! That's how I got this far!

> Adding this:
>
I made the changes suggested, got more output but with the same result.
Given your response I believe I clipped important information that, in its
absence, mislead you. So that I won't do that again, I am placing the entire
source here so that you can run it directly. I hate the length but I want
you to have all the information needed.

Begin code.

import struct
import pythoncom
import win32api
import win32ui
from win32com import storagecon
from winerror import S_OK

class DummyAttr:
    SampleProperty = ""

    _public_attrs_ = ["SampleProperty"]
    _public_methods_ = ["DoSomething", "GetClassID", "IsDirty", "InitNew",
"Load", "Save", "SaveCompleted", "HandsOffStorage"]
    _reg_clsid_ =
    _reg_progid_ = "PerspectiveAttribute.PythonSample"
    _reg_catids_ = ["{5A0E5630-78E2-11D2-9D2E-00105A10A8F3}"]
    _com_interfaces_ = [pythoncom.IID_IPersist,
pythoncom.IID_IPersistStorage]

    def __init__(self):
        self.SampleProperty = "This is an initial value"
        win32ui.OutputDebugString("self.SampleProperty = " +
self.SampleProperty + "\n")
    def DoSomething(self):
        import win32ui
        win32ui.MessageBox("Hello from DoSomething", "Message")
    def GetClassID(self):
        return "{D7929F71-133C-4F63-BE0B-BEC0842E7847}"
    def IsDirty(self):
        return 1
    def InitNew(self):
        return S_OK
    def Load(self, pStg):
        try:
            pStream = pStg.OpenStream("ATTRSAVESTREAM",
storagecon.STGM_READ|storagecon.STGM_SHARE_EXCLUSIVE, 0, 0)
            lenData = pStream.Read(struct.calcsize('l'))
            samplePropertyLen = struct.unpack('l', lenData)[0]
            self.SampleProperty = pStream.Read(samplePropertyLen)
            return S_OK
        except:
            win32api.OutputDebugString('Caught exception in
DummyAttr.Load\n')
            pass
    def Save(self, pStg, fSameAsLoad):
        try:
            pStream = pStg.CreateStream("ATTRSAVESTREAM",
storagecon.STGM_READ|storagecon.STGM_SHARE_EXCLUSIVE|storagecon.STGM_CREATE,
0, 0)
            samplePropertyLen = len(self.SampleProperty)
            data = struct.pack('l', samplePropertyLen)
            pStream.Write(data)
            pStream.Write(self.SampleProperty)
            return S_OK
        except:
            win32api.OutputDebugString('Caught exception in
DummyAttr.Save\n')
            pass
    def SaveCompleted(self, pStg):
        return S_OK
    def HandOffStorage(self):
        return S_OK

class LockBytes:
  _public_methods_ = [ 'ReadAt', 'WriteAt', 'Flush', 'SetSize',
'LockRegion', 'UnlockRegion', 'Stat' ]
  _com_interfaces_ = [ pythoncom.IID_ILockBytes ]

  def __init__(self, data = ""):
    import pywintypes
    import time
    self.data = data
    now = pywintypes.Time(time.time())
    self.ctime = now
    self.mtime = now
    self.atime = now

  def ReadAt(self, offset, cb):
    print "ReadAt"
    result = self.data[offset:offset + cb]
    return result

  def WriteAt(self, offset, data):
    print "WriteAt " +str(offset)
    print "len " + str(len(data))
    print "data:"
    #print data
    if len(self.data) >= offset:
      newdata = self.data[0:offset] + data
    print len(newdata)
    if len(self.data) >= offset + len(data):
      newdata = newdata + self.data[offset +  len(data):]
    print len(newdata)
    self.data = newdata
    return len(data)

  def Flush(self, whatsthis=0):
    print "Flush" + str(whatsthis) #+ "Data:" + self.data
    return S_OK

  def SetSize(self, size):
    print "Set Size" + str(size)
    if size > len(self.data):
      self.data = self.data +  "\000" * (size - len(self.data))
    else:
      self.data = self.data[0:size]
    return S_OK

  def LockRegion(self, offset, size, locktype):
    print "LockRegion"
    pass

  def UnlockRegion(self, offset, size, locktype):
    print "UnlockRegion"
    pass

  def Stat(self, statflag):
    print "returning Stat " + str(statflag)
    return (
      "PyMemBytes",
      storagecon.STGTY_LOCKBYTES,
      len(self.data),
      self.mtime,
      self.ctime,
      self.atime,

storagecon.STGM_DIRECT|storagecon.STGM_READWRITE|storagecon.STGM_CREATE ,
      storagecon.STGM_SHARE_EXCLUSIVE,
      "{00020905-0000-0000-C000-000000000046}",
      0,   # statebits ?
      0
      )

def Test():
    import win32com.client
    import win32com.server.util
    import win32com.server.dispatcher

    useDispatcher = win32com.server.dispatcher.DefaultDebugDispatcher

    # Create the server
    origObj = DummyAttr()
    aServer = win32com.server.util.wrap(origObj,
pythoncom.IID_IPersistStorage, useDispatcher=useDispatcher)
    aServerDisp =
win32com.client.dynamic.Dispatch(aServer.QueryInterface(pythoncom.IID_IDispa
tch))

    # Test a server method
    aServerDisp.DoSomething()

    # Test persistence
    aLockBytes = win32com.server.util.wrap(LockBytes(),
pythoncom.IID_ILockBytes, useDispatcher=useDispatcher)
    pStg = pythoncom.StgCreateDocfileOnILockBytes(aLockBytes,
storagecon.STGM_DIRECT|storagecon.STGM_CREATE|storagecon.STGM_READWRITE|stor
agecon.STGM_SHARE_EXCLUSIVE, 0)

    # Show initial property value
    print "SampleProperty = " + aServerDisp.SampleProperty
    aServerDisp.SampleProperty = "1st change"
    print "SampleProperty = " + aServerDisp.SampleProperty

    persistStg = aServer.QueryInterface(pythoncom.IID_IPersistStorage)
    persistStg.Save(pStg, 1)
    origObj.Save(pStg,1)
    aServer.Save(pStg, 1)
    pStg.Commit(storagecon.STGC_DEFAULT)

    aServerDisp.SampleProperty = "2nd change"
    print "SampleProperty = " + aServerDisp.SampleProperty

    persistStg.Load(pStg)
    aServer.Load(pStg)
    print "SampleProperty = " + aServerDisp.SampleProperty

def Register():
    from win32com.server.register import UseCommandLine
    return UseCommandLine(DummyAttr)

if __name__ == '__main__':
    import sys
    if "/test" in sys.argv:
        print "Testing..."
        Test()
    else:
        Register()

When I run the above, I still get the 'member not found' error. While you're
at it, feel free to comment on my use of the struct module. I couldn't
figure out any other way of writing data to streams. Don't know if it will
work b/c of the member problem.

Ed
eblakes at drwtrading.com





More information about the Python-list mailing list