Skip to content

Commit d33df92

Browse files
authored
Merge pull request pre-commit#2602 from pre-commit/mypy-modules-as-protocols
use modules as protocols
2 parents def3fa3 + 40e69ce commit d33df92

File tree

3 files changed

+60
-70
lines changed

3 files changed

+60
-70
lines changed

pre_commit/languages/all.py

Lines changed: 50 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
from __future__ import annotations
22

3-
from typing import Callable
4-
from typing import NamedTuple
3+
from typing import Protocol
54
from typing import Sequence
65

76
from pre_commit.hook import Hook
@@ -27,44 +26,61 @@
2726
from pre_commit.prefix import Prefix
2827

2928

30-
class Language(NamedTuple):
31-
name: str
29+
class Language(Protocol):
3230
# Use `None` for no installation / environment
33-
ENVIRONMENT_DIR: str | None
31+
@property
32+
def ENVIRONMENT_DIR(self) -> str | None: ...
3433
# return a value to replace `'default` for `language_version`
35-
get_default_version: Callable[[], str]
34+
def get_default_version(self) -> str: ...
35+
3636
# return whether the environment is healthy (or should be rebuilt)
37-
health_check: Callable[[Prefix, str], str | None]
37+
def health_check(
38+
self,
39+
prefix: Prefix,
40+
language_version: str,
41+
) -> str | None:
42+
...
43+
3844
# install a repository for the given language and language_version
39-
install_environment: Callable[[Prefix, str, Sequence[str]], None]
45+
def install_environment(
46+
self,
47+
prefix: Prefix,
48+
version: str,
49+
additional_dependencies: Sequence[str],
50+
) -> None:
51+
...
52+
4053
# execute a hook and return the exit code and output
41-
run_hook: Callable[[Hook, Sequence[str], bool], tuple[int, bytes]]
54+
def run_hook(
55+
self,
56+
hook: Hook,
57+
file_args: Sequence[str],
58+
color: bool,
59+
) -> tuple[int, bytes]:
60+
...
4261

4362

