bpo-33738: Fix macros which contradict PEP 384#7477
bpo-33738: Fix macros which contradict PEP 384#7477ned-deily merged 2 commits intopython:masterfrom pyside:master
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. |
| ((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.
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.
Should return const char *. And please add a space between PyObject and *.
There was a problem hiding this comment.
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.
|
|
||
| #ifndef Py_LIMITED_API | ||
| #define PyExceptionClass_Name(x) \ | ||
| ((char *)(((PyTypeObject*)(x))->tp_name)) |
There was a problem hiding this comment.
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).
| } | ||
|
|
||
| #undef PyExceptionClass_Name | ||
| char * |
| } | ||
|
|
||
| #undef PyIter_Check | ||
| int PyIter_Check(PyObject *obj) |
There was a problem hiding this comment.
Nitpick: Break a line between int and PyIter_Check.
There was a problem hiding this comment.
Ok, will do. Although all other #undef's are without newline.
There was a problem hiding this comment.
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