Skip to content

Commit 61d4c6c

Browse files
committed
Added future flag check
1 parent 3be2743 commit 61d4c6c

File tree

4 files changed

+36
-10
lines changed

4 files changed

+36
-10
lines changed

mypy/fastparse.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1430,7 +1430,8 @@ def visit_BinOp(self, n: ast3.BinOp) -> Type:
14301430
right = self.visit(n.right)
14311431
return UnionType([left, right],
14321432
line=self.line,
1433-
column=self.convert_column(n.col_offset))
1433+
column=self.convert_column(n.col_offset),
1434+
is_binary_op=True)
14341435

14351436
def visit_NameConstant(self, n: NameConstant) -> Type:
14361437
if isinstance(n.value, bool):

mypy/typeanal.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,11 @@ def visit_star_type(self, t: StarType) -> Type:
605605
return StarType(self.anal_type(t.type), t.line)
606606

607607
def visit_union_type(self, t: UnionType) -> Type:
608+
if (t.is_binary_op is True
609+
and self.api.is_stub_file is False
610+
and self.options.python_version < (3, 10)
611+
and self.api.is_future_flag_set('annotations') is False):
612+
self.fail("Alternative syntax for unions requires Python 3.10 or newer", t)
608613
return UnionType(self.anal_array(t.items), t.line)
609614

610615
def visit_partial_type(self, t: PartialType) -> Type:

mypy/types.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1724,11 +1724,13 @@ class UnionType(ProperType):
17241724

17251725
__slots__ = ('items',)
17261726

1727-
def __init__(self, items: Sequence[Type], line: int = -1, column: int = -1) -> None:
1727+
def __init__(self, items: Sequence[Type], line: int = -1, column: int = -1,
1728+
is_binary_op: bool = False) -> None:
17281729
super().__init__(line, column)
17291730
self.items = flatten_nested_unions(items)
17301731
self.can_be_true = any(item.can_be_true for item in items)
17311732
self.can_be_false = any(item.can_be_false for item in items)
1733+
self.is_binary_op = is_binary_op
17321734

17331735
def __hash__(self) -> int:
17341736
return hash(frozenset(self.items))

test-data/unit/check-union-or-syntax.test

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
-- Type checking of union types with '|' syntax
22

33
[case testUnionOrSyntaxWithTwoBuiltinsTypes]
4-
# flags: --python-version 3.9
4+
# flags: --python-version 3.10
5+
from __future__ import annotations
56
def f(x: int | str) -> int | str:
67
reveal_type(x) # N: Revealed type is 'Union[builtins.int, builtins.str]'
78
z: int | str = 0
89
reveal_type(z) # N: Revealed type is 'Union[builtins.int, builtins.str]'
910
return x
1011
reveal_type(f) # N: Revealed type is 'def (x: Union[builtins.int, builtins.str]) -> Union[builtins.int, builtins.str]'
12+
[builtins fixtures/tuple.pyi]
1113

1214
[case testUnionOrSyntaxWithThreeBuiltinsTypes]
13-
# flags: --python-version 3.9
15+
# flags: --python-version 3.10
1416
def f(x: int | str | float) -> int | str | float:
1517
reveal_type(x) # N: Revealed type is 'Union[builtins.int, builtins.str, builtins.float]'
1618
z: int | str | float = 0
@@ -20,7 +22,7 @@ def f(x: int | str | float) -> int | str | float:
2022
reveal_type(f) # N: Revealed type is 'def (x: Union[builtins.int, builtins.str, builtins.float]) -> Union[builtins.int, builtins.str, builtins.float]'
2123

2224
[case testUnionOrSyntaxWithTwoTypes]
23-
# flags: --python-version 3.9
25+
# flags: --python-version 3.10
2426
class A: pass
2527
class B: pass
2628
def f(x: A | B) -> A | B:
@@ -31,7 +33,7 @@ def f(x: A | B) -> A | B:
3133
reveal_type(f) # N: Revealed type is 'def (x: Union[__main__.A, __main__.B]) -> Union[__main__.A, __main__.B]'
3234

3335
[case testUnionOrSyntaxWithThreeTypes]
34-
# flags: --python-version 3.9
36+
# flags: --python-version 3.10
3537
class A: pass
3638
class B: pass
3739
class C: pass
@@ -43,21 +45,37 @@ def f(x: A | B | C) -> A | B | C:
4345
reveal_type(f) # N: Revealed type is 'def (x: Union[__main__.A, __main__.B, __main__.C]) -> Union[__main__.A, __main__.B, __main__.C]'
4446

4547
[case testUnionOrSyntaxWithLiteral]
46-
# flags: --python-version 3.9
48+
# flags: --python-version 3.10
4749
from typing_extensions import Literal
4850
reveal_type(Literal[4] | str) # N: Revealed type is 'Any'
4951
[builtins fixtures/tuple.pyi]
5052

5153
[case testUnionOrSyntaxWithBadOperator]
52-
# flags: --python-version 3.9
54+
# flags: --python-version 3.10
5355
x: 1 + 2 # E: Invalid type comment or annotation
5456

5557
[case testUnionOrSyntaxWithBadOperands]
56-
# flags: --python-version 3.9
58+
# flags: --python-version 3.10
5759
x: int | 42 # E: Invalid type: try using Literal[42] instead?
5860
y: 42 | int # E: Invalid type: try using Literal[42] instead?
5961
z: str | 42 | int # E: Invalid type: try using Literal[42] instead?
6062

6163
[case testUnionOrSyntaxInComment]
62-
# flags: --python-version 3.9
64+
# flags: --python-version 3.10
6365
x = 1 # type: int | str
66+
67+
[case testUnionOrSyntaxFutureImport]
68+
# flags: --python-version 3.7
69+
from __future__ import annotations
70+
x: int | None
71+
[builtins fixtures/tuple.pyi]
72+
73+
[case testUnionOrSyntaxMissingFutureImport]
74+
# flags: --python-version 3.9
75+
x: int | None # E: Alternative syntax for unions requires Python 3.10 or newer
76+
77+
[case testUnionOrSyntaxInStubFile]
78+
# flags: --python-version 3.6
79+
from lib import x
80+
[file lib.pyi]
81+
x: int | None

0 commit comments

Comments
 (0)