Title: __class_getitem__ Unexpectedly Falls Back to the Metaclass · Issue #122634 · python/cpython · GitHub
Open Graph Title: __class_getitem__ Unexpectedly Falls Back to the Metaclass · Issue #122634 · python/cpython
X Title: __class_getitem__ Unexpectedly Falls Back to the Metaclass · Issue #122634 · python/cpython
Description: Bug report Bug description: A major point of __class_getitem__ (PEP 560) is to avoid metaclasses. This implies that the metaclass should never be involved in the mechanism. However, currently (and since the feature landed) we actually do...
Open Graph Description: Bug report Bug description: A major point of __class_getitem__ (PEP 560) is to avoid metaclasses. This implies that the metaclass should never be involved in the mechanism. However, currently (and ...
X Description: Bug report Bug description: A major point of __class_getitem__ (PEP 560) is to avoid metaclasses. This implies that the metaclass should never be involved in the mechanism. However, currently (and ...
Opengraph URL: https://github.com/python/cpython/issues/122634
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"__class_getitem__ Unexpectedly Falls Back to the Metaclass","articleBody":"# Bug report\r\n\r\n### Bug description:\r\n\r\nA major point of `__class_getitem__` ([PEP 560](https://peps.python.org/pep-0560/)) is to avoid metaclasses. This implies that the metaclass should never be involved in the mechanism. However, currently (and since the feature landed) we actually do fall back to the metaclass:\r\n\r\n\u003cdetails\u003e\r\n\u003csummary\u003e(example)\u003c/summary\u003e\r\n\r\n```python\r\nclass Spam:\r\n def __class_getitem__(cls, key):\r\n return f'spam got {key!r}'\r\n\r\n\r\nclass Meta(type):\r\n def __class_getitem__(cls, key):\r\n return f'meta got {key!r}'\r\n\r\n\r\nclass Eggs(metaclass=Meta):\r\n def __class_getitem__(cls, key):\r\n return f'eggs got {key!r}'\r\n\r\n\r\nclass Ham(metaclass=Meta):\r\n pass\r\n\r\nprint(Spam[10])\r\nprint(Eggs[10])\r\nprint(Ham[10])\r\n```\r\n\r\nOutput:\r\n\r\n```\r\nspam got 10\r\neggs got 10\r\nmeta got 10\r\n```\r\n\r\n\u003c/details\u003e\r\n\r\nI was expecting the last one to raise `TypeError: type 'object' is not subscriptable`, since `Ham` does not implement `__class_getitem__`. The actual outcome is surprising because the metaclass can already define `__getitem__`. Falling back to the metaclass `__class_getitem__` doesn't make much sense and can be confusing. The metaclass `__class_getitem__` should only be used when subscripting the metaclass, not its instances.\r\n\r\nThe PEP doesn't really address the question of a metaclass that defines `__class_getiem__` [^1] (nor does the documentation as far as I noticed). Overall, it seems like this was simply not noticed nor considered. It's certainly not an obvious case. Regardless, I think we should fix it.\r\n\r\n[^1]: The PEP does say `Note that this method is used as a fallback, so if a metaclass defines __getitem__, then that will have the priority.` but that's specifically about falling back to `meta.__getitem__`.\r\n\r\nThe fix would involve skipping the metaclass part. That would be in the implementation for the subscript syntax (`PyObject_GetItem()` in Objects/abstract.c). There's a part where it specially handles the case where a class is being subscripted. In that case it looks up `__class_getitem__` on the class. (See gh-4732.) However, currently it uses `PyObject_GetOptionalAttr()`, which involves descriptors and the metaclass (the object's type) and the type's `__mro__`. Again, the fix is to skip the metaclass part.\r\n\r\nFWIW, `__init_subclass__` is fairly similar, but it doesn't fall back to the metaclass. Instead, it effectively does `getattr(super(cls), '__init_subclass__')`. (See `type_new_init_subclass()` in Objects/typeobject.c.) We should probably do something similar in `PyObject_GetItem()`.\r\n\r\nCC @ilevkivskyi @gvanrossum\r\n\r\n### CPython versions tested on:\r\n\r\nCPython main branch\r\n\r\n### Operating systems tested on:\r\n\r\n_No response_\n\n\u003c!-- gh-linked-prs --\u003e\n### Linked PRs\n* gh-122743\n\u003c!-- /gh-linked-prs --\u003e\n","author":{"url":"https://github.com/ericsnowcurrently","@type":"Person","name":"ericsnowcurrently"},"datePublished":"2024-08-03T00:10:24.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":7},"url":"https://github.com/122634/cpython/issues/122634"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:f97c7d1c-f9fc-9d33-3c4d-043796b9d7f1 |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | 9F70:2D209F:37E7FE:51980C:6A4E0331 |
| html-safe-nonce | f2f95f9066527023cb36afc96b6196868d48f4bd43298c72b51b630330bc11db |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiI5RjcwOjJEMjA5RjozN0U3RkU6NTE5ODBDOjZBNEUwMzMxIiwidmlzaXRvcl9pZCI6IjU4Njk4MDU1MDYyODk5OTk4NSIsInJlZ2lvbl9lZGdlIjoiaWFkIiwicmVnaW9uX3JlbmRlciI6ImlhZCJ9 |
| visitor-hmac | b5da809c3e50f1805785932e8dd3630845c76b54d15e1e69aac0887474a085ff |
| hovercard-subject-tag | issue:2445903987 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/python/cpython/122634/issue_layout |
| twitter:image | https://opengraph.githubassets.com/3204049a3e668919191949d45a4e0f5095d6badb4ab49cc6f2131b40b2129c61/python/cpython/issues/122634 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/3204049a3e668919191949d45a4e0f5095d6badb4ab49cc6f2131b40b2129c61/python/cpython/issues/122634 |
| og:image:alt | Bug report Bug description: A major point of __class_getitem__ (PEP 560) is to avoid metaclasses. This implies that the metaclass should never be involved in the mechanism. However, currently (and ... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | ericsnowcurrently |
| hostname | github.com |
| expected-hostname | github.com |
| None | df0492960db29b4938cb72070351d6b1d0c6c0767b27ceb8394bbf4fcc0223c6 |
| turbo-cache-control | no-preview |
| go-import | github.com/python/cpython git https://github.com/python/cpython.git |
| octolytics-dimension-user_id | 1525981 |
| octolytics-dimension-user_login | python |
| octolytics-dimension-repository_id | 81598961 |
| octolytics-dimension-repository_nwo | python/cpython |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 81598961 |
| octolytics-dimension-repository_network_root_nwo | python/cpython |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 52bde38e24398476f8eb1e0760c81346c6a00812 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width