comtypes 1.4.9__zip → 1.4.10__zip

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. {comtypes-1.4.9 → comtypes-1.4.10}/CHANGES.txt +19 -0
  2. {comtypes-1.4.9/comtypes.egg-info → comtypes-1.4.10}/PKG-INFO +3 -2
  3. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/GUID.py +34 -13
  4. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/__init__.py +22 -13
  5. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/_comobject.py +69 -14
  6. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/_memberspec.py +14 -6
  7. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/_meta.py +1 -0
  8. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/_post_coinit/_cominterface_meta_patcher.py +0 -1
  9. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/_post_coinit/bstr.py +12 -5
  10. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/_post_coinit/instancemethod.py +1 -2
  11. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/_post_coinit/misc.py +59 -24
  12. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/_post_coinit/unknwn.py +2 -6
  13. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/_safearray.py +2 -2
  14. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/automation.py +10 -4
  15. comtypes-1.4.10/comtypes/client/__init__.py +42 -0
  16. comtypes-1.4.10/comtypes/client/_activeobj.py +46 -0
  17. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/client/_code_cache.py +6 -1
  18. comtypes-1.4.10/comtypes/client/_create.py +147 -0
  19. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/client/_events.py +57 -12
  20. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/client/_generate.py +3 -3
  21. comtypes-1.4.10/comtypes/client/_managing.py +114 -0
  22. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/client/dynamic.py +2 -3
  23. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/client/lazybind.py +10 -11
  24. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/connectionpoints.py +2 -1
  25. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/errorinfo.py +20 -7
  26. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/git.py +4 -3
  27. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/logutil.py +15 -3
  28. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/messageloop.py +1 -1
  29. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/persist.py +3 -5
  30. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/safearray.py +8 -6
  31. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/server/__init__.py +22 -4
  32. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/server/automation.py +1 -2
  33. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/server/connectionpoints.py +5 -5
  34. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/server/inprocserver.py +6 -3
  35. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/server/localserver.py +23 -5
  36. comtypes-1.4.10/comtypes/server/register.py +478 -0
  37. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/shelllink.py +13 -7
  38. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/stream.py +7 -4
  39. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/TestComServer.py +6 -7
  40. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/TestDispServer.py +4 -2
  41. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/__init__.py +1 -1
  42. comtypes-1.4.10/comtypes/test/find_memleak.py +72 -0
  43. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/runtests.py +1 -0
  44. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/setup.py +2 -1
  45. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_BSTR.py +7 -17
  46. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_GUID.py +1 -0
  47. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_QueryService.py +1 -0
  48. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_agilent.py +4 -3
  49. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_basic.py +12 -6
  50. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_clear_cache.py +1 -1
  51. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_client.py +2 -2
  52. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_client_dynamic.py +2 -2
  53. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_client_regenerate_modules.py +2 -2
  54. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_collections.py +1 -1
  55. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_comobject.py +4 -4
  56. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_comserver.py +31 -1
  57. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_dispifc_records.py +1 -1
  58. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_dispifc_safearrays.py +1 -1
  59. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_dyndispatch.py +1 -0
  60. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_findgendir.py +1 -2
  61. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_getactiveobj.py +4 -4
  62. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_ie.py +19 -6
  63. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_ienum.py +2 -2
  64. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_imfattributes.py +13 -3
  65. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_inout_args.py +1 -1
  66. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_midl_safearray_create.py +6 -4
  67. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_monikers.py +23 -9
  68. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_msscript.py +2 -1
  69. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_npsupport.py +4 -4
  70. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_outparam.py +22 -6
  71. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_persist.py +2 -4
  72. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_recordinfo.py +1 -1
  73. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_sapi.py +4 -1
  74. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_server_register.py +113 -125
  75. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_shelllink.py +2 -3
  76. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_storage.py +12 -6
  77. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_stream.py +16 -5
  78. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_subinterface.py +4 -2
  79. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_typeannotator.py +1 -2
  80. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_typeinfo.py +19 -7
  81. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_urlhistory.py +7 -4
  82. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_variant.py +3 -2
  83. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_word.py +1 -1
  84. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/tools/codegenerator/codegenerator.py +167 -435
  85. comtypes-1.4.10/comtypes/tools/codegenerator/comments.py +79 -0
  86. comtypes-1.4.10/comtypes/tools/codegenerator/heads.py +192 -0
  87. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/tools/codegenerator/helpers.py +3 -6
  88. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/tools/codegenerator/namespaces.py +13 -5
  89. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/tools/codegenerator/typeannotator.py +13 -3
  90. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/tools/tlbparser.py +22 -23
  91. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/tools/typedesc.py +3 -2
  92. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/tools/typedesc_base.py +2 -2
  93. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/typeinfo.py +149 -42
  94. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/viewobject.py +2 -4
  95. {comtypes-1.4.9 → comtypes-1.4.10/comtypes.egg-info}/PKG-INFO +3 -2
  96. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes.egg-info/SOURCES.txt +5 -0
  97. {comtypes-1.4.9 → comtypes-1.4.10}/pyproject.toml +11 -19
  98. comtypes-1.4.9/comtypes/client/__init__.py +0 -323
  99. comtypes-1.4.9/comtypes/server/register.py +0 -419
  100. comtypes-1.4.9/comtypes/test/find_memleak.py +0 -76
  101. {comtypes-1.4.9 → comtypes-1.4.10}/LICENSE.txt +0 -0
  102. {comtypes-1.4.9 → comtypes-1.4.10}/MANIFEST.in +0 -0
  103. {comtypes-1.4.9 → comtypes-1.4.10}/README.md +0 -0
  104. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/_npsupport.py +0 -0
  105. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/_post_coinit/__init__.py +0 -0
  106. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/_tlib_version_checker.py +0 -0
  107. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/_vtbl.py +0 -0
  108. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/clear_cache.py +0 -0
  109. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/client/_constants.py +0 -0
  110. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/hints.pyi +0 -0
  111. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/hresult.py +0 -0
  112. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/patcher.py +0 -0
  113. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/server/w_getopt.py +0 -0
  114. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/TestComServer.idl +0 -0
  115. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/TestComServer.tlb +0 -0
  116. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/TestDispServer.idl +0 -0
  117. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/TestDispServer.tlb +0 -0
  118. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/mylib.idl +0 -0
  119. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/mylib.tlb +0 -0
  120. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/mytypelib.idl +0 -0
  121. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_DISPPARAMS.py +0 -0
  122. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_avmc.py +0 -0
  123. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_casesensitivity.py +0 -0
  124. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_createwrappers.py +0 -0
  125. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_dict.py +0 -0
  126. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_dispinterface.py +0 -0
  127. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_excel.py +0 -0
  128. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_jscript.js +0 -0
  129. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_pump_events.py +0 -0
  130. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_safearray.py +0 -0
  131. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_server.py +0 -0
  132. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_showevents.py +0 -0
  133. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_w_getopt.py +0 -0
  134. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_win32com_interop.py +0 -0
  135. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/test_wmi.py +0 -0
  136. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/test/urlhist.tlb +0 -0
  137. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/tools/__init__.py +0 -0
  138. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/tools/codegenerator/__init__.py +0 -0
  139. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/tools/codegenerator/modulenamer.py +0 -0
  140. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/tools/codegenerator/packing.py +0 -0
  141. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes/util.py +0 -0
  142. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes.egg-info/dependency_links.txt +0 -0
  143. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes.egg-info/entry_points.txt +0 -0
  144. {comtypes-1.4.9 → comtypes-1.4.10}/comtypes.egg-info/top_level.txt +0 -0
  145. {comtypes-1.4.9 → comtypes-1.4.10}/setup.cfg +0 -0
  146. {comtypes-1.4.9 → comtypes-1.4.10}/setup.py +0 -0
