ChatPyPI 0.1.3__tar.gz → 0.1.4__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ChatPyPI
3
- Version: 0.1.3
3
+ Version: 0.1.4
4
4
  Summary: ChatPyPI: ChatArch Python package lifecycle helper extracted from ChatTool.
5
5
  Author-email: ChatArch <1073853456@qq.com>
6
6
  License-Expression: MIT
@@ -14,6 +14,8 @@ Requires-Python: >=3.10
14
14
  Description-Content-Type: text/markdown
15
15
  License-File: LICENSE
16
16
  Requires-Dist: click>=8.0
17
+ Requires-Dist: build<2.0.0,>=1.2.0
18
+ Requires-Dist: twine<7.0.0,>=6.0.0
17
19
  Requires-Dist: chatstyle<0.2.0,>=0.1.0
18
20
  Requires-Dist: chatenv<0.3.0,>=0.2.0
19
21
  Provides-Extra: dev
@@ -9,7 +9,7 @@ description = "ChatPyPI: ChatArch Python package lifecycle helper extracted from
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
11
11
  license = "MIT"
12
- dependencies = ["click>=8.0", "chatstyle>=0.1.0,<0.2.0", "chatenv>=0.2.0,<0.3.0"]
12
+ dependencies = ["click>=8.0", "build>=1.2.0,<2.0.0", "twine>=6.0.0,<7.0.0", "chatstyle>=0.1.0,<0.2.0", "chatenv>=0.2.0,<0.3.0"]
13
13
  authors = [{name = "ChatArch", email = "1073853456@qq.com"}]
14
14
  keywords = ["chatpypi", "chatarch", "cli"]
15
15
  classifiers = [
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ChatPyPI
3
- Version: 0.1.3
3
+ Version: 0.1.4
4
4
  Summary: ChatPyPI: ChatArch Python package lifecycle helper extracted from ChatTool.
5
5
  Author-email: ChatArch <1073853456@qq.com>
6
6
  License-Expression: MIT
@@ -14,6 +14,8 @@ Requires-Python: >=3.10
14
14
  Description-Content-Type: text/markdown
15
15
  License-File: LICENSE
16
16
  Requires-Dist: click>=8.0
17
+ Requires-Dist: build<2.0.0,>=1.2.0
18
+ Requires-Dist: twine<7.0.0,>=6.0.0
17
19
  Requires-Dist: chatstyle<0.2.0,>=0.1.0
18
20
  Requires-Dist: chatenv<0.3.0,>=0.2.0
19
21
  Provides-Extra: dev
@@ -1,4 +1,6 @@
1
1
  click>=8.0
2
+ build<2.0.0,>=1.2.0
3
+ twine<7.0.0,>=6.0.0
2
4
  chatstyle<0.2.0,>=0.1.0
3
5
  chatenv<0.3.0,>=0.2.0
4
6
 
@@ -40,4 +40,4 @@ __all__ = [
40
40
  "upload_distributions",
41
41
  ]
42
42
 
43
- __version__ = "0.1.3"
43
+ __version__ = "0.1.4"
@@ -5,6 +5,7 @@ from datetime import datetime, timezone
5
5
  import importlib
6
6
  import json
7
7
  import importlib.util
8
+ import logging
8
9
  from pathlib import Path
9
10
  import re
10
11
  import subprocess
@@ -21,6 +22,9 @@ except ModuleNotFoundError: # pragma: no cover
21
22
 
22
23
 
23
24
  DEFAULT_DIST_DIRNAME = "dist"
25
+ logger = logging.getLogger(__name__)
26
+ logger.addHandler(logging.NullHandler())
27
+
24
28
  LICENSE_TEMPLATES = {
25
29
  "MIT": """MIT License
26
30
 
@@ -1678,6 +1682,7 @@ def _clean_dist_dir(dist_dir: Path) -> None:
1678
1682
  def run_command(
1679
1683
  args: list[str], cwd: Path, env: dict[str, str] | None = None
1680
1684
  ) -> CommandResult:
1685
+ logger.info("Running command", extra={"command_args": args, "cwd": str(cwd)})
1681
1686
  process = subprocess.run(
1682
1687
  args,
1683
1688
  cwd=str(cwd),
@@ -1686,6 +1691,10 @@ def run_command(
1686
1691
  text=True,
1687
1692
  check=False,
1688
1693
  )
1694
+ logger.info(
1695
+ "Command finished",
1696
+ extra={"command_args": args, "cwd": str(cwd), "returncode": process.returncode},
1697
+ )
1689
1698
  return CommandResult(
1690
1699
  args=list(args),
1691
1700
  returncode=process.returncode,
@@ -1725,12 +1734,28 @@ def build_package(
1725
1734
  elif wheel and not sdist:
1726
1735
  args.append("--wheel")
1727
1736
 
1737
+ logger.info(
1738
+ "Building package distributions",
1739
+ extra={"project_dir": str(project_dir), "dist_dir": str(dist_dir)},
1740
+ )
1728
1741
  result = _ensure_success(runner(args, project_dir), "Build")
1729
1742
  files = find_distributions(dist_dir)
1730
1743
  if not files:
1744
+ logger.error(
1745
+ "Build completed without distributions",
1746
+ extra={"project_dir": str(project_dir), "dist_dir": str(dist_dir)},
1747
+ )
1731
1748
  raise PyPICommandError(
1732
1749
  f"Build completed but no distributions were found under {dist_dir}"
1733
1750
  )
1751
+ logger.info(
1752
+ "Built package distributions",
1753
+ extra={
1754
+ "project_dir": str(project_dir),
1755
+ "dist_dir": str(dist_dir),
1756
+ "artifact_count": len(files),
1757
+ },
1758
+ )
1734
1759
  return result, files
1735
1760
 
1736
1761
 
@@ -1746,14 +1771,30 @@ def check_distributions(
1746
1771
  files = find_distributions(dist_dir)
1747
1772
  if not files:
1748
1773
  raise PyPICommandError(
1749
- f"No distributions found under {dist_dir}. Run `chattool pypi build` first."
1774
+ f"No distributions found under {dist_dir}. Run `chatpypi build` first."
1750
1775
  )
1751
1776
 
1752
1777
  args = [sys.executable, "-m", "twine", "check"]
1753
1778
  if strict:
1754
1779
  args.append("--strict")
1755
1780
  args.extend(str(path) for path in files)
1781
+ logger.info(
1782
+ "Checking package distributions",
1783
+ extra={
1784
+ "project_dir": str(project_dir),
1785
+ "dist_dir": str(dist_dir),
1786
+ "artifact_count": len(files),
1787
+ },
1788
+ )
1756
1789
  result = _ensure_success(runner(args, project_dir), "Twine check")
1790
+ logger.info(
1791
+ "Checked package distributions",
1792
+ extra={
1793
+ "project_dir": str(project_dir),
1794
+ "dist_dir": str(dist_dir),
1795
+ "artifact_count": len(files),
1796
+ },
1797
+ )
1757
1798
  return result, files
1758
1799
 
1759
1800
 
@@ -1769,12 +1810,28 @@ def upload_distributions(
1769
1810
  files = find_distributions(dist_dir)
1770
1811
  if not files:
1771
1812
  raise PyPICommandError(
1772
- f"No distributions found under {dist_dir}. Run `chattool pypi build` first."
1813
+ f"No distributions found under {dist_dir}. Run `chatpypi build` first."
1773
1814
  )
1774
1815
 
1775
1816
  args = [sys.executable, "-m", "twine", "upload"]
1776
1817
  if skip_existing:
1777
1818
  args.append("--skip-existing")
1778
1819
  args.extend(str(path) for path in files)
1820
+ logger.info(
1821
+ "Uploading package distributions",
1822
+ extra={
1823
+ "project_dir": str(project_dir),
1824
+ "dist_dir": str(dist_dir),
1825
+ "artifact_count": len(files),
1826
+ },
1827
+ )
1779
1828
  result = _ensure_success(runner(args, project_dir), "Twine upload")
1829
+ logger.info(
1830
+ "Uploaded package distributions",
1831
+ extra={
1832
+ "project_dir": str(project_dir),
1833
+ "dist_dir": str(dist_dir),
1834
+ "artifact_count": len(files),
1835
+ },
1836
+ )
1780
1837
  return result, files
@@ -0,0 +1,85 @@
1
+ from pathlib import Path
2
+ import logging
3
+
4
+ import chatpypi
5
+ from chatpypi import CommandResult
6
+ from chatpypi import __version__
7
+
8
+
9
+ def test_version_present():
10
+ assert __version__ == "0.1.4"
11
+
12
+
13
+ def test_public_package_api_exports_core_helpers(tmp_path):
14
+ assert chatpypi.normalize_module_name("ChatPyPI") == "chatpypi"
15
+ assert chatpypi.resolve_dist_dir(tmp_path) == tmp_path / "dist"
16
+ assert issubclass(chatpypi.PyPICommandError, RuntimeError)
17
+ assert callable(chatpypi.scaffold_package)
18
+ assert callable(chatpypi.build_package)
19
+ assert callable(chatpypi.check_distributions)
20
+ assert callable(chatpypi.upload_distributions)
21
+ assert callable(chatpypi.check_repository_conflicts)
22
+
23
+
24
+ def test_scaffold_package_importable_api_creates_project(tmp_path):
25
+ project_dir = tmp_path / "DemoPkg"
26
+
27
+ result = chatpypi.scaffold_package(
28
+ package_name="DemoPkg",
29
+ description="Demo package",
30
+ initial_version="0.1.0",
31
+ requires_python=">=3.10",
32
+ license_name="MIT",
33
+ author="ChatArch",
34
+ email="1073853456@qq.com",
35
+ project_dir=project_dir,
36
+ template="default",
37
+ )
38
+
39
+ assert result.project_dir == project_dir
40
+ assert result.package_name == "DemoPkg"
41
+ assert result.module_name == "demopkg"
42
+ assert (project_dir / "pyproject.toml").exists()
43
+ assert (project_dir / "src" / "demopkg" / "__init__.py").exists()
44
+
45
+
46
+ def test_runtime_dependencies_include_build_and_twine():
47
+ pyproject = Path(__file__).resolve().parents[1] / "pyproject.toml"
48
+ text = pyproject.read_text(encoding="utf-8")
49
+
50
+ assert '"build>=1.2.0,<2.0.0"' in text
51
+ assert '"twine>=6.0.0,<7.0.0"' in text
52
+
53
+
54
+ def test_build_package_logs_and_returns_artifacts(tmp_path, caplog):
55
+ project_dir = tmp_path / "DemoBuild"
56
+ project_dir.mkdir()
57
+ (project_dir / "pyproject.toml").write_text("[project]\nname='demo'\n", encoding="utf-8")
58
+
59
+ def fake_runner(args, cwd):
60
+ dist_dir = Path(args[args.index("--outdir") + 1])
61
+ dist_dir.mkdir(parents=True, exist_ok=True)
62
+ (dist_dir / "demo-0.1.0-py3-none-any.whl").write_text(
63
+ "wheel", encoding="utf-8"
64
+ )
65
+ return CommandResult(args=list(args), returncode=0, stdout="built", stderr="")
66
+
67
+ with caplog.at_level(logging.INFO, logger="chatpypi.main"):
68
+ result, files = chatpypi.build_package(project_dir, runner=fake_runner)
69
+
70
+ assert result.returncode == 0
71
+ assert [path.name for path in files] == ["demo-0.1.0-py3-none-any.whl"]
72
+ assert "Building package distributions" in caplog.text
73
+ assert "Built package distributions" in caplog.text
74
+
75
+
76
+ def test_check_distributions_error_mentions_chatpypi_build(tmp_path):
77
+ project_dir = tmp_path / "EmptyDist"
78
+ project_dir.mkdir()
79
+
80
+ try:
81
+ chatpypi.check_distributions(project_dir)
82
+ except chatpypi.PyPICommandError as exc:
83
+ assert "Run `chatpypi build` first" in str(exc)
84
+ else: # pragma: no cover
85
+ raise AssertionError("expected PyPICommandError")
@@ -1,41 +0,0 @@
1
- from pathlib import Path
2
-
3
- import chatpypi
4
- from chatpypi import __version__
5
-
6
-
7
- def test_version_present():
8
- assert __version__ == "0.1.3"
9
-
10
-
11
- def test_public_package_api_exports_core_helpers(tmp_path):
12
- assert chatpypi.normalize_module_name("ChatPyPI") == "chatpypi"
13
- assert chatpypi.resolve_dist_dir(tmp_path) == tmp_path / "dist"
14
- assert issubclass(chatpypi.PyPICommandError, RuntimeError)
15
- assert callable(chatpypi.scaffold_package)
16
- assert callable(chatpypi.build_package)
17
- assert callable(chatpypi.check_distributions)
18
- assert callable(chatpypi.upload_distributions)
19
- assert callable(chatpypi.check_repository_conflicts)
20
-
21
-
22
- def test_scaffold_package_importable_api_creates_project(tmp_path):
23
- project_dir = tmp_path / "DemoPkg"
24
-
25
- result = chatpypi.scaffold_package(
26
- package_name="DemoPkg",
27
- description="Demo package",
28
- initial_version="0.1.0",
29
- requires_python=">=3.10",
30
- license_name="MIT",
31
- author="ChatArch",
32
- email="1073853456@qq.com",
33
- project_dir=project_dir,
34
- template="default",
35
- )
36
-
37
- assert result.project_dir == project_dir
38
- assert result.package_name == "DemoPkg"
39
- assert result.module_name == "demopkg"
40
- assert (project_dir / "pyproject.toml").exists()
41
- assert (project_dir / "src" / "demopkg" / "__init__.py").exists()
File without changes
File without changes
File without changes
File without changes
File without changes