Skip to content

No longer support checking Python 2 #13135

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 25 commits into from
Jul 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions mypy/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -951,6 +951,11 @@ def set_strict_flags() -> None:
# The python_version is either the default, which can be overridden via a config file,
# or stored in special_opts and is passed via the command line.
options.python_version = special_opts.python_version or options.python_version
if options.python_version < (3,):
parser.error(
"Mypy no longer supports checking Python 2 code. "
"Consider pinning to mypy<0.980 if you need to check Python 2 code."
)
try:
infer_python_executable(options, special_opts)
except PythonExecutableInferenceError as e:
Expand Down
5 changes: 2 additions & 3 deletions mypy/test/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,16 +286,15 @@ def num_skipped_suffix_lines(a1: List[str], a2: List[str]) -> int:


def testfile_pyversion(path: str) -> Tuple[int, int]:
if path.endswith('python2.test'):
return defaults.PYTHON2_VERSION
elif path.endswith('python310.test'):
if path.endswith('python310.test'):
return 3, 10
else:
return defaults.PYTHON3_VERSION


def testcase_pyversion(path: str, testcase_name: str) -> Tuple[int, int]:
if testcase_name.endswith('python2'):
raise ValueError(testcase_name)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here

return defaults.PYTHON2_VERSION
else:
return testfile_pyversion(path)
Expand Down
4 changes: 1 addition & 3 deletions mypy/test/testdeps.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from typing import List, Tuple, Dict, Optional, Set
from typing_extensions import DefaultDict

