comtypes 1.4.2__zip → 1.4.4__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 (121) hide show
  1. {comtypes-1.4.2 → comtypes-1.4.4}/CHANGES.txt +22 -2
  2. {comtypes-1.4.2/comtypes.egg-info → comtypes-1.4.4}/PKG-INFO +30 -3
  3. {comtypes-1.4.2 → comtypes-1.4.4}/README.md +28 -1
  4. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/__init__.py +6 -8
  5. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/automation.py +26 -2
  6. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/hints.pyi +15 -0
  7. comtypes-1.4.4/comtypes/test/mylib.tlb +0 -0
  8. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_GUID.py +23 -2
  9. comtypes-1.4.4/comtypes/test/test_dispifc_records.py +90 -0
  10. comtypes-1.4.4/comtypes/test/test_findgendir.py +87 -0
  11. comtypes-1.4.4/comtypes/test/urlhist.tlb +0 -0
  12. comtypes-1.4.4/comtypes/tools/codegenerator/__init__.py +5 -0
  13. {comtypes-1.4.2/comtypes/tools → comtypes-1.4.4/comtypes/tools/codegenerator}/codegenerator.py +56 -721
  14. comtypes-1.4.4/comtypes/tools/codegenerator/helpers.py +357 -0
  15. comtypes-1.4.4/comtypes/tools/codegenerator/modulenamer.py +24 -0
  16. comtypes-1.4.4/comtypes/tools/codegenerator/namespaces.py +212 -0
  17. comtypes-1.4.4/comtypes/tools/codegenerator/packing.py +81 -0
  18. {comtypes-1.4.2/comtypes/tools → comtypes-1.4.4/comtypes/tools/codegenerator}/typeannotator.py +18 -3
  19. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/tools/tlbparser.py +19 -49
  20. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/tools/typedesc.py +57 -9
  21. {comtypes-1.4.2 → comtypes-1.4.4/comtypes.egg-info}/PKG-INFO +30 -3
  22. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes.egg-info/SOURCES.txt +13 -3
  23. comtypes-1.4.4/pyproject.toml +3 -0
  24. comtypes-1.4.4/setup.cfg +51 -0
  25. comtypes-1.4.4/setup.py +117 -0
  26. comtypes-1.4.2/comtypes/test/test_findgendir.py +0 -94
  27. comtypes-1.4.2/setup.cfg +0 -4
  28. comtypes-1.4.2/setup.py +0 -172
  29. {comtypes-1.4.2 → comtypes-1.4.4}/LICENSE.txt +0 -0
  30. {comtypes-1.4.2 → comtypes-1.4.4}/MANIFEST.in +0 -0
  31. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/GUID.py +0 -0
  32. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/_comobject.py +0 -0
  33. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/_memberspec.py +0 -0
  34. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/_meta.py +0 -0
  35. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/_npsupport.py +0 -0
  36. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/_safearray.py +0 -0
  37. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/clear_cache.py +0 -0
  38. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/client/__init__.py +0 -0
  39. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/client/_code_cache.py +0 -0
  40. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/client/_constants.py +0 -0
  41. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/client/_events.py +0 -0
  42. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/client/_generate.py +0 -0
  43. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/client/dynamic.py +0 -0
  44. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/client/lazybind.py +0 -0
  45. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/connectionpoints.py +0 -0
  46. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/errorinfo.py +0 -0
  47. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/git.py +0 -0
  48. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/hresult.py +0 -0
  49. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/logutil.py +0 -0
  50. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/messageloop.py +0 -0
  51. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/patcher.py +0 -0
  52. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/persist.py +0 -0
  53. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/safearray.py +0 -0
  54. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/server/__init__.py +0 -0
  55. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/server/automation.py +0 -0
  56. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/server/connectionpoints.py +0 -0
  57. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/server/inprocserver.py +0 -0
  58. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/server/localserver.py +0 -0
  59. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/server/register.py +0 -0
  60. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/server/w_getopt.py +0 -0
  61. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/shelllink.py +0 -0
  62. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/TestComServer.idl +0 -0
  63. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/TestComServer.py +0 -0
  64. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/TestComServer.tlb +0 -0
  65. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/TestDispServer.idl +0 -0
  66. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/TestDispServer.py +0 -0
  67. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/TestDispServer.tlb +0 -0
  68. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/__init__.py +0 -0
  69. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/find_memleak.py +0 -0
  70. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/mylib.idl +0 -0
  71. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/mytypelib.idl +0 -0
  72. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/runtests.py +0 -0
  73. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/setup.py +0 -0
  74. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_BSTR.py +0 -0
  75. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_DISPPARAMS.py +0 -0
  76. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_QueryService.py +0 -0
  77. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_agilent.py +0 -0
  78. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_avmc.py +0 -0
  79. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_basic.py +0 -0
  80. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_casesensitivity.py +0 -0
  81. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_clear_cache.py +0 -0
  82. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_client.py +0 -0
  83. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_client_dynamic.py +0 -0
  84. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_client_regenerate_modules.py +0 -0
  85. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_collections.py +0 -0
  86. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_comserver.py +0 -0
  87. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_createwrappers.py +0 -0
  88. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_dict.py +0 -0
  89. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_dispinterface.py +0 -0
  90. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_dyndispatch.py +0 -0
  91. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_excel.py +0 -0
  92. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_getactiveobj.py +0 -0
  93. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_ie.py +0 -0
  94. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_ienum.py +0 -0
  95. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_imfattributes.py +0 -0
  96. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_inout_args.py +0 -0
  97. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_jscript.js +0 -0
  98. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_msscript.py +0 -0
  99. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_npsupport.py +0 -0
  100. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_outparam.py +0 -0
  101. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_propputref.py +0 -0
  102. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_pump_events.py +0 -0
  103. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_safearray.py +0 -0
  104. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_sapi.py +0 -0
  105. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_server.py +0 -0
  106. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_showevents.py +0 -0
  107. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_subinterface.py +0 -0
  108. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_typeinfo.py +0 -0
  109. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_urlhistory.py +0 -0
  110. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_variant.py +0 -0
  111. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_win32com_interop.py +0 -0
  112. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_wmi.py +0 -0
  113. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_word.py +0 -0
  114. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/tools/__init__.py +0 -0
  115. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/tools/typedesc_base.py +0 -0
  116. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/typeinfo.py +0 -0
  117. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/util.py +0 -0
  118. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/viewobject.py +0 -0
  119. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes.egg-info/dependency_links.txt +0 -0
  120. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes.egg-info/entry_points.txt +0 -0
  121. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes.egg-info/top_level.txt +0 -0
