comtypes 1.4.1__zip → 1.4.3__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 (116) hide show
  1. {comtypes-1.4.1 → comtypes-1.4.3}/CHANGES.txt +24 -1
  2. {comtypes-1.4.1/comtypes.egg-info → comtypes-1.4.3}/PKG-INFO +29 -1
  3. {comtypes-1.4.1 → comtypes-1.4.3}/README.md +28 -0
  4. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/__init__.py +6 -8
  5. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/automation.py +26 -2
  6. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/client/_generate.py +105 -80
  7. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/hints.pyi +29 -2
  8. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_GUID.py +23 -2
  9. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_client.py +14 -4
  10. comtypes-1.4.3/comtypes/test/test_client_regenerate_modules.py +158 -0
  11. comtypes-1.4.3/comtypes/test/test_dispifc_records.py +90 -0
  12. comtypes-1.4.3/comtypes/test/test_findgendir.py +87 -0
  13. comtypes-1.4.3/comtypes/tools/codegenerator/__init__.py +5 -0
  14. {comtypes-1.4.1/comtypes/tools → comtypes-1.4.3/comtypes/tools/codegenerator}/codegenerator.py +140 -716
  15. comtypes-1.4.3/comtypes/tools/codegenerator/helpers.py +357 -0
  16. comtypes-1.4.3/comtypes/tools/codegenerator/modulenamer.py +24 -0
  17. comtypes-1.4.3/comtypes/tools/codegenerator/namespaces.py +212 -0
  18. comtypes-1.4.3/comtypes/tools/codegenerator/packing.py +81 -0
  19. {comtypes-1.4.1/comtypes/tools → comtypes-1.4.3/comtypes/tools/codegenerator}/typeannotator.py +32 -15
  20. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/tools/tlbparser.py +19 -49
  21. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/tools/typedesc.py +58 -10
  22. {comtypes-1.4.1 → comtypes-1.4.3/comtypes.egg-info}/PKG-INFO +29 -1
  23. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes.egg-info/SOURCES.txt +10 -3
  24. {comtypes-1.4.1 → comtypes-1.4.3}/setup.py +1 -0
  25. comtypes-1.4.1/comtypes/test/test_findgendir.py +0 -94
  26. {comtypes-1.4.1 → comtypes-1.4.3}/LICENSE.txt +0 -0
  27. {comtypes-1.4.1 → comtypes-1.4.3}/MANIFEST.in +0 -0
  28. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/GUID.py +0 -0
  29. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/_comobject.py +0 -0
  30. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/_memberspec.py +0 -0
  31. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/_meta.py +0 -0
  32. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/_npsupport.py +0 -0
  33. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/_safearray.py +0 -0
  34. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/clear_cache.py +0 -0
  35. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/client/__init__.py +0 -0
  36. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/client/_code_cache.py +0 -0
  37. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/client/_constants.py +0 -0
  38. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/client/_events.py +0 -0
  39. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/client/dynamic.py +0 -0
  40. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/client/lazybind.py +0 -0
  41. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/connectionpoints.py +0 -0
  42. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/errorinfo.py +0 -0
  43. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/git.py +0 -0
  44. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/hresult.py +0 -0
  45. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/logutil.py +0 -0
  46. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/messageloop.py +0 -0
  47. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/patcher.py +0 -0
  48. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/persist.py +0 -0
  49. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/safearray.py +0 -0
  50. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/server/__init__.py +0 -0
  51. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/server/automation.py +0 -0
  52. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/server/connectionpoints.py +0 -0
  53. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/server/inprocserver.py +0 -0
  54. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/server/localserver.py +0 -0
  55. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/server/register.py +0 -0
  56. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/server/w_getopt.py +0 -0
  57. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/shelllink.py +0 -0
  58. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/TestComServer.idl +0 -0
  59. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/TestComServer.py +0 -0
  60. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/TestComServer.tlb +0 -0
  61. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/TestDispServer.idl +0 -0
  62. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/TestDispServer.py +0 -0
  63. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/TestDispServer.tlb +0 -0
  64. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/__init__.py +0 -0
  65. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/find_memleak.py +0 -0
  66. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/mylib.idl +0 -0
  67. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/mytypelib.idl +0 -0
  68. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/runtests.py +0 -0
  69. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/setup.py +0 -0
  70. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_BSTR.py +0 -0
  71. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_DISPPARAMS.py +0 -0
  72. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_QueryService.py +0 -0
  73. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_agilent.py +0 -0
  74. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_avmc.py +0 -0
  75. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_basic.py +0 -0
  76. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_casesensitivity.py +0 -0
  77. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_clear_cache.py +0 -0
  78. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_client_dynamic.py +0 -0
  79. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_collections.py +0 -0
  80. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_comserver.py +0 -0
  81. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_createwrappers.py +0 -0
  82. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_dict.py +0 -0
  83. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_dispinterface.py +0 -0
  84. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_dyndispatch.py +0 -0
  85. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_excel.py +0 -0
  86. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_getactiveobj.py +0 -0
  87. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_ie.py +0 -0
  88. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_ienum.py +0 -0
  89. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_imfattributes.py +0 -0
  90. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_inout_args.py +0 -0
  91. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_jscript.js +0 -0
  92. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_msscript.py +0 -0
  93. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_npsupport.py +0 -0
  94. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_outparam.py +0 -0
  95. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_propputref.py +0 -0
  96. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_pump_events.py +0 -0
  97. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_safearray.py +0 -0
  98. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_sapi.py +0 -0
  99. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_server.py +0 -0
  100. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_showevents.py +0 -0
  101. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_subinterface.py +0 -0
  102. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_typeinfo.py +0 -0
  103. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_urlhistory.py +0 -0
  104. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_variant.py +0 -0
  105. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_win32com_interop.py +0 -0
  106. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_wmi.py +0 -0
  107. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_word.py +0 -0
  108. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/tools/__init__.py +0 -0
  109. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/tools/typedesc_base.py +0 -0
  110. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/typeinfo.py +0 -0
  111. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/util.py +0 -0
  112. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/viewobject.py +0 -0
  113. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes.egg-info/dependency_links.txt +0 -0
  114. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes.egg-info/entry_points.txt +0 -0
  115. {comtypes-1.4.1 → comtypes-1.4.3}/comtypes.egg-info/top_level.txt +0 -0
  116. {comtypes-1.4.1 → comtypes-1.4.3}/setup.cfg +0 -0
