Python: from <pkg> import * ignores __all__ regression

Notice that `has_defined_all_indirection` all have both
`all_defined_bar_copy` and `all_defined_foo_copy` marked as exported,
even though only `all_defined_foo_copy` is available.
This commit is contained in:
Rasmus Wriedt Larsen
2023-02-22 15:08:47 +01:00
parent d77ce4f3d7
commit be5812cf91
5 changed files with 134 additions and 5 deletions

View File

@@ -76,6 +76,53 @@
| foo | print | trace.py:7:1:7:27 | ControlFlowNode for FunctionExpr |
| foo | print_function | trace.py:1:24:1:37 | ControlFlowNode for ImportMember |
| foo | status | trace.py:23:1:23:13 | ControlFlowNode for FunctionExpr |
| has_defined_all | __all__ | has_defined_all.py:7:11:7:29 | ControlFlowNode for List |
| has_defined_all | __all__ | trace.py:52:11:52:46 | ControlFlowNode for List |
| has_defined_all | __file__ | has_defined_all.py:2:7:2:14 | ControlFlowNode for __file__ |
| has_defined_all | __file__ | has_defined_all.py:9:6:9:13 | ControlFlowNode for __file__ |
| has_defined_all | _indent_level | trace.py:3:17:3:17 | ControlFlowNode for IntegerLiteral |
| has_defined_all | _print | trace.py:5:10:5:14 | ControlFlowNode for print |
| has_defined_all | _status | trace.py:21:11:21:11 | ControlFlowNode for IntegerLiteral |
| has_defined_all | all_defined_bar | has_defined_all.py:5:19:5:35 | ControlFlowNode for Str |
| has_defined_all | all_defined_foo | has_defined_all.py:4:19:4:35 | ControlFlowNode for Str |
| has_defined_all | check | trace.py:26:1:26:61 | ControlFlowNode for FunctionExpr |
| has_defined_all | enter | trace.py:11:1:11:21 | ControlFlowNode for FunctionExpr |
| has_defined_all | exit | trace.py:16:1:16:20 | ControlFlowNode for FunctionExpr |
| has_defined_all | print | trace.py:7:1:7:27 | ControlFlowNode for FunctionExpr |
| has_defined_all | print_function | trace.py:1:24:1:37 | ControlFlowNode for ImportMember |
| has_defined_all | status | trace.py:23:1:23:13 | ControlFlowNode for FunctionExpr |
| has_defined_all_copy | __all__ | has_defined_all_copy.py:9:11:9:34 | ControlFlowNode for List |
| has_defined_all_copy | __all__ | trace.py:52:11:52:46 | ControlFlowNode for List |
| has_defined_all_copy | __file__ | has_defined_all_copy.py:4:7:4:14 | ControlFlowNode for __file__ |
| has_defined_all_copy | __file__ | has_defined_all_copy.py:11:6:11:13 | ControlFlowNode for __file__ |
| has_defined_all_copy | _indent_level | trace.py:3:17:3:17 | ControlFlowNode for IntegerLiteral |
| has_defined_all_copy | _print | trace.py:5:10:5:14 | ControlFlowNode for print |
| has_defined_all_copy | _status | trace.py:21:11:21:11 | ControlFlowNode for IntegerLiteral |
| has_defined_all_copy | all_defined_bar_copy | has_defined_all_copy.py:7:24:7:45 | ControlFlowNode for Str |
| has_defined_all_copy | all_defined_foo_copy | has_defined_all_copy.py:6:24:6:45 | ControlFlowNode for Str |
| has_defined_all_copy | check | trace.py:26:1:26:61 | ControlFlowNode for FunctionExpr |
| has_defined_all_copy | enter | trace.py:11:1:11:21 | ControlFlowNode for FunctionExpr |
| has_defined_all_copy | exit | trace.py:16:1:16:20 | ControlFlowNode for FunctionExpr |
| has_defined_all_copy | print | trace.py:7:1:7:27 | ControlFlowNode for FunctionExpr |
| has_defined_all_copy | print_function | trace.py:1:24:1:37 | ControlFlowNode for ImportMember |
| has_defined_all_copy | status | trace.py:23:1:23:13 | ControlFlowNode for FunctionExpr |
| has_defined_all_indirection | __all__ | has_defined_all_copy.py:9:11:9:34 | ControlFlowNode for List |
| has_defined_all_indirection | __all__ | trace.py:52:11:52:46 | ControlFlowNode for List |
| has_defined_all_indirection | __file__ | has_defined_all_copy.py:4:7:4:14 | ControlFlowNode for __file__ |
| has_defined_all_indirection | __file__ | has_defined_all_copy.py:11:6:11:13 | ControlFlowNode for __file__ |
| has_defined_all_indirection | __file__ | has_defined_all_indirection.py:2:7:2:14 | ControlFlowNode for __file__ |
| has_defined_all_indirection | __file__ | has_defined_all_indirection.py:6:6:6:13 | ControlFlowNode for __file__ |
| has_defined_all_indirection | _indent_level | trace.py:3:17:3:17 | ControlFlowNode for IntegerLiteral |
| has_defined_all_indirection | _print | trace.py:5:10:5:14 | ControlFlowNode for print |
| has_defined_all_indirection | _status | trace.py:21:11:21:11 | ControlFlowNode for IntegerLiteral |
| has_defined_all_indirection | all_defined_bar_copy | has_defined_all_copy.py:7:24:7:45 | ControlFlowNode for Str |
| has_defined_all_indirection | all_defined_foo_copy | has_defined_all_copy.py:6:24:6:45 | ControlFlowNode for Str |
| has_defined_all_indirection | check | trace.py:26:1:26:61 | ControlFlowNode for FunctionExpr |
| has_defined_all_indirection | enter | trace.py:11:1:11:21 | ControlFlowNode for FunctionExpr |
| has_defined_all_indirection | exit | trace.py:16:1:16:20 | ControlFlowNode for FunctionExpr |
| has_defined_all_indirection | print | trace.py:7:1:7:27 | ControlFlowNode for FunctionExpr |
| has_defined_all_indirection | print_function | trace.py:1:24:1:37 | ControlFlowNode for ImportMember |
| has_defined_all_indirection | status | trace.py:23:1:23:13 | ControlFlowNode for FunctionExpr |
| if_then_else | __all__ | trace.py:52:11:52:46 | ControlFlowNode for List |
| if_then_else | __file__ | if_then_else.py:2:7:2:14 | ControlFlowNode for __file__ |
| if_then_else | __file__ | if_then_else.py:16:6:16:13 | ControlFlowNode for __file__ |
@@ -106,9 +153,17 @@
| if_then_else_refined | src | if_then_else_refined.py:11:11:11:16 | ControlFlowNode for SOURCE |
| if_then_else_refined | src | if_then_else_refined.py:13:11:13:16 | ControlFlowNode for SOURCE |
| if_then_else_refined | status | trace.py:23:1:23:13 | ControlFlowNode for FunctionExpr |
| main | __all__ | has_defined_all.py:7:11:7:29 | ControlFlowNode for List |
| main | __all__ | has_defined_all_copy.py:9:11:9:34 | ControlFlowNode for List |
| main | __all__ | trace.py:52:11:52:46 | ControlFlowNode for List |
| main | __file__ | has_defined_all.py:2:7:2:14 | ControlFlowNode for __file__ |
| main | __file__ | has_defined_all.py:9:6:9:13 | ControlFlowNode for __file__ |
| main | __file__ | has_defined_all_copy.py:4:7:4:14 | ControlFlowNode for __file__ |
| main | __file__ | has_defined_all_copy.py:11:6:11:13 | ControlFlowNode for __file__ |
| main | __file__ | has_defined_all_indirection.py:2:7:2:14 | ControlFlowNode for __file__ |
| main | __file__ | has_defined_all_indirection.py:6:6:6:13 | ControlFlowNode for __file__ |
| main | __file__ | main.py:24:7:24:14 | ControlFlowNode for __file__ |
| main | __file__ | main.py:107:6:107:13 | ControlFlowNode for __file__ |
| main | __file__ | main.py:149:6:149:13 | ControlFlowNode for __file__ |
| main | __file__ | package/subpackage2/__init__.py:2:7:2:14 | ControlFlowNode for __file__ |
| main | __file__ | package/subpackage2/__init__.py:6:6:6:13 | ControlFlowNode for __file__ |
| main | _indent_level | trace.py:3:17:3:17 | ControlFlowNode for IntegerLiteral |
@@ -116,6 +171,10 @@
| main | _status | trace.py:21:11:21:11 | ControlFlowNode for IntegerLiteral |
| main | aliased_subpackage | main.py:54:21:54:52 | ControlFlowNode for ImportMember |
| main | aliased_subpackage | main.py:65:8:65:25 | ControlFlowNode for ImportExpr |
| main | all_defined_bar | has_defined_all.py:5:19:5:35 | ControlFlowNode for Str |
| main | all_defined_bar_copy | has_defined_all_copy.py:7:24:7:45 | ControlFlowNode for Str |
| main | all_defined_foo | has_defined_all.py:4:19:4:35 | ControlFlowNode for Str |
| main | all_defined_foo_copy | has_defined_all_copy.py:6:24:6:45 | ControlFlowNode for Str |
| main | bar_attr | main.py:42:17:42:24 | ControlFlowNode for ImportMember |
| main | check | trace.py:26:1:26:61 | ControlFlowNode for FunctionExpr |
| main | clashing_attr | main.py:83:24:83:36 | ControlFlowNode for ImportMember |
@@ -123,8 +182,10 @@
| main | exit | trace.py:16:1:16:20 | ControlFlowNode for FunctionExpr |
| main | foo | main.py:27:8:27:10 | ControlFlowNode for ImportExpr |
| main | foo_alias | main.py:34:8:34:10 | ControlFlowNode for ImportExpr |
| main | if_then_else_defined | main.py:93:26:93:45 | ControlFlowNode for ImportMember |
| main | if_then_else_refined | main.py:100:8:100:27 | ControlFlowNode for ImportExpr |
| main | has_defined_all | main.py:100:8:100:22 | ControlFlowNode for ImportExpr |
| main | has_defined_all_indirection | main.py:118:8:118:34 | ControlFlowNode for ImportExpr |
| main | if_then_else_defined | main.py:135:26:135:45 | ControlFlowNode for ImportMember |
| main | if_then_else_refined | main.py:142:8:142:27 | ControlFlowNode for ImportExpr |
| main | local_import | main.py:57:1:57:19 | ControlFlowNode for FunctionExpr |
| main | namespace_module_attr | main.py:79:52:79:72 | ControlFlowNode for ImportMember |
| main | non_clashing_submodule | main.py:83:39:83:60 | ControlFlowNode for ImportMember |
@@ -134,8 +195,8 @@
| main | print | trace.py:7:1:7:27 | ControlFlowNode for FunctionExpr |
| main | print_function | main.py:21:24:21:37 | ControlFlowNode for ImportMember |
| main | print_function | trace.py:1:24:1:37 | ControlFlowNode for ImportMember |
| main | refined | main.py:97:8:97:14 | ControlFlowNode for ImportExpr |
| main | simplistic_reexport | main.py:103:8:103:26 | ControlFlowNode for ImportExpr |
| main | refined | main.py:139:8:139:14 | ControlFlowNode for ImportExpr |
| main | simplistic_reexport | main.py:145:8:145:26 | ControlFlowNode for ImportExpr |
| main | status | trace.py:23:1:23:13 | ControlFlowNode for FunctionExpr |
| main | subpackage2_attr | package/subpackage2/__init__.py:4:20:4:37 | ControlFlowNode for Str |
| main | subpackage_attr | main.py:46:32:46:46 | ControlFlowNode for ImportMember |