from mypy import build, defaults
from mypy import build
from mypy.modulefinder import BuildSource
from mypy.errors import CompileError
from mypy.nodes import MypyFile, Expression
Expand All @@ -29,8 +29,6 @@ def run_case(self, testcase: DataDrivenTestCase) -> None:
src = '\n'.join(testcase.input)
dump_all = '# __dump_all__' in src
options = parse_options(src, testcase, incremental_step=1)
if testcase.name.endswith('python2'):
options.python_version = defaults.PYTHON2_VERSION
options.use_builtins_fixtures = True
options.show_traceback = True
options.cache_dir = os.devnull
Expand Down
4 changes: 1 addition & 3 deletions mypy/test/testparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,7 @@ def test_parser(testcase: DataDrivenTestCase) -> None:
"""
options = Options()

if testcase.file.endswith('python2.test'):
options.python_version = defaults.PYTHON2_VERSION
elif testcase.file.endswith('python310.test'):
if testcase.file.endswith('python310.test'):
options.python_version = (3, 10)
else:
options.python_version = defaults.PYTHON3_VERSION
Expand Down
18 changes: 2 additions & 16 deletions mypy/test/testpythoneval.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,12 @@
import sys
from tempfile import TemporaryDirectory

import pytest

from typing import List

from mypy.defaults import PYTHON3_VERSION
from mypy.test.config import test_temp_dir
from mypy.test.data import DataDrivenTestCase, DataSuite
from mypy.test.helpers import assert_string_arrays_equal, split_lines
from mypy.util import try_find_python2_interpreter
from mypy import api

# Path to Python 3 interpreter
Expand All @@ -36,7 +33,6 @@

class PythonEvaluationSuite(DataSuite):
files = ['pythoneval.test',
'python2eval.test',
'pythoneval-asyncio.test']
cache_dir = TemporaryDirectory()

Expand All @@ -59,18 +55,8 @@ def test_python_evaluation(testcase: DataDrivenTestCase, cache_dir: str) -> None
'--no-silence-site-packages',
'--no-error-summary',
]
py2 = testcase.name.lower().endswith('python2')
if py2:
mypy_cmdline.append('--py2')
interpreter = try_find_python2_interpreter()
if interpreter is None:
# Skip, can't find a Python 2 interpreter.
pytest.skip()
# placate the type checker
return
else:
interpreter = python3_path
mypy_cmdline.append(f"--python-version={'.'.join(map(str, PYTHON3_VERSION))}")
interpreter = python3_path
mypy_cmdline.append(f"--python-version={'.'.join(map(str, PYTHON3_VERSION))}")

m = re.search('# flags: (.*)$', '\n'.join(testcase.input), re.MULTILINE)
if m:
Expand Down
3 changes: 1 addition & 2 deletions mypy/test/testtransform.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ class TransformSuite(DataSuite):
'semanal-types.test',
'semanal-modules.test',
'semanal-statements.test',
'semanal-abstractclasses.test',
'semanal-python2.test']
'semanal-abstractclasses.test']
native_sep = True

def run_case(self, testcase: DataDrivenTestCase) -> None:
Expand Down
5 changes: 0 additions & 5 deletions test-data/unit/check-async-await.test
Original file line number Diff line number Diff line change
Expand Up @@ -362,11 +362,6 @@ async def g():
main:3: error: "yield from" in async function
main:5: error: "yield from" in async function

[case testNoAsyncDefInPY2_python2]

async def f(): # E: invalid syntax
pass

[case testYieldFromNoAwaitable]

from typing import Any, Generator
Expand Down
35 changes: 1 addition & 34 deletions test-data/unit/check-attr.test
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ A(1, 2, 3, 4) # E: Argument 2 to "A" has incompatible type "int"; expected "Lis
A(1, [2], '3', 4, 5) # E: Too many arguments for "A"
[builtins fixtures/list.pyi]

[case testAttrsPython2Annotations]
[case testAttrsTypeComments]
import attr
from typing import List, ClassVar
@attr.s
Expand Down Expand Up @@ -1032,28 +1032,6 @@ class C:
reveal_type(C) # N: Revealed type is "def (a: builtins.int, b: builtins.int) -> __main__.C"
[builtins fixtures/bool.pyi]

[case testAttrsNewStyleClassPy2]
# flags: --py2
import attr
@attr.s
class Good(object):
pass
@attr.s
class Bad: # E: attrs only works with new-style classes
pass
@attr.s
class SubclassOfBad(Bad):
pass
[builtins_py2 fixtures/bool.pyi]

[case testAttrsAutoAttribsPy2]
# flags: --py2
import attr
@attr.s(auto_attribs=True) # E: auto_attribs is not supported in Python 2
class A(object):
x = attr.ib()
[builtins_py2 fixtures/bool.pyi]

[case testAttrsFrozenSubclass]
import attr

Expand Down Expand Up @@ -1291,17 +1269,6 @@ class C:

[builtins fixtures/attr.pyi]

[case testAttrsKwOnlyPy2]
# flags: --py2
import attr
@attr.s(kw_only=True) # E: kw_only is not supported in Python 2
class A(object):
x = attr.ib()
@attr.s
class B(object):
x = attr.ib(kw_only=True) # E: kw_only is not supported in Python 2
[builtins_py2 fixtures/bool.pyi]

[case testAttrsDisallowUntypedWorksForward]
# flags: --disallow-untyped-defs
import attr
Expand Down
78 changes: 3 additions & 75 deletions test-data/unit/check-classes.test
Original file line number Diff line number Diff line change
Expand Up @@ -2207,7 +2207,7 @@ reveal_type(Num3() + Num1()) # N: Revealed type is "__main__.Num3"
reveal_type(Num2() + Num3()) # N: Revealed type is "__main__.Num2"
reveal_type(Num3() + Num2()) # N: Revealed type is "__main__.Num3"

[case testDivReverseOperatorPython3]
[case testDivReverseOperator]
# No error: __div__ has no special meaning in Python 3
class A1:
def __div__(self, x: B1) -> int: ...
Expand All @@ -2222,37 +2222,6 @@ class B2:
A1() / B1() # E: Unsupported left operand type for / ("A1")
reveal_type(A2() / B2()) # N: Revealed type is "builtins.int"

[case testDivReverseOperatorPython2]
# flags: --python-version 2.7

# Note: if 'from __future__ import division' is called, we use
# __truediv__. Otherwise, we use __div__. So, we check both:
class A1:
def __div__(self, x):
# type: (B1) -> int
pass
class B1:
def __rdiv__(self, x): # E: Signatures of "__rdiv__" of "B1" and "__div__" of "A1" are unsafely overlapping
# type: (A1) -> str
pass

class A2:
def __truediv__(self, x):
# type: (B2) -> int
pass
class B2:
def __rtruediv__(self, x): # E: Signatures of "__rtruediv__" of "B2" and "__truediv__" of "A2" are unsafely overlapping
# type: (A2) -> str
pass

# That said, mypy currently doesn't handle the actual division operation very
# gracefully -- it doesn't correctly switch to using __truediv__ when
# 'from __future__ import division' is included, it doesn't display a very
# graceful error if __div__ is missing but __truediv__ is present...
# Also see https://github.com/python/mypy/issues/2048
reveal_type(A1() / B1()) # N: Revealed type is "builtins.int"
A2() / B2() # E: "A2" has no attribute "__div__"

[case testReverseOperatorMethodForwardIsAny]
from typing import Any
def deco(f: Any) -> Any: return f
Expand Down Expand Up @@ -2502,17 +2471,7 @@ reveal_type(B() + y) # N: Revealed type is "Union[__main__.Out2, __main__.Out4]
reveal_type(x + C()) # N: Revealed type is "Union[__main__.Out3, __main__.Out2]"
reveal_type(x + D()) # N: Revealed type is "Union[__main__.Out1, __main__.Out4]"

[case testOperatorDoubleUnionDivisionPython2]
# flags: --python-version 2.7
from typing import Union
def f(a):
# type: (Union[int, float]) -> None
a /= 1.1
b = a / 1.1
reveal_type(b) # N: Revealed type is "builtins.float"
[builtins_py2 fixtures/ops.pyi]

[case testOperatorDoubleUnionDivisionPython3]
[case testOperatorDoubleUnionDivision]
from typing import Union
def f(a):
# type: (Union[int, float]) -> None
Expand Down Expand Up @@ -5083,16 +5042,6 @@ reveal_type(type(A).x) # N: Revealed type is "builtins.int"
reveal_type(type(B).x) # N: Revealed type is "builtins.int"
[builtins fixtures/tuple.pyi]

[case testSixMetaclass_python2]
import six
class M(type):
x = 5
class A(six.with_metaclass(M)): pass
@six.add_metaclass(M)
class B: pass
reveal_type(type(A).x) # N: Revealed type is "builtins.int"
reveal_type(type(B).x) # N: Revealed type is "builtins.int"

[case testFromSixMetaclass]
from six import with_metaclass, add_metaclass
class M(type):
Expand Down Expand Up @@ -5216,13 +5165,6 @@ class CQA(Q1): pass # E: Inconsistent metaclass structure for "CQA"
class CQW(six.with_metaclass(M, Q1)): pass # E: Inconsistent metaclass structure for "CQW"
[builtins fixtures/tuple.pyi]

[case testSixMetaclassErrors_python2]
# flags: --python-version 2.7
import six
class M(type): pass
class C4(six.with_metaclass(M)): # E: Multiple metaclass definitions
__metaclass__ = M

[case testSixMetaclassAny]
import t # type: ignore
import six
Expand All @@ -5243,13 +5185,6 @@ class A(future.utils.with_metaclass(M)): pass
reveal_type(type(A).x) # N: Revealed type is "builtins.int"
[builtins fixtures/tuple.pyi]

[case testFutureMetaclass_python2]
import future.utils
class M(type):
x = 5
class A(future.utils.with_metaclass(M)): pass
reveal_type(type(A).x) # N: Revealed type is "builtins.int"

[case testFromFutureMetaclass]
from future.utils import with_metaclass
class M(type):
Expand Down Expand Up @@ -5335,13 +5270,6 @@ class Q1(metaclass=M1): pass
class CQW(future.utils.with_metaclass(M, Q1)): pass # E: Inconsistent metaclass structure for "CQW"
[builtins fixtures/tuple.pyi]

[case testFutureMetaclassErrors_python2]
# flags: --python-version 2.7
import future.utils
class M(type): pass
class C4(future.utils.with_metaclass(M)): # E: Multiple metaclass definitions
__metaclass__ = M

[case testFutureMetaclassAny]
import t # type: ignore
import future.utils
Expand Down Expand Up @@ -7322,7 +7250,7 @@ def foo(self: Any) -> str:
from typing import Any, Callable, TypeVar

class Parent:
foo = Callable[..., int]
foo = Callable[..., int]
class bar:
pass
import typing as baz
Expand Down
46 changes: 0 additions & 46 deletions test-data/unit/check-columns.test
Original file line number Diff line number Diff line change
Expand Up @@ -170,22 +170,6 @@ z: Iterable[bad] # E:13: Variable "__main__.bad" is not valid as a type \
h: bad[int] # E:4: Variable "__main__.bad" is not valid as a type \
# N:4: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases

[case testColumnInvalidType_python2]

from typing import Iterable

bad = 0

if int():
def g(x): # E:5: Variable "__main__.bad" is not valid as a type \
# N:5: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases
# type: (bad) -> None
y = 0 # type: bad # E:9: Variable "__main__.bad" is not valid as a type \
# N:9: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases

z = () # type: Iterable[bad] # E:5: Variable "__main__.bad" is not valid as a type \
# N:5: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases

[case testColumnFunctionMissingTypeAnnotation]
# flags: --disallow-untyped-defs
if int():
Expand Down Expand Up @@ -216,14 +200,6 @@ def f(x, y): pass
(f()) # E:2: Missing positional arguments "x", "y" in call to "f"
(f(y=1)) # E:2: Missing positional argument "x" in call to "f"

[case testColumnTooFewSuperArgs_python2]
class A:
def f(self):
pass
class B(A):
def f(self): # type: () -> None
super().f() # E:9: Too few arguments for "super"

[case testColumnListOrDictItemHasIncompatibleType]
from typing import List, Dict
x: List[int] = [
Expand Down Expand Up @@ -316,12 +292,6 @@ if int():
# type: (int) -> None
pass

[case testColumnTypeSignatureHasTooFewArguments_python2]
if int():
def f(x, y): # E:5: Type signature has too few arguments
# type: (int) -> None
pass

[case testColumnRevealedType]
if int():
reveal_type(1) # N:17: Revealed type is "Literal[1]?"
Expand Down Expand Up @@ -373,22 +343,6 @@ class B(A):
def x(self) -> int: pass
[builtins fixtures/property.pyi]

[case testColumnProperty_python2]
class A:
@property
def x(self): # type: () -> int
pass

@x.setter
def x(self, x): # type: (int) -> None
pass

class B(A):
@property # E:5: Read-only property cannot override read-write property
def x(self): # type: () -> int
pass
[builtins_py2 fixtures/property_py2.pyi]

[case testColumnOverloaded]
from typing import overload, Any
class A:
Expand Down
Loading