fast-dev-cli 0.15.0__tar.gz → 0.15.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {fast_dev_cli-0.15.0 → fast_dev_cli-0.15.2}/PKG-INFO +2 -2
- fast_dev_cli-0.15.2/fast_dev_cli/__init__.py +1 -0
- {fast_dev_cli-0.15.0 → fast_dev_cli-0.15.2}/fast_dev_cli/cli.py +57 -23
- {fast_dev_cli-0.15.0 → fast_dev_cli-0.15.2}/pyproject.toml +4 -4
- {fast_dev_cli-0.15.0 → fast_dev_cli-0.15.2}/tests/conftest.py +8 -3
- {fast_dev_cli-0.15.0 → fast_dev_cli-0.15.2}/tests/test_bump.py +135 -0
- fast_dev_cli-0.15.0/fast_dev_cli/__init__.py +0 -1
- {fast_dev_cli-0.15.0 → fast_dev_cli-0.15.2}/LICENSE +0 -0
- {fast_dev_cli-0.15.0 → fast_dev_cli-0.15.2}/README.md +0 -0
- {fast_dev_cli-0.15.0 → fast_dev_cli-0.15.2}/fast_dev_cli/__main__.py +0 -0
- {fast_dev_cli-0.15.0 → fast_dev_cli-0.15.2}/fast_dev_cli/py.typed +0 -0
- {fast_dev_cli-0.15.0 → fast_dev_cli-0.15.2}/pdm_build.py +0 -0
- {fast_dev_cli-0.15.0 → fast_dev_cli-0.15.2}/scripts/check.py +0 -0
- {fast_dev_cli-0.15.0 → fast_dev_cli-0.15.2}/scripts/format.py +0 -0
- {fast_dev_cli-0.15.0 → fast_dev_cli-0.15.2}/scripts/test.py +0 -0
- {fast_dev_cli-0.15.0 → fast_dev_cli-0.15.2}/tests/__init__.py +0 -0
- {fast_dev_cli-0.15.0 → fast_dev_cli-0.15.2}/tests/test_fast_test.py +0 -0
- {fast_dev_cli-0.15.0 → fast_dev_cli-0.15.2}/tests/test_functions.py +0 -0
- {fast_dev_cli-0.15.0 → fast_dev_cli-0.15.2}/tests/test_lint.py +0 -0
- {fast_dev_cli-0.15.0 → fast_dev_cli-0.15.2}/tests/test_poetry_version_plugin.py +0 -0
- {fast_dev_cli-0.15.0 → fast_dev_cli-0.15.2}/tests/test_runserver.py +0 -0
- {fast_dev_cli-0.15.0 → fast_dev_cli-0.15.2}/tests/test_sync.py +0 -0
- {fast_dev_cli-0.15.0 → fast_dev_cli-0.15.2}/tests/test_tag.py +0 -0
- {fast_dev_cli-0.15.0 → fast_dev_cli-0.15.2}/tests/test_upgrade.py +0 -0
- {fast_dev_cli-0.15.0 → fast_dev_cli-0.15.2}/tests/test_upload.py +0 -0
- {fast_dev_cli-0.15.0 → fast_dev_cli-0.15.2}/tests/test_version.py +0 -0
- {fast_dev_cli-0.15.0 → fast_dev_cli-0.15.2}/tests/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: fast-dev-cli
|
|
3
|
-
Version: 0.15.
|
|
3
|
+
Version: 0.15.2
|
|
4
4
|
Summary: Python project development tool.
|
|
5
5
|
Author-Email: Waket Zheng <waketzheng@gmail.com>>
|
|
6
6
|
Classifier: Development Status :: 4 - Beta
|
|
@@ -23,12 +23,12 @@ Project-URL: Homepage, https://github.com/waketzheng/fast-dev-cli
|
|
|
23
23
|
Requires-Python: >=3.9
|
|
24
24
|
Requires-Dist: typer<1,>=0.12.3
|
|
25
25
|
Requires-Dist: emoji<3,>=2.12.1
|
|
26
|
+
Requires-Dist: packaging>=20.5
|
|
26
27
|
Requires-Dist: tomli<3,>=2.0.1; python_version < "3.11"
|
|
27
28
|
Requires-Dist: coverage<8,>=7.5.1
|
|
28
29
|
Requires-Dist: mypy<2,>=1.15.0
|
|
29
30
|
Requires-Dist: bumpversion2<2,>=1.4.3
|
|
30
31
|
Requires-Dist: pytest<9,>=8.2.0
|
|
31
|
-
Requires-Dist: packaging>=20.5
|
|
32
32
|
Provides-Extra: include-optional-dependencies
|
|
33
33
|
Requires-Dist: all; extra == "include-optional-dependencies"
|
|
34
34
|
Description-Content-Type: text/markdown
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.15.2"
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import contextlib
|
|
3
4
|
import importlib.metadata as importlib_metadata
|
|
4
5
|
import os
|
|
5
6
|
import re
|
|
@@ -11,7 +12,7 @@ from pathlib import Path
|
|
|
11
12
|
from typing import (
|
|
12
13
|
Any,
|
|
13
14
|
Literal,
|
|
14
|
-
# Optional is required by
|
|
15
|
+
# Optional is required by Option generated by typer
|
|
15
16
|
Optional,
|
|
16
17
|
cast,
|
|
17
18
|
get_args,
|
|
@@ -121,16 +122,27 @@ def _parse_version(line: str, pattern: re.Pattern[str]) -> str:
|
|
|
121
122
|
def read_version_from_file(
|
|
122
123
|
package_name: str, work_dir: Path | None = None, toml_text: str | None = None
|
|
123
124
|
) -> str:
|
|
124
|
-
if
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
125
|
+
if not package_name and toml_text:
|
|
126
|
+
pattern = re.compile(r"version\s*=")
|
|
127
|
+
for line in toml_text.splitlines():
|
|
128
|
+
if pattern.match(line):
|
|
129
|
+
return _parse_version(line, pattern)
|
|
130
|
+
version_file = BumpUp.parse_filename(toml_text, work_dir, package_name)
|
|
131
|
+
if version_file == TOML_FILE:
|
|
132
|
+
if toml_text is None:
|
|
133
|
+
toml_text = Project.load_toml_text()
|
|
134
|
+
context = tomllib.loads(toml_text)
|
|
135
|
+
with contextlib.suppress(KeyError):
|
|
136
|
+
return context["project"]["version"]
|
|
137
|
+
with contextlib.suppress(KeyError): # Poetry V1
|
|
138
|
+
return context["tool"]["poetry"]["version"]
|
|
139
|
+
secho(f"WARNING: can not find 'version' item in {version_file}!")
|
|
140
|
+
return "0.0.0"
|
|
141
|
+
pattern = re.compile(r"__version__\s*=")
|
|
142
|
+
for line in Path(version_file).read_text("utf-8").splitlines():
|
|
129
143
|
if pattern.match(line):
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
break
|
|
133
|
-
return version
|
|
144
|
+
return _parse_version(line, pattern)
|
|
145
|
+
# TODO: remove or refactor the following lines.
|
|
134
146
|
if work_dir is None:
|
|
135
147
|
work_dir = Project.get_work_dir()
|
|
136
148
|
package_dir = work_dir / package_name
|
|
@@ -141,6 +153,7 @@ def read_version_from_file(
|
|
|
141
153
|
):
|
|
142
154
|
secho("WARNING: __init__.py file does not exist!")
|
|
143
155
|
return "0.0.0"
|
|
156
|
+
|
|
144
157
|
pattern = re.compile(r"__version__\s*=")
|
|
145
158
|
for line in init_file.read_text("utf-8").splitlines():
|
|
146
159
|
if pattern.match(line):
|
|
@@ -257,8 +270,13 @@ class BumpUp(DryRun):
|
|
|
257
270
|
return emoji.is_emoji(first_char)
|
|
258
271
|
|
|
259
272
|
@staticmethod
|
|
260
|
-
def parse_filename(
|
|
261
|
-
toml_text =
|
|
273
|
+
def parse_filename(
|
|
274
|
+
toml_text: str | None = None,
|
|
275
|
+
work_dir: Path | None = None,
|
|
276
|
+
package_name: str | None = None,
|
|
277
|
+
) -> str:
|
|
278
|
+
if toml_text is None:
|
|
279
|
+
toml_text = Project.load_toml_text()
|
|
262
280
|
context = tomllib.loads(toml_text)
|
|
263
281
|
by_version_plugin = False
|
|
264
282
|
try:
|
|
@@ -276,6 +294,16 @@ class BumpUp(DryRun):
|
|
|
276
294
|
version_value = context["tool"]["poetry"]["version"]
|
|
277
295
|
except KeyError:
|
|
278
296
|
if not Project.manage_by_poetry():
|
|
297
|
+
if work_dir is None:
|
|
298
|
+
work_dir = Project.get_work_dir()
|
|
299
|
+
for tool in ("pdm", "hatch"):
|
|
300
|
+
with contextlib.suppress(KeyError):
|
|
301
|
+
version_path = context["tool"][tool]["version"]["path"]
|
|
302
|
+
if (
|
|
303
|
+
Path(version_path).exists()
|
|
304
|
+
or work_dir.joinpath(version_path).exists()
|
|
305
|
+
):
|
|
306
|
+
return version_path
|
|
279
307
|
# version = { source = "file", path = "fast_dev_cli/__init__.py" }
|
|
280
308
|
v_key = "version = "
|
|
281
309
|
p_key = 'path = "'
|
|
@@ -284,7 +312,7 @@ class BumpUp(DryRun):
|
|
|
284
312
|
continue
|
|
285
313
|
if p_key in (value := line.split(v_key, 1)[-1].split("#")[0]):
|
|
286
314
|
filename = value.split(p_key, 1)[-1].split('"')[0]
|
|
287
|
-
if
|
|
315
|
+
if work_dir.joinpath(filename).exists():
|
|
288
316
|
return filename
|
|
289
317
|
else:
|
|
290
318
|
by_version_plugin = version_value in ("0", "0.0.0", "init")
|
|
@@ -308,6 +336,8 @@ class BumpUp(DryRun):
|
|
|
308
336
|
cwd = Path.cwd()
|
|
309
337
|
pattern = re.compile(r"__version__\s*=\s*['\"]")
|
|
310
338
|
ds: list[Path] = []
|
|
339
|
+
if package_name is not None:
|
|
340
|
+
packages.insert(0, (package_name, ""))
|
|
311
341
|
for package_name, source_dir in packages:
|
|
312
342
|
ds.append(cwd / package_name)
|
|
313
343
|
ds.append(cwd / "src" / package_name)
|
|
@@ -317,7 +347,12 @@ class BumpUp(DryRun):
|
|
|
317
347
|
ds.extend([cwd / module_name, cwd / "src" / module_name, cwd])
|
|
318
348
|
for d in ds:
|
|
319
349
|
init_file = d / "__init__.py"
|
|
320
|
-
if
|
|
350
|
+
if (
|
|
351
|
+
init_file.exists() and pattern.search(init_file.read_text("utf8"))
|
|
352
|
+
) or (
|
|
353
|
+
(init_file := init_file.with_name("__version__.py")).exists()
|
|
354
|
+
and pattern.search(init_file.read_text("utf8"))
|
|
355
|
+
):
|
|
321
356
|
break
|
|
322
357
|
else:
|
|
323
358
|
raise ParseError("Version file not found! Where are you now?")
|
|
@@ -923,23 +958,22 @@ class Sync(DryRun):
|
|
|
923
958
|
raise EnvError("There project is not managed by uv/pdm/poetry!")
|
|
924
959
|
return f"python -m pip install -r {self.filename}"
|
|
925
960
|
prefix = "" if is_venv() else f"{tool} run "
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
if check_call(prefix + "python -m pip --version"):
|
|
930
|
-
ensurepip = ""
|
|
931
|
-
elif tool in ("poetry", "pdm"):
|
|
961
|
+
ensure_pip = " {1}python -m ensurepip && {1}python -m pip install -U pip &&"
|
|
962
|
+
export_cmd = "uv export --no-hashes --all-extras --frozen"
|
|
963
|
+
if tool in ("poetry", "pdm"):
|
|
932
964
|
export_cmd = f"{tool} export --without-hashes --with=dev"
|
|
933
965
|
if tool == "poetry":
|
|
934
|
-
|
|
966
|
+
ensure_pip = ""
|
|
935
967
|
if not UpgradeDependencies.should_with_dev():
|
|
936
968
|
export_cmd = export_cmd.replace(" --with=dev", "")
|
|
937
969
|
if extras and isinstance(extras, (str, list)):
|
|
938
970
|
export_cmd += f" --{extras=}".replace("'", '"')
|
|
939
971
|
elif check_call(prefix + "python -m pip --version"):
|
|
940
|
-
|
|
972
|
+
ensure_pip = ""
|
|
973
|
+
elif check_call(prefix + "python -m pip --version"):
|
|
974
|
+
ensure_pip = ""
|
|
941
975
|
install_cmd = (
|
|
942
|
-
f"{{2}} -o {{0}} &&{
|
|
976
|
+
f"{{2}} -o {{0}} &&{ensure_pip} {{1}}python -m pip install -r {{0}}"
|
|
943
977
|
)
|
|
944
978
|
if should_remove and not save:
|
|
945
979
|
install_cmd += " && rm -f {0}"
|
|
@@ -32,16 +32,16 @@ classifiers = [
|
|
|
32
32
|
"License :: OSI Approved :: MIT License",
|
|
33
33
|
]
|
|
34
34
|
dependencies = [
|
|
35
|
-
"typer>=0.12.3,<1",
|
|
35
|
+
"typer >=0.12.3,<1",
|
|
36
36
|
"emoji >=2.12.1,<3",
|
|
37
|
-
"
|
|
37
|
+
"packaging >=20.5",
|
|
38
|
+
"tomli >=2.0.1,<3; python_version < '3.11'",
|
|
38
39
|
"coverage >=7.5.1,<8",
|
|
39
40
|
"mypy >=1.15.0,<2",
|
|
40
41
|
"bumpversion2 >=1.4.3,<2",
|
|
41
42
|
"pytest >=8.2.0,<9",
|
|
42
|
-
"packaging>=20.5",
|
|
43
43
|
]
|
|
44
|
-
version = "0.15.
|
|
44
|
+
version = "0.15.2"
|
|
45
45
|
|
|
46
46
|
[project.urls]
|
|
47
47
|
Homepage = "https://github.com/waketzheng/fast-dev-cli"
|
|
@@ -51,7 +51,12 @@ build-backend = "poetry.core.masonry.api"
|
|
|
51
51
|
|
|
52
52
|
|
|
53
53
|
@pytest.fixture
|
|
54
|
-
def
|
|
54
|
+
def tmp_work_dir(tmp_path):
|
|
55
55
|
with chdir(tmp_path):
|
|
56
|
-
tmp_path
|
|
57
|
-
|
|
56
|
+
yield tmp_path
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@pytest.fixture
|
|
60
|
+
def tmp_poetry_project(tmp_work_dir: Path):
|
|
61
|
+
Path(TOML_FILE).write_text(TOML_CONTENT)
|
|
62
|
+
yield tmp_work_dir
|
|
@@ -230,3 +230,138 @@ version = "0"
|
|
|
230
230
|
from_dir.mkdir()
|
|
231
231
|
shutil.move(another_dir, from_dir)
|
|
232
232
|
assert BumpUp.parse_filename() == "py/hello/__init__.py"
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
PDM_DYNAMIC_VERSION = """
|
|
236
|
+
[tool.pdm.version]
|
|
237
|
+
source = "file"
|
|
238
|
+
path = "app/__init__.py"
|
|
239
|
+
"""
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
def test_pdm_project(tmp_work_dir):
|
|
243
|
+
capture_cmd_output("pdm new my-project --non-interactive")
|
|
244
|
+
with chdir("my-project"):
|
|
245
|
+
toml_file = Path("pyproject.toml")
|
|
246
|
+
content = toml_file.read_text().replace(
|
|
247
|
+
'version = "0.1.0"', 'dynamic = ["version"]'
|
|
248
|
+
)
|
|
249
|
+
toml_file.write_text(content)
|
|
250
|
+
with toml_file.open("a+") as f:
|
|
251
|
+
f.write(PDM_DYNAMIC_VERSION)
|
|
252
|
+
app = Path("app")
|
|
253
|
+
app.mkdir()
|
|
254
|
+
init_file = app.joinpath("__init__.py")
|
|
255
|
+
init_file.write_text('__version__ = "0.2.0"')
|
|
256
|
+
out = capture_cmd_output("fast bump patch")
|
|
257
|
+
assert str(init_file) in out
|
|
258
|
+
assert "0.2.1" in init_file.read_text()
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
def test_hatch_project(tmp_work_dir):
|
|
262
|
+
project_name = "httpx"
|
|
263
|
+
Path(project_name).mkdir()
|
|
264
|
+
with chdir(project_name):
|
|
265
|
+
toml_file = Path("pyproject.toml")
|
|
266
|
+
toml_file.write_text("""
|
|
267
|
+
[build-system]
|
|
268
|
+
requires = ["hatchling", "hatch-fancy-pypi-readme"]
|
|
269
|
+
build-backend = "hatchling.build"
|
|
270
|
+
|
|
271
|
+
[project]
|
|
272
|
+
name = "httpx"
|
|
273
|
+
description = "The next generation HTTP client."
|
|
274
|
+
license = "BSD-3-Clause"
|
|
275
|
+
requires-python = ">=3.8"
|
|
276
|
+
authors = [
|
|
277
|
+
{ name = "Tom Christie", email = "tom@tomchristie.com" },
|
|
278
|
+
]
|
|
279
|
+
dependencies = [
|
|
280
|
+
"certifi",
|
|
281
|
+
"httpcore==1.*",
|
|
282
|
+
"anyio",
|
|
283
|
+
"idna",
|
|
284
|
+
]
|
|
285
|
+
dynamic = ["readme", "version"]
|
|
286
|
+
|
|
287
|
+
[tool.hatch.version]
|
|
288
|
+
path = "httpx/__version__.py"
|
|
289
|
+
""")
|
|
290
|
+
Path(project_name).mkdir()
|
|
291
|
+
version_file = Path("httpx/__version__.py")
|
|
292
|
+
version_file.write_text("""
|
|
293
|
+
__title__ = "httpx"
|
|
294
|
+
__description__ = "A next generation HTTP client, for Python 3."
|
|
295
|
+
__version__ = "0.28.1"
|
|
296
|
+
""")
|
|
297
|
+
out = capture_cmd_output("fast bump patch")
|
|
298
|
+
assert str(version_file) in out
|
|
299
|
+
assert "0.28.2" in version_file.read_text()
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
def test_package_project_diff(tmp_work_dir):
|
|
303
|
+
project_name = "tortoise-database-url"
|
|
304
|
+
package_name = "database_url"
|
|
305
|
+
Path(project_name).mkdir()
|
|
306
|
+
with chdir(project_name):
|
|
307
|
+
Path(package_name).mkdir()
|
|
308
|
+
version_file = Path(package_name, "__init__.py")
|
|
309
|
+
version_file.write_text('__version__ = "0.3.0"')
|
|
310
|
+
toml_file = Path("pyproject.toml")
|
|
311
|
+
toml_file.write_text("""
|
|
312
|
+
[project]
|
|
313
|
+
name = "tortoise-database-url"
|
|
314
|
+
description = "Make it easy to generate database url."
|
|
315
|
+
authors = [{name="Waket Zheng", email="waketzheng@gmail.com"}]
|
|
316
|
+
readme = "README.md"
|
|
317
|
+
dynamic = ["version"]
|
|
318
|
+
keywords = ["database_url", "tortoise-orm"]
|
|
319
|
+
requires-python = ">=3.9"
|
|
320
|
+
dependencies = []
|
|
321
|
+
|
|
322
|
+
[tool.pdm.version]
|
|
323
|
+
source = "file"
|
|
324
|
+
path = "database_url/__init__.py"
|
|
325
|
+
|
|
326
|
+
[build-system]
|
|
327
|
+
requires = ["pdm-backend"]
|
|
328
|
+
build-backend = "pdm.backend"
|
|
329
|
+
""")
|
|
330
|
+
out = capture_cmd_output("fast bump patch")
|
|
331
|
+
assert str(version_file) in out
|
|
332
|
+
assert "0.3.1" in version_file.read_text()
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
def test_version_file_in_work_dir(tmp_work_dir):
|
|
336
|
+
project_name = package_name = "bigmodels"
|
|
337
|
+
Path(project_name).mkdir()
|
|
338
|
+
with chdir(project_name):
|
|
339
|
+
Path(package_name).mkdir()
|
|
340
|
+
version_file = Path("__version__.py")
|
|
341
|
+
version_file.write_text('__version__ = "0.3.0"')
|
|
342
|
+
toml_file = Path("pyproject.toml")
|
|
343
|
+
toml_file.write_text("""
|
|
344
|
+
[project]
|
|
345
|
+
name = "bigmodels"
|
|
346
|
+
description = ""
|
|
347
|
+
authors = [{name="Waket Zheng", email="waketzheng@gmail.com"}]
|
|
348
|
+
readme = "README.md"
|
|
349
|
+
dynamic = ["version"]
|
|
350
|
+
keywords = []
|
|
351
|
+
requires-python = ">=3.9"
|
|
352
|
+
dependencies = []
|
|
353
|
+
|
|
354
|
+
[tool.pdm]
|
|
355
|
+
distribution = false
|
|
356
|
+
|
|
357
|
+
[tool.pdm.version]
|
|
358
|
+
source = "file"
|
|
359
|
+
path = "__version__.py"
|
|
360
|
+
|
|
361
|
+
[build-system]
|
|
362
|
+
requires = ["pdm-backend"]
|
|
363
|
+
build-backend = "pdm.backend"
|
|
364
|
+
""")
|
|
365
|
+
out = capture_cmd_output("fast bump patch")
|
|
366
|
+
assert str(version_file) in out
|
|
367
|
+
assert "0.3.1" in version_file.read_text()
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.15.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|