forked from pandas-dev/pandas
-
Notifications
You must be signed in to change notification settings - Fork 0
/
sync_flake8_versions.py
145 lines (114 loc) · 4.15 KB
/
sync_flake8_versions.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
"""
Check that the flake8 (and pandas-dev-flaker) pins are the same in:
- environment.yml
- .pre-commit-config.yaml, in the flake8 hook
- .pre-commit-config.yaml, in the additional dependencies of the yesqa hook
The flake8 hook revision in .pre-commit-config.yaml is taken as the reference revision.
Usage: either
- ``python scripts/sync_flake8_versions.py``, or
- ``pre-commit run sync-flake8-versions --all-files``.
"""
from __future__ import annotations
from dataclasses import (
dataclass,
replace,
)
import sys
from typing import (
Any,
Mapping,
Sequence,
TypeVar,
)
import yaml
@dataclass
class Revision:
name: str
compare: str
version: str
@dataclass
class Revisions:
name: str
pre_commit: Revision | None = None
yesqa: Revision | None = None
environment: Revision | None = None
YamlMapping = Mapping[str, Any]
Repo = TypeVar("Repo", bound=YamlMapping)
COMPARE = ("<=", "==", ">=", "<", ">", "=")
def _get_repo_hook(repos: Sequence[Repo], hook_name: str) -> tuple[Repo, YamlMapping]:
for repo in repos:
for hook in repo["hooks"]:
if hook["id"] == hook_name:
return repo, hook
else: # pragma: no cover
raise RuntimeError(f"Repo with hook {hook_name} not found")
def _conda_to_pip_compat(dep):
if dep.compare == "=":
return replace(dep, compare="==")
else:
return dep
def _validate_additional_dependencies(
flake8_additional_dependencies,
environment_additional_dependencies,
) -> None:
for dep in flake8_additional_dependencies:
if dep not in environment_additional_dependencies:
sys.stdout.write(
f"Mismatch of '{dep.name}' version between 'environment.yml' "
"and additional dependencies of 'flake8' in '.pre-commit-config.yaml'\n"
)
sys.exit(1)
def _validate_revisions(revisions):
if revisions.environment != revisions.pre_commit:
sys.stdout.write(
f"{revisions.name} in 'environment.yml' does not "
"match in 'flake8' from 'pre-commit'\n"
)
sys.exit(1)
def _process_dependencies(deps):
for dep in deps:
if isinstance(dep, str):
for compare in COMPARE:
if compare in dep:
pkg, rev = dep.split(compare, maxsplit=1)
yield _conda_to_pip_compat(Revision(pkg, compare, rev))
break
else:
yield from _process_dependencies(dep["pip"])
def get_revisions(
precommit_config: YamlMapping, environment: YamlMapping
) -> tuple[Revisions, Revisions]:
flake8_revisions = Revisions(name="flake8")
pandas_dev_flaker_revisions = Revisions(name="pandas-dev-flaker")
repos = precommit_config["repos"]
flake8_repo, flake8_hook = _get_repo_hook(repos, "flake8")
flake8_revisions.pre_commit = Revision("flake8", "==", flake8_repo["rev"])
flake8_additional_dependencies = []
for dep in _process_dependencies(flake8_hook.get("additional_dependencies", [])):
if dep.name == "pandas-dev-flaker":
pandas_dev_flaker_revisions.pre_commit = dep
else:
flake8_additional_dependencies.append(dep)
environment_dependencies = environment["dependencies"]
environment_additional_dependencies = []
for dep in _process_dependencies(environment_dependencies):
if dep.name == "flake8":
flake8_revisions.environment = dep
environment_additional_dependencies.append(dep)
elif dep.name == "pandas-dev-flaker":
pandas_dev_flaker_revisions.environment = dep
else:
environment_additional_dependencies.append(dep)
_validate_additional_dependencies(
flake8_additional_dependencies,
environment_additional_dependencies,
)
for revisions in flake8_revisions, pandas_dev_flaker_revisions:
_validate_revisions(revisions)
if __name__ == "__main__":
with open(".pre-commit-config.yaml") as fd:
precommit_config = yaml.safe_load(fd)
with open("environment.yml") as fd:
environment = yaml.safe_load(fd)
get_revisions(precommit_config, environment)
sys.exit(0)