-
-
Notifications
You must be signed in to change notification settings - Fork 31.8k
gh-78857: Always return a 2-tuple from divmod() and PyNumber_Divmod(). #9301
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
base: main
Are you sure you want to change the base?
Conversation
@@ -0,0 +1,2 @@ | |||
It is now guarantied that :func:`divmod` and :c:func`PyNumber_Divmod` always |
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.
s/guarantied/guaranteed/
@serhiy-storchaka Seems to be broken because magic mocks just return a magic mock. That could possibly be considered a bug in |
} | ||
if (!PyTuple_Check(result)) { | ||
orig_result = result; | ||
result = PySequence_Tuple(result); |
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.
You could Py_DECREF(orig_result)
right here, and then you could eliminate the 3 Py_(X)DECREF(orig_result)
s below
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.
Then there will be an undefined behavior in orig_result != NULL.
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.
I missed the connection between Py_DECREF
and free
here, good point.
Setting a single boolean in this branch would eliminate the need for the orig_result != NULL
, and would arguably be clearer - but I suppose that's bike-shedding
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.
I now remember why I used this way. Keeping the reference to orig_result
allows to use it in the error/warning message. The current version does not use it, but I was going to make a separate PR for more detailed error messages for all operations.
self.assertEqual(divmod([], fake_rdivmod([2, 3])), (2, 3)) | ||
self.assertRaises(TypeError, divmod, [], fake_rdivmod(42)) | ||
self.assertRaises(TypeError, divmod, [], fake_rdivmod(())) | ||
self.assertRaises(TypeError, divmod, [], fake_rdivmod((1, 2, 3))) |
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.
Might be good to add a namedtuple
example here, to state explicitly that tuple subclasses are intended to be supported.
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.
I hesitate. Should we allow tuple subclasses or require exact tuples? Most converting special methods (__int__
, __index__
, __float__
, __complex__
) are required to return an instance of exact type. From C side, if use the C API for unpacking the tuple, there is no difference between tuples and tuple subclasses. But there mey be difference at Python level if the tuple subclass overrides some methods like __add__
, __iter__
, __len__
, __getitem__
.
For now, I prefer to not promise the namedtuple support.
@@ -1836,7 +1813,7 @@ microseconds_to_delta_ex(PyObject *pyus, PyTypeObject *type) | |||
PyObject *num = NULL; | |||
PyObject *result = NULL; | |||
|
|||
tuple = checked_divmod(pyus, us_per_second); | |||
tuple = PyNumber_Divmod(pyus, us_per_second); |
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.
I haven't looked closely at any of the other stuff, but +1 on the _datetimemodule.c
stuff. It is very nice that it is now possible to make this simplification.
Co-authored-by: Eric Wieser <wieser.eric@gmail.com>
I don't think this should be applied. There isn't a known user issue being solved. Also, this changes a very old API so it might break some deployed code. Also, IIRC it created some issue with magic mocks. |
The problem is that virtually any use of Examples: There were similar issues in Python core code, until they were fixed. Alternatively we can provide a new public API for calling As for mocks, I think that it does not create some issue with magic mocks, but exposes some existing issues with magic mocks. |
-0 I would just let it be. ISTM that API restrictions are almost always more hassle than they are worth. |
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.
This has merge conflicts now.
Doc/whatsnew/3.9.rst
Outdated
@@ -764,6 +764,11 @@ Changes in the Python API | |||
environment variable when the :option:`-E` or :option:`-I` command line | |||
options are being used. | |||
|
|||
* :func:`divmod` and :c:func:`PyNumber_Divmod` will check the result of special | |||
methods ``__divmod__`` and ``__rdivmod__`` and emit a deprecation warning if | |||
it is not a tuple or raise an error if it's size is not 2. |
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.
it's size --> its size
When you're done making the requested changes, leave the comment: |
This PR is stale because it has been open for 30 days with no activity. |
This PR is stale because it has been open for 30 days with no activity. |
https://bugs.python.org/issue34676