Skip to content

Commit c2d0877

Browse files
authored
Merge pull request #307 from krassowski/bump_version_script
Add bump version script
2 parents a65019a + e08bed6 commit c2d0877

File tree

2 files changed

+161
-1
lines changed

2 files changed

+161
-1
lines changed

docs/Releasing.ipynb

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@
2525
"- TODO: create a `release.py` script\n",
2626
" [#88](https://github.com/krassowski/jupyterlab-lsp/issues/88)\n",
2727
"\n",
28+
"Use the `bump_versions` script to manage the version strings:\n",
29+
"\n",
30+
"```bash\n",
31+
"python scripts/bump_versions.py\n",
32+
"```\n",
33+
"\n",
2834
"The PyPI version (jupyter-lsp) must be updated in the following places:\n",
2935
"\n",
3036
"- `py_src/jupyter_lsp/_version.py` (canonical)\n",
@@ -89,4 +95,4 @@
8995
},
9096
"nbformat": 4,
9197
"nbformat_minor": 4
92-
}
98+
}

scripts/bump_versions.py

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
#!/usr/bin/env python3
2+
"""Bump version of selected packages or core requirements (JupyterLab)"""
3+
import sys
4+
from argparse import ArgumentParser
5+
from dataclasses import dataclass
6+
from difflib import context_diff
7+
from pathlib import Path
8+
from typing import List
9+
10+
from integrity import CHANGELOG, PIPE_FILE as PIPELINE
11+
12+
ROOT = Path.cwd()
13+
14+
sys.path.insert(0, str(ROOT))
15+
16+
if True:
17+
# a workaround for isort 4.0 limitations
18+
# see https://github.com/timothycrosley/isort/issues/468
19+
from versions import ( # noqa
20+
JUPYTER_LSP_VERSION,
21+
JUPYTERLAB_LSP_VERSION,
22+
JUPYTERLAB_VERSION,
23+
REQUIRED_JUPYTERLAB,
24+
)
25+
26+
27+
META_PACKAGE = Path("packages/metapackage/package.json")
28+
JUPYTERLAB_LSP_PACKAGE = Path("packages/jupyterlab-lsp/package.json")
29+
README = Path("README.md")
30+
31+
NPM_PACKAGE_VERSION_TEMPLATE = '"version": "{version}"'
32+
33+
34+
@dataclass
35+
class VersionLocation:
36+
path: Path
37+
template: str
38+
39+
40+
@dataclass
41+
class PackageVersionInfo:
42+
name: str
43+
current_version: str
44+
locations: List[VersionLocation]
45+
46+
def maybe_change_version(self, dry: bool):
47+
print(f"Current {self.name} version is: {self.current_version}")
48+
version = input("Change it to [default=skip]: ").strip()
49+
if version:
50+
self.change_version(new_version=version, dry=dry)
51+
52+
def change_version(self, new_version: str, dry: bool):
53+
54+
changelog = CHANGELOG.read_text()
55+
if new_version not in changelog:
56+
raise Exception(
57+
(
58+
f"{new_version} is absent in CHANGELOG.md file."
59+
f" Please update the changelog first."
60+
).format(new_version=new_version)
61+
)
62+
63+
for location in self.locations:
64+
replace_version(
65+
path=location.path,
66+
template=location.template,
67+
old=self.current_version,
68+
new=new_version,
69+
dry=dry,
70+
)
71+
72+
73+
def replace_version(path: Path, template: str, old: str, new: str, dry: bool):
74+
old_content = path.read_text()
75+
new_content = old_content.replace(
76+
template.format(version=old), template.format(version=new)
77+
)
78+
if dry:
79+
diff = context_diff(
80+
old_content.splitlines(),
81+
new_content.splitlines(),
82+
fromfile="current",
83+
tofile="new (proposed update)",
84+
n=4,
85+
)
86+
relative_path = path.relative_to(ROOT) if path.is_absolute() else path
87+
print("\n## Summary of changes proposed to {path}".format(path=relative_path))
88+
print("\n".join(diff) + "\n")
89+
else:
90+
path.write_text(new_content)
91+
92+
93+
def update_versions(dry: bool):
94+
packages: List[PackageVersionInfo] = [
95+
PackageVersionInfo(
96+
name="jupyter-lsp (Python backend)",
97+
current_version=JUPYTER_LSP_VERSION,
98+
locations=[
99+
VersionLocation(
100+
path=Path("py_src/jupyter_lsp/_version.py"),
101+
template='__version__ = "{version}"',
102+
),
103+
VersionLocation(path=PIPELINE, template="PY_JLSP_VERSION: {version}"),
104+
],
105+
),
106+
PackageVersionInfo(
107+
name="jupyterlab-lsp (frontend package)",
108+
current_version=JUPYTERLAB_LSP_VERSION,
109+
locations=[
110+
VersionLocation(
111+
path=JUPYTERLAB_LSP_PACKAGE, template=NPM_PACKAGE_VERSION_TEMPLATE,
112+
),
113+
VersionLocation(path=PIPELINE, template="JS_JLLSP_VERSION: {version}"),
114+
VersionLocation(
115+
path=META_PACKAGE, template=NPM_PACKAGE_VERSION_TEMPLATE
116+
),
117+
],
118+
),
119+
PackageVersionInfo(
120+
name="JupyterLab - exact",
121+
current_version=JUPYTERLAB_VERSION,
122+
locations=[
123+
VersionLocation(
124+
path=JUPYTERLAB_LSP_PACKAGE,
125+
template='"@jupyterlab/application": "~{version}"',
126+
)
127+
],
128+
),
129+
PackageVersionInfo(
130+
name="JupyterLab - range",
131+
current_version=REQUIRED_JUPYTERLAB,
132+
locations=[
133+
VersionLocation(
134+
path=Path("binder/environment.yml"),
135+
template="jupyterlab {version}",
136+
),
137+
VersionLocation(path=README, template="jupyterlab {version}",),
138+
VersionLocation(path=README, template="JupyterLab {version}",),
139+
],
140+
),
141+
]
142+
for package in packages:
143+
package.maybe_change_version(dry=dry)
144+
145+
146+
if __name__ == "__main__":
147+
parser = ArgumentParser()
148+
parser.add_argument(
149+
"--dry",
150+
action="store_true",
151+
help="do not perform the update, only show the changes",
152+
)
153+
args = parser.parse_args()
154+
update_versions(dry=args.dry)

0 commit comments

Comments
 (0)