summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnthony Sottile <asottile@umich.edu>2019-01-20 16:20:01 -0800
committerIan Stapleton Cordasco <graffatcolmingov@gmail.com>2019-01-22 18:56:20 -0600
commit65fdfad26e5213a8245797da3e1368daa63e2067 (patch)
treefd1210319983f92257235c905eb3136a7d13bbab
parent14f28ba0279e3547c09b06870f90f01167da08ec (diff)
downloadpyflakes-65fdfad26e5213a8245797da3e1368daa63e2067.tar.gz
Fix regression with `__all__ = [not, strings]`
Regression introduced in 47a164136982ea6ef80f302200b2a29d3a4b1c3c Example trace before fix: ``` ... File "/home/asottile/workspace/pyflakes/pyflakes/checker.py", line 998, in handleNodeStore binding = ExportBinding(name, node.parent, self.scope) File "/home/asottile/workspace/pyflakes/pyflakes/checker.py", line 426, in __init__ self.names += ast.literal_eval(source.value) File "/usr/lib/python3.6/ast.py", line 85, in literal_eval return _convert(node_or_string) File "/usr/lib/python3.6/ast.py", line 61, in _convert return list(map(_convert, node.elts)) File "/usr/lib/python3.6/ast.py", line 84, in _convert raise ValueError('malformed node or string: ' + repr(node)) ValueError: malformed node or string: <_ast.Attribute object at 0x7f6d2bf37b70> ```
-rw-r--r--pyflakes/checker.py12
-rw-r--r--pyflakes/test/test_imports.py27
2 files changed, 36 insertions, 3 deletions
diff --git a/pyflakes/checker.py b/pyflakes/checker.py
index b8d7be7..650d788 100644
--- a/pyflakes/checker.py
+++ b/pyflakes/checker.py
@@ -422,21 +422,27 @@ class ExportBinding(Binding):
self.names = list(scope['__all__'].names)
else:
self.names = []
+
+ def _add_to_names(container):
+ for node in container.elts:
+ if isinstance(node, ast.Str):
+ self.names.append(node.s)
+
if isinstance(source.value, (ast.List, ast.Tuple)):
- self.names += ast.literal_eval(source.value)
+ _add_to_names(source.value)
# If concatenating lists
elif isinstance(source.value, ast.BinOp):
currentValue = source.value
while isinstance(currentValue.right, ast.List):
left = currentValue.left
right = currentValue.right
- self.names += ast.literal_eval(right)
+ _add_to_names(right)
# If more lists are being added
if isinstance(left, ast.BinOp):
currentValue = left
# If just two lists are being added
elif isinstance(left, ast.List):
- self.names += ast.literal_eval(left)
+ _add_to_names(left)
# All lists accounted for - done
break
# If not list concatenation
diff --git a/pyflakes/test/test_imports.py b/pyflakes/test/test_imports.py
index 193f9d3..13e7bef 100644
--- a/pyflakes/test/test_imports.py
+++ b/pyflakes/test/test_imports.py
@@ -1093,6 +1093,33 @@ class TestSpecialAll(TestCase):
__all__ = ['a'] + ['b'] + ['c']
''', m.UndefinedExport, m.UndefinedExport, m.UndefinedExport, m.UnusedImport)
+ def test_all_with_attributes(self):
+ self.flakes('''
+ from foo import bar
+ __all__ = [bar.__name__]
+ ''')
+
+ def test_all_with_names(self):
+ # not actually valid, but shouldn't produce a crash
+ self.flakes('''
+ from foo import bar
+ __all__ = [bar]
+ ''')
+
+ def test_all_with_attributes_added(self):
+ self.flakes('''
+ from foo import bar
+ from bar import baz
+ __all__ = [bar.__name__] + [baz.__name__]
+ ''')
+
+ def test_all_mixed_attributes_and_strings(self):
+ self.flakes('''
+ from foo import bar
+ from foo import baz
+ __all__ = ['bar', baz.__name__]
+ ''')
+
def test_unboundExported(self):
"""
If C{__all__} includes a name which is not bound, a warning is emitted.