fast-dev-cli 0.19.6__tar.gz → 0.19.8__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 (35) hide show
  1. {fast_dev_cli-0.19.6 → fast_dev_cli-0.19.8}/PKG-INFO +1 -1
  2. fast_dev_cli-0.19.8/fast_dev_cli/__init__.py +1 -0
  3. {fast_dev_cli-0.19.6 → fast_dev_cli-0.19.8}/fast_dev_cli/cli.py +62 -30
  4. {fast_dev_cli-0.19.6 → fast_dev_cli-0.19.8}/pyproject.toml +12 -1
  5. {fast_dev_cli-0.19.6 → fast_dev_cli-0.19.8}/tests/test_lint.py +17 -0
  6. {fast_dev_cli-0.19.6 → fast_dev_cli-0.19.8}/tests/test_upgrade.py +2 -1
  7. fast_dev_cli-0.19.6/fast_dev_cli/__init__.py +0 -1
  8. {fast_dev_cli-0.19.6 → fast_dev_cli-0.19.8}/LICENSE +0 -0
  9. {fast_dev_cli-0.19.6 → fast_dev_cli-0.19.8}/README.md +0 -0
  10. {fast_dev_cli-0.19.6 → fast_dev_cli-0.19.8}/fast_dev_cli/__main__.py +0 -0
  11. {fast_dev_cli-0.19.6 → fast_dev_cli-0.19.8}/fast_dev_cli/py.typed +0 -0
  12. {fast_dev_cli-0.19.6 → fast_dev_cli-0.19.8}/pdm_build.py +0 -0
  13. {fast_dev_cli-0.19.6 → fast_dev_cli-0.19.8}/scripts/check.py +0 -0
  14. {fast_dev_cli-0.19.6 → fast_dev_cli-0.19.8}/scripts/deps.py +0 -0
  15. {fast_dev_cli-0.19.6 → fast_dev_cli-0.19.8}/scripts/format.py +0 -0
  16. {fast_dev_cli-0.19.6 → fast_dev_cli-0.19.8}/scripts/test.py +0 -0
  17. {fast_dev_cli-0.19.6 → fast_dev_cli-0.19.8}/tests/__init__.py +0 -0
  18. {fast_dev_cli-0.19.6 → fast_dev_cli-0.19.8}/tests/assets/uv-tx.lock +0 -0
  19. {fast_dev_cli-0.19.6 → fast_dev_cli-0.19.8}/tests/assets/uv-upload-time.lock +0 -0
  20. {fast_dev_cli-0.19.6 → fast_dev_cli-0.19.8}/tests/assets/uv.lock +0 -0
  21. {fast_dev_cli-0.19.6 → fast_dev_cli-0.19.8}/tests/conftest.py +0 -0
  22. {fast_dev_cli-0.19.6 → fast_dev_cli-0.19.8}/tests/test_bump.py +0 -0
  23. {fast_dev_cli-0.19.6 → fast_dev_cli-0.19.8}/tests/test_deps.py +0 -0
  24. {fast_dev_cli-0.19.6 → fast_dev_cli-0.19.8}/tests/test_exec.py +0 -0
  25. {fast_dev_cli-0.19.6 → fast_dev_cli-0.19.8}/tests/test_fast_test.py +0 -0
  26. {fast_dev_cli-0.19.6 → fast_dev_cli-0.19.8}/tests/test_functions.py +0 -0
  27. {fast_dev_cli-0.19.6 → fast_dev_cli-0.19.8}/tests/test_help.py +0 -0
  28. {fast_dev_cli-0.19.6 → fast_dev_cli-0.19.8}/tests/test_poetry_version_plugin.py +0 -0
  29. {fast_dev_cli-0.19.6 → fast_dev_cli-0.19.8}/tests/test_pypi.py +0 -0
  30. {fast_dev_cli-0.19.6 → fast_dev_cli-0.19.8}/tests/test_runserver.py +0 -0
  31. {fast_dev_cli-0.19.6 → fast_dev_cli-0.19.8}/tests/test_sync.py +0 -0
  32. {fast_dev_cli-0.19.6 → fast_dev_cli-0.19.8}/tests/test_tag.py +0 -0
  33. {fast_dev_cli-0.19.6 → fast_dev_cli-0.19.8}/tests/test_upload.py +0 -0
  34. {fast_dev_cli-0.19.6 → fast_dev_cli-0.19.8}/tests/test_version.py +0 -0
  35. {fast_dev_cli-0.19.6 → fast_dev_cli-0.19.8}/tests/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fast-dev-cli
