Skip to content
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-26868: Fix example usage of PyModule_AddObject. #15725

Merged
merged 7 commits into from
Sep 12, 2019

Conversation

brandtbucher
Copy link
Member

@brandtbucher brandtbucher commented Sep 7, 2019

Unlike other APIs that steal references, PyModule_AddObject only does it on success. However, most calls throughout the codebase don't manually Py_DECREF on failure as required by the implementation, which leads contributors to believe that it is not necessary. This PR fixes example usage and adds a note on this behavior in the documentation only.

There are over 200 bad calls throughout the codebase that are not addressed by this patch. Because there are so many bugs, fixing them all will likely require more care and likely several PRs (or a possible deprecation period and behavior change... it appears incorrect usage is actually more common than correct usage). I'm willing to do the work, but some direction on this would be nice.

https://bugs.python.org/issue26868

@brandtbucher
Copy link
Member Author

@serhiy-storchaka

@brandtbucher
Copy link
Member Author

Thanks for the feedback @serhiy-storchaka! Changes applied, tests are passing.

Py_INCREF(SpamError);
PyModule_AddObject(m, "error", SpamError);
Py_XINCREF(SpamError);
if (PyModule_AddObject(m, "error", SpamError)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest to add also < 0 in all other checks for PyModule_AddObject() result.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this an agreed-upon style? I had always thought it was a matter of taste.

In either case, I guess all of these files should at least be consistent...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add the extra test with < 0

@ghost
Copy link

ghost commented Sep 11, 2019

There are three sytles currently:

  1. if (PyModule_AddObject())
  2. if (PyModule_AddObject() < 0)
  3. if (PyModule_AddObject() == -1)

After some thinking, I think the second one is not bad.

Usually APIs use a negative return number to indicate failure.
Even the reader is not familiar with Python code, if he/she sees < 0, may guess that it's likely to detect failure.
So style 2 is a bit better than style 1.

The third style may produce a very slightly longer machine code:

; 19   :     if (PyModule_AddObject())
  00004	e8 00 00 00 00	 call	 ?PyModule_AddObject@@YAHXZ ; PyModule_AddObject
  00009	85 c0		 test	 eax, eax
  0000b	74 07		 je	 SHORT $LN2@main

; 21   :     if (PyModule_AddObject() < 0)
  00004	e8 00 00 00 00	 call	 ?PyModule_AddObject@@YAHXZ ; PyModule_AddObject
  00009	85 c0		 test	 eax, eax
  0000b	7d 07		 jge	 SHORT $LN2@main

; 23   :     if (PyModule_AddObject() == -1)
  00004	e8 00 00 00 00	 call	 ?PyModule_AddObject@@YAHXZ ; PyModule_AddObject
  00009	83 f8 ff	 cmp	 eax, -1
  0000c	75 07		 jne	 SHORT $LN2@main

And < 0 is likely to indicate that all failures are covered, not a specific failure.
So style 2 is a bit better than style 3.

There are reasons, although the reasons are weak. 😂

Copy link
Member

@matrixise matrixise left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, Thank you for your contribution but could you add the small requested changes.

Thank you

@@ -1261,8 +1267,12 @@ function must take care of initializing the C API pointer array::
/* Create a Capsule containing the API pointer array's address */
c_api_object = PyCapsule_New((void *)PySpam_API, "spam._C_API", NULL);

if (c_api_object != NULL)
PyModule_AddObject(m, "_C_API", c_api_object);
if (PyModule_AddObject(m, "_C_API", c_api_object)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto, change the example with if (PyModule_AddObject(m, "_C_API", c_api_object) < 0)

@@ -179,7 +179,12 @@ This initializes the :class:`Custom` type, filling in a number of members
to the appropriate default values, including :attr:`ob_type` that we initially
set to *NULL*. ::

PyModule_AddObject(m, "Custom", (PyObject *) &CustomType);
Py_INCREF(&CustomType);
if (PyModule_AddObject(m, "Custom", (PyObject *) &CustomType)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

@@ -864,7 +869,12 @@ function::
return NULL;

Py_INCREF(&SubListType);
PyModule_AddObject(m, "SubList", (PyObject *) &SubListType);
if (PyModule_AddObject(m, "SubList", (PyObject *) &SubListType)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

@@ -35,6 +35,11 @@ PyInit_custom(void)
return NULL;

Py_INCREF(&CustomType);
PyModule_AddObject(m, "Custom", (PyObject *) &CustomType);
if (PyModule_AddObject(m, "Custom", (PyObject *) &CustomType)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

@@ -128,6 +128,11 @@ PyInit_custom2(void)
return NULL;

Py_INCREF(&CustomType);
PyModule_AddObject(m, "Custom", (PyObject *) &CustomType);
if (PyModule_AddObject(m, "Custom", (PyObject *) &CustomType)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

@@ -179,6 +179,11 @@ PyInit_custom3(void)
return NULL;

Py_INCREF(&CustomType);
PyModule_AddObject(m, "Custom", (PyObject *) &CustomType);
if (PyModule_AddObject(m, "Custom", (PyObject *) &CustomType)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

@@ -193,6 +193,11 @@ PyInit_custom4(void)
return NULL;

Py_INCREF(&CustomType);
PyModule_AddObject(m, "Custom", (PyObject *) &CustomType);
if (PyModule_AddObject(m, "Custom", (PyObject *) &CustomType)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

@@ -59,6 +59,11 @@ PyInit_sublist(void)
return NULL;

Py_INCREF(&SubListType);
PyModule_AddObject(m, "SubList", (PyObject *) &SubListType);
if (PyModule_AddObject(m, "SubList", (PyObject *) &SubListType)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

@matrixise matrixise self-assigned this Sep 12, 2019
Copy link
Member

@matrixise matrixise left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your contribution, I have fixed the remarks with < 0 in the examples. I am going to merge it.

@matrixise matrixise merged commit 224b8aa into python:master Sep 12, 2019
@bedevere-bot
Copy link

@matrixise: Please replace # with GH- in the commit message next time. Thanks!

@miss-islington
Copy link
Contributor

Thanks @brandtbucher for the PR, and @matrixise for merging it 🌮🎉.. I'm working now to backport this PR to: 3.7, 3.8.
🐍🍒⛏🤖

miss-islington pushed a commit to miss-islington/cpython that referenced this pull request Sep 12, 2019
* Add a note to the PyModule_AddObject docs.

* Correct example usages of PyModule_AddObject.

* Whitespace.

* Clean up wording.

* 📜🤖 Added by blurb_it.

* First code review.

* Add < 0 in the tests with PyModule_AddObject
(cherry picked from commit 224b8aa)

Co-authored-by: Brandt Bucher <brandtbucher@gmail.com>
@bedevere-bot
Copy link

GH-16037 is a backport of this pull request to the 3.8 branch.

miss-islington pushed a commit to miss-islington/cpython that referenced this pull request Sep 12, 2019
* Add a note to the PyModule_AddObject docs.

* Correct example usages of PyModule_AddObject.

* Whitespace.

* Clean up wording.

* 📜🤖 Added by blurb_it.

* First code review.

* Add < 0 in the tests with PyModule_AddObject
(cherry picked from commit 224b8aa)

Co-authored-by: Brandt Bucher <brandtbucher@gmail.com>
@bedevere-bot
Copy link

GH-16038 is a backport of this pull request to the 3.7 branch.

miss-islington added a commit that referenced this pull request Sep 12, 2019
* Add a note to the PyModule_AddObject docs.

* Correct example usages of PyModule_AddObject.

* Whitespace.

* Clean up wording.

* 📜🤖 Added by blurb_it.

* First code review.

* Add < 0 in the tests with PyModule_AddObject
(cherry picked from commit 224b8aa)

Co-authored-by: Brandt Bucher <brandtbucher@gmail.com>
miss-islington added a commit that referenced this pull request Sep 12, 2019
* Add a note to the PyModule_AddObject docs.

* Correct example usages of PyModule_AddObject.

* Whitespace.

* Clean up wording.

* 📜🤖 Added by blurb_it.

* First code review.

* Add < 0 in the tests with PyModule_AddObject
(cherry picked from commit 224b8aa)

Co-authored-by: Brandt Bucher <brandtbucher@gmail.com>
@brandtbucher
Copy link
Member Author

Thanks @matrixise!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs Documentation in the Doc dir
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants