GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
GeezerVison is showing github.com — bpo-42327: Add PyModule_Add() (smaller). by serhiy-storchaka · Pull Request #23443 · python/cpython Conversation
|
|
This is the same as #23240, but without large changes to modules _ssl, _testbuffer, _testcapi, posix, select, socket, _msi, msvcrt. They will be extracted to separate PRs. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
I like the new functon, but I prefer PyModule_AddObjectRef(obj) rather than Py_INCREF(obj); PyModule_Add(obj). In some cases, you removed a test for NULL, but I don't think that it's worth it (I prefer an explicit test with PyModule_AddObjectRef, but that's a personal preference, I guess). At least, when not test for == NULL is needed, PyModule_AddObjectRef() should be preferred IMO.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
|
Could you split this PR in two parts? The first uncontroversial PR which only adds the function, and then a second PR which modify PyInit functions to use it. These days, there are dozens of PRs modifying PyInit functions which would be in conflict with the second part. See bpo-40077 and bpo-1635741. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
I still prefer https://github.com/python/cpython/pull/23286/files over
How about we land PR #23286 first, port more code to the new API, and then see if we still need |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
This PR is stale because it has been open for 30 days with no activity. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
I dislike APIs stealing references. IMO we should stop adding such API. I would prefer regular (boring and verbose) reference counting to make the C API easier to understand. Currently, developers have to check the documentation of each function to check if it returns a borrowed or strong reference, if it adds or removes a reference (and leave the ref count unchanged), etc. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
It is a convenient API. How else would you fix Modules/mathmodule.c, for example? The "N" code in return Py_BuildValue("Nl", _PyLong_FromTime_t(sec), nsec); instead of: PyObject *tmp = _PyLong_FromTime_t(sec); if (tmp == NULL) { return NULL; } PyObject *res = Py_BuildValue("Ol", tmp, nsec); Py_DECREF(tmp); return res; |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
Usually, a macro is written to create a temporary object and add it to the module. If you use PyModule_AddObjectRef(), the macro would also clear the reference. I dislike the fact that macro is "required" to write correct code. In 2020, @tiran proposed designing a new API to make this work easier with a declarative syntax: https://discuss.python.org/t/define-module-constants-in-pymoduledef/5749 |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Macro is convenient because it can include "goto error" or "return NULL". But having to write such macro in every module is tiring. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
We can make it a private function at first if you so dislike adding it to the public API. Then we can add new @tiran's API and decide whether it is worth to add public |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
IMO, that's a good guideline, but But it should be very clear from the name. I don't think |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
To be clear, I dislike APIs stealing references, but I don't plan to block this PR. I will just not endorse it :-) If using PyModule_AddObjectRef() is not convenient, maybe we need to provide "something" to make it easier to use. Sadly, the C language is limited in terms of macros/templates :-( The approach based on a description is promising, but I also know that there are many technical challenges which may not be possible to be solved. By the way, I'm really unhappy on the bad state of our PyInit functions: many of them simply have no error checking, or just one final PyErr_Occurred() check. That's bad. The trend is more to disallow calling functions with an exception set (it might be enforced later). If this new function makes the situation better: go ahead ;-) |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
What does "New" stand for? This function does not create a new reference, but steals a reference. Is is "New" because its a new function replacing an old one? What if tomorrow, there is a newer function? Should we call it PyModule_AddNewer or PyModule_AddNewEx? I suggest to just call it PyModule_Add(). |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
It adds a newly created object. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
It may be easier to review this big PR if you could move code fixing PyInit functions into a separated PR.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
| .. c:function:: int PyModule_Add(PyObject *module, const char *name, PyObject *value) | ||
|
|
||
| Similar to :c:func:`PyModule_AddObjectRef`, but "steals" a reference | ||
| to *value*. |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
PyModule_AddObjectRef() must not be called with NULL. Can you please elaborate the behavior when value is NULL? Something like:
If value is NULL, just return -1.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
PyModule_AddObjectRef() can be called with NULL if an exception is set. Actually, some of my fixes which use PyModule_AddObjectRef() rely on this.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| // Similar to PyModule_AddObjectRef() but steal a reference to 'obj' | ||
| // (Py_DECREF(obj)) on success (if it returns 0). | ||
| #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030d0000 | ||
| // Similar to PyModule_AddObjectRef() but steal a reference to 'value'. |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
I suggest to add "and value can be NULL".
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| PyAPI_FUNC(int) PyModule_Add(PyObject *mod, const char *name, PyObject *value); | ||
| #endif /* Py_LIMITED_API */ | ||
|
|
||
| // Similar to PyModule_AddObjectRef() and PyModule_Add() but steal |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
It's not similar to PyModule_AddObjectRef(): value can be NULL.
| // Similar to PyModule_AddObjectRef() and PyModule_Add() but steal | |
| // Similar to PyModule_Add() but steal |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
|
||
| // Similar to PyModule_AddObjectRef() and PyModule_Add() but steal | ||
| // a reference to 'value' on success and only on success. | ||
| // Errorprone. Should not be used in new code. |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
IMO it's important important to put it in the documentation. This kind of definition fits perfectly with the Soft Deprecated status. Maybe also soft deprecate this API, similar to getopt and optparse soft deprecation. Example with getopt:
.. deprecated:: 3.13
The :mod:`getopt` module is :term:`soft deprecated` and will not be
developed further; development will continue with the :mod:`argparse`
module.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Do you suggest to convert the note block into deprecated?
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Ok, but this PR changes |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
If I have further comments, I may propose them as a separated PR.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Thanks Victor. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Even if I dislike stealing references, the API seems to help simplifying PyInit code a lot. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
I added the |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
I wrote PR #106859 to document PyModule_AddObject() soft deprecation in What's New in Python 3.13. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
There was an error while loading. Please reload this page.