-
Notifications
You must be signed in to change notification settings - Fork 40
/
update-meta.py
118 lines (97 loc) · 3.66 KB
/
update-meta.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
# This file is part of the Indico plugins.
# Copyright (C) 2002 - 2024 CERN
#
# The Indico plugins are free software; you can redistribute
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
import difflib
import errno
import os
import sys
from collections import defaultdict
from pathlib import Path
import click
import tomlkit
import yaml
from packaging.version import Version
from pygments import highlight
from pygments.formatters.terminal256 import Terminal256Formatter
from pygments.lexers.diff import DiffLexer
START_MARKER = '# BEGIN GENERATED REQUIREMENTS'
END_MARKER = '# END GENERATED REQUIREMENTS'
def _find_plugins():
subdirs = sorted(Path(x) for x in next(os.walk('.'))[1]
if x[0] != '.' and x != '_meta' and os.path.exists(os.path.join(x, 'pyproject.toml')))
for subdir in subdirs:
path = subdir / 'pyproject.toml'
data = tomlkit.parse(path.read_text())
name = data['project']['name']
version = data['project']['version']
if name is None or version is None:
click.secho(f'Could not extract name/version from {path}', fg='red', bold=True)
continue
minver = str(Version(version))
yield name, minver
def _get_config():
rv = {'extras': {}, 'skip': []}
try:
f = open('_meta/meta.yaml') # noqa: SIM115
except OSError as exc:
if exc.errno != errno.ENOENT:
raise
else:
with f:
rv.update(yaml.safe_load(f))
return rv
def _show_diff(old, new, filename):
diff = difflib.unified_diff(old.splitlines(), new.splitlines(), filename, filename, lineterm='')
diff = '\n'.join(diff)
print(highlight(diff, DiffLexer(), Terminal256Formatter(style='native')))
def _update_meta(pyproject: Path, data):
content = pyproject.read_text()
new_content = tomlkit.dumps(data)
if content == new_content:
return False
_show_diff(content, new_content, pyproject.name)
pyproject.write_text(new_content)
return True
@click.command()
@click.argument('nextver')
def cli(nextver):
if not os.path.isdir('_meta/'):
click.secho('Could not find meta package (_meta subdir)', fg='red', bold=True)
sys.exit(1)
nextver = Version(nextver)
if nextver.dev is None:
nextver = Version(str(nextver) + '-dev')
config = _get_config()
plugins_require = []
extras_require = defaultdict(list)
for name, minver in sorted(_find_plugins()):
if name in config['skip']:
continue
pkgspec = f'{name}>={minver},<{nextver}'
if name in config['extras']:
extras_require[config['extras'][name]].append(pkgspec)
else:
plugins_require.append(pkgspec)
pyproject = Path('_meta/pyproject.toml')
data = tomlkit.parse(pyproject.read_text())
data['project']['dependencies'] = [
*(x for x in data['project']['dependencies'] if not x.startswith('indico-plugin-')),
*(tomlkit.string(name, literal=True) for name in plugins_require)
]
data['project']['dependencies'].multiline(True)
if extras_require:
optional_deps = tomlkit.table()
for extra, pkgspecs in sorted(extras_require.items()):
optional_deps[extra] = tomlkit.array(sorted(tomlkit.string(x, literal=True) for x in pkgspecs))
data['project']['optional-dependencies'] = optional_deps
else:
data['project'].pop('optional-dependencies', None)
if _update_meta(pyproject, data):
click.secho('Updated meta package', fg='green')
else:
click.secho('Meta package already up to date', fg='yellow')
if __name__ == '__main__':
cli()