blob: 42f0ee8a9ec6ca699b5478b0f14acd4b8196f00b [file] [log] [blame] [edit]
-- Tests for command line parsing
-- ------------------------------
--
-- The initial line specifies the command line, in the format
--
-- # cmd: mypy <options>
--
-- Note that # flags: --some-flag IS NOT SUPPORTED.
-- Use # cmd: mypy --some-flag ...
--
-- '== Return code: <value>' is added to the output when the process return code
-- is "nonobvious" -- that is, when it is something other than 0 if there are no
-- messages and 1 if there are.
-- Directories/packages on the command line
-- ----------------------------------------
[case testCmdlinePackage]
# cmd: mypy pkg
[file pkg/__init__.py]
[file pkg/a.py]
undef
[file pkg/subpkg/__init__.py]
[file pkg/subpkg/a.py]
undef
import pkg.subpkg.a
[out]
pkg/a.py:1: error: Name "undef" is not defined
pkg/subpkg/a.py:1: error: Name "undef" is not defined
[case testCmdlinePackageSlash]
# cmd: mypy pkg/
[file pkg/__init__.py]
[file pkg/a.py]
undef
[file pkg/subpkg/__init__.py]
[file pkg/subpkg/a.py]
undef
import pkg.subpkg.a
[out]
pkg/a.py:1: error: Name "undef" is not defined
pkg/subpkg/a.py:1: error: Name "undef" is not defined
[case testCmdlineNonPackage]
# cmd: mypy dir
[file dir/a.py]
undef
[file dir/subdir/b.py]
undef
[out]
dir/a.py:1: error: Name "undef" is not defined
dir/subdir/b.py:1: error: Name "undef" is not defined
[case testCmdlineNonPackageDuplicate]
# cmd: mypy dir
[file dir/a.py]
undef
[file dir/subdir/a.py]
undef
[out]
dir/a.py: error: Duplicate module named "a" (also at "dir/subdir/a.py")
dir/a.py: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#mapping-file-paths-to-modules for more info
dir/a.py: note: Common resolutions include: a) using `--exclude` to avoid checking one of them, b) adding `__init__.py` somewhere, c) using `--explicit-package-bases` or adjusting MYPYPATH
== Return code: 2
[case testCmdlineNonPackageSlash]
# cmd: mypy dir/
[file dir/a.py]
undef
import b
[file dir/subdir/b.py]
undef
import a
[out]
dir/a.py:1: error: Name "undef" is not defined
dir/subdir/b.py:1: error: Name "undef" is not defined
[case testCmdlinePackageContainingSubdir]
# cmd: mypy pkg
[file pkg/__init__.py]
[file pkg/a.py]
undef
import pkg.a
[file pkg/subdir/a.py]
undef
import pkg.a
[out]
pkg/a.py:1: error: Name "undef" is not defined
pkg/subdir/a.py:1: error: Name "undef" is not defined
[case testCmdlineNonPackageContainingPackage]
# cmd: mypy dir
[file dir/a.py]
undef
import subpkg.a
[file dir/subpkg/__init__.py]
[file dir/subpkg/a.py]
undef
[out]
dir/subpkg/a.py:1: error: Name "undef" is not defined
dir/a.py:1: error: Name "undef" is not defined
[case testCmdlineInvalidPackageName]
# cmd: mypy dir/sub.pkg/a.py
[file dir/sub.pkg/__init__.py]
[file dir/sub.pkg/a.py]
undef
[out]
sub.pkg is not a valid Python package name
== Return code: 2
[case testBadFileEncoding]
# cmd: mypy a.py
[file a.py]
# coding: uft-8
[out]
mypy: can't decode file 'a.py': unknown encoding: uft-8
== Return code: 2
-- '
[case testCannotIgnoreDuplicateModule]
# cmd: mypy one/mod/__init__.py two/mod/__init__.py
[file one/mod/__init__.py]
# type: ignore
[file two/mod/__init__.py]
# type: ignore
[out]
two/mod/__init__.py: error: Duplicate module named "mod" (also at "one/mod/__init__.py")
two/mod/__init__.py: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#mapping-file-paths-to-modules for more info
two/mod/__init__.py: note: Common resolutions include: a) using `--exclude` to avoid checking one of them, b) adding `__init__.py` somewhere, c) using `--explicit-package-bases` or adjusting MYPYPATH
== Return code: 2
-- Note that we use `----`, because this is how `--` is escaped while `--` is a comment starter.
[case testFlagsFile]
# cmd: mypy @flagsfile
[file flagsfile]
----always-true=FLAG
main.py
[file main.py]
x: int
FLAG = False
if not FLAG:
x = "unreachable"
[case testConfigFile]
# cmd: mypy main.py
[file mypy.ini]
\[mypy]
always_true = FLAG
[file main.py]
x: int
FLAG = False
if not FLAG:
x = "unreachable"
[case testErrorContextConfig]
# cmd: mypy main.py
[file mypy.ini]
\[mypy]
show_error_context=True
[file main.py]
def f() -> None:
0 + ""
[out]
main.py: note: In function "f":
main.py:2: error: Unsupported operand types for + ("int" and "str")
[case testAltConfigFile]
# cmd: mypy --config-file config.ini main.py
[file config.ini]
\[mypy]
always_true = FLAG
[file main.py]
x: int
FLAG = False
if not FLAG:
x = "unreachable"
[case testNoConfigFile]
# cmd: mypy main.py --config-file=
[file mypy.ini]
\[mypy]
warn_unused_ignores = True
[file main.py]
# type: ignore
[case testPerFileConfigSection]
# cmd: mypy x.py y.py z.py
[file mypy.ini]
\[mypy]
disallow_untyped_defs = True
\[mypy-y]
disallow_untyped_defs = False
\[mypy-z]
disallow_untyped_calls = True
[file x.py]
def f(a):
pass
def g(a: int) -> int:
return f(a)
[file y.py]
def f(a):
pass
def g(a: int) -> int:
return f(a)
[file z.py]
def f(a):
pass
def g(a: int) -> int:
return f(a)
[out]
z.py:1: error: Function is missing a type annotation
z.py:4: error: Call to untyped function "f" in typed context
x.py:1: error: Function is missing a type annotation
[case testPerFileConfigSectionMultipleMatchesDisallowed]
# cmd: mypy xx.py xy.py yx.py yy.py
[file mypy.ini]
\[mypy]
\[mypy-*x*]
disallow_untyped_defs = True
\[mypy-*y*]
disallow_untyped_calls = True
[file xx.py]
def f(a): pass
def g(a: int) -> int: return f(a)
[file xy.py]
def f(a): pass
def g(a: int) -> int: return f(a)
[file yx.py]
def f(a): pass
def g(a: int) -> int: return f(a)
[file yy.py]
def f(a): pass
def g(a: int) -> int: return f(a)
[out]
mypy.ini: [mypy-*x*]: Patterns must be fully-qualified module names, optionally with '*' in some components (e.g spam.*.eggs.*)
mypy.ini: [mypy-*y*]: Patterns must be fully-qualified module names, optionally with '*' in some components (e.g spam.*.eggs.*)
== Return code: 0
[case testMultipleGlobConfigSection]
# cmd: mypy x.py y.py z.py
[file mypy.ini]
\[mypy]
\[mypy-x.*,z.*]
disallow_untyped_defs = True
[file x.py]
def f(a): pass
[file y.py]
def f(a): pass
[file z.py]
def f(a): pass
[out]
z.py:1: error: Function is missing a type annotation
x.py:1: error: Function is missing a type annotation
[case testConfigErrorNoSection]
# cmd: mypy -c pass
[file mypy.ini]
[out]
mypy.ini: No [mypy] section in config file
== Return code: 0
[case testConfigErrorUnknownFlag]
# cmd: mypy -c pass
[file mypy.ini]
\[mypy]
bad = 0
[out]
mypy.ini: [mypy]: Unrecognized option: bad = 0
== Return code: 0
[case testConfigErrorBadFlag]
# cmd: mypy a.py
[file mypy.ini]
\[mypy]
disallow-untyped-defs = True
[file a.py]
def f():
pass
[out]
mypy.ini: [mypy]: Unrecognized option: disallow-untyped-defs = True
== Return code: 0
[case testConfigErrorBadBoolean]
# cmd: mypy -c pass
[file mypy.ini]
\[mypy]
ignore_missing_imports = nah
[out]
mypy.ini: [mypy]: ignore_missing_imports: Not a boolean: nah
== Return code: 0
[case testConfigErrorNotPerFile]
# cmd: mypy -c pass
[file mypy.ini]
\[mypy]
\[mypy-*]
python_version = 3.11
[out]
mypy.ini: [mypy-*]: Per-module sections should only specify per-module flags (python_version)
== Return code: 0
[case testConfigMypyPath]
# cmd: mypy file.py
[file mypy.ini]
\[mypy]
mypy_path =
foo_dir:bar_dir
, baz_dir
[file foo_dir/foo.pyi]
def foo(x: int) -> str: ...
[file bar_dir/bar.pyi]
def bar(x: str) -> list: ...
[file baz_dir/baz.pyi]
def baz(x: list) -> dict: ...
[file file.py]
import no_stubs
from foo import foo
from bar import bar
from baz import baz
baz(bar(foo(42)))
baz(bar(foo('oof')))
[out]
file.py:1: error: Cannot find implementation or library stub for module named "no_stubs"
file.py:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports
file.py:6: error: Argument 1 to "foo" has incompatible type "str"; expected "int"
[case testIgnoreErrorsConfig]
# cmd: mypy x.py y.py
[file mypy.ini]
\[mypy]
\[mypy-x]
ignore_errors = True
[file x.py]
x: str = 5
[file y.py]
x: str = 5
[out]
y.py:1: error: Incompatible types in assignment (expression has type "int", variable has type "str")
[case testConfigFollowImportsNormal]
# cmd: mypy main.py
[file main.py]
from a import x
x + 0
x + '' # E
import a
a.x + 0
a.x + '' # E
a.y # E
a + 0 # E
[file mypy.ini]
\[mypy]
follow_imports = normal
[file a.py]
x = 0
x += '' # Error reported here
[out]
a.py:2: error: Unsupported operand types for + ("int" and "str")
main.py:3: error: Unsupported operand types for + ("int" and "str")
main.py:6: error: Unsupported operand types for + ("int" and "str")
main.py:7: error: Module has no attribute "y"
main.py:8: error: Unsupported operand types for + (Module and "int")
[case testConfigFollowImportsSysPath]
# cmd: mypy main.py
[file main.py]
from a import x
x + 0
x + '' # E
import a
a.x + 0
a.x + '' # E
a.y # E
a + 0 # E
[file mypy.ini]
\[mypy]
follow_imports = normal
no_silence_site_packages = True
[file pypath/a/__init__.py]
x = 0
x += '' # Error reported here
[file pypath/a/py.typed]
[out]
pypath/a/__init__.py:2: error: Unsupported operand types for + ("int" and "str")
main.py:3: error: Unsupported operand types for + ("int" and "str")
main.py:6: error: Unsupported operand types for + ("int" and "str")
main.py:7: error: Module has no attribute "y"
main.py:8: error: Unsupported operand types for + (Module and "int")
[case testConfigFollowImportsSilent]
# cmd: mypy main.py
[file main.py]
from a import x
x + ''
import a
a.x + ''
a.y
a + 0
[file mypy.ini]
\[mypy]
follow_imports = silent
[file a.py]
x = 0
x += '' # No error reported
[out]
main.py:2: error: Unsupported operand types for + ("int" and "str")
main.py:4: error: Unsupported operand types for + ("int" and "str")
main.py:5: error: Module has no attribute "y"
main.py:6: error: Unsupported operand types for + (Module and "int")
[case testConfigFollowImportsSkip]
# cmd: mypy main.py
[file main.py]
from a import x
reveal_type(x) # Expect Any
import a
reveal_type(a.x) # Expect Any
[file mypy.ini]
\[mypy]
follow_imports = skip
[file a.py]
/ # No error reported
[out]
main.py:2: note: Revealed type is "Any"
main.py:4: note: Revealed type is "Any"
== Return code: 0
[case testConfigFollowImportsError]
# cmd: mypy main.py
[file main.py]
from a import x # Error reported here
reveal_type(x) # Expect Any
import a
reveal_type(a.x) # Expect Any
[file mypy.ini]
\[mypy]
follow_imports = error
[file a.py]
/ # No error reported
[out]
main.py:1: error: Import of "a" ignored
main.py:1: note: (Using --follow-imports=error, module not passed on command line)
main.py:2: note: Revealed type is "Any"
main.py:4: note: Revealed type is "Any"
[case testConfigFollowImportsSelective]
# cmd: mypy main.py
[file mypy.ini]
\[mypy]
\[mypy-normal]
follow_imports = normal
\[mypy-silent]
follow_imports = silent
\[mypy-skip]
follow_imports = skip
\[mypy-error]
follow_imports = error
[file main.py]
import normal
import silent
import skip
import error
reveal_type(normal.x)
reveal_type(silent.x)
reveal_type(skip)
reveal_type(error)
[file normal.py]
x = 0
x += ''
[file silent.py]
x = 0
x += ''
[file skip.py]
bla bla
[file error.py]
bla bla
[out]
normal.py:2: error: Unsupported operand types for + ("int" and "str")
main.py:4: error: Import of "error" ignored
main.py:4: note: (Using --follow-imports=error, module not passed on command line)
main.py:5: note: Revealed type is "builtins.int"
main.py:6: note: Revealed type is "builtins.int"
main.py:7: note: Revealed type is "Any"
main.py:8: note: Revealed type is "Any"
[case testConfigFollowImportsInvalid]
# cmd: mypy main.py
[file mypy.ini]
\[mypy]
follow_imports =True
[file main.py]
[out]
mypy.ini: [mypy]: follow_imports: invalid choice 'True' (choose from 'normal', 'silent', 'skip', 'error')
== Return code: 0
[case testConfigSilentMissingImportsOff]
# cmd: mypy main.py
[file main.py]
import missing # Expect error here
reveal_type(missing.x) # Expect Any
[file mypy.ini]
\[mypy]
ignore_missing_imports = False
[out]
main.py:1: error: Cannot find implementation or library stub for module named "missing"
main.py:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports
main.py:2: note: Revealed type is "Any"
[case testConfigSilentMissingImportsOn]
# cmd: mypy main.py
[file main.py]
import missing # No error here
reveal_type(missing.x) # Expect Any
[file mypy.ini]
\[mypy]
ignore_missing_imports = True
[out]
main.py:2: note: Revealed type is "Any"
== Return code: 0
[case testFailedImportOnWrongCWD]
# cmd: mypy main.py
# cwd: main/subdir1/subdir2
[file main/subdir1/subdir2/main.py]
import parent
import grandparent
import missing
[file main/subdir1/subdir2/__init__.py]
[file main/subdir1/parent.py]
[file main/subdir1/__init__.py]
[file main/grandparent.py]
[file main/__init__.py]
[out]
main.py:1: error: Cannot find implementation or library stub for module named "parent"
main.py:1: note: You may be running mypy in a subpackage, mypy should be run on the package root
main.py:2: error: Cannot find implementation or library stub for module named "grandparent"
main.py:3: error: Cannot find implementation or library stub for module named "missing"
main.py:3: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports
[case testImportInParentButNoInit]
# cmd: mypy main.py
# cwd: main/not_a_package
[file main/not_a_package/main.py]
import needs_init
[file main/needs_init.py]
[file main/__init__.py]
[out]
main.py:1: error: Cannot find implementation or library stub for module named "needs_init"
main.py:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports
[case testConfigNoErrorForUnknownXFlagInSubsection]
# cmd: mypy -c pass
[file mypy.ini]
\[mypy]
\[mypy-foo]
x_bad = 0
[out]
[case testDotInFilenameOKScript]
# cmd: mypy a.b.py c.d.pyi
[file a.b.py]
undef
[file c.d.pyi]
whatever
[out]
c.d.pyi:1: error: Name "whatever" is not defined
a.b.py:1: error: Name "undef" is not defined
[case testDotInFilenameOKFolder]
# cmd: mypy my.folder
[file my.folder/tst.py]
undef
[out]
my.folder/tst.py:1: error: Name "undef" is not defined
[case testDotInFilenameNoImport]
# cmd: mypy main.py
[file main.py]
import a.b
[file a.b.py]
whatever
[out]
main.py:1: error: Cannot find implementation or library stub for module named "a.b"
main.py:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports
main.py:1: error: Cannot find implementation or library stub for module named "a"
[case testPythonVersionWrongFormatPyProjectTOML]
# cmd: mypy -c pass
[file pyproject.toml]
\[tool.mypy]
python_version = 3.10
[out]
pyproject.toml: [mypy]: python_version: Python 3.1 is not supported (must be 3.7 or higher). You may need to put quotes around your Python version
== Return code: 0
[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 3)
== Return code: 0
[case testPythonVersionTooOld36]
# cmd: mypy -c pass
[file mypy.ini]
\[mypy]
python_version = 3.6
[out]
mypy.ini: [mypy]: python_version: Python 3.6 is not supported (must be 3.7 or higher)
== Return code: 0
[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 3)
== Return code: 0
[case testPythonVersionTooDead27]
# cmd: mypy -c pass
[file mypy.ini]
\[mypy]
python_version = 2.7
[out]
usage: mypy [-h] [-v] [-V] [more options; see below]
[-m MODULE] [-p PACKAGE] [-c PROGRAM_TEXT] [files ...]
mypy: error: Mypy no longer supports checking Python 2 code. Consider pinning to mypy<0.980 if you need to check Python 2 code.
== Return code: 2
[case testPythonVersionAccepted37]
# cmd: mypy -c pass
[file mypy.ini]
\[mypy]
python_version = 3.7
[out]
[case testPythonVersionAccepted311]
# cmd: mypy -c pass
[file mypy.ini]
\[mypy]
python_version = 3.11
[out]
-- This should be a dumping ground for tests of plugins that are sensitive to
-- typeshed changes.
[case testTypeshedSensitivePlugins]
# cmd: mypy int_pow.py
[file int_pow.py]
a = 1
b = a + 2
reveal_type(a**0)
reveal_type(a**1)
reveal_type(a**2)
reveal_type(a**-0)
reveal_type(a**-1)
reveal_type(a**(-2))
reveal_type(a**b)
reveal_type(a.__pow__(2))
reveal_type(a.__pow__(a))
[out]
int_pow.py:3: note: Revealed type is "Literal[1]"
int_pow.py:4: note: Revealed type is "builtins.int"
int_pow.py:5: note: Revealed type is "builtins.int"
int_pow.py:6: note: Revealed type is "Literal[1]"
int_pow.py:7: note: Revealed type is "builtins.float"
int_pow.py:8: note: Revealed type is "builtins.float"
int_pow.py:9: note: Revealed type is "Any"
int_pow.py:10: note: Revealed type is "builtins.int"
int_pow.py:11: note: Revealed type is "Any"
== Return code: 0
[case testDisallowAnyGenericsBuiltinCollectionsPre39]
# cmd: mypy m.py
[file mypy.ini]
\[mypy]
python_version = 3.8
\[mypy-m]
disallow_any_generics = True
[file m.py]
s = tuple([1, 2, 3]) # no error
def f(t: tuple) -> None: pass
def g() -> list: pass
def h(s: dict) -> None: pass
def i(s: set) -> None: pass
def j(s: frozenset) -> None: pass
[out]
m.py:3: error: Implicit generic "Any". Use "typing.Tuple" and specify generic parameters
m.py:4: error: Implicit generic "Any". Use "typing.List" and specify generic parameters
m.py:5: error: Implicit generic "Any". Use "typing.Dict" and specify generic parameters
m.py:6: error: Implicit generic "Any". Use "typing.Set" and specify generic parameters
m.py:7: error: Implicit generic "Any". Use "typing.FrozenSet" and specify generic parameters
[case testDisallowAnyGenericsTypingCollections]
# cmd: mypy m.py
[file mypy.ini]
\[mypy]
\[mypy-m]
disallow_any_generics = True
[file m.py]
from typing import Tuple, List, Dict, Set, FrozenSet
def f(t: Tuple) -> None: pass
def g() -> List: pass
def h(s: Dict) -> None: pass
def i(s: Set) -> None: pass
def j(s: FrozenSet) -> None: pass
[out]
m.py:3: error: Missing type parameters for generic type "Tuple"
m.py:4: error: Missing type parameters for generic type "List"
m.py:5: error: Missing type parameters for generic type "Dict"
m.py:6: error: Missing type parameters for generic type "Set"
m.py:7: error: Missing type parameters for generic type "FrozenSet"
[case testSectionInheritance]
# cmd: mypy a
[file a/__init__.py]
0()
[file a/foo.py]
0()
[file a/b/__init__.py]
[file a/b/c/__init__.py]
0()
[file a/b/c/d/__init__.py]
[file a/b/c/d/e/__init__.py]
from typing import List
def g(x: List) -> None: pass
g(None)
[file mypy.ini]
\[mypy]
allow_any_generics = True
\[mypy-a.*]
ignore_errors = True
\[mypy-a.b.*]
disallow_any_generics = True
ignore_errors = True
\[mypy-a.b.c.*]
ignore_errors = True
\[mypy-a.b.c.d.*]
ignore_errors = True
\[mypy-a.b.c.d.e.*]
ignore_errors = True
strict_optional = True
\[mypy-a.b.c.d.e]
ignore_errors = False
[out]
a/b/c/d/e/__init__.py:2: error: Missing type parameters for generic type "List"
a/b/c/d/e/__init__.py:3: error: Argument 1 to "g" has incompatible type "None"; expected "List[Any]"
[case testDisallowUntypedDefsAndGenerics]
# cmd: mypy a.py
[file mypy.ini]
\[mypy]
disallow_untyped_defs = True
disallow_any_generics = True
[file a.py]
def get_tasks(self):
return 'whatever'
[out]
a.py:1: error: Function is missing a return type annotation
[case testMissingFile]
# cmd: mypy nope.py
[out]
mypy: can't read file 'nope.py': No such file or directory
== Return code: 2
--'
[case testParseError]
# cmd: mypy a.py
[file a.py]
def foo(
[out]
a.py:1: error: unexpected EOF while parsing
== Return code: 2
[out version>=3.10]
a.py:1: error: '(' was never closed
== Return code: 2
[case testParseErrorAnnots]
# cmd: mypy a.py
[file a.py]
def foo(x):
# type: (str, int) -> None
return
[out]
a.py:1: error: Type signature has too many arguments
[case testModulesAndPackages]
# cmd: mypy --package p.a --package p.b --module c
[file p/__init__.py]
[file p/a.py]
def foo(x):
# type: (int) -> str
return "x"
foo("wrong")
[file p/b/__init__.py]
from ..a import foo
def bar(a):
# type: (int) -> str
return foo(a)
bar("wrong")
[file c.py]
import p.b
p.b.bar("wrong")
[out]
p/a.py:4: error: Argument 1 to "foo" has incompatible type "str"; expected "int"
p/b/__init__.py:5: error: Argument 1 to "bar" has incompatible type "str"; expected "int"
c.py:2: error: Argument 1 to "bar" has incompatible type "str"; expected "int"
[case testSrcPEP420Packages]
# cmd: mypy -p anamespace --namespace-packages
[file mypy.ini]
\[mypy]
mypy_path = src
[file src/setup.cfg]
[file src/anamespace/foo/__init__.py]
[file src/anamespace/foo/bar.py]
def bar(a: int, b: int) -> str:
return a + b
[out]
src/anamespace/foo/bar.py:2: error: Incompatible return value type (got "int", expected "str")
[case testNestedPEP420Packages]
# cmd: mypy -p pkg --namespace-packages
[file pkg/a1/b/c/d/e.py]
x = 0 # type: str
[file pkg/a1/b/f.py]
from pkg.a1.b.c.d.e import x
x()
[file pkg/a2/__init__.py]
[file pkg/a2/b/c/d/e.py]
x = 0 # type: str
[file pkg/a2/b/f.py]
from pkg.a2.b.c.d.e import x
x()
[out]
pkg/a2/b/c/d/e.py:1: error: Incompatible types in assignment (expression has type "int", variable has type "str")
pkg/a1/b/c/d/e.py:1: error: Incompatible types in assignment (expression has type "int", variable has type "str")
pkg/a2/b/f.py:2: error: "str" not callable
pkg/a1/b/f.py:2: error: "str" not callable
[case testFollowImportStubs1]
# cmd: mypy main.py
[file mypy.ini]
\[mypy]
\[mypy-math.*]
follow_imports = error
follow_imports_for_stubs = True
[file main.py]
import math
math.frobnicate()
[out]
main.py:1: error: Import of "math" ignored
main.py:1: note: (Using --follow-imports=error, module not passed on command line)
[case testFollowImportStubs2]
# cmd: mypy main.py
[file mypy.ini]
\[mypy]
\[mypy-math.*]
follow_imports = skip
follow_imports_for_stubs = True
[file main.py]
import math
math.frobnicate()
[case testShadowFile1]
# cmd: mypy --shadow-file source.py shadow.py source.py
[file source.py]
def foo() -> str:
return "bar"
[file shadow.py]
def bar() -> str:
return 14
[out]
source.py:2: error: Incompatible return value type (got "int", expected "str")
[case testShadowFile2]
# cmd: mypy --shadow-file s1.py shad1.py --shadow-file s2.py shad2.py --shadow-file s3.py shad3.py s1.py s2.py s3.py s4.py
[file s1.py]
def foo() -> str:
return "bar"
[file shad1.py]
def bar() -> str:
return 14
[file s2.py]
def baz() -> str:
return 14
[file shad2.py]
def baz() -> int:
return 14
[file s3.py]
def qux() -> str:
return "bar"
[file shad3.py]
def foo() -> int:
return [42]
[file s4.py]
def foo() -> str:
return 9
[out]
s4.py:2: error: Incompatible return value type (got "int", expected "str")
s3.py:2: error: Incompatible return value type (got "List[int]", expected "int")
s1.py:2: error: Incompatible return value type (got "int", expected "str")
[case testConfigWarnUnusedSection1]
# cmd: mypy foo.py quux.py spam/eggs.py
[file mypy.ini]
\[mypy]
warn_unused_configs = True
incremental = False
\[mypy-bar]
\[mypy-foo]
\[mypy-baz.*]
\[mypy-quux.*]
\[mypy-spam.*]
\[mypy-spam.eggs]
\[mypy-emarg.*]
\[mypy-emarg.hatch]
-- Currently we don't treat an unstructured pattern like a.*.b as unused
-- if it matches another section (like a.x.b). This would be reasonable
-- to change. '
\[mypy-a.*.b]
\[mypy-a.*.c]
\[mypy-a.x.b]
[file foo.py]
[file quux.py]
[file spam/__init__.py]
[file spam/eggs.py]
[out]
Warning: unused section(s) in mypy.ini: [mypy-bar], [mypy-baz.*], [mypy-emarg.*], [mypy-emarg.hatch], [mypy-a.*.c], [mypy-a.x.b]
== Return code: 0
[case testConfigUnstructuredGlob]
# cmd: mypy emarg foo
[file mypy.ini]
\[mypy]
ignore_errors = true
\[mypy-*.lol]
ignore_errors = false
\[mypy-emarg.*]
ignore_errors = false
\[mypy-emarg.*.villip.*]
ignore_errors = true
\[mypy-emarg.hatch.villip.mankangulisk]
ignore_errors = false
[file emarg/__init__.py]
[file emarg/foo.py]
fail
[file emarg/villip.py]
fail
[file emarg/hatch/__init__.py]
[file emarg/hatch/villip/__init__.py]
[file emarg/hatch/villip/nus.py]
fail
[file emarg/hatch/villip/mankangulisk.py]
fail
[file foo/__init__.py]
[file foo/lol.py]
fail
[out]
foo/lol.py:1: error: Name "fail" is not defined
emarg/foo.py:1: error: Name "fail" is not defined
emarg/hatch/villip/mankangulisk.py:1: error: Name "fail" is not defined
[case testPackageRootEmpty]
# cmd: mypy --no-namespace-packages --package-root= a/b/c.py main.py
[file a/b/c.py]
[file main.py]
import a.b.c
[case testPackageRootEmptyNamespacePackage]
# cmd: mypy --namespace-packages --package-root= a/b/c.py main.py
[file a/b/c.py]
[file main.py]
import a.b.c
[case testPackageRootNonEmpty]
# cmd: mypy --package-root=a/ a/b/c.py main.py
[file a/b/c.py]
[file main.py]
import b.c
[case testPackageRootMultiple1]
# cmd: mypy --package-root=. --package-root=a a/b/c.py d.py main.py
[file a/b/c.py]
[file d.py]
[file main.py]
import b.c
import d
[case testPackageRootMultiple2]
# cmd: mypy --package-root=a/ --package-root=./ a/b/c.py d.py main.py
[file a/b/c.py]
[file d.py]
[file main.py]
import b.c
import d
[case testCacheMap]
-- This just checks that a valid --cache-map triple is accepted.
-- (Errors are too verbose to check.)
# cmd: mypy a.py --no-sqlite-cache --cache-map a.py a.meta.json a.data.json
[file a.py]
[out]
[case testIniFiles]
# cmd: mypy
[file mypy.ini]
\[mypy]
files = a.py, b.py
[file a.py]
fail
[file b.py]
fail
[out]
b.py:1: error: Name "fail" is not defined
a.py:1: error: Name "fail" is not defined
[case testIniFilesGlobbing]
# cmd: mypy
[file mypy.ini]
\[mypy]
files = **/*.py
[file a/b.py]
fail
[file c.py]
fail
[out]
a/b.py:1: error: Name "fail" is not defined
c.py:1: error: Name "fail" is not defined
[case testIniFilesCmdlineOverridesConfig]
# cmd: mypy override.py
[file mypy.ini]
\[mypy]
files = config.py
[out]
mypy: can't read file 'override.py': No such file or directory
== Return code: 2
[case testErrorSummaryOnSuccess]
# cmd: mypy --error-summary good.py
[file good.py]
x = 2 + 2
[out]
Success: no issues found in 1 source file
== Return code: 0
[case testErrorSummaryOnFail]
# cmd: mypy --error-summary bad.py
[file bad.py]
42 + 'no'
[out]
bad.py:1: error: Unsupported operand types for + ("int" and "str")
Found 1 error in 1 file (checked 1 source file)
[case testErrorSummaryOnFailNotes]
# cmd: mypy --error-summary bad.py
[file bad.py]
from typing import List
x = [] # type: List[float]
y = [] # type: List[int]
x = y
[out]
bad.py:4: error: Incompatible types in assignment (expression has type "List[int]", variable has type "List[float]")
bad.py:4: note: "List" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance
bad.py:4: note: Consider using "Sequence" instead, which is covariant
Found 1 error in 1 file (checked 1 source file)
[case testErrorSummaryOnFailTwoErrors]
# cmd: mypy --error-summary bad.py foo.py
[file bad.py]
42 + 'no'
42 + 'no'
[file foo.py]
[out]
bad.py:1: error: Unsupported operand types for + ("int" and "str")
bad.py:2: error: Unsupported operand types for + ("int" and "str")
Found 2 errors in 1 file (checked 2 source files)
[case testErrorSummaryOnFailTwoFiles]
# cmd: mypy --error-summary bad.py bad2.py
[file bad.py]
42 + 'no'
[file bad2.py]
42 + 'no'
[out]
bad2.py:1: error: Unsupported operand types for + ("int" and "str")
bad.py:1: error: Unsupported operand types for + ("int" and "str")
Found 2 errors in 2 files (checked 2 source files)
[case testErrorSummaryOnBadUsage]
# cmd: mypy --error-summary missing.py
[out]
mypy: can't read file 'missing.py': No such file or directory
== Return code: 2
[case testShowSourceCodeSnippetsWrappedFormatting]
# cmd: mypy --pretty some_file.py
[file some_file.py]
from typing import Union
42 + 'no way'
class OneCustomClassName:
def some_interesting_method(self, arg: AnotherCustomClassDefinedBelow) -> AnotherCustomClassDefinedBelow:
...
class AnotherCustomClassDefinedBelow:
def another_even_more_interesting_method(self, arg: Union[int, str, float]) -> None:
self.very_important_attribute_with_long_name: OneCustomClassName = OneCustomClassName().some_interesting_method(arg)
[out]
some_file.py:3: error: Unsupported operand types for + ("int" and "str")
42 + 'no way'
^~~~~~~~
some_file.py:11: error: Incompatible types in assignment (expression has type
"AnotherCustomClassDefinedBelow", variable has type "OneCustomClassName")
...t_attribute_with_long_name: OneCustomClassName = OneCustomClassName()....
^~~~~~~~~~~~~~~~~~~~~...
some_file.py:11: error: Argument 1 to "some_interesting_method" of
"OneCustomClassName" has incompatible type "Union[int, str, float]"; expected
"AnotherCustomClassDefinedBelow"
...OneCustomClassName = OneCustomClassName().some_interesting_method(arg)
^~~
[case testShowSourceCodeSnippetsBlockingError]
# cmd: mypy --pretty --show-error-codes some_file.py
[file some_file.py]
it_looks_like_we_started_typing_something_but_then. = did_not_notice(an_extra_dot)
[out]
some_file.py:1: error: invalid syntax [syntax]
...ooks_like_we_started_typing_something_but_then. = did_not_notice(an_ex...
^
== Return code: 2
[case testTabRenderingUponError]
# cmd: mypy --pretty tabs.py
[file tabs.py]
def test_tabs() -> str:
return None
def test_between(x: str) -> None: ...
test_between(1 + 1)
[out]
tabs.py:2: error: Incompatible return value type (got "None", expected "str")
return None
^~~~
tabs.py:4: error: Argument 1 to "test_between" has incompatible type "int";
expected "str"
test_between(1 + 1)
^~~~~~~~~~~~
[case testErrorMessageWhenOpenPydFile]
# cmd: mypy a.pyd
[file a.pyd]
# coding: uft-8
[out]
mypy: stubgen does not support .pyd files: 'a.pyd'
== Return code: 2
[case testDuplicateModules]
# cmd: mypy src
[file mypy.ini]
\[mypy]
mypy_path = src
[file src/__init__.py]
[file src/a.py]
import foo.bar
[file src/foo/__init__.py]
[file src/foo/bar.py]
1+'x'
[out]
src/foo/bar.py: error: Source file found twice under different module names: "src.foo.bar" and "foo.bar"
src/foo/bar.py: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#mapping-file-paths-to-modules for more info
src/foo/bar.py: note: Common resolutions include: a) adding `__init__.py` somewhere, b) using `--explicit-package-bases` or adjusting MYPYPATH
== Return code: 2
[case testEnableInvalidErrorCode]
# cmd: mypy --enable-error-code YOLO test.py
[file test.py]
x = 1
[out]
usage: mypy [-h] [-v] [-V] [more options; see below]
[-m MODULE] [-p PACKAGE] [-c PROGRAM_TEXT] [files ...]
mypy: error: Invalid error code(s): YOLO
== Return code: 2
[case testDisableInvalidErrorCode]
# cmd: mypy --disable-error-code YOLO test.py
[file test.py]
x = 1
[out]
usage: mypy [-h] [-v] [-V] [more options; see below]
[-m MODULE] [-p PACKAGE] [-c PROGRAM_TEXT] [files ...]
mypy: error: Invalid error code(s): YOLO
== Return code: 2
[case testEnableAndDisableInvalidErrorCode]
# cmd: mypy --disable-error-code YOLO --enable-error-code YOLO2 test.py
[file test.py]
x = 1
[out]
usage: mypy [-h] [-v] [-V] [more options; see below]
[-m MODULE] [-p PACKAGE] [-c PROGRAM_TEXT] [files ...]
mypy: error: Invalid error code(s): YOLO, YOLO2
== Return code: 2
[case testEnableValidAndInvalidErrorCode]
# cmd: mypy --enable-error-code attr-defined --enable-error-code YOLO test.py
[file test.py]
x = 1
[out]
usage: mypy [-h] [-v] [-V] [more options; see below]
[-m MODULE] [-p PACKAGE] [-c PROGRAM_TEXT] [files ...]
mypy: error: Invalid error code(s): YOLO
== Return code: 2
[case testDisableValidAndInvalidErrorCode]
# cmd: mypy --disable-error-code attr-defined --disable-error-code YOLO test.py
[file test.py]
x = 1
[out]
usage: mypy [-h] [-v] [-V] [more options; see below]
[-m MODULE] [-p PACKAGE] [-c PROGRAM_TEXT] [files ...]
mypy: error: Invalid error code(s): YOLO
== Return code: 2
[case testStubsDirectory]
# cmd: mypy --error-summary pkg-stubs
[file pkg-stubs/__init__.pyi]
[file pkg-stubs/thing.pyi]
class Thing: ...
[out]
Success: no issues found in 2 source files
== Return code: 0
[case testStubsDirectoryFile]
# cmd: mypy --error-summary pkg-stubs/thing.pyi
[file pkg-stubs/__init__.pyi]
[file pkg-stubs/thing.pyi]
class Thing: ...
[out]
Success: no issues found in 1 source file
== Return code: 0
[case testStubsSubDirectory]
# cmd: mypy --error-summary src/pkg-stubs
[file src/pkg-stubs/__init__.pyi]
[file src/pkg-stubs/thing.pyi]
class Thing: ...
[out]
Success: no issues found in 2 source files
== Return code: 0
[case testStubsSubDirectoryFile]
# cmd: mypy --error-summary src/pkg-stubs/thing.pyi
[file src/pkg-stubs/__init__.pyi]
[file src/pkg-stubs/thing.pyi]
class Thing: ...
[out]
Success: no issues found in 1 source file
== Return code: 0
[case testBlocker]
# cmd: mypy pkg --error-summary --disable-error-code syntax
[file pkg/x.py]
public static void main(String[] args)
[file pkg/y.py]
x: str = 0
[out]
pkg/x.py:1: error: invalid syntax
Found 1 error in 1 file (errors prevented further checking)
== Return code: 2
[out version>=3.10]
pkg/x.py:1: error: invalid syntax. Perhaps you forgot a comma?
Found 1 error in 1 file (errors prevented further checking)
== Return code: 2
[out version>=3.10.3]
pkg/x.py:1: error: invalid syntax
Found 1 error in 1 file (errors prevented further checking)
== Return code: 2
[case testCmdlinePackageAndFile]
# cmd: mypy -p pkg file
[out]
usage: mypy [-h] [-v] [-V] [more options; see below]
[-m MODULE] [-p PACKAGE] [-c PROGRAM_TEXT] [files ...]
mypy: error: May only specify one of: module/package, files, or command.
== Return code: 2
[case testCmdlinePackageAndIniFiles]
# cmd: mypy -p pkg
[file mypy.ini]
\[mypy]
files=file
[file pkg.py]
x = 0 # type: str
[file file.py]
y = 0 # type: str
[out]
pkg.py:1: error: Incompatible types in assignment (expression has type "int", variable has type "str")
[case testCmdlineModuleAndIniFiles]
# cmd: mypy -m pkg
[file mypy.ini]
\[mypy]
files=file
[file pkg.py]
x = 0 # type: str
[file file.py]
y = 0 # type: str
[out]
pkg.py:1: error: Incompatible types in assignment (expression has type "int", variable has type "str")
[case testCmdlineNonInteractiveWithoutInstallTypes]
# cmd: mypy --non-interactive -m pkg
[out]
error: --non-interactive is only supported with --install-types
== Return code: 2
[case testCmdlineNonInteractiveInstallTypesNothingToDo]
# cmd: mypy --install-types --non-interactive -m pkg
[file pkg.py]
1()
[out]
pkg.py:1: error: "int" not callable
[case testCmdlineNonInteractiveInstallTypesNothingToDoNoError]
# cmd: mypy --install-types --non-interactive -m pkg
[file pkg.py]
1 + 2
[out]
[case testCmdlineNonInteractiveInstallTypesNoSitePackages]
# cmd: mypy --install-types --non-interactive --no-site-packages -m pkg
[out]
error: --install-types not supported without python executable or site packages
== Return code: 2
[case testCmdlineInteractiveInstallTypesNothingToDo]
# cmd: mypy --install-types -m pkg
[file pkg.py]
1()
[out]
pkg.py:1: error: "int" not callable
[case testCmdlineExclude]
# cmd: mypy --exclude abc .
[file abc/apkg.py]
1()
[file b/bpkg.py]
1()
[file c/cpkg.py]
1()
[out]
c/cpkg.py:1: error: "int" not callable
b/bpkg.py:1: error: "int" not callable
[case testCmdlineMultipleExclude]
# cmd: mypy --exclude abc --exclude b/ .
[file abc/apkg.py]
1()
[file b/bpkg.py]
1()
[file c/cpkg.py]
1()
[out]
c/cpkg.py:1: error: "int" not callable
[case testCmdlineCfgExclude]
# cmd: mypy .
[file mypy.ini]
\[mypy]
exclude = abc
[file abc/apkg.py]
1()
[file b/bpkg.py]
1()
[file c/cpkg.py]
1()
[out]
c/cpkg.py:1: error: "int" not callable
b/bpkg.py:1: error: "int" not callable
[case testCmdlineCfgMultipleExclude]
# cmd: mypy .
[file mypy.ini]
\[mypy]
exclude = (?x)(
^abc/
|^b/
)
[file abc/apkg.py]
1()
[file b/bpkg.py]
1()
[file c/cpkg.py]
1()
[out]
c/cpkg.py:1: error: "int" not callable
[case testCmdlineTimingStats]
# cmd: mypy --timing-stats timing.txt .
[file b/__init__.py]
[file b/c.py]
class C: pass
[outfile-re timing.txt]
.*
b \d+
b\.c \d+
.*
[case testCmdlineEnableIncompleteFeatures]
# cmd: mypy --enable-incomplete-features a.py
[file a.py]
pass
[out]
Warning: --enable-incomplete-features is deprecated, use --enable-incomplete-feature=FEATURE instead
== Return code: 0
[case testShadowTypingModuleEarlyLoad]
# cmd: mypy dir
[file dir/__init__.py]
from typing import Union
def foo(a: Union[int, str]) -> str:
return str
[file typing.py]
# Since this file will be picked by mypy itself, we need it to be a fully-working typing
# A bare minimum would be NamedTuple and TypedDict, which are used in runtime,
# everything else technically can be just mocked.
import sys
import os
del sys.modules["typing"]
path = sys.path
try:
sys.path.remove(os.getcwd())
except ValueError:
sys.path.remove("") # python 3.6
from typing import *
sys.path = path
[out]
mypy: "typing.py" shadows library module "typing"
note: A user-defined top-level module with name "typing" is not supported
== Return code: 2
[case testCustomTypeshedDirWithRelativePathDoesNotCrash]
# cmd: mypy --custom-typeshed-dir dir dir/typing.pyi
[file dir/stdlib/abc.pyi]
[file dir/stdlib/builtins.pyi]
[file dir/stdlib/sys.pyi]
[file dir/stdlib/types.pyi]
[file dir/stdlib/typing.pyi]
[file dir/stdlib/typing_extensions.pyi]
[file dir/stdlib/_typeshed.pyi]
[file dir/stdlib/_collections_abc.pyi]
[file dir/stdlib/collections/abc.pyi]
[file dir/stdlib/collections/__init__.pyi]
[file dir/stdlib/VERSIONS]
[out]
Failed to find builtin module mypy_extensions, perhaps typeshed is broken?
== Return code: 2
[case testRecursiveAliasesFlagDeprecated]
# cmd: mypy --enable-recursive-aliases a.py
[file a.py]
pass
[out]
Warning: --enable-recursive-aliases is deprecated; recursive types are enabled by default
== Return code: 0
[case testNotesOnlyResultInExitSuccess]
# cmd: mypy a.py
[file a.py]
def f():
x: int = "no"
[out]
a.py:2: note: By default the bodies of untyped functions are not checked, consider using --check-untyped-defs
== Return code: 0
[case testCustomTypeshedDirFilePassedExplicitly]
# cmd: mypy --custom-typeshed-dir dir m.py dir/stdlib/foo.pyi
[file m.py]
1()
[file dir/stdlib/abc.pyi]
1() # Errors are not reported from typeshed by default
[file dir/stdlib/builtins.pyi]
class object: pass
class str(object): pass
class int(object): pass
class list: pass
class dict: pass
[file dir/stdlib/sys.pyi]
[file dir/stdlib/types.pyi]
[file dir/stdlib/typing.pyi]
[file dir/stdlib/mypy_extensions.pyi]
[file dir/stdlib/typing_extensions.pyi]
[file dir/stdlib/_typeshed.pyi]
[file dir/stdlib/_collections_abc.pyi]
[file dir/stdlib/collections/abc.pyi]
[file dir/stdlib/collections/__init__.pyi]
[file dir/stdlib/foo.pyi]
1() # Errors are reported if the file was explicitly passed on the command line
[file dir/stdlib/VERSIONS]
[out]
dir/stdlib/foo.pyi:1: error: "int" not callable
m.py:1: error: "int" not callable
[case testFileInPythonPathPassedExplicitly1]
# cmd: mypy $CWD/pypath/foo.py
[file pypath/foo.py]
1()
[out]
pypath/foo.py:1: error: "int" not callable
[case testFileInPythonPathPassedExplicitly2]
# cmd: mypy pypath/foo.py
[file pypath/foo.py]
1()
[out]
pypath/foo.py:1: error: "int" not callable
[case testFileInPythonPathPassedExplicitly3]
# cmd: mypy -p foo
# cwd: pypath
[file pypath/foo/__init__.py]
1()
[file pypath/foo/m.py]
1()
[out]
foo/m.py:1: error: "int" not callable
foo/__init__.py:1: error: "int" not callable
[case testFileInPythonPathPassedExplicitly4]
# cmd: mypy -m foo
# cwd: pypath
[file pypath/foo.py]
1()
[out]
foo.py:1: error: "int" not callable
[case testFileInPythonPathPassedExplicitly5]
# cmd: mypy -m foo.m
# cwd: pypath
[file pypath/foo/__init__.py]
1() # TODO: Maybe this should generate errors as well? But how would we decide?
[file pypath/foo/m.py]
1()
[out]
foo/m.py:1: error: "int" not callable
[case testCmdlineCfgEnableErrorCodeTrailingComma]
# cmd: mypy .
[file mypy.ini]
\[mypy]
enable_error_code =
truthy-bool,
redundant-expr,
[out]
[case testCmdlineCfgDisableErrorCodeTrailingComma]
# cmd: mypy .
[file mypy.ini]
\[mypy]
disable_error_code =
misc,
override,
[out]
[case testCmdlineCfgAlwaysTrueTrailingComma]
# cmd: mypy .
[file mypy.ini]
\[mypy]
always_true =
MY_VAR,
[out]