-
-
Notifications
You must be signed in to change notification settings - Fork 31.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
bpo-33738: Fix macros which contradict PEP 384 #7477
Conversation
During development of the limited API support for PySide, we saw an error in a macro that accessed a type field. This patch fixes the 7 errors in the Python headers. Macros which were not written as capitals were implemented as function. To do the necessary analysis again, a script was included that parses all headers and looks for "->tp_" in serctions which can be reached with active limited API. It is easily possible to call this script as a test. Error listing: ../../Include/objimpl.h:243 #define PyObject_IS_GC(o) (PyType_IS_GC(Py_TYPE(o)) && \ (Py_TYPE(o)->tp_is_gc == NULL || Py_TYPE(o)->tp_is_gc(o))) Action: commented only ../../Include/objimpl.h:362 #define PyType_SUPPORTS_WEAKREFS(t) ((t)->tp_weaklistoffset > 0) Action: commented only ../../Include/objimpl.h:364 #define PyObject_GET_WEAKREFS_LISTPTR(o) \ ((PyObject **) (((char *) (o)) + Py_TYPE(o)->tp_weaklistoffset)) Action: commented only ../../Include/pyerrors.h:143 #define PyExceptionClass_Name(x) \ ((char *)(((PyTypeObject*)(x))->tp_name)) Action: implemented function ../../Include/abstract.h:593 #define PyIter_Check(obj) \ ((obj)->ob_type->tp_iternext != NULL && \ (obj)->ob_type->tp_iternext != &_PyObject_NextNotImplemented) Action: implemented function ../../Include/abstract.h:713 #define PyIndex_Check(obj) \ ((obj)->ob_type->tp_as_number != NULL && \ (obj)->ob_type->tp_as_number->nb_index != NULL) Action: implemented function ../../Include/abstract.h:924 #define PySequence_ITEM(o, i)\ ( Py_TYPE(o)->tp_as_sequence->sq_item(o, i) ) Action: commented only
During development of the limited API support for PySide, we saw an error in a macro that accessed a type field. This patch fixes the 7 errors in the Python headers. Macros which were not written as capitals were implemented as function. To do the necessary analysis again, a script was included that parses all headers and looks for "->tp_" in sections which can be reached with active limited API. It is easily possible to call this script as a test. Error listing: ../../Include/objimpl.h:243 (Py_TYPE(o)->tp_is_gc == NULL || Py_TYPE(o)->tp_is_gc(o))) Action: commented only ../../Include/objimpl.h:362 Action: commented only ../../Include/objimpl.h:364 ((PyObject **) (((char *) (o)) + Py_TYPE(o)->tp_weaklistoffset)) Action: commented only ../../Include/pyerrors.h:143 ((char *)(((PyTypeObject*)(x))->tp_name)) Action: implemented function ../../Include/abstract.h:593 ((obj)->ob_type->tp_iternext != NULL && \ (obj)->ob_type->tp_iternext != &_PyObject_NextNotImplemented) Action: implemented function ../../Include/abstract.h:713 ((obj)->ob_type->tp_as_number != NULL && \ (obj)->ob_type->tp_as_number->nb_index != NULL) Action: implemented function ../../Include/abstract.h:924 ( Py_TYPE(o)->tp_as_sequence->sq_item(o, i) ) Action: commented only
Can I squash these commits, or do I need to re-send the whole thing? (Or leave it in pieces) |
They'll be squashed at merge time, don't worry about it until then :) |
LGTM, although this is not an area of my expertise. Since we are getting very close to 3.7.0rc1 and it would be good to have this resolved, I'm going to merge this to master now so it gets some buildbot exposure. If anyone has any review comments, get them in real soon! Otherwise, I will backport and merge to 3.7 within the next 24 hours. |
Looks like the change introduces a compile warning. Should that be addressed?:
|
Yes it should be fixed. I was not aware that Python has const-ness, already. |
@ctismer Thanks. The best thing would be to open a new PR but, if you can paste the diff here, I'll take care of it. |
#define PyIter_Check(obj) \ | ||
((obj)->ob_type->tp_iternext != NULL && \ | ||
(obj)->ob_type->tp_iternext != &_PyObject_NextNotImplemented) | ||
#else | ||
PyAPI_FUNC(int) PyIter_Check(PyObject*); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick: it would look better if add a space between PyObject
and *
.
#define PyExceptionClass_Name(x) \ | ||
((char *)(((PyTypeObject*)(x))->tp_name)) | ||
#else | ||
PyAPI_FUNC(char *) PyExceptionClass_Name(PyObject*); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should return const char *
. And please add a space between PyObject
and *
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do.
My style is a bit spoiled by Qt's C++ style. They write "func(PyObject *self)"
but "func(PyObject*)".
I am preparing a diff as Ned said, but I can also repeat the PR.
@@ -140,8 +140,12 @@ PyAPI_FUNC(void) _PyErr_ChainExceptions(PyObject *, PyObject *, PyObject *); | |||
#define PyExceptionInstance_Check(x) \ | |||
PyType_FastSubclass((x)->ob_type, Py_TPFLAGS_BASE_EXC_SUBCLASS) | |||
|
|||
#ifndef Py_LIMITED_API | |||
#define PyExceptionClass_Name(x) \ | |||
((char *)(((PyTypeObject*)(x))->tp_name)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually (char *)
is not needed. But it should be documented in What's New that PyExceptionClass_Name()
now returns const char *
instead of char *
(there were similar breaking changes in 3.7).
@@ -342,6 +342,12 @@ PyException_SetContext(PyObject *self, PyObject *context) | |||
Py_XSETREF(((PyBaseExceptionObject *)self)->context, context); | |||
} | |||
|
|||
#undef PyExceptionClass_Name | |||
char * |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Return const char *
.
@@ -2535,6 +2543,13 @@ PyObject_GetIter(PyObject *o) | |||
} | |||
} | |||
|
|||
#undef PyIter_Check | |||
int PyIter_Check(PyObject *obj) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick: Break a line between int
and PyIter_Check
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, will do. Although all other #undef's are without newline.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Eeek, misunderstood!
Sure, you wanted a line after int!
I must have been very tired...
Seems I forgot to press the "Submit review" button after adding comments. |
Ok, I hope I got all changes right. Doing a new PR. |
Since this PR has been merged, my comments except the one about the result of |
Was this ever backported to Python 3.7? |
@tekknolagi No, I don't think they were ever backported to 3.7. See the discussion on the still open bug issue (https://bugs.python.org/issue33738) which is also the place for comments. In any case, with the upcoming release of 3.7.8, 3.7 has moved to |
During development of the limited API support for PySide,
we saw an error in a macro that accessed a type field.
This patch fixes the 7 errors in the Python headers.
Macros which were not written as capitals were implemented
as function.
To do the necessary analysis again, a script was included that
parses all headers and looks for "->tp_" in sections which can
be reached with active limited API.
It is easily possible to call this script as a test.
Error listing:
../../Include/objimpl.h:243
#define PyObject_IS_GC(o) (PyType_IS_GC(Py_TYPE(o)) &&
(Py_TYPE(o)->tp_is_gc == NULL || Py_TYPE(o)->tp_is_gc(o)))
Action: commented only
../../Include/objimpl.h:362
#define PyType_SUPPORTS_WEAKREFS(t) ((t)->tp_weaklistoffset > 0)
Action: commented only
../../Include/objimpl.h:364
#define PyObject_GET_WEAKREFS_LISTPTR(o)
((PyObject **) (((char *) (o)) + Py_TYPE(o)->tp_weaklistoffset))
Action: commented only
../../Include/pyerrors.h:143
#define PyExceptionClass_Name(x)
((char )(((PyTypeObject)(x))->tp_name))
Action: implemented function
../../Include/abstract.h:593
#define PyIter_Check(obj)
((obj)->ob_type->tp_iternext != NULL &&
(obj)->ob_type->tp_iternext != &_PyObject_NextNotImplemented)
Action: implemented function
../../Include/abstract.h:713
#define PyIndex_Check(obj)
((obj)->ob_type->tp_as_number != NULL &&
(obj)->ob_type->tp_as_number->nb_index != NULL)
Action: implemented function
../../Include/abstract.h:924
#define PySequence_ITEM(o, i)
( Py_TYPE(o)->tp_as_sequence->sq_item(o, i) )
Action: commented only
https://bugs.python.org/issue33738