44-
# TODO: back to modules + Protocol: https://github.com/python/mypy/issues/5018
45-
languages = {
46-
# BEGIN GENERATED (testing/gen-languages-all)
47-
'conda': Language(name='conda', ENVIRONMENT_DIR=conda.ENVIRONMENT_DIR, get_default_version=conda.get_default_version, health_check=conda.health_check, install_environment=conda.install_environment, run_hook=conda.run_hook), # noqa: E501
48-
'coursier': Language(name='coursier', ENVIRONMENT_DIR=coursier.ENVIRONMENT_DIR, get_default_version=coursier.get_default_version, health_check=coursier.health_check, install_environment=coursier.install_environment, run_hook=coursier.run_hook), # noqa: E501
49-
'dart': Language(name='dart', ENVIRONMENT_DIR=dart.ENVIRONMENT_DIR, get_default_version=dart.get_default_version, health_check=dart.health_check, install_environment=dart.install_environment, run_hook=dart.run_hook), # noqa: E501
50-
'docker': Language(name='docker', ENVIRONMENT_DIR=docker.ENVIRONMENT_DIR, get_default_version=docker.get_default_version, health_check=docker.health_check, install_environment=docker.install_environment, run_hook=docker.run_hook), # noqa: E501
51-
'docker_image': Language(name='docker_image', ENVIRONMENT_DIR=docker_image.ENVIRONMENT_DIR, get_default_version=docker_image.get_default_version, health_check=docker_image.health_check, install_environment=docker_image.install_environment, run_hook=docker_image.run_hook), # noqa: E501
52-
'dotnet': Language(name='dotnet', ENVIRONMENT_DIR=dotnet.ENVIRONMENT_DIR, get_default_version=dotnet.get_default_version, health_check=dotnet.health_check, install_environment=dotnet.install_environment, run_hook=dotnet.run_hook), # noqa: E501
53-
'fail': Language(name='fail', ENVIRONMENT_DIR=fail.ENVIRONMENT_DIR, get_default_version=fail.get_default_version, health_check=fail.health_check, install_environment=fail.install_environment, run_hook=fail.run_hook), # noqa: E501
54-
'golang': Language(name='golang', ENVIRONMENT_DIR=golang.ENVIRONMENT_DIR, get_default_version=golang.get_default_version, health_check=golang.health_check, install_environment=golang.install_environment, run_hook=golang.run_hook), # noqa: E501
55-
'lua': Language(name='lua', ENVIRONMENT_DIR=lua.ENVIRONMENT_DIR, get_default_version=lua.get_default_version, health_check=lua.health_check, install_environment=lua.install_environment, run_hook=lua.run_hook), # noqa: E501
56-
'node': Language(name='node', ENVIRONMENT_DIR=node.ENVIRONMENT_DIR, get_default_version=node.get_default_version, health_check=node.health_check, install_environment=node.install_environment, run_hook=node.run_hook), # noqa: E501
57-
'perl': Language(name='perl', ENVIRONMENT_DIR=perl.ENVIRONMENT_DIR, get_default_version=perl.get_default_version, health_check=perl.health_check, install_environment=perl.install_environment, run_hook=perl.run_hook), # noqa: E501
58-
'pygrep': Language(name='pygrep', ENVIRONMENT_DIR=pygrep.ENVIRONMENT_DIR, get_default_version=pygrep.get_default_version, health_check=pygrep.health_check, install_environment=pygrep.install_environment, run_hook=pygrep.run_hook), # noqa: E501
59-
'python': Language(name='python', ENVIRONMENT_DIR=python.ENVIRONMENT_DIR, get_default_version=python.get_default_version, health_check=python.health_check, install_environment=python.install_environment, run_hook=python.run_hook), # noqa: E501
60-
'r': Language(name='r', ENVIRONMENT_DIR=r.ENVIRONMENT_DIR, get_default_version=r.get_default_version, health_check=r.health_check, install_environment=r.install_environment, run_hook=r.run_hook), # noqa: E501
61-
'ruby': Language(name='ruby', ENVIRONMENT_DIR=ruby.ENVIRONMENT_DIR, get_default_version=ruby.get_default_version, health_check=ruby.health_check, install_environment=ruby.install_environment, run_hook=ruby.run_hook), # noqa: E501
62-
'rust': Language(name='rust', ENVIRONMENT_DIR=rust.ENVIRONMENT_DIR, get_default_version=rust.get_default_version, health_check=rust.health_check, install_environment=rust.install_environment, run_hook=rust.run_hook), # noqa: E501
63-
'script': Language(name='script', ENVIRONMENT_DIR=script.ENVIRONMENT_DIR, get_default_version=script.get_default_version, health_check=script.health_check, install_environment=script.install_environment, run_hook=script.run_hook), # noqa: E501
64-
'swift': Language(name='swift', ENVIRONMENT_DIR=swift.ENVIRONMENT_DIR, get_default_version=swift.get_default_version, health_check=swift.health_check, install_environment=swift.install_environment, run_hook=swift.run_hook), # noqa: E501
65-
'system': Language(name='system', ENVIRONMENT_DIR=system.ENVIRONMENT_DIR, get_default_version=system.get_default_version, health_check=system.health_check, install_environment=system.install_environment, run_hook=system.run_hook), # noqa: E501
66-
# END GENERATED
63+
languages: dict[str, Language] = {
64+
'conda': conda,
65+
'coursier': coursier,
66+
'dart': dart,
67+
'docker': docker,
68+
'docker_image': docker_image,
69+
'dotnet': dotnet,
70+
'fail': fail,
71+
'golang': golang,
72+
'lua': lua,
73+
'node': node,
74+
'perl': perl,
75+
'pygrep': pygrep,
76+
'python': python,
77+
'r': r,
78+
'ruby': ruby,
79+
'rust': rust,
80+
'script': script,
81+
'swift': swift,
82+
'system': system,
83+
# TODO: fully deprecate `python_venv`
84+
'python_venv': python,
6785
}
68-
# TODO: fully deprecate `python_venv`
69-
languages['python_venv'] = languages['python']
7086
all_languages = sorted(languages)

testing/gen-languages-all

Lines changed: 0 additions & 30 deletions
This file was deleted.

tests/repository_test.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -133,9 +133,11 @@ def test_python_hook(tempdir_factory, store):
133133
def test_python_hook_default_version(tempdir_factory, store):
134134
# make sure that this continues to work for platforms where default
135135
# language detection does not work
136-
returns_default = mock.Mock(return_value=C.DEFAULT)
137-
lang = languages['python']._replace(get_default_version=returns_default)
138-
with mock.patch.dict(languages, python=lang):
136+
with mock.patch.object(
137+
python,
138+
'get_default_version',
139+
return_value=C.DEFAULT,
140+
):
139141
test_python_hook(tempdir_factory, store)
140142

141143

@@ -247,9 +249,11 @@ def test_run_a_node_hook(tempdir_factory, store):
247249
def test_run_a_node_hook_default_version(tempdir_factory, store):
248250
# make sure that this continues to work for platforms where node is not
249251
# installed at the system
250-
returns_default = mock.Mock(return_value=C.DEFAULT)
251-
lang = languages['node']._replace(get_default_version=returns_default)
252-
with mock.patch.dict(languages, node=lang):
252+
with mock.patch.object(
253+
node,
254+
'get_default_version',
255+
return_value=C.DEFAULT,
256+
):
253257
test_run_a_node_hook(tempdir_factory, store)
254258

255259

0 commit comments

Comments
 (0)