comtypes 1.4.7__zip → 1.4.9__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 (149) hide show
  1. {comtypes-1.4.7 → comtypes-1.4.9}/CHANGES.txt +39 -0
  2. {comtypes-1.4.7/comtypes.egg-info → comtypes-1.4.9}/PKG-INFO +6 -4
  3. {comtypes-1.4.7 → comtypes-1.4.9}/README.md +5 -3
  4. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/GUID.py +6 -5
  5. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/__init__.py +16 -5
  6. comtypes-1.4.9/comtypes/_comobject.py +507 -0
  7. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/_memberspec.py +81 -9
  8. comtypes-1.4.9/comtypes/_meta.py +95 -0
  9. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/_npsupport.py +2 -1
  10. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/_post_coinit/__init__.py +1 -0
  11. comtypes-1.4.9/comtypes/_post_coinit/_cominterface_meta_patcher.py +153 -0
  12. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/_post_coinit/misc.py +21 -40
  13. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/_post_coinit/unknwn.py +88 -209
  14. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/_safearray.py +1 -2
  15. comtypes-1.4.9/comtypes/_vtbl.py +448 -0
  16. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/automation.py +36 -45
  17. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/client/__init__.py +21 -31
  18. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/client/_code_cache.py +5 -4
  19. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/client/_constants.py +1 -1
  20. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/client/_events.py +1 -2
  21. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/client/_generate.py +9 -13
  22. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/client/lazybind.py +2 -7
  23. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/errorinfo.py +3 -3
  24. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/git.py +2 -2
  25. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/hints.pyi +11 -19
  26. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/persist.py +7 -7
  27. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/safearray.py +12 -6
  28. comtypes-1.4.9/comtypes/server/__init__.py +86 -0
  29. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/server/inprocserver.py +22 -17
  30. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/server/localserver.py +28 -16
  31. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/server/register.py +62 -73
  32. comtypes-1.4.9/comtypes/server/w_getopt.py +48 -0
  33. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/shelllink.py +49 -67
  34. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/TestComServer.py +1 -1
  35. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/TestDispServer.py +1 -1
  36. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/__init__.py +9 -12
  37. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/find_memleak.py +0 -1
  38. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_BSTR.py +4 -7
  39. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_agilent.py +0 -1
  40. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_avmc.py +1 -1
  41. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_casesensitivity.py +3 -5
  42. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_clear_cache.py +1 -0
  43. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_collections.py +3 -3
  44. comtypes-1.4.9/comtypes/test/test_comobject.py +146 -0
  45. comtypes-1.4.9/comtypes/test/test_comserver.py +319 -0
  46. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_createwrappers.py +2 -6
  47. comtypes-1.4.9/comtypes/test/test_dispinterface.py +153 -0
  48. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_excel.py +22 -13
  49. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_ie.py +2 -5
  50. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_inout_args.py +8 -5
  51. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_midl_safearray_create.py +9 -1
  52. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_outparam.py +17 -10
  53. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_safearray.py +1 -90
  54. comtypes-1.4.9/comtypes/test/test_server.py +350 -0
  55. comtypes-1.4.9/comtypes/test/test_server_register.py +536 -0
  56. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_shelllink.py +10 -14
  57. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_showevents.py +7 -17
  58. comtypes-1.4.9/comtypes/test/test_stream.py +131 -0
  59. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_typeannotator.py +1 -1
  60. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_urlhistory.py +1 -0
  61. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_variant.py +0 -19
  62. comtypes-1.4.9/comtypes/test/test_w_getopt.py +29 -0
  63. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_win32com_interop.py +80 -36
  64. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_wmi.py +0 -3
  65. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/codegenerator/codegenerator.py +62 -68
  66. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/codegenerator/helpers.py +8 -8
  67. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/codegenerator/namespaces.py +97 -27
  68. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/codegenerator/packing.py +4 -4
  69. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/codegenerator/typeannotator.py +9 -11
  70. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/tlbparser.py +33 -32
  71. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/typedesc.py +3 -8
  72. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/typeinfo.py +32 -47
  73. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/util.py +1 -0
  74. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/viewobject.py +1 -5
  75. {comtypes-1.4.7 → comtypes-1.4.9/comtypes.egg-info}/PKG-INFO +6 -4
  76. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes.egg-info/SOURCES.txt +6 -3
  77. comtypes-1.4.9/pyproject.toml +55 -0
  78. comtypes-1.4.7/comtypes/_comobject.py +0 -834
  79. comtypes-1.4.7/comtypes/_idl_stuff.py +0 -67
  80. comtypes-1.4.7/comtypes/_meta.py +0 -70
  81. comtypes-1.4.7/comtypes/server/__init__.py +0 -69
  82. comtypes-1.4.7/comtypes/server/w_getopt.py +0 -75
  83. comtypes-1.4.7/comtypes/test/test_comserver.py +0 -239
  84. comtypes-1.4.7/comtypes/test/test_dispinterface.py +0 -138
  85. comtypes-1.4.7/comtypes/test/test_propputref.py +0 -40
  86. comtypes-1.4.7/comtypes/test/test_server.py +0 -348
  87. comtypes-1.4.7/comtypes/test/test_stream.py +0 -53
  88. comtypes-1.4.7/pyproject.toml +0 -3
  89. {comtypes-1.4.7 → comtypes-1.4.9}/LICENSE.txt +0 -0
  90. {comtypes-1.4.7 → comtypes-1.4.9}/MANIFEST.in +0 -0
  91. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/_post_coinit/bstr.py +0 -0
  92. /comtypes-1.4.7/comtypes/_py_instance_method.py → /comtypes-1.4.9/comtypes/_post_coinit/instancemethod.py +0 -0
  93. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/_tlib_version_checker.py +0 -0
  94. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/clear_cache.py +0 -0
  95. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/client/dynamic.py +0 -0
  96. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/connectionpoints.py +0 -0
  97. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/hresult.py +0 -0
  98. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/logutil.py +0 -0
  99. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/messageloop.py +0 -0
  100. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/patcher.py +0 -0
  101. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/server/automation.py +0 -0
  102. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/server/connectionpoints.py +0 -0
  103. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/stream.py +0 -0
  104. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/TestComServer.idl +0 -0
  105. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/TestComServer.tlb +0 -0
  106. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/TestDispServer.idl +0 -0
  107. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/TestDispServer.tlb +0 -0
  108. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/mylib.idl +0 -0
  109. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/mylib.tlb +0 -0
  110. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/mytypelib.idl +0 -0
  111. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/runtests.py +0 -0
  112. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/setup.py +0 -0
  113. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_DISPPARAMS.py +0 -0
  114. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_GUID.py +0 -0
  115. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_QueryService.py +0 -0
  116. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_basic.py +0 -0
  117. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_client.py +0 -0
  118. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_client_dynamic.py +0 -0
  119. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_client_regenerate_modules.py +0 -0
  120. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_dict.py +0 -0
  121. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_dispifc_records.py +0 -0
  122. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_dispifc_safearrays.py +0 -0
  123. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_dyndispatch.py +0 -0
  124. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_findgendir.py +0 -0
  125. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_getactiveobj.py +0 -0
  126. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_ienum.py +0 -0
  127. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_imfattributes.py +0 -0
  128. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_jscript.js +0 -0
  129. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_monikers.py +0 -0
  130. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_msscript.py +0 -0
  131. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_npsupport.py +0 -0
  132. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_persist.py +0 -0
  133. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_pump_events.py +0 -0
  134. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_recordinfo.py +0 -0
  135. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_sapi.py +0 -0
  136. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_storage.py +0 -0
  137. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_subinterface.py +0 -0
  138. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_typeinfo.py +0 -0
  139. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_word.py +0 -0
  140. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/urlhist.tlb +0 -0
  141. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/__init__.py +0 -0
  142. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/codegenerator/__init__.py +0 -0
  143. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/codegenerator/modulenamer.py +0 -0
  144. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/typedesc_base.py +0 -0
  145. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes.egg-info/dependency_links.txt +0 -0
  146. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes.egg-info/entry_points.txt +0 -0
  147. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes.egg-info/top_level.txt +0 -0
  148. {comtypes-1.4.7 → comtypes-1.4.9}/setup.cfg +0 -0
  149. {comtypes-1.4.7 → comtypes-1.4.9}/setup.py +0 -0
