Skip to content

BUG: ensure _UFuncNoLoopError can be pickled#17377

Merged
seberg merged 4 commits intonumpy:masterfrom
bfgray3:ufuncnolooperror-pickling
Nov 18, 2020
Merged

BUG: ensure _UFuncNoLoopError can be pickled#17377
seberg merged 4 commits intonumpy:masterfrom
bfgray3:ufuncnolooperror-pickling

Conversation

@bfgray3
Copy link
Copy Markdown
Contributor

@bfgray3 bfgray3 commented Sep 26, 2020

Applies the suggested solution in #16490 and adds a simple test.

@bfgray3 bfgray3 changed the title BUG: ensure _UFuncNoLoopError can be pickled; closes #16490 BUG: ensure _UFuncNoLoopError can be pickled Sep 26, 2020
@mattip
Copy link
Copy Markdown
Member

mattip commented Sep 26, 2020

Still need to adjust the doctest that is failing

class TestUFuncNoLoopError:
def test_pickling(self):
""" Test that _UFuncNoLoopError can be pickled """
assert isinstance(pickle.dumps(_UFuncNoLoopError), bytes)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for looking into this, looks good to me. If you have some time, maybe you can extend the test to also loading and the error instance and not just the error class?

It may be easier for memory error (either seems enough to me for now). Could you add a test that round-tripping works, maybe something like:

error = _ArrayMemoryError((1023,), np.dtype(np.uint8))
res = pickle.loads(pickle.dumps(error))

assert res._total_size == error._total_size

I would mostly like a test that the error (instances) can also be unpickled again. I admit, they clearly can here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

done in 866b39e

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks. One more nitpick: test would make more sense as a test_pickling in the TestArrayMemoryError class.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

fixed in ea0c5f5

Traceback (most recent call last):
...
numpy.core._exceptions.UFuncTypeError: Cannot cast ufunc 'add' output from dtype('float64') to dtype('int64') with casting rule 'same_kind'
numpy.core._exceptions._UFuncOutputCastingError: Cannot cast ufunc 'add' output from dtype('float64') to dtype('int64') with casting rule 'same_kind'
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Hmm, @eric-wieser I think you had an opinion on the original issue? I had tried in ipython, and I thought it just printed the __name__, but maybe not.

I think I will just open an issue about it after this is done, but it would seem nice if we can find a solution and also print out a name that we want users to use in try: ... except: Error. UFuncTypeError seems good, but it should not be in a private module, and maybe we should just use a single class for all the subclasses (at least until we make them public), to avoid printing a private name?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

maybe we should just use a single class for all the subclasses (at least until we make them public), to avoid printing a private name?

One of the ideas behind the subclasses was to avoid actually paying any string formatting costs until the traceback is printed. Merging them into one class would make that more difficult.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

OK, maybe the real question is different: If UFuncTypeError is private (due to being defined in _exceptions), should this set it to TypeError.__qualname__ and TypeError.__name__, etc. instead?

It might not be hard to fix this differently by using __reduce__(self): return f"{original_module}.{original_qualname}".

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Overloading __reduce__ sounds promising to me

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I guess the question is whether right now we are OK with messing up the print slightly to fix the pickling. Sorry, I thought this was much clearer :(.

I am not sure __reduce__ will work easily. It will be a solution for the error instance, but I doubt it will work for the error class. Now the original bug report did not have an issue with that, so maybe we can get away with a class that cannot be pickled (but its instances can).

@bfgray3 bfgray3 requested review from eric-wieser and seberg October 6, 2020 22:30
@mattip
Copy link
Copy Markdown
Member

mattip commented Oct 19, 2020

@seberg, @eric-wieser is this good to go?

@seberg
Copy link
Copy Markdown
Member

seberg commented Oct 19, 2020

Arrg, sorry. I am +0.5 for putting it in. The printing gets slightly worse, but it is already bad with np._exceptions. I am unsure that a custom __reduce__ will work easily. Especially, that cannot fix the pickling of the type object itself probably (unless you create a metaclass, and I don't see that a good idea).

There is some "proper" fix missing here, but right now I am not sure what it is. Maybe exposing a UfuncTypeError properly and moving the error message creation into a single class for all the calls.

@charris charris added the 09 - Backport-Candidate PRs tagged should be backported label Oct 27, 2020
@seberg seberg added the triage review Issue/PR to be discussed at the next triage meeting label Nov 11, 2020
@seberg
Copy link
Copy Markdown
Member

seberg commented Nov 18, 2020

OK, this is not ideal with printing. But it is a possible regression in some use cases, so putting it in (we discussed it briefly on the call). Thanks!

@seberg seberg merged commit 8fee756 into numpy:master Nov 18, 2020
@bfgray3 bfgray3 deleted the ufuncnolooperror-pickling branch November 20, 2020 02:35
@charris charris removed the 09 - Backport-Candidate PRs tagged should be backported label Dec 4, 2020
@charris charris removed this from the 1.19.5 release milestone Dec 4, 2020
charris pushed a commit to charris/numpy that referenced this pull request Dec 4, 2020
* BUG: ensure _UFuncNoLoopError can be pickled; closes numpy#16490

* update quickstart.rst

* add round trip pickle test

* move _ArrayMemoryError picking test
@charris charris modified the milestone: 1.19.5 release Dec 4, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

00 - Bug triage review Issue/PR to be discussed at the next triage meeting

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants