fast-dev-cli 0.9.3__tar.gz → 0.9.5__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.
Files changed (27) hide show
  1. {fast_dev_cli-0.9.3 → fast_dev_cli-0.9.5}/PKG-INFO +2 -2
  2. fast_dev_cli-0.9.5/fast_dev_cli/__init__.py +1 -0
  3. {fast_dev_cli-0.9.3 → fast_dev_cli-0.9.5}/fast_dev_cli/cli.py +27 -20
  4. {fast_dev_cli-0.9.3 → fast_dev_cli-0.9.5}/pdm_build.py +7 -7
  5. {fast_dev_cli-0.9.3 → fast_dev_cli-0.9.5}/pyproject.toml +2 -2
  6. {fast_dev_cli-0.9.3 → fast_dev_cli-0.9.5}/scripts/format.sh +1 -1
  7. {fast_dev_cli-0.9.3 → fast_dev_cli-0.9.5}/tests/test_fast_test.py +2 -2
  8. {fast_dev_cli-0.9.3 → fast_dev_cli-0.9.5}/tests/test_lint.py +3 -2
  9. fast_dev_cli-0.9.5/tests/test_poetry_version_plugin.py +62 -0
  10. {fast_dev_cli-0.9.3 → fast_dev_cli-0.9.5}/tests/test_runserver.py +14 -14
  11. {fast_dev_cli-0.9.3 → fast_dev_cli-0.9.5}/tests/test_tag.py +2 -3
  12. {fast_dev_cli-0.9.3 → fast_dev_cli-0.9.5}/tests/test_upgrade.py +20 -0
  13. {fast_dev_cli-0.9.3 → fast_dev_cli-0.9.5}/tests/test_upload.py +1 -1
  14. fast_dev_cli-0.9.3/fast_dev_cli/__init__.py +0 -1
  15. {fast_dev_cli-0.9.3 → fast_dev_cli-0.9.5}/LICENSE +0 -0
  16. {fast_dev_cli-0.9.3 → fast_dev_cli-0.9.5}/README.md +0 -0
  17. {fast_dev_cli-0.9.3 → fast_dev_cli-0.9.5}/fast_dev_cli/__main__.py +0 -0
  18. {fast_dev_cli-0.9.3 → fast_dev_cli-0.9.5}/fast_dev_cli/py.typed +0 -0
  19. {fast_dev_cli-0.9.3 → fast_dev_cli-0.9.5}/scripts/check.sh +0 -0
  20. {fast_dev_cli-0.9.3 → fast_dev_cli-0.9.5}/scripts/test.sh +0 -0
  21. {fast_dev_cli-0.9.3 → fast_dev_cli-0.9.5}/tests/__init__.py +0 -0
  22. {fast_dev_cli-0.9.3 → fast_dev_cli-0.9.5}/tests/conftest.py +0 -0
  23. {fast_dev_cli-0.9.3 → fast_dev_cli-0.9.5}/tests/test_bump.py +0 -0
  24. {fast_dev_cli-0.9.3 → fast_dev_cli-0.9.5}/tests/test_functions.py +0 -0
  25. {fast_dev_cli-0.9.3 → fast_dev_cli-0.9.5}/tests/test_sync.py +0 -0
  26. {fast_dev_cli-0.9.3 → fast_dev_cli-0.9.5}/tests/test_version.py +0 -0
  27. {fast_dev_cli-0.9.3 → fast_dev_cli-0.9.5}/tests/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fast-dev-cli
3
- Version: 0.9.3
3
+ Version: 0.9.5
4
4
  Summary: Python project development tool.
5
5
  Author-Email: Waket Zheng <waketzheng@gmail.com>>
6
6
  Classifier: Development Status :: 4 - Beta
@@ -23,7 +23,7 @@ Requires-Python: <4,>=3.10
23
23
  Requires-Dist: typer<0.13,>=0.12.3
24
24
  Requires-Dist: tomli<3,>=2.0.1; python_version < "3.11"
25
25
  Requires-Dist: coverage<8,>=7.5.1
26
- Requires-Dist: ruff<0.6,>=0.4.4
26
+ Requires-Dist: ruff<0.7,>=0.4.4
27
27
  Requires-Dist: mypy<2,>=1.10.0
