René's URL Explorer Experiment


Title: Add tests to verify the behavior of basic COM methods. · Issue #126384 · python/cpython · GitHub

Open Graph Title: Add tests to verify the behavior of basic COM methods. · Issue #126384 · python/cpython

X Title: Add tests to verify the behavior of basic COM methods. · Issue #126384 · python/cpython

Description: Feature or enhancement Proposal: I am one of the maintainers of comtypes. comtypes is based on ctypes to implement IUnknown and other COM stuffs. In the past, I reported in gh-124520 that projects dependent on ctypes was broken due to ch...

Open Graph Description: Feature or enhancement Proposal: I am one of the maintainers of comtypes. comtypes is based on ctypes to implement IUnknown and other COM stuffs. In the past, I reported in gh-124520 that projects ...

X Description: Feature or enhancement Proposal: I am one of the maintainers of comtypes. comtypes is based on ctypes to implement IUnknown and other COM stuffs. In the past, I reported in gh-124520 that projects ...

Opengraph URL: https://github.com/python/cpython/issues/126384

X: @github

direct link

Domain: github.com


Hey, it has json ld scripts:
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"Add tests to verify the behavior of basic COM methods.","articleBody":"# Feature or enhancement\r\n\r\n### Proposal:\r\n\r\nI am one of the maintainers of [`comtypes`](https://github.com/enthought/comtypes/). `comtypes` is based on `ctypes` to implement [`IUnknown`](https://learn.microsoft.com/en-us/windows/win32/api/unknwn/nn-unknwn-iunknown) and other COM stuffs.\r\n\r\nIn the past, I reported in [gh-124520](https://github.com/python/cpython/issues/124520) that projects dependent on `ctypes` was broken due to changes in Python 3.13.\r\n\r\nI am currently researching whether there are any effective ways to proactively prevent such regressions beyond what I attempted in [gh-125783](https://github.com/python/cpython/issues/125783).\r\n\r\nI noticed that the `cpython` repository might not contain tests for basic COM methods, such as [`QueryInterface`](https://learn.microsoft.com/en-us/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(refiid_void)), [`AddRef`](https://learn.microsoft.com/en-us/windows/win32/api/unknwn/nf-unknwn-iunknown-addref), and [`Release`](https://learn.microsoft.com/en-us/windows/win32/api/unknwn/nf-unknwn-iunknown-release).\r\nThere are many projects besides `comtypes` that define COM interfaces and call COM methods, so I think it’s important to test them.\r\n\r\nI think that simple tests like the one below, which implements a very basic COM interface and calls its methods, might help prevent regressions.\r\n(I removed the complex parts in `comtypes`, such as defining methods, registering pointer types, and using `__del__` to call `Release` through metaclasse magic.)\r\n(I have confirmed that this test passes in a virtual environment with Python 3.11.2, which I could quickly set up.)\r\n\r\n```py\r\nimport sys\r\nimport unittest\r\n\r\n\r\ndef setUpModule():\r\n    if sys.platform != \"win32\":\r\n        raise unittest.SkipTest(\"Win32 only\")\r\n\r\n\r\nimport ctypes\r\nimport gc\r\nfrom ctypes import HRESULT, POINTER, byref\r\nfrom ctypes.wintypes import BYTE, DWORD, HGLOBAL, WORD\r\n\r\nole32 = ctypes.oledll.ole32\r\noleaut32 = ctypes.oledll.oleaut32\r\n\r\n\r\ndef CLSIDFromString(name):\r\n    guid = GUID()\r\n    ole32.CLSIDFromString(name, byref(guid))\r\n    return guid\r\n\r\n\r\nclass GUID(ctypes.Structure):\r\n    _fields_ = [\r\n        (\"Data1\", DWORD),\r\n        (\"Data2\", WORD),\r\n        (\"Data3\", WORD),\r\n        (\"Data4\", BYTE * 8),\r\n    ]\r\n\r\n\r\nPyInstanceMethod_New = ctypes.pythonapi.PyInstanceMethod_New\r\nPyInstanceMethod_New.argtypes = [ctypes.py_object]\r\nPyInstanceMethod_New.restype = ctypes.py_object\r\nPyInstanceMethod_Type = type(PyInstanceMethod_New(id))\r\n\r\n\r\nclass COM_METHOD:\r\n    def __init__(self, index, restype, *argtypes):\r\n        self.index = index\r\n        self.proto = ctypes.WINFUNCTYPE(restype, *argtypes)\r\n\r\n    def __set_name__(self, owner, name):\r\n        self.mth = PyInstanceMethod_Type(self.proto(self.index, name))\r\n\r\n    def __call__(self, *args, **kwargs):\r\n        return self.mth(*args, **kwargs)\r\n\r\n    def __get__(self, instance, owner):\r\n        if instance is None:\r\n            return self\r\n        return self.mth.__get__(instance)\r\n\r\n\r\nclass IUnknown(ctypes.c_void_p):\r\n    IID = CLSIDFromString(\"{00000000-0000-0000-C000-000000000046}\")\r\n    QueryInterface = COM_METHOD(0, HRESULT, POINTER(GUID), POINTER(ctypes.c_void_p))\r\n    AddRef = COM_METHOD(1, ctypes.c_long)\r\n    Release = COM_METHOD(2, ctypes.c_long)\r\n\r\n\r\nclass ICreateTypeLib(IUnknown):\r\n    IID = CLSIDFromString(\"{00020406-0000-0000-C000-000000000046}\")\r\n    # `CreateTypeInfo` and more methods should be implemented\r\n\r\n\r\nclass ICreateTypeLib2(ICreateTypeLib):\r\n    IID = CLSIDFromString(\"{0002040F-0000-0000-C000-000000000046}\")\r\n    # `DeleteTypeInfo` and more methods should be implemented\r\n\r\n\r\nclass ISequentialStream(IUnknown):\r\n    IID = CLSIDFromString(\"{0C733A30-2A1C-11CE-ADE5-00AA0044773D}\")\r\n    # `Read` and `Write` methods should be implemented\r\n\r\n\r\nclass IStream(ISequentialStream):\r\n    IID = CLSIDFromString(\"{0000000C-0000-0000-C000-000000000046}\")\r\n    # `Seek` and more methods should be implemented\r\n\r\n\r\nCreateTypeLib2 = oleaut32.CreateTypeLib2\r\nCreateTypeLib2.argtypes = (ctypes.c_int, ctypes.c_wchar_p, POINTER(ICreateTypeLib2))\r\n\r\nCreateStreamOnHGlobal = ole32.CreateStreamOnHGlobal\r\nCreateStreamOnHGlobal.argtypes = (HGLOBAL, ctypes.c_bool, POINTER(IStream))\r\n\r\n\r\nCOINIT_APARTMENTTHREADED = 0x2\r\nS_OK = 0\r\nE_NOINTERFACE = -2147467262\r\n\r\n\r\nclass Test(unittest.TestCase):\r\n    def setUp(self):\r\n        ole32.CoInitializeEx(None, COINIT_APARTMENTTHREADED)\r\n\r\n    def tearDown(self):\r\n        ole32.CoUninitialize()\r\n        gc.collect()\r\n\r\n    def test_create_typelib_2(self):\r\n        pctlib = ICreateTypeLib2()\r\n        hr = CreateTypeLib2(0, \"sample.tlb\", pctlib)\r\n        self.assertEqual(S_OK, hr)\r\n\r\n        self.assertEqual(2, pctlib.AddRef())\r\n        self.assertEqual(3, pctlib.AddRef())\r\n\r\n        self.assertEqual(2, pctlib.Release())\r\n        self.assertEqual(1, pctlib.Release())\r\n        self.assertEqual(0, pctlib.Release())\r\n\r\n    def test_stream(self):\r\n        pstm = IStream()\r\n        hr = CreateStreamOnHGlobal(None, True, pstm)\r\n        self.assertEqual(S_OK, hr)\r\n\r\n        self.assertEqual(2, pstm.AddRef())\r\n        self.assertEqual(3, pstm.AddRef())\r\n\r\n        self.assertEqual(2, pstm.Release())\r\n        self.assertEqual(1, pstm.Release())\r\n        self.assertEqual(0, pstm.Release())\r\n\r\n    def test_query_interface(self):\r\n        pctlib2 = ICreateTypeLib2()\r\n        CreateTypeLib2(0, \"sample.tlb\", pctlib2)\r\n\r\n        pctlib = ICreateTypeLib()\r\n        hr1 = pctlib2.QueryInterface(byref(ICreateTypeLib.IID), byref(pctlib))\r\n        self.assertEqual(S_OK, hr1)\r\n        self.assertEqual(1, pctlib.Release())\r\n\r\n        punk = IUnknown()\r\n        hr2 = pctlib.QueryInterface(byref(IUnknown.IID), byref(punk))\r\n        self.assertEqual(S_OK, hr2)\r\n        self.assertEqual(1, punk.Release())\r\n\r\n        pstm = IStream()\r\n        with self.assertRaises(WindowsError) as e:  # Why not `COMError`?\r\n            punk.QueryInterface(byref(IStream.IID), byref(pstm))\r\n        self.assertEqual(E_NOINTERFACE, e.exception.winerror)\r\n\r\n        self.assertEqual(0, punk.Release())\r\n```\r\n\r\n- I am not sure why a `WindowsError` is raised instead of a `COMError` when `QueryInterface` fails.\r\n- Perhaps an interface with even fewer methods should be used in the test.\r\n- At this stage, I think creating custom COM type libraries and interfaces might be excessive.\r\n\r\nI welcome any feedback.\r\n\r\n\r\n\r\n### Has this already been discussed elsewhere?\r\n\r\nNo response given\r\n\r\n### Links to previous discussion of this feature:\r\n\r\n_No response_\n\n\u003c!-- gh-linked-prs --\u003e\n### Linked PRs\n* gh-126610\n* gh-127159\n* gh-127160\n\u003c!-- /gh-linked-prs --\u003e\n","author":{"url":"https://github.com/junkmd","@type":"Person","name":"junkmd"},"datePublished":"2024-11-04T08:13:18.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":2},"url":"https://github.com/126384/cpython/issues/126384"}

