11from __future__ import print_function
2- import types
3- import os
4- import sys
5-
6- import comtypes
7- from comtypes import GUID
8- import comtypes .client
9- from comtypes .tools import codegenerator , tlbparser
10- from comtypes .typeinfo import LoadRegTypeLib , LoadTypeLibEx
2+ import ctypes
113import importlib
12-
134import logging
14- logger = logging .getLogger (__name__ )
15-
5+ import os
6+ import sys
7+ import types
168if sys .version_info >= (3 , 0 ):
179 base_text_type = str
1810 import winreg
1911else :
2012 base_text_type = basestring
2113 import _winreg as winreg
2214
15+ from comtypes import GUID , TYPE_CHECKING , typeinfo
16+ import comtypes .client
17+ from comtypes .tools import codegenerator , tlbparser
18+
19+ if TYPE_CHECKING :
20+ from typing import Any , Tuple , List , Optional , Union as _UnionT
21+
22+
23+ logger = logging .getLogger (__name__ )
2324
2425PATH = os .environ ["PATH" ].split (os .pathsep )
2526
2627
2728def _my_import (fullname ):
29+ # type: (str) -> types.ModuleType
2830 """helper function to import dotted modules"""
29- import comtypes .gen
30- if comtypes .client .gen_dir \
31- and comtypes .client .gen_dir not in comtypes .gen .__path__ :
32- comtypes .gen .__path__ .append (comtypes .client .gen_dir )
31+ import comtypes .gen as g
32+ if comtypes .client .gen_dir and comtypes .client .gen_dir not in g .__path__ :
33+ g .__path__ .append (comtypes .client .gen_dir ) # type: ignore
3334 return importlib .import_module (fullname )
3435
3536
3637def _resolve_filename (tlib_string , dirpath ):
38+ # type: (str, str) -> Tuple[str, bool]
3739 """Tries to make sense of a type library specified as a string.
38-
40+
3941 Args:
4042 tlib_string: type library designator
4143 dirpath: a directory to relativize the location
@@ -63,57 +65,59 @@ def _resolve_filename(tlib_string, dirpath):
6365
6466
6567def GetModule (tlib ):
68+ # type: (_UnionT[Any, typeinfo.ITypeLib]) -> types.ModuleType
6669 """Create a module wrapping a COM typelibrary on demand.
6770
68- 'tlib' must be an ITypeLib COM pointer instance, the pathname of a
69- type library, a COM CLSID GUID, or a tuple/list specifying the
70- arguments to a comtypes.typeinfo.LoadRegTypeLib call:
71-
72- (libid, wMajorVerNum, wMinorVerNum, lcid=0)
73-
74- Or it can be an object with _reg_libid_ and _reg_version_
75- attributes.
76-
77- A relative pathname is interpreted as relative to the callers
78- __file__, if this exists.
71+ 'tlib' must be ...
72+ - an `ITypeLib` COM pointer instance
73+ - an absolute pathname of a type library
74+ - a relative pathname of a type library
75+ - interpreted as relative to the callers `__file__`, if this exists
76+ - a COM CLSID `GUID`
77+ - a `tuple`/`list` specifying the typelib
78+ - `List[_UnionT[str, int]]`
79+ - `(libid: str[, wMajorVerNum: int, wMinorVerNum: int[, lcid: int]])`
80+ - an object with `_reg_libid_: str` and `_reg_version_: Iterable[int]`
7981
8082 This function determines the module name from the typelib
8183 attributes, then tries to import it. If that fails because the
8284 module doesn't exist, the module is generated into the
83- comtypes.gen package.
85+ ` comtypes.gen` package.
8486
8587 It is possible to delete the whole `comtypes/gen` directory to
86- remove all generated modules, the directory and the __init__.py
88+ remove all generated modules, the directory and the ` __init__.py`
8789 file in it will be recreated when needed.
8890
89- If comtypes.gen __path__ is not a directory (in a frozen
91+ If ` comtypes.gen. __path__` is not a directory (in a frozen
9092 executable it lives in a zip archive), generated modules are only
9193 created in memory without writing them to the file system.
9294
9395 Example:
94-
95- GetModule("shdocvw.dll")
96+ GetModule("UIAutomationCore.dll")
9697
9798 would create modules named
9899
99- comtypes.gen._EAB22AC0_30C1_11CF_A7EB_0000C05BAE0B_0_1_1
100- comtypes.gen.SHDocVw
100+ `comtypes.gen._944DE083_8FB8_45CF_BCB7_C477ACB2F897_L_M_m`
101+ - typelib wrapper module
102+ - where L, M, m are numbers of Lcid, Major-ver, minor-ver
103+ `comtypes.gen.UIAutomationClient`
104+ - friendly named module
101105
102106 containing the Python wrapper code for the type library used by
103- Internet Explorer . The former module contains all the code, the
107+ UIAutomation . The former module contains all the code, the
104108 latter is a short stub loading the former.
105109 """
106110 if isinstance (tlib , base_text_type ):
107111 tlib_string = tlib
108- # if a relative pathname is used, we try to interpret it relative to the
109- # directory of the calling module (if not from command line)
112+ # if a relative pathname is used, we try to interpret it relative to
113+ # the directory of the calling module (if not from command line)
110114 frame = sys ._getframe (1 )
111- _file_ = frame .f_globals .get ("__file__" , None )
115+ _file_ = frame .f_globals .get ("__file__" , None ) # type: str
112116 pathname , is_abs = _resolve_filename (tlib_string , _file_ and os .path .dirname (_file_ ))
113117 logger .debug ("GetModule(%s), resolved: %s" , pathname , is_abs )
114118 tlib = _load_tlib (pathname ) # don't register
115119 if not is_abs :
116- # try to get path after loading, but this only works if already registered
120+ # try to get path after loading, but this only works if already registered
117121 pathname = tlbparser .get_tlib_filename (tlib )
118122 if pathname is None :
119123 logger .info ("GetModule(%s): could not resolve to a filename" , tlib )
@@ -137,36 +141,40 @@ def GetModule(tlib):
137141
138142
139143def _load_tlib (obj ):
144+ # type: (Any) -> typeinfo.ITypeLib
140145 """Load a pointer of ITypeLib on demand."""
141146 # obj is a filepath or a ProgID
142147 if isinstance (obj , base_text_type ):
143148 # in any case, attempt to load and if tlib_string is not valid, then raise
144149 # as "OSError: [WinError -2147312566] Error loading type library/DLL"
145- return LoadTypeLibEx (obj )
150+ return typeinfo . LoadTypeLibEx (obj )
146151 # obj is a tlib GUID contain a clsid
147152 elif isinstance (obj , GUID ):
148153 clsid = str (obj )
149154 # lookup associated typelib in registry
150155 with winreg .OpenKey (winreg .HKEY_CLASSES_ROOT , r"CLSID\%s\TypeLib" % clsid ) as key :
151156 libid = winreg .EnumValue (key , 0 )[1 ]
152157 with winreg .OpenKey (winreg .HKEY_CLASSES_ROOT , r"CLSID\%s\Version" % clsid ) as key :
153- version = winreg .EnumValue (key , 0 )[1 ].split ("." )
154- return LoadRegTypeLib (GUID (libid ), int (version [0 ]), int (version [1 ]), 0 )
158+ ver = winreg .EnumValue (key , 0 )[1 ].split ("." )
159+ return typeinfo . LoadRegTypeLib (GUID (libid ), int (ver [0 ]), int (ver [1 ]), 0 )
155160 # obj is a sequence containing libid
156161 elif isinstance (obj , (tuple , list )):
157- libid , version = obj [0 ], obj [1 :]
158- if not version : # case of version numbers are not containing
162+ libid , ver = obj [0 ], obj [1 :]
163+ if not ver : # case of version numbers are not containing
159164 with winreg .OpenKey (winreg .HKEY_CLASSES_ROOT , r"TypeLib\%s" % libid ) as key :
160- version = [int (v , base = 16 ) for v in winreg .EnumKey (key , 0 ).split ("." )]
161- return LoadRegTypeLib (GUID (libid ), * version )
165+ ver = [int (v , base = 16 ) for v in winreg .EnumKey (key , 0 ).split ("." )]
166+ return typeinfo . LoadRegTypeLib (GUID (libid ), * ver )
162167 # obj is a COMObject implementation
163168 elif hasattr (obj , "_reg_libid_" ):
164- return LoadRegTypeLib (GUID (obj ._reg_libid_ ), * obj ._reg_version_ )
165- # perhaps obj is a pointer of ITypeLib
166- return obj
169+ return typeinfo .LoadRegTypeLib (GUID (obj ._reg_libid_ ), * obj ._reg_version_ )
170+ # obj is a pointer of ITypeLib
171+ elif isinstance (obj , ctypes .POINTER (typeinfo .ITypeLib )):
172+ return obj # type: ignore
173+ raise TypeError ("'%r' is not supported type for loading typelib" % obj )
167174
168175
169176def _create_module_in_file (modulename , code ):
177+ # type: (str, str) -> types.ModuleType
170178 """create module in file system, and import it"""
171179 # `modulename` is 'comtypes.gen.xxx'
172180 filename = "%s.py" % modulename .split ("." )[- 1 ]
@@ -179,18 +187,21 @@ def _create_module_in_file(modulename, code):
179187
180188
181189def _create_module_in_memory (modulename , code ):
190+ # type: (str, str) -> types.ModuleType
182191 """create module in memory system, and import it"""
183192 # `modulename` is 'comtypes.gen.xxx'
193+ import comtypes .gen as g
184194 mod = types .ModuleType (modulename )
185- abs_gen_path = os .path .abspath (comtypes . gen . __path__ [0 ])
195+ abs_gen_path = os .path .abspath (g . __path__ [0 ]) # type: ignore
186196 mod .__file__ = os .path .join (abs_gen_path , "<memory>" )
187197 exec (code , mod .__dict__ )
188198 sys .modules [modulename ] = mod
189- setattr (comtypes . gen , modulename .split ("." )[- 1 ], mod )
199+ setattr (g , modulename .split ("." )[- 1 ], mod )
190200 return mod
191201
192202
193203def _create_friendly_module (tlib , modulename ):
204+ # type: (typeinfo.ITypeLib, str) -> types.ModuleType
194205 """helper which creates and imports the friendly-named module."""
195206 try :
196207 mod = _my_import (modulename )
@@ -211,6 +222,7 @@ def _create_friendly_module(tlib, modulename):
211222
212223
213224def _create_wrapper_module (tlib , pathname ):
225+ # type: (typeinfo.ITypeLib, Optional[str]) -> types.ModuleType
214226 """helper which creates and imports the real typelib wrapper module."""
215227 modulename = codegenerator .name_wrapper_module (tlib )
216228 if modulename in sys .modules :
@@ -235,13 +247,16 @@ def _create_wrapper_module(tlib, pathname):
235247
236248
237249def _get_known_symbols ():
250+ # type: () -> dict[str, str]
238251 known_symbols = {} # type: dict[str, str]
239- for mod_name in ("comtypes.persist" ,
240- "comtypes.typeinfo" ,
241- "comtypes.automation" ,
242- "comtypes" ,
243- "ctypes.wintypes" ,
244- "ctypes" ):
252+ for mod_name in (
253+ "comtypes.persist" ,
254+ "comtypes.typeinfo" ,
255+ "comtypes.automation" ,
256+ "comtypes" ,
257+ "ctypes.wintypes" ,
258+ "ctypes"
259+ ):
245260 mod = importlib .import_module (mod_name )
246261 if hasattr (mod , "__known_symbols__" ):
247262 names = mod .__known_symbols__ # type: list[str]
0 commit comments