Skip to content

Fix #5713: Emit used-before-assignment instead of undefined-variable when accessing unused type annotations #5718

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

Merged
merged 3 commits into from
Jan 26, 2022

Conversation

jacobtylerwalls
Copy link
Member

@jacobtylerwalls jacobtylerwalls commented Jan 25, 2022

Type of Changes

Type
βœ“ πŸ”¨ Refactoring

Description

This one is somewhat pedantic, sorry! I simply noticed that we could attempt to raise more targeted messages so that undefined-variable corresponds generally with NameError and used-before-assignment corresponds generally with UnboundLocalError. The only use of the message affected by this PR is new in 2.12, so hopefully not breaking too many existing disables. But I suppose that should be balanced against people suppressing undefined-variable that would be glad to get used-before-assignment coming through now.

See example shell session drawn from existing unit tests adjusted in this PR:

In [1]: G: int
   ...: 
   ...: 
   ...: def a():
   ...:     global G
   ...:     print(G)
   ...: 
   ...: 
   ...: def bound_value():
   ...:     variable: int
   ...:     print(variable)
   ...: 
   ...: 
   ...: def decorator_returning_incorrect_function():
   ...:     """A decorator that returns a wrapper function with decoupled typing"""
   ...: 
   ...:     def wrapper_with_type_and_no_value():
   ...:         # This emits NameError, so undefined-variable is okay
   ...:         # even though the traceback refers to
   ...:         print(var)  # [undefined-variable]
   ...: 
   ...:     var: int
   ...:     return wrapper_with_type_and_no_value

In [2]: a()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Input In [2], in <module>
----> 1 a()

Input In [1], in a()
      4 def a():
      5     global G
----> 6     print(G)

NameError: name 'G' is not defined

In [3]: bound_value()
---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
Input In [3], in <module>
----> 1 bound_value()

Input In [1], in bound_value()
      9 def bound_value():
     10     variable: int
---> 11     print(variable)

UnboundLocalError: local variable 'variable' referenced before assignment

In [4]: decorator_returning_incorrect_function()()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Input In [4], in <module>
----> 1 decorator_returning_incorrect_function()()

Input In [1], in decorator_returning_incorrect_function.<locals>.wrapper_with_type_and_no_value()
     17 def wrapper_with_type_and_no_value():
     18     # This emits NameError, so undefined-variable is okay
     19     # even though the traceback refers to "used before assignment"
---> 20     print(var)

NameError: free variable 'var' referenced before assignment in enclosing scope

Closes #5713

…ned-variable` when accessing unused type annotations
@coveralls
Copy link

coveralls commented Jan 25, 2022

Pull Request Test Coverage Report for Build 1746877150

  • 3 of 3 (100.0%) changed or added relevant lines in 1 file are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+0.0008%) to 93.844%

Totals Coverage Status
Change from base Build 1741985260: 0.0008%
Covered Lines: 14712
Relevant Lines: 15677

πŸ’› - Coveralls

@Pierre-Sassoulas Pierre-Sassoulas added this to the 2.13.0 milestone Jan 25, 2022
@Pierre-Sassoulas Pierre-Sassoulas added the Enhancement ✨ Improvement to a component label Jan 25, 2022
Copy link
Member

@Pierre-Sassoulas Pierre-Sassoulas left a comment

Choose a reason for hiding this comment

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

It's a nice consistency refactor, thank you πŸ‘ I think we can do it as the number of false positives for those two message is probably low and of disable of those message even lower.

Copy link
Member

@Pierre-Sassoulas Pierre-Sassoulas left a comment

Choose a reason for hiding this comment

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

πŸ‘Œ

Copy link
Collaborator

@DanielNoord DanielNoord left a comment

Choose a reason for hiding this comment

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

Thanks @jacobtylerwalls for looking into this. I think this makes sense (even though somewhat breaking)!

@Pierre-Sassoulas Pierre-Sassoulas merged commit 0fb6a12 into pylint-dev:main Jan 26, 2022
@DanielNoord
Copy link
Collaborator

This fails on main as well. I think it is related to the fail of #5711. Perhaps @jacobtylerwalls can take a look at them together and do a follow-up PR?

@jacobtylerwalls jacobtylerwalls deleted the change-msg-type branch January 26, 2022 13:33
@jacobtylerwalls
Copy link
Member Author

@DanielNoord actually this failure looks "random" -->

>               _winapi.TerminateProcess(int(self._handle), TERMINATE)
E               PermissionError: [WinError 5] Access is denied

Note the test suite passed on all other runners. πŸ€”

@Pierre-Sassoulas
Copy link
Member

this failure looks "random"

I came to the same conclusion when looking at it (I'm notified if what I merge fail on main).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Enhancement ✨ Improvement to a component
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Emit used-before-assignment instead of undefined-variable for unused type annotations
4 participants