route-pattern/_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format)
route-controllervoltron_issues_fragments
route-actionissue_layout
fetch-noncev2:c6cd6ada-1542-888f-0e7d-258a44c15180
current-catalog-service-hash81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114
request-id9F38:16685B:72A132:A27C0E:6A620F15
html-safe-nonce220fe841d6e2522eb66aa1c9e757f7009b0bd0a494e5939c75232e8cdf359132
visitor-payloadeyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiI5RjM4OjE2Njg1Qjo3MkExMzI6QTI3QzBFOjZBNjIwRjE1IiwidmlzaXRvcl9pZCI6Ijg3NjkyMzEwMDE0NDM1MDM4OTMiLCJyZWdpb25fZWRnZSI6ImlhZCIsInJlZ2lvbl9yZW5kZXIiOiJpYWQifQ==
visitor-hmac775e4c22e89c09b640187e1b122ad3b3c894ae75dbce63374a7861221de53e11
hovercard-subject-tagissue:2632130207
github-keyboard-shortcutsrepository,issues,copilot
google-site-verificationApib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I
octolytics-urlhttps://collector.github.com/github/collect
analytics-location///voltron/issues_fragments/issue_layout
fb:app_id1401488693436528
apple-itunes-appapp-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/python/cpython/126384/issue_layout
twitter:imagehttps://opengraph.githubassets.com/0035a4cec2477cd36794120ff12514a60bd6f84e4d5e642979b8024d3fc2710c/python/cpython/issues/126384
twitter:cardsummary_large_image
og:imagehttps://opengraph.githubassets.com/0035a4cec2477cd36794120ff12514a60bd6f84e4d5e642979b8024d3fc2710c/python/cpython/issues/126384
og:image:altFeature or enhancement Proposal: I am one of the maintainers of comtypes. comtypes is based on ctypes to implement IUnknown and other COM stuffs. In the past, I reported in gh-124520 that projects ...
og:image:width1200
og:image:height600
og:site_nameGitHub
og:typeobject
og:author:usernamejunkmd
hostnamegithub.com
expected-hostnamegithub.com
Nonebe9a4d9589756e22b427637ffbf1123a96e067050e57f5cec403e3080a650ca4
turbo-cache-controlno-preview
go-importgithub.com/python/cpython git https://github.com/python/cpython.git
octolytics-dimension-user_id1525981
octolytics-dimension-user_loginpython
octolytics-dimension-repository_id81598961
octolytics-dimension-repository_nwopython/cpython
octolytics-dimension-repository_publictrue
octolytics-dimension-repository_is_forkfalse
octolytics-dimension-repository_network_root_id81598961
octolytics-dimension-repository_network_root_nwopython/cpython
turbo-body-classeslogged-out env-production page-responsive
disable-turbofalse
browser-stats-urlhttps://api.github.com/_private/browser/stats
browser-errors-urlhttps://api.github.com/_private/browser/errors
release7b5509702f01f876c214a2cbb142690847de0019
ui-targetfull
theme-color#1e2327
color-schemelight dark

