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

Relax Y011, Y014 and Y015 to allow default values in many contexts #326

Merged
merged 12 commits into from
Jan 16, 2023

Conversation

AlexWaygood
Copy link
Collaborator

@AlexWaygood AlexWaygood commented Jan 16, 2023

Fixes #316, among other things.

@AlexWaygood
Copy link
Collaborator Author

AlexWaygood commented Jan 16, 2023

The typeshed_primer diff won't be very helpful here, since we've already switched off Y011 and Y015 in typeshed's .flake8 file. (The aim of this PR is to get to a point where we can switch them back on over at typeshed.) Here's a diff I created manually instead, by switching them back on and then running flake8 with this patch applied:

stubs\pywin32\win32\lib\ntsecuritycon.pyi:35:1: Y015 Only simple default values are allowed for assignments
stubs\pywin32\win32\lib\ntsecuritycon.pyi:36:1: Y015 Only simple default values are allowed for assignments
stubs\pywin32\win32\lib\ntsecuritycon.pyi:37:1: Y015 Only simple default values are allowed for assignments
stubs\pywin32\win32\lib\ntsecuritycon.pyi:38:1: Y015 Only simple default values are allowed for assignments
stubs\pywin32\win32\lib\ntsecuritycon.pyi:39:1: Y015 Only simple default values are allowed for assignments
stubs\pywin32\win32\lib\ntsecuritycon.pyi:40:1: Y015 Only simple default values are allowed for assignments
stubs\pywin32\win32\lib\ntsecuritycon.pyi:49:1: Y015 Only simple default values are allowed for assignments
stubs\pywin32\win32\lib\ntsecuritycon.pyi:101:1: Y015 Only simple default values are allowed for assignments
stubs\pywin32\win32\lib\ntsecuritycon.pyi:109:1: Y015 Only simple default values are allowed for assignments
stubs\pywin32\win32\lib\ntsecuritycon.pyi:110:1: Y015 Only simple default values are allowed for assignments
stubs\pywin32\win32\lib\ntsecuritycon.pyi:111:1: Y015 Only simple default values are allowed for assignments
stubs\pywin32\win32\lib\ntsecuritycon.pyi:112:1: Y015 Only simple default values are allowed for assignments
stubs\pywin32\win32\lib\ntsecuritycon.pyi:113:1: Y015 Only simple default values are allowed for assignments
stubs\tensorflow\tensorflow\__init__.pyi:112:52: Y011 Only simple default values allowed for typed arguments
stubs\tensorflow\tensorflow\__init__.pyi:113:44: Y011 Only simple default values allowed for typed arguments
stubs\tensorflow\tensorflow\__init__.pyi:125:94: Y011 Only simple default values allowed for typed arguments

I think these are all "true positives". I'll file a PR to fix them over at typeshed, if others agree.

@github-actions

This comment has been minimized.

pyi.py Outdated
if not is_special_assignment:
self._check_for_type_aliases(node, target, assignment)
if isinstance(
assignment, (ast.Dict, ast.List, ast.Tuple, ast.Set, ast.JoinedStr)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why doesn't this use _is_valid_stub_default? There are a lot of other expression nodes.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yup. But for assignments, we want to allow much more than just the things we allow in default values for parameters. All of the following are valid in a stub:

T = TypeVar("T") # ast.Call

def foo(): ...
bar = foo # ast.Name

class Spam:
    def eggs(self): ...
ham = Spam.eggs  # ast.Attribute

baz = Literal["foo"]  # ast.Subscript — this should trigger Y026 but not Y015

Copy link
Collaborator

Choose a reason for hiding this comment

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

I see, but this still allows a bunch of nodes that have little conceivable use, like Lambda and SetComp. Might be better to go with an allowlist instead of a blocklist.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Hmm, fair enough, I'll rework.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

README.md Outdated Show resolved Hide resolved
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

pyi.py Outdated
def _is_valid_assignment_value(self, node: ast.expr) -> bool:
return (
isinstance(node, (ast.Call, ast.Name, ast.Attribute, ast.Subscript))
or (isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr))
Copy link
Collaborator

Choose a reason for hiding this comment

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

For extra paranoia could check that the operands to | are themselves valid, but fine to omit that.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Oh good idea, I'll do that


is_special_assignment = isinstance(
node_target, ast.Name
) and _is_assignment_which_must_have_a_value(
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 not Black's finest hour

@github-actions

This comment has been minimized.

@github-actions
Copy link

This change has no effect on typeshed. 🤖🎉

JelleZijlstra pushed a commit that referenced this pull request Jan 28, 2023
…class namespaces where the assignments don't have type annotations (#339)

Following #326, we now allow constructs such as these in a stub file:

```python
x = 1
y = "foo"
z = b"bar"
```

It's good that we now allow variables to have default values. However,
the above constructs are problematic in a stub, as we're leaving it up
to the type checker to make inferences about the types of these
variables, which can have unpredictable consequences. For example, the
`x` variable could be inferred to be of type `int`, `Final[int]`,
`Literal[1]`, or `Final[Literal[1]]`. In a class namespace, the problem
is even worse -- the `eggs` variable in the following snippet could
reasonably be inferred as being of type `str`, `ClassVar[str]`,
`Final[str]`, `Literal["EGGS"]`, `ClassVar[Literal["EGGS"]]`, or
`Final[Literal["EGGS"]]`:

```python
class Whatever:
    eggs = "EGGS"
```

This PR introduces Y052, enforcing type annotations for assignments to
simple constants.
@sbdchd sbdchd mentioned this pull request Feb 26, 2023
56 tasks
sbdchd added a commit to sbdchd/ruff that referenced this pull request Feb 26, 2023
charliermarsh pushed a commit to astral-sh/ruff that referenced this pull request Feb 26, 2023
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.

False-positive error for Final if it's aliased
2 participants