Skip to content

Commit f2641a5

Browse files
authored
add annotations (#378)
1 parent 39af40d commit f2641a5

3 files changed

Lines changed: 298 additions & 164 deletions

File tree

comtypes/tools/tlbparser.py

Lines changed: 56 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,20 @@
11
from __future__ import print_function
22
import os
33
import sys
4-
from ctypes import windll
5-
from ctypes import c_void_p
6-
from ctypes import sizeof
7-
from ctypes import alignment
8-
9-
from comtypes import automation
10-
from comtypes import typeinfo
11-
from comtypes import COMError
4+
from ctypes import alignment, c_void_p, sizeof, windll
5+
6+
from comtypes import automation, COMError, TYPE_CHECKING, typeinfo
127
from comtypes.tools import typedesc
138
from comtypes.client._code_cache import _get_module_filename
149

10+
if TYPE_CHECKING:
11+
from typing import (
12+
Any, Callable, Dict, List, Optional, Type, TypeVar, Tuple,
13+
Union as _UnionT,
14+
)
15+
from ctypes import _CData, _Pointer
16+
from comtypes import hints
17+
1518

1619
# Is the process 64-bit?
1720
is_64bits = sys.maxsize > 2**32
@@ -105,25 +108,26 @@ def midlSAFEARRAY(typ):
105108
################################################################
106109

107110
class Parser(object):
111+
if TYPE_CHECKING:
112+
tlib = hints.AnnoField() # type: typeinfo.ITypeLib
113+
items = hints.AnnoField() # type: Dict[str, Any]
108114

109115
def make_type(self, tdesc, tinfo):
110-
try:
116+
# type: (typeinfo.TYPEDESC, typeinfo.ITypeInfo) -> Any
117+
if tdesc.vt in COMTYPES:
111118
return COMTYPES[tdesc.vt]
112-
except KeyError:
113-
pass
114-
115119
if tdesc.vt == automation.VT_CARRAY:
116-
typ = self.make_type(tdesc._.lpadesc[0].tdescElem, tinfo)
117-
for i in range(tdesc._.lpadesc[0].cDims):
118-
typ = typedesc.ArrayType(typ,
119-
tdesc._.lpadesc[0].rgbounds[i].lLbound,
120-
tdesc._.lpadesc[0].rgbounds[i].cElements-1)
120+
arraydesc = tdesc._.lpadesc[0] # type: typeinfo.tagARRAYDESC
121+
typ = self.make_type(arraydesc.tdescElem, tinfo)
122+
for i in range(arraydesc.cDims):
123+
typ = typedesc.ArrayType(
124+
typ, arraydesc.rgbounds[i].lLbound, arraydesc.rgbounds[i].cElements-1
125+
)
121126
return typ
122-
123127
elif tdesc.vt == automation.VT_PTR:
124-
typ = self.make_type(tdesc._.lptdesc[0], tinfo)
128+
ptrdesc = tdesc._.lptdesc[0] # type: typeinfo.TYPEDESC
129+
typ = self.make_type(ptrdesc, tinfo)
125130
return PTR(typ)
126-
127131
elif tdesc.vt == automation.VT_USERDEFINED:
128132
try:
129133
ti = tinfo.GetRefTypeInfo(tdesc._.hreftype)
@@ -136,26 +140,24 @@ def make_type(self, tdesc, tinfo):
136140
(tlib_name, details, type_name)
137141
import warnings
138142
warnings.warn(message, UserWarning);
139-
result = typedesc.Structure(type_name,
140-
align=8,
141-
members=[], bases=[],
142-
size=0)
143+
result = typedesc.Structure(
144+
type_name, align=8, members=[], bases=[], size=0
145+
)
143146
return result
144147
result = self.parse_typeinfo(ti)
145148
assert result is not None, ti.GetDocumentation(-1)[0]
146149
return result
147-
148150
elif tdesc.vt == automation.VT_SAFEARRAY:
149151
# SAFEARRAY(<type>), see Don Box pp.331f
150-
itemtype = self.make_type(tdesc._.lptdesc[0], tinfo)
151-
return midlSAFEARRAY(itemtype)
152-
152+
safearraydesc = tdesc._.lptdesc[0] # type: typeinfo.TYPEDESC
153+
return midlSAFEARRAY(self.make_type(safearraydesc, tinfo))
153154
raise NotImplementedError(tdesc.vt)
154155

155156
################################################################
156157

157158
# TKIND_ENUM = 0
158159
def ParseEnum(self, tinfo, ta):
160+
# type: (typeinfo.ITypeInfo, typeinfo.TYPEATTR) -> typedesc.Enumeration
159161
ta = tinfo.GetTypeAttr()
160162
enum_name = tinfo.GetDocumentation(-1)[0]
161163
enum = typedesc.Enumeration(enum_name, 32, 32)
@@ -165,13 +167,14 @@ def ParseEnum(self, tinfo, ta):
165167
vd = tinfo.GetVarDesc(i)
166168
name = tinfo.GetDocumentation(vd.memid)[0]
167169
assert vd.varkind == typeinfo.VAR_CONST
168-
num_val = vd._.lpvarValue[0].value
170+
num_val = vd._.lpvarValue[0].value # type: int
169171
v = typedesc.EnumValue(name, num_val, enum)
170172
enum.add_value(v)
171173
return enum
172174

173175
# TKIND_RECORD = 1
174176
def ParseRecord(self, tinfo, ta):
177+
# type: (typeinfo.ITypeInfo, typeinfo.TYPEATTR) -> typedesc.Structure
175178
members = [] # will be filled later
176179
struct_name, doc, helpcntext, helpfile = tinfo.GetDocumentation(-1)
177180
struct = typedesc.Structure(struct_name,
@@ -211,6 +214,7 @@ def ParseRecord(self, tinfo, ta):
211214

212215
# TKIND_MODULE = 2
213216
def ParseModule(self, tinfo, ta):
217+
# type: (typeinfo.ITypeInfo, typeinfo.TYPEATTR) -> None
214218
assert 0 == ta.cImplTypes
215219
# functions
216220
for i in range(ta.cFuncs):
@@ -253,6 +257,7 @@ def ParseModule(self, tinfo, ta):
253257

254258
# TKIND_INTERFACE = 3
255259
def ParseInterface(self, tinfo, ta):
260+
# type: (typeinfo.ITypeInfo, typeinfo.TYPEATTR) -> Optional[typedesc.ComInterface]
256261
itf_name, itf_doc = tinfo.GetDocumentation(-1)[0:2]
257262
assert ta.cImplTypes <= 1
258263
if ta.cImplTypes == 0 and itf_name != "IUnknown":
@@ -284,7 +289,6 @@ def ParseInterface(self, tinfo, ta):
284289
members = []
285290
for i in range(ta.cFuncs):
286291
fd = tinfo.GetFuncDesc(i)
287-
## func_name = tinfo.GetDocumentation(fd.memid)[0]
288292
func_name, func_doc = tinfo.GetDocumentation(fd.memid)[:2]
289293
assert fd.funckind == typeinfo.FUNC_PUREVIRTUAL
290294
returns = self.make_type(fd.elemdescFunc.tdesc, tinfo)
@@ -295,15 +299,14 @@ def ParseInterface(self, tinfo, ta):
295299
flags = self.func_flags(fd.wFuncFlags)
296300
flags += self.inv_kind(fd.invkind)
297301
mth = typedesc.ComMethod(fd.invkind, fd.memid, func_name, returns, flags, func_doc)
298-
mth.oVft = fd.oVft
299302
for p in range(fd.cParams):
300303
typ = self.make_type(fd.lprgelemdescParam[p].tdesc, tinfo)
301304
name = names[p+1]
302305
flags = fd.lprgelemdescParam[p]._.paramdesc.wParamFlags
303306
if flags & typeinfo.PARAMFLAG_FHASDEFAULT:
304307
# XXX should be handled by VARIANT itself
305308
var = fd.lprgelemdescParam[p]._.paramdesc.pparamdescex[0].varDefaultValue
306-
default = var.value
309+
default = var.value # type: Any
307310
else:
308311
default = None
309312
mth.add_argument(typ, name, self.param_flags(flags), default)
@@ -317,6 +320,7 @@ def ParseInterface(self, tinfo, ta):
317320

318321
# TKIND_DISPATCH = 4
319322
def ParseDispatch(self, tinfo, ta):
323+
# type: (typeinfo.ITypeInfo, typeinfo.TYPEATTR) -> typedesc.DispInterface
320324
itf_name, doc = tinfo.GetDocumentation(-1)[0:2]
321325
assert ta.cImplTypes == 1
322326

@@ -372,27 +376,29 @@ def ParseDispatch(self, tinfo, ta):
372376
flags += self.inv_kind(fd.invkind)
373377
mth = typedesc.DispMethod(fd.memid, fd.invkind, func_name, returns, flags, func_doc)
374378
for p in range(fd.cParams):
375-
typ = self.make_type(fd.lprgelemdescParam[p].tdesc, tinfo)
379+
descparam = fd.lprgelemdescParam[p]
380+
typ = self.make_type(descparam.tdesc, tinfo)
376381
name = names[p+1]
377-
flags = fd.lprgelemdescParam[p]._.paramdesc.wParamFlags
382+
flags = descparam._.paramdesc.wParamFlags
378383
if flags & typeinfo.PARAMFLAG_FHASDEFAULT:
379-
var = fd.lprgelemdescParam[p]._.paramdesc.pparamdescex[0].varDefaultValue
380-
default = var.value
384+
var = descparam._.paramdesc.pparamdescex[0].varDefaultValue # type: ignore
385+
default = var.value # type: Any
381386
else:
382387
default = None
383388
mth.add_argument(typ, name, self.param_flags(flags), default)
384389
itf.members.append(mth)
385-
386390
return itf
387391

388392
def inv_kind(self, invkind):
393+
# type: (int) -> List[str]
389394
NAMES = {automation.DISPATCH_METHOD: [],
390395
automation.DISPATCH_PROPERTYPUT: ["propput"],
391396
automation.DISPATCH_PROPERTYPUTREF: ["propputref"],
392397
automation.DISPATCH_PROPERTYGET: ["propget"]}
393398
return NAMES[invkind]
394399

395400
def func_flags(self, flags):
401+
# type: (int) -> List[str]
396402
# map FUNCFLAGS values to idl attributes
397403
NAMES = {typeinfo.FUNCFLAG_FRESTRICTED: "restricted",
398404
typeinfo.FUNCFLAG_FSOURCE: "source",
@@ -410,6 +416,7 @@ def func_flags(self, flags):
410416
return [NAMES[bit] for bit in NAMES if bit & flags]
411417

412418
def param_flags(self, flags):
419+
# type: (int) -> List[str]
413420
# map PARAMFLAGS values to idl attributes
414421
NAMES = {typeinfo.PARAMFLAG_FIN: "in",
415422
typeinfo.PARAMFLAG_FOUT: "out",
@@ -422,6 +429,7 @@ def param_flags(self, flags):
422429
return [NAMES[bit] for bit in NAMES if bit & flags]
423430

424431
def coclass_type_flags(self, flags):
432+
# type: (int) -> List[str]
425433
# map TYPEFLAGS values to idl attributes
426434
NAMES = {typeinfo.TYPEFLAG_FAPPOBJECT: "appobject",
427435
# typeinfo.TYPEFLAG_FCANCREATE:
@@ -444,6 +452,7 @@ def coclass_type_flags(self, flags):
444452
[NEGATIVE_NAMES[bit] for bit in NEGATIVE_NAMES if not (bit & flags)]
445453

446454
def interface_type_flags(self, flags):
455+
# type: (int) -> List[str]
447456
# map TYPEFLAGS values to idl attributes
448457
NAMES = {typeinfo.TYPEFLAG_FAPPOBJECT: "appobject",
449458
# typeinfo.TYPEFLAG_FCANCREATE:
@@ -466,6 +475,7 @@ def interface_type_flags(self, flags):
466475
[NEGATIVE_NAMES[bit] for bit in NEGATIVE_NAMES if not (bit & flags)]
467476

468477
def var_flags(self, flags):
478+
# type: (int) -> List[str]
469479
NAMES = {typeinfo.VARFLAG_FREADONLY: "readonly",
470480
typeinfo.VARFLAG_FSOURCE: "source",
471481
typeinfo.VARFLAG_FBINDABLE: "bindable",
@@ -482,9 +492,9 @@ def var_flags(self, flags):
482492
}
483493
return [NAMES[bit] for bit in NAMES if bit & flags]
484494

485-
486495
# TKIND_COCLASS = 5
487496
def ParseCoClass(self, tinfo, ta):
497+
# type: (typeinfo.ITypeInfo, typeinfo.TYPEATTR) -> typedesc.CoClass
488498
# possible ta.wTypeFlags: helpstring, helpcontext, licensed,
489499
# version, control, hidden, and appobject
490500
coclass_name, doc = tinfo.GetDocumentation(-1)[0:2]
@@ -507,6 +517,7 @@ def ParseCoClass(self, tinfo, ta):
507517

508518
# TKIND_ALIAS = 6
509519
def ParseAlias(self, tinfo, ta):
520+
# type: (typeinfo.ITypeInfo, typeinfo.TYPEATTR) -> typedesc.Typedef
510521
name = tinfo.GetDocumentation(-1)[0]
511522
typ = self.make_type(ta.tdescAlias, tinfo)
512523
alias = typedesc.Typedef(name, typ)
@@ -515,6 +526,7 @@ def ParseAlias(self, tinfo, ta):
515526

516527
# TKIND_UNION = 7
517528
def ParseUnion(self, tinfo, ta):
529+
# type: (typeinfo.ITypeInfo, typeinfo.TYPEATTR) -> typedesc.Union
518530
union_name, doc, helpcntext, helpfile = tinfo.GetDocumentation(-1)
519531
members = []
520532
union = typedesc.Union(union_name,
@@ -549,13 +561,15 @@ def ParseUnion(self, tinfo, ta):
549561
################################################################
550562

551563
def _typelib_module(self, tlib=None):
564+
# type: (Optional[typeinfo.ITypeLib]) -> str
552565
if tlib is None:
553566
tlib = self.tlib
554567
# return a string that uniquely identifies a typelib.
555568
# The string doesn't have any meaning outside this instance.
556569
return str(tlib.GetLibAttr())
557570

558571
def _register(self, name, value, tlib=None):
572+
# type: (Optional[str], Any, Optional[typeinfo.ITypeLib]) -> None
559573
modname = self._typelib_module(tlib)
560574
fullname = "%s.%s" % (modname, name)
561575
if fullname in self.items:
@@ -567,6 +581,7 @@ def _register(self, name, value, tlib=None):
567581
self.items[fullname] = value
568582

569583
def parse_typeinfo(self, tinfo):
584+
# type: (typeinfo.ITypeInfo) -> Any
570585
name = tinfo.GetDocumentation(-1)[0]
571586
modname = self._typelib_module()
572587
try:
@@ -579,11 +594,9 @@ def parse_typeinfo(self, tinfo):
579594
ta = tinfo.GetTypeAttr()
580595
size = ta.cbSizeInstance * 8
581596
align = ta.cbAlignment * 8
582-
typ = typedesc.External(tlib,
583-
name,
584-
size,
585-
align,
586-
tlib.GetDocumentation(-1)[:2])
597+
typ = typedesc.External(
598+
tlib, name, size, align, tlib.GetDocumentation(-1)[:2]
599+
)
587600
self._register(name, typ, tlib)
588601
return typ
589602

comtypes/tools/typedesc.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ def __init__(self, typ):
5555
class ComMethod(object):
5656
# custom COM method, parsed from typelib
5757
def __init__(self, invkind, memid, name, returns, idlflags, doc):
58-
# type: (int, int, str, Typedef, List[str], Optional[str]) -> None
58+
# type: (int, int, str, Any, List[str], Optional[str]) -> None
5959
self.invkind = invkind
6060
self.name = name
6161
self.returns = returns
@@ -71,7 +71,7 @@ def add_argument(self, typ, name, idlflags, default):
7171
class DispMethod(object):
7272
# dispatchable COM method, parsed from typelib
7373
def __init__(self, dispid, invkind, name, returns, idlflags, doc):
74-
# type: (int, int, str, Typedef, List[str], Optional[str]) -> None
74+
# type: (int, int, str, Any, List[str], Optional[str]) -> None
7575
self.dispid = dispid
7676
self.invkind = invkind
7777
self.name = name

0 commit comments

Comments
 (0)