-
-
Notifications
You must be signed in to change notification settings - Fork 18.4k
BUG: divmod return type #22932
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
BUG: divmod return type #22932
Changes from 14 commits
52538fa
c92a4a8
1b4261f
0671e7d
35d4213
7ef697c
c9fe5d3
2247461
a0cd5e7
11a0d93
cc2bfc8
4e9b7f0
95d5cbf
c9d6e89
ec814db
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,7 +8,7 @@ | |
|
||
from pandas.tests.extension import base | ||
|
||
from .array import DecimalDtype, DecimalArray, make_data | ||
from .array import DecimalDtype, DecimalArray, make_data, to_decimal | ||
|
||
|
||
@pytest.fixture | ||
|
@@ -102,7 +102,7 @@ class TestInterface(BaseDecimal, base.BaseInterfaceTests): | |
|
||
class TestConstructors(BaseDecimal, base.BaseConstructorsTests): | ||
|
||
@pytest.mark.xfail(reason="not implemented constructor from dtype") | ||
@pytest.mark.skip(reason="not implemented constructor from dtype") | ||
def test_from_dtype(self, data): | ||
# construct from our dtype & string dtype | ||
pass | ||
|
@@ -240,9 +240,28 @@ def test_arith_series_with_array(self, data, all_arithmetic_operators): | |
context.traps[decimal.DivisionByZero] = divbyzerotrap | ||
context.traps[decimal.InvalidOperation] = invalidoptrap | ||
|
||
@pytest.mark.skip(reason="divmod not appropriate for decimal") | ||
def test_divmod(self, data): | ||
pass | ||
@pytest.mark.parametrize("reverse, expected_div, expected_mod", [ | ||
(False, [0, 1, 1, 2], [1, 0, 1, 0]), | ||
(True, [2, 1, 0, 0], [0, 0, 2, 2]), | ||
]) | ||
def test_divmod_array(self, reverse, expected_div, expected_mod): | ||
# https://github.com/pandas-dev/pandas/issues/22930 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we try to better indicate that this is an "extra" test (not overriding a base one)? (not necessarily needs to be solved here, but question is relevant in general, as we sometimes add tests to eg decimal to test specific aspects not covered in the base tests, to clearly see which those tests are. Maybe we would put them outside the class?) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Having it off the class makes the most sense. Moved. |
||
arr = to_decimal([1, 2, 3, 4]) | ||
if reverse: | ||
div, mod = divmod(2, arr) | ||
else: | ||
div, mod = divmod(arr, 2) | ||
expected_div = to_decimal(expected_div) | ||
expected_mod = to_decimal(expected_mod) | ||
|
||
tm.assert_extension_array_equal(div, expected_div) | ||
tm.assert_extension_array_equal(mod, expected_mod) | ||
|
||
def _check_divmod_op(self, s, op, other, exc=NotImplementedError): | ||
# We implement divmod | ||
super(TestArithmeticOps, self)._check_divmod_op( | ||
s, op, other, exc=None | ||
) | ||
|
||
def test_error(self): | ||
pass | ||
|
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.
@jbrockmendel can't we use dispatch_to_extension_op here to avoid duplication of code?
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 asked something similar a few days ago. If Tom says it isn't feasible, I believe him.
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.
We are inside the extension array here, so it would also be strange to use (which doesn't prevent that both could share a helper function, if that would be appropriate).
But here we need to construct the divmod correctly, while dispatch_to_extension_op should assume this is already done correctly by the EA
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.
Right. This is possible, if people want it. I'll push up a commit with some kind of
do_extension_op
that both of these call to so people can take a look.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.
Ah, now that I take a look it's not so straightforward. The two are similar but just slightly different in enough places that they wouldn't benefit from sharing code really.
dispatch_to_extension_op
knows that at least one of the two is a Series[EA]._binop
knows thatself
is an EA.dispatch_to_extension_op
dispatches,_binop
is defining it in a list comprehension_binop
has the whole maybe re-constructing_from_seqence
that thedispatch_to_extension_op
doesn't have to worry about at all.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.
They do not do "conceptually exactly the same thing". Paraphrasing myself from above:
Why would those two different things necessarily need to live in the same place / code path?
Of course, we could still move the whole
EA._create_method
toops.py
(which would indeed be similar as functions likeadd_flex_arithmetic_methods
in ops.py that is used inseries.py
to add methods to Series). But this is then not related to the change in this PR, and should be left for another issue/PR to discuss (personally I don't think that would be an improvement).Well, and both Tom and me who have looked into the code, say: we don't think it is possible.
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.
@TomAugspurger I saw your comment. I also @jorisvandenbossche comments. I have not looked at this in detail, nor do I have time to. My point is that this instantly creates technical debt no matter how you slice it.
It may require some reorganization to integrate this, and I appreciate that. So happy to defer this, maybe @jbrockmendel has more insight.
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'll be doing a sparse-de-duplication PR following #22880, can take a fresh look at this then. In the interim, I wouldn't let this issue hold up this PR.
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 really doesn't. They're doing two different things.
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 PR is fixing a bug, not doing a refactor of how the ops on EA's are implemented** . If somebody want to look into that, it should be done in a separate PR anyway. So merging.
** and I fully acknowledge that sometimes, to properly fix a bug, you also need to refactor otherwise you just keep adding hacks. However, I don't think that is the case here, see all the comments above.