summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharlie Liu <CLiu13@users.noreply.github.com>2018-10-30 23:15:59 -0400
committerCharlie Liu <CLiu13@users.noreply.github.com>2018-10-31 00:34:36 -0400
commit47a164136982ea6ef80f302200b2a29d3a4b1c3c (patch)
tree3e7aaecfe4b66dde891a1673d35d14f3ff2cf294
parenta3eed737212ef8ac6a6ac740da529791651603b2 (diff)
downloadpyflakes-47a164136982ea6ef80f302200b2a29d3a4b1c3c.tar.gz
checker.py: Add support for list concatenation
This adds support for when '__all__' is defined from concatenated lists. However, because pyflakes is not an interpreter, this only applies to certain reduced test cases. Fixes https://github.com/PyCQA/pyflakes/issues/276
-rw-r--r--pyflakes/checker.py28
-rw-r--r--pyflakes/test/test_imports.py15
2 files changed, 27 insertions, 16 deletions
diff --git a/pyflakes/checker.py b/pyflakes/checker.py
index 2060ce4..3dd968d 100644
--- a/pyflakes/checker.py
+++ b/pyflakes/checker.py
@@ -390,10 +390,10 @@ class ExportBinding(Binding):
can be determined statically, they will be treated as names for export and
additional checking applied to them.
- The only C{__all__} assignment that can be recognized is one which takes
- the value of a literal list containing literal strings. For example::
+ The only recognized C{__all__} assignment via list concatenation is in the
+ following format:
- __all__ = ["foo", "bar"]
+ __all__ = ['a'] + ['b'] + ['c']
Names which are imported and not otherwise used but appear in the value of
C{__all__} will not have an unused import warning reported for them.
@@ -405,9 +405,25 @@ class ExportBinding(Binding):
else:
self.names = []
if isinstance(source.value, (ast.List, ast.Tuple)):
- for node in source.value.elts:
- if isinstance(node, ast.Str):
- self.names.append(node.s)
+ self.names += ast.literal_eval(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)
+ # 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)
+ # All lists accounted for - done
+ break
+ # If not list concatenation
+ else:
+ break
super(ExportBinding, self).__init__(name, source)
diff --git a/pyflakes/test/test_imports.py b/pyflakes/test/test_imports.py
index 86e1d37..f83e77e 100644
--- a/pyflakes/test/test_imports.py
+++ b/pyflakes/test/test_imports.py
@@ -1068,19 +1068,14 @@ class TestSpecialAll(TestCase):
__all__ += ['c', 'd']
''', m.UndefinedExport, m.UndefinedExport)
- def test_unrecognizable(self):
+ def test_concatenationAssignment(self):
"""
- If C{__all__} is defined in a way that can't be recognized statically,
- it is ignored.
+ The C{__all__} variable is defined through list concatenation.
"""
self.flakes('''
- import foo
- __all__ = ["f" + "oo"]
- ''', m.UnusedImport)
- self.flakes('''
- import foo
- __all__ = [] + ["foo"]
- ''', m.UnusedImport)
+ import sys
+ __all__ = ['a'] + ['b'] + ['c']
+ ''', m.UndefinedExport, m.UndefinedExport, m.UndefinedExport, m.UnusedImport)
def test_unboundExported(self):
"""