Links:

Skip to contenthttps://github.com/python/cpython/issues/126384#start-of-content
https://github.com/
Sign in https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Fpython%2Fcpython%2Fissues%2F126384
GitHub CopilotWrite better code with AIhttps://github.com/features/copilot
GitHub Copilot appDirect agents from issue to mergehttps://github.com/features/ai/github-app
MCP RegistryNewIntegrate external toolshttps://github.com/mcp
ActionsAutomate any workflowhttps://github.com/features/actions
CodespacesInstant dev environmentshttps://github.com/features/codespaces
IssuesPlan and track workhttps://github.com/features/issues
Code ReviewManage code changeshttps://github.com/features/code-review
Code QualityEnforce quality at mergehttps://github.com/features/code-quality
GitHub Advanced SecurityFind and fix vulnerabilitieshttps://github.com/security/advanced-security
Code securitySecure your code as you buildhttps://github.com/security/advanced-security/code-security
Secret protectionStop leaks before they starthttps://github.com/security/advanced-security/secret-protection
Why GitHubhttps://github.com/why-github
Documentationhttps://docs.github.com
Bloghttps://github.blog
Changeloghttps://github.blog/changelog
Marketplacehttps://github.com/marketplace
View all featureshttps://github.com/features
Enterpriseshttps://github.com/enterprise
Small and medium teamshttps://github.com/team
Startupshttps://github.com/enterprise/startups
Nonprofitshttps://github.com/solutions/industry/nonprofits
App Modernizationhttps://github.com/solutions/use-case/app-modernization
DevSecOpshttps://github.com/solutions/use-case/devsecops
DevOpshttps://github.com/solutions/use-case/devops
CI/CDhttps://github.com/solutions/use-case/ci-cd
View all use caseshttps://github.com/solutions/use-case
Healthcarehttps://github.com/solutions/industry/healthcare
Financial serviceshttps://github.com/solutions/industry/financial-services
Manufacturinghttps://github.com/solutions/industry/manufacturing
Governmenthttps://github.com/solutions/industry/government
View all industrieshttps://github.com/solutions/industry
View all solutionshttps://github.com/solutions
AIhttps://github.com/resources/articles?topic=ai
Software Developmenthttps://github.com/resources/articles?topic=software-development
DevOpshttps://github.com/resources/articles?topic=devops
Securityhttps://github.com/resources/articles?topic=security
View all topicshttps://github.com/resources/articles
Customer storieshttps://github.com/customer-stories
Events & webinarshttps://github.com/resources/events
Ebooks & reportshttps://github.com/resources/whitepapers
Business insightshttps://github.com/solutions/executive-insights
GitHub Skillshttps://skills.github.com
Documentationhttps://docs.github.com
Customer supporthttps://support.github.com
Community forumhttps://github.com/orgs/community/discussions
Trust centerhttps://github.com/trust-center
Partnershttps://github.com/partners
View all resourceshttps://github.com/resources
GitHub SponsorsFund open source developershttps://github.com/open-source/sponsors
Security Labhttps://securitylab.github.com
Maintainer Communityhttps://maintainers.github.com
Acceleratorhttps://github.com/open-source/accelerator
GitHub Starshttps://stars.github.com
Archive Programhttps://archiveprogram.github.com
Topicshttps://github.com/topics
Trendinghttps://github.com/trending
Collectionshttps://github.com/collections
Enterprise platformAI-powered developer platformhttps://github.com/enterprise
GitHub Advanced SecurityEnterprise-grade security featureshttps://github.com/security/advanced-security
Copilot for BusinessEnterprise-grade AI featureshttps://github.com/features/copilot/copilot-business
Premium SupportEnterprise-grade 24/7 supporthttps://github.com/enterprise/premium-support
Pricinghttps://github.com/pricing
Search syntax tipshttps://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax
documentationhttps://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax
Sign in https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Fpython%2Fcpython%2Fissues%2F126384
Sign up https://github.com/signup?ref_cta=Sign+up&ref_loc=header+logged+out&ref_page=%2F%3Cuser-name%3E%2F%3Crepo-name%3E%2Fvoltron%2Fissues_fragments%2Fissue_layout&source=header-repo&source_repo=python%2Fcpython
Reloadhttps://github.com/python/cpython/issues/126384
Reloadhttps://github.com/python/cpython/issues/126384
Reloadhttps://github.com/python/cpython/issues/126384
Please reload this pagehttps://github.com/python/cpython/issues/126384
python https://github.com/python
cpythonhttps://github.com/python/cpython
Please reload this pagehttps://github.com/python/cpython/issues/126384
Notifications https://github.com/login?return_to=%2Fpython%2Fcpython
Fork 35k https://github.com/login?return_to=%2Fpython%2Fcpython
Star 73.9k https://github.com/login?return_to=%2Fpython%2Fcpython
Code https://github.com/python/cpython
Issues 5k+ https://github.com/python/cpython/issues
Pull requests 2.4k https://github.com/python/cpython/pulls
Actions https://github.com/python/cpython/actions
Projects https://github.com/python/cpython/projects
Security and quality 0 https://github.com/python/cpython/security
Insights https://github.com/python/cpython/pulse
Code https://github.com/python/cpython
Issues https://github.com/python/cpython/issues
Pull requests https://github.com/python/cpython/pulls
Actions https://github.com/python/cpython/actions
Projects https://github.com/python/cpython/projects
Security and quality https://github.com/python/cpython/security
Insights https://github.com/python/cpython/pulse
Add tests to verify the behavior of basic COM methods.https://github.com/python/cpython/issues/126384#top
testsTests in the Lib/test dirhttps://github.com/python/cpython/issues?q=state%3Aopen%20label%3A%22tests%22
topic-ctypeshttps://github.com/python/cpython/issues?q=state%3Aopen%20label%3A%22topic-ctypes%22
type-featureA feature request or enhancementhttps://github.com/python/cpython/issues?q=state%3Aopen%20label%3A%22type-feature%22
https://github.com/junkmd
junkmdhttps://github.com/junkmd
on Nov 4, 2024https://github.com/python/cpython/issues/126384#issue-2632130207
comtypeshttps://github.com/enthought/comtypes/
IUnknownhttps://learn.microsoft.com/en-us/windows/win32/api/unknwn/nn-unknwn-iunknown
gh-124520https://github.com/python/cpython/issues/124520
gh-125783https://github.com/python/cpython/issues/125783
QueryInterfacehttps://learn.microsoft.com/en-us/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(refiid_void)
AddRefhttps://learn.microsoft.com/en-us/windows/win32/api/unknwn/nf-unknwn-iunknown-addref
Releasehttps://learn.microsoft.com/en-us/windows/win32/api/unknwn/nf-unknwn-iunknown-release
gh-126384: Add tests to verify the behavior of basic COM methods. #126610https://github.com/python/cpython/pull/126610
[3.13] gh-126384: Add tests to verify the behavior of basic COM methods. (GH-126610) #127159https://github.com/python/cpython/pull/127159
[3.12] gh-126384: Add tests to verify the behavior of basic COM methods. (GH-126610) #127160https://github.com/python/cpython/pull/127160
testsTests in the Lib/test dirhttps://github.com/python/cpython/issues?q=state%3Aopen%20label%3A%22tests%22
topic-ctypeshttps://github.com/python/cpython/issues?q=state%3Aopen%20label%3A%22topic-ctypes%22
type-featureA feature request or enhancementhttps://github.com/python/cpython/issues?q=state%3Aopen%20label%3A%22type-feature%22
https://github.com
Termshttps://docs.github.com/site-policy/github-terms/github-terms-of-service
Privacyhttps://docs.github.com/site-policy/privacy-policies/github-privacy-statement
Securityhttps://github.com/security
Statushttps://www.githubstatus.com/
Communityhttps://github.community/
Docshttps://docs.github.com/
Contacthttps://support.github.com?tags=dotcom-footer

Viewport: width=device-width


URLs of crawlers that visited me.