28
28
  Requires-Dist: bumpversion2<2,>=1.4.0
29
29
  Requires-Dist: pytest<9,>=8.2.0
@@ -0,0 +1 @@
1
+ __version__ = "0.9.5"
@@ -35,10 +35,6 @@ else: # pragma: no cover
35
35
  __str__ = str.__str__
36
36
 
37
37
 
38
- def parse_files(args: list[str] | tuple[str, ...]) -> list[str]:
39
- return [i for i in args if not i.startswith("-")]
40
-
41
-
42
38
  TOML_FILE = "pyproject.toml"
43
39
  cli = typer.Typer()
44
40
 
@@ -176,12 +172,13 @@ class BumpUp(DryRun):
176
172
  pattern = re.compile(r"__version__\s*=\s*['\"]")
177
173
  ds = [cwd / i for i in packages] + [cwd / cwd.name.replace("-", "_"), cwd]
178
174
  for d in ds:
179
- if (init_file := d / "__init__.py").exists():
180
- if pattern.search(init_file.read_text()):
181
- break
175
+ if (init_file := d / "__init__.py").exists() and pattern.search(
176
+ init_file.read_text()
177
+ ):
178
+ break
182
179
  else:
183
180
  raise ParseError("Version file not found! Where are you now?")
184
- return init_file.relative_to(cwd).as_posix()
181
+ return os.path.relpath(init_file, cwd)
185
182
 
186
183
  return TOML_FILE
187
184
 
@@ -203,11 +200,9 @@ class BumpUp(DryRun):
203
200
  if self.part:
204
201
  part = self.get_part(self.part)
205
202
  else:
206
- tip = "Which one?"
207
- if a := input(tip).strip():
203
+ part = "patch"
204
+ if a := input("Which one?").strip():
208
205
  part = self.get_part(a)
209
- else:
210
- part = "patch"
211
206
  self.part = part
212
207
  parse = r'--parse "(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)"'
213
208
  cmd = f'bumpversion {parse} --current-version="{_version}" {part} {filename}'
@@ -369,6 +364,9 @@ class UpgradeDependencies(Project, DryRun):
369
364
  if v == "*":
370
365
  echo(f"Skip wildcard line: {line}")
371
366
  return True
367
+ elif v == "[":
368
+ echo(f"Skip complex dependence: {line}")
369
+ return True
372
370
  elif v.startswith(">") or v.startswith("<") or v[0].isdigit():
373
371
  echo(f"Ignore bigger/smaller/equal: {line}")
374
372
  return True
@@ -380,13 +378,18 @@ class UpgradeDependencies(Project, DryRun):
380
378
  ) -> tuple[list[str], dict[str, list[str]]]:
381
379
  args: list[str] = [] # ['typer[all]', 'fastapi']
382
380
  specials: dict[str, list[str]] = {} # {'--platform linux': ['gunicorn']}
383
- for line in package_lines:
384
- if not (m := line.strip()) or m.startswith("#"):
381
+ for no, line in enumerate(package_lines, 1):
382
+ if (
383
+ not (m := line.strip())
384
+ or m.startswith("#")
385
+ or m == "]"
386
+ or (m.startswith("{") and m.strip(",").endswith("}"))
387
+ ):
385
388
  continue
386
389
  try:
387
390
  package, version_info = m.split("=", 1)
388
391
  except ValueError as e:
389
- raise ParseError(f"{m = }") from e
392
+ raise ParseError(f"Failed to separate by '='@line {no}: {m}") from e
390
393
  if (package := package.strip()).lower() == "python":
391
394
  continue
392
395
  if cls.no_need_upgrade(version_info := version_info.strip(' "'), line):
@@ -553,7 +556,7 @@ class LintCode(DryRun):
553
556
  @classmethod
554
557
  def to_cmd(cls: Type[Self], paths=".", check_only=False) -> str:
555
558
  cmd = ""
556
- tools = ["ruff format", "ruff check --extend-select=I --fix", "mypy"]
559
+ tools = ["ruff format", "ruff check --extend-select=I,B,SIM --fix", "mypy"]
557
560
  if check_only:
558
561
  tools[0] += " --check"
559
562
  if check_only or load_bool("NO_FIX"):
@@ -571,8 +574,8 @@ class LintCode(DryRun):
571
574
  should_run_by_tool = True
572
575
  if check_call("python -c 'import fast_dev_cli'"):
573
576
  command = 'python -m pip install -U "fast_dev_cli"'
574
- tip = "You may need to run following command to install lint tools"
575
- secho(f"{tip}:\n\n {command}\n", fg="yellow")
577
+ tip = "You may need to run following command to install lint tools:"
578
+ secho(f"{tip}\n\n {command}\n", fg="yellow")
576
579
  else:
577
580
  should_run_by_tool = True
578
581
  if should_run_by_tool:
@@ -585,6 +588,10 @@ class LintCode(DryRun):
585
588
  return self.to_cmd(paths, self.check_only)
586
589
 
587
590
 
591
+ def parse_files(args: list[str] | tuple[str, ...]) -> list[str]:
592
+ return [i for i in args if not i.startswith("-")]
593
+
594
+
588
595
  def lint(files=None, dry=False) -> None:
589
596
  if files is None:
590
597
  files = parse_files(sys.argv[1:])
@@ -668,7 +675,7 @@ def test(dry: bool, ignore_script=False) -> None:
668
675
  root = Project.get_work_dir(cwd=cwd, allow_cwd=True)
669
676
  test_script = root / "scripts" / "test.sh"
670
677
  if not _ensure_bool(ignore_script) and _should_run_test_script(test_script):
671
- cmd = f"sh {test_script.relative_to(root)}"
678
+ cmd = f"sh {os.path.relpath(test_script, root)}"
672
679
  if cwd != root:
673
680
  cmd = f"cd {root} && " + cmd
674
681
  else:
@@ -713,7 +720,7 @@ def dev(
713
720
  cmd += f" {file}"
714
721
  else:
715
722
  if port != 8000:
716
- cmd += f" --{port=}"
723
+ cmd += f" --port={port}"
717
724
  no_port_yet = False
718
725
  if no_port_yet and (port := getattr(port, "default", port)) and str(port) != "8000":
719
726
  cmd += f" --port={port}"
@@ -1,5 +1,5 @@
1
1
  import os
2
- from typing import Any, Dict, List
2
+ from typing import Any
3
3
 
4
4
  from pdm.backend.hooks import Context
5
5
 
@@ -9,30 +9,30 @@ BUILD_PACKAGE = os.getenv("BUILD_PACKAGE", "fast-dev-cli")
9
9
  def pdm_build_initialize(context: Context) -> None:
10
10
  metadata = context.config.metadata
11
11
  # Get custom config for the current package, from the env var
12
- config: Dict[str, Any] = context.config.data["tool"]["waketzheng"][
12
+ config: dict[str, Any] = context.config.data["tool"]["waketzheng"][
13
13
  "_internal-slim-build"
14
14
  ]["packages"][BUILD_PACKAGE]
15
- project_config: Dict[str, Any] = config["project"]
15
+ project_config: dict[str, Any] = config["project"]
16
16
  # Get main optional dependencies, extras
17
- optional_dependencies: Dict[str, List[str]] = metadata.get(
17
+ optional_dependencies: dict[str, list[str]] = metadata.get(
18
18
  "optional-dependencies", {}
19
19
  )
20
20
  # Get custom optional dependencies name to always include in this (non-slim) package
21
- include_optional_dependencies: List[str] = config.get(
21
+ include_optional_dependencies: list[str] = config.get(
22
22
  "include-optional-dependencies", []
23
23
  )
24
24
  # Override main [project] configs with custom configs for this package
25
25
  for key, value in project_config.items():
26
26
  metadata[key] = value
27
27
  # Get custom build config for the current package
28
- build_config: Dict[str, Any] = (
28
+ build_config: dict[str, Any] = (
29
29
  config.get("tool", {}).get("pdm", {}).get("build", {})
30
30
  )
31
31
  # Override PDM build config with custom build config for this package
32
32
  for key, value in build_config.items():
33
33
  context.config.build_config[key] = value
34
34
  # Get main dependencies
35
- dependencies: List[str] = metadata.get("dependencies", [])
35
+ dependencies: list[str] = metadata.get("dependencies", [])
36
36
  # Add optional dependencies to the default dependencies for this (non-slim) package
37
37
  for include_optional in include_optional_dependencies:
38
38
  optional_dependencies_group = optional_dependencies.get(include_optional, [])
@@ -34,12 +34,12 @@ dependencies = [
34
34
  "typer>=0.12.3,<0.13",
35
35
  "tomli>=2.0.1,<3; python_version < '3.11'",
36
36
  "coverage >=7.5.1,<8",
37
- "ruff >=0.4.4,<0.6",
37
+ "ruff >=0.4.4,<0.7",
38
38
  "mypy >=1.10.0,<2",
39
39
  "bumpversion2 >=1.4.0,<2",
40
40
  "pytest >=8.2.0,<9",
41
41
  ]
42
- version = "0.9.3"
42
+ version = "0.9.5"
43
43
 
44
44
  [project.urls]
45
45
  Homepage = "https://github.com/waketzheng/fast-dev-cli"
@@ -3,4 +3,4 @@ set -x
3
3
 
4
4
  [ -f ../pyproject.toml ] && cd ..
5
5
 
6
- pdm run fast lint
6
+ SKIP_MYPY=1 pdm run fast lint
@@ -41,7 +41,7 @@ def test_test_with_poetry_or_pdm_run(mocker: MockerFixture, capsys):
41
41
  if tool := Project.get_manage_tool():
42
42
  command = tool + " run " + command
43
43
  assert (
44
- '--> {0} run -m pytest -s && {0} report --omit="tests/*" -m'.format(command)
44
+ f'--> {command} run -m pytest -s && {command} report --omit="tests/*" -m'
45
45
  in capsys.readouterr().out
46
46
  )
47
47
 
@@ -54,7 +54,7 @@ def test_test_not_in_venv(mocker: MockerFixture, capsys):
54
54
  if tool := Project.get_manage_tool():
55
55
  command = tool + " run " + command
56
56
  assert (
57
- '--> {0} run -m pytest -s && {0} report --omit="tests/*" -m'.format(command)
57
+ f'--> {command} run -m pytest -s && {command} report --omit="tests/*" -m'
58
58
  in capsys.readouterr().out
59
59
  )
60
60
 
@@ -41,8 +41,9 @@ def mock_ignore_missing_imports_0(monkeypatch):
41
41
 
42
42
 
43
43
  SEP = " && "
44
- LINT_CMD = "ruff format . && ruff check --extend-select=I --fix . && mypy ."
45
- CHECK_CMD = "ruff format --check . && ruff check --extend-select=I . && mypy ."
44
+ _CMD = "ruff format{} . && ruff check --extend-select=I,B,SIM{} . && mypy ."
45
+ LINT_CMD = _CMD.format("", " --fix")
46
+ CHECK_CMD = _CMD.format(" --check", "")
46
47
 
47
48
 
48
49
  def test_check():
@@ -0,0 +1,62 @@
1
+ from pathlib import Path
2
+
3
+ import pytest
4
+
5
+ from fast_dev_cli.cli import (
6
+ TOML_FILE,
7
+ BumpUp,
8
+ ParseError,
9
+ run_and_echo,
10
+ )
11
+
12
+ from .utils import chdir
13
+
14
+ CONF = """
15
+
16
+ [tool.poetry-version-plugin]
17
+ source = "init"
18
+ """
19
+
20
+
21
+ def test_version_plugin(tmp_path: Path) -> None:
22
+ package_path = tmp_path / "helloworld"
23
+ toml_file = package_path / TOML_FILE
24
+ init_file = package_path / package_path.name / "__init__.py"
25
+ a, b = 'version = "0.1.0"', 'version = "0"'
26
+ with chdir(tmp_path):
27
+ run_and_echo(f"poetry new {package_path.name}")
28
+ with chdir(package_path):
29
+ text = toml_file.read_text().replace(a, b)
30
+ toml_file.write_text(text + CONF)
31
+ init_file.write_text('__version__ = "0.0.1"\n')
32
+ assert (
33
+ BumpUp(part="patch", commit=False, dry=True).gen()
34
+ == 'bumpversion --parse "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)" --current-version="0.0.1" patch helloworld/__init__.py --allow-dirty'
35
+ )
36
+ run_and_echo("poetry run fast bump patch")
37
+ assert init_file.read_text() == '__version__ = "0.0.2"\n'
38
+ init_file.unlink()
39
+ with pytest.raises(ParseError, match=r"Version file not found!.*"):
40
+ BumpUp(part="patch", commit=False, dry=True).gen()
41
+
42
+
43
+ def test_version_plugin_include_defined(tmp_path: Path) -> None:
44
+ package_path = tmp_path / "hello world"
45
+ toml_file = package_path / TOML_FILE
46
+ package_name = package_path.name.replace(" ", "_")
47
+ init_file = package_path / package_name / "__init__.py"
48
+ a, b = 'version = "0.1.0"', 'version = "0"'
49
+ b += '\npackages = [{include = "%s"}]' % package_name
50
+ with chdir(tmp_path):
51
+ run_and_echo(f"poetry new '{package_path.name}'")
52
+ with chdir(package_path):
53
+ text = toml_file.read_text().replace(a, b)
54
+ toml_file.write_text(text + CONF)
55
+ run_and_echo(f"mv '{package_path.name}' {package_name}")
56
+ init_file.write_text('__version__ = "0.0.1"\n')
57
+ assert (
58
+ BumpUp(part="patch", commit=False, dry=True).gen()
59
+ == f'bumpversion --parse "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)" --current-version="0.0.1" patch {package_name}/__init__.py --allow-dirty'
60
+ )
61
+ run_and_echo("poetry run fast bump patch")
62
+ assert init_file.read_text() == '__version__ = "0.0.2"\n'
@@ -4,49 +4,49 @@ from fast_dev_cli.cli import dev, run_and_echo, runserver
4
4
  def test_runserver(capsys):
5
5
  runserver(dry=True)
6
6
  out = capsys.readouterr().out.strip()
7
- assert "fastapi dev" == out.replace("--> ", "")
7
+ assert out.replace("--> ", "") == "fastapi dev"
8
8
  runserver(port=8000, dry=True)
9
9
  out = capsys.readouterr().out.strip()
10
- assert "fastapi dev" == out.replace("--> ", "")
10
+ assert out.replace("--> ", "") == "fastapi dev"
11
11
  runserver(port=9000, dry=True)
12
12
  out = capsys.readouterr().out.strip()
13
- assert "fastapi dev --port=9000" == out.replace("--> ", "")
13
+ assert out.replace("--> ", "") == "fastapi dev --port=9000"
14
14
  runserver(host="0.0.0.0", dry=True)
15
15
  out = capsys.readouterr().out.strip()
16
- assert "fastapi dev --host=0.0.0.0" == out.replace("--> ", "")
16
+ assert out.replace("--> ", "") == "fastapi dev --host=0.0.0.0"
17
17
  runserver(port=9000, host="0.0.0.0", dry=True)
18
18
  out = capsys.readouterr().out.strip()
19
- assert "fastapi dev --port=9000 --host=0.0.0.0" == out.replace("--> ", "")
19
+ assert out.replace("--> ", "") == "fastapi dev --port=9000 --host=0.0.0.0"
20
20
 
21
21
 
22
22
  def test_dev(capsys):
23
23
  dev(None, None, dry=True)
24
24
  out = capsys.readouterr().out.strip()
25
- assert "fastapi dev" == out.replace("--> ", "")
25
+ assert out.replace("--> ", "") == "fastapi dev"
26
26
  dev(port=8000, host="", dry=True)
27
27
  out = capsys.readouterr().out.strip()
28
- assert "fastapi dev" == out.replace("--> ", "")
28
+ assert out.replace("--> ", "") == "fastapi dev"
29
29
  dev(port=9000, host=None, dry=True)
30
30
  out = capsys.readouterr().out.strip()
31
- assert "fastapi dev --port=9000" == out.replace("--> ", "")
31
+ assert out.replace("--> ", "") == "fastapi dev --port=9000"
32
32
  dev(8000, host="0.0.0.0", dry=True)
33
33
  out = capsys.readouterr().out.strip()
34
- assert "fastapi dev --host=0.0.0.0" == out.replace("--> ", "")
34
+ assert out.replace("--> ", "") == "fastapi dev --host=0.0.0.0"
35
35
  dev(port=9000, host="0.0.0.0", dry=True)
36
36
  out = capsys.readouterr().out.strip()
37
- assert "fastapi dev --port=9000 --host=0.0.0.0" == out.replace("--> ", "")
37
+ assert out.replace("--> ", "") == "fastapi dev --port=9000 --host=0.0.0.0"
38
38
  dev(8001, host="0.0.0.0", dry=True)
39
39
  out = capsys.readouterr().out.strip()
40
- assert "fastapi dev --port=8001 --host=0.0.0.0" == out.replace("--> ", "")
40
+ assert out.replace("--> ", "") == "fastapi dev --port=8001 --host=0.0.0.0"
41
41
  dev(None, file="8001", host="0.0.0.0", dry=True)
42
42
  out = capsys.readouterr().out.strip()
43
- assert "fastapi dev --port=8001 --host=0.0.0.0" == out.replace("--> ", "")
43
+ assert out.replace("--> ", "") == "fastapi dev --port=8001 --host=0.0.0.0"
44
44
  dev(None, file="main.py", host="0.0.0.0", dry=True)
45
45
  out = capsys.readouterr().out.strip()
46
- assert "fastapi dev main.py --host=0.0.0.0" == out.replace("--> ", "")
46
+ assert out.replace("--> ", "") == "fastapi dev main.py --host=0.0.0.0"
47
47
  dev(8001, file="main.py", host="0.0.0.0", dry=True)
48
48
  out = capsys.readouterr().out.strip()
49
- assert "fastapi dev main.py --port=8001 --host=0.0.0.0" == out.replace("--> ", "")
49
+ assert out.replace("--> ", "") == "fastapi dev main.py --port=8001 --host=0.0.0.0"
50
50
 
51
51
 
52
52
  def test_fast_dev(tmp_path):
@@ -16,9 +16,8 @@ def test_tag():
16
16
  GitTag(message="", dry=True).run()
17
17
  assert "git tag -a" in stream.getvalue()
18
18
 
19
- with temp_file("foo.txt"):
20
- with capture_stdout() as stream:
21
- GitTag(message="", dry=True).run()
19
+ with temp_file("foo.txt"), capture_stdout() as stream:
20
+ GitTag(message="", dry=True).run()
22
21
 
23
22
  assert "git status" in stream.getvalue()
24
23
  assert "ERROR" in stream.getvalue()
@@ -258,3 +258,23 @@ def test_get_dir(mocker, tmp_path):
258
258
  assert UpgradeDependencies.get_root_dir() == parent
259
259
  mocker.patch.object(UpgradeDependencies, "python_exec_dir", return_value=me)
260
260
  assert UpgradeDependencies.get_root_dir() == root
261
+
262
+
263
+ def test_parse_complex_segment():
264
+ segment = """
265
+ [tool.poetry.dependencies]
266
+ torch = [
267
+ {version="*",platform="linux"},
268
+ {version="^1.2.0",platform=""},
269
+ {version=">=1.2.0",platform=""},
270
+ ]
271
+ fastapi = "^0.112.2"
272
+
273
+ [tool.isort]
274
+ """.strip()
275
+ assert UpgradeDependencies.get_args(segment) == (
276
+ ['"fastapi@latest"'],
277
+ [],
278
+ [],
279
+ "--dev",
280
+ )
@@ -4,4 +4,4 @@ from fast_dev_cli.cli import upload
4
4
  def test_upload(capsys):
5
5
  upload(dry=True)
6
6
  out = capsys.readouterr().out.strip()
7
- assert "poetry publish --build" == out.replace("--> ", "")
7
+ assert out.replace("--> ", "") == "poetry publish --build"
@@ -1 +0,0 @@
1
- __version__ = "0.9.3"
File without changes
File without changes