Title: Argument clinic: improve generated code for self converter type checks · Issue #101409 · python/cpython · GitHub
Open Graph Title: Argument clinic: improve generated code for self converter type checks · Issue #101409 · python/cpython
X Title: Argument clinic: improve generated code for self converter type checks · Issue #101409 · python/cpython
Description: Feature or enhancement Currently, typically for __new__ and __init__ methods, Argument Clinic will spell out the self type check as such: if kind == METHOD_NEW: type_check = ('({0} == {1} ||\n ' ' {0}->tp_init == {2}tp_init)' ).format(se...
Open Graph Description: Feature or enhancement Currently, typically for __new__ and __init__ methods, Argument Clinic will spell out the self type check as such: if kind == METHOD_NEW: type_check = ('({0} == {1} ||\n ' ' ...
X Description: Feature or enhancement Currently, typically for __new__ and __init__ methods, Argument Clinic will spell out the self type check as such: if kind == METHOD_NEW: type_check = ('({0} == {1} ||\n ...
Opengraph URL: https://github.com/python/cpython/issues/101409
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"Argument clinic: improve generated code for self converter type checks","articleBody":"# Feature or enhancement\r\n\r\nCurrently, typically for `__new__` and `__init__` methods, Argument Clinic will spell out the `self` type check as such:\r\n\r\n```python\r\nif kind == METHOD_NEW:\r\n type_check = ('({0} == {1} ||\\n '\r\n ' {0}-\u003etp_init == {2}tp_init)'\r\n ).format(self.name, type_object, prefix)\r\nelse:\r\n type_check = ('(Py_IS_TYPE({0}, {1}) ||\\n '\r\n ' Py_TYPE({0})-\u003etp_new == {2}tp_new)'\r\n ).format(self.name, type_object, prefix)\r\n```\r\n\r\n`prefix` is a slightly modified variant of `type_object`, depending on if the latter is a pointer. This works swell in most cases, but with module state and heap types, the generated code is not optimal. First, let's just quote the AC docs on how to declare a class:\r\n\r\n\u003e When you declare a class, you must also specify two aspects of its type in C: the type declaration you’d use for a pointer to an instance of this class, and a pointer to the [PyTypeObject](https://docs.python.org/3.10/c-api/type.html#c.PyTypeObject) for this class.\r\n\r\nFor heap types with module state, you'd typically do something like this:\r\n\r\n```c\r\ntypedef struct {\r\n ...\r\n} myclass_object;\r\n\r\ntypedef struct {\r\n PyTypeObject myclass_type;\r\n} module_state;\r\n\r\nstatic inline module_state *\r\nfind_state_by_type(PyTypeObject *tp)\r\n{\r\n PyObject *mod = PyType_GetModuleByDef(\u0026moduledef); // Potentially slow!\r\n void *state = PyModule_GetState(mod);\r\n return (module_state*)state;\r\n}\r\n\r\n#define clinic_state() (find_state_by_type(type))\r\n#include \"clinic/mymod.c.h\"\r\n#undef clinic_state\r\n\r\n/*[clinic input]\r\nmodule mymod\r\nclass mymod.myclass \"myclass_object *\" \"clinic_state()-\u003emyclass_type\"\r\n[clinic start generated code]*/\r\n```\r\n\r\nCurrently, this generates clinic code like this:\r\n\r\n```c\r\nmymod_myclass_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)\r\n{\r\n ...\r\n\r\n if ((type == clinic_state()-\u003eRowType ||\r\n type-\u003etp_init == clinic_state()-\u003eRowType-\u003etp_init) \u0026\u0026\r\n```\r\n\r\n... _potentially_ calling `PyType_GetModuleByDef` twice in the self type check.\r\n\r\n# Pitch\r\n\r\nSuggesting to modify clinic to store the self type pointer in a local variable, and use that variable in the self type check. Proof-of-concept diff from the `_sqlite` extension module clinic code\r\n\r\n```diff\r\ndiff --git a/Modules/_sqlite/clinic/cursor.c.h b/Modules/_sqlite/clinic/cursor.c.h\r\nindex 36b8d0051a..633ad2e73d 100644\r\n--- a/Modules/_sqlite/clinic/cursor.c.h\r\n+++ b/Modules/_sqlite/clinic/cursor.c.h\r\n@@ -16,10 +16,11 @@ static int\r\n pysqlite_cursor_init(PyObject *self, PyObject *args, PyObject *kwargs)\r\n {\r\n int return_value = -1;\r\n+ PyTypeObject *self_tp = clinic_state()-\u003eCursorType;\r\n pysqlite_Connection *connection;\r\n \r\n- if ((Py_IS_TYPE(self, clinic_state()-\u003eCursorType) ||\r\n- Py_TYPE(self)-\u003etp_new == clinic_state()-\u003eCursorType-\u003etp_new) \u0026\u0026\r\n+ if ((Py_IS_TYPE(self, self_tp) ||\r\n+ Py_TYPE(self)-\u003etp_new == self_tp-\u003etp_new) \u0026\u0026\r\n !_PyArg_NoKeywords(\"Cursor\", kwargs)) {\r\n goto exit;\r\n }\r\n@@ -318,4 +319,4 @@ pysqlite_cursor_close(pysqlite_Cursor *self, PyObject *Py_UNUSED(ignored))\r\n {\r\n return pysqlite_cursor_close_impl(self);\r\n }\r\n-/*[clinic end generated code: output=e53e75a32a9d92bd input=a9049054013a1b77]*/\r\n+/*[clinic end generated code: output=e5eac0cbe29c88ad input=a9049054013a1b77]*/\r\n```\r\n\r\n# Previous discussion\r\n\r\nhttps://github.com/python/cpython/pull/101302#discussion_r1089924859\r\n\r\n\u003c!-- gh-linked-prs --\u003e\r\n### Linked PRs\r\n* gh-101411\r\n\u003c!-- /gh-linked-prs --\u003e\r\n","author":{"url":"https://github.com/erlend-aasland","@type":"Person","name":"erlend-aasland"},"datePublished":"2023-01-29T22:42:07.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":1},"url":"https://github.com/101409/cpython/issues/101409"}
| 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:1418aa50-2b88-1abd-df43-c4f2ba3b6a61 |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | 8C56:37C592:F17D34:1419A5A:696991B8 |
| html-safe-nonce | 3d01f03bb9d003e1231a667af77931e60e56ad7e33686d6b7d6d1758e5a425f9 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiI4QzU2OjM3QzU5MjpGMTdEMzQ6MTQxOUE1QTo2OTY5OTFCOCIsInZpc2l0b3JfaWQiOiIzNzgwNzE2NzYzMDQwODEzNDk2IiwicmVnaW9uX2VkZ2UiOiJpYWQiLCJyZWdpb25fcmVuZGVyIjoiaWFkIn0= |
| visitor-hmac | 51e0a6d707662c7f50b252e0e915b239793549f0ea165bc20d57a4e6048b3696 |
| hovercard-subject-tag | issue:1561489769 |
| 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/101409/issue_layout |
| twitter:image | https://opengraph.githubassets.com/4bcb79c2d71d4688ae712729e14f18e157c3f31358f1a8f70e4dbc1b007c3d2a/python/cpython/issues/101409 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/4bcb79c2d71d4688ae712729e14f18e157c3f31358f1a8f70e4dbc1b007c3d2a/python/cpython/issues/101409 |
| og:image:alt | Feature or enhancement Currently, typically for __new__ and __init__ methods, Argument Clinic will spell out the self type check as such: if kind == METHOD_NEW: type_check = ('({0} == {1} ||\n ' ' ... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | erlend-aasland |
| hostname | github.com |
| expected-hostname | github.com |
| None | 3542e147982176a7ebaa23dfb559c8af16f721c03ec560c68c56b64a0f35e751 |
| 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 | af80af7cc9e3de9c336f18b208a600950a3c187c |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width