mirror of
https://github.com/pre-commit/pre-commit.git
synced 2026-01-14 04:50:20 -06:00
Add types to pre-commit
This commit is contained in:
@@ -2,29 +2,40 @@ import contextlib
|
||||
import functools
|
||||
import os
|
||||
import sys
|
||||
from typing import Callable
|
||||
from typing import ContextManager
|
||||
from typing import Generator
|
||||
from typing import Optional
|
||||
from typing import Sequence
|
||||
from typing import Tuple
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import pre_commit.constants as C
|
||||
from pre_commit.envcontext import envcontext
|
||||
from pre_commit.envcontext import PatchesT
|
||||
from pre_commit.envcontext import UNSET
|
||||
from pre_commit.envcontext import Var
|
||||
from pre_commit.languages import helpers
|
||||
from pre_commit.parse_shebang import find_executable
|
||||
from pre_commit.prefix import Prefix
|
||||
from pre_commit.util import CalledProcessError
|
||||
from pre_commit.util import clean_path_on_failure
|
||||
from pre_commit.util import cmd_output
|
||||
from pre_commit.util import cmd_output_b
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from pre_commit.repository import Hook
|
||||
|
||||
ENVIRONMENT_DIR = 'py_env'
|
||||
|
||||
|
||||
def bin_dir(venv):
|
||||
def bin_dir(venv: str) -> str:
|
||||
"""On windows there's a different directory for the virtualenv"""
|
||||
bin_part = 'Scripts' if os.name == 'nt' else 'bin'
|
||||
return os.path.join(venv, bin_part)
|
||||
|
||||
|
||||
def get_env_patch(venv):
|
||||
def get_env_patch(venv: str) -> PatchesT:
|
||||
return (
|
||||
('PYTHONHOME', UNSET),
|
||||
('VIRTUAL_ENV', venv),
|
||||
@@ -32,7 +43,9 @@ def get_env_patch(venv):
|
||||
)
|
||||
|
||||
|
||||
def _find_by_py_launcher(version): # pragma: no cover (windows only)
|
||||
def _find_by_py_launcher(
|
||||
version: str,
|
||||
) -> Optional[str]: # pragma: no cover (windows only)
|
||||
if version.startswith('python'):
|
||||
try:
|
||||
return cmd_output(
|
||||
@@ -41,14 +54,16 @@ def _find_by_py_launcher(version): # pragma: no cover (windows only)
|
||||
)[1].strip()
|
||||
except CalledProcessError:
|
||||
pass
|
||||
return None
|
||||
|
||||
|
||||
def _find_by_sys_executable():
|
||||
def _norm(path):
|
||||
def _find_by_sys_executable() -> Optional[str]:
|
||||
def _norm(path: str) -> Optional[str]:
|
||||
_, exe = os.path.split(path.lower())
|
||||
exe, _, _ = exe.partition('.exe')
|
||||
if find_executable(exe) and exe not in {'python', 'pythonw'}:
|
||||
return exe
|
||||
return None
|
||||
|
||||
# On linux, I see these common sys.executables:
|
||||
#
|
||||
@@ -66,7 +81,7 @@ def _find_by_sys_executable():
|
||||
|
||||
|
||||
@functools.lru_cache(maxsize=1)
|
||||
def get_default_version(): # pragma: no cover (platform dependent)
|
||||
def get_default_version() -> str: # pragma: no cover (platform dependent)
|
||||
# First attempt from `sys.executable` (or the realpath)
|
||||
exe = _find_by_sys_executable()
|
||||
if exe:
|
||||
@@ -88,7 +103,7 @@ def get_default_version(): # pragma: no cover (platform dependent)
|
||||
return C.DEFAULT
|
||||
|
||||
|
||||
def _sys_executable_matches(version):
|
||||
def _sys_executable_matches(version: str) -> bool:
|
||||
if version == 'python':
|
||||
return True
|
||||
elif not version.startswith('python'):
|
||||
@@ -102,7 +117,7 @@ def _sys_executable_matches(version):
|
||||
return sys.version_info[:len(info)] == info
|
||||
|
||||
|
||||
def norm_version(version):
|
||||
def norm_version(version: str) -> str:
|
||||
# first see if our current executable is appropriate
|
||||
if _sys_executable_matches(version):
|
||||
return sys.executable
|
||||
@@ -126,14 +141,25 @@ def norm_version(version):
|
||||
return os.path.expanduser(version)
|
||||
|
||||
|
||||
def py_interface(_dir, _make_venv):
|
||||
def py_interface(
|
||||
_dir: str,
|
||||
_make_venv: Callable[[str, str], None],
|
||||
) -> Tuple[
|
||||
Callable[[Prefix, str], ContextManager[None]],
|
||||
Callable[[Prefix, str], bool],
|
||||
Callable[['Hook', Sequence[str], bool], Tuple[int, bytes]],
|
||||
Callable[[Prefix, str, Sequence[str]], None],
|
||||
]:
|
||||
@contextlib.contextmanager
|
||||
def in_env(prefix, language_version):
|
||||
def in_env(
|
||||
prefix: Prefix,
|
||||
language_version: str,
|
||||
) -> Generator[None, None, None]:
|
||||
envdir = prefix.path(helpers.environment_dir(_dir, language_version))
|
||||
with envcontext(get_env_patch(envdir)):
|
||||
yield
|
||||
|
||||
def healthy(prefix, language_version):
|
||||
def healthy(prefix: Prefix, language_version: str) -> bool:
|
||||
with in_env(prefix, language_version):
|
||||
retcode, _, _ = cmd_output_b(
|
||||
'python', '-c',
|
||||
@@ -143,11 +169,19 @@ def py_interface(_dir, _make_venv):
|
||||
)
|
||||
return retcode == 0
|
||||
|
||||
def run_hook(hook, file_args, color):
|
||||
def run_hook(
|
||||
hook: 'Hook',
|
||||
file_args: Sequence[str],
|
||||
color: bool,
|
||||
) -> Tuple[int, bytes]:
|
||||
with in_env(hook.prefix, hook.language_version):
|
||||
return helpers.run_xargs(hook, hook.cmd, file_args, color=color)
|
||||
|
||||
def install_environment(prefix, version, additional_dependencies):
|
||||
def install_environment(
|
||||
prefix: Prefix,
|
||||
version: str,
|
||||
additional_dependencies: Sequence[str],
|
||||
) -> None:
|
||||
additional_dependencies = tuple(additional_dependencies)
|
||||
directory = helpers.environment_dir(_dir, version)
|
||||
|
||||
@@ -166,7 +200,7 @@ def py_interface(_dir, _make_venv):
|
||||
return in_env, healthy, run_hook, install_environment
|
||||
|
||||
|
||||
def make_venv(envdir, python):
|
||||
def make_venv(envdir: str, python: str) -> None:
|
||||
env = dict(os.environ, VIRTUALENV_NO_DOWNLOAD='1')
|
||||
cmd = (sys.executable, '-mvirtualenv', envdir, '-p', python)
|
||||
cmd_output_b(*cmd, env=env, cwd='/')
|
||||
|
||||
Reference in New Issue
Block a user