@@ -1,9 +1,29 @@
1
1
  Comtypes CHANGELOG
2
2
  ==================
3
3
 
4
- Release 1.4.2
4
+ Release 1.4.4
5
+ --------------
6
+ * Stop mentioning the last version supporting Windows CE in ``README.md``. By @forderud.
7
+ * Declare the minimum Python version as 3.7. By @jaraco.
8
+ * Move package configuration to declarative config. By @jaraco.
9
+
10
+ Release 1.4.3
5
11
  --------------
12
+ * Refactor ``test_findgendir``. By @junkmd.
13
+ * Update ``test_GUID``. By @junkmd.
14
+ * Add a feature to ``typeannotator`` that interprets the return value. By @junkmd.
15
+ * Update type annotations for ``_IUnknown_Base`` and ``IUnknown``. By @junkmd.
16
+ * Add ``groupby_impltypeflags``. By @junkmd.
17
+ * Add static typing for when a ``CoClass`` is assigned as the return value type. By @junkmd.
18
+ * Improve ``EnumerationNamespaces`` and ``CodeGenerator.enum_aliases``. By @junkmd.
19
+ * Modernize constructor arguments and attributes of each stuff in ``typedesc``. By @junkmd.
20
+ * Split ``codegenerator`` into some modules in the sub-package directory. By @junkmd.
21
+ * Implement record pointers as method parameters of a Dispatch Interface. By @geppi.
22
+ * Add ``npsupport`` to CI pipeline matrix. By @junkmd.
23
+ * Add "Frequently Asked Questions" to ``README.md``. By @junkmd.
6
24
 
25
+ Release 1.4.2
26
+ --------------
7
27
  * Improve the stability of module generation by ``GetModule``. By @junkmd.
8
28
  * Define ``c_int`` aliases earlier than others in wrapper modules. By @junkmd.
