fast-dev-cli 0.17.2__tar.gz → 0.18.0__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.17.2 → fast_dev_cli-0.18.0}/PKG-INFO +7 -7
- fast_dev_cli-0.18.0/fast_dev_cli/__init__.py +1 -0
- {fast_dev_cli-0.17.2 → fast_dev_cli-0.18.0}/fast_dev_cli/cli.py +160 -1
- {fast_dev_cli-0.17.2 → fast_dev_cli-0.18.0}/pyproject.toml +7 -9
- fast_dev_cli-0.18.0/tests/assets/uv-tx.lock +1476 -0
- fast_dev_cli-0.18.0/tests/assets/uv.lock +1476 -0
- fast_dev_cli-0.18.0/tests/test_deps.py +33 -0
- {fast_dev_cli-0.17.2 → fast_dev_cli-0.18.0}/tests/test_lint.py +2 -2
- fast_dev_cli-0.18.0/tests/test_pypi.py +43 -0
- {fast_dev_cli-0.17.2 → fast_dev_cli-0.18.0}/tests/test_version.py +1 -1
- fast_dev_cli-0.17.2/fast_dev_cli/__init__.py +0 -1
- {fast_dev_cli-0.17.2 → fast_dev_cli-0.18.0}/LICENSE +0 -0
- {fast_dev_cli-0.17.2 → fast_dev_cli-0.18.0}/README.md +0 -0
- {fast_dev_cli-0.17.2 → fast_dev_cli-0.18.0}/fast_dev_cli/__main__.py +0 -0
- {fast_dev_cli-0.17.2 → fast_dev_cli-0.18.0}/fast_dev_cli/py.typed +0 -0
- {fast_dev_cli-0.17.2 → fast_dev_cli-0.18.0}/pdm_build.py +0 -0
- {fast_dev_cli-0.17.2 → fast_dev_cli-0.18.0}/scripts/check.py +0 -0
- {fast_dev_cli-0.17.2 → fast_dev_cli-0.18.0}/scripts/deps.py +0 -0
- {fast_dev_cli-0.17.2 → fast_dev_cli-0.18.0}/scripts/format.py +0 -0
- {fast_dev_cli-0.17.2 → fast_dev_cli-0.18.0}/scripts/test.py +0 -0
- {fast_dev_cli-0.17.2 → fast_dev_cli-0.18.0}/tests/__init__.py +0 -0
- {fast_dev_cli-0.17.2 → fast_dev_cli-0.18.0}/tests/conftest.py +0 -0
- {fast_dev_cli-0.17.2 → fast_dev_cli-0.18.0}/tests/test_bump.py +0 -0
- {fast_dev_cli-0.17.2 → fast_dev_cli-0.18.0}/tests/test_exec.py +0 -0
- {fast_dev_cli-0.17.2 → fast_dev_cli-0.18.0}/tests/test_fast_test.py +0 -0
- {fast_dev_cli-0.17.2 → fast_dev_cli-0.18.0}/tests/test_functions.py +0 -0
- {fast_dev_cli-0.17.2 → fast_dev_cli-0.18.0}/tests/test_help.py +0 -0
- {fast_dev_cli-0.17.2 → fast_dev_cli-0.18.0}/tests/test_poetry_version_plugin.py +0 -0
- {fast_dev_cli-0.17.2 → fast_dev_cli-0.18.0}/tests/test_runserver.py +0 -0
- {fast_dev_cli-0.17.2 → fast_dev_cli-0.18.0}/tests/test_sync.py +0 -0
- {fast_dev_cli-0.17.2 → fast_dev_cli-0.18.0}/tests/test_tag.py +0 -0
- {fast_dev_cli-0.17.2 → fast_dev_cli-0.18.0}/tests/test_upgrade.py +0 -0
- {fast_dev_cli-0.17.2 → fast_dev_cli-0.18.0}/tests/test_upload.py +0 -0
- {fast_dev_cli-0.17.2 → fast_dev_cli-0.18.0}/tests/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: fast-dev-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.18.0
|
|
4
4
|
Summary: Python project development tool.
|
|
5
5
|
Author-Email: Waket Zheng <waketzheng@gmail.com>>
|
|
6
6
|
Classifier: Development Status :: 4 - Beta
|
|
@@ -22,14 +22,14 @@ Classifier: Typing :: Typed
|
|
|
22
22
|
Classifier: License :: OSI Approved :: MIT License
|
|
23
23
|
Project-URL: Homepage, https://github.com/waketzheng/fast-dev-cli
|
|
24
24
|
Requires-Python: >=3.9
|
|
25
|
-
Requires-Dist: typer<1,>=0.12.3
|
|
25
|
+
Requires-Dist: typer-slim<1,>=0.12.3
|
|
26
26
|
Requires-Dist: tomli<3,>=2.0.1; python_version < "3.11"
|
|
27
|
-
Requires-Dist: emoji
|
|
27
|
+
Requires-Dist: emoji>=2.12.1
|
|
28
28
|
Requires-Dist: packaging>=20.5
|
|
29
|
-
Requires-Dist: coverage
|
|
30
|
-
Requires-Dist: mypy
|
|
31
|
-
Requires-Dist: bumpversion2
|
|
32
|
-
Requires-Dist: pytest
|
|
29
|
+
Requires-Dist: coverage>=7.5.1
|
|
30
|
+
Requires-Dist: mypy>=1.15.0
|
|
31
|
+
Requires-Dist: bumpversion2>=1.4.3
|
|
32
|
+
Requires-Dist: pytest>=8.2.0
|
|
33
33
|
Provides-Extra: include-optional-dependencies
|
|
34
34
|
Requires-Dist: all; extra == "include-optional-dependencies"
|
|
35
35
|
Description-Content-Type: text/markdown
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.18.0"
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import contextlib
|
|
4
|
+
import functools
|
|
4
5
|
import importlib.metadata as importlib_metadata
|
|
5
6
|
import os
|
|
6
7
|
import re
|
|
@@ -21,6 +22,7 @@ from typing import (
|
|
|
21
22
|
)
|
|
22
23
|
|
|
23
24
|
import typer
|
|
25
|
+
from click import UsageError
|
|
24
26
|
from typer import Exit, Option, echo, secho
|
|
25
27
|
from typer.models import ArgumentInfo, OptionInfo
|
|
26
28
|
|
|
@@ -285,7 +287,7 @@ def exit_if_run_failed(
|
|
|
285
287
|
|
|
286
288
|
class DryRun:
|
|
287
289
|
def __init__(self, _exit: bool = False, dry: bool = False) -> None:
|
|
288
|
-
self.dry = dry
|
|
290
|
+
self.dry = _ensure_bool(dry)
|
|
289
291
|
self._exit = _exit
|
|
290
292
|
|
|
291
293
|
def gen(self) -> str:
|
|
@@ -1317,6 +1319,163 @@ def run_by_subprocess(cmd: str, dry: bool = DryOption) -> None:
|
|
|
1317
1319
|
raise Exit(rc)
|
|
1318
1320
|
|
|
1319
1321
|
|
|
1322
|
+
class MakeDeps(DryRun):
|
|
1323
|
+
def __init__(self, tool: str, prod: bool = False, dry: bool = False) -> None:
|
|
1324
|
+
self._tool = tool
|
|
1325
|
+
self._prod = prod
|
|
1326
|
+
super().__init__(dry=dry)
|
|
1327
|
+
|
|
1328
|
+
def should_ensure_pip(self) -> bool:
|
|
1329
|
+
return True
|
|
1330
|
+
|
|
1331
|
+
def should_upgrade_pip(self) -> bool:
|
|
1332
|
+
return True
|
|
1333
|
+
|
|
1334
|
+
def get_groups(self) -> list[str]:
|
|
1335
|
+
if self._prod:
|
|
1336
|
+
return []
|
|
1337
|
+
return ["dev"]
|
|
1338
|
+
|
|
1339
|
+
def gen(self) -> str:
|
|
1340
|
+
if self._tool == "pdm":
|
|
1341
|
+
return "pdm sync " + ("--prod" if self._prod else "-G :all")
|
|
1342
|
+
elif self._tool == "uv":
|
|
1343
|
+
return "uv sync --inexact --active" + (
|
|
1344
|
+
"" if self._prod else " --all-extras --all-groups"
|
|
1345
|
+
)
|
|
1346
|
+
elif self._tool == "poetry":
|
|
1347
|
+
return "poetry install " + (
|
|
1348
|
+
"--only=main" if self._prod else "--all-extras --all-groups"
|
|
1349
|
+
)
|
|
1350
|
+
else:
|
|
1351
|
+
cmd = "python -m pip install -e ."
|
|
1352
|
+
if gs := self.get_groups():
|
|
1353
|
+
cmd += " " + " ".join(f"--group {g}" for g in gs)
|
|
1354
|
+
upgrade = "python -m pip install --upgrade pip"
|
|
1355
|
+
if self.should_ensure_pip():
|
|
1356
|
+
cmd = f"python -m ensurepip && {upgrade} && {cmd}"
|
|
1357
|
+
elif self.should_upgrade_pip():
|
|
1358
|
+
cmd = "{upgrade} && {cmd}"
|
|
1359
|
+
return cmd
|
|
1360
|
+
|
|
1361
|
+
|
|
1362
|
+
@cli.command(name="deps")
|
|
1363
|
+
def make_deps(
|
|
1364
|
+
prod: bool = Option(
|
|
1365
|
+
False,
|
|
1366
|
+
"--prod",
|
|
1367
|
+
help="Only instead production dependencies.",
|
|
1368
|
+
),
|
|
1369
|
+
tool: str = ToolOption,
|
|
1370
|
+
use_uv: bool = Option(False, "--uv", help="Use `uv` to install deps"),
|
|
1371
|
+
use_pdm: bool = Option(False, "--pdm", help="Use `pdm` to install deps"),
|
|
1372
|
+
use_pip: bool = Option(False, "--pip", help="Use `pip` to install deps"),
|
|
1373
|
+
use_poetry: bool = Option(False, "--poetry", help="Use `poetry` to install deps"),
|
|
1374
|
+
dry: bool = DryOption,
|
|
1375
|
+
) -> None:
|
|
1376
|
+
"""Run: ruff check/format to reformat code and then mypy to check"""
|
|
1377
|
+
if use_uv + use_pdm + use_pip + use_poetry > 1:
|
|
1378
|
+
raise UsageError("`--uv/--pdm/--pip/--poetry` can only choose one!")
|
|
1379
|
+
if use_uv:
|
|
1380
|
+
tool = "uv"
|
|
1381
|
+
elif use_pdm:
|
|
1382
|
+
tool = "pdm"
|
|
1383
|
+
elif use_pip:
|
|
1384
|
+
tool = "pip"
|
|
1385
|
+
elif use_poetry:
|
|
1386
|
+
tool = "poetry"
|
|
1387
|
+
elif tool == ToolOption.default:
|
|
1388
|
+
tool = Project.get_manage_tool(cache=True) or "pip"
|
|
1389
|
+
MakeDeps(tool, prod, dry=dry).run()
|
|
1390
|
+
|
|
1391
|
+
|
|
1392
|
+
class UvPypi(DryRun):
|
|
1393
|
+
PYPI = "https://pypi.org/simple"
|
|
1394
|
+
HOST = "https://files.pythonhosted.org"
|
|
1395
|
+
|
|
1396
|
+
def __init__(self, lock_file: Path, dry: bool, verbose: bool, quiet: bool) -> None:
|
|
1397
|
+
super().__init__(dry=dry)
|
|
1398
|
+
self.lock_file = lock_file
|
|
1399
|
+
self._verbose = _ensure_bool(verbose)
|
|
1400
|
+
self._quiet = _ensure_bool(quiet)
|
|
1401
|
+
|
|
1402
|
+
def run(self) -> None:
|
|
1403
|
+
try:
|
|
1404
|
+
rc = self.update_lock(self.lock_file, self._verbose, self._quiet)
|
|
1405
|
+
except ValueError as e:
|
|
1406
|
+
secho(str(e), fg=typer.colors.RED)
|
|
1407
|
+
raise Exit(1) from e
|
|
1408
|
+
else:
|
|
1409
|
+
if rc != 0:
|
|
1410
|
+
raise Exit(rc)
|
|
1411
|
+
|
|
1412
|
+
@classmethod
|
|
1413
|
+
def update_lock(cls, p: Path, verbose: bool, quiet: bool) -> int:
|
|
1414
|
+
text = p.read_text("utf-8")
|
|
1415
|
+
registry_pattern = r'(registry = ")(.*?)"'
|
|
1416
|
+
replace_registry = functools.partial(
|
|
1417
|
+
re.sub, registry_pattern, rf'\1{cls.PYPI}"'
|
|
1418
|
+
)
|
|
1419
|
+
registry_urls = {i[1] for i in re.findall(registry_pattern, text)}
|
|
1420
|
+
download_pattern = r'(url = ")(https?://.*?)(/packages/.*?\.)(gz|whl)"'
|
|
1421
|
+
replace_host = functools.partial(
|
|
1422
|
+
re.sub, download_pattern, rf'\1{cls.HOST}\3\4"'
|
|
1423
|
+
)
|
|
1424
|
+
download_hosts = {i[1] for i in re.findall(download_pattern, text)}
|
|
1425
|
+
if not registry_urls:
|
|
1426
|
+
raise ValueError(f"Failed to find pattern {registry_pattern!r} in {p}")
|
|
1427
|
+
if len(registry_urls) == 1:
|
|
1428
|
+
current_registry = registry_urls.pop()
|
|
1429
|
+
if current_registry == cls.PYPI:
|
|
1430
|
+
if download_hosts == {cls.HOST}:
|
|
1431
|
+
if verbose:
|
|
1432
|
+
echo(f"Registry of {p} is {cls.PYPI}, no need to change.")
|
|
1433
|
+
return 0
|
|
1434
|
+
else:
|
|
1435
|
+
text = replace_registry(text)
|
|
1436
|
+
if verbose:
|
|
1437
|
+
echo(f"{current_registry} --> {cls.PYPI}")
|
|
1438
|
+
else:
|
|
1439
|
+
# TODO: ask each one to confirm replace
|
|
1440
|
+
text = replace_registry(text)
|
|
1441
|
+
if verbose:
|
|
1442
|
+
for current_registry in sorted(registry_urls):
|
|
1443
|
+
echo(f"{current_registry} --> {cls.PYPI}")
|
|
1444
|
+
if len(download_hosts) == 1:
|
|
1445
|
+
current_host = download_hosts.pop()
|
|
1446
|
+
if current_host != cls.HOST:
|
|
1447
|
+
text = replace_host(text)
|
|
1448
|
+
if verbose:
|
|
1449
|
+
print(current_host, "-->", cls.HOST)
|
|
1450
|
+
elif download_hosts:
|
|
1451
|
+
# TODO: ask each one to confirm replace
|
|
1452
|
+
text = replace_host(text)
|
|
1453
|
+
if verbose:
|
|
1454
|
+
for current_host in sorted(download_hosts):
|
|
1455
|
+
echo(f"{current_host} --> {cls.HOST}")
|
|
1456
|
+
size = p.write_text(text, encoding="utf-8")
|
|
1457
|
+
if verbose:
|
|
1458
|
+
echo(f"Updated {p} with {size} bytes.")
|
|
1459
|
+
if quiet:
|
|
1460
|
+
return 0
|
|
1461
|
+
return 1
|
|
1462
|
+
|
|
1463
|
+
|
|
1464
|
+
@cli.command()
|
|
1465
|
+
def pypi(
|
|
1466
|
+
dry: bool = DryOption,
|
|
1467
|
+
verbose: bool = False,
|
|
1468
|
+
quiet: bool = False,
|
|
1469
|
+
) -> None:
|
|
1470
|
+
"""Change registry of uv.lock to be pypi.org"""
|
|
1471
|
+
if not (p := Path("uv.lock")).exists() and not (
|
|
1472
|
+
(p := Project.get_work_dir() / p.name).exists()
|
|
1473
|
+
):
|
|
1474
|
+
yellow_warn(f"{p.name!r} not found!")
|
|
1475
|
+
return
|
|
1476
|
+
UvPypi(p, dry, verbose, quiet).run()
|
|
1477
|
+
|
|
1478
|
+
|
|
1320
1479
|
def version_callback(value: bool) -> None:
|
|
1321
1480
|
if value:
|
|
1322
1481
|
echo("Fast Dev Cli Version: " + typer.style(__version__, bold=True))
|
|
@@ -33,16 +33,16 @@ classifiers = [
|
|
|
33
33
|
"License :: OSI Approved :: MIT License",
|
|
34
34
|
]
|
|
35
35
|
dependencies = [
|
|
36
|
-
"typer >=0.12.3,<1",
|
|
36
|
+
"typer-slim >=0.12.3,<1",
|
|
37
37
|
"tomli >=2.0.1,<3; python_version < '3.11'",
|
|
38
|
-
"emoji >=2.12.1
|
|
38
|
+
"emoji >=2.12.1",
|
|
39
39
|
"packaging >=20.5",
|
|
40
|
-
"coverage >=7.5.1
|
|
41
|
-
"mypy >=1.15.0
|
|
42
|
-
"bumpversion2 >=1.4.3
|
|
43
|
-
"pytest >=8.2.0
|
|
40
|
+
"coverage >=7.5.1",
|
|
41
|
+
"mypy >=1.15.0",
|
|
42
|
+
"bumpversion2 >=1.4.3",
|
|
43
|
+
"pytest >=8.2.0",
|
|
44
44
|
]
|
|
45
|
-
version = "0.
|
|
45
|
+
version = "0.18.0"
|
|
46
46
|
|
|
47
47
|
[project.urls]
|
|
48
48
|
Homepage = "https://github.com/waketzheng/fast-dev-cli"
|
|
@@ -58,8 +58,6 @@ fast = "fast_dev_cli:cli.main"
|
|
|
58
58
|
[dependency-groups]
|
|
59
59
|
dev = [
|
|
60
60
|
"twine>=6.1.0",
|
|
61
|
-
]
|
|
62
|
-
test = [
|
|
63
61
|
"asynctor>=0.8.6",
|
|
64
62
|
]
|
|
65
63
|
|