View File

@@ -0,0 +1,9 @@
from trace import *
enter(__file__)
all_defined_foo = "all_defined_foo"
all_defined_bar = "all_defined_bar"
__all__ = ["all_defined_foo"]
exit(__file__)

View File

@@ -0,0 +1,11 @@
# a copy of `has_defined_all.py` that is imported by `has_defined_all_indirection.py`
# with its' own names such that we can check both `import *` without any cross-talk
from trace import *
enter(__file__)
all_defined_foo_copy = "all_defined_foo_copy"
all_defined_bar_copy = "all_defined_bar_copy"
__all__ = ["all_defined_foo_copy"]
exit(__file__)

View File

@@ -0,0 +1,6 @@
from trace import *
enter(__file__)
from has_defined_all_copy import *
exit(__file__)

View File

@@ -84,6 +84,48 @@ from attr_clash import clashing_attr, non_clashing_submodule #$ imports=attr_cla
check("clashing_attr", clashing_attr, "clashing_attr", globals()) #$ prints=clashing_attr SPURIOUS: prints="<module attr_clash.clashing_attr>"
check("non_clashing_submodule", non_clashing_submodule, "<module attr_clash.non_clashing_submodule>", globals()) #$ prints="<module attr_clash.non_clashing_submodule>"
# check that import * only imports the __all__ attributes
from has_defined_all import *
check("all_defined_foo", all_defined_foo, "all_defined_foo", globals()) #$ prints=all_defined_foo
try:
check("all_defined_bar", all_defined_bar, "all_defined_bar", globals()) #$ SPURIOUS: prints=all_defined_bar
raise Exception("Did not get expected NameError")
except NameError as e:
if "all_defined_bar" in str(e):
print("Got expected NameError:", e)
else:
raise
import has_defined_all # $ imports=has_defined_all as=has_defined_all
check("has_defined_all.all_defined_foo", has_defined_all.all_defined_foo, "all_defined_foo", globals()) #$ prints=all_defined_foo
check("has_defined_all.all_defined_bar", has_defined_all.all_defined_bar, "all_defined_bar", globals()) #$ prints=all_defined_bar
# same check as above, but going through one level of indirection (which can make a difference)
from has_defined_all_indirection import *
check("all_defined_foo_copy", all_defined_foo_copy, "all_defined_foo_copy", globals()) #$ prints=all_defined_foo_copy
try:
check("all_defined_bar_copy", all_defined_bar_copy, "all_defined_bar_copy", globals()) #$ SPURIOUS: prints=all_defined_bar_copy
raise Exception("Did not get expected NameError")
except NameError as e:
if "all_defined_bar_copy" in str(e):
print("Got expected NameError:", e)
else:
raise
# same check as above, but going through one level of indirection (which can make a difference)
import has_defined_all_indirection # $ imports=has_defined_all_indirection as=has_defined_all_indirection
check("has_defined_all_indirection.all_defined_foo_copy", has_defined_all_indirection.all_defined_foo_copy, "all_defined_foo_copy", globals()) #$ prints=all_defined_foo_copy
try:
check("has_defined_all_indirection.all_defined_bar_copy", has_defined_all_indirection.all_defined_bar_copy, "all_defined_bar_copy", globals()) #$ SPURIOUS: prints=all_defined_bar_copy
raise Exception("Did not get expected AttributeError")
except AttributeError as e:
if "all_defined_bar_copy" in str(e):
print("Got expected AttributeError:", e)
else:
raise
# check that import * from an __init__ file works
from package.subpackage2 import *