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

Adding more information to "Too Few Arguments" #9796

Merged
merged 7 commits into from Dec 17, 2020

Conversation

abhinaypandey02
Copy link
Contributor

@abhinaypandey02 abhinaypandey02 commented Dec 12, 2020

Description

Fixes #9340

As mentioned in the feature request, mypy now gives more information about the missing required arguments when creating an instance.
The problem was with the if statement that only gave information when the arguments provided were not empty and none. Removing that check gives information for calls with no argument too.

Before:
test.py:6: error: Too few arguments for "Foo"

After:
test.py:7: error: "Foo" missing 1 required positional argument: 'bar'

Test Plan

All tests passing

@abhinaypandey02
Copy link
Contributor Author

I am sorry I don't have much knowledge about tests. Do I need to manually change all the tests because "Too few arguments" error is invoked plenty of times. Forgive me for sounding stupid I am new.

@TH3CHARLie
Copy link
Collaborator

Do I need to manually change all the tests because "Too few arguments" error is invoked plenty of times.

Yes but you can do it smartly. Using --update-data flag can save a lot of trouble, see: https://github.com/python/mypy/blob/master/mypyc/doc/dev-intro.md#ir-tests

@TH3CHARLie
Copy link
Collaborator

And you also need to fix your code formatting to pass flake8 tests

@abhinaypandey02
Copy link
Contributor Author

abhinaypandey02 commented Dec 13, 2020

Do I need to manually change all the tests because "Too few arguments" error is invoked plenty of times.

Yes but you can do it smartly. Using --update-data flag can save a lot of trouble

None of pytest --update-data mypy, pytest --update-data, pytest --update-data mypyc worked for me when executed in the mypyc/ main directory.They all just add a newline above the test that fails. Am I missing something?(Eventually I built my own python script to modify test files)

Also I integrated flake8 with my Visual Studio code. It would be nice if you could help me figure out the flake8 arguments/settings used with mypy (other than max-length, I am getting many errors that are ignored by mypy's flake8, so what all am I supposed to add to --ignore argument.

@TH3CHARLie
Copy link
Collaborator

To submit a PR to mypy, all you need is to run runtests.py in your workspace. The script would run self type checking, formatting checking, and IR tests. There's no need to write your own custom script or use vscode's flake8 functionality.

For the --update-data flag, add the flag to runtests.py when you actually need it and remember to exclude this change when you are committing the changes.

This may help you have a better understanding of mypy testing workflow: https://github.com/python/mypy/blob/master/test-data/unit/README.md

@abhinaypandey02
Copy link
Contributor Author

To submit a PR to mypy, all you need is to run runtests.py in your workspace. The script would run self type checking, formatting checking, and IR tests. There's no need to write your own custom script or use vscode's flake8 functionality.

For the --update-data flag, add the flag to runtests.py when you actually need it and remember to exclude this change when you are committing the changes.

This may help you have a better understanding of mypy testing workflow: https://github.com/python/mypy/blob/master/test-data/unit/README.md

Thanks a lot and sorry for not giving the readme a read.

Copy link
Collaborator

@TH3CHARLie TH3CHARLie left a comment

Choose a reason for hiding this comment

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

The change to existing code needs some second thoughts, see comments below.

@@ -110,7 +110,7 @@ from typing import Callable, Union
x = 5 # type: Union[int, Callable[[], None], Callable[[int], None]]

if callable(x):
x() # E: Too few arguments
x() # E: Missing positional argument
Copy link
Collaborator

Choose a reason for hiding this comment

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

This error message should not apply to Callable IMO. The current one would do the job.

@@ -3751,7 +3751,7 @@ int.__eq__(int)
int.__eq__(3, 4)
[builtins fixtures/args.pyi]
[out]
main:33: error: Too few arguments for "__eq__" of "int"
main:33: error: Missing positional arguments
Copy link
Collaborator

Choose a reason for hiding this comment

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

same here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I understand callable and lamda functions. But here are you pointing at magic methods?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If I make my message something as Missing positional argument for call to "__eq__" of "int" then the only difference would be language. So is it about language or the missing function name here?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think the original language is sufficient. The new one does not make much improvement.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So I think where the information about the arguments to be provided is not available, i.e. the message is just "Missing positional argument", there we can leave it to the old language? Should I code it that way?

Copy link
Collaborator

Choose a reason for hiding this comment

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

exactly. For callables, lambdas, magic methods (and maybe more), the names of the arguments are unknown so staying to the old language is totally fine. Let's improve the language only for user-defined functions and methods in this PR. If there's a need to improve other cases in the future, we can do them later in separate PRs.

@@ -623,7 +623,7 @@ reveal_type((lambda x, y: x + y)(1, 2)) # N: Revealed type is 'builtins.int'
reveal_type((lambda s, i: s)(i=0, s='x')) # N: Revealed type is 'Literal['x']?'
reveal_type((lambda s, i: i)(i=0, s='x')) # N: Revealed type is 'Literal[0]?'
reveal_type((lambda x, s, i: x)(1.0, i=0, s='x')) # N: Revealed type is 'builtins.float'
(lambda x, s, i: x)() # E: Too few arguments
(lambda x, s, i: x)() # E: Missing positional arguments
Copy link
Collaborator

Choose a reason for hiding this comment

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

same for lambda functions

@@ -214,7 +214,7 @@ main:5: error: Invalid "type: ignore" comment [syntax]

[case testErrorCodeArgKindAndCount]
def f(x: int) -> None: pass # N: "f" defined here
f() # E: Too few arguments for "f" [call-arg]
f() # E: Missing positional argument "x" in call to "f" [call-arg]
Copy link
Collaborator

Choose a reason for hiding this comment

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

this is a perfect example of what's expected in this PR IMO

@TH3CHARLie
Copy link
Collaborator

Thanks for the updates! Can you verify the case in #9340? For example, use the following code(copied from the issue):

class Foo:
    def __init__(self, bar: int):
        pass

c = Foo()

def foo(baz: int, bas: int):
    pass

foo()

You may also make this a new test case. I did some verification locally and looks like the changes don't work on this segment.

@abhinaypandey02
Copy link
Contributor Author

@TH3CHARLie I have tested the code in the issue #9340 and the new changes reflect. I made a new test case to check missing positional arguments using the code in the issue and it passes.

Copy link
Collaborator

@TH3CHARLie TH3CHARLie left a comment

Choose a reason for hiding this comment

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

Thanks for the updates and verifications, looks good to me. However I am not sure I am 100% in sync with the expectations in #9340, @gvanrossum Would you mind taking a look if you have time?

@abhinaypandey02
Copy link
Contributor Author

Thanks for the updates and verifications, looks good to me. However I am not sure I am 100% in sync with the expectations in #9340, @gvanrossum Would you mind taking a look if you have time?

Thanks a lot for your review and approval.

Copy link
Member

@gvanrossum gvanrossum left a comment

Choose a reason for hiding this comment

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

Hm, the number of tests that have to be fixed is a bit much, and in some cases the name of the missing argument isn't very useful, but I agree its most consistent. So weak +1.

@TH3CHARLie
Copy link
Collaborator

Hm, the number of tests that have to be fixed is a bit much, and in some cases the name of the missing argument isn't very useful, but I agree its most consistent. So weak +1.

Thanks for the review. I am merging this now but I'll keep an eye on this(and respond to any future feedbacks about it) since error messages are important and pervasive

@TH3CHARLie TH3CHARLie merged commit eb0bf11 into python:master Dec 17, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Class __init__ "Too few arguments" should be a better error message
3 participants