[build-system] requires = [ # NOTE: this needs to be kept in sync with mypy-requirements.txt # and build-requirements.txt, because those are both needed for # self-typechecking :/ "setuptools >= 77.0.3", # the following is from mypy-requirements.txt/setup.py "typing_extensions>=4.6.0; python_version<'3.15'", "typing_extensions>=4.14.0; python_version>='3.15'", "mypy_extensions>=1.0.0", "pathspec>=1.0.0", "tomli>=1.1.0; python_version<'3.11'", "librt>=0.9.0; platform_python_implementation != 'PyPy'", # the following is from build-requirements.txt "types-psutil", "types-setuptools", ] build-backend = "setuptools.build_meta" [project] name = "mypy" description = "Optional static typing for Python" readme = {text = """ Mypy -- Optional Static Typing for Python ========================================= Add type annotations to your Python programs, and use mypy to type check them. Mypy is essentially a Python linter on steroids, and it can catch many programming errors by analyzing your program, without actually having to run it. Mypy has a powerful type system with features such as type inference, gradual typing, generics and union types. """, content-type = "text/x-rst"} authors = [{name = "Jukka Lehtosalo", email = "jukka.lehtosalo@iki.fi"}] license = "MIT" license-files = ["LICENSE", "mypy/typeshed/LICENSE"] classifiers = [ "Development Status :: 5 - Production/Stable", "Environment :: Console", "Intended Audience :: Developers", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.14", "Topic :: Software Development", "Typing :: Typed", ] requires-python = ">=3.10" dependencies = [ # When changing this, also update build-system.requires and mypy-requirements.txt "typing_extensions>=4.6.0; python_version<'3.15'", "typing_extensions>=4.14.0; python_version>='3.15'", "mypy_extensions>=1.0.0", "pathspec>=1.0.0", "tomli>=1.1.0; python_version<'3.11'", "librt>=0.9.0; platform_python_implementation != 'PyPy'", "ast-serialize>=0.2.0,<1.0.0", ] dynamic = ["version"] [project.optional-dependencies] dmypy = ["psutil>=4.0"] mypyc = ["setuptools>=50"] reports = ["lxml"] install-types = ["pip"] faster-cache = ["orjson"] native-parser = [] [project.urls] Homepage = "https://www.mypy-lang.org/" Documentation = "https://mypy.readthedocs.io/en/stable/index.html" Repository = "https://github.com/python/mypy" Changelog = "https://github.com/python/mypy/blob/master/CHANGELOG.md" Issues = "https://github.com/python/mypy/issues" [project.scripts] mypy = "mypy.__main__:console_entry" stubgen = "mypy.stubgen:main" stubtest = "mypy.stubtest:main" dmypy = "mypy.dmypy.client:console_entry" mypyc = "mypyc.__main__:main" [tool.setuptools.packages.find] include = ["mypy*", "mypyc*", "*__mypyc*"] exclude = ["mypyc.test-data*"] namespaces = false [tool.setuptools.package-data] mypy = [ "py.typed", "typeshed/**/*.py", "typeshed/**/*.pyi", "typeshed/stdlib/VERSIONS", "xml/*.xsd", "xml/*.xslt", "xml/*.css", ] [tool.setuptools.exclude-package-data] mypyc = [ "README.md", "doc/**", "external/**", "lib-rt/test_capi.cc", "lib-rt/setup.py", "test-data/**", ] [tool.black] line-length = 99 target-version = ["py310", "py311", "py312", "py313", "py314"] skip-magic-trailing-comma = true force-exclude = ''' ^/mypy/typeshed| ^/mypyc/test-data| ^/test-data ''' [tool.ruff] line-length = 99 target-version = "py310" fix = true extend-exclude = [ "@*", # Sphinx configuration is irrelevant "docs/source/conf.py", "mypyc/doc/conf.py", # tests have more relaxed styling requirements # fixtures have their own .pyi-specific configuration "test-data/*", "mypyc/test-data/*", # typeshed has its own .pyi-specific configuration "mypy/typeshed/*", ] [tool.ruff.lint] select = [ "E", # pycodestyle (error) "F", # pyflakes "W", # pycodestyle (warning) "B", # flake8-bugbear "I", # isort "N", # pep8-naming "PIE", # flake8-pie "PLE", # pylint error "RUF100", # Unused noqa comments "PGH004", # blanket noqa comments "UP", # pyupgrade "C4", # flake8-comprehensions "SIM101", # merge duplicate isinstance calls "SIM201", "SIM202", "SIM222", "SIM223", # flake8-simplify "FURB168", # Prefer is operator over isinstance for None checks "FURB169", # Do not use is comparison with type(None). Use None "FURB187", # avoid list reverse copy "FURB188", # use str.remove(pre|suf)fix "ISC001", # implicitly concatenated string "RET501", "RET502", # better return None handling ] ignore = [ "B007", # Loop control variable not used within the loop body. "B011", # Don't use assert False "B023", # Function definition does not bind loop variable "B905", # zip-without-explicit-strict "E2", # conflicts with black "E402", # module level import not at top of file "E501", # conflicts with black "E721", # Use `is` and `is not` for type comparisons, or `isinstance()` for isinstance checks "E731", # Do not assign a `lambda` expression, use a `def` "E741", # Ambiguous variable name "N818", # Exception should be named with an Error suffix "N806", # UPPER_CASE used for constant local variables "UP031", # Use format specifiers instead of percent format "UP032", # 'f-string always preferable to format' is controversial "C409", # https://github.com/astral-sh/ruff/issues/12912 "C420", # reads a little worse. fromkeys predates dict comprehensions "C416", # There are a few cases where it's nice to have names for the dict items "PIE790", # there's nothing wrong with pass ] unfixable = [ "F841", # unused variable. ruff keeps the call, but mostly we want to get rid of it all "F601", # automatic fix might obscure issue "F602", # automatic fix might obscure issue "B018", # automatic fix might obscure issue "UP036", # sometimes it's better to just noqa this "SIM222", # automatic fix might obscure issue "SIM223", # automatic fix might obscure issue ] [tool.ruff.lint.per-file-ignores] # Mixed case variable and function names. "mypy/fastparse.py" = ["N802", "N816"] [tool.ruff.lint.isort] combine-as-imports = true extra-standard-library = ["typing_extensions"] [tool.check-manifest] ignore = ["**/.readthedocs.yaml"] [tool.pytest.ini_options] minversion = "7.0.0" testpaths = ["mypy/test", "mypyc/test"] python_files = 'test*.py' # Where do the test cases come from? We provide our own collection # logic by implementing `pytest_pycollect_makeitem` in mypy.test.data; # the test files import that module, and pytest sees the magic name # and invokes it at the relevant moment. See # https://doc.pytest.org/en/latest/how-to/writing_plugins.html#collection-hooks # Both our plugin and unittest provide their own collection logic, # So we can disable the default python collector by giving it empty # patterns to search for. # Note that unittest requires that no "Test*" classes exist. python_classes = [] python_functions = [] # always run in parallel (requires pytest-xdist, see test-requirements.txt) # and enable strict mode: require all markers # to be defined and raise on invalid config values addopts = "-nauto --strict-markers --strict-config" # treat xpasses as test failures so they get converted to regular tests as soon as possible xfail_strict = true # Force warnings as errors filterwarnings = [ "error", ] [tool.coverage.run] branch = true source = ["mypy"] parallel = true [tool.coverage.report] show_missing = true skip_covered = true omit = ['mypy/test/*'] exclude_lines = [ '\#\s*pragma: no cover', '^\s*raise AssertionError\b', '^\s*raise NotImplementedError\b', '^\s*return NotImplemented\b', '^\s*raise$', '^assert False\b', '''^if __name__ == ['"]__main__['"]:$''', ]