@@ -0,0 +1,536 @@
1
+ import _ctypes
2
+ import ctypes
3
+ import os
4
+ import sys
5
+ import unittest as ut
6
+ import winreg
7
+ from unittest import mock
8
+
9
+ import comtypes
10
+ import comtypes.server.inprocserver
11
+ from comtypes import GUID
12
+ from comtypes.server import register
13
+ from comtypes.server.register import Registrar, RegistryEntries, _get_serverdll
14
+
15
+ HKCR = winreg.HKEY_CLASSES_ROOT
16
+ MULTI_SZ = winreg.REG_MULTI_SZ
17
+ SZ = winreg.REG_SZ
18
+
19
+
20
+ class Test_Registrar_nodebug(ut.TestCase):
21
+ @mock.patch.object(register, "winreg")
22
+ def test_calls_openkey_and_deletekey(self, _winreg):
23
+ _winreg.HKEY_CLASSES_ROOT = HKCR
24
+ hkey = mock.Mock(spec=winreg.HKEYType)
25
+ _winreg.OpenKey.return_value = hkey
26
+ reg_clsid = GUID.create_new()
27
+ registrar = Registrar()
28
+
29
+ class Cls:
30
+ _reg_clsid_ = reg_clsid
31
+
32
+ registrar.nodebug(Cls)
33
+ _winreg.OpenKey.assert_called_once_with(HKCR, rf"CLSID\{reg_clsid}")
34
+ _winreg.DeleteKey.assert_called_once_with(hkey, "Logging")
35
+
36
+ @mock.patch.object(register, "winreg")
37
+ def test_ignores_winerror(self, _winreg):
38
+ _winreg.HKEY_CLASSES_ROOT = HKCR
39
+ ERROR_FILE_NOT_FOUND = 2
40
+ err = OSError(ERROR_FILE_NOT_FOUND, "msg", "filename", ERROR_FILE_NOT_FOUND)
41
+ _winreg.OpenKey.side_effect = err
42
+ reg_clsid = GUID.create_new()
43
+ registrar = Registrar()
44
+
45
+ class Cls:
46
+ _reg_clsid_ = reg_clsid
47
+
48
+ registrar.nodebug(Cls)
49
+ _winreg.OpenKey.assert_called_once_with(HKCR, rf"CLSID\{reg_clsid}")
50
+ _winreg.DeleteKey.assert_not_called()
51
+
52
+ @mock.patch.object(register, "winreg")
53
+ def test_not_ignores_winerror(self, _winreg):
54
+ _winreg.HKEY_CLASSES_ROOT = HKCR
55
+ hkey = mock.Mock(spec=winreg.HKEYType)
56
+ _winreg.OpenKey.return_value = hkey
57
+ ERROR_ACCESS_DENIED = 5
58
+ err = OSError(ERROR_ACCESS_DENIED, "msg", "filename", ERROR_ACCESS_DENIED)
59
+ _winreg.OpenKey.return_value = hkey
60
+ _winreg.DeleteKey.side_effect = err
61
+ reg_clsid = GUID.create_new()
62
+ registrar = Registrar()
63
+
64
+ class Cls:
65
+ _reg_clsid_ = reg_clsid
66
+
67
+ with self.assertRaises(OSError) as e:
68
+ registrar.nodebug(Cls)
69
+ self.assertEqual(e.exception.winerror, ERROR_ACCESS_DENIED)
70
+ _winreg.OpenKey.assert_called_once_with(HKCR, rf"CLSID\{reg_clsid}")
71
+ _winreg.DeleteKey.assert_called_once_with(hkey, "Logging")
72
+
73
+
74
+ class Test_Registrar_debug(ut.TestCase):
75
+ @mock.patch.object(register, "winreg")
76
+ def test_calls_createkey_and_sets_format(self, _winreg):
77
+ _winreg.HKEY_CLASSES_ROOT = HKCR
78
+ _winreg.REG_MULTI_SZ = MULTI_SZ
79
+ _winreg.REG_SZ = SZ
80
+ hkey = mock.Mock(spec=winreg.HKEYType)
81
+ _winreg.CreateKey.return_value = hkey
82
+ levels = ["lv=DEBUG"]
83
+ format = "FMT"
84
+ reg_clsid = GUID.create_new()
85
+ registrar = Registrar()
86
+
87
+ class Cls:
88
+ _reg_clsid_ = reg_clsid
89
+
90
+ registrar.debug(Cls, levels, format)
91
+ _winreg.CreateKey.assert_called_once_with(HKCR, rf"CLSID\{reg_clsid}\Logging")
92
+ self.assertEqual(
93
+ _winreg.SetValueEx.call_args_list,
94
+ [
95
+ mock.call(hkey, "levels", None, MULTI_SZ, levels),
96
+ mock.call(hkey, "format", None, SZ, format),
97
+ ],
98
+ )
99
+
100
+ @mock.patch.object(register, "winreg")
101
+ def test_calls_createkey_and_deletes_format(self, _winreg):
102
+ _winreg.HKEY_CLASSES_ROOT = HKCR
103
+ _winreg.REG_MULTI_SZ = MULTI_SZ
104
+ hkey = mock.Mock(spec=winreg.HKEYType)
105
+ _winreg.CreateKey.return_value = hkey
106
+ levels = ["lv=DEBUG"]
107
+ reg_clsid = GUID.create_new()
108
+ registrar = Registrar()
109
+
110
+ class Cls:
111
+ _reg_clsid_ = reg_clsid
112
+
113
+ registrar.debug(Cls, levels, None)
114
+ _winreg.CreateKey.assert_called_once_with(HKCR, rf"CLSID\{reg_clsid}\Logging")
115
+ _winreg.SetValueEx.assert_called_once_with(
116
+ hkey, "levels", None, MULTI_SZ, levels
117
+ )
118
+ _winreg.DeleteValue.assert_called_once_with(hkey, "format")
119
+
120
+ @mock.patch.object(register, "winreg")
121
+ def test_calls_createkey_and_ignores_errors_on_deleting(self, _winreg):
122
+ _winreg.HKEY_CLASSES_ROOT = HKCR
123
+ _winreg.REG_MULTI_SZ = MULTI_SZ
124
+ hkey = mock.Mock(spec=winreg.HKEYType)
125
+ _winreg.CreateKey.return_value = hkey
126
+ ERROR_FILE_NOT_FOUND = 2
127
+ err = OSError(ERROR_FILE_NOT_FOUND, "msg", "filename", ERROR_FILE_NOT_FOUND)
128
+ _winreg.DeleteValue.side_effect = err
129
+ levels = ["lv=DEBUG"]
130
+ reg_clsid = GUID.create_new()
131
+ registrar = Registrar()
132
+
133
+ class Cls:
134
+ _reg_clsid_ = reg_clsid
135
+
136
+ registrar.debug(Cls, levels, None)
137
+ _winreg.CreateKey.assert_called_once_with(HKCR, rf"CLSID\{reg_clsid}\Logging")
138
+ _winreg.SetValueEx.assert_called_once_with(
139
+ hkey, "levels", None, MULTI_SZ, levels
140
+ )
141
+ _winreg.DeleteValue.assert_called_once_with(hkey, "format")
142
+
143
+ @mock.patch.object(register, "winreg")
144
+ def test_calls_createkey_and_not_ignores_errors_on_deleting(self, _winreg):
145
+ _winreg.HKEY_CLASSES_ROOT = HKCR
146
+ _winreg.REG_MULTI_SZ = MULTI_SZ
147
+ hkey = mock.Mock(spec=winreg.HKEYType)
148
+ _winreg.CreateKey.return_value = hkey
149
+ ERROR_ACCESS_DENIED = 5
150
+ err = OSError(ERROR_ACCESS_DENIED, "msg", "filename", ERROR_ACCESS_DENIED)
151
+ _winreg.DeleteValue.side_effect = err
152
+ levels = ["lv=DEBUG"]
153
+ reg_clsid = GUID.create_new()
154
+ registrar = Registrar()
155
+
156
+ class Cls:
157
+ _reg_clsid_ = reg_clsid
158
+
159
+ with self.assertRaises(OSError) as e:
160
+ registrar.debug(Cls, levels, None)
161
+ self.assertEqual(e.exception.winerror, ERROR_ACCESS_DENIED)
162
+ _winreg.CreateKey.assert_called_once_with(HKCR, rf"CLSID\{reg_clsid}\Logging")
163
+ _winreg.SetValueEx.assert_called_once_with(
164
+ hkey, "levels", None, MULTI_SZ, levels
165
+ )
166
+ _winreg.DeleteValue.assert_called_once_with(hkey, "format")
167
+
168
+
169
+ class Test_Registrar_register(ut.TestCase):
170
+ def test_calls_cls_register(self):
171
+ cls = mock.Mock(spec=["_register"])
172
+ registrar = Registrar()
173
+ registrar.register(cls)
174
+ cls._register.assert_called_once_with(registrar)
175
+
176
+ # The coverage for COM server registration is ensured by the setup
177
+ # of `test_comserver` and `test_dispinterface`, so no additional tests
178
+ # are performed here now.
179
+
180
+
181
+ class Test_Registrar_unregister(ut.TestCase):
182
+ def test_calls_cls_unregister(self):
183
+ cls = mock.Mock(spec=["_unregister"])
184
+ registrar = Registrar()
185
+ registrar.unregister(cls)
186
+ cls._unregister.assert_called_once_with(registrar)
187
+
188
+ # The coverage for COM server unregistration is ensured by the teardown
189
+ # of `test_comserver` and `test_dispinterface`, so no additional tests
190
+ # are performed here now.
191
+
192
+
193
+ class Test_get_serverdll(ut.TestCase):
194
+ def test_nonfrozen(self):
195
+ self.assertEqual(_ctypes.__file__, _get_serverdll())
196
+
197
+ def test_frozen(self):
198
+ with mock.patch.object(register, "sys") as _sys:
199
+ with mock.patch.object(register, "windll") as _windll:
200
+ handle = 1234
201
+ _sys.frozendllhandle = handle
202
+ self.assertEqual(b"\x00" * 260, _get_serverdll())
203
+ GetModuleFileName = _windll.kernel32.GetModuleFileNameA
204
+ (((hModule, lpFilename, nSize), _),) = GetModuleFileName.call_args_list
205
+ self.assertEqual(handle, hModule)
206
+ buf_type = type(ctypes.create_string_buffer(260))
207
+ self.assertIsInstance(lpFilename, buf_type)
208
+ self.assertEqual(260, nSize)
209
+
210
+
211
+ class Test_NonFrozen_RegistryEntries(ut.TestCase):
212
+ def test_reg_clsid(self):
213
+ reg_clsid = GUID.create_new()
214
+
215
+ class Cls:
216
+ _reg_clsid_ = reg_clsid
217
+
218
+ expected = [(HKCR, rf"CLSID\{reg_clsid}", "", "")]
219
+ self.assertEqual(expected, list(RegistryEntries(Cls)))
220
+
221
+ def test_reg_desc(self):
222
+ reg_clsid = GUID.create_new()
223
+ reg_desc = "description for testing"
224
+
225
+ class Cls:
226
+ _reg_clsid_ = reg_clsid
227
+ _reg_desc_ = reg_desc
228
+
229
+ expected = [(HKCR, rf"CLSID\{reg_clsid}", "", reg_desc)]
230
+ self.assertEqual(expected, list(RegistryEntries(Cls)))
231
+
232
+ def test_reg_novers_progid(self):
233
+ reg_clsid = GUID.create_new()
234
+ reg_novers_progid = "Lib.Server"
235
+
236
+ class Cls:
237
+ _reg_clsid_ = reg_clsid
238
+ _reg_novers_progid_ = reg_novers_progid
239
+
240
+ expected = [(HKCR, rf"CLSID\{reg_clsid}", "", "Lib Server")]
241
+ self.assertEqual(expected, list(RegistryEntries(Cls)))
242
+
243
+ def test_progid(self):
244
+ reg_clsid = GUID.create_new()
245
+ reg_progid = "Lib.Server.1"
246
+
247
+ class Cls:
248
+ _reg_clsid_ = reg_clsid
249
+ _reg_progid_ = reg_progid
250
+
251
+ expected = [
252
+ (HKCR, rf"CLSID\{reg_clsid}", "", "Lib Server 1"),
253
+ (HKCR, rf"CLSID\{reg_clsid}\ProgID", "", reg_progid),
254
+ (HKCR, reg_progid, "", "Lib Server 1"),
255
+ (HKCR, rf"{reg_progid}\CLSID", "", str(reg_clsid)),
256
+ ]
257
+ self.assertEqual(expected, list(RegistryEntries(Cls)))
258
+
259
+ def test_reg_progid_reg_desc(self):
260
+ reg_clsid = GUID.create_new()
261
+ reg_progid = "Lib.Server.1"
262
+ reg_desc = "description for testing"
263
+
264
+ class Cls:
265
+ _reg_clsid_ = reg_clsid
266
+ _reg_progid_ = reg_progid
267
+ _reg_desc_ = reg_desc
268
+
269
+ expected = [
270
+ (HKCR, rf"CLSID\{reg_clsid}", "", reg_desc),
271
+ (HKCR, rf"CLSID\{reg_clsid}\ProgID", "", reg_progid),
272
+ (HKCR, reg_progid, "", "description for testing"),
273
+ (HKCR, rf"{reg_progid}\CLSID", "", str(reg_clsid)),
274
+ ]
275
+ self.assertEqual(expected, list(RegistryEntries(Cls)))
276
+
277
+ def test_reg_progid_reg_novers_progid(self):
278
+ reg_clsid = GUID.create_new()
279
+ reg_progid = "Lib.Server.1"
280
+ reg_novers_progid = "Lib.Server"
281
+
282
+ class Cls:
283
+ _reg_clsid_ = reg_clsid
284
+ _reg_progid_ = reg_progid
285
+ _reg_novers_progid_ = reg_novers_progid
286
+
287
+ clsid_sub = rf"CLSID\{reg_clsid}"
288
+ expected = [
289
+ (HKCR, clsid_sub, "", "Lib Server"),
290
+ (HKCR, rf"{clsid_sub}\ProgID", "", reg_progid),
291
+ (HKCR, reg_progid, "", "Lib Server"),
292
+ (HKCR, rf"{reg_progid}\CLSID", "", str(reg_clsid)),
293
+ (HKCR, rf"{clsid_sub}\VersionIndependentProgID", "", reg_novers_progid),
294
+ (HKCR, reg_novers_progid, "", "Lib Server"),
295
+ (HKCR, rf"{reg_novers_progid}\CurVer", "", "Lib.Server.1"),
296
+ (HKCR, rf"{reg_novers_progid}\CLSID", "", str(reg_clsid)),
297
+ ]
298
+ self.assertEqual(expected, list(RegistryEntries(Cls)))
299
+
300
+ def test_local_server(self):
301
+ reg_clsid = GUID.create_new()
302
+ reg_clsctx = comtypes.CLSCTX_LOCAL_SERVER
303
+
304
+ class Cls:
305
+ _reg_clsid_ = reg_clsid
306
+ _reg_clsctx_ = reg_clsctx
307
+
308
+ clsid_sub = rf"CLSID\{reg_clsid}"
309
+ local_srv_sub = rf"{clsid_sub}\LocalServer32"
310
+ expected = [
311
+ (HKCR, clsid_sub, "", ""),
312
+ (HKCR, local_srv_sub, "", f"{sys.executable} {__file__}"),
313
+ ]
314
+ self.assertEqual(expected, list(RegistryEntries(Cls)))
315
+
316
+ def test_inproc_server(self):
317
+ reg_clsid = GUID.create_new()
318
+ reg_clsctx = comtypes.CLSCTX_INPROC_SERVER
319
+
320
+ class Cls:
321
+ _reg_clsid_ = reg_clsid
322
+ _reg_clsctx_ = reg_clsctx
323
+
324
+ clsid_sub = rf"CLSID\{reg_clsid}"
325
+ inproc_srv_sub = rf"{clsid_sub}\InprocServer32"
326
+ full_classname = f"{__name__}.Cls"
327
+ expected = [
328
+ (HKCR, clsid_sub, "", ""),
329
+ (HKCR, inproc_srv_sub, "", _ctypes.__file__),
330
+ (HKCR, inproc_srv_sub, "PythonClass", full_classname),
331
+ (HKCR, inproc_srv_sub, "PythonPath", os.path.dirname(__file__)),
332
+ ]
333
+ self.assertEqual(expected, list(RegistryEntries(Cls)))
334
+
335
+ def test_inproc_server_reg_threading(self):
336
+ reg_clsid = GUID.create_new()
337
+ reg_threading = "Both"
338
+ reg_clsctx = comtypes.CLSCTX_INPROC_SERVER
339
+
340
+ class Cls:
341
+ _reg_clsid_ = reg_clsid
342
+ _reg_threading_ = reg_threading
343
+ _reg_clsctx_ = reg_clsctx
344
+
345
+ clsid_sub = rf"CLSID\{reg_clsid}"
346
+ inproc_srv_sub = rf"{clsid_sub}\InprocServer32"
347
+ full_classname = f"{__name__}.Cls"
348
+ expected = [
349
+ (HKCR, clsid_sub, "", ""),
350
+ (HKCR, inproc_srv_sub, "", _ctypes.__file__),
351
+ (HKCR, inproc_srv_sub, "PythonClass", full_classname),
352
+ (HKCR, inproc_srv_sub, "PythonPath", os.path.dirname(__file__)),
353
+ (HKCR, inproc_srv_sub, "ThreadingModel", reg_threading),
354
+ ]
355
+ self.assertEqual(expected, list(RegistryEntries(Cls)))
356
+
357
+ def test_reg_typelib(self):
358
+ reg_clsid = GUID.create_new()
359
+ libid = str(GUID.create_new())
360
+ reg_typelib = (libid, 1, 0)
361
+
362
+ class Cls:
363
+ _reg_clsid_ = reg_clsid
364
+ _reg_typelib_ = reg_typelib
365
+
366
+ expected = [
367
+ (HKCR, rf"CLSID\{reg_clsid}", "", ""),
368
+ (HKCR, rf"CLSID\{reg_clsid}\Typelib", "", libid),
369
+ ]
370
+ self.assertEqual(expected, list(RegistryEntries(Cls)))
371
+
372
+ def test_all_entries(self):
373
+ reg_clsid = GUID.create_new()
374
+ libid = str(GUID.create_new())
375
+ reg_typelib = (libid, 1, 0)
376
+ reg_threading = "Both"
377
+ reg_progid = "Lib.Server.1"
378
+ reg_novers_progid = "Lib.Server"
379
+ reg_desc = "description for testing"
380
+ reg_clsctx = comtypes.CLSCTX_INPROC_SERVER | comtypes.CLSCTX_LOCAL_SERVER
381
+
382
+ class Cls:
383
+ _reg_clsid_ = reg_clsid
384
+ _reg_typelib_ = reg_typelib
385
+ _reg_threading_ = reg_threading
386
+ _reg_progid_ = reg_progid
387
+ _reg_novers_progid_ = reg_novers_progid
388
+ _reg_desc_ = reg_desc
389
+ _reg_clsctx_ = reg_clsctx
390
+
391
+ clsid_sub = rf"CLSID\{reg_clsid}"
392
+ inproc_srv_sub = rf"{clsid_sub}\InprocServer32"
393
+ local_srv_sub = rf"{clsid_sub}\LocalServer32"
394
+ full_classname = f"{__name__}.Cls"
395
+ expected = [
396
+ (HKCR, clsid_sub, "", reg_desc),
397
+ (HKCR, rf"{clsid_sub}\ProgID", "", reg_progid),
398
+ (HKCR, reg_progid, "", reg_desc),
399
+ (HKCR, rf"{reg_progid}\CLSID", "", str(reg_clsid)),
400
+ (HKCR, rf"{clsid_sub}\VersionIndependentProgID", "", reg_novers_progid),
401
+ (HKCR, reg_novers_progid, "", reg_desc),
402
+ (HKCR, rf"{reg_novers_progid}\CurVer", "", reg_progid),
403
+ (HKCR, rf"{reg_novers_progid}\CLSID", "", str(reg_clsid)),
404
+ (HKCR, local_srv_sub, "", f"{sys.executable} {__file__}"),
405
+ (HKCR, inproc_srv_sub, "", _ctypes.__file__),
406
+ (HKCR, inproc_srv_sub, "PythonClass", full_classname),
407
+ (HKCR, inproc_srv_sub, "PythonPath", os.path.dirname(__file__)),
408
+ (HKCR, inproc_srv_sub, "ThreadingModel", reg_threading),
409
+ (HKCR, rf"{clsid_sub}\Typelib", "", libid),
410
+ ]
411
+ self.assertEqual(expected, list(RegistryEntries(Cls)))
412
+
413
+
414
+ class Test_Frozen_RegistryEntries(ut.TestCase):
415
+ @mock.patch.object(register, "sys")
416
+ def test_local_dll(self, _sys):
417
+ _sys.mock_add_spec(["executable", "frozen"])
418
+ _sys.executable = sys.executable
419
+ _sys.frozen = "dll"
420
+ reg_clsid = GUID.create_new()
421
+ reg_clsctx = comtypes.CLSCTX_LOCAL_SERVER
422
+
423
+ class Cls:
424
+ _reg_clsid_ = reg_clsid
425
+ _reg_clsctx_ = reg_clsctx
426
+
427
+ clsid_sub = rf"CLSID\{reg_clsid}"
428
+ expected = [
429
+ (HKCR, clsid_sub, "", ""),
430
+ (HKCR, rf"{clsid_sub}\LocalServer32", "", sys.executable),
431
+ ]
432
+ self.assertEqual(expected, list(RegistryEntries(Cls)))
433
+
434
+ @mock.patch.object(register, "sys")
435
+ def test_local_frozendllhandle(self, _sys):
436
+ _sys.mock_add_spec(["frozen", "frozendllhandle"])
437
+ _sys.frozen = "dll"
438
+ _sys.frozendllhandle = 1234
439
+ reg_clsid = GUID.create_new()
440
+ reg_clsctx = comtypes.CLSCTX_LOCAL_SERVER
441
+
442
+ class Cls:
443
+ _reg_clsid_ = reg_clsid
444
+ _reg_clsctx_ = reg_clsctx
445
+
446
+ expected = [(HKCR, rf"CLSID\{reg_clsid}", "", "")]
447
+ self.assertEqual(expected, list(RegistryEntries(Cls)))
448
+
449
+ @mock.patch.object(register, "sys")
450
+ def test_inproc_windows_exe(self, _sys):
451
+ _sys.mock_add_spec(["frozen"])
452
+ _sys.frozen = "windows_exe"
453
+ reg_clsid = GUID.create_new()
454
+ reg_clsctx = comtypes.CLSCTX_INPROC_SERVER
455
+
456
+ class Cls:
457
+ _reg_clsid_ = reg_clsid
458
+ _reg_clsctx_ = reg_clsctx
459
+
460
+ expected = [(HKCR, rf"CLSID\{reg_clsid}", "", "")]
461
+ self.assertEqual(expected, list(RegistryEntries(Cls)))
462
+
463
+ @mock.patch.object(register, "_get_serverdll", lambda: r"my\target\server.dll")
464
+ @mock.patch.object(register, "sys")
465
+ def test_inproc_dll_frozendllhandle_clsid_to_class(self, _sys):
466
+ _sys.mock_add_spec(["frozen", "frozendllhandle"])
467
+ _sys.frozen = "dll"
468
+ _sys.frozendllhandle = 1234
469
+ reg_clsid = GUID.create_new()
470
+ reg_clsctx = comtypes.CLSCTX_INPROC_SERVER
471
+
472
+ class Cls:
473
+ _reg_clsid_ = reg_clsid
474
+ _reg_clsctx_ = reg_clsctx
475
+
476
+ clsid_sub = rf"CLSID\{reg_clsid}"
477
+ inproc_srv_sub = rf"{clsid_sub}\InprocServer32"
478
+ expected = [
479
+ (HKCR, clsid_sub, "", ""),
480
+ (HKCR, inproc_srv_sub, "", r"my\target\server.dll"),
481
+ ]
482
+
483
+ with mock.patch.dict(comtypes.server.inprocserver._clsid_to_class):
484
+ comtypes.server.inprocserver._clsid_to_class.update({5678: Cls})
485
+ self.assertEqual(expected, list(RegistryEntries(Cls)))
486
+
487
+ @mock.patch.object(register, "_get_serverdll", lambda: r"my\target\server.dll")
488
+ @mock.patch.object(register, "sys")
489
+ def test_inproc_dll(self, _sys):
490
+ _sys.mock_add_spec(["frozen", "modules"])
491
+ _sys.frozen = "dll"
492
+ _sys.modules = sys.modules
493
+ reg_clsid = GUID.create_new()
494
+ reg_clsctx = comtypes.CLSCTX_INPROC_SERVER
495
+
496
+ class Cls:
497
+ _reg_clsid_ = reg_clsid
498
+ _reg_clsctx_ = reg_clsctx
499
+
500
+ clsid_sub = rf"CLSID\{reg_clsid}"
501
+ inproc_srv_sub = rf"{clsid_sub}\InprocServer32"
502
+ full_classname = f"{__name__}.Cls"
503
+ expected = [
504
+ (HKCR, clsid_sub, "", ""),
505
+ (HKCR, inproc_srv_sub, "", r"my\target\server.dll"),
506
+ (HKCR, inproc_srv_sub, "PythonClass", full_classname),
507
+ (HKCR, inproc_srv_sub, "PythonPath", os.path.dirname(__file__)),
508
+ ]
509
+ self.assertEqual(expected, list(RegistryEntries(Cls)))
510
+
511
+ @mock.patch.object(register, "_get_serverdll", lambda: r"my\target\server.dll")
512
+ @mock.patch.object(register, "sys")
513
+ def test_inproc_dll_reg_threading(self, _sys):
514
+ _sys.mock_add_spec(["frozen", "modules"])
515
+ _sys.frozen = "dll"
516
+ _sys.modules = sys.modules
517
+ reg_clsid = GUID.create_new()
518
+ reg_threading = "Both"
519
+ reg_clsctx = comtypes.CLSCTX_INPROC_SERVER
520
+
521
+ class Cls:
522
+ _reg_clsid_ = reg_clsid
523
+ _reg_threading_ = reg_threading
524
+ _reg_clsctx_ = reg_clsctx
525
+
526
+ clsid_sub = rf"CLSID\{reg_clsid}"
527
+ inproc_srv_sub = rf"{clsid_sub}\InprocServer32"
528
+ full_classname = f"{__name__}.Cls"
529
+ expected = [
530
+ (HKCR, clsid_sub, "", ""),
531
+ (HKCR, inproc_srv_sub, "", r"my\target\server.dll"),
532
+ (HKCR, inproc_srv_sub, "PythonClass", full_classname),
533
+ (HKCR, inproc_srv_sub, "PythonPath", os.path.dirname(__file__)),
534
+ (HKCR, inproc_srv_sub, "ThreadingModel", reg_threading),
535
+ ]
536
+ self.assertEqual(expected, list(RegistryEntries(Cls)))
@@ -50,17 +50,15 @@ class Test_IShellLinkA(ut.TestCase):
50
50
  self.assertEqual(shortcut.GetArguments(), b"-f")
51
51
 
52
52
  def test_set_and_get_hotkey(self):
53
- HOTKEYF_ALT = 0x04
54
- HOTKEYF_CONTROL = 0x02
53
+ hotkey = shelllink.HOTKEYF_ALT | shelllink.HOTKEYF_CONTROL
55
54
  shortcut = self._create_shortcut()
56
- shortcut.Hotkey = HOTKEYF_ALT | HOTKEYF_CONTROL
57
- self.assertEqual(shortcut.Hotkey, HOTKEYF_ALT | HOTKEYF_CONTROL)
55
+ shortcut.Hotkey = hotkey
56
+ self.assertEqual(shortcut.Hotkey, hotkey)
58
57
 
59
58
  def test_set_and_get_showcmd(self):
60
- SW_SHOWMAXIMIZED = 0x03
61
59
  shortcut = self._create_shortcut()
62
- shortcut.ShowCmd = SW_SHOWMAXIMIZED
63
- self.assertEqual(shortcut.ShowCmd, SW_SHOWMAXIMIZED)
60
+ shortcut.ShowCmd = shelllink.SW_SHOWMAXIMIZED
61
+ self.assertEqual(shortcut.ShowCmd, shelllink.SW_SHOWMAXIMIZED)
64
62
 
65
63
  def test_set_and_get_icon_location(self):
