| 1 |
|
|---|
| 2 |
|
|---|
| 3 |
|
|---|
| 4 |
|
|---|
| 5 |
|
|---|
| 6 |
|
|---|
| 7 |
|
|---|
| 8 |
|
|---|
| 9 |
|
|---|
| 10 |
|
|---|
| 11 |
|
|---|
| 12 |
|
|---|
| 13 |
|
|---|
| 14 |
|
|---|
| 15 |
|
|---|
| 16 |
|
|---|
| 17 |
|
|---|
| 18 |
|
|---|
| 19 |
|
|---|
| 20 |
|
|---|
| 21 |
import sys |
|---|
| 22 |
|
|---|
| 23 |
|
|---|
| 24 |
|
|---|
| 25 |
if sys.platform.lower() == u'win32': |
|---|
| 26 |
|
|---|
| 27 |
import datetime |
|---|
| 28 |
import inspect |
|---|
| 29 |
import logging |
|---|
| 30 |
import new |
|---|
| 31 |
import re |
|---|
| 32 |
import sys |
|---|
| 33 |
import types |
|---|
| 34 |
|
|---|
| 35 |
import pythoncom |
|---|
| 36 |
import pywintypes |
|---|
| 37 |
import win32com.client |
|---|
| 38 |
import win32com.server.dispatcher |
|---|
| 39 |
from win32com.server.exception import COMException |
|---|
| 40 |
import win32com.server.policy |
|---|
| 41 |
import winerror |
|---|
| 42 |
|
|---|
| 43 |
from GeoEco.DynamicDocString import DynamicDocString |
|---|
| 44 |
from GeoEco.Internationalization import * |
|---|
| 45 |
from GeoEco.Metadata import * |
|---|
| 46 |
from GeoEco.Types import * |
|---|
| 47 |
|
|---|
| 48 |
|
|---|
| 49 |
TypeLibraryGUID = '{B062A595-DFFC-4980-9212-EBC8A54A4845}' |
|---|
| 50 |
TypeLibraryVersion = (0,5) |
|---|
| 51 |
TypeLibraryLCID = 0 |
|---|
| 52 |
|
|---|
| 53 |
|
|---|
| 54 |
class ExceptionTranslatingDispatcher(win32com.server.dispatcher.DispatcherBase): |
|---|
| 55 |
|
|---|
| 56 |
def __init__(self, policyClass, obj): |
|---|
| 57 |
win32com.server.dispatcher.DispatcherBase.__init__(self, policyClass, obj) |
|---|
| 58 |
|
|---|
| 59 |
|
|---|
| 60 |
class MetadataDesignatedWrapPolicy(win32com.server.policy.DesignatedWrapPolicy): |
|---|
| 61 |
|
|---|
| 62 |
def _wrap_(self, ob): |
|---|
| 63 |
|
|---|
| 64 |
|
|---|
| 65 |
|
|---|
| 66 |
|
|---|
| 67 |
classMetadata = ob.__doc__.Obj |
|---|
| 68 |
|
|---|
| 69 |
|
|---|
| 70 |
|
|---|
| 71 |
|
|---|
| 72 |
|
|---|
| 73 |
|
|---|
| 74 |
ob._com_interfaces_ = [u'I' + classMetadata.Name] |
|---|
| 75 |
ob._typelib_guid_ = globals()[u'TypeLibraryGUID'] |
|---|
| 76 |
ob._typelib_version_ = globals()[u'TypeLibraryVersion'] |
|---|
| 77 |
ob._typelib_lcid_ = globals()[u'TypeLibraryLCID'] |
|---|
| 78 |
|
|---|
| 79 |
|
|---|
| 80 |
|
|---|
| 81 |
self._Log(_(u'COM object 0x%08x: Initializing wrapper for %s.%s instance exposing interface %s (I%s) from type library %s, version %i.%i, LCID %i'), id(ob), classMetadata.Module.Name, classMetadata.Name, classMetadata.COMIID, classMetadata.Name, globals()['TypeLibraryGUID'], globals()['TypeLibraryVersion'][0], globals()['TypeLibraryVersion'][1], globals()['TypeLibraryLCID']) |
|---|
| 82 |
win32com.server.policy.DesignatedWrapPolicy._wrap_(self, ob) |
|---|
| 83 |
|
|---|
| 84 |
def _invokeex_(self, dispid, lcid, wFlags, args, kwArgs, serviceProvider): |
|---|
| 85 |
|
|---|
| 86 |
|
|---|
| 87 |
|
|---|
| 88 |
wFlagsDisplayStrings = [] |
|---|
| 89 |
|
|---|
| 90 |
if wFlags & pythoncom.DISPATCH_METHOD: |
|---|
| 91 |
wFlagsDisplayStrings.append(u'DISPATCH_METHOD') |
|---|
| 92 |
if wFlags & pythoncom.DISPATCH_PROPERTYGET: |
|---|
| 93 |
wFlagsDisplayStrings.append(u'DISPATCH_PROPERTYGET') |
|---|
| 94 |
if wFlags & pythoncom.DISPATCH_PROPERTYPUT: |
|---|
| 95 |
wFlagsDisplayStrings.append(u'DISPATCH_PROPERTYPUT') |
|---|
| 96 |
if wFlags & pythoncom.DISPATCH_PROPERTYPUTREF: |
|---|
| 97 |
wFlagsDisplayStrings.append(u'DISPATCH_PROPERTYPUTREF') |
|---|
| 98 |
if len(wFlagsDisplayStrings) <= 0 or wFlags & ~(pythoncom.DISPATCH_METHOD | pythoncom.DISPATCH_PROPERTYGET | pythoncom.DISPATCH_PROPERTYPUT | pythoncom.DISPATCH_PROPERTYPUTREF) > 0: |
|---|
| 99 |
wFlagsDisplayStrings.append(_(u'unknown flags!')) |
|---|
| 100 |
|
|---|
| 101 |
wFlagsDisplayString = u' | '.join(wFlagsDisplayStrings) |
|---|
| 102 |
|
|---|
| 103 |
|
|---|
| 104 |
|
|---|
| 105 |
memberName = None |
|---|
| 106 |
|
|---|
| 107 |
if wFlags & pythoncom.DISPATCH_METHOD: |
|---|
| 108 |
try: |
|---|
| 109 |
memberName = self._dispid_to_func_[dispid] |
|---|
| 110 |
except KeyError: |
|---|
| 111 |
pass |
|---|
| 112 |
|
|---|
| 113 |
if memberName is None and wFlags & pythoncom.DISPATCH_PROPERTYGET: |
|---|
| 114 |
try: |
|---|
| 115 |
memberName = self._dispid_to_get_[dispid] |
|---|
| 116 |
except KeyError: |
|---|
| 117 |
pass |
|---|
| 118 |
|
|---|
| 119 |
if memberName is None and wFlags & (pythoncom.DISPATCH_PROPERTYPUT | pythoncom.DISPATCH_PROPERTYPUTREF): |
|---|
| 120 |
try: |
|---|
| 121 |
memberName = self._dispid_to_put_[dispid] |
|---|
| 122 |
except KeyError: |
|---|
| 123 |
pass |
|---|
| 124 |
|
|---|
| 125 |
|
|---|
| 126 |
|
|---|
| 127 |
if memberName is None: |
|---|
| 128 |
memberName = _(u'member not found!') |
|---|
| 129 |
memberType = u'' |
|---|
| 130 |
memberMetadata = None |
|---|
| 131 |
else: |
|---|
| 132 |
if not isinstance(self._obj_.__class__.__doc__, DynamicDocString) or not isinstance(self._obj_.__class__.__doc__.Obj, ClassMetadata): |
|---|
| 133 |
raise COMException(scode=winerror.DISP_E_EXCEPTION, source=_(u'GeoEco.COM.MetadataDesignatedWrapPolicy Python class'), description=_(u'Programming error in the %s class. In order for this class to expose itself to COM callers using GeoEco.COM.MetadataDesignatedWrapPolicy, it must set its __doc__ member to an instance of GeoEco.Metadata.DynamicDocString and initialize it to an instance of GeoEco.Metadata.ClassMetadata. Please contact the developer of %s for assistance.') % (self._obj_.__class__.__name__, self._obj_.__class__.__name__)) |
|---|
| 134 |
classMetadata = self._obj_.__class__.__doc__.Obj |
|---|
| 135 |
if inspect.ismethod(getattr(classMetadata.Object, memberName)): |
|---|
| 136 |
if not isinstance(getattr(classMetadata.Object, memberName).__doc__, DynamicDocString) or not isinstance(getattr(classMetadata.Object, memberName).__doc__.Obj, MethodMetadata): |
|---|
| 137 |
raise COMException(scode=winerror.DISP_E_EXCEPTION, source=_(u'GeoEco.COM.MetadataDesignatedWrapPolicy Python class'), description=_(u'Programming error in the %s class. In order for this class to expose member %s to COM callers using GeoEco.COM.MetadataDesignatedWrapPolicy, it must set the __doc__ member of %s to an instance of GeoEco.Metadata.DynamicDocString and initialize it to an instance of GeoEco.Metadata.MethodMetadata. Please contact the developer of %s for assistance.') % (self._obj_.__class__.__name__, methodName, methodName, self._obj_.__class__.__name__)) |
|---|
| 138 |
memberType = _(u' method') |
|---|
| 139 |
elif inspect.isdatadescriptor(getattr(classMetadata.Object, memberName)): |
|---|
| 140 |
if not isinstance(getattr(classMetadata.Object, memberName).__doc__, DynamicDocString) or not isinstance(getattr(classMetadata.Object, memberName).__doc__.Obj, PropertyMetadata): |
|---|
| 141 |
raise COMException(scode=winerror.DISP_E_EXCEPTION, source=_(u'GeoEco.COM.MetadataDesignatedWrapPolicy Python class'), description=_(u'Programming error in the %s class. In order for this class to expose member %s to COM callers using GeoEco.COM.MetadataDesignatedWrapPolicy, it must set the __doc__ member of %s to an instance of GeoEco.Metadata.DynamicDocString and initialize it to an instance of GeoEco.Metadata.PropertyMetadata. Please contact the developer of %s for assistance.') % (self._obj_.__class__.__name__, methodName, methodName, self._obj_.__class__.__name__)) |
|---|
| 142 |
memberType = _(u' property') |
|---|
| 143 |
else: |
|---|
| 144 |
raise COMException(scode=winerror.DISP_E_EXCEPTION, source=_(u'GeoEco.COM.MetadataDesignatedWrapPolicy Python class'), description=_(u'Programming error in the %s class. In order for this class to expose member %s to COM callers using GeoEco.COM.MetadataDesignatedWrapPolicy, %s must be an instance method, a class method, or a property. Please contact the developer of %s for assistance.') % (self._obj_.__class__.__name__, methodName, methodName, self._obj_.__class__.__name__)) |
|---|
| 145 |
memberMetadata = getattr(classMetadata.Object, memberName).__doc__.Obj |
|---|
| 146 |
|
|---|
| 147 |
self._Log(_(u'COM object 0x%08X: InvokeEx called: dispid = %i (%s%s), lcid = %i, wFlags = %i (%s), args = %s, kwArgs = %s, serviceProvider = %s'), id(self._obj_), dispid, memberName, memberType, lcid, wFlags, wFlagsDisplayString, repr(args), repr(kwArgs), serviceProvider) |
|---|
| 148 |
|
|---|
| 149 |
|
|---|
| 150 |
|
|---|
| 151 |
|
|---|
| 152 |
args = list(args) |
|---|
| 153 |
argsChanged = False |
|---|
| 154 |
|
|---|
| 155 |
|
|---|
| 156 |
|
|---|
| 157 |
if isinstance(memberMetadata, PropertyMetadata): |
|---|
| 158 |
|
|---|
| 159 |
|
|---|
| 160 |
|
|---|
| 161 |
|
|---|
| 162 |
|
|---|
| 163 |
if len(args) == 1 and isinstance(args[0], types.TupleType) and isinstance(memberMetadata.Type, ListTypeMetadata): |
|---|
| 164 |
args = (self._TuplesToLists(args[0], memberMetadata.Type),) |
|---|
| 165 |
argsChanged = True |
|---|
| 166 |
|
|---|
| 167 |
|
|---|
| 168 |
|
|---|
| 169 |
elif isinstance(memberMetadata, MethodMetadata): |
|---|
| 170 |
|
|---|
| 171 |
|
|---|
| 172 |
|
|---|
| 173 |
|
|---|
| 174 |
|
|---|
| 175 |
|
|---|
| 176 |
|
|---|
| 177 |
|
|---|
| 178 |
|
|---|
| 179 |
|
|---|
| 180 |
|
|---|
| 181 |
if len(memberMetadata.Results) > 1: |
|---|
| 182 |
argsToRemove = len(memberMetadata.Results) - 1 |
|---|
| 183 |
if memberMetadata.Arguments[len(memberMetadata.Arguments) - 1].IsArbitraryArgumentList: |
|---|
| 184 |
formalArgCount = len(memberMetadata.Arguments) - 2 |
|---|
| 185 |
else: |
|---|
| 186 |
formalArgCount = len(memberMetadata.Arguments) - 1 |
|---|
| 187 |
while argsToRemove > 0 and len(args) > formalArgCount: |
|---|
| 188 |
del args[formalArgCount] |
|---|
| 189 |
argsChanged = True |
|---|
| 190 |
|
|---|
| 191 |
|
|---|
| 192 |
|
|---|
| 193 |
|
|---|
| 194 |
|
|---|
| 195 |
for i in range(len(memberMetadata.Arguments) - 1): |
|---|
| 196 |
if i < len(args) and memberMetadata.Arguments[i + 1].IsFormalParameter and isinstance(args[i], types.TupleType) and isinstance(memberMetadata.Arguments[i + 1].Type, SequenceTypeMetadata): |
|---|
| 197 |
args[i] = self._TuplesToLists(args[i], memberMetadata.Arguments[i + 1].Type) |
|---|
| 198 |
argsChanged = True |
|---|
| 199 |
|
|---|
| 200 |
|
|---|
| 201 |
|
|---|
| 202 |
|
|---|
| 203 |
|
|---|
| 204 |
|
|---|
| 205 |
|
|---|
| 206 |
|
|---|
| 207 |
|
|---|
| 208 |
|
|---|
| 209 |
|
|---|
| 210 |
|
|---|
| 211 |
|
|---|
| 212 |
|
|---|
| 213 |
|
|---|
| 214 |
|
|---|
| 215 |
|
|---|
| 216 |
|
|---|
| 217 |
|
|---|
| 218 |
|
|---|
| 219 |
|
|---|
| 220 |
|
|---|
| 221 |
|
|---|
| 222 |
|
|---|
| 223 |
|
|---|
| 224 |
|
|---|
| 225 |
|
|---|
| 226 |
|
|---|
| 227 |
if not memberMetadata.Arguments[len(memberMetadata.Arguments) - 1].IsArbitraryArgumentList: |
|---|
| 228 |
for i in range(0, len(args)): |
|---|
| 229 |
if args[i] == winerror.DISP_E_PARAMNOTFOUND and i < len(memberMetadata.Arguments) - 1: |
|---|
| 230 |
argMetadata = memberMetadata.Arguments[i + 1] |
|---|
| 231 |
if argMetadata.IsFormalParameter and argMetadata.HasDefault: |
|---|
| 232 |
if not isinstance(argMetadata.Type, IntegerTypeMetadata): |
|---|
| 233 |
args[i] = argMetadata.Default |
|---|
| 234 |
argsChanged = True |
|---|
| 235 |
else: |
|---|
| 236 |
logger = logging.getLogger(u'GeoEco.COM') |
|---|
| 237 |
if logger is not None: |
|---|
| 238 |
logger.warning(_(u'COM object 0x%08X: Method %s.%s received the value %i for the %s parameter. Due to the design of the pythoncom Python library, this method cannot determine if the caller provided an integer with this value or a VARIANT of type VT_ERROR with error code DISP_E_PARAMNOTFOUND, indicating that the caller is not providing a value. (From .Net code, this is done by passing System.Type.Missing.) This method will assume that the caller provided the integer, not the VT_ERROR VARIANT. If this was not your intention, and you wanted the method to use its default value for this parameter, you should pass in the default value %i explicitly.'), id(self._obj_), argMetadata.Method.Name, argMetadata.Method.Class.Name, winerror.DISP_E_PARAMNOTFOUND, argMetadata.Name, argMetadata.Default) |
|---|
| 239 |
|
|---|
| 240 |
|
|---|
| 241 |
|
|---|
| 242 |
|
|---|
| 243 |
|
|---|
| 244 |
|
|---|
| 245 |
|
|---|
| 246 |
|
|---|
| 247 |
|
|---|
| 248 |
|
|---|
| 249 |
|
|---|
| 250 |
|
|---|
| 251 |
|
|---|
| 252 |
|
|---|
| 253 |
|
|---|
| 254 |
|
|---|
| 255 |
|
|---|
| 256 |
|
|---|
| 257 |
|
|---|
| 258 |
|
|---|
| 259 |
if memberMetadata.Arguments[len(memberMetadata.Arguments) - 1].IsArbitraryArgumentList and len(args) == len(memberMetadata.Arguments) - 1: |
|---|
| 260 |
if isinstance(args[len(args) - 1], types.TupleType) and self._InvokedByUniversalDispatcher(): |
|---|
| 261 |
varargTuple = args.pop() |
|---|
| 262 |
args = args + list(varargTuple) |
|---|
| 263 |
argsChanged = True |
|---|
| 264 |
|
|---|
| 265 |
|
|---|
| 266 |
|
|---|
| 267 |
args = tuple(args) |
|---|
| 268 |
|
|---|
| 269 |
if argsChanged: |
|---|
| 270 |
self._Log(_(u'COM object 0x%08X: Fixed arguments provided by pythoncom. New args = %s'), id(self._obj_), repr(args)) |
|---|
| 271 |
|
|---|
| 272 |
|
|---|
| 273 |
|
|---|
| 274 |
|
|---|
| 275 |
|
|---|
| 276 |
returnedValue = win32com.server.policy.DesignatedWrapPolicy._invokeex_(self, dispid, lcid, wFlags, args, kwArgs, serviceProvider) |
|---|
| 277 |
|
|---|
| 278 |
|
|---|
| 279 |
|
|---|
| 280 |
|
|---|
| 281 |
|
|---|
| 282 |
|
|---|
| 283 |
|
|---|
| 284 |
|
|---|
| 285 |
|
|---|
| 286 |
|
|---|
| 287 |
if isinstance(returnedValue, types.TupleType) and (isinstance(memberMetadata, PropertyMetadata) and isinstance(memberMetadata.Type, TupleTypeMetadata) or isinstance(memberMetadata, MethodMetadata) and len(memberMetadata.Results) == 1 and isinstance(memberMetadata.Results[0].Type, TupleTypeMetadata)): |
|---|
| 288 |
returnedValue = list(returnedValue) |
|---|
| 289 |
self._Log(_(u'COM object 0x%08X: Coerced the returned Python tuple into a Python list, so pythoncom will return it as a SAFEARRAY'), id(self._obj_)) |
|---|
| 290 |
|
|---|
| 291 |
|
|---|
| 292 |
|
|---|
| 293 |
|
|---|
| 294 |
|
|---|
| 295 |
|
|---|
| 296 |
|
|---|
| 297 |
|
|---|
| 298 |
|
|---|
| 299 |
|
|---|
| 300 |
|
|---|
| 301 |
|
|---|
| 302 |
|
|---|
| 303 |
|
|---|
| 304 |
|
|---|
| 305 |
|
|---|
| 306 |
|
|---|
| 307 |
|
|---|
| 308 |
if isinstance(memberMetadata, MethodMetadata) and len(memberMetadata.Results) > 1 and isinstance(returnedValue, types.TupleType) and len(returnedValue) == len(memberMetadata.Results) and self._InvokedByUniversalDispatcher(): |
|---|
| 309 |
returnedValue = tuple([winerror.S_OK] + list(returnedValue)) |
|---|
| 310 |
self._Log(_(u'COM object 0x%08X: Prepended the HRESULT S_OK to the tuple of output arguments, so pythoncom\'s "universal dispatcher" will not fail.'), id(self._obj_)) |
|---|
| 311 |
|
|---|
| 312 |
|
|---|
| 313 |
|
|---|
| 314 |
|
|---|
| 315 |
self._Log(_(u'COM object 0x%08X: InvokeEx returning %s'), id(self._obj_), repr(returnedValue)) |
|---|
| 316 |
return returnedValue |
|---|
| 317 |
|
|---|
| 318 |
def _Log(self, format, *args): |
|---|
| 319 |
logger = logging.getLogger(u'GeoEco.COM') |
|---|
| 320 |
if logger is not None: |
|---|
| 321 |
logger.debug(format, *args) |
|---|
| 322 |
|
|---|
| 323 |
def _TuplesToLists(self, arg, typeMetadata, depthToDescend=None): |
|---|
| 324 |
|
|---|
| 325 |
|
|---|
| 326 |
|
|---|
| 327 |
|
|---|
| 328 |
|
|---|
| 329 |
|
|---|
| 330 |
|
|---|
| 331 |
|
|---|
| 332 |
|
|---|
| 333 |
|
|---|
| 334 |
if depthToDescend is None: |
|---|
| 335 |
currentDepth = 0 |
|---|
| 336 |
depthToDescend = 0 |
|---|
| 337 |
t = typeMetadata |
|---|
| 338 |
while isinstance(t, SequenceTypeMetadata): |
|---|
| 339 |
currentDepth += 1 |
|---|
| 340 |
t = t.ElementType |
|---|
| 341 |
if isinstance(t, ListTypeMetadata): |
|---|
| 342 |
depthToDescend = currentDepth |
|---|
| 343 |
|
|---|
| 344 |
|
|---|
| 345 |
|
|---|
| 346 |
if isinstance(arg, types.TupleType) and isinstance(typeMetadata, ListTypeMetadata): |
|---|
| 347 |
arg = list(arg) |
|---|
| 348 |
|
|---|
| 349 |
|
|---|
| 350 |
|
|---|
| 351 |
|
|---|
| 352 |
|
|---|
| 353 |
if depthToDescend > 0: |
|---|
| 354 |
arg = list(arg) |
|---|
| 355 |
for i in range(len(arg)): |
|---|
| 356 |
arg[i] = self._TuplesToLists(arg[i], typeMetadata.ElementType, depthToDescend - 1) |
|---|
| 357 |
if isinstance(typeMetadata, TupleTypeMetadata): |
|---|
| 358 |
arg = tuple(arg) |
|---|
| 359 |
|
|---|
| 360 |
|
|---|
| 361 |
|
|---|
| 362 |
return arg |
|---|
| 363 |
|
|---|
| 364 |
def _InvokedByUniversalDispatcher(self): |
|---|
| 365 |
currentFrame = inspect.currentframe() |
|---|
| 366 |
try: |
|---|
| 367 |
outerFrames = inspect.getouterframes(currentFrame) |
|---|
| 368 |
try: |
|---|
| 369 |
for frame in outerFrames: |
|---|
| 370 |
if frame[1].endswith(u'win32com\\universal.py'): |
|---|
| 371 |
return True |
|---|
| 372 |
finally: |
|---|
| 373 |
del outerFrames |
|---|
| 374 |
finally: |
|---|
| 375 |
del currentFrame |
|---|
| 376 |
return False |
|---|
| 377 |
|
|---|
| 378 |
|
|---|
| 379 |
def ValidateClassMetadata(cls): |
|---|
| 380 |
assert inspect.isclass(cls), u'cls must be a class' |
|---|
| 381 |
assert isinstance(cls.__doc__, DynamicDocString) and isinstance(cls.__doc__.Obj, ClassMetadata), u'cls.__doc__ must be an instance of GeoEco.Metadata.DynamicDocString and cls.__doc__.Obj must be an instance of GeoEco.Metadata.ClassMetadata.' |
|---|
| 382 |
|
|---|
| 383 |
|
|---|
| 384 |
|
|---|
| 385 |
classMetadata = cls.__doc__.Obj |
|---|
| 386 |
|
|---|
| 387 |
assert classMetadata.IsExposedAsCOMServer, u'cls.__doc__.Obj.IsExposedAsCOMServer must be True' |
|---|
| 388 |
assert classMetadata.COMIID is not None, u'Class %s.%s is flagged for exposure by COM but its COMIID property is None. You must specify a value for COMIID; here is a randomly generated value you can use: %s. See the documentation for GeoEco.Metadata.ClassMetadata.COMIID for more information.' % (classMetadata.Module.Name, classMetadata.Name, repr(unicode(pythoncom.CreateGuid()))) |
|---|
| 389 |
assert classMetadata.COMCLSID is not None, u'Class %s.%s is flagged for exposure by COM but its COMCLSID property is None. You must specify a value for COMCLSID; here is a randomly generated value you can use: %s. See the documentation for GeoEco.Metadata.ClassMetadata.COMCLSID for more information.' % (classMetadata.Module.Name, classMetadata.Name, repr(unicode(pythoncom.CreateGuid()))) |
|---|
| 390 |
assert classMetadata.COMIID != classMetadata.COMCLSID, u'Class %s.%s is flagged for exposure by COM but its COMCLSID property has the same value as is COMIID property. These two values must not be the same. Please change one to a unique GUID; here is a randomly generated value you can use: %s. See the documentation for GeoEco.Metadata.ClassMetadata.COMCLSID for more information.' % (classMetadata.Module.Name, classMetadata.Name, repr(unicode(pythoncom.CreateGuid()))) |
|---|
| 391 |
|
|---|
| 392 |
|
|---|
| 393 |
|
|---|
| 394 |
atLeastOneExposed = False |
|---|
| 395 |
|
|---|
| 396 |
for propName, prop in inspect.getmembers(cls, inspect.isdatadescriptor): |
|---|
| 397 |
if hasattr(prop, u'__doc__') and isinstance(prop.__doc__, DynamicDocString) and isinstance(prop.__doc__.Obj, PropertyMetadata) and prop.__doc__.Obj.IsExposedByCOM: |
|---|
| 398 |
atLeastOneExposed = True |
|---|
| 399 |
propMetadata = prop.__doc__.Obj |
|---|
| 400 |
assert propMetadata.Type.CanBeCOMParameter, u'Property %s.%s.%s is flagged for exposure by COM but %s.%s.%s.Type.CanBeCOMParameter is False. Change the property\'s type to one that can be exposed as a COM parameter or do not designate this property for exposure by COM.' % (propMetadata.Class.Module.Name, propMetadata.Class.Name, propMetadata.Name, propMetadata.Class.Module.Name, propMetadata.Class.Name, propMetadata.Name) |
|---|
| 401 |
assert propMetadata.Type.COMIDLType is not None, u'Property %s.%s.%s is flagged for exposure by COM but %s.%s.%s.Type.COMIDLType is None. This should not be possible, since the type\'s CanBeCOMParameter property is True. Please fix the definition of this type to include a COMIDLType or to assign CanBeCOMParameter to False.' % (propMetadata.Class.Module.Name, propMetadata.Class.Name, propMetadata.Name, propMetadata.Class.Module.Name, propMetadata.Class.Name, propMetadata.Name) |
|---|
| 402 |
assert not propMetadata.Type.CanBeNone or propMetadata.Type.COMIDLType == 'VARIANT', u'Property %s.%s.%s is flagged for exposure by COM but its Type.CanBeNone == True while its Type.COMIDLType != \'VARIANT\'. This is not allowed; if Type.CanBeNone is True then Type.COMIDLType must be \'VARIANT\', so that COM callers can pass a VT_NULL or VT_EMPTY. Please fix this.' % (propMetadata.Class.Module.Name, propMetadata.Class.Name, propMetadata.Name) |
|---|
| 403 |
assert prop.fget is not None, u'Property %s.%s.%s is flagged for exposure by COM but it has no "fget" method. This means it is a write-only property, which is not presently supported by GeoEco. Please give this property an fget method or do not flag it for exposure using COM.' % (propMetadata.Class.Module.Name, propMetadata.Class.Name, propMetadata.Name) |
|---|
| 404 |
|
|---|
| 405 |
|
|---|
| 406 |
|
|---|
| 407 |
for methodName, method in inspect.getmembers(cls, inspect.ismethod): |
|---|
| 408 |
|
|---|
| 409 |
|
|---|
| 410 |
|
|---|
| 411 |
|
|---|
| 412 |
|
|---|
| 413 |
(args, varargs, varkw, defaults) = inspect.getargspec(method) |
|---|
| 414 |
|
|---|
| 415 |
if methodName == u'__init__': |
|---|
| 416 |
assert len(args) >= 1, u'Method %s.%s.%s must have at least one argument ("self") because it is the class\'s constructor.' % (methodMetadata.Class.Module.Name, methodMetadata.Class.Name, methodMetadata.Name) |
|---|
| 417 |
assert len(args) <= 1 or isinstance(defaults, types.TupleType) and len(defaults) == len(args) - 1, u'Class %s.%s is flagged for exposure by COM but not all of the arguments to its __init__ have default values. All __init__ arguments must have default values for pythoncom to be able to instantiate the class. Please provide defaults for every argument (except the "self" argument) or do not expose the class using COM.' % (methodMetadata.Class.Module.Name, methodMetadata.Class.Name) |
|---|
| 418 |
|
|---|
| 419 |
|
|---|
| 420 |
|
|---|
| 421 |
|
|---|
| 422 |
if hasattr(method, u'__doc__') and isinstance(method.__doc__, DynamicDocString) and isinstance(method.__doc__.Obj, MethodMetadata) and method.__doc__.Obj.IsExposedByCOM: |
|---|
| 423 |
atLeastOneExposed = True |
|---|
| 424 |
methodMetadata = method.__doc__.Obj |
|---|
| 425 |
|
|---|
| 426 |
|
|---|
| 427 |
|
|---|
| 428 |
assert varkw is None, u'Method %s.%s.%s is flagged for exposure by COM but it has an optional keywords dictionary argument (**%s). This is not supported by COM. Please remove this argument or do not expose this method by COM.' % (methodMetadata.Class.Module.Name, methodMetadata.Class.Name, methodMetadata.Name, varkw) |
|---|
| 429 |
expectedArgCount = len(args) |
|---|
| 430 |
if varargs is not None: |
|---|
| 431 |
expectedArgCount += 1 |
|---|
| 432 |
assert len(methodMetadata.Arguments) == expectedArgCount, u'Method %s.%s.%s is flagged for exposure by COM but its metadata is not consistent with its definition: the metadata lists a different number of arguments than the method definition. Please correct the metadata.' % (methodMetadata.Class.Module.Name, methodMetadata.Class.Name, methodMetadata.Name) |
|---|
| 433 |
|
|---|
| 434 |
foundArgWithDefault = False |
|---|
| 435 |
|
|---|
| 436 |
for i in range(len(methodMetadata.Arguments)): |
|---|
| 437 |
argMetadata = methodMetadata.Arguments[i] |
|---|
| 438 |
if i < len(args): |
|---|
| 439 |
assert args[i] == argMetadata.Name, u'Method %s.%s.%s is flagged for exposure by COM but its metadata is not consistent with its definition: Argument %i is named %s in the metadata but %s in the definition. Please correct the metadata.' % (methodMetadata.Class.Module.Name, methodMetadata.Class.Name, methodMetadata.Name, i, argMetadata.Name, args[i]) |
|---|
| 440 |
else: |
|---|
| 441 |
assert varargs == argMetadata.Name, u'Method %s.%s.%s is flagged for exposure by COM but its metadata is not consistent with its definition: Argument %i is named %s in the metadata but %s in the definition. Please correct the metadata.' % (methodMetadata.Class.Module.Name, methodMetadata.Class.Name, methodMetadata.Name, i, argMetadata.Name, varargs) |
|---|
| 442 |
if i > 0: |
|---|
| 443 |
assert argMetadata.Type.CanBeCOMParameter, u'Method %s.%s.%s is flagged for exposure by COM but the metadata for its "%s" argument has Type.CanBeCOMParameter == False. Change the arguments\'s type to one that can be exposed as a COM parameter or do not designate this method for exposure by COM.' % (methodMetadata.Class.Module.Name, methodMetadata.Class.Name, methodMetadata.Name, argMetadata.Name) |
|---|
| 444 |
assert argMetadata.Type.COMIDLType is not None, u'Method %s.%s.%s is flagged for exposure by COM but the metadata for its "%s" argument has Type.COMIDLType == None. This should not be possible, since the type\'s CanBeCOMParameter property is True. Please fix the definition of this type to include a COMIDLType or to assign CanBeCOMParameter to False.' % (methodMetadata.Class.Module.Name, methodMetadata.Class.Name, methodMetadata.Name, argMetadata.Name) |
|---|
| 445 |
assert not argMetadata.Type.CanBeNone or argMetadata.Type.COMIDLType == 'VARIANT', u'Method %s.%s.%s is flagged for exposure by COM but the metadata for its "%s" argument has Type.CanBeNone == True but Type.COMIDLType != \'VARIANT\'. This is not allowed; if Type.CanBeNone is True then Type.COMIDLType must be \'VARIANT\', so that COM callers can pass a VT_NULL or VT_EMPTY. Please fix this.' % (methodMetadata.Class.Module.Name, methodMetadata.Class.Name, methodMetadata.Name, argMetadata.Name) |
|---|
| 446 |
|
|---|
| 447 |
|
|---|
| 448 |
|
|---|
| 449 |
for resultMetadata in methodMetadata.Results: |
|---|
| 450 |
assert resultMetadata.Type.CanBeCOMParameter, u'Method %s.%s.%s is flagged for exposure by COM but the metadata for its "%s" result has Type.CanBeCOMParameter == False. Change the result\'s type to one that can be exposed as a COM parameter or do not designate this method for exposure by COM.' % (methodMetadata.Class.Module.Name, methodMetadata.Class.Name, methodMetadata.Name, resultMetadata.Name) |
|---|
| 451 |
assert resultMetadata.Type.COMIDLType is not None, u'Method %s.%s.%s is flagged for exposure by COM but the metadata for its "%s" result has Type.COMIDLType == None. This should not be possible, since the type\'s CanBeCOMParameter property is True. Please fix the definition of this type to include a COMIDLType or to assign CanBeCOMParameter to False.' % (methodMetadata.Class.Module.Name, methodMetadata.Class.Name, methodMetadata.Name, resultMetadata.Name) |
|---|
| 452 |
assert not resultMetadata.Type.CanBeNone or resultMetadata.Type.COMIDLType == 'VARIANT', u'Method %s.%s.%s is flagged for exposure by COM but the metadata for its "%s" result has Type.CanBeNone == True but Type.COMIDLType != \'VARIANT\'. This is not allowed; if Type.CanBeNone is True then Type.COMIDLType must be \'VARIANT\', so that a VT_NULL VARIANT may be returned to the COM when the Python method returns None. Please fix this.' % (methodMetadata.Class.Module.Name, methodMetadata.Class.Name, methodMetadata.Name, resultMetadata.Name) |
|---|
| 453 |
|
|---|
| 454 |
|
|---|
| 455 |
|
|---|
| 456 |
|
|---|
| 457 |
for funcName, func in inspect.getmembers(cls, inspect.isfunction): |
|---|
| 458 |
if hasattr(func, u'__doc__') and isinstance(func.__doc__, DynamicDocString) and isinstance(func.__doc__.Obj, MethodMetadata) and func.__doc__.Obj.IsExposedByCOM: |
|---|
| 459 |
methodMetadata = func.__doc__.Obj |
|---|
| 460 |
assert not methodMetadata.IsStaticMethod, u'Static method %s.%s.%s is flagged for exposure by COM. This is not supported. Please change this method to a class method if you want to expose it using COM.' % (methodMetadata.Class.Module.Name, methodMetadata.Class.Name, methodMetadata.Name) |
|---|
| 461 |
|
|---|
| 462 |
|
|---|
| 463 |
|
|---|
| 464 |
|
|---|
| 465 |
assert atLeastOneExposed, u'Class %s.%s is flagged for exposure by COM but it does not have any properties or methods flagged for exposure by COM. At least one property or method must be flagged for exposure, or you should not flag the class for exposure.' % (classMetadata.Module.Name, classMetadata.Name) |
|---|
| 466 |
|
|---|
| 467 |
|
|---|
| 468 |
def GetIDLInterfaceDefinitionFromMetadata(classMetadata): |
|---|
| 469 |
assert isinstance(classMetadata, ClassMetadata), u'classMetadata must be an instance of GeoEco.Metadata.ClassMetadata' |
|---|
| 470 |
|
|---|
| 471 |
|
|---|
| 472 |
|
|---|
| 473 |
header = '[\n dual,\n uuid(%s),\n helpstring("I%s Interface"),\n pointer_default(unique)\n]\ninterface I%s : IDispatch\n{\n' % (classMetadata.COMIID[1:-1], classMetadata.Name, classMetadata.Name) |
|---|
| 474 |
|
|---|
| 475 |
|
|---|
| 476 |
|
|---|
| 477 |
dispID = 1 |
|---|
| 478 |
propertiesIDL = [] |
|---|
| 479 |
|
|---|
| 480 |
properties = inspect.getmembers(classMetadata.Object, inspect.isdatadescriptor) |
|---|
| 481 |
for (name, prop) in properties: |
|---|
| 482 |
if isinstance(prop.__doc__, DynamicDocString) and isinstance(prop.__doc__.Obj, PropertyMetadata) and prop.__doc__.Obj.IsExposedByCOM: |
|---|
| 483 |
if len(propertiesIDL) <= 0: |
|---|
| 484 |
propertiesIDL = [' // Properties\n'] |
|---|
| 485 |
propertiesIDL.append(GetIDLPropertyDefinitionFromMetadata(prop.__doc__.Obj, dispID)) |
|---|
| 486 |
dispID += 1 |
|---|
| 487 |
|
|---|
| 488 |
|
|---|
| 489 |
|
|---|
| 490 |
methodsIDL = [] |
|---|
| 491 |
|
|---|
| 492 |
methods = inspect.getmembers(classMetadata.Object, inspect.ismethod) |
|---|
| 493 |
for (name, method) in methods: |
|---|
| 494 |
if isinstance(method.__doc__, DynamicDocString) and isinstance(method.__doc__.Obj, MethodMetadata) and method.__doc__.Obj.IsExposedByCOM: |
|---|
| 495 |
if len(methodsIDL) <= 0: |
|---|
| 496 |
methodsIDL = [' // Methods\n'] |
|---|
| 497 |
methodsIDL.append(GetIDLMethodDefinitionFromMetadata(method.__doc__.Obj, dispID)) |
|---|
| 498 |
dispID += 1 |
|---|
| 499 |
|
|---|
| 500 |
|
|---|
| 501 |
|
|---|
| 502 |
footer = '};\n' |
|---|
| 503 |
|
|---|
| 504 |
|
|---|
| 505 |
|
|---|
| 506 |
return header + ''.join(propertiesIDL) + ''.join(methodsIDL) + footer |
|---|
| 507 |
|
|---|
| 508 |
|
|---|
| 509 |
def GetIDLPropertyDefinitionFromMetadata(propertyMetadata, dispID): |
|---|
| 510 |
assert isinstance(propertyMetadata, PropertyMetadata), u'propertyMetadata must be an instance of GeoEco.Metadata.PropertyMetadata' |
|---|
| 511 |
assert isinstance(dispID, types.IntType), u'dispID must be an int' |
|---|
| 512 |
|
|---|
| 513 |
|
|---|
| 514 |
|
|---|
| 515 |
|
|---|
| 516 |
|
|---|
| 517 |
|
|---|
| 518 |
|
|---|
| 519 |
|
|---|
| 520 |
|
|---|
| 521 |
|
|---|
| 522 |
|
|---|
| 523 |
|
|---|
| 524 |
|
|---|
| 525 |
|
|---|
| 526 |
|
|---|
| 527 |
|
|---|
| 528 |
typeIDL = propertyMetadata.Type.COMIDLType |
|---|
| 529 |
if typeIDL.upper().startswith('SAFEARRAY'): |
|---|
| 530 |
typeIDL = 'VARIANT' |
|---|
| 531 |
|
|---|
| 532 |
|
|---|
| 533 |
|
|---|
| 534 |
idl = ' [id(%s), propget, helpstring("%s Property")] HRESULT %s([out, retval] %s *pValue);\n' % (dispID, propertyMetadata.Name, propertyMetadata.Name, typeIDL) |
|---|
| 535 |
|
|---|
| 536 |
|
|---|
| 537 |
|
|---|
| 538 |
if not propertyMetadata.IsReadOnly: |
|---|
| 539 |
idl = idl + ' [id(%s), propput, helpstring("%s Property")] HRESULT %s([in] %s value);\n' % (dispID, propertyMetadata.Name, propertyMetadata.Name, typeIDL) |
|---|
| 540 |
|
|---|
| 541 |
return idl |
|---|
| 542 |
|
|---|
| 543 |
|
|---|
| 544 |
def GetIDLMethodDefinitionFromMetadata(methodMetadata, dispID): |
|---|
| 545 |
assert isinstance(methodMetadata, MethodMetadata), u'methodMetadata must be an instance of GeoEco.Metadata.MethodMetadata' |
|---|
| 546 |
assert isinstance(dispID, types.IntType), u'dispID must be an int' |
|---|
| 547 |
|
|---|
| 548 |
|
|---|
| 549 |
|
|---|
| 550 |
|
|---|
| 551 |
|
|---|
| 552 |
|
|---|
| 553 |
|
|---|
| 554 |
|
|---|
| 555 |
|
|---|
| 556 |
|
|---|
| 557 |
|
|---|
| 558 |
|
|---|
| 559 |
(args, varargs, varkw, defaults) = inspect.getargspec(methodMetadata.Object) |
|---|
| 560 |
|
|---|
| 561 |
requiredInputParams = [] |
|---|
| 562 |
optionalInputParams = [] |
|---|
| 563 |
inOutParams = [] |
|---|
| 564 |
varargParam = [] |
|---|
| 565 |
retvalParam = [] |
|---|
| 566 |
|
|---|
| 567 |
foundOptionalVariant = False |
|---|
| 568 |
foundDefaultvalue = False |
|---|
| 569 |
varargAttribute = '' |
|---|
| 570 |
|
|---|
| 571 |
|
|---|
| 572 |
|
|---|
| 573 |
for i in range(1, len(methodMetadata.Arguments)): |
|---|
| 574 |
argMetadata = methodMetadata.Arguments[i] |
|---|
| 575 |
|
|---|
| 576 |
|
|---|
| 577 |
|
|---|
| 578 |
if argMetadata.IsFormalParameter: |
|---|
| 579 |
assert len(varargParam) == 0, u'Programming error in GeoEco.COM: got formal parameter but varargParam is not empty' |
|---|
| 580 |
|
|---|
| 581 |
|
|---|
| 582 |
|
|---|
| 583 |
|
|---|
| 584 |
|
|---|
| 585 |
if not argMetadata.HasDefault or varargs is not None: |
|---|
| 586 |
assert len(optionalInputParams) == 0, u'Programming error in GeoEco.COM: got required input argument but optionalInputParams is not empty' |
|---|
| 587 |
requiredInputParams.append('[in] %s %s' % (argMetadata.Type.COMIDLType, argMetadata.Name)) |
|---|
| 588 |
|
|---|
| 589 |
|
|---|
| 590 |
|
|---|
| 591 |
|
|---|
| 592 |
|
|---|
| 593 |
else: |
|---|
| 594 |
if argMetadata.Default is not None: |
|---|
| 595 |
idlForDefault = argMetadata.Type.COMIDLRepresentationOfValue(argMetadata.Default) |
|---|
| 596 |
else: |
|---|
| 597 |
idlForDefault = None |
|---|
| 598 |
assert isinstance(idlForDefault, (types.StringType, types.NoneType)), u'Programming error in %s: COMIDLRepresentationOfValue must return an 8-bit string or None.' % argMetadata.Type.__class__.__name__ |
|---|
| 599 |
|
|---|
| 600 |
|
|---|
| 601 |
|
|---|
| 602 |
|
|---|
| 603 |
|
|---|
| 604 |
|
|---|
| 605 |
|
|---|
| 606 |
|
|---|
| 607 |
|
|---|
| 608 |
if idlForDefault is None and not argMetadata.Type.CanBeNone and len(optionalInputParams) <= 0: |
|---|
| 609 |
requiredInputParams.append('[in] %s %s' % (argMetadata.Type.COMIDLType, argMetadata.Name)) |
|---|
| 610 |
|
|---|
| 611 |
|
|---|
| 612 |
|
|---|
| 613 |
|
|---|
| 614 |
|
|---|
| 615 |
|
|---|
| 616 |
|
|---|
| 617 |
|
|---|
| 618 |
|
|---|
| 619 |
|
|---|
| 620 |
|
|---|
| 621 |
|
|---|
| 622 |
|
|---|
| 623 |
|
|---|
| 624 |
|
|---|
| 625 |
|
|---|
| 626 |
|
|---|
| 627 |
|
|---|
| 628 |
|
|---|
| 629 |
|
|---|
| 630 |
|
|---|
| 631 |
|
|---|
| 632 |
|
|---|
| 633 |
|
|---|
| 634 |
|
|---|
| 635 |
|
|---|
| 636 |
|
|---|
| 637 |
|
|---|
| 638 |
|
|---|
| 639 |
|
|---|
| 640 |
|
|---|
| 641 |
|
|---|
| 642 |
|
|---|
| 643 |
|
|---|
| 644 |
|
|---|
| 645 |
else: |
|---|
| 646 |
if idlForDefault is None or argMetadata.Type.CanBeNone or foundOptionalVariant: |
|---|
| 647 |
optionalInputParams.append('[in, optional] VARIANT %s' % argMetadata.Name) |
|---|
| 648 |
foundOptionalVariant = True |
|---|
| 649 |
else: |
|---|
| 650 |
requiredInputParams.append('[in, defaultvalue(%s)] %s %s' % (idlForDefault, argMetadata.Type.COMIDLType, argMetadata.Name)) |
|---|
| 651 |
foundDefaultvalue = True |
|---|
| 652 |
|
|---|
| 653 |
|
|---|
| 654 |
|
|---|
| 655 |
|
|---|
| 656 |
|
|---|
| 657 |
elif argMetadata.IsArbitraryArgumentList: |
|---|
| 658 |
assert len(varargParam) == 0, u'Programming error in GeoEco.COM: got vararg but varargParam is not empty' |
|---|
| 659 |
varargParam.append('[in] SAFEARRAY(VARIANT) %s' % argMetadata.Name) |
|---|
| 660 |
varargAttribute = ', vararg' |
|---|
| 661 |
|
|---|
| 662 |
|
|---|
| 663 |
|
|---|
| 664 |
|
|---|
| 665 |
|
|---|
| 666 |
|
|---|
| 667 |
|
|---|
| 668 |
|
|---|
| 669 |
else: |
|---|
| 670 |
assert False, u'Programming error in GeoEco.COM: argMetadata.IsArbitraryArgumentList is True' |
|---|
| 671 |
|
|---|
| 672 |
|
|---|
| 673 |
|
|---|
| 674 |
for i in range(len(methodMetadata.Results)): |
|---|
| 675 |
resultMetadata = methodMetadata.Results[i] |
|---|
| 676 |
idlType = resultMetadata.Type.COMIDLType |
|---|
| 677 |
|
|---|
| 678 |
|
|---|
| 679 |
|
|---|
| 680 |
|
|---|
| 681 |
|
|---|
| 682 |
|
|---|
| 683 |
|
|---|
| 684 |
|
|---|
| 685 |
|
|---|
| 686 |
|
|---|
| 687 |
|
|---|
| 688 |
|
|---|
| 689 |
if idlType.upper().startswith('SAFEARRAY'): |
|---|
| 690 |
idlType = 'VARIANT' |
|---|
| 691 |
|
|---|
| 692 |
|
|---|
| 693 |
|
|---|
| 694 |
|
|---|
| 695 |
|
|---|
| 696 |
|
|---|
| 697 |
if i == 0: |
|---|
| 698 |
retvalParam.append('[out, retval] %s *%s' % (idlType, resultMetadata.Name)) |
|---|
| 699 |
|
|---|
| 700 |
|
|---|
| 701 |
|
|---|
| 702 |
|
|---|
| 703 |
|
|---|
| 704 |
elif not foundOptionalVariant and not foundDefaultvalue: |
|---|
| 705 |
inOutParams.append('[in, out] %s *%s' % (idlType, resultMetadata.Name)) |
|---|
| 706 |
|
|---|
| 707 |
|
|---|
| 708 |
|
|---|
| 709 |
|
|---|
| 710 |
else: |
|---|
| 711 |
inOutParams.append('[in, out, optional] VARIANT *%s' % (resultMetadata.Name)) |
|---|
| 712 |
|
|---|
| 713 |
|
|---|
| 714 |
|
|---|
| 715 |
idl = ' [id(%s), helpstring("%s Method")%s] HRESULT %s(%s);\n' % (dispID, methodMetadata.Name, varargAttribute, methodMetadata.Name, ', '.join(requiredInputParams + optionalInputParams + inOutParams + varargParam + retvalParam)) |
|---|
| 716 |
return idl |
|---|
| 717 |
|
|---|
| 718 |
|
|---|
| 719 |
def RegisterCOMServerUsingClassMetadata(moduleName, className): |
|---|
| 720 |
|
|---|
| 721 |
|
|---|
| 722 |
|
|---|
| 723 |
assert isinstance(moduleName, basestring), u'moduleName must be a string.' |
|---|
| 724 |
assert isinstance(className, basestring), u'className must be a string.' |
|---|
| 725 |
__import__(moduleName) |
|---|
| 726 |
classMetadata = sys.modules[moduleName].__dict__[className].__doc__.Obj |
|---|
| 727 |
|
|---|
| 728 |
|
|---|
| 729 |
|
|---|
| 730 |
import win32com.server.register |
|---|
| 731 |
try: |
|---|
| 732 |
win32com.server.register.RegisterServer(clsid=classMetadata.COMCLSID, |
|---|
| 733 |
pythonInstString=moduleName + '.' + className, |
|---|
| 734 |
desc=classMetadata.ShortDescription, |
|---|
| 735 |
progID=classMetadata.COMVersionIndependentProgID, |
|---|
| 736 |
verProgID=classMetadata.COMVersionDependentProgID, |
|---|
| 737 |
policy=__name__ + '.' + MetadataDesignatedWrapPolicy.__name__, |
|---|
| 738 |
dispatcher=__name__ + '.' + ExceptionTranslatingDispatcher.__name__) |
|---|
| 739 |
except Exception, e: |
|---|
| 740 |
return 'The Python win32com.server.register.RegisterServer function raised %s: %s' % (e.__class__.__name__, str(e)) |
|---|
| 741 |
|
|---|
| 742 |
return None |
|---|
| 743 |
|
|---|
| 744 |
|
|---|
| 745 |
def UnregisterCOMServerUsingClassMetadata(moduleName, className): |
|---|
| 746 |
|
|---|
| 747 |
|
|---|
| 748 |
|
|---|
| 749 |
assert isinstance(moduleName, basestring), u'moduleName must be a string.' |
|---|
| 750 |
assert isinstance(className, basestring), u'className must be a string.' |
|---|
| 751 |
__import__(moduleName) |
|---|
| 752 |
classMetadata = sys.modules[moduleName].__dict__[className].__doc__.Obj |
|---|
| 753 |
|
|---|
| 754 |
|
|---|
| 755 |
|
|---|
| 756 |
import win32com.server.register |
|---|
| 757 |
try: |
|---|
| 758 |
win32com.server.register.UnregisterServer(clsid=classMetadata.COMCLSID, |
|---|
| 759 |
progID=classMetadata.COMVersionIndependentProgID, |
|---|
| 760 |
verProgID=classMetadata.COMVersionDependentProgID) |
|---|
| 761 |
except: |
|---|
| 762 |
pass |
|---|
| 763 |
|
|---|
| 764 |
|
|---|
| 765 |
class COMAutomationObject(object): |
|---|
| 766 |
|
|---|
| 767 |
def __init__(self, progID, obj=None): |
|---|
| 768 |
assert isinstance(progID, basestring), u'progID must be a string.' |
|---|
| 769 |
assert isinstance(obj, (win32com.client.CDispatch, types.NoneType)), u'obj must be an instance of win32com.client.CDispatch, or None.' |
|---|
| 770 |
|
|---|
| 771 |
self._ProgID = unicode(progID) |
|---|
| 772 |
self._WrappedMethods = {} |
|---|
| 773 |
|
|---|
| 774 |
if obj is not None: |
|---|
| 775 |
self._Object = obj |
|---|
| 776 |
else: |
|---|
| 777 |
try: |
|---|
| 778 |
self._Object = win32com.client.Dispatch(progID) |
|---|
| 779 |
except pythoncom.com_error, (hr, msg, exc, arg): |
|---|
| 780 |
from GeoEco.Logging import Logger |
|---|
| 781 |
Logger.RaiseException(RuntimeError(_(u'Failed to instantiate the %(progid)s COM Automation object. win32com.client.Dispatch reported %(error)s') % {u'progid': progID, u'error': FormatCOMError(hr, msg, exc, arg)})) |
|---|
| 782 |
except Exception, e: |
|---|
| 783 |
from GeoEco.Logging import Logger |
|---|
| 784 |
Logger.RaiseException(RuntimeError(_(u'Failed to instantiate the %(progid)s COM Automation object. win32com.client.Dispatch reported %(error)s: %(msg)s') % {u'progid': progID, u'error': e.__class__.__name__, u'msg': unicode(e)})) |
|---|
| 785 |
|
|---|
| 786 |
self._LogDebug(_(u'%(progid)s COM Automation object 0x%(id)08X: Instantiated.') % {u'progid': self._ProgID, u'id': id(self._Object)}) |
|---|
| 787 |
|
|---|
| 788 |
def __del__(self): |
|---|
| 789 |
self._LogDebug(_(u'%(progid)s COM Automation object 0x%(id)08X: Last reference released.') % {u'progid': self._ProgID, u'id': id(self._Object)}) |
|---|
| 790 |
|
|---|
| 791 |
def _LogDebug(self, format, *args, **kwargs): |
|---|
| 792 |
try: |
|---|
| 793 |
logging.getLogger(u'GeoEco.COM').debug(format, *args, **kwargs) |
|---|
| 794 |
except: |
|---|
| 795 |
pass |
|---|
| 796 |
|
|---|
| 797 |
def _LogInfo(self, format, *args, **kwargs): |
|---|
| 798 |
try: |
|---|
| 799 |
logging.getLogger(u'GeoEco.COM').info(format, *args, **kwargs) |
|---|
| 800 |
except: |
|---|
| 801 |
pass |
|---|
| 802 |
|
|---|
| 803 |
def _LogWarning(self, format, *args, **kwargs): |
|---|
| 804 |
try: |
|---|
| 805 |
logging.getLogger(u'GeoEco.COM').warning(format, *args, **kwargs) |
|---|
| 806 |
except: |
|---|
| 807 |
pass |
|---|
| 808 |
|
|---|
| 809 |
def _LogError(self, format, *args, **kwargs): |
|---|
| 810 |
try: |
|---|
| 811 |
logging.getLogger(u'GeoEco.COM').error(format, *args, **kwargs) |
|---|
| 812 |
except: |
|---|
| 813 |
pass |
|---|
| 814 |
|
|---|
| 815 |
def __getattr__(self, name): |
|---|
| 816 |
assert isinstance(name, basestring), u'name must be a string.' |
|---|
| 817 |
|
|---|
| 818 |
|
|---|
| 819 |
|
|---|
| 820 |
|
|---|
| 821 |
|
|---|
| 822 |
|
|---|
| 823 |
if isinstance(name, types.StringType): |
|---|
| 824 |
name = unicode(name) |
|---|
| 825 |
if name.startswith(u'_'): |
|---|
| 826 |
return object.__getattribute__(self, name) |
|---|
| 827 |
|
|---|
| 828 |
|
|---|
| 829 |
|
|---|
| 830 |
|
|---|
| 831 |
|
|---|
| 832 |
|
|---|
| 833 |
if self._WrappedMethods.has_key(name.lower()): |
|---|
| 834 |
return new.instancemethod(self._WrappedMethods[name.lower()], self, COMAutomationObject) |
|---|
| 835 |
|
|---|
| 836 |
|
|---|
| 837 |
|
|---|
| 838 |
try: |
|---|
| 839 |
value = getattr(self._Object, name) |
|---|
| 840 |
except pythoncom.com_error, (hr, msg, exc, arg): |
|---|
| 841 |
from GeoEco.Logging import Logger |
|---|
| 842 |
Logger.RaiseException(AttributeError(_(u'Failed to get the %(attr)s property or method of the %(progid)s COM Automation object 0x%(id)08X. win32com.client.Dispatch reported %(error)s') % {u'attr': name, u'progid': self._ProgID, u'id': id(self._Object), u'error': FormatCOMError(hr, msg, exc, arg)})) |
|---|
| 843 |
except Exception, e: |
|---|
| 844 |
from GeoEco.Logging import Logger |
|---|
| 845 |
Logger.RaiseException(AttributeError(_(u'Failed to get the %(attr)s property or method of the %(progid)s COM Automation object 0x%(id)08X. win32com.client.Dispatch reported %(error)s: %(msg)s') % {u'attr': name, u'progid': self._ProgID, u'id': id(self._Object), u'error': e.__class__.__name__, u'msg': unicode(e)})) |
|---|
| 846 |
|
|---|
| 847 |
|
|---|
| 848 |
|
|---|
| 849 |
|
|---|
| 850 |
if isinstance(value, (types.MethodType, types.BuiltinFunctionType, types.BuiltinMethodType)): |
|---|
| 851 |
|
|---|
| 852 |
|
|---|
| 853 |
|
|---|
| 854 |
|
|---|
| 855 |
|
|---|
| 856 |
|
|---|
| 857 |
|
|---|
| 858 |
|
|---|
| 859 |
|
|---|
| 860 |
(args, varargs, varkw, defaults) = inspect.getargspec(value) |
|---|
| 861 |
sourceCode = 'def %s%s:\n' % (str(name), inspect.formatargspec(args, varargs, varkw, defaults)) |
|---|
| 862 |
sourceCode = re.subn('<PyOleMissing object at 0x........>', 'pythoncom.Missing', sourceCode)[0] |
|---|
| 863 |
sourceCode = re.subn('<PyOleEmpty object at 0x........>', 'pythoncom.Empty', sourceCode)[0] |
|---|
| 864 |
|
|---|
| 865 |
|
|---|
| 866 |
|
|---|
| 867 |
sourceCode = sourceCode + ' return self._InvokeMethod(self._Object.%s)\n' % name |
|---|
| 868 |
|
|---|
| 869 |
|
|---|
| 870 |
|
|---|
| 871 |
_locals = {} |
|---|
| 872 |
exec sourceCode in globals(), _locals |
|---|
| 873 |
|
|---|
| 874 |
|
|---|
| 875 |
|
|---|
| 876 |
self._WrappedMethods[name.lower()] = _locals[name] |
|---|
| 877 |
|
|---|
| 878 |
|
|---|
| 879 |
|
|---|
| 880 |
return new.instancemethod(_locals[name], self, COMAutomationObject) |
|---|
| 881 |
|
|---|
| 882 |
|
|---|
| 883 |
|
|---|
| 884 |
self._LogDebug(_(u'%(progid)s COM Automation object 0x%(id)08X: Get %(name)s returned %(value)s') % {u'progid': self._ProgID, u'id': id(self._Object), u'name': name, u'value': repr(value)}) |
|---|
| 885 |
|
|---|
| 886 |
|
|---|
| 887 |
|
|---|
| 888 |
|
|---|
| 889 |
value = self._FromPythonCOMType(value) |
|---|
| 890 |
|
|---|
| 891 |
|
|---|
| 892 |
|
|---|
| 893 |
return value |
|---|
| 894 |
|
|---|
| 895 |
def __setattr__(self, name, value): |
|---|
| 896 |
assert isinstance(name, basestring), u'name must be a string.' |
|---|
| 897 |
|
|---|
| 898 |
|
|---|
| 899 |
|
|---|
| 900 |
|
|---|
| 901 |
|
|---|
| 902 |
|
|---|
| 903 |
if isinstance(name, types.StringType): |
|---|
| 904 |
name = unicode(name) |
|---|
| 905 |
if name.startswith(u'_'): |
|---|
| 906 |
return object.__setattr__(self, name, value) |
|---|
| 907 |
|
|---|
| 908 |
|
|---|
| 909 |
|
|---|
| 910 |
|
|---|
| 911 |
|
|---|
| 912 |
value = self._ToPythonCOMType(value) |
|---|
| 913 |
|
|---|
| 914 |
|
|---|
| 915 |
|
|---|
| 916 |
try: |
|---|
| 917 |
setattr(self._Object, name, value) |
|---|
| 918 |
except pythoncom.com_error, (hr, msg, exc, arg): |
|---|
| 919 |
from GeoEco.Logging import Logger |
|---|
| 920 |
Logger.RaiseException(AttributeError(_(u'Failed to set the %(attr)s property of the %(progid)s COM Automation object 0x%(id)08X to %(value)s. win32com.client.Dispatch reported %(error)s') % {u'attr': name, u'progid': self._ProgID, u'id': id(self._Object), u'value': repr(value), u'error': FormatCOMError(hr, msg, exc, arg)})) |
|---|
| 921 |
except Exception, e: |
|---|
| 922 |
from GeoEco.Logging import Logger |
|---|
| 923 |
Logger.RaiseException(AttributeError(_(u'Failed to set the %(attr)s property of the %(progid)s COM Automation object 0x%(id)08X to %(value)s. win32com.client.Dispatch reported %(error)s: %(msg)s') % {u'attr': name, u'progid': self._ProgID, u'id': id(self._Object), u'value': repr(value), u'error': e.__class__.__name__, u'msg': unicode(e)})) |
|---|
| 924 |
|
|---|
| 925 |
|
|---|
| 926 |
|
|---|
| 927 |
if isinstance(value, COMAutomationObject): |
|---|
| 928 |
self._LogDebug(_(u'%(progid)s COM Automation object 0x%(id)08X: Set %(name)s to %(progid2)s COM Automation object 0x%(id2)08X.') % {u'progid': self._ProgID, u'id': id(self._Object), u'name': name, u'progid2': value._ProgID, u'id2': id(value._Object)}) |
|---|
| 929 |
else: |
|---|
| 930 |
self._LogDebug(_(u'%(progid)s COM Automation object 0x%(id)08X: Set %(name)s to %(value)s') % {u'progid': self._ProgID, u'id': id(self._Object), u'name': name, u'value': repr(value)}) |
|---|
| 931 |
|
|---|
| 932 |
def _InvokeMethod(self, method): |
|---|
| 933 |
|
|---|
| 934 |
|
|---|
| 935 |
|
|---|
| 936 |
|
|---|
| 937 |
(_args, _varargs, _varkw, _locals) = inspect.getargvalues(inspect.currentframe().f_back) |
|---|
| 938 |
del _args[0] |
|---|
| 939 |
|
|---|
| 940 |
for argName in _args: |
|---|
| 941 |
_locals[argName] = self._ToPythonCOMType(_locals[argName]) |
|---|
| 942 |
|
|---|
| 943 |
if _varargs is not None: |
|---|
| 944 |
_locals[_varargs] = self._ToPythonCOMType(_locals[_varargs]) |
|---|
| 945 |
|
|---|
| 946 |
|
|---|
| 947 |
|
|---|
| 948 |
sourceCode = 'self._Object.%s(' % method.__name__ |
|---|
| 949 |
for argName in _args: |
|---|
| 950 |
if not sourceCode.endswith('('): |
|---|
| 951 |
sourceCode = sourceCode + ', ' |
|---|
| 952 |
sourceCode = sourceCode + '%s=_locals[\'%s\']' % (argName, argName) |
|---|
| 953 |
if _varargs is not None: |
|---|
| 954 |
if not sourceCode.endswith('('): |
|---|
| 955 |
sourceCode = sourceCode + ', ' |
|---|
| 956 |
sourceCode = sourceCode + '*_locals[\'%s\'] ' % _varargs |
|---|
| 957 |
sourceCode = sourceCode + ')' |
|---|
| 958 |
|
|---|
| 959 |
|
|---|
| 960 |
|
|---|
| 961 |
self._LogDebug(_(u'%(progid)s COM Automation object 0x%(id)08X: Invoking %(name)s%(args)s.') % {u'progid': self._ProgID, u'id': id(self._Object), u'name': method.__name__, u'args': inspect.formatargvalues(_args, _varargs, _varkw, _locals)}) |
|---|
| 962 |
|
|---|
| 963 |
try: |
|---|
| 964 |
value = eval(sourceCode, globals(), locals()) |
|---|
| 965 |
except pythoncom.com_error, (hr, msg, exc, arg): |
|---|
| 966 |
from GeoEco.Logging import Logger |
|---|
| 967 |
Logger.RaiseException(RuntimeError(_(u'Execution of %(name)s%(args)s failed for the %(progid)s COM Automation object 0x%(id)08X. The function reported %(error)s') % {u'name': method.__name__, u'args': inspect.formatargvalues(_args, _varargs, _varkw, _locals), u'progid': self._ProgID, u'id': id(self._Object), u'error': FormatCOMError(hr, msg, exc, arg)})) |
|---|
| 968 |
except Exception, e: |
|---|
| 969 |
from GeoEco.Logging import Logger |
|---|
| 970 |
Logger.RaiseException(RuntimeError(_(u'Execution of %(name)s%(args)s failed for the %(progid)s COM Automation object 0x%(id)08X. win32com.client.Dispatch reported %(error)s: %(msg)s') % {u'name': method.__name__, u'args': inspect.formatargvalues(_args, _varargs, _varkw, _locals), u'progid': self._ProgID, u'id': id(self._Object), u'error': e.__class__.__name__, u'msg': unicode(e)})) |
|---|
| 971 |
|
|---|
| 972 |
|
|---|
| 973 |
|
|---|
| 974 |
self._LogDebug(_(u'%(progid)s COM Automation object 0x%(id)08X: %(method)s returned %(value)s') % {u'progid': self._ProgID, u'id': id(self._Object), u'method': method.__name__, u'value': repr(value)}) |
|---|
| 975 |
|
|---|
| 976 |
|
|---|
| 977 |
|
|---|
| 978 |
|
|---|
| 979 |
value = self._FromPythonCOMType(value) |
|---|
| 980 |
|
|---|
| 981 |
|
|---|
| 982 |
|
|---|
| 983 |
return value |
|---|
| 984 |
|
|---|
| 985 |
def _ToPythonCOMType(self, obj): |
|---|
| 986 |
if isinstance(obj, types.ListType): |
|---|
| 987 |
return self._ToPythonCOMTypeList(obj) |
|---|
| 988 |
if isinstance(obj, types.TupleType): |
|---|
| 989 |
l = list(obj) |
|---|
| 990 |
l = self._ToPythonCOMTypeList(l) |
|---|
| 991 |
return tuple(l) |
|---|
| 992 |
if isinstance(obj, types.StringType): |
|---|
| 993 |
return UserPreferredEncodingToUnicode(obj) |
|---|
| 994 |
if isinstance(obj, datetime.datetime): |
|---|
| 995 |
return pywintypes.Time((obj.year, obj.month, obj.day, obj.hour, obj.minute, obj.second, 0, 0, 0)) |
|---|
| 996 |
if isinstance(obj, COMAutomationObject): |
|---|
| 997 |
return obj._Object |
|---|
| 998 |
return obj |
|---|
| 999 |
|
|---|
| 1000 |
def _ToPythonCOMTypeList(self, obj): |
|---|
| 1001 |
for i in range(len(obj)): |
|---|
| 1002 |
obj[i] = self._ToPythonCOMType(obj[i]) |
|---|
| 1003 |
return obj |
|---|
| 1004 |
|
|---|
| 1005 |
def _FromPythonCOMType(self, obj): |
|---|
| 1006 |
if isinstance(obj, types.ListType): |
|---|
| 1007 |
return self._FromPythonCOMTypeList(obj) |
|---|
| 1008 |
if isinstance(obj, types.TupleType): |
|---|
| 1009 |
l = list(obj) |
|---|
| 1010 |
l = self._FromPythonCOMTypeList(l) |
|---|
| 1011 |
return tuple(l) |
|---|
| 1012 |
if isinstance(obj, pywintypes.TimeType): |
|---|
| 1013 |
return datetime.datetime(obj.year, obj.month, obj.day, obj.hour, obj.minute, obj.second, obj.msec) |
|---|
| 1014 |
if isinstance(obj, win32com.client.CDispatch): |
|---|
| 1015 |
return COMAutomationObject(u'<unnamed>', obj) |
|---|
| 1016 |
return obj |
|---|
| 1017 |
|
|---|
| 1018 |
def _FromPythonCOMTypeList(self, obj): |
|---|
| 1019 |
for i in range(len(obj)): |
|---|
| 1020 |
obj[i] = self._FromPythonCOMType(obj[i]) |
|---|
| 1021 |
return obj |
|---|
| 1022 |
|
|---|
| 1023 |
|
|---|
| 1024 |
def FormatCOMError(hr, msg, exc, arg): |
|---|
| 1025 |
|
|---|
| 1026 |
|
|---|
| 1027 |
|
|---|
| 1028 |
|
|---|
| 1029 |
|
|---|
| 1030 |
|
|---|
| 1031 |
|
|---|
| 1032 |
|
|---|
| 1033 |
|
|---|
| 1034 |
|
|---|
| 1035 |
|
|---|
| 1036 |
|
|---|
| 1037 |
|
|---|
| 1038 |
|
|---|
| 1039 |
|
|---|
| 1040 |
|
|---|
| 1041 |
|
|---|
| 1042 |
|
|---|
| 1043 |
|
|---|
| 1044 |
|
|---|
| 1045 |
|
|---|
| 1046 |
|
|---|
| 1047 |
|
|---|
| 1048 |
|
|---|
| 1049 |
if hr < 0: |
|---|
| 1050 |
hr = hr + 4294967296 |
|---|
| 1051 |
|
|---|
| 1052 |
|
|---|
| 1053 |
|
|---|
| 1054 |
s = u'COM Error 0x%08X' % hr |
|---|
| 1055 |
if isinstance(msg, basestring): |
|---|
| 1056 |
s = u'%s: "%s"' % (s, msg.strip()) |
|---|
| 1057 |
if not s.endswith(u'.'): |
|---|
| 1058 |
s += u'.' |
|---|
| 1059 |
if exc is not None: |
|---|
| 1060 |
moreInfo = [] |
|---|
| 1061 |
(wcode, source, description, helpFile, helpId, scode) = exc |
|---|
| 1062 |
if isinstance(source, basestring): |
|---|
| 1063 |
moreInfo.append(u'source="%s"' % source.strip()) |
|---|
| 1064 |
if isinstance(description, basestring): |
|---|
| 1065 |
moreInfo.append(u'description="%s"' % description.strip()) |
|---|
| 1066 |
if isinstance(scode, int) and scode != 0: |
|---|
| 1067 |
scodeMsg = None |
|---|
| 1068 |
try: |
|---|
| 1069 |
import win32api |
|---|
| 1070 |
scodeMsg = win32api.FormatMessage(scode) |
|---|
| 1071 |
except: |
|---|
| 1072 |
pass |
|---|
| 1073 |
if scode < 0: |
|---|
| 1074 |
scode += 4294967296 |
|---|
| 1075 |
if scodeMsg is not None: |
|---|
| 1076 |
moreInfo.append(u'scode=0x%08X ("%s")' % (scode, scodeMsg)) |
|---|
| 1077 |
else: |
|---|
| 1078 |
moreInfo.append(u'scode=0x%08X' % scode) |
|---|
| 1079 |
if isinstance(wcode, int) and wcode != 0: |
|---|
| 1080 |
moreInfo.append(u'wcode=%i' % wcode) |
|---|
| 1081 |
s += u' Error details: ' + u', '.join(moreInfo) |
|---|
| 1082 |
if not s.endswith(u'.'): |
|---|
| 1083 |
s += u'.' |
|---|
| 1084 |
if isinstance(helpFile, basestring) and isinstance(helpId, int): |
|---|
| 1085 |
s = _(u'%s More information may be found under topic %i of help file "%s".') % (s, helpId, helpFile) |
|---|
| 1086 |
|
|---|
| 1087 |
return s |
|---|
| 1088 |
|
|---|
| 1089 |
|
|---|
| 1090 |
|
|---|
| 1091 |
|
|---|
| 1092 |
|
|---|
| 1093 |
|
|---|
| 1094 |
__all__ = ['TypeLibraryGUID', |
|---|
| 1095 |
'TypeLibraryVersion', |
|---|
| 1096 |
'TypeLibraryLCID', |
|---|
| 1097 |
'ValidateClassMetadata', |
|---|
| 1098 |
'GetIDLInterfaceDefinitionFromMetadata', |
|---|
| 1099 |
'GetIDLPropertyDefinitionFromMetadata', |
|---|
| 1100 |
'GetIDLMethodDefinitionFromMetadata', |
|---|
| 1101 |
'RegisterCOMServerUsingClassMetadata', |
|---|
| 1102 |
'UnregisterCOMServerUsingClassMetadata', |
|---|
| 1103 |
'COMAutomationObject', |
|---|
| 1104 |
'FormatCOMError'] |
|---|
| 1105 |
|
|---|
| 1106 |
else: |
|---|
| 1107 |
__all__ = [] |
|---|