comtypes 1.4.8__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 (154) hide show
  1. {comtypes-1.4.8 → comtypes-1.4.10}/CHANGES.txt +40 -0
  2. {comtypes-1.4.8/comtypes.egg-info → comtypes-1.4.10}/PKG-INFO +4 -3
  3. {comtypes-1.4.8 → comtypes-1.4.10}/README.md +1 -1
  4. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/GUID.py +38 -16
  5. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/__init__.py +36 -16
  6. comtypes-1.4.10/comtypes/_comobject.py +562 -0
  7. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/_memberspec.py +93 -13
  8. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/_meta.py +1 -0
  9. comtypes-1.4.10/comtypes/_post_coinit/_cominterface_meta_patcher.py +152 -0
  10. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/_post_coinit/bstr.py +12 -5
  11. comtypes-1.4.8/comtypes/_py_instance_method.py → comtypes-1.4.10/comtypes/_post_coinit/instancemethod.py +1 -2
  12. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/_post_coinit/misc.py +60 -25
  13. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/_post_coinit/unknwn.py +26 -176
  14. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/_safearray.py +3 -4
  15. comtypes-1.4.10/comtypes/_vtbl.py +448 -0
  16. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/automation.py +46 -49
  17. comtypes-1.4.10/comtypes/client/__init__.py +42 -0
  18. comtypes-1.4.10/comtypes/client/_activeobj.py +46 -0
  19. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/client/_code_cache.py +10 -5
  20. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/client/_constants.py +1 -1
  21. comtypes-1.4.10/comtypes/client/_create.py +147 -0
  22. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/client/_events.py +58 -13
  23. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/client/_generate.py +7 -11
  24. comtypes-1.4.10/comtypes/client/_managing.py +114 -0
  25. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/client/dynamic.py +2 -3
  26. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/client/lazybind.py +12 -13
  27. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/connectionpoints.py +2 -1
  28. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/errorinfo.py +22 -9
  29. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/git.py +5 -5
  30. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/hints.pyi +7 -15
  31. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/logutil.py +15 -3
  32. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/messageloop.py +1 -1
  33. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/persist.py +3 -5
  34. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/safearray.py +17 -5
  35. comtypes-1.4.10/comtypes/server/__init__.py +104 -0
  36. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/server/automation.py +1 -2
  37. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/server/connectionpoints.py +5 -5
  38. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/server/inprocserver.py +25 -17
  39. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/server/localserver.py +49 -19
  40. comtypes-1.4.10/comtypes/server/register.py +478 -0
  41. comtypes-1.4.10/comtypes/server/w_getopt.py +48 -0
  42. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/shelllink.py +16 -33
  43. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/stream.py +7 -4
  44. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/TestComServer.py +6 -7
  45. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/TestDispServer.py +4 -2
  46. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/__init__.py +10 -12
  47. comtypes-1.4.10/comtypes/test/find_memleak.py +72 -0
  48. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/runtests.py +1 -0
  49. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/setup.py +2 -1
  50. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_BSTR.py +10 -23
  51. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_GUID.py +1 -0
  52. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_QueryService.py +1 -0
  53. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_agilent.py +4 -3
  54. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_avmc.py +1 -1
  55. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_basic.py +12 -6
  56. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_casesensitivity.py +3 -5
  57. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_clear_cache.py +1 -1
  58. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_client.py +2 -2
  59. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_client_dynamic.py +2 -2
  60. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_client_regenerate_modules.py +2 -2
  61. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_collections.py +4 -4
  62. comtypes-1.4.10/comtypes/test/test_comobject.py +146 -0
  63. comtypes-1.4.10/comtypes/test/test_comserver.py +349 -0
  64. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_createwrappers.py +2 -4
  65. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_dispifc_records.py +1 -1
  66. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_dispifc_safearrays.py +1 -1
  67. comtypes-1.4.10/comtypes/test/test_dispinterface.py +153 -0
  68. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_dyndispatch.py +1 -0
  69. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_excel.py +22 -12
  70. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_findgendir.py +1 -2
  71. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_getactiveobj.py +4 -4
  72. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_ie.py +19 -9
  73. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_ienum.py +2 -2
  74. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_imfattributes.py +13 -3
  75. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_inout_args.py +8 -5
  76. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_midl_safearray_create.py +14 -4
  77. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_monikers.py +23 -9
  78. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_msscript.py +2 -1
  79. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_npsupport.py +4 -4
  80. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_outparam.py +37 -14
  81. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_persist.py +2 -4
  82. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_recordinfo.py +1 -1
  83. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_safearray.py +1 -90
  84. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_sapi.py +4 -1
  85. comtypes-1.4.10/comtypes/test/test_server.py +350 -0
  86. comtypes-1.4.10/comtypes/test/test_server_register.py +524 -0
  87. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_shelllink.py +2 -3
  88. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_showevents.py +7 -17
  89. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_storage.py +12 -6
  90. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_stream.py +16 -5
  91. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_subinterface.py +4 -2
  92. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_typeannotator.py +1 -2
  93. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_typeinfo.py +19 -7
  94. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_urlhistory.py +7 -4
  95. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_variant.py +3 -19
  96. comtypes-1.4.10/comtypes/test/test_w_getopt.py +29 -0
  97. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_win32com_interop.py +80 -36
  98. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_wmi.py +0 -3
  99. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_word.py +1 -1
  100. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/codegenerator/codegenerator.py +166 -440
  101. comtypes-1.4.10/comtypes/tools/codegenerator/comments.py +79 -0
  102. comtypes-1.4.10/comtypes/tools/codegenerator/heads.py +192 -0
  103. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/codegenerator/helpers.py +11 -14
  104. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/codegenerator/namespaces.py +13 -5
  105. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/codegenerator/packing.py +4 -4
  106. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/codegenerator/typeannotator.py +19 -9
  107. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/tlbparser.py +22 -23
  108. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/typedesc.py +4 -8
  109. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/typedesc_base.py +2 -2
  110. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/typeinfo.py +159 -63
  111. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/viewobject.py +3 -9
  112. {comtypes-1.4.8 → comtypes-1.4.10/comtypes.egg-info}/PKG-INFO +4 -3
  113. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes.egg-info/SOURCES.txt +11 -3
  114. {comtypes-1.4.8 → comtypes-1.4.10}/pyproject.toml +12 -19
  115. comtypes-1.4.8/comtypes/_comobject.py +0 -833
  116. comtypes-1.4.8/comtypes/_idl_stuff.py +0 -67
  117. comtypes-1.4.8/comtypes/client/__init__.py +0 -323
  118. comtypes-1.4.8/comtypes/server/__init__.py +0 -70
  119. comtypes-1.4.8/comtypes/server/register.py +0 -431
  120. comtypes-1.4.8/comtypes/server/w_getopt.py +0 -75
  121. comtypes-1.4.8/comtypes/test/find_memleak.py +0 -76
  122. comtypes-1.4.8/comtypes/test/test_comserver.py +0 -239
  123. comtypes-1.4.8/comtypes/test/test_dispinterface.py +0 -137
  124. comtypes-1.4.8/comtypes/test/test_propputref.py +0 -40
  125. comtypes-1.4.8/comtypes/test/test_server.py +0 -354
  126. {comtypes-1.4.8 → comtypes-1.4.10}/LICENSE.txt +0 -0
  127. {comtypes-1.4.8 → comtypes-1.4.10}/MANIFEST.in +0 -0
  128. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/_npsupport.py +0 -0
  129. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/_post_coinit/__init__.py +0 -0
  130. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/_tlib_version_checker.py +0 -0
  131. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/clear_cache.py +0 -0
  132. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/hresult.py +0 -0
  133. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/patcher.py +0 -0
  134. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/TestComServer.idl +0 -0
  135. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/TestComServer.tlb +0 -0
  136. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/TestDispServer.idl +0 -0
  137. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/TestDispServer.tlb +0 -0
  138. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/mylib.idl +0 -0
  139. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/mylib.tlb +0 -0
  140. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/mytypelib.idl +0 -0
  141. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_DISPPARAMS.py +0 -0
  142. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_dict.py +0 -0
  143. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_jscript.js +0 -0
  144. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_pump_events.py +0 -0
  145. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/urlhist.tlb +0 -0
  146. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/__init__.py +0 -0
  147. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/codegenerator/__init__.py +0 -0
  148. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/codegenerator/modulenamer.py +0 -0
  149. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/util.py +0 -0
  150. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes.egg-info/dependency_links.txt +0 -0
  151. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes.egg-info/entry_points.txt +0 -0
  152. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes.egg-info/top_level.txt +0 -0
  153. {comtypes-1.4.8 → comtypes-1.4.10}/setup.cfg +0 -0
  154. {comtypes-1.4.8 → comtypes-1.4.10}/setup.py +0 -0
@@ -1,431 +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 sys
40
- import os
41
- import winreg
42
- import logging
43
-
44
- import comtypes
45
- from comtypes.typeinfo import LoadTypeLibEx, UnRegisterTypeLib, REGKIND_REGISTER
46
- from comtypes.hresult import *
47
- from comtypes.server import w_getopt
48
- import comtypes.server.inprocserver
49
- from ctypes import windll, c_ulong, c_wchar_p, WinError, sizeof, create_string_buffer
50
-
51
- _debug = logging.getLogger(__name__).debug
52
-
53
-
54
- def get_winerror(exception):
55
- try:
56
- return exception.winerror
57
- except AttributeError:
58
- return exception.errno
59
-
60
-
61
- # a SHDeleteKey function, will remove a registry key with all subkeys.
62
- def _non_zero(retval, func, args):
63
- if retval:
64
- raise WinError(retval)
65
-
66
-
67
- SHDeleteKey = windll.shlwapi.SHDeleteKeyW
68
- SHDeleteKey.errcheck = _non_zero
69
- SHDeleteKey.argtypes = c_ulong, c_wchar_p
70
-
71
- Set = set
72
-
73
-
74
- _KEYS = {
75
- winreg.HKEY_CLASSES_ROOT: "HKCR",
76
- winreg.HKEY_LOCAL_MACHINE: "HKLM",
77
- winreg.HKEY_CURRENT_USER: "HKCU",
78
- }
79
-
80
-
81
- def _explain(hkey):
82
- return _KEYS.get(hkey, hkey)
83
-
84
-
85
- class Registrar(object):
86
- """COM class registration.
87
-
88
- The COM class can override what this does by implementing
89
- _register and/or _unregister class methods. These methods will be
90
- called with the calling instance of Registrar, and so can call the
91
- Registrars _register and _unregister methods which do the actual
92
- work.
93
- """
94
-
95
- def nodebug(self, cls):
96
- """Delete logging entries from the registry."""
97
- clsid = cls._reg_clsid_
98
- try:
99
- _debug(
100
- 'DeleteKey( %s\\CLSID\\%s\\Logging"'
101
- % (_explain(winreg.HKEY_CLASSES_ROOT), clsid)
102
- )
103
- hkey = winreg.OpenKey(winreg.HKEY_CLASSES_ROOT, r"CLSID\%s" % clsid)
104
- winreg.DeleteKey(hkey, "Logging")
105
- except WindowsError as detail:
106
- if get_winerror(detail) != 2:
107
- raise
108
-
109
- def debug(self, cls, levels, format):
110
- """Write entries in the registry to setup logging for this clsid."""
111
- # handlers
112
- # format
113
- clsid = cls._reg_clsid_
114
- _debug(
115
- 'CreateKey( %s\\CLSID\\%s\\Logging"'
116
- % (_explain(winreg.HKEY_CLASSES_ROOT), clsid)
117
- )
118
- hkey = winreg.CreateKey(winreg.HKEY_CLASSES_ROOT, r"CLSID\%s\Logging" % clsid)
119
- for item in levels:
120
- name, value = item.split("=")
121
- v = getattr(logging, value)
122
- assert isinstance(v, int)
123
- _debug("SetValueEx(levels, %s)" % levels)
124
- winreg.SetValueEx(hkey, "levels", None, winreg.REG_MULTI_SZ, levels)
125
- if format:
126
- _debug("SetValueEx(format, %s)" % format)
127
- winreg.SetValueEx(hkey, "format", None, winreg.REG_SZ, format)
128
- else:
129
- _debug("DeleteValue(format)")
130
- try:
131
- winreg.DeleteValue(hkey, "format")
132
- except WindowsError as detail:
133
- if get_winerror(detail) != 2:
134
- raise
135
-
136
- def register(self, cls, executable=None):
137
- """Register the COM server class."""
138
- # First, we unregister the object with force=True, to force removal
139
- # of all registry entries, even if we would not write them.
140
- # Second, we create new entries.
141
- # It seems ATL does the same.
142
- mth = getattr(cls, "_register", None)
143
- if mth is not None:
144
- mth(self)
145
- else:
146
- self._unregister(cls, force=True)
147
- self._register(cls, executable)
148
-
149
- def _register(self, cls, executable=None):
150
- table = self._registry_entries(cls)
151
- table.sort()
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 = self._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 self._registry_entries(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
- def _get_serverdll(self):
218
- """Return the pathname of the dll hosting the COM object."""
219
- handle = getattr(sys, "frozendllhandle", None)
220
- if handle is not None:
221
- buf = create_string_buffer(260)
222
- windll.kernel32.GetModuleFileNameA(handle, buf, sizeof(buf))
223
- return buf[:]
224
- import _ctypes
225
-
226
- return _ctypes.__file__
227
-
228
- def _get_full_classname(self, cls):
229
- """Return <modulename>.<classname> for 'cls'."""
230
- modname = cls.__module__
231
- if modname == "__main__":
232
- modname = os.path.splitext(os.path.basename(sys.argv[0]))[0]
233
- return "%s.%s" % (modname, cls.__name__)
234
-
235
- def _get_pythonpath(self, cls):
236
- """Return the filesystem path of the module containing 'cls'."""
237
- modname = cls.__module__
238
- dirname = os.path.dirname(sys.modules[modname].__file__)
239
- return os.path.abspath(dirname)
240
-
241
- def _registry_entries(self, cls):
242
- """Return a sequence of tuples containing registry entries.
243
-
244
- The tuples must be (key, subkey, name, value).
245
-
246
- Required entries:
247
- =================
248
- _reg_clsid_ - a string or GUID instance
249
- _reg_clsctx_ - server type(s) to register
250
-
251
- Optional entries:
252
- =================
253
- _reg_desc_ - a string
254
- _reg_progid_ - a string naming the progid, typically 'MyServer.MyObject.1'
255
- _reg_novers_progid_ - version independend progid, typically 'MyServer.MyObject'
256
- _reg_typelib_ - an tuple (libid, majorversion, minorversion) specifying a typelib.
257
- _reg_threading_ - a string specifying the threading model
258
-
259
- Note that the first part of the progid string is typically the
260
- IDL library name of the type library containing the coclass.
261
- """
262
- HKCR = winreg.HKEY_CLASSES_ROOT
263
-
264
- # table format: rootkey, subkey, valuename, value
265
- table = []
266
- append = lambda *args: table.append(args)
267
-
268
- # basic entry - names the comobject
269
- reg_clsid = str(
270
- cls._reg_clsid_
271
- ) # that's the only required attribute for registration
272
- reg_desc = getattr(cls, "_reg_desc_", "")
273
- if not reg_desc:
274
- # Simple minded algorithm to construct a description from
275
- # the progid:
276
- reg_desc = getattr(cls, "_reg_novers_progid_", "") or getattr(
277
- cls, "_reg_progid_", ""
278
- )
279
- if reg_desc:
280
- reg_desc = reg_desc.replace(".", " ")
281
- append(HKCR, "CLSID\\%s" % reg_clsid, "", reg_desc)
282
-
283
- reg_progid = getattr(cls, "_reg_progid_", None)
284
- if reg_progid:
285
- # for ProgIDFromCLSID:
286
- append(HKCR, "CLSID\\%s\\ProgID" % reg_clsid, "", reg_progid) # 1
287
-
288
- # for CLSIDFromProgID
289
- if reg_desc:
290
- append(HKCR, reg_progid, "", reg_desc) # 2
291
- append(HKCR, "%s\\CLSID" % reg_progid, "", reg_clsid) # 3
292
-
293
- reg_novers_progid = getattr(cls, "_reg_novers_progid_", None)
294
- if reg_novers_progid:
295
- append(
296
- HKCR,
297
- "CLSID\\%s\\VersionIndependentProgID" % reg_clsid, # 1a
298
- "",
299
- reg_novers_progid,
300
- )
301
- if reg_desc:
302
- append(HKCR, reg_novers_progid, "", reg_desc) # 2a
303
- append(HKCR, "%s\\CurVer" % reg_novers_progid, "", reg_progid) #
304
- append(HKCR, "%s\\CLSID" % reg_novers_progid, "", reg_clsid) # 3a
305
-
306
- clsctx = getattr(cls, "_reg_clsctx_", 0)
307
-
308
- if clsctx & comtypes.CLSCTX_LOCAL_SERVER and not hasattr(
309
- sys, "frozendllhandle"
310
- ):
311
- exe = sys.executable
312
- if " " in exe:
313
- exe = '"%s"' % exe
314
- if not hasattr(sys, "frozen"):
315
- if not __debug__:
316
- exe = "%s -O" % exe
317
- script = os.path.abspath(sys.modules[cls.__module__].__file__)
318
- if " " in script:
319
- script = '"%s"' % script
320
- append(
321
- HKCR,
322
- "CLSID\\%s\\LocalServer32" % reg_clsid,
323
- "",
324
- "%s %s" % (exe, script),
325
- )
326
- else:
327
- append(HKCR, "CLSID\\%s\\LocalServer32" % reg_clsid, "", "%s" % exe)
328
-
329
- # Register InprocServer32 only when run from script or from
330
- # py2exe dll server, not from py2exe exe server.
331
- if clsctx & comtypes.CLSCTX_INPROC_SERVER and getattr(sys, "frozen", None) in (
332
- None,
333
- "dll",
334
- ):
335
- append(
336
- HKCR, "CLSID\\%s\\InprocServer32" % reg_clsid, "", self._get_serverdll()
337
- )
338
- # only for non-frozen inproc servers the PythonPath/PythonClass is needed.
339
- if (
340
- not hasattr(sys, "frozendllhandle")
341
- or not comtypes.server.inprocserver._clsid_to_class
342
- ):
343
- append(
344
- HKCR,
345
- "CLSID\\%s\\InprocServer32" % reg_clsid,
346
- "PythonClass",
347
- self._get_full_classname(cls),
348
- )
349
- append(
350
- HKCR,
351
- "CLSID\\%s\\InprocServer32" % reg_clsid,
352
- "PythonPath",
353
- self._get_pythonpath(cls),
354
- )
355
-
356
- reg_threading = getattr(cls, "_reg_threading_", None)
357
- if reg_threading is not None:
358
- append(
359
- HKCR,
360
- "CLSID\\%s\\InprocServer32" % reg_clsid,
361
- "ThreadingModel",
362
- reg_threading,
363
- )
364
-
365
- reg_tlib = getattr(cls, "_reg_typelib_", None)
366
- if reg_tlib is not None:
367
- append(HKCR, "CLSID\\%s\\Typelib" % reg_clsid, "", reg_tlib[0])
368
-
369
- return table
370
-
371
-
372
- ################################################################
373
-
374
-
375
- def register(cls):
376
- Registrar().register(cls)
377
-
378
-
379
- def unregister(cls):
380
- Registrar().unregister(cls)
381
-
382
-
383
- def UseCommandLine(*classes):
384
- usage = (
385
- """Usage: %s [-regserver] [-unregserver] [-nodebug] [-f logformat] [-l loggername=level]"""
386
- % sys.argv[0]
387
- )
388
- opts, args = w_getopt.w_getopt(
389
- sys.argv[1:], "regserver unregserver embedding l: f: nodebug"
390
- )
391
- if not opts:
392
- sys.stderr.write(usage + "\n")
393
- return 0 # nothing for us to do
394
-
395
- levels = []
396
- format = None
397
- nodebug = False
398
- runit = False
399
- for option, value in opts:
400
- if option == "regserver":
401
- for cls in classes:
402
- register(cls)
403
- elif option == "unregserver":
404
- for cls in classes:
405
- unregister(cls)
406
- elif option == "embedding":
407
- runit = True
408
- elif option == "f":
409
- format = value
410
- elif option == "l":
411
- levels.append(value)
412
- elif option == "nodebug":
413
- nodebug = True
414
-
415
- if levels or format is not None:
416
- for cls in classes:
417
- Registrar().debug(cls, levels, format)
418
- if nodebug:
419
- for cls in classes:
420
- Registrar().nodebug(cls)
421
-
422
- if runit:
423
- import comtypes.server.localserver
424
-
425
- comtypes.server.localserver.run(classes)
426
-
427
- return 1 # we have done something
428
-
429
-
430
- if __name__ == "__main__":
431
- UseCommandLine()
@@ -1,75 +0,0 @@
1
- class GetoptError(Exception):
2
- pass
3
-
4
-
5
- def w_getopt(args, options):
6
- """A getopt for Windows.
7
-
8
- Options may start with either '-' or '/', the option names may
9
- have more than one letter (/tlb or -RegServer), and option names
10
- are case insensitive.
11
-
12
- Returns two elements, just as getopt.getopt. The first is a list
13
- of (option, value) pairs in the same way getopt.getopt does, but
14
- there is no '-' or '/' prefix to the option name, and the option
15
- name is always lower case. The second is the list of arguments
16
- which do not belong to an option.
17
-
18
- Different from getopt.getopt, a single argument not belonging to an option
19
- does not terminate parsing.
20
- """
21
- opts = []
22
- arguments = []
23
- while args:
24
- if args[0][:1] in "/-":
25
- arg = args[0][1:] # strip the '-' or '/'
26
- arg = arg.lower()
27
-
28
- if arg + ":" in options:
29
- try:
30
- opts.append((arg, args[1]))
31
- except IndexError:
32
- raise GetoptError("option '%s' requires an argument" % args[0])
33
- args = args[1:]
34
- elif arg in options:
35
- opts.append((arg, ""))
36
- else:
37
- raise GetoptError("invalid option '%s'" % args[0])
38
- args = args[1:]
39
- else:
40
- arguments.append(args[0])
41
- args = args[1:]
42
-
43
- return opts, arguments
44
-
45
-
46
- if __debug__:
47
- if __name__ == "__main__":
48
- import unittest
49
-
50
- class TestCase(unittest.TestCase):
51
- def test_1(self):
52
- args = "-embedding spam /RegServer foo /UnregSERVER blabla".split()
53
- opts, args = w_getopt(args, "regserver unregserver embedding".split())
54
- self.assertEqual(
55
- opts, [("embedding", ""), ("regserver", ""), ("unregserver", "")]
56
- )
57
- self.assertEqual(args, ["spam", "foo", "blabla"])
58
-
59
- def test_2(self):
60
- args = "/TLB Hello.Tlb HELLO.idl".split()
61
- opts, args = w_getopt(args, ["tlb:"])
62
- self.assertEqual(opts, [("tlb", "Hello.Tlb")])
63
- self.assertEqual(args, ["HELLO.idl"])
64
-
65
- def test_3(self):
66
- # Invalid option
67
- self.assertRaises(
68
- GetoptError, w_getopt, "/TLIB hello.tlb hello.idl".split(), ["tlb:"]
69
- )
70
-
71
- def test_4(self):
72
- # Missing argument
73
- self.assertRaises(GetoptError, w_getopt, "/TLB".split(), ["tlb:"])
74
-
75
- unittest.main()
@@ -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)