Skip to content

Commit 224b7bc

Browse files
authored
Initial implementation (#1)
1 parent d4f1eeb commit 224b7bc

12 files changed

Lines changed: 426 additions & 0 deletions

.github/workflows/main.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
name: main
2+
3+
on:
4+
pull_request:
5+
push:
6+
branches: [master]
7+
8+
jobs:
9+
main:
10+
uses: asottile/workflows/.github/workflows/tox.yml@v1.5.0
11+
with:
12+
env: '["py38", "py39", "py310", "py311", "py312", "py313", "pypy3"]'
13+
main-win:
14+
uses: asottile/workflows/.github/workflows/tox.yml@v1.5.0
15+
with:
16+
env: '["py38"]'
17+
os: windows-latest
18+
arch: '["x64", "x86"]'

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
*.egg-info
2+
*.pyc
3+
.vscode/
4+
/.coverage
5+
/.tox
6+
venv/

.pre-commit-config.yaml

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
repos:
2+
- repo: https://github.com/pre-commit/pre-commit-hooks
3+
rev: v4.4.0
4+
hooks:
5+
- id: check-docstring-first
6+
- id: debug-statements
7+
- id: end-of-file-fixer
8+
- id: trailing-whitespace
9+
- repo: https://github.com/asottile/setup-cfg-fmt
10+
rev: v2.4.0
11+
hooks:
12+
- id: setup-cfg-fmt
13+
args: ['--min-py-version', '3.8']
14+
- repo: https://github.com/asottile/reorder-python-imports
15+
rev: v3.10.0
16+
hooks:
17+
- id: reorder-python-imports
18+
args: [--py38-plus, --add-import, 'from __future__ import annotations']
19+
- repo: https://github.com/asottile/pyupgrade
20+
rev: v3.9.0
21+
hooks:
22+
- id: pyupgrade
23+
args: [--py38-plus]
24+
- repo: https://github.com/hakancelikdev/unimport
25+
rev: 1.0.0
26+
hooks:
27+
- id: unimport
28+
- repo: https://github.com/mxr/unkey
29+
rev: v0.0.1
30+
hooks:
31+
- id: unkey
32+
- repo: https://github.com/psf/black
33+
rev: 23.7.0
34+
hooks:
35+
- id: black
36+
- repo: https://github.com/PyCQA/flake8
37+
rev: 6.0.0
38+
hooks:
39+
- id: flake8
40+
additional_dependencies:
41+
- flake8-bugbear==23.7.10
42+
- flake8-builtins==2.1.0
43+
- flake8-comprehensions==3.14.0
44+
- flake8-typing-imports==1.14.0
45+
- flake8_simplify==0.20.0
46+
- repo: https://github.com/asottile/yesqa
47+
rev: v1.5.0
48+
hooks:
49+
- id: yesqa
50+
additional_dependencies:
51+
- flake8==6.0.0
52+
- flake8-bugbear==23.7.10
53+
- flake8-builtins==2.1.0
54+
- flake8-comprehensions==3.14.0
55+
- flake8-typing-imports==1.14.0
56+
- flake8_simplify==0.20.0
57+
- repo: https://github.com/pre-commit/mirrors-mypy
58+
rev: v1.4.1
59+
hooks:
60+
- id: mypy

.pre-commit-hooks.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
- id: sync-pre-commit-deps
2+
name: sync-pre-commit-deps
3+
description: Sync pre-commit hook dependencies based on other installed hooks
4+
entry: sync-pre-commit-deps
5+
language: python
6+
language_version: python3
7+
files: '^\.pre-commit-config.yaml$'

README.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
sync-pre-commit-deps
2+
====================
3+
4+
Sync pre-commit hook dependencies based on other installed hooks
5+
6+
## install (standalone)
7+
8+
```bash
9+
pip install sync-pre-commit-deps
10+
```
11+
12+
## install as a pre-commit hook (recommended)
13+
14+
See [pre-commit](https://github.com/pre-commit/pre-commit) for instructions
15+
16+
Sample `.pre-commit-config.yaml`:
17+
18+
```yaml
19+
- repo: https://github.com/mxr/sync-pre-commit-deps
20+
rev: v0.0.1
21+
hooks:
22+
- id: sync-pre-commit-deps
23+
```
24+
25+
## cli
26+
27+
```console
28+
$ sync-pre-commit-deps path/to/.pre-commit-config.yaml
29+
```
30+
31+
## what it does
32+
33+
Ensures tools which declare `flake8` and `black` as additional dependencies will have those versions synced with the `flake8` and `black` versions in the rest of the config. For example, `flake8` under `yesqa` is updated from `5.0.0` to `6.0.0`.
34+
35+
```diff
36+
repos:
37+
- repo: https://github.com/PyCQA/flake8
38+
rev: 6.0.0
39+
hooks:
40+
- id: flake8
41+
- repo: https://github.com/asottile/yesqa
42+
rev: v1.5.0
43+
hooks:
44+
- id: yesqa
45+
additional_dependencies:
46+
- - flake8==5.0.0
47+
+ - flake8==6.0.0
48+
```

requirements-dev.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
covdefaults
2+
coverage
3+
pytest

setup.cfg

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
[metadata]
2+
name = sync_pre_commit_deps
3+
version = 0.0.1
4+
description = apply a consistent format to `setup.cfg` files
5+
long_description = file: README.md
6+
long_description_content_type = text/markdown
7+
url = https://github.com/mxr/sync-pre-commit-deps
8+
author = Max R
9+
author_email = maxr@outlook.com
10+
license = MIT
11+
license_files = LICENSE
12+
classifiers =
13+
License :: OSI Approved :: MIT License
14+
Programming Language :: Python :: 3
15+
Programming Language :: Python :: 3 :: Only
16+
Programming Language :: Python :: Implementation :: CPython
17+
Programming Language :: Python :: Implementation :: PyPy
18+
19+
[options]
20+
py_modules = sync_pre_commit_deps
21+
install_requires =
22+
ruamel.yaml>=0.17
23+
python_requires = >=3.8
24+
25+
[options.entry_points]
26+
console_scripts =
27+
sync-pre-commit-deps=sync_pre_commit_deps:main
28+
29+
[bdist_wheel]
30+
universal = True
31+
32+
[coverage:run]
33+
plugins = covdefaults
34+
35+
[flake8]
36+
max-line-length = 88
37+
extend-ignore = E203
38+
min_python_version = 3.8
39+
40+
[mypy]
41+
check_untyped_defs = true
42+
disallow_any_generics = true
43+
disallow_incomplete_defs = true
44+
disallow_untyped_defs = true
45+
warn_redundant_casts = true
46+
warn_unused_ignores = true
47+
48+
[mypy-testing.*]
49+
disallow_untyped_defs = false
50+
51+
[mypy-tests.*]
52+
disallow_untyped_defs = false

setup.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from __future__ import annotations
2+
3+
from setuptools import setup
4+
5+
setup()

sync_pre_commit_deps.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
from __future__ import annotations
2+
3+
import argparse
4+
from collections.abc import Sequence
5+
6+
import ruamel.yaml
7+
8+
SUPPORTED = frozenset(
9+
(
10+
"black",
11+
"flake8",
12+
)
13+
)
14+
15+
16+
def main(argv: Sequence[str] | None = None) -> int:
17+
parser = argparse.ArgumentParser()
18+
parser.add_argument("filename", default=".pre-commit-config.yaml")
19+
20+
args = parser.parse_args(argv)
21+
filename: str = args.filename
22+
23+
# match pre-commit config as documented
24+
# TODO - support round-tripping
25+
yaml = ruamel.yaml.YAML()
26+
yaml.preserve_quotes = True
27+
yaml.indent(mapping=4, sequence=4)
28+
29+
with open(filename) as f:
30+
loaded = yaml.load(f)
31+
32+
# TODO - validate schema?
33+
versions = {}
34+
for repo in loaded["repos"]:
35+
for hook in repo["hooks"]:
36+
if (hid := hook["id"]) in SUPPORTED:
37+
versions[hid] = repo["rev"]
38+
39+
updated = []
40+
for repo in loaded["repos"]:
41+
for hook in repo["hooks"]:
42+
for i, dep in enumerate(hook.get("additional_dependencies", ())):
43+
name, _, cur_version = dep.partition("==")
44+
target_version = versions.get(name, cur_version)
45+
if target_version != cur_version:
46+
hook["additional_dependencies"][i] = f"{name}=={target_version}"
47+
updated.append((hook["id"], name))
48+
49+
if updated:
50+
print(f"Writing updates to {filename}:")
51+
for hid, name in updated:
52+
print(f"\tSetting {hid!r} dependency {name!r} to {versions[name]}")
53+
54+
with open(filename, "w+") as f:
55+
yaml.dump(loaded, f)
56+
return 1
57+
58+
return 0
59+
60+
61+
if __name__ == "__main__":
62+
raise SystemExit(main())

tests/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)