9
29
  * Remove trailing newlines generated by ``codegenerator`` and ``typeannotator``. By @junkmd.
@@ -12,7 +32,7 @@ Release 1.4.2
12
32
 
13
33
  Release 1.4.1
14
34
  --------------
15
- * Fix `TypeError` when defining enumeration types
35
+ * Fix ``TypeError`` when defining enumeration types. By @junkmd.
16
36
 
17
37
  Release 1.4.0
18
38
  --------------
@@ -1,12 +1,11 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: comtypes
3
- Version: 1.4.2
3
+ Version: 1.4.4
4
4
  Summary: Pure Python COM package
5
5
  Home-page: https://github.com/enthought/comtypes
6
6
  Download-URL: https://github.com/enthought/comtypes/releases
7
7
  Author: Thomas Heller
8
8
  Author-email: theller@python.net
9
- License: MIT License
10
9
  Classifier: Development Status :: 5 - Production/Stable
11
10
  Classifier: Intended Audience :: Developers
12
11
  Classifier: License :: OSI Approved :: MIT License
@@ -14,6 +13,7 @@ Classifier: Operating System :: Microsoft :: Windows
14
13
  Classifier: Programming Language :: Python
15
14
  Classifier: Programming Language :: Python :: 3
16
15
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
16
+ Requires-Python: >=3.7
17
17
  Description-Content-Type: text/markdown
18
18
  License-File: LICENSE.txt
19
19
 
@@ -31,7 +31,6 @@ License-File: LICENSE.txt
31
31
  `comtypes` allows to define, call, and implement custom and dispatch-based COM interfaces in pure `Python`.
32
32
 
33
33
  This package works on Windows only.
