Skip to content

ENH: Adding type checks to set_printoptions() #7859

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

Closed
wants to merge 2 commits into from

Conversation

tom-bird
Copy link
Contributor

See issue #7852.

We raise a TypeError if the first argument isn't of the expected type. Not very Pythonic, but otherwise set_printoptions() doesn't fail, but will cause any subsequent calls to print() to fail with an opaque error. In particular someone could mistakenly pass a dict (rather than an unpacked dict).

@@ -161,6 +165,8 @@ def set_printoptions(precision=None, threshold=None, edgeitems=None,
if edgeitems is not None:
_summaryEdgeItems = edgeitems
if precision is not None:
if type(precision) is not int:
Copy link
Member

Choose a reason for hiding this comment

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

if not isinstance(precision, int):

@rkern
Copy link
Member

rkern commented Jul 21, 2016

It might be worth adding type checks for some of the other arguments and value checks (e.g. that precision >= 0), if you feel up to it, but I agree that this solves the error mode in #7852, which is probably the most important to deal with.

@tom-bird
Copy link
Contributor Author

Yeh. I'll leave it for now, as I think the main issue is passing a dict or some other object as the only argument, and in general we should be promoting duck typing

@njsmith
Copy link
Member

njsmith commented Jul 22, 2016

Well, there are two somewhat conflicting principles here: Duck typing is a good thing, but failing early rather than late is also a good thing :-). If we can tell at set_printoptions time that we're just going to fail later, then it's better to raise the error immediately. But I also agree with @rkern that this is an improvement.

@njsmith
Copy link
Member

njsmith commented Jul 22, 2016

Code contents

@njsmith njsmith closed this Jul 22, 2016
@njsmith njsmith reopened this Jul 22, 2016
@njsmith
Copy link
Member

njsmith commented Jul 22, 2016

Sorry for the misclick...

Code comments:

  • There should be a comment noting why this particular argument needs to be checked (because it's the first positional argument and we want to catch this common mistake where it's a dict)
  • Like all changes, this needs a test added to make sure it works and keeps working.

Thanks for contributing!

@tom-bird
Copy link
Contributor Author

No worries!

I originally included a comment explaining why the error was being raised, but it was suggested I remove it. I will add it back in if @rkern is happy?

Ah ok, I'm new to this - could you possibly run me through the process of adding the test?

@seberg
Copy link
Member

seberg commented Jul 22, 2016

I would argue that duck typing is easy, just do precision = operator.index(precision), or something similar.
You can find tests in numpy/core/tests/ check for the right file (probably test_arrayprint.py and find some place that seems good. The tests are pretty self explanatory.

EDIT: of course operator.index is assuming that an ssize_t is sufficient for the precision keyword ;).

@rkern
Copy link
Member

rkern commented Jul 22, 2016

I dislike the comment. The only reason it might be desirable is to explain why there is only type-checking on the one argument. I'd rather you just add basic type-checking to the other arguments instead.

@njsmith
Copy link
Member

njsmith commented Jul 22, 2016

reason it might be desirable is to explain why there is only type-checking on the one argument

Well, yes, exactly ;-)

For adding a test: tests are just functions whose name starts with test_, and that live in one of the test files, and that call assert_* functions to check things. There are probably some tests for printing already; if you grep for the string "printoptions" then you'll probably find the right place to add your test. Here you'll want to use assert_raises (again, grep will find you other examples in the codebase), and to run the tests just run ./runtests.py in the root of your checkout. (Plus tests will also be run automatically when you push new changes to the PR.)

@tom-bird
Copy link
Contributor Author

OK. Well it's 1 v 1 on the comment issue, but I decided to add it as I think it could be unclear to someone examining the code a to why there is only one type check.

I've added a test in the appropriate place, thanks for the explanation.

I've also combined my commits into one to clean it all up. Hopefully this all done and dusted now :)

@rkern
Copy link
Member

rkern commented Jul 25, 2016

If you are going to make a comment, make it a comment and not part of the docs. It's only a puzzle to people reading the source code, not users.

But I'd really rather you add basic checks to the other arguments.

@seberg
Copy link
Member

seberg commented Jul 25, 2016

Well, as long as the error makes sense in the other cases, it would not matter, but otherwise I think Robert is right, there is not much gain by not adding the other checks to have a more reasonable error.

As to the isinstance check. In cetero censeo: Use operator.index instead to convert it in a duck-typing way. I seriously dislike that isinstance check, it will even fail some (on python 3 all) numpy integers.

@tom-bird
Copy link
Contributor Author

Good points, I will add the operator.index logic instead - duck typing is better and I didn't realise isinstance could fail on numpy ints.

I will check all the int parameters that are passed, is there an equally clean way to check the bool or string parameters? I.e. using duck typing.

@njsmith
Copy link
Member

njsmith commented Jul 26, 2016

Yes, when I said comment I meant a comment next to the check, not anything in the docstring.

For type checks: Probably just calling bool(...) and str(...)? I guess that's effectively what will happen later anyway, either explicitly or implicitly...

@tom-bird
Copy link
Contributor Author

I left the boolean argument - it was already parsed by not not, but I've added parsing the string arguments with str(...). All the integer arguments are now parsed by operator.index(...), and I removed the comment.

I think now we're implementing duck typing in the right way, raising errors when we need to.

@seberg
Copy link
Member

seberg commented Jul 28, 2016

Just to note, that I realized that operator.index is slightly more strict then the current behaviour (by not allowing things such as floats). Not sure we should be bothered by it or not.

@seberg
Copy link
Member

seberg commented Jul 28, 2016

However, since it is a slight change in behaviour, if we do it, we still might want to note it in the release notes for completeness.

@charris charris changed the title Adding a type check to set_printoptions() ENH: Adding a type check to set_printoptions() Aug 23, 2016
@homu
Copy link
Contributor

homu commented May 17, 2017

☔ The latest upstream changes (presumably #8983) made this pull request unmergeable. Please resolve the merge conflicts.

@mattip mattip changed the title ENH: Adding a type check to set_printoptions() ENH: Adding type checks to set_printoptions() May 1, 2019
@mattip
Copy link
Member

mattip commented May 1, 2019

@tom-bird this seems like a nice addition, feel like rebasing it (to fix merge conflicts) and adding a release note?

@eric-wieser
Copy link
Member

At this point, this PR will probably need to restart from scratch - none of the modified lines exist any more. The idea is still good though, so if we close this PR we should open an issue to replace it.

@charris
Copy link
Member

charris commented Dec 17, 2020

Going to close this, the original issue remains open. @tom-bird If you want to give it another shot please open a new PR. @BvB93 Do the annotations help with this?

@charris charris closed this Dec 17, 2020
@BvB93
Copy link
Member

BvB93 commented Dec 17, 2020

@charris I would imagine so, yes.
Though at first the glance i suspect that somewhat convoluted nature of np.core.arrayprint will make annotating it a bit challenging (needs further investigation).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants