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

TypeError message became less helpful in Python 2.7 #54152

Closed
gjb1002 mannequin opened this issue Sep 24, 2010 · 10 comments
Closed

TypeError message became less helpful in Python 2.7 #54152

gjb1002 mannequin opened this issue Sep 24, 2010 · 10 comments
Labels
interpreter-core (Objects, Python, Grammar, and Parser dirs) type-bug An unexpected behavior, bug, or error

Comments

@gjb1002
Copy link
Mannequin

gjb1002 mannequin commented Sep 24, 2010

BPO 9943
Nosy @terryjreedy, @ncoghlan, @benjaminp, @merwok

Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

Show more details

GitHub fields:

assignee = None
closed_at = <Date 2014-09-29.02:57:24.290>
created_at = <Date 2010-09-24.19:44:17.519>
labels = ['interpreter-core', 'type-bug']
title = 'TypeError message became less helpful in Python 2.7'
updated_at = <Date 2014-09-29.02:57:24.288>
user = 'https://bugs.python.org/gjb1002'

bugs.python.org fields:

activity = <Date 2014-09-29.02:57:24.288>
actor = 'benjamin.peterson'
assignee = 'none'
closed = True
closed_date = <Date 2014-09-29.02:57:24.290>
closer = 'benjamin.peterson'
components = ['Interpreter Core']
creation = <Date 2010-09-24.19:44:17.519>
creator = 'gjb1002'
dependencies = []
files = []
hgrepos = []
issue_num = 9943
keywords = []
message_count = 10.0
messages = ['117327', '117346', '117347', '117354', '117413', '117468', '117820', '227784', '227786', '227787']
nosy_count = 6.0
nosy_names = ['terry.reedy', 'gjb1002', 'ncoghlan', 'benjamin.peterson', 'eric.araujo', 'BreamoreBoy']
pr_nums = []
priority = 'normal'
resolution = 'wont fix'
stage = None
status = 'closed'
superseder = None
type = 'behavior'
url = 'https://bugs.python.org/issue9943'
versions = ['Python 2.7']

@gjb1002
Copy link
Mannequin Author

gjb1002 mannequin commented Sep 24, 2010

Consider the following code:

### keywords.py

def f(**kw):
    print arg, kw

f("hello", keyword=True)

and compare the behaviour in Python 2.6 and Python 2.7:

$ python keywords.py 
Traceback (most recent call last):
  File "keywords.py", line 5, in <module>
    f("hello", keyword=True)
TypeError: f() takes exactly 0 non-keyword arguments (1 given)

$ python2.7 keywords.py
Traceback (most recent call last):
  File "keywords.py", line 5, in <module>
    f("hello", keyword=True)
TypeError: f() takes exactly 0 arguments (2 given)

The error message from 2.6 is I would say a more accurate description of the situation.

@gjb1002 gjb1002 mannequin added interpreter-core (Objects, Python, Grammar, and Parser dirs) type-bug An unexpected behavior, bug, or error labels Sep 24, 2010
@benjaminp
Copy link
Contributor

r85003 Thanks for the report.

@benjaminp
Copy link
Contributor

Reverted, however. Let me clarify: you think the unhelpful part is that the count includes keyword arguments? This change was intentional, actually wrt to cases like this:

    >>> def f(a):
    ...    pass
    >>> f(6, a=4, *(1, 2, 3))
    Traceback (most recent call last):
      ...
    TypeError: f() takes exactly 1 positional argument (5 given)
    >>> def f(a, *, kw):
    ...    pass
    >>> f(6, 4, kw=4)
    Traceback (most recent call last):
      ...
    TypeError: f() takes exactly 1 positional argument (3 given)

@benjaminp benjaminp reopened this Sep 25, 2010
@gjb1002
Copy link
Mannequin Author

gjb1002 mannequin commented Sep 25, 2010

I think the unhelpful part is mostly that it does not distinguish between argument types any more when the distinction is important in this context. In fact, it could be argued that what it said isn't even true:

f() takes exactly 0 arguments (2 given)

f() doesn't take exactly 0 arguments. It takes any number of arguments, so long as they are keyword arguments.

Surely you agree that the Python 2.6 error describes the problem more accurately?

As for your examples, the message in the first one has changed from

TypeError: f() takes exactly 1 non-keyword argument (4 given)

to

TypeError: f() takes exactly 1 argument (5 given)

which is possibly a marginal improvement, although taken together I would say this isn't an improvement, especially as I think examples like my first one are more widespread (OK, I didn't even know this syntax was legal...)

Your second example is only legal syntax in Python 3, so I don't really get the point with respect to comparing Python 2.6 and Python 2.7.

@ncoghlan
Copy link
Contributor

Having seen the reversion go by on the checkins list, I think there are distinctions the interpreter should be making here in order to improve the error messages, but it isn't.

Ideally, we want to be able to tell the user (without writing War and Peace as an error message):

  1. How many positional parameters are expected
  2. How many positional parameters were supplied as positional arguments
  3. How many positional parameters were supplied as keyword arguments

For example:

Def: f(**kw)
Call: f("hello", keyword=True)
Error: f() does not accept positional arguments (1 given)

Def: f(x, **kw)
Call: f("hello", "goodbye", keyword=True)
Error: f() accepts at most 1 positional argument (2 given)

Def: f(x, **kw)
Call: f("hello", x="goodbye", keyword=True)
Error: f() accepts at most 1 positional argument (2 given, 1 via keyword)

Basically:

  1. Get rid of the "exactly"/"at most" distinction ("exactly" is wrong, since you can always provide positional arguments as keyword arguments instead)
  2. Use "positional" instead of the awkward "non-keyword"
  3. Append additional info when some or all of the positional arguments are provided as keywords.

@gjb1002
Copy link
Mannequin Author

gjb1002 mannequin commented Sep 27, 2010

I agree with Nick :)

Though I'd say fixing a regression should take priority over further enhancing the messages.

@terryjreedy
Copy link
Member

FWIW 3.1 gives same message as 2.6. I have not installed 3.2a yet to check that.

Reporting of argument count mismatch has always been problematical, especially for methods. I almost think the message should be simplified to "Arguments passed do not match function signature." Programmers who do not immediately immediately see the problem (because they know the signature but made an inadvertent mistake) will have to check the signature anyway.

The alternative should be a clearer and more complete report than currently, which will take more than one line.

@BreamoreBoy
Copy link
Mannequin

BreamoreBoy mannequin commented Sep 28, 2014

3.4.1 and 3.5.0a0 give the same message as 2.6. I don't have 2.7 to see what it currently does.

@terryjreedy
Copy link
Member

Still TypeError: f() takes exactly 0 arguments (2 given). I consider the 2.6/3.x message better (more accurate). But at this point, I could be persuaded to leave 2.7 alone and close this.

@benjaminp
Copy link
Contributor

Yes, the argument error messages for 2.x are all not very good. Note this issue was fixed once and for all in Python 3:

% python3 x.py
Traceback (most recent call last):
  File "x.py", line 3, in <module>
    f("hello", keyword=True)
TypeError: f() takes 0 positional arguments but 1 was given

@ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
interpreter-core (Objects, Python, Grammar, and Parser dirs) type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

No branches or pull requests

3 participants