fast-dev-cli 0.18.1__tar.gz → 0.18.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.18.1 → fast_dev_cli-0.18.2}/PKG-INFO +1 -1
- fast_dev_cli-0.18.2/fast_dev_cli/__init__.py +1 -0
- {fast_dev_cli-0.18.1 → fast_dev_cli-0.18.2}/fast_dev_cli/cli.py +58 -48
- {fast_dev_cli-0.18.1 → fast_dev_cli-0.18.2}/pyproject.toml +1 -1
- {fast_dev_cli-0.18.1 → fast_dev_cli-0.18.2}/tests/test_lint.py +13 -0
- fast_dev_cli-0.18.1/fast_dev_cli/__init__.py +0 -1
- {fast_dev_cli-0.18.1 → fast_dev_cli-0.18.2}/LICENSE +0 -0
- {fast_dev_cli-0.18.1 → fast_dev_cli-0.18.2}/README.md +0 -0
- {fast_dev_cli-0.18.1 → fast_dev_cli-0.18.2}/fast_dev_cli/__main__.py +0 -0
- {fast_dev_cli-0.18.1 → fast_dev_cli-0.18.2}/fast_dev_cli/py.typed +0 -0
- {fast_dev_cli-0.18.1 → fast_dev_cli-0.18.2}/pdm_build.py +0 -0
- {fast_dev_cli-0.18.1 → fast_dev_cli-0.18.2}/scripts/check.py +0 -0
- {fast_dev_cli-0.18.1 → fast_dev_cli-0.18.2}/scripts/deps.py +0 -0
- {fast_dev_cli-0.18.1 → fast_dev_cli-0.18.2}/scripts/format.py +0 -0
- {fast_dev_cli-0.18.1 → fast_dev_cli-0.18.2}/scripts/test.py +0 -0
- {fast_dev_cli-0.18.1 → fast_dev_cli-0.18.2}/tests/__init__.py +0 -0
- {fast_dev_cli-0.18.1 → fast_dev_cli-0.18.2}/tests/assets/uv-tx.lock +0 -0
- {fast_dev_cli-0.18.1 → fast_dev_cli-0.18.2}/tests/assets/uv.lock +0 -0
- {fast_dev_cli-0.18.1 → fast_dev_cli-0.18.2}/tests/conftest.py +0 -0
- {fast_dev_cli-0.18.1 → fast_dev_cli-0.18.2}/tests/test_bump.py +0 -0
- {fast_dev_cli-0.18.1 → fast_dev_cli-0.18.2}/tests/test_deps.py +0 -0
- {fast_dev_cli-0.18.1 → fast_dev_cli-0.18.2}/tests/test_exec.py +0 -0
- {fast_dev_cli-0.18.1 → fast_dev_cli-0.18.2}/tests/test_fast_test.py +0 -0
- {fast_dev_cli-0.18.1 → fast_dev_cli-0.18.2}/tests/test_functions.py +0 -0
- {fast_dev_cli-0.18.1 → fast_dev_cli-0.18.2}/tests/test_help.py +0 -0
- {fast_dev_cli-0.18.1 → fast_dev_cli-0.18.2}/tests/test_poetry_version_plugin.py +0 -0
- {fast_dev_cli-0.18.1 → fast_dev_cli-0.18.2}/tests/test_pypi.py +0 -0
- {fast_dev_cli-0.18.1 → fast_dev_cli-0.18.2}/tests/test_runserver.py +0 -0
- {fast_dev_cli-0.18.1 → fast_dev_cli-0.18.2}/tests/test_sync.py +0 -0
- {fast_dev_cli-0.18.1 → fast_dev_cli-0.18.2}/tests/test_tag.py +0 -0
- {fast_dev_cli-0.18.1 → fast_dev_cli-0.18.2}/tests/test_upgrade.py +0 -0
- {fast_dev_cli-0.18.1 → fast_dev_cli-0.18.2}/tests/test_upload.py +0 -0
- {fast_dev_cli-0.18.1 → fast_dev_cli-0.18.2}/tests/test_version.py +0 -0
- {fast_dev_cli-0.18.1 → fast_dev_cli-0.18.2}/tests/utils.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.18.2"
|
|
@@ -6,6 +6,7 @@ import importlib.metadata as importlib_metadata
|
|
|
6
6
|
import os
|
|
7
7
|
import re
|
|
8
8
|
import shlex
|
|
9
|
+
import shutil
|
|
9
10
|
import subprocess # nosec:B404
|
|
10
11
|
import sys
|
|
11
12
|
from functools import cached_property
|
|
@@ -61,10 +62,20 @@ ToolOption = Option(
|
|
|
61
62
|
)
|
|
62
63
|
|
|
63
64
|
|
|
64
|
-
class FastDevCliError(Exception):
|
|
65
|
+
class FastDevCliError(Exception):
|
|
66
|
+
"""Basic exception of this library, all custom exceptions inherit from it"""
|
|
65
67
|
|
|
66
68
|
|
|
67
|
-
class ShellCommandError(FastDevCliError):
|
|
69
|
+
class ShellCommandError(FastDevCliError):
|
|
70
|
+
"""Raise if cmd command returncode is not zero"""
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class ParseError(FastDevCliError):
|
|
74
|
+
"""Raise this if parse dependence line error"""
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class EnvError(FastDevCliError):
|
|
78
|
+
"""Raise when expected to be managed by poetry, but toml file not found."""
|
|
68
79
|
|
|
69
80
|
|
|
70
81
|
def poetry_module_name(name: str) -> str:
|
|
@@ -259,7 +270,7 @@ def _ensure_bool(value: bool | OptionInfo) -> bool:
|
|
|
259
270
|
return value
|
|
260
271
|
|
|
261
272
|
|
|
262
|
-
def _ensure_str(value: str | OptionInfo) -> str:
|
|
273
|
+
def _ensure_str(value: str | OptionInfo | None) -> str:
|
|
263
274
|
if not isinstance(value, str):
|
|
264
275
|
value = getattr(value, "default", "")
|
|
265
276
|
return value
|
|
@@ -535,10 +546,6 @@ def bump() -> None:
|
|
|
535
546
|
return BumpUp(commit, part, no_sync="--no-sync" in args, dry="--dry" in args).run()
|
|
536
547
|
|
|
537
548
|
|
|
538
|
-
class EnvError(Exception):
|
|
539
|
-
"""Raise when expected to be managed by poetry, but toml file not found."""
|
|
540
|
-
|
|
541
|
-
|
|
542
549
|
class Project:
|
|
543
550
|
path_depth = 5
|
|
544
551
|
_tool: ToolName | None = None
|
|
@@ -590,30 +597,33 @@ class Project:
|
|
|
590
597
|
try:
|
|
591
598
|
text = cls.load_toml_text()
|
|
592
599
|
except EnvError:
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
if "poetry" in backend:
|
|
599
|
-
cls._tool = "poetry"
|
|
600
|
-
return cls._tool
|
|
601
|
-
elif "pdm" in backend:
|
|
602
|
-
cls._tool = "pdm"
|
|
603
|
-
work_dir = cls.get_work_dir(allow_cwd=True)
|
|
604
|
-
if not Path(work_dir, "pdm.lock").exists() and (
|
|
605
|
-
"[tool.uv]" in text or Path(work_dir, "uv.lock").exists()
|
|
606
|
-
):
|
|
607
|
-
cls._tool = "uv"
|
|
608
|
-
return cls._tool
|
|
609
|
-
for name in get_args(ToolName):
|
|
610
|
-
if f"[tool.{name}]" in text:
|
|
611
|
-
cls._tool = cast(ToolName, name)
|
|
612
|
-
return cls._tool
|
|
613
|
-
# Poetry 2.0 default to not include the '[tool.poetry]' section
|
|
614
|
-
if cls.is_poetry_v2(text):
|
|
600
|
+
return None
|
|
601
|
+
with contextlib.suppress(KeyError, tomllib.TOMLDecodeError):
|
|
602
|
+
doc = tomllib.loads(text)
|
|
603
|
+
backend = doc["build-system"]["build-backend"]
|
|
604
|
+
if "poetry" in backend:
|
|
615
605
|
cls._tool = "poetry"
|
|
616
606
|
return cls._tool
|
|
607
|
+
work_dir = cls.get_work_dir(allow_cwd=True)
|
|
608
|
+
uv_lock_exists = Path(work_dir, "uv.lock").exists()
|
|
609
|
+
if "pdm" in backend:
|
|
610
|
+
cls._tool = "pdm"
|
|
611
|
+
if not Path(work_dir, "pdm.lock").exists() and (
|
|
612
|
+
uv_lock_exists or "[tool.uv]" in text
|
|
613
|
+
):
|
|
614
|
+
cls._tool = "uv"
|
|
615
|
+
return cls._tool
|
|
616
|
+
elif uv_lock_exists:
|
|
617
|
+
cls._tool = "uv"
|
|
618
|
+
return cls._tool
|
|
619
|
+
for name in get_args(ToolName):
|
|
620
|
+
if f"[tool.{name}]" in text:
|
|
621
|
+
cls._tool = cast(ToolName, name)
|
|
622
|
+
return cls._tool
|
|
623
|
+
# Poetry 2.0 default to not include the '[tool.poetry]' section
|
|
624
|
+
if cls.is_poetry_v2(text):
|
|
625
|
+
cls._tool = "poetry"
|
|
626
|
+
return cls._tool
|
|
617
627
|
return None
|
|
618
628
|
|
|
619
629
|
@staticmethod
|
|
@@ -664,12 +674,6 @@ class Project:
|
|
|
664
674
|
run_and_echo(cmd)
|
|
665
675
|
|
|
666
676
|
|
|
667
|
-
class ParseError(Exception):
|
|
668
|
-
"""Raise this if parse dependence line error"""
|
|
669
|
-
|
|
670
|
-
pass
|
|
671
|
-
|
|
672
|
-
|
|
673
677
|
class UpgradeDependencies(Project, DryRun):
|
|
674
678
|
def __init__(
|
|
675
679
|
self, _exit: bool = False, dry: bool = False, tool: ToolName = "poetry"
|
|
@@ -943,6 +947,10 @@ class LintCode(DryRun):
|
|
|
943
947
|
def check_lint_tool_installed() -> bool:
|
|
944
948
|
return check_call("ruff --version")
|
|
945
949
|
|
|
950
|
+
@staticmethod
|
|
951
|
+
def missing_mypy_exec() -> bool:
|
|
952
|
+
return shutil.which("mypy") is None
|
|
953
|
+
|
|
946
954
|
@staticmethod
|
|
947
955
|
def prefer_dmypy(paths: str, tools: list[str], use_dmypy: bool = False) -> bool:
|
|
948
956
|
return (
|
|
@@ -1006,6 +1014,16 @@ class LintCode(DryRun):
|
|
|
1006
1014
|
".local/bin"
|
|
1007
1015
|
):
|
|
1008
1016
|
if not ruff_exists:
|
|
1017
|
+
should_run_by_tool = True
|
|
1018
|
+
command = "pipx install ruff"
|
|
1019
|
+
if shutil.which("pipx") is None:
|
|
1020
|
+
ensure_pipx = "pip install --user pipx\n pipx ensurepath\n "
|
|
1021
|
+
command = ensure_pipx + command
|
|
1022
|
+
yellow_warn(
|
|
1023
|
+
"You may need to run the following command"
|
|
1024
|
+
f" to install ruff:\n\n {command}\n"
|
|
1025
|
+
)
|
|
1026
|
+
elif "mypy" in str(tools) and cls.missing_mypy_exec():
|
|
1009
1027
|
should_run_by_tool = True
|
|
1010
1028
|
if check_call('python -c "import fast_dev_cli"'):
|
|
1011
1029
|
command = 'python -m pip install -U "fast-dev-cli"'
|
|
@@ -1129,18 +1147,11 @@ def make_style(
|
|
|
1129
1147
|
bandit = _ensure_bool(bandit)
|
|
1130
1148
|
prefix = _ensure_bool(prefix)
|
|
1131
1149
|
tool = _ensure_str(tool)
|
|
1150
|
+
kwargs = {"dry": dry, "skip_mypy": skip, "dmypy": dmypy, "bandit": bandit}
|
|
1132
1151
|
if _ensure_bool(check_only):
|
|
1133
|
-
check(files,
|
|
1152
|
+
check(files, tool=tool, **kwargs)
|
|
1134
1153
|
else:
|
|
1135
|
-
lint(
|
|
1136
|
-
files,
|
|
1137
|
-
dry=dry,
|
|
1138
|
-
skip_mypy=skip,
|
|
1139
|
-
dmypy=dmypy,
|
|
1140
|
-
bandit=bandit,
|
|
1141
|
-
tool=tool,
|
|
1142
|
-
prefix=prefix,
|
|
1143
|
-
)
|
|
1154
|
+
lint(files, prefix=prefix, tool=tool, **kwargs)
|
|
1144
1155
|
|
|
1145
1156
|
|
|
1146
1157
|
@cli.command(name="check")
|
|
@@ -1469,7 +1480,7 @@ def pypi(
|
|
|
1469
1480
|
quiet: bool = False,
|
|
1470
1481
|
) -> None:
|
|
1471
1482
|
"""Change registry of uv.lock to be pypi.org"""
|
|
1472
|
-
if not (p := Path(file or "uv.lock")).exists() and not (
|
|
1483
|
+
if not (p := Path(_ensure_str(file) or "uv.lock")).exists() and not (
|
|
1473
1484
|
(p := Project.get_work_dir() / p.name).exists()
|
|
1474
1485
|
):
|
|
1475
1486
|
yellow_warn(f"{p.name!r} not found!")
|
|
@@ -1493,8 +1504,7 @@ def common(
|
|
|
1493
1504
|
is_eager=True,
|
|
1494
1505
|
help="Show the version of this tool",
|
|
1495
1506
|
),
|
|
1496
|
-
) -> None:
|
|
1497
|
-
pass
|
|
1507
|
+
) -> None: ...
|
|
1498
1508
|
|
|
1499
1509
|
|
|
1500
1510
|
def main() -> None:
|
|
@@ -245,6 +245,19 @@ def test_lint_without_ruff_installed(mocker, mock_no_dmypy):
|
|
|
245
245
|
with capture_stdout() as stream:
|
|
246
246
|
lint(".", dry=True)
|
|
247
247
|
output = stream.getvalue()
|
|
248
|
+
cmd = "pipx install ruff"
|
|
249
|
+
assert cmd in output
|
|
250
|
+
tip = "You may need to run the following command to install ruff"
|
|
251
|
+
assert tip in output
|
|
252
|
+
assert f"{tip}:\n\n {cmd}" in output
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def test_lint_without_mypy_installed(mocker, mock_no_dmypy):
|
|
256
|
+
mocker.patch("fast_dev_cli.cli.is_venv", return_value=True)
|
|
257
|
+
mocker.patch("fast_dev_cli.cli.LintCode.missing_mypy_exec", return_value=True)
|
|
258
|
+
with capture_stdout() as stream:
|
|
259
|
+
lint(".", dry=True)
|
|
260
|
+
output = stream.getvalue()
|
|
248
261
|
cmd = 'python -m pip install -U "fast-dev-cli"'
|
|
249
262
|
assert cmd in output
|
|
250
263
|
tip = "You may need to run the following command to install lint tools"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.18.1"
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|