Skip to content

Commit 54e119d

Browse files
authored
Add typehints to codegenerator and typedesc (#369)
* add type annotations to `typedesc` * add type annotations to `codegenerator`
1 parent 083e358 commit 54e119d

File tree

3 files changed

+100
-27
lines changed

3 files changed

+100
-27
lines changed

comtypes/tools/codegenerator.py

Lines changed: 41 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,28 @@
11
# Code generator to generate code for everything contained in COM type
22
# libraries.
33
from __future__ import print_function
4+
import ctypes
5+
import keyword
6+
import logging
47
import os
58
import sys
9+
import textwrap
610
if sys.version_info >= (3, 0):
711
import io
812
else:
913
import cStringIO as io
10-
import keyword
11-
import ctypes
12-
import textwrap
1314

14-
from comtypes.tools import tlbparser, typedesc
1515
import comtypes
16+
from comtypes import TYPE_CHECKING
17+
from comtypes.tools import tlbparser, typedesc
1618
import comtypes.typeinfo
1719

20+
if TYPE_CHECKING:
21+
from typing import List, Union as _UnionT
22+
23+
1824
version = comtypes.__version__
1925

20-
import logging
2126
logger = logging.getLogger(__name__)
2227

2328
__warn_on_munge__ = __debug__
@@ -343,14 +348,13 @@ def _to_docstring(self, orig, depth=1):
343348
repled = orig.replace("\\", r"\\").replace("\"", r"'")
344349
return '%s"""%s"""' % (indent, repled)
345350

346-
_arraytypes = 0
347351
def ArrayType(self, tp):
348-
self._arraytypes += 1
352+
# type: (typedesc.ArrayType) -> None
349353
self.generate(get_real_type(tp.typ))
350354
self.generate(tp.typ)
351355

352-
_enumvalues = 0
353356
def EnumValue(self, tp):
357+
# type: (typedesc.EnumValue) -> None
354358
self.last_item_class = False
355359
value = int(tp.value)
356360
if keyword.iskeyword(tp.name):
@@ -360,11 +364,9 @@ def EnumValue(self, tp):
360364
tp_name = self._to_type_name(tp)
361365
print("%s = %d" % (tp_name, value), file=self.stream)
362366
self.names.add(tp_name)
363-
self._enumvalues += 1
364367

365-
_enumtypes = 0
366368
def Enumeration(self, tp):
367-
self._enumtypes += 1
369+
# type: (typedesc.Enumeration) -> None
368370
self.last_item_class = False
369371
if tp.name:
370372
print("# values for enumeration '%s'" % tp.name, file=self.stream)
@@ -380,10 +382,9 @@ def Enumeration(self, tp):
380382
print("%s = c_int # enum" % tp.name, file=self.stream)
381383
self.names.add(tp.name)
382384

383-
_typedefs = 0
384385
def Typedef(self, tp):
385-
self._typedefs += 1
386-
if type(tp.typ) in (typedesc.Structure, typedesc.Union):
386+
# type: (typedesc.Typedef) -> None
387+
if isinstance(tp.typ, (typedesc.Structure, typedesc.Union)):
387388
self.generate(tp.typ.get_head())
388389
self.more.add(tp.typ)
389390
else:
@@ -398,9 +399,11 @@ def Typedef(self, tp):
398399
self.names.add(tp.name)
399400

400401
def FundamentalType(self, item):
402+
# type: (typedesc.FundamentalType) -> None
401403
pass # we should check if this is known somewhere
402404

403405
def StructureHead(self, head):
406+
# type: (typedesc.StructureHead) -> None
404407
for struct in head.struct.bases:
405408
self.generate(struct.get_head())
406409
self.more.add(struct)
@@ -479,17 +482,20 @@ def StructureHead(self, head):
479482
print(file=self.stream)
480483
self.names.add(head.struct.name)
481484

482-
_structures = 0
483485
def Structure(self, struct):
484-
self._structures += 1
486+
# type: (typedesc.Structure) -> None
485487
self.generate(struct.get_head())
486488
self.generate(struct.get_body())
487489

488-
Union = Structure
490+
def Union(self, union):
491+
# type: (typedesc.Union) -> None
492+
self.generate(union.get_head())
493+
self.generate(union.get_body())
489494

490495
def StructureBody(self, body):
491-
fields = []
492-
methods = []
496+
# type: (typedesc.StructureBody) -> None
497+
fields = [] # type: List[typedesc.Field]
498+
methods = [] # type: List[typedesc.Method]
493499
for m in body.struct.members:
494500
if type(m) is typedesc.Field:
495501
fields.append(m)
@@ -596,8 +602,7 @@ def StructureBody(self, body):
596602
# top-level typedesc generators
597603
#
598604
def TypeLib(self, lib):
599-
# lib.name, lib.gui, lib.major, lib.minor, lib.doc
600-
605+
# type: (typedesc.TypeLib) -> None
601606
# Hm, in user code we have to write:
602607
# class MyServer(COMObject, ...):
603608
# _com_interfaces_ = [MyTypeLib.IInterface]
@@ -624,25 +629,27 @@ def TypeLib(self, lib):
624629
print(file=self.stream)
625630

626631
def External(self, ext):
632+
# type: (typedesc.External) -> None
627633
modname = name_wrapper_module(ext.tlib)
628634
if modname not in self.imports:
629635
self.externals.append(ext.tlib)
630636
self.imports.add(modname)
631637

632638
def Constant(self, tp):
639+
# type: (typedesc.Constant) -> None
633640
self.last_item_class = False
634641
print("%s = %r # Constant %s" % (tp.name,
635642
tp.value,
636643
self._to_type_name(tp.typ)), file=self.stream)
637644
self.names.add(tp.name)
638645

639646
def SAFEARRAYType(self, sa):
647+
# type: (typedesc.SAFEARRAYType) -> None
640648
self.generate(sa.typ)
641649
self.imports.add("comtypes.automation", "_midlSAFEARRAY")
642650

643-
_pointertypes = 0
644651
def PointerType(self, tp):
645-
self._pointertypes += 1
652+
# type: (typedesc.PointerType) -> None
646653
if type(tp.typ) is typedesc.ComInterface:
647654
# this defines the class
648655
self.generate(tp.typ.get_head())
@@ -667,6 +674,7 @@ def PointerType(self, tp):
667674
self.declarations.add("WSTRING", "c_wchar_p")
668675

669676
def CoClass(self, coclass):
677+
# type: (typedesc.CoClass) -> None
670678
self.imports.add("comtypes", "GUID")
671679
self.imports.add("comtypes", "CoClass")
672680
if not self.last_item_class:
@@ -719,11 +727,13 @@ def CoClass(self, coclass):
719727
self.names.add(coclass.name)
720728

721729
def ComInterface(self, itf):
730+
# type: (typedesc.ComInterface) -> None
722731
self.generate(itf.get_head())
723732
self.generate(itf.get_body())
724733
self.names.add(itf.name)
725734

726735
def _is_enuminterface(self, itf):
736+
# type: (typedesc.ComInterface) -> bool
727737
# Check if this is an IEnumXXX interface
728738
if not itf.name.startswith("IEnum"):
729739
return False
@@ -734,6 +744,7 @@ def _is_enuminterface(self, itf):
734744
return True
735745

736746
def ComInterfaceHead(self, head):
747+
# type: (typedesc.ComInterfaceHead) -> None
737748
if head.itf.name in self.known_symbols:
738749
return
739750
base = head.itf.base
@@ -786,6 +797,7 @@ def ComInterfaceHead(self, head):
786797
print(file=self.stream)
787798

788799
def ComInterfaceBody(self, body):
800+
# type: (typedesc.ComInterfaceBody) -> None
789801
# The base class must be fully generated, including the
790802
# _methods_ list.
791803
self.generate(body.itf.base)
@@ -856,11 +868,13 @@ def ComInterfaceBody(self, body):
856868
print("#", file=self.stream)
857869

858870
def DispInterface(self, itf):
871+
# type: (typedesc.DispInterface) -> None
859872
self.generate(itf.get_head())
860873
self.generate(itf.get_body())
861874
self.names.add(itf.name)
862875

863876
def DispInterfaceHead(self, head):
877+
# type: (typedesc.DispInterfaceHead) -> None
864878
self.generate(head.itf.base)
865879
basename = self._to_type_name(head.itf.base)
866880

@@ -883,6 +897,7 @@ def DispInterfaceHead(self, head):
883897
print(file=self.stream)
884898

885899
def DispInterfaceBody(self, body):
900+
# type: (typedesc.DispInterfaceBody) -> None
886901
# make sure we can generate the body
887902
for m in body.itf.members:
888903
if isinstance(m, typedesc.DispMethod):
@@ -913,6 +928,7 @@ def DispInterfaceBody(self, body):
913928
# non-toplevel method generators
914929
#
915930
def make_ComMethod(self, m, isdual):
931+
# type: (typedesc.ComMethod, bool) -> None
916932
self.imports.add("comtypes", "COMMETHOD")
917933
# typ, name, idlflags, default
918934
if isdual:
@@ -1028,6 +1044,7 @@ def make_ComMethod(self, m, isdual):
10281044
print(" ),", file=self.stream)
10291045

10301046
def make_DispMethod(self, m):
1047+
# type: (typedesc.DispMethod) -> None
10311048
self.imports.add("comtypes", "DISPMETHOD")
10321049
self.imports.add("comtypes", "dispid")
10331050
idlflags = [dispid(m.dispid)] + m.idlflags
@@ -1094,6 +1111,7 @@ def make_DispMethod(self, m):
10941111
print(" ),", file=self.stream)
10951112

10961113
def make_DispProperty(self, prop):
1114+
# type: (typedesc.DispProperty) -> None
10971115
self.imports.add("comtypes", "DISPPROPERTY")
10981116
self.imports.add("comtypes", "dispid")
10991117
idlflags = [dispid(prop.dispid)] + prop.idlflags

comtypes/tools/typedesc.py

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,17 @@
22
# in typedesc_base
33

44
import ctypes
5+
from comtypes import TYPE_CHECKING
6+
from comtypes.typeinfo import ITypeLib, TLIBATTR
57
from comtypes.tools.typedesc_base import *
68

9+
if TYPE_CHECKING:
10+
from typing import Any, List, Optional, Tuple, Union as _UnionT
11+
12+
713
class TypeLib(object):
814
def __init__(self, name, guid, major, minor, doc=None):
15+
# type: (str, str, int, int, Optional[str]) -> None
916
self.name = name
1017
self.guid = guid
1118
self.major = major
@@ -17,12 +24,14 @@ def __repr__(self):
1724

1825
class Constant(object):
1926
def __init__(self, name, typ, value):
27+
# type: (str, _UnionT[Typedef, FundamentalType], Any) -> None
2028
self.name = name
2129
self.typ = typ
2230
self.value = value
2331

2432
class External(object):
2533
def __init__(self, tlib, name, size, align, docs=None):
34+
# type: (ITypeLib, str, int, int, Optional[Tuple[str, str]]) -> None
2635
# the type library containing the symbol
2736
self.tlib = tlib
2837
# name of symbol
@@ -33,45 +42,52 @@ def __init__(self, tlib, name, size, align, docs=None):
3342
self.docs = docs
3443

3544
def get_head(self):
45+
# type: () -> External
3646
# codegen might call this
3747
return self
3848

3949
class SAFEARRAYType(object):
4050
def __init__(self, typ):
51+
# type: (Any) -> None
4152
self.typ = typ
4253
self.align = self.size = ctypes.sizeof(ctypes.c_void_p) * 8
4354

4455
class ComMethod(object):
4556
# custom COM method, parsed from typelib
4657
def __init__(self, invkind, memid, name, returns, idlflags, doc):
58+
# type: (int, int, str, Typedef, List[str], Optional[str]) -> None
4759
self.invkind = invkind
4860
self.name = name
4961
self.returns = returns
5062
self.idlflags = idlflags
5163
self.memid = memid
5264
self.doc = doc
53-
self.arguments = []
65+
self.arguments = [] # type: List[Tuple[Any, str, List[str], Optional[Any]]]
5466

5567
def add_argument(self, typ, name, idlflags, default):
68+
# type: (Any, str, List[str], Optional[Any]) -> None
5669
self.arguments.append((typ, name, idlflags, default))
5770

5871
class DispMethod(object):
5972
# dispatchable COM method, parsed from typelib
6073
def __init__(self, dispid, invkind, name, returns, idlflags, doc):
74+
# type: (int, int, str, Typedef, List[str], Optional[str]) -> None
6175
self.dispid = dispid
6276
self.invkind = invkind
6377
self.name = name
6478
self.returns = returns
6579
self.idlflags = idlflags
6680
self.doc = doc
67-
self.arguments = []
81+
self.arguments = [] # type: List[Tuple[Any, str, List[str], Optional[Any]]]
6882

6983
def add_argument(self, typ, name, idlflags, default):
84+
# type: (Any, str, List[str], Optional[Any]) -> None
7085
self.arguments.append((typ, name, idlflags, default))
7186

7287
class DispProperty(object):
7388
# dispatchable COM property, parsed from typelib
7489
def __init__(self, dispid, name, typ, idlflags, doc):
90+
# type: (int, str, Any, List[str], Optional[Any]) -> None
7591
self.dispid = dispid
7692
self.name = name
7793
self.typ = typ
@@ -80,14 +96,17 @@ def __init__(self, dispid, name, typ, idlflags, doc):
8096

8197
class DispInterfaceHead(object):
8298
def __init__(self, itf):
99+
# type: (DispInterface) -> None
83100
self.itf = itf
84101

85102
class DispInterfaceBody(object):
86103
def __init__(self, itf):
104+
# type: (DispInterface) -> None
87105
self.itf = itf
88106

89107
class DispInterface(object):
90108
def __init__(self, name, members, base, iid, idlflags):
109+
# type: (str, List[_UnionT[DispMethod, DispProperty]], Any, str, List[str]) -> None
91110
self.name = name
92111
self.members = members
93112
self.base = base
@@ -97,21 +116,26 @@ def __init__(self, name, members, base, iid, idlflags):
97116
self.itf_body = DispInterfaceBody(self)
98117

99118
def get_body(self):
119+
# type: () -> DispInterfaceBody
100120
return self.itf_body
101121

102122
def get_head(self):
123+
# type: () -> DispInterfaceHead
103124
return self.itf_head
104125

105126
class ComInterfaceHead(object):
106127
def __init__(self, itf):
128+
# type: (ComInterface) -> None
107129
self.itf = itf
108130

109131
class ComInterfaceBody(object):
110132
def __init__(self, itf):
133+
# type: (ComInterface) -> None
111134
self.itf = itf
112135

113136
class ComInterface(object):
114137
def __init__(self, name, members, base, iid, idlflags):
138+
# type: (str, List[ComMethod], Any, str, List[str]) -> None
115139
self.name = name
116140
self.members = members
117141
self.base = base
@@ -121,18 +145,22 @@ def __init__(self, name, members, base, iid, idlflags):
121145
self.itf_body = ComInterfaceBody(self)
122146

123147
def get_body(self):
148+
# type: () -> ComInterfaceBody
124149
return self.itf_body
125150

126151
def get_head(self):
152+
# type: () -> ComInterfaceHead
127153
return self.itf_head
128154

129155
class CoClass(object):
130156
def __init__(self, name, clsid, idlflags, tlibattr):
157+
# type: (str, str, List[str], TLIBATTR) -> None
131158
self.name = name
132159
self.clsid = clsid
133160
self.idlflags = idlflags
134161
self.tlibattr = tlibattr
135-
self.interfaces = []
162+
self.interfaces = [] # type: List[Tuple[Any, int]]
136163

137164
def add_interface(self, itf, idlflags):
165+
# type: (Any, int) -> None
138166
self.interfaces.append((itf, idlflags))

0 commit comments

Comments
 (0)