3
- Version: 0.19.6
3
+ Version: 0.19.8
4
4
  Summary: Python project development tool.
5
5
  Author-Email: Waket Zheng <waketzheng@gmail.com>>
6
6
  Classifier: Development Status :: 4 - Beta
@@ -0,0 +1 @@
1
+ __version__ = "0.19.8"
@@ -564,7 +564,7 @@ def version() -> None:
564
564
  echo(f"Got Version from {TOML_FILE}: " + styled)
565
565
  return
566
566
  version_file = doc["tool"]["pdm"]["version"]["path"]
567
- text = Project.get_work_dir().joinpath(version_file).read_text()
567
+ text = Project.get_work_dir().joinpath(version_file).read_text(encoding="utf-8")
568
568
  varname = "__version__"
569
569
  for line in text.splitlines():
570
570
  if line.strip().startswith(varname):
@@ -1064,6 +1064,7 @@ class LintCode(DryRun):
1064
1064
  up: bool = False,
1065
1065
  sim: bool = True,
1066
1066
  strict: bool = False,
1067
+ ty: bool = False,
1067
1068
  ) -> None:
1068
1069
  self.args = args
1069
1070
  self.check_only = check_only
@@ -1075,6 +1076,7 @@ class LintCode(DryRun):
1075
1076
  self._up = up
1076
1077
  self._sim = sim
1077
1078
  self._strict = strict
1079
+ self._ty = _ensure_bool(ty)
1078
1080
  super().__init__(_exit, dry)
1079
1081
 
1080
1082
  @staticmethod
@@ -1120,6 +1122,7 @@ class LintCode(DryRun):
1120
1122
  ruff_check_up: bool = False,
1121
1123
  ruff_check_sim: bool = True,
1122
1124
  mypy_strict: bool = False,
1125
+ prefer_ty: bool = False,
1123
1126
  ) -> str:
1124
1127
  if paths != "." and all(i.endswith(".html") for i in paths.split()):
1125
1128
  return f"prettier -w {paths}"
@@ -1137,10 +1140,13 @@ class LintCode(DryRun):
1137
1140
  # Sometimes mypy is too slow
1138
1141
  tools = tools[:-1]
1139
1142
  else:
1140
- if load_bool("IGNORE_MISSING_IMPORTS"):
1141
- tools[-1] += " --ignore-missing-imports"
1142
- if mypy_strict or load_bool("FASTDEVCLI_STRICT"):
1143
- tools[-1] += " --strict"
1143
+ if prefer_ty or load_bool("FASTDEVCLI_TY"):
1144
+ tools[-1] = "ty check"
1145
+ else:
1146
+ if load_bool("IGNORE_MISSING_IMPORTS"):
1147
+ tools[-1] += " --ignore-missing-imports"
1148
+ if mypy_strict or load_bool("FASTDEVCLI_STRICT"):
1149
+ tools[-1] += " --strict"
1144
1150
  lint_them = " && ".join(
1145
1151
  "{0}{" + str(i) + "} {1}" for i in range(2, len(tools) + 2)
1146
1152
  )
@@ -1249,6 +1255,7 @@ class LintCode(DryRun):
1249
1255
  ruff_check_up=self._up,
1250
1256
  ruff_check_sim=self._sim,
1251
1257
  mypy_strict=self._strict,
1258
+ prefer_ty=self._ty,
1252
1259
  )
1253
1260
 
1254
1261
 
@@ -1267,6 +1274,7 @@ def lint(
1267
1274
  up: bool = False,
1268
1275
  sim: bool = True,
1269
1276
  strict: bool = False,
1277
+ ty: bool = False,
1270
1278
  ) -> None:
1271
1279
  if files is None:
1272
1280
  files = parse_files(sys.argv[1:])
@@ -1283,6 +1291,7 @@ def lint(
1283
1291
  up=up,
1284
1292
  sim=sim,
1285
1293
  strict=strict,
1294
+ ty=ty,
1286
1295
  ).run()
1287
1296
 
1288
1297
 
@@ -1296,6 +1305,7 @@ def check(
1296
1305
  up: bool = False,
1297
1306
  sim: bool = True,
1298
1307
  strict: bool = False,
1308
+ ty: bool = False,
1299
1309
  ) -> None:
1300
1310
  LintCode(
1301
1311
  files,
@@ -1309,6 +1319,7 @@ def check(
1309
1319
  up=up,
1310
1320
  sim=sim,
1311
1321
  strict=strict,
1322
+ ty=ty,
1312
1323
  ).run()
1313
1324
 
1314
1325
 
@@ -1331,6 +1342,7 @@ def make_style(
1331
1342
  up: bool = Option(False, help="Whether ruff check with --extend-select=UP"),
1332
1343
  sim: bool = Option(True, help="Whether ruff check with --extend-select=SIM"),
1333
1344
  strict: bool = Option(False, help="Whether run mypy with --strict"),
1345
+ ty: bool = Option(False, help="Whether use ty instead of mypy"),
1334
1346
  ) -> None:
1335
1347
  """Run: ruff check/format to reformat code and then mypy to check"""
1336
1348
  if getattr(files, "default", files) is None:
@@ -1347,7 +1359,7 @@ def make_style(
1347
1359
  strict = _ensure_bool(strict)
1348
1360
  kwargs = {"dry": dry, "skip_mypy": skip, "dmypy": dmypy, "bandit": bandit}
1349
1361
  run = check if _ensure_bool(check_only) else functools.partial(lint, prefix=prefix)
1350
- run(files, tool=tool, up=up, sim=sim, strict=strict, **kwargs)
1362
+ run(files, tool=tool, up=up, sim=sim, strict=strict, ty=ty, **kwargs)
1351
1363
 
1352
1364
 
1353
1365
  @cli.command(name="check")
@@ -1358,12 +1370,14 @@ def only_check(
1358
1370
  up: bool = Option(False, help="Whether ruff check with --extend-select=UP"),
1359
1371
  sim: bool = Option(True, help="Whether ruff check with --extend-select=SIM"),
1360
1372
  strict: bool = Option(False, help="Whether run mypy with --strict"),
1373
+ ty: bool = Option(False, help="Whether use ty instead of mypy"),
1361
1374
  ) -> None:
1362
1375
  """Check code style without reformat"""
1363
1376
  bandit = _ensure_bool(bandit)
1364
1377
  up = _ensure_bool(up)
1365
1378
  sim = _ensure_bool(sim)
1366
- check(dry=dry, bandit=bandit, skip_mypy=_ensure_bool(skip_mypy), up=up, sim=sim)
1379
+ skip_mypy = _ensure_bool(skip_mypy)
1380
+ check(dry=dry, bandit=bandit, skip_mypy=skip_mypy, up=up, sim=sim, ty=ty)
1367
1381
 
1368
1382
 
1369
1383
  class Sync(DryRun):
@@ -1648,52 +1662,70 @@ class UvPypi(DryRun):
1648
1662
  if rc != 0:
1649
1663
  raise Exit(rc)
1650
1664
 
1651
- @classmethod
1652
- def update_lock(
1653
- cls, p: Path, verbose: bool, quiet: bool, slim: bool = False
1654
- ) -> int:
1655
- text = p.read_text("utf-8")
1665
+ @staticmethod
1666
+ def get_target_content(
1667
+ text: str, verbose: bool, target_registry, target_host: str
1668
+ ) -> str | None:
1656
1669
  registry_pattern = r'(registry = ")(.*?)"'
1657
- replace_registry = functools.partial(
1658
- re.sub, registry_pattern, rf'\1{cls.PYPI}"'
1659
- )
1660
1670
  registry_urls = {i[1] for i in re.findall(registry_pattern, text)}
1661
- download_pattern = r'(url = ")(https?://.*?)(/packages/.*?\.)(gz|whl)"'
1662
- replace_host = functools.partial(
1663
- re.sub, download_pattern, rf'\1{cls.HOST}\3\4"'
1664
- )
1671
+ download_pattern = r'(url = ")(https?://.*?)(/packages/.*?\.)(gz|whl|zip)"'
1665
1672
  download_hosts = {i[1] for i in re.findall(download_pattern, text)}
1666
1673
  if not registry_urls:
1667
- raise ValueError(f"Failed to find pattern {registry_pattern!r} in {p}")
1674
+ raise ValueError(
1675
+ f"Failed to find pattern {registry_pattern!r} in uv lock file"
1676
+ )
1677
+
1678
+ def replace_registry(s: str) -> str:
1679
+ return re.sub(registry_pattern, rf'\1{target_registry}"', s)
1680
+
1681
+ def replace_host(s: str) -> str:
1682
+ return re.sub(download_pattern, rf'\1{target_host}\3\4"', s)
1683
+
1668
1684
  if len(registry_urls) == 1:
1669
1685
  current_registry = registry_urls.pop()
1670
- if current_registry == cls.PYPI:
1671
- if download_hosts == {cls.HOST}:
1672
- if verbose:
1673
- echo(f"Registry of {p} is {cls.PYPI}, no need to change.")
1674
- return 0
1686
+ if current_registry == target_registry:
1687
+ if download_hosts == {target_host}:
1688
+ return None
1675
1689
  else:
1676
1690
  text = replace_registry(text)
1677
1691
  if verbose:
1678
- echo(f"{current_registry} --> {cls.PYPI}")
1692
+ echo(f"{current_registry} --> {target_registry}")
1679
1693
  else:
1680
1694
  # TODO: ask each one to confirm replace
1681
1695
  text = replace_registry(text)
1682
1696
  if verbose:
1683
1697
  for current_registry in sorted(registry_urls):
1684
- echo(f"{current_registry} --> {cls.PYPI}")
1698
+ echo(f"{current_registry} --> {target_registry}")
1685
1699
  if len(download_hosts) == 1:
1686
1700
  current_host = download_hosts.pop()
1687
- if current_host != cls.HOST:
1701
+ if current_host != target_host:
1688
1702
  text = replace_host(text)
1689
1703
  if verbose:
1690
- print(current_host, "-->", cls.HOST)
1704
+ echo(f"{current_host} --> {target_host}")
1691
1705
  elif download_hosts:
1692
1706
  # TODO: ask each one to confirm replace
1693
1707
  text = replace_host(text)
1694
1708
  if verbose:
1695
1709
  for current_host in sorted(download_hosts):
1696
- echo(f"{current_host} --> {cls.HOST}")
1710
+ echo(f"{current_host} --> {target_host}")
1711
+ return text
1712
+
1713
+ @classmethod
1714
+ def update_lock(
1715
+ cls, p: Path, verbose: bool, quiet: bool, slim: bool = False
1716
+ ) -> int:
1717
+ text = p.read_text("utf-8")
1718
+ new_text = cls.get_target_content(text, verbose, cls.PYPI, cls.HOST)
1719
+ if new_text is None:
1720
+ if verbose:
1721
+ echo(f"Registry of {p} is {cls.PYPI}, no need to change.")
1722
+ return 0
1723
+ return cls.slim_and_write(new_text, slim, p, verbose, quiet)
1724
+
1725
+ @staticmethod
1726
+ def slim_and_write(
1727
+ text: str, slim: bool, p: Path, verbose: bool, quiet: bool
1728
+ ) -> int:
1697
1729
  if slim:
1698
1730
  pattern = r', size = \d+, upload-time = ".*?"'
1699
1731
  text = re.sub(pattern, "", text)
@@ -41,7 +41,7 @@ dependencies = [
41
41
  "bumpversion2 >=1.4.3",
42
42
  "pytest >=8.2.0",
43
43
  ]
44
- version = "0.19.6"
44
+ version = "0.19.8"
45
45
 
46
46
  [project.urls]
47
47
  Homepage = "https://github.com/waketzheng/fast-dev-cli"
@@ -161,6 +161,17 @@ omit = [
161
161
  "fast_dev_cli/__main__.py",
162
162
  ]
163
163
 
164
+ [tool.ty.src]
165
+ exclude = [
166
+ "*.bak",
167
+ ]
168
+
169
+ [tool.ty.rules]
170
+ unresolved-import = "ignore"
171
+
172
+ [tool.ty.environment]
173
+ python-version = "3.10"
174
+
164
175
  [tool.mypy]
165
176
  pretty = true
166
177
  python_version = "3.10"
@@ -72,6 +72,16 @@ def test_check(mock_no_dmypy, monkeypatch, mocker):
72
72
  monkeypatch.setenv("FASTDEVCLI_BANDIT", "0")
73
73
  command4 = capture_cmd_output("fast check --dry")
74
74
  assert command4 == command
75
+ command5 = capture_cmd_output("fast check --dry --ty")
76
+ assert "ty check" in command5
77
+ command6 = capture_cmd_output("fast check --dry --ty --skip-mypy")
78
+ assert "ty check" not in command6
79
+
80
+
81
+ def test_check_ty(monkeypatch, mocker):
82
+ monkeypatch.setenv("FASTDEVCLI_TY", "1")
83
+ command = capture_cmd_output("fast check --dry")
84
+ assert "ty check" in command
75
85
 
76
86
 
77
87
  def test_check_up_sim(monkeypatch):
@@ -181,6 +191,13 @@ def test_lint_cmd(mock_no_dmypy, monkeypatch):
181
191
  assert "mypy --strict" in capture_cmd_output("fast lint --strict --dry")
182
192
  monkeypatch.setenv("FASTDEVCLI_STRICT", "1")
183
193
  assert "mypy --strict" in capture_cmd_output("fast lint --dry")
194
+ output = capture_cmd_output("fast lint --dry --ty")
195
+ assert "--strict" not in output
196
+ assert "ty check" in output
197
+ monkeypatch.setenv("FASTDEVCLI_TY", "1")
198
+ output = capture_cmd_output("fast lint --dry")
199
+ assert "--strict" not in output
200
+ assert "ty check" in output
184
201
 
185
202
 
186
203
  def test_lint_html():
@@ -58,7 +58,8 @@ anyio = {version = ">=3.7.1", optional = true}
58
58
  typer = {extras = ["all"], version = "^0.9.0", optional = true}
59
59
  uvicorn = {version = "^0.23.2", platform = "linux", optional = true}
60
60
  """
61
- assert UpgradeDependencies.build_args(segment.splitlines()) == (
61
+ lines = [str(i) for i in segment.splitlines()]
62
+ assert UpgradeDependencies.build_args(lines) == (
62
63
  [
63
64
  '"ipython@latest"',
64
65
  '"coveralls@latest"',
@@ -1 +0,0 @@
1
- __version__ = "0.19.6"
File without changes
File without changes