fast-dev-cli 0.19.0__tar.gz → 0.19.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.19.0 → fast_dev_cli-0.19.2}/PKG-INFO +1 -1
- fast_dev_cli-0.19.2/fast_dev_cli/__init__.py +1 -0
- {fast_dev_cli-0.19.0 → fast_dev_cli-0.19.2}/fast_dev_cli/cli.py +152 -98
- {fast_dev_cli-0.19.0 → fast_dev_cli-0.19.2}/pyproject.toml +2 -2
- {fast_dev_cli-0.19.0 → fast_dev_cli-0.19.2}/tests/test_deps.py +28 -0
- {fast_dev_cli-0.19.0 → fast_dev_cli-0.19.2}/tests/test_sync.py +26 -8
- fast_dev_cli-0.19.0/fast_dev_cli/__init__.py +0 -1
- {fast_dev_cli-0.19.0 → fast_dev_cli-0.19.2}/LICENSE +0 -0
- {fast_dev_cli-0.19.0 → fast_dev_cli-0.19.2}/README.md +0 -0
- {fast_dev_cli-0.19.0 → fast_dev_cli-0.19.2}/fast_dev_cli/__main__.py +0 -0
- {fast_dev_cli-0.19.0 → fast_dev_cli-0.19.2}/fast_dev_cli/py.typed +0 -0
- {fast_dev_cli-0.19.0 → fast_dev_cli-0.19.2}/pdm_build.py +0 -0
- {fast_dev_cli-0.19.0 → fast_dev_cli-0.19.2}/scripts/check.py +0 -0
- {fast_dev_cli-0.19.0 → fast_dev_cli-0.19.2}/scripts/deps.py +0 -0
- {fast_dev_cli-0.19.0 → fast_dev_cli-0.19.2}/scripts/format.py +0 -0
- {fast_dev_cli-0.19.0 → fast_dev_cli-0.19.2}/scripts/test.py +0 -0
- {fast_dev_cli-0.19.0 → fast_dev_cli-0.19.2}/tests/__init__.py +0 -0
- {fast_dev_cli-0.19.0 → fast_dev_cli-0.19.2}/tests/assets/uv-tx.lock +0 -0
- {fast_dev_cli-0.19.0 → fast_dev_cli-0.19.2}/tests/assets/uv.lock +0 -0
- {fast_dev_cli-0.19.0 → fast_dev_cli-0.19.2}/tests/conftest.py +0 -0
- {fast_dev_cli-0.19.0 → fast_dev_cli-0.19.2}/tests/test_bump.py +0 -0
- {fast_dev_cli-0.19.0 → fast_dev_cli-0.19.2}/tests/test_exec.py +0 -0
- {fast_dev_cli-0.19.0 → fast_dev_cli-0.19.2}/tests/test_fast_test.py +0 -0
- {fast_dev_cli-0.19.0 → fast_dev_cli-0.19.2}/tests/test_functions.py +0 -0
- {fast_dev_cli-0.19.0 → fast_dev_cli-0.19.2}/tests/test_help.py +0 -0
- {fast_dev_cli-0.19.0 → fast_dev_cli-0.19.2}/tests/test_lint.py +0 -0
- {fast_dev_cli-0.19.0 → fast_dev_cli-0.19.2}/tests/test_poetry_version_plugin.py +0 -0
- {fast_dev_cli-0.19.0 → fast_dev_cli-0.19.2}/tests/test_pypi.py +0 -0
- {fast_dev_cli-0.19.0 → fast_dev_cli-0.19.2}/tests/test_runserver.py +0 -0
- {fast_dev_cli-0.19.0 → fast_dev_cli-0.19.2}/tests/test_tag.py +0 -0
- {fast_dev_cli-0.19.0 → fast_dev_cli-0.19.2}/tests/test_upgrade.py +0 -0
- {fast_dev_cli-0.19.0 → fast_dev_cli-0.19.2}/tests/test_upload.py +0 -0
- {fast_dev_cli-0.19.0 → fast_dev_cli-0.19.2}/tests/test_version.py +0 -0
- {fast_dev_cli-0.19.0 → fast_dev_cli-0.19.2}/tests/utils.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.19.2"
|
|
@@ -12,16 +12,7 @@ import subprocess # nosec:B404
|
|
|
12
12
|
import sys
|
|
13
13
|
from functools import cached_property
|
|
14
14
|
from pathlib import Path
|
|
15
|
-
from typing import
|
|
16
|
-
TYPE_CHECKING,
|
|
17
|
-
Any,
|
|
18
|
-
Literal,
|
|
19
|
-
# Optional is required by Option generated by typer
|
|
20
|
-
Optional,
|
|
21
|
-
cast,
|
|
22
|
-
get_args,
|
|
23
|
-
overload,
|
|
24
|
-
)
|
|
15
|
+
from typing import TYPE_CHECKING, Any, Literal, cast, get_args, overload
|
|
25
16
|
|
|
26
17
|
import typer
|
|
27
18
|
from click import UsageError
|
|
@@ -57,7 +48,7 @@ if TYPE_CHECKING:
|
|
|
57
48
|
cli = typer.Typer(no_args_is_help=True)
|
|
58
49
|
DryOption = Option(False, "--dry", help="Only print, not really run shell command")
|
|
59
50
|
TOML_FILE = "pyproject.toml"
|
|
60
|
-
ToolName = Literal["
|
|
51
|
+
ToolName = Literal["uv", "pdm", "poetry"]
|
|
61
52
|
ToolOption = Option(
|
|
62
53
|
"auto", "--tool", help="Explicit declare manage tool (default to auto detect)"
|
|
63
54
|
)
|
|
@@ -391,7 +382,36 @@ class BumpUp(DryRun):
|
|
|
391
382
|
return is_emoji(first_char)
|
|
392
383
|
|
|
393
384
|
@staticmethod
|
|
385
|
+
def parse_dynamic_version(
|
|
386
|
+
toml_text: str,
|
|
387
|
+
context: dict,
|
|
388
|
+
work_dir: Path | None = None,
|
|
389
|
+
) -> str | None:
|
|
390
|
+
if work_dir is None:
|
|
391
|
+
work_dir = Project.get_work_dir()
|
|
392
|
+
for tool in ("pdm", "hatch"):
|
|
393
|
+
with contextlib.suppress(KeyError):
|
|
394
|
+
version_path = cast(str, context["tool"][tool]["version"]["path"])
|
|
395
|
+
if (
|
|
396
|
+
Path(version_path).exists()
|
|
397
|
+
or work_dir.joinpath(version_path).exists()
|
|
398
|
+
):
|
|
399
|
+
return version_path
|
|
400
|
+
# version = { source = "file", path = "fast_dev_cli/__init__.py" }
|
|
401
|
+
v_key = "version = "
|
|
402
|
+
p_key = 'path = "'
|
|
403
|
+
for line in toml_text.splitlines():
|
|
404
|
+
if not line.startswith(v_key):
|
|
405
|
+
continue
|
|
406
|
+
if p_key in (value := line.split(v_key, 1)[-1].split("#")[0]):
|
|
407
|
+
filename = value.split(p_key, 1)[-1].split('"')[0]
|
|
408
|
+
if work_dir.joinpath(filename).exists():
|
|
409
|
+
return filename
|
|
410
|
+
return None
|
|
411
|
+
|
|
412
|
+
@classmethod
|
|
394
413
|
def parse_filename(
|
|
414
|
+
cls,
|
|
395
415
|
toml_text: str | None = None,
|
|
396
416
|
work_dir: Path | None = None,
|
|
397
417
|
package_name: str | None = None,
|
|
@@ -414,74 +434,55 @@ class BumpUp(DryRun):
|
|
|
414
434
|
try:
|
|
415
435
|
version_value = context["tool"]["poetry"]["version"]
|
|
416
436
|
except KeyError:
|
|
417
|
-
if not Project.manage_by_poetry()
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
with contextlib.suppress(KeyError):
|
|
422
|
-
version_path = cast(
|
|
423
|
-
str, context["tool"][tool]["version"]["path"]
|
|
424
|
-
)
|
|
425
|
-
if (
|
|
426
|
-
Path(version_path).exists()
|
|
427
|
-
or work_dir.joinpath(version_path).exists()
|
|
428
|
-
):
|
|
429
|
-
return version_path
|
|
430
|
-
# version = { source = "file", path = "fast_dev_cli/__init__.py" }
|
|
431
|
-
v_key = "version = "
|
|
432
|
-
p_key = 'path = "'
|
|
433
|
-
for line in toml_text.splitlines():
|
|
434
|
-
if not line.startswith(v_key):
|
|
435
|
-
continue
|
|
436
|
-
if p_key in (value := line.split(v_key, 1)[-1].split("#")[0]):
|
|
437
|
-
filename = value.split(p_key, 1)[-1].split('"')[0]
|
|
438
|
-
if work_dir.joinpath(filename).exists():
|
|
439
|
-
return filename
|
|
437
|
+
if not Project.manage_by_poetry() and (
|
|
438
|
+
filename := cls.parse_dynamic_version(toml_text, context, work_dir)
|
|
439
|
+
):
|
|
440
|
+
return filename
|
|
440
441
|
else:
|
|
441
442
|
by_version_plugin = version_value in ("0", "0.0.0", "init")
|
|
442
443
|
if by_version_plugin:
|
|
444
|
+
return cls.parse_plugin_version(context, package_name)
|
|
445
|
+
|
|
446
|
+
return TOML_FILE
|
|
447
|
+
|
|
448
|
+
@staticmethod
|
|
449
|
+
def parse_plugin_version(context: dict, package_name: str | None) -> str:
|
|
450
|
+
try:
|
|
451
|
+
package_item = context["tool"]["poetry"]["packages"]
|
|
452
|
+
except KeyError:
|
|
443
453
|
try:
|
|
444
|
-
|
|
454
|
+
project_name = context["project"]["name"]
|
|
445
455
|
except KeyError:
|
|
446
|
-
|
|
447
|
-
project_name = context["project"]["name"]
|
|
448
|
-
except KeyError:
|
|
449
|
-
packages = []
|
|
450
|
-
else:
|
|
451
|
-
packages = [(poetry_module_name(project_name), "")]
|
|
456
|
+
packages = []
|
|
452
457
|
else:
|
|
453
|
-
packages = [
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
raise ParseError("Version file not found! Where are you now?")
|
|
482
|
-
return os.path.relpath(init_file, cwd)
|
|
483
|
-
|
|
484
|
-
return TOML_FILE
|
|
458
|
+
packages = [(poetry_module_name(project_name), "")]
|
|
459
|
+
else:
|
|
460
|
+
packages = [
|
|
461
|
+
(j, i.get("from", "")) for i in package_item if (j := i.get("include"))
|
|
462
|
+
]
|
|
463
|
+
# In case of managed by `poetry-plugin-version`
|
|
464
|
+
cwd = Path.cwd()
|
|
465
|
+
pattern = re.compile(r"__version__\s*=\s*['\"]")
|
|
466
|
+
ds: list[Path] = []
|
|
467
|
+
if package_name is not None:
|
|
468
|
+
packages.insert(0, (package_name, ""))
|
|
469
|
+
for package_name, source_dir in packages:
|
|
470
|
+
ds.append(cwd / package_name)
|
|
471
|
+
ds.append(cwd / "src" / package_name)
|
|
472
|
+
if source_dir and source_dir != "src":
|
|
473
|
+
ds.append(cwd / source_dir / package_name)
|
|
474
|
+
module_name = poetry_module_name(cwd.name)
|
|
475
|
+
ds.extend([cwd / module_name, cwd / "src" / module_name, cwd])
|
|
476
|
+
for d in ds:
|
|
477
|
+
init_file = d / "__init__.py"
|
|
478
|
+
if (init_file.exists() and pattern.search(init_file.read_text("utf8"))) or (
|
|
479
|
+
(init_file := init_file.with_name("__version__.py")).exists()
|
|
480
|
+
and pattern.search(init_file.read_text("utf8"))
|
|
481
|
+
):
|
|
482
|
+
break
|
|
483
|
+
else:
|
|
484
|
+
raise ParseError("Version file not found! Where are you now?")
|
|
485
|
+
return os.path.relpath(init_file, cwd)
|
|
485
486
|
|
|
486
487
|
def get_part(self, s: str) -> str:
|
|
487
488
|
choices: dict[str, str] = {}
|
|
@@ -517,7 +518,11 @@ class BumpUp(DryRun):
|
|
|
517
518
|
cmd += " && git push && git push --tags && git log -1"
|
|
518
519
|
else:
|
|
519
520
|
cmd += " --allow-dirty"
|
|
520
|
-
if
|
|
521
|
+
if (
|
|
522
|
+
should_sync
|
|
523
|
+
and not self._no_sync
|
|
524
|
+
and (sync := Project.get_sync_command(only_me=True))
|
|
525
|
+
):
|
|
521
526
|
cmd = f"{sync} && " + cmd
|
|
522
527
|
return cmd
|
|
523
528
|
|
|
@@ -561,7 +566,7 @@ def bump_version(
|
|
|
561
566
|
commit: bool = Option(
|
|
562
567
|
False, "--commit", "-c", help="Whether run `git commit` after version changed"
|
|
563
568
|
),
|
|
564
|
-
emoji:
|
|
569
|
+
emoji: bool | None = Option(
|
|
565
570
|
None, "--emoji", help="Whether add emoji prefix to commit message"
|
|
566
571
|
),
|
|
567
572
|
no_sync: bool = Option(
|
|
@@ -658,28 +663,64 @@ class Project:
|
|
|
658
663
|
text = cls.load_toml_text()
|
|
659
664
|
except EnvError:
|
|
660
665
|
return None
|
|
666
|
+
backend = ""
|
|
667
|
+
skip_uv = load_bool("FASTDEVCLI_SKIP_UV")
|
|
661
668
|
with contextlib.suppress(KeyError, tomllib.TOMLDecodeError):
|
|
662
669
|
doc = tomllib.loads(text)
|
|
663
670
|
backend = doc["build-system"]["build-backend"]
|
|
664
|
-
if
|
|
665
|
-
|
|
666
|
-
|
|
671
|
+
if skip_uv:
|
|
672
|
+
for t in ("pdm", "poetry"):
|
|
673
|
+
if t in backend:
|
|
674
|
+
cls._tool = t
|
|
675
|
+
return cls._tool
|
|
676
|
+
work_dir: Path | None = None
|
|
677
|
+
uv_lock_exists: bool | None = None
|
|
678
|
+
if skip_uv:
|
|
679
|
+
for name in ("pdm", "poetry"):
|
|
680
|
+
if f"[tool.{name}]" in text:
|
|
681
|
+
cls._tool = cast(ToolName, name)
|
|
682
|
+
return cls._tool
|
|
667
683
|
work_dir = cls.get_work_dir(allow_cwd=True)
|
|
668
|
-
|
|
669
|
-
|
|
684
|
+
for name in ("pdm", "poetry"):
|
|
685
|
+
if Path(work_dir, f"{name}.lock").exists():
|
|
686
|
+
cls._tool = cast(ToolName, name)
|
|
687
|
+
return cls._tool
|
|
688
|
+
if uv_lock_exists := Path(work_dir, "uv.lock").exists():
|
|
689
|
+
# Use pdm when uv is not available for uv managed project
|
|
670
690
|
cls._tool = "pdm"
|
|
671
|
-
if not Path(work_dir, "pdm.lock").exists() and (
|
|
672
|
-
uv_lock_exists or "[tool.uv]" in text
|
|
673
|
-
):
|
|
674
|
-
cls._tool = "uv"
|
|
675
|
-
return cls._tool
|
|
676
|
-
elif uv_lock_exists:
|
|
677
|
-
cls._tool = "uv"
|
|
678
691
|
return cls._tool
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
692
|
+
return None
|
|
693
|
+
if work_dir is None:
|
|
694
|
+
work_dir = cls.get_work_dir(allow_cwd=True)
|
|
695
|
+
if uv_lock_exists is None:
|
|
696
|
+
uv_lock_exists = Path(work_dir, "uv.lock").exists()
|
|
697
|
+
if uv_lock_exists:
|
|
698
|
+
cls._tool = "uv"
|
|
699
|
+
return cls._tool
|
|
700
|
+
pdm_lock_exists = Path(work_dir, "pdm.lock").exists()
|
|
701
|
+
poetry_lock_exists = Path(work_dir, "poetry.lock").exists()
|
|
702
|
+
match pdm_lock_exists + poetry_lock_exists:
|
|
703
|
+
case 1:
|
|
704
|
+
cls._tool = "pdm" if pdm_lock_exists else "poetry"
|
|
682
705
|
return cls._tool
|
|
706
|
+
case _ as x:
|
|
707
|
+
if backend:
|
|
708
|
+
for t in ("pdm", "poetry"):
|
|
709
|
+
if t in backend:
|
|
710
|
+
cls._tool = cast(ToolName, t)
|
|
711
|
+
return cls._tool
|
|
712
|
+
for name in ("pdm", "poetry"):
|
|
713
|
+
if f"[tool.{name}]" in text:
|
|
714
|
+
cls._tool = cast(ToolName, name)
|
|
715
|
+
return cls._tool
|
|
716
|
+
if x == 2:
|
|
717
|
+
cls._tool = (
|
|
718
|
+
"poetry" if load_bool("FASTDEVCLI_PREFER_POETRY") else "pdm"
|
|
719
|
+
)
|
|
720
|
+
return cls._tool
|
|
721
|
+
if "[tool.uv]" in text or load_bool("FASTDEVCLI_PREFER_uv"):
|
|
722
|
+
cls._tool = "uv"
|
|
723
|
+
return cls._tool
|
|
683
724
|
# Poetry 2.0 default to not include the '[tool.poetry]' section
|
|
684
725
|
if cls.is_poetry_v2(text):
|
|
685
726
|
cls._tool = "poetry"
|
|
@@ -708,9 +749,12 @@ class Project:
|
|
|
708
749
|
return True
|
|
709
750
|
|
|
710
751
|
@classmethod
|
|
711
|
-
def get_sync_command(
|
|
752
|
+
def get_sync_command(
|
|
753
|
+
cls, prod: bool = True, doc: dict | None = None, only_me: bool = False
|
|
754
|
+
) -> str:
|
|
755
|
+
pdm_i = "pdm install --frozen" + " --prod" * prod
|
|
712
756
|
if cls.is_pdm_project():
|
|
713
|
-
return
|
|
757
|
+
return pdm_i
|
|
714
758
|
elif cls.manage_by_poetry(cache=True):
|
|
715
759
|
cmd = "poetry install"
|
|
716
760
|
if prod:
|
|
@@ -725,7 +769,17 @@ class Project:
|
|
|
725
769
|
cmd += " --only=main"
|
|
726
770
|
return cmd
|
|
727
771
|
elif cls.get_manage_tool(cache=True) == "uv":
|
|
728
|
-
|
|
772
|
+
install_me = "uv pip install -e ."
|
|
773
|
+
if doc is None:
|
|
774
|
+
doc = tomllib.loads(cls.load_toml_text())
|
|
775
|
+
is_distribution = (
|
|
776
|
+
doc.get("tool", {}).get("pdm", {}).get("distribution") is not False
|
|
777
|
+
)
|
|
778
|
+
if only_me:
|
|
779
|
+
return install_me if is_distribution else pdm_i
|
|
780
|
+
cmd = "uv sync --inexact" + " --no-dev" * prod
|
|
781
|
+
if is_distribution:
|
|
782
|
+
cmd += f" && {install_me}"
|
|
729
783
|
return ""
|
|
730
784
|
|
|
731
785
|
@classmethod
|
|
@@ -1215,7 +1269,7 @@ def check(
|
|
|
1215
1269
|
|
|
1216
1270
|
@cli.command(name="lint")
|
|
1217
1271
|
def make_style(
|
|
1218
|
-
files:
|
|
1272
|
+
files: list[str] | None = typer.Argument(default=None), # noqa:B008
|
|
1219
1273
|
check_only: bool = Option(False, "--check-only", "-c"),
|
|
1220
1274
|
bandit: bool = Option(False, "--bandit", help="Run `bandit -r <package_dir>`"),
|
|
1221
1275
|
prefix: bool = Option(
|
|
@@ -1398,9 +1452,9 @@ def dev(
|
|
|
1398
1452
|
|
|
1399
1453
|
@cli.command(name="dev")
|
|
1400
1454
|
def runserver(
|
|
1401
|
-
file_or_port:
|
|
1402
|
-
port:
|
|
1403
|
-
host:
|
|
1455
|
+
file_or_port: str | None = typer.Argument(default=None),
|
|
1456
|
+
port: int | None = Option(None, "-p", "--port"),
|
|
1457
|
+
host: str | None = Option(None, "-h", "--host"),
|
|
1404
1458
|
dry: bool = DryOption,
|
|
1405
1459
|
) -> None:
|
|
1406
1460
|
"""Start a fastapi server(only for fastapi>=0.111.0)"""
|
|
@@ -1588,7 +1642,7 @@ class UvPypi(DryRun):
|
|
|
1588
1642
|
|
|
1589
1643
|
@cli.command()
|
|
1590
1644
|
def pypi(
|
|
1591
|
-
file:
|
|
1645
|
+
file: str | None = typer.Argument(default=None),
|
|
1592
1646
|
dry: bool = DryOption,
|
|
1593
1647
|
verbose: bool = False,
|
|
1594
1648
|
quiet: bool = False,
|
|
@@ -41,7 +41,7 @@ dependencies = [
|
|
|
41
41
|
"bumpversion2 >=1.4.3",
|
|
42
42
|
"pytest >=8.2.0",
|
|
43
43
|
]
|
|
44
|
-
version = "0.19.
|
|
44
|
+
version = "0.19.2"
|
|
45
45
|
|
|
46
46
|
[project.urls]
|
|
47
47
|
Homepage = "https://github.com/waketzheng/fast-dev-cli"
|
|
@@ -57,7 +57,7 @@ fast = "fast_dev_cli:cli.main"
|
|
|
57
57
|
[dependency-groups]
|
|
58
58
|
dev = [
|
|
59
59
|
"twine>=6.1.0",
|
|
60
|
-
"asynctor>=0.
|
|
60
|
+
"asynctor>=0.10.0",
|
|
61
61
|
]
|
|
62
62
|
|
|
63
63
|
[tool.pdm]
|
|
@@ -48,3 +48,31 @@ def test_fast_deps():
|
|
|
48
48
|
assert out == "--> uv sync --active --all-extras --all-groups"
|
|
49
49
|
out = capture_cmd_output("fast deps --uv --dry --no-active --no-inexact")
|
|
50
50
|
assert out == "--> uv sync --all-extras --all-groups"
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def test_smart_fast_deps(tmp_work_dir, monkeypatch):
|
|
54
|
+
toml_file = tmp_work_dir.joinpath("pyproject.toml")
|
|
55
|
+
if toml_file.exists():
|
|
56
|
+
toml_file.unlink()
|
|
57
|
+
tmp_work_dir.joinpath("uv.lock").touch()
|
|
58
|
+
out = capture_cmd_output("fast deps --dry")
|
|
59
|
+
assert (
|
|
60
|
+
out
|
|
61
|
+
== "--> python -m ensurepip && python -m pip install --upgrade pip && python -m pip install -e . --group dev"
|
|
62
|
+
)
|
|
63
|
+
toml_file.touch()
|
|
64
|
+
out = capture_cmd_output("fast deps --dry")
|
|
65
|
+
assert out == "--> uv sync --inexact --active --all-extras --all-groups"
|
|
66
|
+
pdm_lock = tmp_work_dir.joinpath("pdm.lock")
|
|
67
|
+
pdm_lock.touch()
|
|
68
|
+
out = capture_cmd_output("fast deps --dry")
|
|
69
|
+
assert out == "--> uv sync --inexact --active --all-extras --all-groups"
|
|
70
|
+
toml_file.write_text("[tool.pdm]\ndistribution=false")
|
|
71
|
+
out = capture_cmd_output("fast deps --dry")
|
|
72
|
+
assert out == "--> uv sync --inexact --active --all-extras --all-groups"
|
|
73
|
+
monkeypatch.setenv("FASTDEVCLI_SKIP_UV", "1")
|
|
74
|
+
out = capture_cmd_output("fast deps --dry")
|
|
75
|
+
assert out == "--> pdm install --frozen -G :all"
|
|
76
|
+
pdm_lock.unlink()
|
|
77
|
+
out = capture_cmd_output("fast deps --dry")
|
|
78
|
+
assert out == "--> pdm install --frozen -G :all"
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import functools
|
|
3
4
|
from pathlib import Path
|
|
4
5
|
|
|
5
6
|
import pytest
|
|
@@ -30,6 +31,16 @@ build-backend = "poetry.core.masonry.api"
|
|
|
30
31
|
"""
|
|
31
32
|
|
|
32
33
|
|
|
34
|
+
@functools.cache
|
|
35
|
+
def is_pip_installed() -> bool:
|
|
36
|
+
try:
|
|
37
|
+
import pip # NOQA
|
|
38
|
+
except ImportError:
|
|
39
|
+
return False
|
|
40
|
+
else:
|
|
41
|
+
return True
|
|
42
|
+
|
|
43
|
+
|
|
33
44
|
def test_sync_not_in_venv(mocker, capsys):
|
|
34
45
|
mocker.patch("fast_dev_cli.cli.is_venv", return_value=False)
|
|
35
46
|
test_dir = Path(__file__).parent
|
|
@@ -44,10 +55,15 @@ def test_sync_not_in_venv(mocker, capsys):
|
|
|
44
55
|
mocker.patch(
|
|
45
56
|
"fast_dev_cli.cli.UpgradeDependencies.should_with_dev", return_value=True
|
|
46
57
|
)
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
58
|
+
pdm_export = "pdm export --without-hashes --with=dev -o req.txt"
|
|
59
|
+
installing = "pdm run python -m pip install -r req.txt"
|
|
60
|
+
if not is_pip_installed():
|
|
61
|
+
installing = (
|
|
62
|
+
"pdm run python -m ensurepip && pdm run python -m pip install -U pip && "
|
|
63
|
+
+ installing
|
|
64
|
+
)
|
|
65
|
+
expected = f"{pdm_export} && {installing}"
|
|
66
|
+
assert Sync("req.txt", "", True, dry=True).gen() == expected
|
|
51
67
|
|
|
52
68
|
|
|
53
69
|
def test_sync(mocker):
|
|
@@ -62,10 +78,12 @@ def test_sync(mocker):
|
|
|
62
78
|
mocker.patch(
|
|
63
79
|
"fast_dev_cli.cli.UpgradeDependencies.should_with_dev", return_value=True
|
|
64
80
|
)
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
81
|
+
pdm_export = "pdm export --without-hashes --with=dev -o req.txt"
|
|
82
|
+
if is_pip_installed():
|
|
83
|
+
expected = f"{pdm_export} && python -m pip install -r req.txt"
|
|
84
|
+
else:
|
|
85
|
+
expected = f"{pdm_export} && python -m ensurepip && python -m pip install -U pip && python -m pip install -r req.txt"
|
|
86
|
+
assert Sync("req.txt", "", True, dry=True).gen() == expected
|
|
69
87
|
|
|
70
88
|
|
|
71
89
|
UV_TOML_EXAMPLE = """
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.19.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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|