@@ -0,0 +1,158 @@
1
+ import contextlib
2
+ import importlib
3
+ from pathlib import Path
4
+ import shutil
5
+ import sys
6
+ import tempfile
7
+ import types
8
+ from typing import Iterator
9
+ import unittest as ut
10
+ from unittest import mock
11
+
12
+ import comtypes
13
+ import comtypes.client
14
+ import comtypes.gen
15
+
16
+ comtypes.client.GetModule("scrrun.dll")
17
+ from comtypes.gen import Scripting # noqa
18
+ from comtypes.gen import stdole # noqa
19
+
20
+
21
+ SCRRUN_FRIENDLY = Path(Scripting.__file__)
22
+ SCRRUN_WRAPPER = Path(Scripting.__wrapper_module__.__file__)
23
+ STDOLE_FRIENDLY = Path(stdole.__file__)
24
+ STDOLE_WRAPPER = Path(stdole.__wrapper_module__.__file__)
25
+
26
+
27
+ @contextlib.contextmanager
28
+ def _mkdtmp_gen_dir() -> Iterator[Path]:
29
+ with tempfile.TemporaryDirectory() as t:
30
+ tmp_dir = Path(t)
31
+ tmp_comtypes_dir = tmp_dir / "comtypes"
32
+ tmp_comtypes_dir.mkdir()
33
+ (tmp_comtypes_dir / "__init__.py").touch()
34
+ tmp_comtypes_gen_dir = tmp_comtypes_dir / "gen"
35
+ tmp_comtypes_gen_dir.mkdir()
36
+ (tmp_comtypes_gen_dir / "__init__.py").touch()
37
+ yield tmp_comtypes_gen_dir
38
+
39
+
40
+ @contextlib.contextmanager
41
+ def _patch_gen_pkg(new_path: Path) -> Iterator[types.ModuleType]:
42
+ new_comtypes_init = (new_path / "comtypes" / "__init__.py").resolve()
43
+ assert new_comtypes_init.exists()
44
+ new_comtypes_gen_init = (new_path / "comtypes" / "gen" / "__init__.py").resolve()
45
+ assert new_comtypes_gen_init.exists()
46
+ orig_comtypes = sys.modules["comtypes"]
47
+ orig_gen_names = list(filter(lambda k: k.startswith("comtypes.gen"), sys.modules))
48
+ tmp_sys_path = list(sys.path) # copy
49
+ with mock.patch.object(sys, "path", tmp_sys_path):
50
+ sys.path.insert(0, str(new_path))
51
+ with mock.patch.dict(sys.modules):
52
+ # The reason for removing the parent module (in this case, `comtypes`)
53
+ # from `sys.modules` is because the child module (in this case,
54
+ # `comtypes.gen`) refers to the namespace of the parent module.
55
+ # If the parent module exists in `sys.modules`, Python uses that cache
56
+ # to import the child module. Therefore, in order to import a new version
57
+ # of the child module, it is necessary to temporarily remove the parent
58
+ # module from `sys.modules`.
59
+ del sys.modules["comtypes"]
60
+ for k in orig_gen_names:
61
+ del sys.modules[k]
62
+ # The module that is imported here is not the one cached in `sys.modules`
63
+ # before the patch, but the module that is newly loaded from
64
+ # `new_path / 'comtypes' / 'gen' / '__init__.py'`.
65
+ new_comtypes_gen = importlib.import_module("comtypes.gen")
66
+ assert new_comtypes_gen.__file__ is not None
67
+ assert Path(new_comtypes_gen.__file__).resolve() == new_comtypes_gen_init
68
+ # The `comtypes` module cached in `sys.modules` as a side effect of
69
+ # executing the above line is empty because it is the one loaded from
70
+ # `new_path / 'comtypes' / '__init__.py'`.
71
+ # If we call the test target as it is, an error will occur due to
72
+ # referencing an empty module, so we restore the original `comtypes`
73
+ # to `sys.modules`.
74
+ sys.modules["comtypes"] = orig_comtypes
75
+ assert sys.modules["comtypes.gen"] is new_comtypes_gen
76
+ # By making the empty `comtypes.gen` package we created earlier to be
77
+ # referenced as the `gen` attribute of `comtypes`, the original
78
+ # `comtypes.gen` will not be referenced within the context.
79
+ with mock.patch.object(orig_comtypes, "gen", new_comtypes_gen):
80
+ yield new_comtypes_gen
81
+
82
+
83
+ @contextlib.contextmanager
84
+ def patch_gen_dir() -> Iterator[Path]:
85
+ with _mkdtmp_gen_dir() as tmp_gen_dir:
86
+ with mock.patch.object(comtypes.client, "gen_dir", str(tmp_gen_dir)):
87
+ try:
88
+ with _patch_gen_pkg(tmp_gen_dir.parent.parent):
89
+ yield tmp_gen_dir
90
+ finally:
91
+ importlib.invalidate_caches()
92
+ importlib.reload(comtypes.gen)
93
+ importlib.reload(stdole)
94
+ importlib.reload(Scripting)
95
+
96
+
97
+ class Test(ut.TestCase):
98
+ def test_all_modules_are_missing(self):
99
+ with patch_gen_dir() as gen_dir:
100
+ # ensure `gen_dir` and `sys.modules` are patched.
101
+ with self.assertRaises(ImportError):
102
+ from comtypes.gen import Scripting as _ # noqa
103
+ self.assertFalse((gen_dir / SCRRUN_FRIENDLY.name).exists())
104
+ self.assertFalse((gen_dir / SCRRUN_WRAPPER.name).exists())
105
+ self.assertFalse((gen_dir / STDOLE_FRIENDLY.name).exists())
106
+ self.assertFalse((gen_dir / STDOLE_WRAPPER.name).exists())
107
+ # generate new files and modules.
108
+ comtypes.client.GetModule("scrrun.dll")
109
+ self.assertTrue((gen_dir / SCRRUN_FRIENDLY.name).exists())
110
+ self.assertTrue((gen_dir / SCRRUN_WRAPPER.name).exists())
111
+ self.assertTrue((gen_dir / STDOLE_FRIENDLY.name).exists())
112
+ self.assertTrue((gen_dir / STDOLE_WRAPPER.name).exists())
113
+
114
+ def test_friendly_module_is_missing(self):
115
+ with patch_gen_dir() as gen_dir:
116
+ shutil.copy2(SCRRUN_WRAPPER, gen_dir / SCRRUN_WRAPPER.name)
117
+ wrp_mtime = (gen_dir / SCRRUN_WRAPPER.name).stat().st_mtime_ns
118
+ shutil.copy2(STDOLE_FRIENDLY, gen_dir / STDOLE_FRIENDLY.name)
119
+ shutil.copy2(STDOLE_WRAPPER, gen_dir / STDOLE_WRAPPER.name)
120
+ comtypes.client.GetModule("scrrun.dll")
121
+ self.assertTrue((gen_dir / SCRRUN_FRIENDLY.name).exists())
122
+ # Check the most recent content modification time to confirm whether
123
+ # the module file has been regenerated.
124
+ self.assertGreater(
125
+ (gen_dir / SCRRUN_WRAPPER.name).stat().st_mtime_ns, wrp_mtime
126
+ )
127
+
128
+ def test_wrapper_module_is_missing(self):
129
+ with patch_gen_dir() as gen_dir:
130
+ shutil.copy2(SCRRUN_WRAPPER, gen_dir / SCRRUN_FRIENDLY.name)
131
+ frd_mtime = (gen_dir / SCRRUN_FRIENDLY.name).stat().st_mtime_ns
132
+ shutil.copy2(STDOLE_FRIENDLY, gen_dir / STDOLE_FRIENDLY.name)
133
+ shutil.copy2(STDOLE_WRAPPER, gen_dir / STDOLE_WRAPPER.name)
134
+ comtypes.client.GetModule("scrrun.dll")
135
+ self.assertTrue((gen_dir / SCRRUN_WRAPPER.name).exists())
136
+ self.assertGreater(
137
+ (gen_dir / SCRRUN_FRIENDLY.name).stat().st_mtime_ns, frd_mtime
138
+ )
139
+
140
+ def test_dependency_modules_are_missing(self):
141
+ with patch_gen_dir() as gen_dir:
142
+ shutil.copy2(SCRRUN_WRAPPER, gen_dir / SCRRUN_FRIENDLY.name)
143
+ frd_mtime = (gen_dir / SCRRUN_FRIENDLY.name).stat().st_mtime_ns
144
+ shutil.copy2(SCRRUN_WRAPPER, gen_dir / SCRRUN_WRAPPER.name)
145
+ wrp_mtime = (gen_dir / SCRRUN_WRAPPER.name).stat().st_mtime_ns
146
+ comtypes.client.GetModule("scrrun.dll")
147
+ self.assertTrue((gen_dir / STDOLE_FRIENDLY.name).exists())
148
+ self.assertTrue((gen_dir / STDOLE_WRAPPER.name).exists())
149
+ self.assertGreater(
150
+ (gen_dir / SCRRUN_FRIENDLY.name).stat().st_mtime_ns, frd_mtime
151
+ )
152
+ self.assertGreater(
153
+ (gen_dir / SCRRUN_WRAPPER.name).stat().st_mtime_ns, wrp_mtime
154
+ )
155
+
156
+
157
+ if __name__ == "__main__":
158
+ ut.main()
@@ -0,0 +1,90 @@
1
+ # coding: utf-8
2
+
3
+ import unittest
4
+
5
+ from comtypes import CLSCTX_LOCAL_SERVER
6
+ from comtypes.client import CreateObject, GetModule
7
+ from ctypes import byref, pointer
8
+
9
+ ComtypesCppTestSrvLib_GUID = "{07D2AEE5-1DF8-4D2C-953A-554ADFD25F99}"
10
+
11
+ try:
12
+ GetModule((ComtypesCppTestSrvLib_GUID, 1, 0, 0))
13
+ import comtypes.gen.ComtypesCppTestSrvLib as ComtypesCppTestSrvLib
14
+
15
+ IMPORT_FAILED = False
16
+ except (ImportError, OSError):
17
+ IMPORT_FAILED = True
18
+
19
+
20
+ @unittest.skipIf(IMPORT_FAILED, "This depends on the out of process COM-server.")
21
+ class Test_DispMethods(unittest.TestCase):
22
+ """Test dispmethods with record and record pointer parameters."""
23
+
24
+ EXPECTED_INITED_QUESTIONS = "The meaning of life, the universe and everything?"
25
+
26
+ def _create_dispifc(self) -> "ComtypesCppTestSrvLib.IDispRecordParamTest":
27
+ # Explicitely ask for the dispinterface of the component.
28
+ return CreateObject(
29
+ "Comtypes.DispIfcParamTests",
30
+ clsctx=CLSCTX_LOCAL_SERVER,
31
+ interface=ComtypesCppTestSrvLib.IDispRecordParamTest,
32
+ )
33
+
34
+ def test_inout_byref(self):
35
+ dispifc = self._create_dispifc()
36
+ # Passing a record by reference to a method that has declared the parameter
37
+ # as [in, out] we expect modifications of the record on the server side to
38
+ # also change the record on the client side.
39
+ test_record = ComtypesCppTestSrvLib.StructRecordParamTest()
40
+ self.assertEqual(test_record.question, None)
41
+ self.assertEqual(test_record.answer, 0)
42
+ self.assertEqual(test_record.needs_clarification, False)
43
+ dispifc.InitRecord(byref(test_record))
44
+ self.assertEqual(test_record.question, self.EXPECTED_INITED_QUESTIONS)
45
+ self.assertEqual(test_record.answer, 42)
46
+ self.assertEqual(test_record.needs_clarification, True)
47
+
48
+ def test_inout_pointer(self):
49
+ dispifc = self._create_dispifc()
50
+ # Passing a record pointer to a method that has declared the parameter
51
+ # as [in, out] we expect modifications of the record on the server side to
52
+ # also change the record on the client side.
53
+ test_record = ComtypesCppTestSrvLib.StructRecordParamTest()
54
+ self.assertEqual(test_record.question, None)
55
+ self.assertEqual(test_record.answer, 0)
56
+ self.assertEqual(test_record.needs_clarification, False)
57
+ dispifc.InitRecord(pointer(test_record))
58
+ self.assertEqual(test_record.question, self.EXPECTED_INITED_QUESTIONS)
59
+ self.assertEqual(test_record.answer, 42)
60
+ self.assertEqual(test_record.needs_clarification, True)
61
+
62
+ def test_in_record(self):
63
+ # Passing a record to a method that has declared the parameter just as [in]
64
+ # we expect modifications of the record on the server side NOT to change
65
+ # the record on the client side.
66
+ # We also need to test if the record gets properly passed to the method on
67
+ # the server side. For this, the 'VerifyRecord' method returns 'True' if
68
+ # all record fields have values equivalent to the initialization values
69
+ # provided by 'InitRecord'.
70
+ inited_record = ComtypesCppTestSrvLib.StructRecordParamTest()
71
+ inited_record.question = self.EXPECTED_INITED_QUESTIONS
72
+ inited_record.answer = 42
73
+ inited_record.needs_clarification = True
74
+ for rec, expected, (q, a, nc) in [
75
+ (inited_record, True, (self.EXPECTED_INITED_QUESTIONS, 42, True)),
76
+ # Also perform the inverted test. For this, create a blank record.
77
+ (ComtypesCppTestSrvLib.StructRecordParamTest(), False, (None, 0, False)),
78
+ ]:
79
+ with self.subTest(expected=expected, q=q, a=a, nc=nc):
80
+ # Perform the check on initialization values.
81
+ self.assertEqual(self._create_dispifc().VerifyRecord(rec), expected)
82
+ self.assertEqual(rec.question, q)
83
+ # Check if the 'answer' field is unchanged although the method
84
+ # modifies this field on the server side.
85
+ self.assertEqual(rec.answer, a)
86
+ self.assertEqual(rec.needs_clarification, nc)
87
+
88
+
89
+ if __name__ == "__main__":
90
+ unittest.main()
@@ -0,0 +1,87 @@
1
+ import contextlib
2
+ import importlib
3
+ import os
4
+ import sys
5
+ import tempfile
6
+ import types
7
+ from typing import Iterator
8
+ import unittest
9
+ from unittest import mock
10
+
11
+ import comtypes
12
+ import comtypes.client
13
+ import comtypes.gen
14
+
15
+
16
+ IMGBASE = os.path.splitext(os.path.basename(sys.executable))[0]
17
+
18
+
19
+ @contextlib.contextmanager
20
+ def patch_empty_module_to_comtypes_gen() -> Iterator[types.ModuleType]:
21
+ with mock.patch.dict(sys.modules):
22
+ del sys.modules["comtypes.gen"]
23
+ mod = sys.modules["comtypes.gen"] = types.ModuleType("comtypes.gen")
24
+ mod.__path__ = []
25
+ with mock.patch.object(comtypes, "gen", mod):
26
+ try:
27
+ yield mod
28
+ finally:
29
+ importlib.reload(comtypes.gen)
30
+
31
+
32
+ class Test(unittest.TestCase):
33
+ """Test the comtypes.client._find_gen_dir() function in several
34
+ simulated environments.
35
+ """
36
+
37
+ def test_script(self):
38
+ # %APPDATA%\Python\Python25\comtypes_cache
39
+ ma, mi = sys.version_info[:2]
40
+ cache = rf"$APPDATA\Python\Python{ma:d}{mi:d}\comtypes_cache"
41
+ path = os.path.expandvars(cache)
42
+ with patch_empty_module_to_comtypes_gen():
43
+ gen_dir = comtypes.client._find_gen_dir()
44
+ self.assertEqual(path, gen_dir)
45
+
46
+ # patch py2exe-attributes to `sys` modules
47
+ @mock.patch.object(sys, "frozen", "dll", create=True)
48
+ @mock.patch.object(sys, "frozendllhandle", sys.dllhandle, create=True)
49
+ def test_frozen_dll(self):
50
+ # %TEMP%\comtypes_cache\<imagebasename>25-25
51
+ # the image is python25.dll
52
+ ma, mi = sys.version_info[:2]
53
+ cache = rf"comtypes_cache\{IMGBASE}{ma:d}{mi:d}-{ma:d}{mi:d}"
54
+ path = os.path.join(tempfile.gettempdir(), cache)
55
+ with patch_empty_module_to_comtypes_gen():
56
+ gen_dir = comtypes.client._find_gen_dir()
57
+ self.assertEqual(path, gen_dir)
58
+
59
+ # patch py2exe-attributes to `sys` modules
60
+ @mock.patch.object(sys, "frozen", "console_exe", create=True)
61
+ def test_frozen_console_exe(self):
62
+ # %TEMP%\comtypes_cache\<imagebasename>-25
63
+ ma, mi = sys.version_info[:2]
64
+ cache = rf"comtypes_cache\{IMGBASE}-{ma:d}{mi:d}"
65
+ path = os.path.join(tempfile.gettempdir(), cache)
66
+ with patch_empty_module_to_comtypes_gen():
67
+ gen_dir = comtypes.client._find_gen_dir()
68
+ self.assertEqual(path, gen_dir)
69
+
70
+ # patch py2exe-attributes to `sys` modules
71
+ @mock.patch.object(sys, "frozen", "windows_exe", create=True)
72
+ def test_frozen_windows_exe(self):
73
+ # %TEMP%\comtypes_cache\<imagebasename>-25
74
+ ma, mi = sys.version_info[:2]
75
+ cache = rf"comtypes_cache\{IMGBASE}-{ma:d}{mi:d}"
76
+ path = os.path.join(tempfile.gettempdir(), cache)
77
+ with patch_empty_module_to_comtypes_gen():
78
+ gen_dir = comtypes.client._find_gen_dir()
79
+ self.assertEqual(path, gen_dir)
80
+
81
+
82
+ def main():
83
+ unittest.main()
84
+
85
+
86
+ if __name__ == "__main__":
87
+ main()
@@ -0,0 +1,5 @@
1
+ from comtypes.tools.codegenerator.modulenamer import ( # noqa
2
+ name_friendly_module,
3
+ name_wrapper_module,
4
+ )
5
+ from comtypes.tools.codegenerator.codegenerator import CodeGenerator, version # noqa