diff --git a/nox/_decorators.py b/nox/_decorators.py index 153e331b..f94cef9a 100644 --- a/nox/_decorators.py +++ b/nox/_decorators.py @@ -18,7 +18,7 @@ def __new__( return cast("FunctionDecorator", functools.wraps(func)(obj)) -def _copy_func(src: Callable, name: str = None) -> Callable: +def _copy_func(src: Callable, name: Optional[str] = None) -> Callable: dst = types.FunctionType( src.__code__, src.__globals__, # type: ignore @@ -41,7 +41,7 @@ def __init__( name: Optional[str] = None, venv_backend: Any = None, venv_params: Any = None, - should_warn: Dict[str, Any] = None, + should_warn: Optional[Dict[str, Any]] = None, ): self.func = func self.python = python @@ -53,7 +53,7 @@ def __init__( def __call__(self, *args: Any, **kwargs: Any) -> Any: return self.func(*args, **kwargs) - def copy(self, name: str = None) -> "Func": + def copy(self, name: Optional[str] = None) -> "Func": return Func( _copy_func(self.func, name), self.python, diff --git a/nox/_option_set.py b/nox/_option_set.py index 4bcbb357..0da46fb0 100644 --- a/nox/_option_set.py +++ b/nox/_option_set.py @@ -20,7 +20,8 @@ import argparse import collections import functools -from argparse import ArgumentError, ArgumentParser, Namespace +from argparse import ArgumentError as ArgumentError +from argparse import ArgumentParser, Namespace from typing import Any, Callable, List, Optional, Tuple, Union import argcomplete diff --git a/nox/_version.py b/nox/_version.py index 740b7fd3..2e247534 100644 --- a/nox/_version.py +++ b/nox/_version.py @@ -36,7 +36,7 @@ class InvalidVersionSpecifier(Exception): def get_nox_version() -> str: """Return the version of the installed Nox package.""" - return metadata.version("nox") + return metadata.version("nox") # type: ignore def _parse_string_constant(node: ast.AST) -> Optional[str]: # pragma: no cover diff --git a/nox/command.py b/nox/command.py index 8d915054..2c3f1095 100644 --- a/nox/command.py +++ b/nox/command.py @@ -21,11 +21,16 @@ from nox.logger import logger from nox.popen import popen +if sys.version_info < (3, 8): # pragma: no cover + from typing_extensions import Literal +else: # pragma: no cover + from typing import Literal + class CommandFailed(Exception): """Raised when an executed command returns a non-success status code.""" - def __init__(self, reason: str = None) -> None: + def __init__(self, reason: Optional[str] = None) -> None: super(CommandFailed, self).__init__(reason) self.reason = reason @@ -70,7 +75,7 @@ def run( paths: Optional[List[str]] = None, success_codes: Optional[Iterable[int]] = None, log: bool = True, - external: bool = False, + external: Union[Literal["error"], bool] = False, **popen_kws: Any ) -> Union[str, bool]: """Run a command-line program.""" diff --git a/nox/popen.py b/nox/popen.py index 9bd1c115..010dd321 100644 --- a/nox/popen.py +++ b/nox/popen.py @@ -16,7 +16,7 @@ import locale import subprocess import sys -from typing import IO, Mapping, Sequence, Tuple, Union +from typing import IO, Mapping, Optional, Sequence, Tuple, Union def shutdown_process(proc: subprocess.Popen) -> Tuple[bytes, bytes]: @@ -54,9 +54,9 @@ def decode_output(output: bytes) -> str: def popen( args: Sequence[str], - env: Mapping[str, str] = None, + env: Optional[Mapping[str, str]] = None, silent: bool = False, - stdout: Union[int, IO] = None, + stdout: Optional[Union[int, IO]] = None, stderr: Union[int, IO] = subprocess.STDOUT, ) -> Tuple[int, str]: if silent and stdout is not None: diff --git a/nox/sessions.py b/nox/sessions.py index cabaae12..0cdbe78e 100644 --- a/nox/sessions.py +++ b/nox/sessions.py @@ -211,7 +211,7 @@ def _run_func( raise nox.command.CommandFailed() def run( - self, *args: str, env: Mapping[str, str] = None, **kwargs: Any + self, *args: str, env: Optional[Mapping[str, str]] = None, **kwargs: Any ) -> Optional[Any]: """Run a command. @@ -269,7 +269,7 @@ def run( return self._run(*args, env=env, **kwargs) def run_always( - self, *args: str, env: Mapping[str, str] = None, **kwargs: Any + self, *args: str, env: Optional[Mapping[str, str]] = None, **kwargs: Any ) -> Optional[Any]: """Run a command **always**. @@ -311,7 +311,9 @@ def run_always( return self._run(*args, env=env, **kwargs) - def _run(self, *args: str, env: Mapping[str, str] = None, **kwargs: Any) -> Any: + def _run( + self, *args: str, env: Optional[Mapping[str, str]] = None, **kwargs: Any + ) -> Any: """Like run(), except that it runs even if --install-only is provided.""" # Legacy support - run a function given. if callable(args[0]): diff --git a/nox/tasks.py b/nox/tasks.py index c23b118d..60b5f9a6 100644 --- a/nox/tasks.py +++ b/nox/tasks.py @@ -63,7 +63,7 @@ def load_nox_module(global_config: Namespace) -> Union[types.ModuleType, int]: os.chdir(os.path.realpath(os.path.dirname(global_config.noxfile))) return importlib.machinery.SourceFileLoader( "user_nox_module", global_config.noxfile - ).load_module() # type: ignore + ).load_module() except (VersionCheckFailed, InvalidVersionSpecifier) as error: logger.error(str(error)) diff --git a/nox/virtualenv.py b/nox/virtualenv.py index 13f3fbc3..a6bf8448 100644 --- a/nox/virtualenv.py +++ b/nox/virtualenv.py @@ -53,7 +53,9 @@ class ProcessEnv: # Special programs that aren't included in the environment. allowed_globals = () # type: _typing.ClassVar[Tuple[Any, ...]] - def __init__(self, bin_paths: None = None, env: Mapping[str, str] = None) -> None: + def __init__( + self, bin_paths: None = None, env: Optional[Mapping[str, str]] = None + ) -> None: self._bin_paths = bin_paths self.env = os.environ.copy() self._reused = False diff --git a/noxfile.py b/noxfile.py index 9e247bb2..58967c2c 100644 --- a/noxfile.py +++ b/noxfile.py @@ -86,15 +86,16 @@ def blacken(session): @nox.session(python="3.8") def lint(session): - session.install("flake8==3.9.2", "black==21.5b2", "isort==5.8.0", "mypy==0.812") - session.run( - "mypy", - "--config-file=", - "--disallow-untyped-defs", - "--warn-unused-ignores", - "--ignore-missing-imports", - "nox", + session.install( + "flake8==3.9.2", + "black==21.6b0", + "isort==5.8.0", + "mypy==0.902", + "types-jinja2", + "packaging", + "importlib_metadata", ) + session.run("mypy") files = ["nox", "tests", "noxfile.py", "setup.py"] session.run("black", "--check", *files) session.run("isort", "--check", *files) diff --git a/pyproject.toml b/pyproject.toml index f6c16894..90bcd11d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,3 +4,26 @@ requires = [ "wheel", ] build-backend = "setuptools.build_meta" + + +[tool.mypy] +files = ["nox"] +python_version = "3.6" +warn_unused_configs = true +disallow_any_generics = false +disallow_subclassing_any = false +disallow_untyped_calls = true +disallow_untyped_defs = true +disallow_incomplete_defs = true +check_untyped_defs = true +disallow_untyped_decorators = true +no_implicit_optional = true +warn_redundant_casts = true +warn_unused_ignores = true +warn_return_any = false +no_implicit_reexport = true +strict_equality = true + +[[tool.mypy.overrides]] +module = [ "argcomplete", "colorlog.*", "py", "tox.*" ] +ignore_missing_imports = true \ No newline at end of file diff --git a/setup.py b/setup.py index 28d99cd4..92e3d6a1 100644 --- a/setup.py +++ b/setup.py @@ -54,6 +54,7 @@ "colorlog>=2.6.1,<7.0.0", "packaging>=20.9", "py>=1.4.0,<2.0.0", + "typing_extensions>=3.7.4; python_version < '3.8'", "virtualenv>=14.0.0", "importlib_metadata; python_version < '3.8'", ],