34
- - [`comtypes==1.1.7`](https://pypi.org/project/comtypes/1.1.7/) is the last version supporting Windows CE.
35
34
 
36
35
  Available on `Python` 3.7-3.12.
37
36
  - [`comtypes==1.2.1`](https://pypi.org/project/comtypes/1.2.1/) is the last version supporting `Python` 2.7 and 3.3-3.6.
@@ -75,6 +74,34 @@ This project and the maintainers of thousands of other packages are working with
75
74
 
76
75
  [Learn more](https://tidelift.com/subscription/pkg/pypi-comtypes?utm_source=pypi-comtypes&utm_medium=referral&utm_campaign=github).
77
76
 
77
+ ## Frequently Asked Questions
78
+
79
+ ### Q: Why does this package not support platforms other than Windows?
80
+ **A:** [The Microsoft Component Object Model (COM)](https://learn.microsoft.com/en-us/windows/win32/com/com-technical-overview) is a technology that is unique to Windows and is not supported on other platforms.
81
+
82
+ [The phrase _"COM is a platform-independent"_ in the MS documentation](https://learn.microsoft.com/en-us/windows/win32/com/component-object-model--com--portal) means that COM maintains compatibility across different versions of Windows, and does NOT imply that it is supported on Linux or Mac.
83
+
84
+ As long as COM is not supported outside of Windows, this project does not plan to port to other platforms.
85
+
86
+ ### Q: Why does `cannot import name 'COMError' from '_ctypes'` error occur when using this package on platforms other than Windows?
87
+ **A:** The [`_ctypes`](https://github.com/python/cpython/blob/main/Modules/_ctypes/_ctypes.c) is part of the internal implementation of the [`ctypes`](https://github.com/python/cpython/blob/main/Lib/ctypes/) standard library that exists for Python on all platforms.
88
+ However, `COMError` and COM-related features are implemented only in Python for Windows.
89
+
90
+ In cross-platform software development, care must be taken to ensure that codebase dependent on `comtypes` does not execute in environments other than Windows.
91
+
92
+ ### Q: Despite a script that depends on `comtypes` having run successfully before, a error (`ImportError`, `NameError`, or `SyntaxError`) is raised now, and the same error occurs again and again.
93
+
94
+ **A:** Executing `py -m comtypes.clear_cache` and then running the script again might resolve the problem.
95
+
96
+ When `comtypes.client.GetModule` is called (either directly or indirectly), `comtypes` generates Python module files.
97
+ If Python is forced to terminate or crashes in the middle of file generation, the codebase written to the file becomes partial.
98
+ When Python tries to import this unexecutable partial codebase module, an error occurs.
99
+
100
+ Executing `py -m comtypes.clear_cache` identifies the directories where the "cache module files" are stored and deletes them.
101
+ After deleting these partial modules and running the script again, `comtypes.client.GetModule` is called and executable modules are generated anew.
102
+
103
+ However, if the script implementation does not use `comtypes.client.GetModule` or processes generated files, it may not be a solution.
104
+
78
105
  ## Documentation:
79
106
 
80
107
  The documentation is currently hosted on pythonhosted at:
@@ -12,7 +12,6 @@
12
12
  `comtypes` allows to define, call, and implement custom and dispatch-based COM interfaces in pure `Python`.
13
13
 
14
14
  This package works on Windows only.
15
- - [`comtypes==1.1.7`](https://pypi.org/project/comtypes/1.1.7/) is the last version supporting Windows CE.
16
15
 
17
16
  Available on `Python` 3.7-3.12.
18
17
  - [`comtypes==1.2.1`](https://pypi.org/project/comtypes/1.2.1/) is the last version supporting `Python` 2.7 and 3.3-3.6.
@@ -56,6 +55,34 @@ This project and the maintainers of thousands of other packages are working with
56
55
 
57
56
  [Learn more](https://tidelift.com/subscription/pkg/pypi-comtypes?utm_source=pypi-comtypes&utm_medium=referral&utm_campaign=github).
58
57
 
58
+ ## Frequently Asked Questions
59
+
60
+ ### Q: Why does this package not support platforms other than Windows?
61
+ **A:** [The Microsoft Component Object Model (COM)](https://learn.microsoft.com/en-us/windows/win32/com/com-technical-overview) is a technology that is unique to Windows and is not supported on other platforms.
62
+
63
+ [The phrase _"COM is a platform-independent"_ in the MS documentation](https://learn.microsoft.com/en-us/windows/win32/com/component-object-model--com--portal) means that COM maintains compatibility across different versions of Windows, and does NOT imply that it is supported on Linux or Mac.
64
+
65
+ As long as COM is not supported outside of Windows, this project does not plan to port to other platforms.
66
+
67
+ ### Q: Why does `cannot import name 'COMError' from '_ctypes'` error occur when using this package on platforms other than Windows?
68
+ **A:** The [`_ctypes`](https://github.com/python/cpython/blob/main/Modules/_ctypes/_ctypes.c) is part of the internal implementation of the [`ctypes`](https://github.com/python/cpython/blob/main/Lib/ctypes/) standard library that exists for Python on all platforms.
69
+ However, `COMError` and COM-related features are implemented only in Python for Windows.
70
+
71
+ In cross-platform software development, care must be taken to ensure that codebase dependent on `comtypes` does not execute in environments other than Windows.
72
+
73
+ ### Q: Despite a script that depends on `comtypes` having run successfully before, a error (`ImportError`, `NameError`, or `SyntaxError`) is raised now, and the same error occurs again and again.
74
+
75
+ **A:** Executing `py -m comtypes.clear_cache` and then running the script again might resolve the problem.
76
+
77
+ When `comtypes.client.GetModule` is called (either directly or indirectly), `comtypes` generates Python module files.
78
+ If Python is forced to terminate or crashes in the middle of file generation, the codebase written to the file becomes partial.
79
+ When Python tries to import this unexecutable partial codebase module, an error occurs.
80
+
81
+ Executing `py -m comtypes.clear_cache` identifies the directories where the "cache module files" are stored and deletes them.
82
+ After deleting these partial modules and running the script again, `comtypes.client.GetModule` is called and executable modules are generated anew.
83
+
84
+ However, if the script implementation does not use `comtypes.client.GetModule` or processes generated files, it may not be a solution.
85
+
59
86
  ## Documentation:
60
87
 
61
88
  The documentation is currently hosted on pythonhosted at:
@@ -1,5 +1,5 @@
1
1
  # comtypes version numbers follow semver (http://semver.org/) and PEP 440
2
- __version__ = "1.4.2"
2
+ __version__ = "1.4.4"
3
3
 
4
4
  import atexit
5
5
  from ctypes import *
@@ -774,7 +774,7 @@ _T_IUnknown = TypeVar("_T_IUnknown", bound="IUnknown")
774
774
 
775
775
  if TYPE_CHECKING:
776
776
 
777
- class _IUnknown_Base(c_void_p, metaclass=_cominterface_meta):
777
+ class _IUnknown_Base(c_void_p, metaclass=_cominterface_meta): # type: ignore
778
778
  """This is workaround to avoid false-positive of static type checking.
779
779
 
780
780
  `IUnknown` behaves as a ctypes type, and `POINTER` can take it.
@@ -784,9 +784,7 @@ if TYPE_CHECKING:
784
784
  `builtins.object`.
785
785
  """
786
786
 
787
- __com_QueryInterface: Callable[[Any, Any], int]
788
- __com_AddRef: Callable[[], int]
789
- __com_Release: Callable[[], int]
787
+ ...
790
788
 
791
789
  else:
792
790
  _IUnknown_Base = object
@@ -825,7 +823,7 @@ class IUnknown(_IUnknown_Base, metaclass=_cominterface_meta):
825
823
  p = POINTER(interface)()
826
824
  if iid is None:
827
825
  iid = interface._iid_
828
- self.__com_QueryInterface(byref(iid), byref(p))
826
+ self.__com_QueryInterface(byref(iid), byref(p)) # type: ignore
829
827
  clsid = self.__dict__.get("__clsid")
830
828
  if clsid is not None:
831
829
  p.__dict__["__clsid"] = clsid
@@ -835,11 +833,11 @@ class IUnknown(_IUnknown_Base, metaclass=_cominterface_meta):
835
833
  # XXX There should be other ways to install a docstring.
836
834
  def AddRef(self) -> int:
837
835
  """Increase the internal refcount by one and return it."""
838
- return self.__com_AddRef()
836
+ return self.__com_AddRef() # type: ignore
839
837
 
840
838
  def Release(self) -> int:
841
839
  """Decrease the internal refcount by one and return it."""
842
- return self.__com_Release()
840
+ return self.__com_Release() # type: ignore
843
841
 
844
842
 
845
843
  ################################################################
@@ -393,12 +393,36 @@ class tagVARIANT(Structure):
393
393
  ref = value._obj
394
394
  self._.c_void_p = addressof(ref)
395
395
  self.__keepref = value
396
- self.vt = _ctype_to_vartype[type(ref)] | VT_BYREF
396
+ if isinstance(ref, Structure) and hasattr(ref, "_recordinfo_"):
397
+ guids = ref._recordinfo_
398
+ from comtypes.typeinfo import GetRecordInfoFromGuids
399
+
400
+ ri = GetRecordInfoFromGuids(*guids)
401
+ self.vt = VT_RECORD | VT_BYREF
402
+ # Assigning a COM pointer to a structure field does NOT
403
+ # call AddRef(), have to call it manually:
404
+ ri.AddRef()
405
+ self._.pRecInfo = ri
406
+ self._.pvRecord = cast(value, c_void_p)
407
+ else:
408
+ self.vt = _ctype_to_vartype[type(ref)] | VT_BYREF
397
409
  elif isinstance(value, _Pointer):
398
410
  ref = value.contents
399
411
  self._.c_void_p = addressof(ref)
400
412
  self.__keepref = value
401
- self.vt = _ctype_to_vartype[type(ref)] | VT_BYREF
413
+ if isinstance(ref, Structure) and hasattr(ref, "_recordinfo_"):
414
+ guids = ref._recordinfo_
415
+ from comtypes.typeinfo import GetRecordInfoFromGuids
416
+
417
+ ri = GetRecordInfoFromGuids(*guids)
418
+ self.vt = VT_RECORD | VT_BYREF
419
+ # Assigning a COM pointer to a structure field does NOT
420
+ # call AddRef(), have to call it manually:
421
+ ri.AddRef()
422
+ self._.pRecInfo = ri
423
+ self._.pvRecord = cast(value, c_void_p)
424
+ else:
425
+ self.vt = _ctype_to_vartype[type(ref)] | VT_BYREF
402
426
  else:
403
427
  raise TypeError("Cannot put %r in VARIANT" % value)
404
428
  # buffer -> SAFEARRAY of VT_UI1 ?
@@ -21,6 +21,10 @@ if sys.version_info >= (3, 8):
21
21
  from typing import Protocol
22
22
  else:
23
23
  from typing_extensions import Protocol
24
+ if sys.version_info >= (3, 9):
25
+ from typing import Annotated as Annotated
26
+ else:
27
+ from typing_extensions import Annotated as Annotated
24
28
  if sys.version_info >= (3, 10):
25
29
  from typing import Concatenate, ParamSpec, TypeAlias
26
30
  from typing import TypeGuard as TypeGuard
@@ -32,6 +36,7 @@ if sys.version_info >= (3, 11):
32
36
  else:
33
37
  from typing_extensions import Self
34
38
 
39
+ import comtypes
35
40
  from comtypes.automation import IDispatch as IDispatch, VARIANT as VARIANT
36
41
  from comtypes.server import IClassFactory as IClassFactory
37
42
  from comtypes.typeinfo import ITypeInfo as ITypeInfo
@@ -46,6 +51,16 @@ Hresult: TypeAlias = int
46
51
  arguments and with `HRESULT` as its return type in its COM method definition.
47
52
  """
48
53
 
54
+ _T_coclass = TypeVar("_T_coclass", bound=comtypes.CoClass)
55
+
56
+ class FirstComItfOf(Generic[_T_coclass]):
57
+ """When the type assigned to the parameter marked as `'out'` is `CoClass`,
58
+ the return type of that method at runtime becomes `_com_interface_[0]`
59
+ due to the metaclass.
60
+ This is used as `Annotated` metadata for such parameters, taking `CoClass`
61
+ as an argument.
62
+ """
63
+
49
64
  class _MethodTypeDesc(Protocol):
50
65
  arguments: List[Tuple[Any, str, List[str], Optional[Any]]]
51
66
  idlflags: List[str]
Binary file
@@ -1,34 +1,55 @@
1
- import os
2
1
  import unittest
3
2
  from comtypes import GUID
4
3
 
5
4
 
6
5
  class Test(unittest.TestCase):
7
- def test(self):
6
+ def test_GUID_null(self):
8
7
  self.assertEqual(GUID(), GUID())
8
+ self.assertEqual(
9
+ str(GUID()),
10
+ "{00000000-0000-0000-0000-000000000000}",
11
+ )
12
+
13
+ def test_dunder_eq(self):
9
14
  self.assertEqual(
10
15
  GUID("{00000000-0000-0000-C000-000000000046}"),
11
16
  GUID("{00000000-0000-0000-C000-000000000046}"),
12
17
  )
13
18
 
19
+ def test_duner_str(self):
14
20
  self.assertEqual(
15
21
  str(GUID("{0002DF01-0000-0000-C000-000000000046}")),
16
22
  "{0002DF01-0000-0000-C000-000000000046}",
17
23
  )
24
+
25
+ def test_dunder_repr(self):
18
26
  self.assertEqual(
19
27
  repr(GUID("{0002DF01-0000-0000-C000-000000000046}")),
20
28
  'GUID("{0002DF01-0000-0000-C000-000000000046}")',
21
29
  )
22
30
 
31
+ def test_invalid_constructor_arg(self):
23
32
  self.assertRaises(WindowsError, GUID, "abc")
33
+
34
+ def test_from_progid(self):
35
+ self.assertEqual(
36
+ GUID.from_progid("Scripting.FileSystemObject"),
37
+ GUID("{0D43FE01-F093-11CF-8940-00A0C9054228}"),
38
+ )
24
39
  self.assertRaises(WindowsError, GUID.from_progid, "abc")
25
40
 
41
+ def test_as_progid(self):
42
+ self.assertEqual(
43
+ GUID("{0D43FE01-F093-11CF-8940-00A0C9054228}").as_progid(),
44
+ "Scripting.FileSystemObject",
45
+ )
26
46
  self.assertRaises(
27
47
  WindowsError,
28
48
  lambda guid: guid.as_progid(),
29
49
  GUID("{00000000-0000-0000-C000-000000000046}"),
30
50
  )
31
51
 
52
+ def test_create_new(self):
32
53
  self.assertNotEqual(GUID.create_new(), GUID.create_new())
33
54
 
34
55
 
@@ -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()
Binary file
@@ -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