Mailing List Archive

Pythonwin and Office 2000
I believe that Pythonwin is not compatible with Office 2000. Here are some
symptoms:

D:\Program Files\PYTHON\WIN32COM\TEST>python testMSOffice.py

Starting Word 8 for dynamic test
Starting Word 8 for non-lazy dynamic test
Starting MSWord for generated test
Traceback (innermost last):
File "testMSOffice.py", line 143, in TestAll
TestWord()
File "testMSOffice.py", line 46, in TestWord
if gencache.EnsureModule("{00020905-0000-0000-C000-000000000046}",
1033, 8,
0) is None:
File "D:\Program Files\Python\win32com\client\gencache.py", line 226, in
Ensur
eModule
tlbAttr = pythoncom.LoadRegTypeLib(typelibCLSID, major, minor,
lcid).GetLibA
ttr()
com_error: (-2147319779, 'Library not registered.', None, None)


>>> a=win32com.client.Dispatch("MSWord.Application")
Traceback (innermost last):
File "<interactive input>", line 1, in ?
File "D:\Program Files\Python\win32com\client\__init__.py", line 13, in
Dispatch
dispatch, userName =
dynamic._GetGoodDispatchAndUserName(dispatch,userName,clsctx)
File "D:\Program Files\Python\win32com\client\dynamic.py", line 67, in
_GetGoodDispatchAndUserName
return (_GetGoodDispatch(IDispatch, clsctx), userName)
File "D:\Program Files\Python\win32com\client\dynamic.py", line 58, in
_GetGoodDispatch
IDispatch = pythoncom.CoCreateInstance(IDispatch, None, clsctx,
pythoncom.IID_IDispatch)
com_error: (-2147221005, 'Invalid class string', None, None)




File "..\..\slides\slidesppvisitor.py", line 4, in ?
ppmod = win32com.client.gencache.GetModuleForProgID(
"PowerPoint.Application" )
File "D:\Program Files\Python\win32com\client\gencache.py", line 134, in
GetModuleForProgID
return GetModuleForCLSID(iid)
File "D:\Program Files\Python\win32com\client\gencache.py", line 152, in
GetModuleForCLSID
return GetModuleForTypelib(typelibCLSID, lcid, major, minor)
File "D:\Program Files\Python\win32com\client\gencache.py", line 167, in
GetModuleForTypelib
return _GetModule(modName)
File "D:\Program Files\Python\win32com\client\gencache.py", line 328, in
_GetModule
mod = __import__("win32com.gen_py.%s" % fname)
File "D:\Program
Files\Python\win32com\gen_py\91493440-5A91-11CF-8700-00AA0060263Bx0x2x14.py",
line 4549
def AddOLEObject(self, Left=0.0, Top=0.0, Width=-1.0, Height=-1.0,
ClassName
=L'', FileName=L'', DisplayAsIcon=0, IconFileName=L'', IconIndex=0,
IconLabel=L'
', Link=0):

Is this "L" syntax a future syntax for Unicode that Python 1.5.2 doesn't
support? Perhaps PythonWin should test for support for that syntax before
it generates the Python code?

--
Paul Prescod - ISOGEN Consulting Engineer speaking for only himself
http://itrc.uwaterloo.ca/~papresco

Perhaps the war in Kosovo would get more press if it were directed by
George Lucas.
Pythonwin and Office 2000 [ In reply to ]
Paul Prescod wrote in message <377648A7.9B9BE59F@prescod.net>...
>I believe that Pythonwin is not compatible with Office 2000. Here are some
>symptoms:

I havent tried this, although I believe it!

> File "testMSOffice.py", line 46, in TestWord
> if gencache.EnsureModule("{00020905-0000-0000-C000-000000000046}",
>1033, 8,
>0) is None:

This is expected (unfortunately). Word will have a new typelibrary, and
hence a new IID for the library. The "fix" will be to work out what the
library ID of the new one is (by using "makepy -i") and changing TestWord.py
to gracefully allow either version.

However, this is a PITA in general, and a less-clunky solution would be
great!

>>>> a=win32com.client.Dispatch("MSWord.Application")
...
>com_error: (-2147221005, 'Invalid class string', None, None)

That is a strange one :-(

> def AddOLEObject(self, Left=0.0, Top=0.0, Width=-1.0, Height=-1.0,
>ClassName
>=L'', FileName=L'', DisplayAsIcon=0, IconFileName=L'', IconIndex=0,
>IconLabel=L'
>', Link=0):
>
>Is this "L" syntax a future syntax for Unicode that Python 1.5.2 doesn't
>support? Perhaps PythonWin should test for support for that syntax before
>it generates the Python code?

Eeeek. I have no idea where that is coming from. I havent added special
Unicode features anywhere. This _is_ a strange one!

I hope to install Office2000 and IE5 soon, but until then Im not sure I can
do much :-(

Mark.
Pythonwin and Office 2000 [ In reply to ]
> From: Mark Hammond [mailto:MHammond@skippinet.com.au]
>
>
> Paul Prescod wrote in message <377648A7.9B9BE59F@prescod.net>...
> >I believe that Pythonwin is not compatible with Office 2000.
> Here are some
> >symptoms:
>

Heh, now there's a vague statement...
My Python COM code is talking to Excel 2k quite happily, although I don't
generate the .py wrapper, those things are just too big, and take too long
to initially create on other peoples machines.

> I havent tried this, although I believe it!
>
> > File "testMSOffice.py", line 46, in TestWord
> > if
> gencache.EnsureModule("{00020905-0000-0000-C000-000000000046}",
> >1033, 8,
> >0) is None:
>
> This is expected (unfortunately). Word will have a new
> typelibrary, and
> hence a new IID for the library. The "fix" will be to work
> out what the
> library ID of the new one is (by using "makepy -i") and
> changing TestWord.py
> to gracefully allow either version.
>

Actually, the GUID hasn't changed. Its just has a version of 8.1 instead of
8.0.

> However, this is a PITA in general, and a less-clunky
> solution would be
> great!
>

You're the one who required the version number. :)

> >>>> a=win32com.client.Dispatch("MSWord.Application")
> ...
> >com_error: (-2147221005, 'Invalid class string', None, None)
>
> That is a strange one :-(

Err. I think thats the "can't find ProgID" error message.
The progID is "Word.Application" unless something else wierd is going on. :)

Bill
Pythonwin and Office 2000 [ In reply to ]
Mark Hammond wrote:
>
> Paul Prescod wrote in message <377648A7.9B9BE59F@prescod.net>...
> >I believe that Pythonwin is not compatible with Office 2000. Here are some
> >symptoms:
>
> I havent tried this, although I believe it!

Well, I got it to work eventually. I used the command line makepy instead
of the one in the GUI. It didn't test the result before it registered it
in the .dat file. Then I edited the file by hand to remove the upper-case
"L" characters.

> This is expected (unfortunately). Word will have a new typelibrary, and
> hence a new IID for the library. The "fix" will be to work out what the
> library ID of the new one is (by using "makepy -i") and changing TestWord.py
> to gracefully allow either version.

>>> from win32com.client import gencache
>>> gencache.EnsureModule('{91493440-5A91-11CF-8700-00AA0060263B}', 0, 2,
14)

Is there an equivalent to EnsureModule that works from the textual library
name? I know that the textual library name still changes from version to
version but I don't think it is Pythonish (easy, clean and readable) to
put UUIDs in code at all.

In fact, the most Pythonish way would be to do what Python does with
Pyc's. When Pythonwin does a win32com.client.Dispatch, it could generate
the gencache module if possible. If not possible then no problem, it just
works in the dynamic mode.

Also, is there any chance of having win32com.client.Dispatch renamed
CreateObject() for JavaScript and VBScript compatibility?

> > def AddOLEObject(self, Left=0.0, Top=0.0, Width=-1.0, Height=-1.0,
> >ClassName
> >=L'', FileName=L'', DisplayAsIcon=0, IconFileName=L'', IconIndex=0,
> >IconLabel=L'
> >', Link=0):

Once I deleted that strange "L" thing, the generated module worked.

In case it helps, here is the code:

def AddOLEObject(self, Left=0.0, Top=0.0, Width=-1.0, Height=-1.0,
ClassName=L'', FileName=L'', DisplayAsIcon=0, IconFileName=L'',
IconIndex=0, IconLabel=L'', Link=0):
return self._ApplyTypes_(0x7d8, 1, (9, 32), ((4, 49), (4, 49), (4, 49),
(4, 49), (8, 49), (8, 49), (3, 49), (8, 49), (22, 49), (8, 49), (3, 49)),
'AddOLEObject', '{91493479-5A91-11CF-8700-00AA0060263B}', Left, Top,
Width, Height, ClassName, FileName, DisplayAsIcon, IconFileName,
IconIndex, IconLabel, Link)

...
# Result is of type TextRange
def InsertAfter(self, NewText=L''):
return self._ApplyTypes_(0x7e1, 1, (9, 32), ((8, 49),), 'InsertAfter',
'{9149348F-5A91-11CF-8700-00AA0060263B}', NewText)
...


def Help(self, HelpFile=L'vbappt9.chm', ContextID=0):
return self._ApplyTypes_(0x7e4, 1, (24, 32), ((8, 49), (22, 49)),
'Help', None, HelpFile, ContextID)


--
Paul Prescod - ISOGEN Consulting Engineer speaking for only himself
http://itrc.uwaterloo.ca/~papresco

Those who profess to favor freedom and yet depreciate agitation, are men
who want crops without plowing up the ground. They want rain without
thunder and lightning. They want the ocean without the roar of its many
waters. - Fredrick Douglass
http://www.informamerica.com/Articles/Quotes.htm
Pythonwin and Office 2000 [ In reply to ]
[CC'd from the newsgroup to the python-com developers list]

Paul Prescod wrote in message <3776D1E6.45E1AAF7@prescod.net>...

>Is there an equivalent to EnsureModule that works from the textual library
>name? I know that the textual library name still changes from version to
>version but I don't think it is Pythonish (easy, clean and readable) to
>put UUIDs in code at all.

I agree. Worse, as you found out, it breaks when upgrading the COM object.
However, the only way to do it textually would be to search the registry for
the name. Depending on the system, this can be significant. The IID and
version info give us a direct key into the registry. On my development
system, searching for an IID name could take a few seconds, and (IMO) we
can't afford this hit just to check.

I can't think of a better solution. The Python equivilent to the VB system
would be for the developer of a script to nominate the type libraries they
reference, and to generate the necessary makepy support into a single file.
This single file would then be shipped with the script. (VB puts the
generated code in the same .exe, hiding this extra distribution - in Python
terms, this would be integrating with freeze etc). To go this route would
really require that makepy no longer generate source code, but instead
generate a tight binary format (which may be desirable anyway).

VBScript, for example, does not have the concept - it only understands (in
Python parlance) "dynamic dispatch". Delphi, AFAIK, also makes it a
build-time step, rather than a run-time step.

Anyway, I have thought about this, and could not come up with a decent
solution. The "gencache" implementation was the result - I knew it to be
half-baked, but really couldnt come up with a reasonable solution.

>In fact, the most Pythonish way would be to do what Python does with
>Pyc's. When Pythonwin does a win32com.client.Dispatch, it could generate
>the gencache module if possible. If not possible then no problem, it just
>works in the dynamic mode.

Yes - this could also work. Indeed, we could change the generation so that
instead of doing the whole type library, it only does the classes of
interest. In many respects, you could consider makepy itself a hack that
should be removed once Python can do a better job dynamically.

However, it is worth noting that speed is no longer a good justification for
using makepy. Recent changes to dynamic dispatch mean that we are now
comparable speed wise to VB without makepy support. The reason you often
now need makepy support is to get decent parameter support, but the problem
is worse than that. In many non-trivial cases, the code you write is simply
not compatible between makepy supported and dynamic dispatch. So, if you
want to ensure your code will run when installed, you must _insist_ on
makepy support. (ie, silent failure of makepy is usually not a good option,
as you are simply delaying the inevitable error, but in a less obvious way).

There is plenty of scope to rationalize some of this. As Python COM support
has grown from its humble beginnings, some of the existing code is no longer
appropriate. It is also big and scary enough that fiddling will not have
the desired effect - it needs a good, hard think and a revamp.
Compatibility shouldnt be an issue - there are only about 4 truly public
functions in the whole package - 99% of users will only care that
"win32com.client.Dispatch" does what they expect!

>Also, is there any chance of having win32com.client.Dispatch renamed
>CreateObject() for JavaScript and VBScript compatibility?

This sounds reasonable (well, not rename, but alias). OTOH, maybe we should
reserve this name for the "new world order" - eg, just incase someone _does_
step forward and some of this does get rationalised, there may be
better-but-slightly-different semantics better exposed as CreateObject()
(with Dispatch()" becoming a backwards compatible interface)

Hope this all makes sense... Just incase people hadnt noticed, COM
development is very quite these days. Almost no new activity and only
maintenance type work is being done. This sort of work is unlikely to get
done without a volunteer.

Mark.
Pythonwin and Office 2000 [ In reply to ]
Mark Hammond wrote:
>
> I agree. Worse, as you found out, it breaks when upgrading the COM object.
> However, the only way to do it textually would be to search the registry for
> the name.

Would that be the same speed as .Dispatch("..."), or ar you saying it
would be slower? Anyhow, could we store the mapping from string names to
UUIDs in the gencache directory so that the second time is fast?

> However, it is worth noting that speed is no longer a good justification for
> using makepy. Recent changes to dynamic dispatch mean that we are now
> comparable speed wise to VB without makepy support. The reason you often
> now need makepy support is to get decent parameter support, but the problem
> is worse than that. In many non-trivial cases, the code you write is simply
> not compatible between makepy supported and dynamic dispatch. So, if you
> want to ensure your code will run when installed, you must _insist_ on
> makepy support. (ie, silent failure of makepy is usually not a good option,
> as you are simply delaying the inevitable error, but in a less obvious way).

Okay, I don't understand what stuff works with makepy and what stuff
doesn't. Let's put it this way: if we did everything dynamically the same
stuff VBScript does dynamically would we slow down so much that makepy
would be significantly faster again?

Part of the reason I was using makepy was because I needed access to
constants. How does JScript/VBscript handle this? Do you just have to use
numbers?

Even if makepy is 10 times faster than dynamic dispatch, if code at least
behaved the same with and without it, then we could just try to do the
makepy generation when possible and fallback to dynamic dispatch
otherwise. Savvy programmers could manually force makepy generation if
they really care about speed.

> There is plenty of scope to rationalize some of this. As Python COM support
> has grown from its humble beginnings, some of the existing code is no longer
> appropriate. It is also big and scary enough that fiddling will not have
> the desired effect - it needs a good, hard think and a revamp.
> Compatibility shouldnt be an issue - there are only about 4 truly public
> functions in the whole package - 99% of users will only care that
> "win32com.client.Dispatch" does what they expect!

You're suggesting a volunteer take your big, scary code and improve upon
it? :)

Is this just Python code that needs fixing or a mix of Python and C++?
(i.e. are the C++ primatives you provide enough to build the cool new
Python system on top?)

--
Paul Prescod - ISOGEN Consulting Engineer speaking for only himself
http://itrc.uwaterloo.ca/~papresco

Those who profess to favor freedom and yet depreciate agitation, are men
who want crops without plowing up the ground. They want rain without
thunder and lightning. They want the ocean without the roar of its many
waters. - Fredrick Douglass
http://www.informamerica.com/Articles/Quotes.htm
Pythonwin and Office 2000 [ In reply to ]
"Mark Hammond" <MHammond@skippinet.com.au> wrote:

>[CC'd from the newsgroup to the python-com developers list]
>
>Paul Prescod wrote in message <3776D1E6.45E1AAF7@prescod.net>...
>
>>Is there an equivalent to EnsureModule that works from the textual library
>>name? I know that the textual library name still changes from version to
>>version but I don't think it is Pythonish (easy, clean and readable) to
>>put UUIDs in code at all.
>
>I agree. Worse, as you found out, it breaks when upgrading the COM object.
>However, the only way to do it textually would be to search the registry for
>the name. Depending on the system, this can be significant. The IID and
>version info give us a direct key into the registry. On my development
>system, searching for an IID name could take a few seconds, and (IMO) we
>can't afford this hit just to check.

If you need to ensure that the makepy wrapper is always available, independent
of type library, then I have found the most convenient approach is to copy the
appropriate module out of the genpy directory and import it directly. No UUIDs
in sight, and it works with freeze. This is effectively what Mark describes
below.

makepy should always generate the same wrapper for the same version of each type
library, so you don't lose anything after this initial inconvenience.

In theory, the old wrapper should continue to work after upgrading the com
server. In practice, any uprade involves some risk but this strategy seems to
minimise it.

>I can't think of a better solution. The Python equivilent to the VB system
>would be for the developer of a script to nominate the type libraries they
>reference, and to generate the necessary makepy support into a single file.
>This single file would then be shipped with the script.

(this is possible to hack today, described above)

> (VB puts the
>generated code in the same .exe, hiding this extra distribution - in Python
>terms, this would be integrating with freeze etc). To go this route would
>really require that makepy no longer generate source code, but instead
>generate a tight binary format (which may be desirable anyway).

Why single out the makepy wrapper for this compacting effort? Several other
modules lead to embarrasingle big .pyc and frozen .exe files, but I have never
found this a practical problem.

VB and C++ (and maybe Delphi) gain an advantage from the compile-time approach
since, in combination with static typing, they can optimise into vtbl method
calls. Today, Python is firmly tied to Invoke. We could gain this same
_performance_ advantage by extending makegw to understand type libraries, but
that just changes the problem into having big .dlls. And you also need a
compiler.

(Note: this may be a practical approach if you need to run many python processes
on the one machine; the dll images could be shared between processes. However I
don't see it as a general solution)

>VBScript, for example, does not have the concept - it only understands (in
>Python parlance) "dynamic dispatch". Delphi, AFAIK, also makes it a
>build-time step, rather than a run-time step.
>However, it is worth noting that speed is no longer a good justification for
>using makepy. Recent changes to dynamic dispatch mean that we are now
>comparable speed wise to VB without makepy support.



> The reason you often
>now need makepy support is to get decent parameter support, but the problem
>is worse than that.

Is the parameter support still a continuing problem? I had the impression that
in general only older servers had this problem, with newer servers being much
better behaved?

> In many non-trivial cases, the code you write is simply
>not compatible between makepy supported and dynamic dispatch. So, if you
>want to ensure your code will run when installed, you must _insist_ on
>makepy support. (ie, silent failure of makepy is usually not a good option,
>as you are simply delaying the inevitable error, but in a less obvious way).

Agreed.



Toby Dickenson
Pythonwin and Office 2000 [ In reply to ]
Toby Dickenson wrote in message <377cdaaa.6963555@news.freeserve.net>...

>If you need to ensure that the makepy wrapper is always available,
independent
>of type library, then I have found the most convenient approach is to copy
the
>appropriate module out of the genpy directory and import it directly. No
UUIDs
>in sight, and it works with freeze. This is effectively what Mark describes
>below.

And back to how makepy worked originally. Damn it.

>> (VB puts the
>>generated code in the same .exe, hiding this extra distribution - in
Python
>>terms, this would be integrating with freeze etc). To go this route would
>>really require that makepy no longer generate source code, but instead
>>generate a tight binary format (which may be desirable anyway).
>
>Why single out the makepy wrapper for this compacting effort? Several other
>modules lead to embarrasingle big .pyc and frozen .exe files, but I have
never
>found this a practical problem.
>
>VB and C++ (and maybe Delphi) gain an advantage from the compile-time
approach
>since, in combination with static typing, they can optimise into vtbl
method
>calls. Today, Python is firmly tied to Invoke. We could gain this same

Sure. I wasnt thinking about going that far, simply optimizing the makepy
approach. Eg, rather than generating Python code, it may be better
generating Pythonish datastructures that can be used at runtime. A good
example is the "propMap???" entries for each class. Generating these maps
as Python code is a little pointless.

Im not sure moving to vtables is appropriate for win32com. I think we
should be looking at the COM+ space, and making sure any significant work
like this will tie in with the future.

>> The reason you often
>>now need makepy support is to get decent parameter support, but the
problem
>>is worse than that.
>
>Is the parameter support still a continuing problem? I had the impression
that
>in general only older servers had this problem, with newer servers being
much
>better behaved?

It is a problem mainly with byrefs, and only for those byrefs used on a
dynamic dispatch object that has a type library available, but does not
provide type info at runtime. However, for most well-behaved objects this
should work fine, either for makepy or dynamic dispatch objects.

[.Then we have servers like Notes, that provide 1/2 the information necessary
as a type library, and dont provide _any_ type info at runtime, leaving poor
win32com with a bit of a mess on its hands.]

Mark.
Pythonwin and Office 2000 [ In reply to ]
[.This is getting too esoteric for the newsgroup. I'll continue this on the
pycom-dev@pythonpros.com list]

Paul Prescod wrote in message <3777C93C.F0B5E236@prescod.net>...

>Would that be the same speed as .Dispatch("..."), or ar you saying it
>would be slower? Anyhow, could we store the mapping from string names to
>UUIDs in the gencache directory so that the second time is fast?

Significantly slower. Using Dispatch(), there are 2 indexed lookups in the
registry to locate the object. Using a typelibrary description, there will
need to be a search down "HKCR\Typelib" - have a quick look at this sub-tree
(and the reason for the EnsureModule() params should become more obvious :-)

>
>Okay, I don't understand what stuff works with makepy and what stuff

Neither do I most of the time :-( This often depends on the COM object
itself.

>doesn't. Let's put it this way: if we did everything dynamically the same
>stuff VBScript does dynamically would we slow down so much that makepy
>would be significantly faster again?

If I understand the question, then "No". But again, it depends on the COM
object, and what type information it provides at runtime. Some provide all
info both in a typelib and at runtime. Some provide all info in only one
place or another. Some (like Notes :-) provide half the info in half the
places!

PythonCOM does the worst job without _any_ typeinfo. Then it guesses, and
byref or other complex parameters will be wrong. The level of type info
available determines the likely success.

>Part of the reason I was using makepy was because I needed access to
>constants. How does JScript/VBscript handle this? Do you just have to use
>numbers?

I believe so.

>Even if makepy is 10 times faster than dynamic dispatch, if code at least
>behaved the same with and without it, then we could just try to do the

Yes. But as I mentioned, speed is no longer the driver. The type info and
constants are. And there is no way we can _guarantee_ the same level of
support will be available. Best we can do is get this working for a class
of "nice" servers (where "nice" may be defined as providing all type info
both statically (ie, type library) and as runtime type info. Most MS
servers, and indeed most servers written with VB or ATL, will conform.


>You're suggesting a volunteer take your big, scary code and improve upon
>it? :)
Actually, most of this code did not originate from me (is Curt Hagenlocher
still out there:-) But I have certainly hacked it beyond recognition since
then!


>Is this just Python code that needs fixing or a mix of Python and C++?
>(i.e. are the C++ primatives you provide enough to build the cool new
>Python system on top?)

Just Python. And just in the win32com.client directory.

Mark.