diff options
author | Charlie Liu <CLiu13@users.noreply.github.com> | 2018-10-30 23:15:59 -0400 |
---|---|---|
committer | Charlie Liu <CLiu13@users.noreply.github.com> | 2018-10-31 00:34:36 -0400 |
commit | 47a164136982ea6ef80f302200b2a29d3a4b1c3c (patch) | |
tree | 3e7aaecfe4b66dde891a1673d35d14f3ff2cf294 | |
parent | a3eed737212ef8ac6a6ac740da529791651603b2 (diff) | |
download | pyflakes-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.py | 28 | ||||
-rw-r--r-- | pyflakes/test/test_imports.py | 15 |
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): """ |