ChatPyPI 0.1.2__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.2
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.2
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.2"
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
 
@@ -1051,13 +1055,14 @@ def scaffold_package(
1051
1055
  workflow_dispatch:
1052
1056
 
1053
1057
  permissions:
1054
- contents: write
1055
- id-token: write
1058
+ contents: read
1056
1059
 
1057
1060
  jobs:
1058
1061
  publish:
1059
1062
  runs-on: ubuntu-latest
1060
- environment: pypi
1063
+ permissions:
1064
+ contents: read
1065
+ id-token: write
1061
1066
  steps:
1062
1067
  - uses: actions/checkout@v4
1063
1068
  with:
@@ -1677,6 +1682,7 @@ def _clean_dist_dir(dist_dir: Path) -> None:
1677
1682
  def run_command(
1678
1683
  args: list[str], cwd: Path, env: dict[str, str] | None = None
1679
1684
  ) -> CommandResult:
1685
+ logger.info("Running command", extra={"command_args": args, "cwd": str(cwd)})
1680
1686
  process = subprocess.run(
1681
1687
  args,
1682
1688
  cwd=str(cwd),
@@ -1685,6 +1691,10 @@ def run_command(
1685
1691
  text=True,
1686
1692
  check=False,
1687
1693
  )
1694
+ logger.info(
1695
+ "Command finished",
1696
+ extra={"command_args": args, "cwd": str(cwd), "returncode": process.returncode},
1697
+ )
1688
1698
  return CommandResult(
1689
1699
  args=list(args),
1690
1700
  returncode=process.returncode,
@@ -1724,12 +1734,28 @@ def build_package(
1724
1734
  elif wheel and not sdist:
1725
1735
  args.append("--wheel")
1726
1736
 
1737
+ logger.info(
1738
+ "Building package distributions",
1739
+ extra={"project_dir": str(project_dir), "dist_dir": str(dist_dir)},
1740
+ )
1727
1741
  result = _ensure_success(runner(args, project_dir), "Build")
1728
1742
  files = find_distributions(dist_dir)
1729
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
+ )
1730
1748
  raise PyPICommandError(
1731
1749
  f"Build completed but no distributions were found under {dist_dir}"
1732
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
+ )
1733
1759
  return result, files
1734
1760
 
1735
1761
 
@@ -1745,14 +1771,30 @@ def check_distributions(
1745
1771
  files = find_distributions(dist_dir)
1746
1772
  if not files:
1747
1773
  raise PyPICommandError(
1748
- f"No distributions found under {dist_dir}. Run `chattool pypi build` first."
1774
+ f"No distributions found under {dist_dir}. Run `chatpypi build` first."
1749
1775
  )
1750
1776
 
1751
1777
  args = [sys.executable, "-m", "twine", "check"]
1752
1778
  if strict:
1753
1779
  args.append("--strict")
1754
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
+ )
1755
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
+ )
1756
1798
  return result, files
1757
1799
 
1758
1800
 
@@ -1768,12 +1810,28 @@ def upload_distributions(
1768
1810
  files = find_distributions(dist_dir)
1769
1811
  if not files:
1770
1812
  raise PyPICommandError(
1771
- f"No distributions found under {dist_dir}. Run `chattool pypi build` first."
1813
+ f"No distributions found under {dist_dir}. Run `chatpypi build` first."
1772
1814
  )
1773
1815
 
1774
1816
  args = [sys.executable, "-m", "twine", "upload"]
1775
1817
  if skip_existing:
1776
1818
  args.append("--skip-existing")
1777
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
+ )
1778
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
+ )
1779
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.2"
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