@@ -626,6 +626,30 @@ reveal_type(X) # revealed: Unknown
626
626
reveal_type(Y) # revealed: bool
627
627
```
628
628
629
+ ### An implicit import in a ` .pyi ` file later overridden by another assignment
630
+
631
+ ` a.pyi ` :
632
+
633
+ ``` pyi
634
+ X: bool = True
635
+ ```
636
+
637
+ ` b.pyi ` :
638
+
639
+ ``` pyi
640
+ from a import X
641
+
642
+ X: bool = False
643
+ ```
644
+
645
+ ` c.py ` :
646
+
647
+ ``` py
648
+ from b import *
649
+
650
+ reveal_type(X) # revealed: bool
651
+ ```
652
+
629
653
## Visibility constraints
630
654
631
655
If an ` importer ` module contains a ` from exporter import * ` statement in its global namespace, the
@@ -865,15 +889,10 @@ from exporter import *
865
889
866
890
reveal_type(X) # revealed: bool
867
891
868
- # TODO none of these should error, should all reveal `bool`
869
- # error: [unresolved-reference]
870
- reveal_type(_private) # revealed: Unknown
871
- # error: [unresolved-reference]
872
- reveal_type(__protected) # revealed: Unknown
873
- # error: [unresolved-reference]
874
- reveal_type(__dunder__) # revealed: Unknown
875
- # error: [unresolved-reference]
876
- reveal_type(___thunder___) # revealed: Unknown
892
+ reveal_type(_private) # revealed: bool
893
+ reveal_type(__protected) # revealed: bool
894
+ reveal_type(__dunder__) # revealed: bool
895
+ reveal_type(___thunder___) # revealed: bool
877
896
878
897
# TODO : should emit [unresolved-reference] diagnostic & reveal `Unknown`
879
898
reveal_type(Y) # revealed: bool
@@ -1072,6 +1091,44 @@ reveal_type(Y) # revealed: bool
1072
1091
reveal_type(Z) # revealed: Unknown
1073
1092
```
1074
1093
1094
+ ### ` __all__ ` conditionally defined in a statically known branch (2)
1095
+
1096
+ The same example again, but with a different ` python-version ` set:
1097
+
1098
+ ``` toml
1099
+ [environment ]
1100
+ python-version = " 3.10"
1101
+ ```
1102
+
1103
+ ` exporter.py ` :
1104
+
1105
+ ``` py
1106
+ import sys
1107
+
1108
+ X: bool = True
1109
+
1110
+ if sys.version_info >= (3 , 11 ):
1111
+ __all__ = [" X" , " Y" ]
1112
+ Y: bool = True
1113
+ else :
1114
+ __all__ = (" Z" ,)
1115
+ Z: bool = True
1116
+ ```
1117
+
1118
+ ` importer.py ` :
1119
+
1120
+ ``` py
1121
+ from exporter import *
1122
+
1123
+ # TODO : should reveal `Unknown` and emit `[unresolved-reference]`
1124
+ reveal_type(X) # revealed: bool
1125
+
1126
+ # error: [unresolved-reference]
1127
+ reveal_type(Y) # revealed: Unknown
1128
+
1129
+ reveal_type(Z) # revealed: bool
1130
+ ```
1131
+
1075
1132
### ` __all__ ` conditionally mutated in a statically known branch
1076
1133
1077
1134
``` toml
@@ -1084,11 +1141,11 @@ python-version = "3.11"
1084
1141
``` py
1085
1142
import sys
1086
1143
1087
- __all__ = [" X " ]
1144
+ __all__ = []
1088
1145
X: bool = True
1089
1146
1090
1147
if sys.version_info >= (3 , 11 ):
1091
- __all__ .append( " Y " )
1148
+ __all__ .extend([ " X " , " Y " ] )
1092
1149
Y: bool = True
1093
1150
else :
1094
1151
__all__ .append(" Z" )
@@ -1107,6 +1164,45 @@ reveal_type(Y) # revealed: bool
1107
1164
reveal_type(Z) # revealed: Unknown
1108
1165
```
1109
1166
1167
+ ### ` __all__ ` conditionally mutated in a statically known branch (2)
1168
+
1169
+ The same example again, but with a different ` python-version ` set:
1170
+
1171
+ ``` toml
1172
+ [environment ]
1173
+ python-version = " 3.10"
1174
+ ```
1175
+
1176
+ ` exporter.py ` :
1177
+
1178
+ ``` py
1179
+ import sys
1180
+
1181
+ __all__ = []
1182
+ X: bool = True
1183
+
1184
+ if sys.version_info >= (3 , 11 ):
1185
+ __all__ .extend([" X" , " Y" ])
1186
+ Y: bool = True
1187
+ else :
1188
+ __all__ .append(" Z" )
1189
+ Z: bool = True
1190
+ ```
1191
+
1192
+ ` importer.py ` :
1193
+
1194
+ ``` py
1195
+ from exporter import *
1196
+
1197
+ # TODO : should reveal `Unknown` & emit `[unresolved-reference]
1198
+ reveal_type(X) # revealed: bool
1199
+
1200
+ # error: [unresolved-reference]
1201
+ reveal_type(Y) # revealed: Unknown
1202
+
1203
+ reveal_type(Z) # revealed: bool
1204
+ ```
1205
+
1110
1206
### Empty ` __all__ `
1111
1207
1112
1208
An empty ` __all__ ` is valid, but a ` * ` import from a module with an empty ` __all__ ` results in 0
@@ -1166,6 +1262,7 @@ from b import *
1166
1262
1167
1263
# TODO : should not error, should reveal `bool`
1168
1264
# (`X` is re-exported from `b.pyi` due to presence in `__all__`)
1265
+ # See https://github.com/astral-sh/ruff/issues/16159
1169
1266
#
1170
1267
# error: [unresolved-reference]
1171
1268
reveal_type(X) # revealed: Unknown
0 commit comments