>> The com object, I am dispatching, is provided by Rhinoceros CAD package. The >> evaluation version of Rhinoceros can be obtained from here - >> http://download.rhino3d.com/rhino/4.0/evaluation/download/ >> . The evaluation is quite liberal, since you can use it as much as you like, >> but you are restricted to 15 saves only. >> >> I am using this object to control VB functions provided by Rhino scripting >> interface. >> >> You can reproduce the problem by: >> >> 1. R = CreateObject("Rhino4.Application") >> 2. RS = R.GetScriptObject >> 3. RS.AddPoint([10.0,10.0,10.0]) >> >> At this point I should obtain all functions provided by RhinoScript type >> library as methods, but all I get are attributes e.g. >> >>>>> RS.AddPoint([10.0,10.0,10.0]) >> Traceback (most recent call last): >> File "<stdin>", line 1, in ? >> TypeError: 'NoneType' object is not callable >> >> , where RS.AddPoint() is the function I am calling. >> >> I presume that all functions in R.GetScriptObject are flagged as attributes >> instead of methods, note that R.visible =True works. In PyWin32 I used to >> flag each attribute as methods with _FlagAsMethod(attribute name) function. >> >> I hope I was able to describe the problem as much as I can. > > Very clear description, and very helpful - thanks. > > This simple patch should do the trick (the docstring is stolen from win32com):
The patch is now in the repository. > > <snip> > Index: comtypes/client/dynamic.py > =================================================================== > --- comtypes/client/dynamic.py (revision 572) > +++ comtypes/client/dynamic.py (working copy) > @@ -58,6 +58,7 @@ > def __init__(self, comobj): > self.__dict__["_comobj"] = comobj > self.__dict__["_ids"] = {} # Tiny optimization: trying not to use > GetIDsOfNames more than once > + self.__dict__["_methods"] = set() > > def __enum(self): > e = self._comobj.Invoke(-4) # DISPID_NEWENUM > @@ -85,7 +86,23 @@ > "QueryInterface is forwarded to the real com object." > return self._comobj.QueryInterface(*args) > > + def _FlagAsMethod(self, *names): > + """Flag these attribute names as being methods. > + Some objects do not correctly differentiate methods and > + properties, leading to problems when calling these methods. > + > + Specifically, trying to say: ob.SomeFunc() > + may yield an exception "None object is not callable" > + In this case, an attempt to fetch the *property*has worked > + and returned None, rather than indicating it is really a method. > + Calling: ob._FlagAsMethod("SomeFunc") > + should then allow this to work. > + """ > + self._methods.update(names) > + > def __getattr__(self, name): > + if name.startswith("__") and name.endswith("__"): > + raise AttributeError(name) > ## tc = > self._comobj.GetTypeInfo(0).QueryInterface(comtypes.typeinfo.ITypeComp) > ## dispid = tc.Bind(name)[1].memid > dispid = self._ids.get(name) > @@ -93,6 +110,11 @@ > dispid = self._comobj.GetIDsOfNames(name)[0] > self._ids[name] = dispid > > + if name in self._methods: > + result = MethodCaller(dispid, self) > + self.__dict__[name] = result > + return result > + > flags = comtypes.automation.DISPATCH_PROPERTYGET > try: > result = self._comobj.Invoke(dispid, _invkind=flags) > </snip> > > If it works for you I can commit it to the repository. > -- Thanks, Thomas ------------------------------------------------------------------------------ Download Intel® Parallel Studio Eval Try the new software tools for yourself. Speed compiling, find bugs proactively, and fine-tune applications for parallel performance. See why Intel Parallel Studio got high marks during beta. http://p.sf.net/sfu/intel-sw-dev _______________________________________________ comtypes-users mailing list comtypes-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/comtypes-users