66
64
  shortcut = self._create_shortcut()
@@ -113,17 +111,15 @@ class Test_IShellLinkW(ut.TestCase):
113
111
  self.assertEqual(shortcut.GetArguments(), "-f")
114
112
 
115
113
  def test_set_and_get_hotkey(self):
116
- HOTKEYF_ALT = 0x04
117
- HOTKEYF_CONTROL = 0x02
114
+ hotkey = shelllink.HOTKEYF_ALT | shelllink.HOTKEYF_CONTROL
118
115
  shortcut = self._create_shortcut()
119
- shortcut.Hotkey = HOTKEYF_ALT | HOTKEYF_CONTROL
120
- self.assertEqual(shortcut.Hotkey, HOTKEYF_ALT | HOTKEYF_CONTROL)
116
+ shortcut.Hotkey = hotkey
117
+ self.assertEqual(shortcut.Hotkey, hotkey)
121
118
 
122
119
  def test_set_and_get_showcmd(self):
123
- SW_SHOWMAXIMIZED = 0x03
124
120
  shortcut = self._create_shortcut()
125
- shortcut.ShowCmd = SW_SHOWMAXIMIZED
126
- self.assertEqual(shortcut.ShowCmd, SW_SHOWMAXIMIZED)
121
+ shortcut.ShowCmd = shelllink.SW_SHOWMAXIMIZED
122
+ self.assertEqual(shortcut.ShowCmd, shelllink.SW_SHOWMAXIMIZED)
127
123
 
128
124
  def test_set_and_get_icon_location(self):
129
125
  shortcut = self._create_shortcut()
@@ -1,24 +1,14 @@
1
1
  import doctest
2
- import sys
3
- import re
4
2
  import unittest
3
+ from typing import Optional
5
4
 
6
5
 
7
- class SixDocChecker(doctest.OutputChecker):
8
- # see https://dirkjan.ochtman.nl/writing/2014/07/06/single-source-python-23-doctests.html
9
- def check_output(self, want, got, optionflags):
10
- if sys.version_info >= (3, 0):
11
- want = re.sub(r"u'(.*?)'", r"'\1'", want)
12
- want = re.sub(r'u"(.*?)"', r'"\1"', want)
13
- return doctest.OutputChecker.check_output(self, want, got, optionflags)
14
-
15
-
16
- def load_tests(loader, tests, ignore):
6
+ def load_tests(
7
+ loader: unittest.TestLoader, tests: unittest.TestSuite, pattern: Optional[str]
8
+ ) -> unittest.TestSuite:
17
9
  import comtypes.test.test_showevents
18
10
 
19
- tests.addTests(
20
- doctest.DocTestSuite(comtypes.test.test_showevents, checker=SixDocChecker())
21
- )
11
+ tests.addTests(doctest.DocTestSuite(comtypes.test.test_showevents))
22
12
  return tests
23
13
 
24
14
 
@@ -32,9 +22,9 @@ class ShowEventsExamples:
32
22
  >>> conn = ShowEvents(font)
33
23
  # event found: FontEvents_FontChanged
34
24
  >>> font.Name = 'Arial'
35
- Event FontEvents_FontChanged(None, u'Name')
25
+ Event FontEvents_FontChanged(None, 'Name')
36
26
  >>> font.Italic = True
37
- Event FontEvents_FontChanged(None, u'Italic')
27
+ Event FontEvents_FontChanged(None, 'Italic')
38
28
  >>> PumpEvents(0.01) # just calling. assertion does in `test_pump_events.py`
39
29
  >>> conn.disconnect()
40
30
  """