diff --git a/mypy/main.py b/mypy/main.py index b90d82a30979..a5511671c966 100644 --- a/mypy/main.py +++ b/mypy/main.py @@ -121,11 +121,22 @@ def __getattr__(self, name: str) -> Any: def parse_version(v: str) -> Tuple[int, int]: m = re.match(r'\A(\d)\.(\d+)\Z', v) - if m: - return int(m.group(1)), int(m.group(2)) - else: + if not m: raise argparse.ArgumentTypeError( "Invalid python version '{}' (expected format: 'x.y')".format(v)) + major, minor = int(m.group(1)), int(m.group(2)) + if major == 2: + if minor != 7: + raise argparse.ArgumentTypeError( + "Python 2.{} is not supported (must be 2.7)".format(minor)) + elif major == 3: + if minor <= 2: + raise argparse.ArgumentTypeError( + "Python 3.{} is not supported (must be 3.3 or higher)".format(minor)) + else: + raise argparse.ArgumentTypeError( + "Python major version '{}' out of range (must be 2 or 3)".format(major)) + return major, minor # Make the help output a little less jarring. @@ -553,8 +564,7 @@ def get_init_file(dir: str) -> Optional[str]: # exists to specify types for values initialized to None or container # types. config_types = { - # TODO: Check validity of python version - 'python_version': lambda s: tuple(map(int, s.split('.'))), + 'python_version': parse_version, 'strict_optional_whitelist': lambda s: s.split(), 'custom_typing_module': str, 'custom_typeshed_dir': str, @@ -663,7 +673,11 @@ def parse_section(prefix: str, template: Options, if ct is bool: v = section.getboolean(key) # type: ignore # Until better stub elif callable(ct): - v = ct(section.get(key)) + try: + v = ct(section.get(key)) + except argparse.ArgumentTypeError as err: + print("%s: %s: %s" % (prefix, key, err), file=sys.stderr) + continue else: print("%s: Don't know what type %s should have" % (prefix, key), file=sys.stderr) continue diff --git a/mypy/test/testcheck.py b/mypy/test/testcheck.py index 77c820e51fa6..967186e2644c 100644 --- a/mypy/test/testcheck.py +++ b/mypy/test/testcheck.py @@ -10,7 +10,7 @@ from typing import Dict, List, Optional, Set, Tuple from mypy import build, defaults -from mypy.main import parse_version, process_options +from mypy.main import process_options from mypy.build import BuildSource, find_module_clear_caches from mypy.myunit import AssertionFailure from mypy.test.config import test_temp_dir, test_data_prefix diff --git a/test-data/unit/check-unreachable-code.test b/test-data/unit/check-unreachable-code.test index a18a42bd6dda..75e6f88c0c35 100644 --- a/test-data/unit/check-unreachable-code.test +++ b/test-data/unit/check-unreachable-code.test @@ -404,9 +404,9 @@ x = 1 [out] [case testCustomSysVersionInfo] -# flags: --python-version 3.2 +# flags: --python-version 3.5 import sys -if sys.version_info == (3, 2): +if sys.version_info == (3, 5): x = "foo" else: x = 3 @@ -415,9 +415,9 @@ reveal_type(x) # E: Revealed type is 'builtins.str' [out] [case testCustomSysVersionInfo2] -# flags: --python-version 3.1 +# flags: --python-version 3.5 import sys -if sys.version_info == (3, 2): +if sys.version_info == (3, 6): x = "foo" else: x = 3 diff --git a/test-data/unit/cmdline.test b/test-data/unit/cmdline.test index 50410cd9504e..f8c8a7e7e1ff 100644 --- a/test-data/unit/cmdline.test +++ b/test-data/unit/cmdline.test @@ -514,3 +514,64 @@ whatever main.py:1: error: Cannot find module named 'a' main.py:1: note: (Perhaps setting MYPYPATH or using the "--ignore-missing-imports" flag would help) main.py:1: error: Cannot find module named 'a.b' + +[case testPythonVersionTooOld10] +# cmd: mypy -c pass +[file mypy.ini] +[[mypy] +python_version = 1.0 +[out] +mypy.ini: [mypy]: python_version: Python major version '1' out of range (must be 2 or 3) + +[case testPythonVersionTooOld26] +# cmd: mypy -c pass +[file mypy.ini] +[[mypy] +python_version = 2.6 +[out] +mypy.ini: [mypy]: python_version: Python 2.6 is not supported (must be 2.7) + +[case testPythonVersionTooOld32] +# cmd: mypy -c pass +[file mypy.ini] +[[mypy] +python_version = 3.2 +[out] +mypy.ini: [mypy]: python_version: Python 3.2 is not supported (must be 3.3 or higher) + +[case testPythonVersionTooNew28] +# cmd: mypy -c pass +[file mypy.ini] +[[mypy] +python_version = 2.8 +[out] +mypy.ini: [mypy]: python_version: Python 2.8 is not supported (must be 2.7) + +[case testPythonVersionTooNew40] +# cmd: mypy -c pass +[file mypy.ini] +[[mypy] +python_version = 4.0 +[out] +mypy.ini: [mypy]: python_version: Python major version '4' out of range (must be 2 or 3) + +[case testPythonVersionAccepted27] +# cmd: mypy -c pass +[file mypy.ini] +[[mypy] +python_version = 2.7 +[out] + +[case testPythonVersionAccepted33] +# cmd: mypy -c pass +[file mypy.ini] +[[mypy] +python_version = 3.3 +[out] + +[case testPythonVersionAccepted36] +# cmd: mypy -c pass +[file mypy.ini] +[[mypy] +python_version = 3.6 +[out]