Skip to content
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

bpo-37034: Display argument name on errors with keyword-only arguments with Argument Clinic #13593

Merged

Conversation

remilapeyre
Copy link
Contributor

@remilapeyre remilapeyre commented May 27, 2019

@vstinner
Copy link
Member

Is _PyArg_BadArgument() used with positional-only argument? If yes, your PR is wrong. The name of positional-only arguments must not be used.

@remilapeyre
Copy link
Contributor Author

Is _PyArg_BadArgument() used with positional-only argument? If yes, your PR is wrong. The name of positional-only arguments must not be used.

I tried to take care of this case in https://github.com/python/cpython/pull/13593/files#diff-5e15637e15d50f49f6cb1d7f69fcab4bR854. Did I miss something? If so, happy to start again :D

Python/getargs.c Outdated Show resolved Hide resolved
@vstinner
Copy link
Member

argnum = repr(p.name) if p.is_keyword_only() else str(i + 1)

I don't think that this line is correct. You should also use the parameter name for positional-or-keyword. I propose the following change on top of your PR:

diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py
index f6f8704ba6..68303f5b19 100755
--- a/Tools/clinic/clinic.py
+++ b/Tools/clinic/clinic.py
@@ -928,7 +928,7 @@ class CLanguage(Language):
 
             add_label = None
             for i, p in enumerate(parameters):
-                argnum = repr(p.name) if p.is_keyword_only() else str(i + 1)
+                argnum = p.name if p.is_positional_or_keyword() else str(i + 1)
                 parsearg = p.converter.parse_arg(argname_fmt % i, argnum)
                 if parsearg is None:
                     #print('Cannot convert %s %r for %s' % (p.converter.__class__.__name__, p.converter.format_unit, p.converter.name), file=sys.stderr)
@@ -2267,6 +2267,9 @@ class Parameter:
     def __repr__(self):
         return '<clinic.Parameter ' + self.name + '>'
 
+    def is_positional_or_keyword(self):
+        return self.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD
+
     def is_keyword_only(self):
         return self.kind == inspect.Parameter.KEYWORD_ONLY
 

I'm not even sure that my change is correct. Maybe is_positional_only() should be used to decide if the name must not be used.

I removed repr() to let the compiler merge duplicated strings. If you care of '...' format, please add use 2 exclusive parameters in _PyArg_BadArgument(): one for argument position, one for positional-only arguments.

@vstinner
Copy link
Member

If you care of '...' format, please add use 2 exclusive parameters in _PyArg_BadArgument(): one for argument position, one for positional-only arguments.

By the way, that would be my preference: it's strange to store an integer as a bytes string ("2") rather than just an int (2).

@remilapeyre
Copy link
Contributor Author

remilapeyre commented May 28, 2019

You should also use the parameter name for positional-or-keyword.

Thanks, I wasn't sure what to do here so I made a conservative choice but I agree this is better.

In the implementation of _PyArg_BadArgument(), the position of the argument is checked so that it is not displayed when it is the first argument. I think it was introduced in this commit : 4fa9591#diff-8aaf09dbd5eefbcdceb804ab2143a907. This seems weird to me, you get the position of the argument in the error message if an error happened with the second, the third, etc. but not if it's the first. Should I keep this behavior?

@vstinner
Copy link
Member

In the implementation of _PyArg_BadArgument(), the position of the argument is checked so that it is not displayed when it is the first argument.

If the parameter is a keyword-only or positional-or-keyword, IHMO we must display its name. it's helpful.

@remilapeyre
Copy link
Contributor Author

Yes but for positional only parameters, the current message is

>>> b = BytesIO(b"foobar")
>>> b.readinto(4)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: readinto() argument must be read-write bytes-like object, not int

without indications about which parameter (when it is the first one), instead of the more useful

>>> b.readinto(4)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: readinto() argument 0 must be read-write bytes-like object, not int

This could be confusing when there is multiple arguments, should I keep the first one or make it display the second one?

@vstinner
Copy link
Member

TypeError: readinto() argument must be read-write bytes-like object, not int

is fine if the function accepts 0 or 1 argument.

TypeError: readinto() argument 0 must be read-write bytes-like object, not int

is bad if the function accepts more than 1 argument.

@remilapeyre
Copy link
Contributor Author

Hi Victor, thanks for your feedback. I updated the PR based on your comments, it should be better now.

Copy link

@auvipy auvipy left a comment

Choose a reason for hiding this comment

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

please re base

@remilapeyre
Copy link
Contributor Author

please re base
Is this recommanded? I thought that we needed to avoid rebasing to keep the comments in the review meaningful and that everything would get squashed anyway.

@brettcannon brettcannon added the type-feature A feature request or enhancement label Jun 3, 2019
Copy link
Member

@vstinner vstinner left a comment

Choose a reason for hiding this comment

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

LGTM. I just ask a minor change, add a comment :-)

@serhiy-storchaka: Would you mind to double check this change?

Python/getargs.c Outdated Show resolved Hide resolved
@remilapeyre remilapeyre requested review from a team as code owners August 29, 2019 14:01
@remilapeyre
Copy link
Contributor Author

Hi, I made the last changes and regenerated the clinic files. I tried to do a squashed merge but that made GitHub noisy-ing nearly everybody, sorry about that :/

@serhiy-storchaka serhiy-storchaka merged commit 4901fe2 into python:master Aug 29, 2019
@miss-islington
Copy link
Contributor

Thanks @remilapeyre for the PR, and @serhiy-storchaka for merging it 🌮🎉.. I'm working now to backport this PR to: 3.8.
🐍🍒⛏🤖

@miss-islington
Copy link
Contributor

Sorry, @remilapeyre and @serhiy-storchaka, I could not cleanly backport this to 3.8 due to a conflict.
Please backport using cherry_picker on command line.
cherry_picker 4901fe274bc82b95dc89bcb3de8802a3dfedab32 3.8

serhiy-storchaka pushed a commit to serhiy-storchaka/cpython that referenced this pull request Aug 29, 2019
…ts with Argument Clinic. (pythonGH-13593).

(cherry picked from commit 4901fe2)

Co-authored-by: Rémi Lapeyre <remi.lapeyre@henki.fr>
@bedevere-bot
Copy link

GH-15599 is a backport of this pull request to the 3.8 branch.

serhiy-storchaka added a commit that referenced this pull request Aug 29, 2019
…ts with Argument Clinic. (GH-13593). (GH-15599)

(cherry picked from commit 4901fe2)

Co-authored-by: Rémi Lapeyre <remi.lapeyre@henki.fr>
lisroach pushed a commit to lisroach/cpython that referenced this pull request Sep 10, 2019
DinoV pushed a commit to DinoV/cpython that referenced this pull request Jan 14, 2020
websurfer5 pushed a commit to websurfer5/cpython that referenced this pull request Jul 20, 2020
@serhiy-storchaka serhiy-storchaka removed their assignment Dec 29, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants