From 5b4502560ba83274badac46ad7f263402f7ad269 Mon Sep 17 00:00:00 2001 From: Jun Komoda <45822440+junkmd@users.noreply.github.com> Date: Wed, 20 Nov 2024 21:53:43 +0900 Subject: [PATCH] gh-126615: `ctypes`: Make `COMError` public (GH-126686) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> --- Doc/library/ctypes.rst | 47 ++++++++++++++++--- Doc/whatsnew/3.14.rst | 3 ++ Lib/ctypes/__init__.py | 2 +- Lib/test/test_ctypes/test_win32.py | 7 +-- ...-11-19-14-34-05.gh-issue-126615.LOskwi.rst | 2 + 5 files changed, 51 insertions(+), 10 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2024-11-19-14-34-05.gh-issue-126615.LOskwi.rst diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst index 99909de20ef..8ed75d9b756 100644 --- a/Doc/library/ctypes.rst +++ b/Doc/library/ctypes.rst @@ -1707,12 +1707,6 @@ in :mod:`!ctypes`) which inherits from the private :class:`_CFuncPtr` class: and raise an exception if the foreign function call failed. -.. exception:: ArgumentError - - This exception is raised when a foreign function call cannot convert one of the - passed arguments. - - .. audit-event:: ctypes.set_exception code foreign-functions On Windows, when a foreign function call raises a system exception (for @@ -1799,10 +1793,15 @@ different ways, depending on the type and number of the parameters in the call: integer. *name* is name of the COM method. *iid* is an optional pointer to the interface identifier which is used in extended error reporting. + If *iid* is not specified, an :exc:`OSError` is raised if the COM method + call fails. If *iid* is specified, a :exc:`~ctypes.COMError` is raised + instead. + COM methods use a special calling convention: They require a pointer to the COM interface as first argument, in addition to those parameters that are specified in the :attr:`!argtypes` tuple. + The optional *paramflags* parameter creates foreign function wrappers with much more functionality than the features described above. @@ -2741,3 +2740,39 @@ Arrays and pointers Returns the object to which to pointer points. Assigning to this attribute changes the pointer to point to the assigned object. + + +.. _ctypes-exceptions: + +Exceptions +^^^^^^^^^^ + +.. exception:: ArgumentError + + This exception is raised when a foreign function call cannot convert one of the + passed arguments. + + +.. exception:: COMError(hresult, text, details) + + Windows only: This exception is raised when a COM method call failed. + + .. attribute:: hresult + + The integer value representing the error code. + + .. attribute:: text + + The error message. + + .. attribute:: details + + The 5-tuple ``(descr, source, helpfile, helpcontext, progid)``. + + *descr* is the textual description. *source* is the language-dependent + ``ProgID`` for the class or application that raised the error. *helpfile* + is the path of the help file. *helpcontext* is the help context + identifier. *progid* is the ``ProgID`` of the interface that defined the + error. + + .. versionadded:: next diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index cddcaafc461..1f0b2454c0e 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -273,6 +273,9 @@ ctypes to help match a non-default ABI. (Contributed by Petr Viktorin in :gh:`97702`.) +* The :exc:`~ctypes.COMError` exception is now public. + (Contributed by Jun Komoda in :gh:`126686`.) + datetime -------- diff --git a/Lib/ctypes/__init__.py b/Lib/ctypes/__init__.py index 4a368f02d85..ac649389206 100644 --- a/Lib/ctypes/__init__.py +++ b/Lib/ctypes/__init__.py @@ -19,7 +19,7 @@ if __version__ != _ctypes_version: raise Exception("Version number mismatch", __version__, _ctypes_version) if _os.name == "nt": - from _ctypes import FormatError + from _ctypes import COMError, FormatError DEFAULT_MODE = RTLD_LOCAL if _os.name == "posix" and _sys.platform == "darwin": diff --git a/Lib/test/test_ctypes/test_win32.py b/Lib/test/test_ctypes/test_win32.py index 31919118670..54b47dc28fb 100644 --- a/Lib/test/test_ctypes/test_win32.py +++ b/Lib/test/test_ctypes/test_win32.py @@ -65,15 +65,16 @@ class TestWintypes(unittest.TestCase): sizeof(c_void_p)) def test_COMError(self): - from _ctypes import COMError + from ctypes import COMError if support.HAVE_DOCSTRINGS: self.assertEqual(COMError.__doc__, "Raised when a COM method call failed.") - ex = COMError(-1, "text", ("details",)) + ex = COMError(-1, "text", ("descr", "source", "helpfile", 0, "progid")) self.assertEqual(ex.hresult, -1) self.assertEqual(ex.text, "text") - self.assertEqual(ex.details, ("details",)) + self.assertEqual(ex.details, + ("descr", "source", "helpfile", 0, "progid")) self.assertEqual(COMError.mro(), [COMError, Exception, BaseException, object]) diff --git a/Misc/NEWS.d/next/Library/2024-11-19-14-34-05.gh-issue-126615.LOskwi.rst b/Misc/NEWS.d/next/Library/2024-11-19-14-34-05.gh-issue-126615.LOskwi.rst new file mode 100644 index 00000000000..8c7a2ade03c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-11-19-14-34-05.gh-issue-126615.LOskwi.rst @@ -0,0 +1,2 @@ +The :exc:`~ctypes.COMError` exception is now public. +Previously, this was private and only available in ``_ctypes``.