From 58d08219e83bbaf36aa514e2bdd53202856871b3 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Thu, 8 Jun 2023 13:19:56 -0400 Subject: [PATCH] Allow re-assignments to `__all__` (#4967) --- .../fixtures/pylint/invalid_all_format.py | 11 +++++++ ..._tests__PLE0605_invalid_all_format.py.snap | 32 ++++++++++++++++++- crates/ruff_python_ast/src/all.rs | 14 +++++++- 3 files changed, 55 insertions(+), 2 deletions(-) diff --git a/crates/ruff/resources/test/fixtures/pylint/invalid_all_format.py b/crates/ruff/resources/test/fixtures/pylint/invalid_all_format.py index 60e508f381..9054087de4 100644 --- a/crates/ruff/resources/test/fixtures/pylint/invalid_all_format.py +++ b/crates/ruff/resources/test/fixtures/pylint/invalid_all_format.py @@ -14,6 +14,12 @@ __all__ = (x for x in ["Hello", "world"]) # [invalid-all-format] __all__ = {x for x in ["Hello", "world"]} # [invalid-all-format] +__all__ = foo # [invalid-all-format] + +__all__ = foo.bar # [invalid-all-format] + +__all__ = foo["bar"] # [invalid-all-format] + __all__ = ["Hello"] __all__ = ("Hello",) @@ -29,3 +35,8 @@ __all__ = list({"Hello", "world"}) __all__ = list(["Hello"]) + list(["world"]) __all__ = tuple(["Hello"]) + ("world",) + +__all__ = __all__ + ["Hello"] + +__all__ = __all__ + multiprocessing.__all__ + diff --git a/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLE0605_invalid_all_format.py.snap b/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLE0605_invalid_all_format.py.snap index 6810d72ac1..aad4b6185e 100644 --- a/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLE0605_invalid_all_format.py.snap +++ b/crates/ruff/src/rules/pylint/snapshots/ruff__rules__pylint__tests__PLE0605_invalid_all_format.py.snap @@ -76,7 +76,37 @@ invalid_all_format.py:15:1: PLE0605 Invalid format for `__all__`, must be `tuple 17 | __all__ = {x for x in ["Hello", "world"]} # [invalid-all-format] | ^^^^^^^ PLE0605 18 | -19 | __all__ = ["Hello"] +19 | __all__ = foo # [invalid-all-format] + | + +invalid_all_format.py:17:1: PLE0605 Invalid format for `__all__`, must be `tuple` or `list` + | +17 | __all__ = {x for x in ["Hello", "world"]} # [invalid-all-format] +18 | +19 | __all__ = foo # [invalid-all-format] + | ^^^^^^^ PLE0605 +20 | +21 | __all__ = foo.bar # [invalid-all-format] + | + +invalid_all_format.py:19:1: PLE0605 Invalid format for `__all__`, must be `tuple` or `list` + | +19 | __all__ = foo # [invalid-all-format] +20 | +21 | __all__ = foo.bar # [invalid-all-format] + | ^^^^^^^ PLE0605 +22 | +23 | __all__ = foo["bar"] # [invalid-all-format] + | + +invalid_all_format.py:21:1: PLE0605 Invalid format for `__all__`, must be `tuple` or `list` + | +21 | __all__ = foo.bar # [invalid-all-format] +22 | +23 | __all__ = foo["bar"] # [invalid-all-format] + | ^^^^^^^ PLE0605 +24 | +25 | __all__ = ["Hello"] | diff --git a/crates/ruff_python_ast/src/all.rs b/crates/ruff_python_ast/src/all.rs index 29a17869f1..09244135be 100644 --- a/crates/ruff_python_ast/src/all.rs +++ b/crates/ruff_python_ast/src/all.rs @@ -45,11 +45,23 @@ where // Allow comprehensions, even though we can't statically analyze them. return (None, AllNamesFlags::empty()); } + Expr::Name(ast::ExprName { id, .. }) => { + // Ex) `__all__ = __all__ + multiprocessing.__all__` + if id == "__all__" { + return (None, AllNamesFlags::empty()); + } + } + Expr::Attribute(ast::ExprAttribute { attr, .. }) => { + // Ex) `__all__ = __all__ + multiprocessing.__all__` + if attr == "__all__" { + return (None, AllNamesFlags::empty()); + } + } Expr::Call(ast::ExprCall { func, args, keywords, - range: _range, + .. }) => { // Allow `tuple()` and `list()` calls. if keywords.is_empty() && args.len() <= 1 {