@@ -1,419 +0,0 @@
1
- """comtypes.server.register - register and unregister a COM object.
2
-
3
- Exports the UseCommandLine function. UseCommandLine is called with
4
- the COM object classes that a module exposes. It parses the Windows
5
- command line and takes the appropriate actions.
6
- These command line options are supported:
7
-
8
- /regserver - register the classes with COM.
9
- /unregserver - unregister the classes with COM.
10
-
11
- /nodebug - remove all logging configuration from the registry.
12
-
13
- /l <name>=<level> - configure the logging level for the standard Python loggind module,
14
- this option may be used several times.
15
-
16
- /f <formatter> - specify the formatter string.
17
-
18
- Note: Registering and unregistering the objects does remove logging
19
- entries. Configuring the logging does not change other registry
20
- entries, so it is possible to freeze a comobject with py2exe, register
21
- it, then configure logging afterwards to debug it, and delete the
22
- logging config afterwards.
23
-
24
- Sample usage:
25
-
26
- Register the COM object:
27
-
28
- python mycomobj.py /regserver
29
-
30
- Configure logging info:
31
-
32
- python mycomobj.py /l comtypes=INFO /l comtypes.server=DEBUG /f %(message)s
33
-
34
- Now, debug the object, and when done delete logging info:
35
-
36
- python mycomobj.py /nodebug
37
- """
38
-
39
- import logging
40
- import os
41
- import sys
42
- import winreg
43
- from ctypes import WinError, c_ulong, c_wchar_p, create_string_buffer, sizeof, windll
44
- from typing import Iterator, Tuple
45
-
46
- import comtypes
47
- import comtypes.server.inprocserver
48
- from comtypes.hresult import *
49
- from comtypes.server import w_getopt
50
- from comtypes.typeinfo import REGKIND_REGISTER, LoadTypeLibEx, UnRegisterTypeLib
51
-
52
- _debug = logging.getLogger(__name__).debug
53
-
54
-
55
- def get_winerror(exception):
56
- try:
57
- return exception.winerror
58
- except AttributeError:
59
- return exception.errno
60
-
61
-
62
- # a SHDeleteKey function, will remove a registry key with all subkeys.
63
- def _non_zero(retval, func, args):
64
- if retval:
65
- raise WinError(retval)
66
-
67
-
68
- SHDeleteKey = windll.shlwapi.SHDeleteKeyW
69
- SHDeleteKey.errcheck = _non_zero
70
- SHDeleteKey.argtypes = c_ulong, c_wchar_p
71
-
72
- Set = set
73
-
74
-
75
- _KEYS = {
76
- winreg.HKEY_CLASSES_ROOT: "HKCR",
77
- winreg.HKEY_LOCAL_MACHINE: "HKLM",
78
- winreg.HKEY_CURRENT_USER: "HKCU",
79
- }
80
-
81
-
82
- def _explain(hkey):
83
- return _KEYS.get(hkey, hkey)
84
-
85
-
86
- class Registrar(object):
87
- """COM class registration.
88
-
89
- The COM class can override what this does by implementing
90
- _register and/or _unregister class methods. These methods will be
91
- called with the calling instance of Registrar, and so can call the
92
- Registrars _register and _unregister methods which do the actual
93
- work.
94
- """
95
-
96
- def nodebug(self, cls):
97
- """Delete logging entries from the registry."""
98
- clsid = cls._reg_clsid_
99
- try:
100
- _debug(
101
- 'DeleteKey( %s\\CLSID\\%s\\Logging"'
102
- % (_explain(winreg.HKEY_CLASSES_ROOT), clsid)
103
- )
104
- hkey = winreg.OpenKey(winreg.HKEY_CLASSES_ROOT, rf"CLSID\{clsid}")
105
- winreg.DeleteKey(hkey, "Logging")
106
- except WindowsError as detail:
107
- if get_winerror(detail) != 2:
108
- raise
109
-
110
- def debug(self, cls, levels, format):
111
- """Write entries in the registry to setup logging for this clsid."""
112
- # handlers
113
- # format
114
- clsid = cls._reg_clsid_
115
- _debug(
116
- 'CreateKey( %s\\CLSID\\%s\\Logging"'
117
- % (_explain(winreg.HKEY_CLASSES_ROOT), clsid)
118
- )
119
- hkey = winreg.CreateKey(winreg.HKEY_CLASSES_ROOT, rf"CLSID\{clsid}\Logging")
120
- for item in levels:
121
- name, value = item.split("=")
122
- v = getattr(logging, value)
123
- assert isinstance(v, int)
124
- _debug("SetValueEx(levels, %s)" % levels)
125
- winreg.SetValueEx(hkey, "levels", None, winreg.REG_MULTI_SZ, levels)
126
- if format:
127
- _debug("SetValueEx(format, %s)" % format)
128
- winreg.SetValueEx(hkey, "format", None, winreg.REG_SZ, format)
129
- else:
130
- _debug("DeleteValue(format)")
131
- try:
132
- winreg.DeleteValue(hkey, "format")
133
- except WindowsError as detail:
134
- if get_winerror(detail) != 2:
135
- raise
136
-
137
- def register(self, cls, executable=None):
138
- """Register the COM server class."""
139
- # First, we unregister the object with force=True, to force removal
140
- # of all registry entries, even if we would not write them.
141
- # Second, we create new entries.
142
- # It seems ATL does the same.
143
- mth = getattr(cls, "_register", None)
144
- if mth is not None:
145
- mth(self)
146
- else:
147
- self._unregister(cls, force=True)
148
- self._register(cls, executable)
149
-
150
- def _register(self, cls, executable=None):
151
- table = sorted(RegistryEntries(cls))
152
- _debug("Registering %s", cls)
153
- for hkey, subkey, valuename, value in table:
154
- _debug("[%s\\%s]", _explain(hkey), subkey)
155
- _debug('%s="%s"', valuename or "@", value)
156
- k = winreg.CreateKey(hkey, subkey)
157
- winreg.SetValueEx(k, valuename, None, winreg.REG_SZ, str(value))
158
-
159
- tlib = getattr(cls, "_reg_typelib_", None)
160
- if tlib is not None:
161
- if hasattr(sys, "frozendllhandle"):
162
- dll = _get_serverdll()
163
- _debug("LoadTypeLibEx(%s, REGKIND_REGISTER)", dll)
164
- LoadTypeLibEx(dll, REGKIND_REGISTER)
165
- else:
166
- if executable:
167
- path = executable
168
- elif hasattr(sys, "frozen"):
169
- path = sys.executable
170
- else:
171
- path = cls._typelib_path_
172
- _debug("LoadTypeLibEx(%s, REGKIND_REGISTER)", path)
173
- LoadTypeLibEx(path, REGKIND_REGISTER)
174
- _debug("Done")
175
-
176
- def unregister(self, cls, force=False):
177
- """Unregister the COM server class."""
178
- mth = getattr(cls, "_unregister", None)
179
- if mth is not None:
180
- mth(self)
181
- else:
182
- self._unregister(cls, force=force)
183
-
184
- def _unregister(self, cls, force=False):
185
- # If force==False, we only remove those entries that we
186
- # actually would have written. It seems ATL does the same.
187
- table = [t[:2] for t in RegistryEntries(cls)]
188
- # only unique entries
189
- table = list(set(table))
190
- table.sort()
191
- table.reverse()
192
- _debug("Unregister %s", cls)
193
- for hkey, subkey in table:
194
- try:
195
- if force:
196
- _debug("SHDeleteKey %s\\%s", _explain(hkey), subkey)
197
- SHDeleteKey(hkey, subkey)
198
- else:
199
- _debug("DeleteKey %s\\%s", _explain(hkey), subkey)
200
- winreg.DeleteKey(hkey, subkey)
201
- except WindowsError as detail:
202
- if get_winerror(detail) != 2:
203
- raise
204
- tlib = getattr(cls, "_reg_typelib_", None)
205
- if tlib is not None:
206
- try:
207
- _debug("UnRegisterTypeLib(%s, %s, %s)", *tlib)
208
- UnRegisterTypeLib(*tlib)
209
- except WindowsError as detail:
210
- if not get_winerror(detail) in (
211
- TYPE_E_REGISTRYACCESS,
212
- TYPE_E_CANTLOADLIBRARY,
213
- ):
214
- raise
215
- _debug("Done")
216
-
217
-
218
- def _get_serverdll():
219
- """Return the pathname of the dll hosting the COM object."""
220
- handle = getattr(sys, "frozendllhandle", None)
221
- if handle is not None:
222
- buf = create_string_buffer(260)
223
- windll.kernel32.GetModuleFileNameA(handle, buf, sizeof(buf))
224
- return buf[:]
225
- import _ctypes
226
-
227
- return _ctypes.__file__
228
-
229
-
230
- class RegistryEntries(object):
231
- def __init__(self, cls):
232
- self._cls = cls
233
-
234
- def _get_full_classname(self, cls):
235
- """Return <modulename>.<classname> for 'cls'."""
236
- modname = cls.__module__
237
- if modname == "__main__":
238
- modname = os.path.splitext(os.path.basename(sys.argv[0]))[0]
239
- return f"{modname}.{cls.__name__}"
240
-
241
- def _get_pythonpath(self, cls):
242
- """Return the filesystem path of the module containing 'cls'."""
243
- modname = cls.__module__
244
- dirname = os.path.dirname(sys.modules[modname].__file__)
245
- return os.path.abspath(dirname)
246
-
247
- def __iter__(self) -> Iterator[Tuple[int, str, str, str]]:
248
- """Return a iterator of tuples containing registry entries.
249
-
250
- The tuples must be (key, subkey, name, value).
251
-
252
- Required entries:
253
- =================
254
- _reg_clsid_ - a string or GUID instance
255
- _reg_clsctx_ - server type(s) to register
256
-
257
- Optional entries:
258
- =================
259
- _reg_desc_ - a string
260
- _reg_progid_ - a string naming the progid, typically 'MyServer.MyObject.1'
261
- _reg_novers_progid_ - version independend progid, typically 'MyServer.MyObject'
262
- _reg_typelib_ - an tuple (libid, majorversion, minorversion) specifying a typelib.
263
- _reg_threading_ - a string specifying the threading model
264
-
265
- Note that the first part of the progid string is typically the
266
- IDL library name of the type library containing the coclass.
267
- """
268
- cls = self._cls
269
- HKCR = winreg.HKEY_CLASSES_ROOT
270
-
271
- # basic entry - names the comobject
272
-
273
- # that's the only required attribute for registration
274
- reg_clsid = str(cls._reg_clsid_)
275
- reg_desc = getattr(cls, "_reg_desc_", "")
276
- if not reg_desc:
277
- # Simple minded algorithm to construct a description from
278
- # the progid:
279
- reg_desc = getattr(cls, "_reg_novers_progid_", "") or getattr(
280
- cls, "_reg_progid_", ""
281
- )
282
- if reg_desc:
283
- reg_desc = reg_desc.replace(".", " ")
284
- yield (HKCR, f"CLSID\\{reg_clsid}", "", reg_desc)
285
-
286
- reg_progid = getattr(cls, "_reg_progid_", None)
287
- if reg_progid:
288
- # for ProgIDFromCLSID:
289
- yield (HKCR, f"CLSID\\{reg_clsid}\\ProgID", "", reg_progid) # 1
290
-
291
- # for CLSIDFromProgID
292
- if reg_desc:
293
- yield (HKCR, reg_progid, "", reg_desc) # 2
294
- yield (HKCR, f"{reg_progid}\\CLSID", "", reg_clsid) # 3
295
-
296
- reg_novers_progid = getattr(cls, "_reg_novers_progid_", None)
297
- if reg_novers_progid:
298
- yield (
299
- HKCR,
300
- f"CLSID\\{reg_clsid}\\VersionIndependentProgID", # 1a
301
- "",
302
- reg_novers_progid,
303
- )
304
- if reg_desc:
305
- yield (HKCR, reg_novers_progid, "", reg_desc) # 2a
306
- yield (HKCR, f"{reg_novers_progid}\\CurVer", "", reg_progid) #
307
- yield (HKCR, f"{reg_novers_progid}\\CLSID", "", reg_clsid) # 3a
308
-
309
- clsctx: int = getattr(cls, "_reg_clsctx_", 0)
310
- localsvr_ctx = bool(clsctx & comtypes.CLSCTX_LOCAL_SERVER)
311
- inprocsvr_ctx = bool(clsctx & comtypes.CLSCTX_INPROC_SERVER)
312
-
313
- if localsvr_ctx and not hasattr(sys, "frozendllhandle"):
314
- exe = sys.executable
315
- if " " in exe:
316
- exe = f'"{exe}"'
317
- if not hasattr(sys, "frozen"):
318
- if not __debug__:
319
- exe = f"{exe} -O"
320
- script = os.path.abspath(sys.modules[cls.__module__].__file__)
321
- if " " in script:
322
- script = f'"{script}"'
323
- yield (HKCR, rf"CLSID\{reg_clsid}\LocalServer32", "", f"{exe} {script}")
324
- else:
325
- yield (HKCR, rf"CLSID\{reg_clsid}\LocalServer32", "", f"{exe}")
326
-
327
- # Register InprocServer32 only when run from script or from
328
- # py2exe dll server, not from py2exe exe server.
329
- if inprocsvr_ctx and getattr(sys, "frozen", None) in (None, "dll"):
330
- yield (HKCR, rf"CLSID\{reg_clsid}\InprocServer32", "", _get_serverdll())
331
- # only for non-frozen inproc servers the PythonPath/PythonClass is needed.
332
- if (
333
- not hasattr(sys, "frozendllhandle")
334
- or not comtypes.server.inprocserver._clsid_to_class
335
- ):
336
- yield (
337
- HKCR,
338
- rf"CLSID\{reg_clsid}\InprocServer32",
339
- "PythonClass",
340
- self._get_full_classname(cls),
341
- )
342
- yield (
343
- HKCR,
344
- rf"CLSID\{reg_clsid}\InprocServer32",
345
- "PythonPath",
346
- self._get_pythonpath(cls),
347
- )
348
-
349
- reg_threading = getattr(cls, "_reg_threading_", None)
350
- if reg_threading is not None:
351
- yield (
352
- HKCR,
353
- rf"CLSID\{reg_clsid}\InprocServer32",
354
- "ThreadingModel",
355
- reg_threading,
356
- )
357
-
358
- reg_tlib = getattr(cls, "_reg_typelib_", None)
359
- if reg_tlib is not None:
360
- yield (HKCR, rf"CLSID\{reg_clsid}\Typelib", "", reg_tlib[0])
361
-
362
-
363
- ################################################################
364
-
365
-
366
- def register(cls):
367
- Registrar().register(cls)
368
-
369
-
370
- def unregister(cls):
371
- Registrar().unregister(cls)
372
-
373
-
374
- def UseCommandLine(*classes):
375
- usage = f"""Usage: {sys.argv[0]} [-regserver] [-unregserver] [-nodebug] [-f logformat] [-l loggername=level]"""
376
- opts, args = w_getopt.w_getopt(
377
- sys.argv[1:], "regserver unregserver embedding l: f: nodebug"
378
- )
379
- if not opts:
380
- sys.stderr.write(usage + "\n")
381
- return 0 # nothing for us to do
382
-
383
- levels = []
384
- format = None
385
- nodebug = False
386
- runit = False
387
- for option, value in opts:
388
- if option == "regserver":
389
- for cls in classes:
390
- register(cls)
391
- elif option == "unregserver":
392
- for cls in classes:
393
- unregister(cls)
394
- elif option == "embedding":
395
- runit = True
396
- elif option == "f":
397
- format = value
398
- elif option == "l":
399
- levels.append(value)
400
- elif option == "nodebug":
401
- nodebug = True
402
-
403
- if levels or format is not None:
404
- for cls in classes:
405
- Registrar().debug(cls, levels, format)
406
- if nodebug:
407
- for cls in classes:
408
- Registrar().nodebug(cls)
409
-
410
- if runit:
411
- import comtypes.server.localserver
412
-
413
- comtypes.server.localserver.run(classes)
414
-
415
- return 1 # we have done something
416
-
417
-
418
- if __name__ == "__main__":
419
- UseCommandLine()
@@ -1,76 +0,0 @@
1
- import unittest, gc
2
- from ctypes import *
3
- from ctypes.wintypes import *
4
-
5
- ################################################################
6
-
7
-
8
- class PROCESS_MEMORY_COUNTERS(Structure):
9
- _fields_ = [
10
- ("cb", DWORD),
11
- ("PageFaultCount", DWORD),
12
- ("PeakWorkingSetSize", c_size_t),
13
- ("WorkingSetSize", c_size_t),
14
- ("QuotaPeakPagedPoolUsage", c_size_t),
15
- ("QuotaPagedPoolUsage", c_size_t),
16
- ("QuotaPeakNonPagedPoolUsage", c_size_t),
17
- ("QuotaNonPagedPoolUsage", c_size_t),
18
- ("PagefileUsage", c_size_t),
19
- ("PeakPagefileUsage", c_size_t),
20
- ]
21
-
22
- def __init__(self):
23
- self.cb = sizeof(self)
24
-
25
- def dump(self):
26
- for n, _ in self._fields_[2:]:
27
- print(n, getattr(self, n) / 1e6)
28
-
29
-
30
- try:
31
- windll.psapi.GetProcessMemoryInfo.argtypes = (
32
- HANDLE,
33
- POINTER(PROCESS_MEMORY_COUNTERS),
34
- DWORD,
35
- )
36
- except WindowsError:
37
- # cannot search for memory leaks on Windows CE
38
- def find_memleak(func, loops=None):
39
- return 0
40
-
41
- else:
42
-
43
- def wss():
44
- # Return the working set size (memory used by process)
45
- pmi = PROCESS_MEMORY_COUNTERS()
46
- if not windll.psapi.GetProcessMemoryInfo(-1, byref(pmi), sizeof(pmi)):
47
- raise WinError()
48
- return pmi.WorkingSetSize
49
-
50
- LOOPS = 10, 1000
51
-
52
- def find_memleak(func, loops=LOOPS):
53
- # call 'func' several times, so that memory consumption
54
- # stabilizes:
55
- for j in range(loops[0]):
56
- for k in range(loops[1]):
57
- func()
58
- gc.collect()
59
- gc.collect()
60
- gc.collect()
61
- bytes = wss()
62
- # call 'func' several times, recording the difference in
63
- # memory consumption before and after the call. Repeat this a
64
- # few times, and return a list containing the memory
65
- # consumption differences.
66
- for j in range(loops[0]):
67
- for k in range(loops[1]):
68
- func()
69
- gc.collect()
70
- gc.collect()
71
- gc.collect()
72
- # return the increased in process size
73
- result = wss() - bytes
74
- # Sometimes the process size did decrease, we do not report leaks
75
- # in this case:
76
- return max(result, 0)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes