fast-dev-cli 0.9.10__tar.gz → 0.10.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.
Files changed (28) hide show
  1. {fast_dev_cli-0.9.10 → fast_dev_cli-0.10.0}/PKG-INFO +3 -3
  2. fast_dev_cli-0.10.0/fast_dev_cli/__init__.py +1 -0
  3. {fast_dev_cli-0.9.10 → fast_dev_cli-0.10.0}/fast_dev_cli/cli.py +33 -9
  4. {fast_dev_cli-0.9.10 → fast_dev_cli-0.10.0}/pyproject.toml +2 -2
  5. {fast_dev_cli-0.9.10 → fast_dev_cli-0.10.0}/scripts/check.sh +1 -1
  6. fast_dev_cli-0.10.0/scripts/format.sh +6 -0
  7. {fast_dev_cli-0.9.10 → fast_dev_cli-0.10.0}/tests/test_fast_test.py +7 -1
  8. {fast_dev_cli-0.9.10 → fast_dev_cli-0.10.0}/tests/test_functions.py +6 -1
  9. {fast_dev_cli-0.9.10 → fast_dev_cli-0.10.0}/tests/test_lint.py +19 -1
  10. {fast_dev_cli-0.9.10 → fast_dev_cli-0.10.0}/tests/test_runserver.py +14 -1
  11. fast_dev_cli-0.9.10/fast_dev_cli/__init__.py +0 -1
  12. fast_dev_cli-0.9.10/scripts/format.sh +0 -6
  13. {fast_dev_cli-0.9.10 → fast_dev_cli-0.10.0}/LICENSE +0 -0
  14. {fast_dev_cli-0.9.10 → fast_dev_cli-0.10.0}/README.md +0 -0
  15. {fast_dev_cli-0.9.10 → fast_dev_cli-0.10.0}/fast_dev_cli/__main__.py +0 -0
  16. {fast_dev_cli-0.9.10 → fast_dev_cli-0.10.0}/fast_dev_cli/py.typed +0 -0
  17. {fast_dev_cli-0.9.10 → fast_dev_cli-0.10.0}/pdm_build.py +0 -0
  18. {fast_dev_cli-0.9.10 → fast_dev_cli-0.10.0}/scripts/test.sh +0 -0
  19. {fast_dev_cli-0.9.10 → fast_dev_cli-0.10.0}/tests/__init__.py +0 -0
  20. {fast_dev_cli-0.9.10 → fast_dev_cli-0.10.0}/tests/conftest.py +0 -0
  21. {fast_dev_cli-0.9.10 → fast_dev_cli-0.10.0}/tests/test_bump.py +0 -0
  22. {fast_dev_cli-0.9.10 → fast_dev_cli-0.10.0}/tests/test_poetry_version_plugin.py +0 -0
  23. {fast_dev_cli-0.9.10 → fast_dev_cli-0.10.0}/tests/test_sync.py +0 -0
  24. {fast_dev_cli-0.9.10 → fast_dev_cli-0.10.0}/tests/test_tag.py +0 -0
  25. {fast_dev_cli-0.9.10 → fast_dev_cli-0.10.0}/tests/test_upgrade.py +0 -0
  26. {fast_dev_cli-0.9.10 → fast_dev_cli-0.10.0}/tests/test_upload.py +0 -0
  27. {fast_dev_cli-0.9.10 → fast_dev_cli-0.10.0}/tests/test_version.py +0 -0
  28. {fast_dev_cli-0.9.10 → fast_dev_cli-0.10.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.9.10
3
+ Version: 0.10.0
4
4
  Summary: Python project development tool.
5
5
  Author-Email: Waket Zheng <waketzheng@gmail.com>>
6
6
  Classifier: Development Status :: 4 - Beta
@@ -24,13 +24,13 @@ Requires-Dist: typer<0.13,>=0.12.3
24
24
  Requires-Dist: emoji<3,>=2.12.1
25
25
  Requires-Dist: tomli<3,>=2.0.1; python_version < "3.11"
26
26
  Requires-Dist: coverage<8,>=7.5.1
27
- Requires-Dist: ruff<0.7,>=0.4.4
27
+ Requires-Dist: ruff<0.8,>=0.4.4
28
28
  Requires-Dist: mypy<2,>=1.10.0
29
29
  Requires-Dist: bumpversion2<2,>=1.4.2
30
30
  Requires-Dist: pytest<9,>=8.2.0
31
+ Provides-Extra: all
31
32
  Requires-Dist: ipython<9,>=8.24.0; extra == "all"
32
33
  Requires-Dist: pytest-mock<4,>=3.14.0; extra == "all"
33
- Provides-Extra: all
34
34
  Description-Content-Type: text/markdown
35
35
 
36
36
  <p align="center">
@@ -0,0 +1 @@
1
+ __version__ = "0.10.0"
@@ -44,7 +44,12 @@ cli = typer.Typer()
44
44
  def load_bool(name: str, default=False) -> bool:
45
45
  if not (v := os.getenv(name)):
46
46
  return default
47
- return v.lower() not in ("0", "false", "off", "no", "n")
47
+ if (lower := v.lower()) in ("0", "false", "f", "off", "no", "n"):
48
+ return False
49
+ elif lower in ("1", "true", "t", "on", "yes", "y"):
50
+ return True
51
+ secho(f"WARNING: can not convert value({v!r}) of {name} to bool!")
52
+ return default
48
53
 
49
54
 
50
55
  def is_venv() -> bool:
@@ -567,9 +572,12 @@ def tag(
567
572
 
568
573
 
569
574
  class LintCode(DryRun):
570
- def __init__(self: Self, args, check_only=False, _exit=False, dry=False) -> None:
575
+ def __init__(
576
+ self: Self, args, check_only=False, _exit=False, dry=False, bandit=False
577
+ ) -> None:
571
578
  self.args = args
572
579
  self.check_only = check_only
580
+ self._bandit = bandit
573
581
  super().__init__(_exit, dry)
574
582
 
575
583
  @staticmethod
@@ -579,11 +587,13 @@ class LintCode(DryRun):
579
587
  @staticmethod
580
588
  def prefer_dmypy(paths: str, tools: list[str]) -> bool:
581
589
  return (
582
- paths == "." and tools[-1].startswith("mypy") and not load_bool("NO_DMYPY")
590
+ paths == "."
591
+ and any(t.startswith("mypy") for t in tools)
592
+ and not load_bool("NO_DMYPY")
583
593
  )
584
594
 
585
595
  @classmethod
586
- def to_cmd(cls: Type[Self], paths=".", check_only=False) -> str:
596
+ def to_cmd(cls: Type[Self], paths=".", check_only=False, bandit=False) -> str:
587
597
  cmd = ""
588
598
  tools = ["ruff format", "ruff check --extend-select=I,B,SIM --fix", "mypy"]
589
599
  if check_only:
@@ -612,11 +622,24 @@ class LintCode(DryRun):
612
622
  if cls.prefer_dmypy(paths, tools):
613
623
  tools[-1] = "dmypy run"
614
624
  cmd += lint_them.format(prefix, paths, *tools)
625
+ if bandit or load_bool("FASTDEVCLI_BANDIT"):
626
+ command = prefix + "bandit"
627
+ if paths == ".": # fast check --bandit
628
+ command += " -r"
629
+ root = Project.get_work_dir(allow_cwd=True)
630
+ package_maybe = (root.name.replace("-", "_"), "src")
631
+ for name in package_maybe:
632
+ if root.joinpath(name).is_dir():
633
+ command += " " + name
634
+ break
635
+ else:
636
+ command += " ."
637
+ cmd += " && " + command
615
638
  return cmd
616
639
 
617
640
  def gen(self: Self) -> str:
618
641
  paths = " ".join(map(str, self.args)) if self.args else "."
619
- return self.to_cmd(paths, self.check_only)
642
+ return self.to_cmd(paths, self.check_only, self._bandit)
620
643
 
621
644
 
622
645
  def parse_files(args: list[str] | tuple[str, ...]) -> list[str]:
@@ -631,8 +654,8 @@ def lint(files=None, dry=False) -> None:
631
654
  LintCode(files, dry=dry).run()
632
655
 
633
656
 
634
- def check(files=None, dry=False) -> None:
635
- LintCode(files, check_only=True, _exit=True, dry=dry).run()
657
+ def check(files=None, dry=False, bandit=False) -> None:
658
+ LintCode(files, check_only=True, _exit=True, dry=dry, bandit=bandit).run()
636
659
 
637
660
 
638
661
  @cli.command(name="lint")
@@ -654,10 +677,11 @@ def make_style(
654
677
 
655
678
  @cli.command(name="check")
656
679
  def only_check(
680
+ bandit: bool = Option(False, "--bandit", help="Run `bandit -r <package_dir>`"),
657
681
  dry: bool = Option(False, "--dry", help="Only print, not really run shell command"),
658
682
  ) -> None:
659
683
  """Check code style without reformat"""
660
- check(dry=dry)
684
+ check(dry=dry, bandit=bandit)
661
685
 
662
686
 
663
687
  class Sync(DryRun):
@@ -697,7 +721,7 @@ def sync(
697
721
  Sync(filename, extras, save, dry=dry).run()
698
722
 
699
723
 
700
- def _should_run_test_script(path: Path) -> bool:
724
+ def _should_run_test_script(path: Path = Path("scripts/test.sh")) -> bool:
701
725
  return path.exists()
702
726
 
703
727
 
@@ -35,12 +35,12 @@ dependencies = [
35
35
  "emoji >=2.12.1,<3",
36
36
  "tomli>=2.0.1,<3; python_version < '3.11'",
37
37
  "coverage >=7.5.1,<8",
38
- "ruff >=0.4.4,<0.7",
38
+ "ruff >=0.4.4,<0.8",
39
39
  "mypy >=1.10.0,<2",
40
40
  "bumpversion2 >=1.4.2,<2",
41
41
  "pytest >=8.2.0,<9",
42
42
  ]
43
- version = "0.9.10"
43
+ version = "0.10.0"
44
44
 
45
45
  [project.urls]
46
46
  Homepage = "https://github.com/waketzheng/fast-dev-cli"
@@ -3,7 +3,7 @@
3
3
  set -e
4
4
  set -x
5
5
 
6
- [ -f ../pyproject.toml ] && cd ..
6
+ [ -f pyproject.toml ] || ([ -f ../pyproject.toml ] && cd ..)
7
7
 
8
8
  pdm run fast check || \
9
9
  echo -e "\033[1m Please run './scripts/format.sh' to auto-fix style issues \033[0m"
@@ -0,0 +1,6 @@
1
+ #!/bin/sh -e
2
+ set -x
3
+
4
+ [ -f pyproject.toml ] || ([ -f ../pyproject.toml ] && cd ..)
5
+
6
+ SKIP_MYPY=1 pdm run fast lint
@@ -2,7 +2,12 @@ import pathlib
2
2
 
3
3
  from pytest_mock import MockerFixture
4
4
 
5
- from fast_dev_cli.cli import Project, capture_cmd_output, coverage_test
5
+ from fast_dev_cli.cli import (
6
+ Project,
7
+ _should_run_test_script,
8
+ capture_cmd_output,
9
+ coverage_test,
10
+ )
6
11
  from fast_dev_cli.cli import test as unitcase
7
12
 
8
13
 
@@ -60,6 +65,7 @@ def test_test_not_in_venv(mocker: MockerFixture, capsys):
60
65
 
61
66
 
62
67
  def test_run_script(mocker: MockerFixture, capsys):
68
+ assert _should_run_test_script()
63
69
  mocker.patch("fast_dev_cli.cli._should_run_test_script", return_value=True)
64
70
  unitcase(dry=True)
65
71
  assert "sh scripts/test.sh" in capsys.readouterr().out
@@ -16,7 +16,7 @@ from fast_dev_cli.cli import (
16
16
  )
17
17
 
18
18
 
19
- def test_utils():
19
+ def test_utils(capsys):
20
20
  # parse files
21
21
  assert parse_files([]) == []
22
22
  assert parse_files(["-a", "--a"]) == []
@@ -52,6 +52,11 @@ def test_utils():
52
52
  assert load_bool(name) is True
53
53
  os.environ.pop(name)
54
54
  assert load_bool(name) is False
55
+ os.environ[name] = "yeah"
56
+ assert load_bool(name) is False
57
+ assert load_bool(name, True) is True
58
+ out = capsys.readouterr().out.strip()
59
+ assert "WARNING" in out
55
60
 
56
61
 
57
62
  def test_run_shell():
@@ -56,10 +56,18 @@ LINT_CMD = _CMD.format("", " --fix")
56
56
  CHECK_CMD = _CMD.format(" --check", "")
57
57
 
58
58
 
59
- def test_check(mock_no_dmypy):
59
+ def test_check(mock_no_dmypy, monkeypatch):
60
60
  command = capture_cmd_output("fast check --dry")
61
61
  for cmd in CHECK_CMD.split(SEP):
62
62
  assert cmd in command
63
+ command2 = capture_cmd_output("fast check --bandit --dry")
64
+ assert command2 == command + " && bandit -r fast_dev_cli"
65
+ monkeypatch.setenv("FASTDEVCLI_BANDIT", "1")
66
+ command3 = capture_cmd_output("fast check --dry")
67
+ assert command3 == command2
68
+ monkeypatch.setenv("FASTDEVCLI_BANDIT", "0")
69
+ command4 = capture_cmd_output("fast check --dry")
70
+ assert command4 == command
63
71
 
64
72
 
65
73
  def test_fast_check():
@@ -110,9 +118,15 @@ def test_lint_with_prefix(mocker):
110
118
 
111
119
  def test_make_style(mocker, mock_no_dmypy):
112
120
  mocker.patch("fast_dev_cli.cli.is_venv", return_value=True)
121
+ with capture_stdout() as stream:
122
+ make_style(check_only=False, dry=True)
123
+ assert LINT_CMD in stream.getvalue()
113
124
  with capture_stdout() as stream:
114
125
  make_style([Path(".")], check_only=False, dry=True)
115
126
  assert LINT_CMD in stream.getvalue()
127
+ with capture_stdout() as stream:
128
+ make_style(".", check_only=False, dry=True) # type:ignore[arg-type]
129
+ assert LINT_CMD in stream.getvalue()
116
130
  with capture_stdout() as stream:
117
131
  make_style([Path(".")], check_only=True, dry=True)
118
132
  assert CHECK_CMD in stream.getvalue()
@@ -138,6 +152,10 @@ def test_lint_func(mocker, mock_no_dmypy):
138
152
  with mock_sys_argv(["tests"]), capture_stdout() as stream:
139
153
  lint(dry=True)
140
154
  assert LINT_CMD.replace(" .", " tests") in stream.getvalue()
155
+ with capture_stdout() as stream:
156
+ lint(["lint"], dry=True)
157
+ assert LINT_CMD in stream.getvalue()
158
+ assert LINT_CMD in capture_cmd_output("python -m fast_dev_cli lint --dry")
141
159
 
142
160
 
143
161
  def test_lint_without_ruff_installed(mocker, mock_no_dmypy):
@@ -1,4 +1,5 @@
1
- from fast_dev_cli.cli import dev, run_and_echo, runserver
1
+ import fast_dev_cli
2
+ from fast_dev_cli.cli import dev, main, run_and_echo, runserver
2
3
 
3
4
 
4
5
  def test_runserver(capsys):
@@ -17,6 +18,12 @@ def test_runserver(capsys):
17
18
  runserver(port=9000, host="0.0.0.0", dry=True)
18
19
  out = capsys.readouterr().out.strip()
19
20
  assert out.replace("--> ", "") == "fastapi dev --port=9000 --host=0.0.0.0"
21
+ runserver("9000", host="0.0.0.0", dry=True)
22
+ out = capsys.readouterr().out.strip()
23
+ assert out.replace("--> ", "") == "fastapi dev --port=9000 --host=0.0.0.0"
24
+ runserver("app.py", host="0.0.0.0", dry=True)
25
+ out = capsys.readouterr().out.strip()
26
+ assert out.replace("--> ", "") == "fastapi dev app.py --host=0.0.0.0"
20
27
 
21
28
 
22
29
  def test_dev(capsys):
@@ -80,3 +87,9 @@ def test_run_by_module(tmp_path):
80
87
  assert "fastapi dev main.py --port=9000 --host=0.0.0.0" in out.read_text()
81
88
  run_and_echo(f"{fast} dev 9000 --host=0.0.0.0 --dry > {out}", verbose=False)
82
89
  assert "fastapi dev --port=9000 --host=0.0.0.0" in out.read_text()
90
+
91
+
92
+ def test_main(mocker):
93
+ mocker.patch("fast_dev_cli.cli.cli")
94
+ main()
95
+ fast_dev_cli.cli.cli.assert_called_once() # type:ignore[attr-defined]
@@ -1 +0,0 @@
1
- __version__ = "0.9.10"
@@ -1,6 +0,0 @@
1
- #!/bin/sh -e
2
- set -x
3
-
4
- [ -f ../pyproject.toml ] && cd ..
5
-
6
- SKIP_MYPY=1 pdm run fast lint
File without changes
File without changes