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

Add Flag to Suppress Warnings for Dynamically Typed Functions #87

Closed
Dreamsorcerer opened this issue May 25, 2020 · 12 comments · Fixed by #83 or #91
Closed

Add Flag to Suppress Warnings for Dynamically Typed Functions #87

Dreamsorcerer opened this issue May 25, 2020 · 12 comments · Fixed by #83 or #91
Assignees
Labels
enhancement New feature or request
Milestone

Comments

@Dreamsorcerer
Copy link

Dreamsorcerer commented May 25, 2020

For consistency with mypy, it would be nice to have an option/rule that behaved the same way as mypy regarding typing of __init__().

Currently, flake8-annotations always raises a violation if there is no return type annotation.

Mypy, however, raises an error if there are no annotations at all (as this would indicate an untyped function).
i.e. If there are any annotations on parameters, then a return type is not needed. The return type is only needed when there are no parameters in order to mark the function as statically typed.
e.g. def __init__(self, foo: str): and def __init__(self) -> None: are both correctly typed.

@sco1
Copy link
Owner

sco1 commented May 25, 2020

Suppressing ANN204 will ignore these warnings.

@Dreamsorcerer
Copy link
Author

Dreamsorcerer commented May 25, 2020

Yes, but it doesn't give any violation for def __init__(self):, which Mypy does. Allowing or suppressing will result in different behaviour to Mypy (more lenient or more strict respectively).

So, to be consistent with Mypy, I'm expecting violations for:
def __init__(self):
but, no violations for:
def __init__(self, foo: str):

@Dreamsorcerer
Copy link
Author

Dreamsorcerer commented May 25, 2020

i.e. Mypy assumes an implicit return type of None for __init__(). But, there has to be atleast 1 annotation somewhere in order for the function to be marked as statically typed. No annotations indicates a dynamically typed function.
So, standard practice for def __init__(self): is to add a return type annotation to mark it as statically typed.

@sco1
Copy link
Owner

sco1 commented May 25, 2020

Ok, I'm following now, sorry.

Right now we don't have a mechanism for discriminating between statically and dynamically typed functions like Mypy does (not just for __init__). Adding something like --allow-untyped-defs a la Mypy's --disallow-untyped-defs shouldn't be too complicated to add and would be worthwhile to provide as a flag.

In the interim you could probably fake it with the --suppress-non-returning flag, though it's not really semantically what you're looking for.

@sco1 sco1 added status: planning enhancement New feature or request labels May 25, 2020
@sco1 sco1 changed the title Optional return type for __init__() Add Flag to Suppress Warnings for Dynamically Typed Functions May 25, 2020
@sco1 sco1 added this to the 2.2.x milestone May 25, 2020
@Dreamsorcerer
Copy link
Author

Indeed, I actually just disabled that flag, as Mypy will complain about no return types on regular functions. It's only __init__() that gets an implicit return type.

@sco1 sco1 self-assigned this May 25, 2020
@sco1 sco1 mentioned this issue May 25, 2020
@sco1 sco1 closed this as completed in #83 Jul 6, 2020
@Dreamsorcerer
Copy link
Author

Dreamsorcerer commented Jul 6, 2020

Unfortunately, that doesn't really resolve the problem, although still a nice addition to have.

For me, I want to:

  • ensure all functions are statically typed.
  • not add a return type to __init__(), unless it is required to make it statically typed (i.e. there are no typed parameters).

If there is a typed parameter, then it is considered statically typed. Mypy will infer the return type for __init__(), so there is no need to add an annotation for it.

@Dreamsorcerer
Copy link
Author

Dreamsorcerer commented Jul 6, 2020

Expected results:

def __init__(self, foo: int): pass
def __init__(self) -> None: pass
def __init__(self, foo): fail
def __init__(self): fail
def __init__(self, foo) -> None: fail
def __init__(self, foo: int) -> None: Maybe fail (or just allow the redundant return type).

@sco1
Copy link
Owner

sco1 commented Jul 6, 2020

Ok. I guess we'll have to take another look at your specific use case. Sorry about that.

@sco1 sco1 reopened this Jul 6, 2020
@sco1 sco1 removed their assignment Jul 6, 2020
@sco1 sco1 modified the milestones: 2.2.0, 2.3.0 Jul 6, 2020
@sco1 sco1 self-assigned this Jul 10, 2020
@sco1 sco1 mentioned this issue Jul 10, 2020
@sco1
Copy link
Owner

sco1 commented Jul 10, 2020

Hopefully I got it right this time, would you be interested in checking out the dev-next branch (#91) to verify that we are able to provide a behavior that Mypy users would expect?

@Dreamsorcerer
Copy link
Author

I cloned the branch, however I'm unsure how to make flake8 load it as a plugin..

@MarkKoz
Copy link
Contributor

MarkKoz commented Jul 11, 2020

@Dreamsorcerer Activate your virtual environment if you're using one and then run pip install -U /path/to/clone/directory

@Dreamsorcerer
Copy link
Author

Perfect, seems to be working correctly with the extra argument enabled.

@sco1 sco1 closed this as completed in #91 Jul 12, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants