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

False positive undefined name after del in branch #175

Closed
pyflakes-bot opened this issue Apr 16, 2014 · 8 comments
Closed

False positive undefined name after del in branch #175

pyflakes-bot opened this issue Apr 16, 2014 · 8 comments

Comments

@pyflakes-bot
Copy link

Original report by dimaqq (@dimaqq?) on Launchpad:


Consider this test code:

def foo():
    bar = 1
    if 0:
        del bar
    else:
        del bar

pyflakes reports test.py:6: undefined name 'bar', that is 2nd del bar is considered in error.

understandably it is impossible to analyse all code paths in general case, so how about tagging bar as uncertain if label is present and allowing to del it?

@pyflakes-bot
Copy link
Author

Original comment by ramalho (@ramalho?) on Launchpad:


Here is another false positive, for a not-so-subtle case:

Using flake8, which uses PyFlakes, I get the report:

board.py:14:19: F821 undefined name 'StandardError'

However, StandardError is a built-in exception in Python 2 (but not in Python 3).

@pyflakes-bot
Copy link
Author

Original comment by florent.x (@florentx?) on Launchpad:


I agree with the initial bug reported : probably we could do better in this case.

The issue reported by @ramalho is not related to the initial report, and it's not an issue at all:

$ python3 -m pyflakes <<< StandardError
<stdin>:1: undefined name 'StandardError'
$ python2 -m pyflakes <<< StandardError
$ 

@pyflakes-bot
Copy link
Author

pyflakes-bot commented Jul 31, 2014

Original comment by blueyed (@blueyed?) on Launchpad:


I came across a similar issue like in #175 (comment), where flake8/pyflakes on python3 reports "F821: undefined name 'unicode'" , but the code path is not triggered for Python3:

if sys.version_info < (3, 0):
    def __unicode__(self):
        return self.url

    def __add__(self, other):
        return unicode(self) + other
else:
    def __str__(self):
        return self.url

    def __add__(self, other):
        return str(self) + other

@pyflakes-bot
Copy link
Author

pyflakes-bot commented Nov 20, 2015

Original comment by jayvdb (@jayvdb?) on Launchpad:


This bug is about del (and the cases in https://bugs.launchpad.net/pyflakes/+bug/1431099 (#108) appear to be the same problem)

@myint
Copy link
Member

myint commented Jun 13, 2017

@adhikasp found a good example of this in datetime.

adhikasp added a commit to adhikasp/autoflake that referenced this issue Jun 15, 2017
This patch add new feature to automatically expand a star 
(wildcard) import to specify all names that used inside the code.

A sample code like this

```python
from math import *
sin(1)
cos(0)
```

will be changed into 

```python
from math import cos, sin
sin(1)
cos(0)
```

Note that there are still 2 bugs regarding this feature, 
which mainly caused by related upstream bug from pyflakes:

1. A function/names that declared but later deleted by `del` 
   command will raise a false positive that the names is
   undeclared and could possibly come from a star import 
   (if present).
   PyCQA/pyflakes#175
2. pyflakes is "inconsistent" on defining an undefined var 
   in case of __all__ is used (like in module API files).
   
```python
from foo import * # contain function_1 and function_2

__all__ = ['function_1', 'function_2', 'function_3']

function_2() # just use it somewhere to trigger pyflake

def function_3:
    return 'something'
```

pyflakes will complain that function_2 is undefined and 
possibly come from module foo. The import then will be 
expanded into...

```python
from foo import function_2
```

But then pyflakes will complain function_1 is undefined 
because its used in `__all__`

Closes PyCQA#14
adhikasp added a commit to adhikasp/autoflake that referenced this issue Jun 15, 2017
This patch add new feature to automatically expand a star 
(wildcard) import to specify all names that used inside the code.

A sample code like this

```python
from math import *
sin(1)
cos(0)
```

will be changed into 

```python
from math import cos, sin
sin(1)
cos(0)
```

Note that there are still 2 bugs regarding this feature, 
which mainly caused by related upstream bug from pyflakes:

1. A function/names that declared but later deleted by `del` 
   command will raise a false positive that the names is
   undeclared and could possibly come from a star import 
   (if present).
   PyCQA/pyflakes#175
2. pyflakes is "inconsistent" on defining an undefined var 
   in case of __all__ is used (like in module API files).
   
```python
from foo import * # contain function_1 and function_2

__all__ = ['function_1', 'function_2', 'function_3']

function_2() # just use it somewhere to trigger pyflake

def function_3:
    return 'something'
```

pyflakes will complain that function_2 is undefined and 
possibly come from module foo. The import then will be 
expanded into...

```python
from foo import function_2
```

But then pyflakes will complain function_1 is undefined 
because its used in `__all__`

Closes PyCQA#14
adhikasp added a commit to adhikasp/autoflake that referenced this issue Jun 16, 2017
This patch add new feature to automatically expand a star 
(wildcard) import to specify all names that used inside the code.

A sample code like this

```python
from math import *
sin(1)
cos(0)
```

will be changed into 

```python
from math import cos, sin
sin(1)
cos(0)
```

Note that there are still 2 bugs regarding this feature, 
which mainly caused by related upstream bug from pyflakes:

1. A function/names that declared but later deleted by `del` 
   command will raise a false positive that the names is
   undeclared and could possibly come from a star import 
   (if present).
   PyCQA/pyflakes#175
2. pyflakes is "inconsistent" on defining an undefined var 
   in case of __all__ is used (like in module API files).
   
```python
from foo import * # contain function_1 and function_2

__all__ = ['function_1', 'function_2', 'function_3']

function_2() # just use it somewhere to trigger pyflake

def function_3:
    return 'something'
```

pyflakes will complain that function_2 is undefined and 
possibly come from module foo. The import then will be 
expanded into...

```python
from foo import function_2
```

But then pyflakes will complain function_1 is undefined 
because its used in `__all__`

Closes PyCQA#14
adhikasp added a commit to adhikasp/autoflake that referenced this issue Jun 16, 2017
This patch add new feature to automatically expand a star 
(wildcard) import to specify all names that used inside the code.

A sample code like this

```python
from math import *
sin(1)
cos(0)
```

will be changed into 

```python
from math import cos, sin
sin(1)
cos(0)
```

Note that there are still 2 bugs regarding this feature, 
which mainly caused by related upstream bug from pyflakes:

1. A function/names that declared but later deleted by `del` 
   command will raise a false positive that the names is
   undeclared and could possibly come from a star import 
   (if present).
   PyCQA/pyflakes#175
2. pyflakes is "inconsistent" on defining an undefined var 
   in case of __all__ is used (like in module API files).
   
```python
from foo import * # contain function_1 and function_2

__all__ = ['function_1', 'function_2', 'function_3']

function_2() # just use it somewhere to trigger pyflake

def function_3:
    return 'something'
```

pyflakes will complain that function_2 is undefined and 
possibly come from module foo. The import then will be 
expanded into...

```python
from foo import function_2
```

But then pyflakes will complain function_1 is undefined 
because its used in `__all__`

Closes PyCQA#14
@pzahemszky
Copy link

Is there a recommended way of dealing with this issue? Or is adding a noqa: F821 comment to the lines in question the only workaround?

@bitglue
Copy link
Member

bitglue commented Mar 4, 2019

The underlying issue is conditional branches are "invisible" to pyflakes. So

def foo():
    bar = 1
    if 0:
        del bar
    else:
        del bar

looks like:

def foo():
    bar = 1
    del bar
    del bar

Once you understand what's going on under the hood, it's often possible to rewrite the code in a way to avoid the issue, though the specific solution depends on the specific situation.

This has been a long-standing bug since it's a complex problem to track all the possible paths though the code and calculate all the possible states of the variable assignments.

@asottile
Copy link
Member

collecting duplicates for "pyflakes doesn't do branch analysis" here: #715

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants