Metadata-Version: 2.5
Name: release-pypi-cli
Version: 0.1.2
Summary: A PyPI package publishing tool based on Typer framework
Author-email: Chandler <275737875@qq.com>
License: MIT
License-File: LICENSE
Keywords: build,publish,pypi,release,twine,typer
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Build Tools
Classifier: Topic :: System :: Software Distribution
Requires-Python: >=3.8
Requires-Dist: tomli>=1.0; python_version < '3.11'
Requires-Dist: typer>=0.9.0
Provides-Extra: dev
Requires-Dist: black>=23.7.0; extra == 'dev'
Requires-Dist: mypy>=1.5.0; extra == 'dev'
Requires-Dist: pytest-cov>=4.1.0; extra == 'dev'
Requires-Dist: pytest>=7.4.0; extra == 'dev'
Requires-Dist: ruff>=0.0.280; extra == 'dev'
Description-Content-Type: text/markdown

# release-pypi-cli

[![PyPI 版本](https://badge.fury.io/py/release-pypi-cli.svg)](https://badge.fury.io/py/release-pypi-cli)
[![Python 版本](https://img.shields.io/pypi/pyversions/release-pypi-cli)](https://pypi.org/project/release-pypi-cli/)
[![许可证](https://img.shields.io/pypi/l/release-pypi-cli)](https://github.com/codearts/release-pypi-cli/blob/main/LICENSE)
[![代码风格: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)

> 🚀 一个让你用一条命令就能把 Python 包发布到 PyPI 的工具

**release-pypi-cli** 是一个命令行工具，帮助你把 Python 包发布到 PyPI（Python 官方包仓库）。它把复杂的发布流程简化为一条命令，适合所有 Python 开发者使用。

---

## 目录

- [这是什么？](#这是什么)
- [为什么需要它？](#为什么需要它)
- [安装](#安装)
- [5 分钟快速教程](#5-分钟快速教程)
- [从零开始的完整案例](#从零开始的完整案例)
- [命令参数详解](#命令参数详解)
- [凭据配置详解](#凭据配置详解)
- [常见问题解答](#常见问题解答)
- [高级用法](#高级用法)
- [开发指南](#开发指南)
- [贡献指南](#贡献指南)
- [许可证](#许可证)

---

## 这是什么？

### 用大白话解释

想象一下：你写了一个很棒的 Python 工具，想让全世界的人都能用 `pip install` 来安装它。怎么做？

**PyPI**（Python Package Index）就是 Python 的"应用商店"。你把包上传到 PyPI，别人就能用 `pip install 你的包名` 来安装。

**release-pypi-cli** 就是帮你"上架"的工具。就像手机应用商店有上传工具一样，这个工具帮你把代码打包、检查、上传到 PyPI，全自动完成。

### 它做了什么？

当你运行 `release-pypi` 时，它会自动完成 6 个步骤：

```
步骤 1/6：预检查     → 检查你的项目配置是否正确
步骤 2/6：清理       → 删除旧的构建文件
步骤 3/6：安装工具   → 安装打包需要的工具
步骤 4/6：构建       → 把你的代码打包成 .whl 和 .tar.gz
步骤 5/6：检查       → 验证包的元数据是否完整
步骤 6/6：上传       → 把包上传到 PyPI
```

### 举个例子

假设你写了一个叫 `hello-tool` 的工具，发布前你需要：

```bash
# 传统方式（手动操作，容易出错）
rm -rf dist build *.egg-info          # 1. 清理
python -m pip install build twine     # 2. 安装工具
python -m build                       # 3. 构建
python -m twine check dist/*          # 4. 检查
python -m twine upload dist/*         # 5. 上传（需要输入密码）

# 使用: 使用 release-pypi（一条命令搞定）
release-pypi
```

---

## 为什么需要它？

### 传统发布方式的痛点

| 问题 | 传统方式 | 使用 release-pypi-cli |
|------|----------|----------------------|
| 步骤多 | 需要手动执行 5-6 个命令 | 一条命令搞定 |
| 容易忘 | 经常忘记清理旧文件 | 自动清理 |
| 易出错 | 手动输入命令容易打错 | 自动执行 |
| 不安全 | 密码可能暴露在命令行 | 通过环境变量安全传递 |
| 无检查 | 容易上传有问题的包 | 自动检查元数据 |
| 无确认 | 误操作直接上传 | 上传前确认 |

### 适合谁用？

- ✅ **Python 初学者**：不想记复杂命令的人
- ✅ **开源开发者**：经常发布包到 PyPI 的人
- ✅ **团队开发**：需要统一发布流程的团队
- ✅ **CI/CD 自动化**：在 GitHub Actions 中自动发布

---

## 安装

### 前提条件

- Python 3.8 或更高版本
- pip 包管理器

### 安装命令

```bash
pip install release-pypi-cli
```

### 验证安装

```bash
release-pypi --help
```

如果看到帮助信息，说明安装成功！

---

## 5 分钟快速教程

### 第 1 分钟：理解概念

**什么是 Python 包？**

包就是一组 Python 代码的集合，可以被其他人导入和使用。比如你写了一个工具：

```python
# my_tool.py
def say_hello(name):
    print(f"你好，{name}！")
```

这就是一个最简单的包。

### 第 2 分钟：准备项目

创建一个项目文件夹，结构如下：

```
my-project/
├── pyproject.toml      # 项目配置文件
├── README.md           # 项目说明
└── my_project/         # 你的代码文件夹
    └── __init__.py     # 包的入口文件
```

### 第 3 分钟：创建配置文件

创建 `pyproject.toml`：

```toml
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "my-project"
version = "0.1.0"
description = "我的第一个 Python 包"
readme = "README.md"
requires-python = ">=3.8"
license = {text = "MIT"}
authors = [
  {name = "你的名字", email = "you@example.com"}
]
```

创建 `README.md`：

```markdown
# my-project

我的第一个 Python 包。
```

创建 `my_project/__init__.py`：

```python
def say_hello(name):
    """打招呼函数"""
    print(f"你好，{name}！")

__version__ = "0.1.0"
```

### 第 4 分钟：配置 PyPI 账号

1. 去 [PyPI 官网](https://pypi.org/) 注册账号
2. 登录后，进入 Account settings → API tokens
3. 创建一个 API token（选择 "Entire account"）
4. 复制 token（格式类似 `pypi-xxxxxxxxxxxx`）

创建配置文件 `~/.pypirc`（Windows 在 `C:\Users\你的用户名\.pypirc`）：

```ini
[pypi]
  username = __token__
  password = pypi-你的token
```

### 第 5 分钟：发布！

```bash
cd my-project
release-pypi
```

看到这样的输出就成功了：

```
=== 步骤 1/6 : 预检查 ===
[OK] 项目根目录: /path/to/my-project
[OK] 版本号: 0.1.0

=== 步骤 2/6 : 清理旧构建产物 ===
[OK] 清理完成

...

=== 步骤 6/6 : 上传到 PyPI ===
[OK] 上传完成

[OK] 发布完成: my-project 0.1.0 → https://pypi.org/project/my-project/0.1.0/
```

现在全世界的人都可以用 `pip install my-project` 安装你的包了！

---

## 从零开始的完整案例

### 案例：创建并发布一个计算器包

我们将创建一个简单的计算器包 `simple-calc` 并发布到 PyPI。

#### 第 1 步：创建项目结构

```bash
# 创建项目文件夹
mkdir simple-calc
cd simple-calc

# 创建目录结构
mkdir simple_calc
```

项目结构：

```
simple-calc/
├── pyproject.toml
├── README.md
├── LICENSE
└── simple_calc/
    └── __init__.py
```

#### 第 2 步：编写配置文件

**pyproject.toml**：

```toml
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "simple-calc"
version = "1.0.0"
description = "一个简单的计算器包"
readme = "README.md"
requires-python = ">=3.8"
license = {text = "MIT"}
authors = [
  {name = "张三", email = "zhangsan@example.com"}
]
keywords = ["calculator", "math"]
classifiers = [
  "Development Status :: 4 - Beta",
  "Intended Audience :: Developers",
  "License :: OSI Approved :: MIT License",
  "Programming Language :: Python :: 3",
  "Programming Language :: Python :: 3.8",
  "Programming Language :: Python :: 3.9",
  "Programming Language :: Python :: 3.10",
  "Programming Language :: Python :: 3.11",
  "Programming Language :: Python :: 3.12",
]

[project.urls]
Homepage = "https://github.com/zhangsan/simple-calc"
```

**README.md**：

```markdown
# simple-calc

一个简单的计算器包，支持加减乘除。

## 安装

```bash
pip install simple-calc
```

## 使用

```python
from simple_calc import add, subtract, multiply, divide

print(add(1, 2))        # 输出: 3
print(subtract(5, 3))   # 输出: 2
print(multiply(2, 3))   # 输出: 6
print(divide(6, 2))     # 输出: 3.0
```

## 许可证

MIT
```

**LICENSE**：

```
MIT License

Copyright (c) 2024 张三

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```

#### 第 3 步：编写代码

**simple_calc/__init__.py**：

```python
"""simple-calc - 一个简单的计算器包"""

__version__ = "1.0.0"


def add(a, b):
    """加法"""
    return a + b


def subtract(a, b):
    """减法"""
    return a - b


def multiply(a, b):
    """乘法"""
    return a * b


def divide(a, b):
    """除法"""
    if b == 0:
        raise ValueError("除数不能为 0")
    return a / b
```

#### 第 4 步：测试代码

```bash
# 在项目目录下运行
python -c "from simple_calc import add, subtract, multiply, divide; print(add(1, 2))"
# 应该输出: 3
```

#### 第 5 步：干运行测试

先不实际上传，只测试构建：

```bash
release-pypi --dry-run
```

看到 `[OK] 构建完成（dry-run，未上传）` 说明构建成功。

#### 第 6 步：正式发布

```bash
release-pypi --yes
```

#### 第 7 步：验证发布

```bash
# 在另一个目录测试安装
pip install simple-calc

# 测试使用
python -c "from simple_calc import add; print(add(1, 2))"
# 应该输出: 3
```

---

## 命令参数详解

### 基本用法

```bash
release-pypi [选项]
```

### 选项说明

| 选项 | 简写 | 类型 | 默认值 | 说明 |
|------|------|------|--------|------|
| `--dry-run` | - | 布尔 | False | 只构建和检查，不上传到 PyPI |
| `--yes` | `-y` | 布尔 | False | 跳过上传前确认提示 |
| `--build-version` | - | 字符串 | `"~=1.0"` | build 工具版本约束 |
| `--twine-version` | - | 字符串 | `"~=4.0"` | twine 工具版本约束 |

### 使用示例

```bash
# 1. 完整发布（会询问确认）
release-pypi

# 2. 干运行（只构建，不上传）
release-pypi --dry-run

# 3. 跳过确认直接发布
release-pypi --yes

# 4. 指定工具版本
release-pypi --build-version "~=1.0" --twine-version "~=4.0"

# 5. 组合使用
release-pypi --dry-run --yes
```

### 什么是版本约束？

`~=1.0` 表示"兼容 1.0 版本"，相当于 `>=1.0, <2.0`。

- `~=1.0`：1.0 到 1.x.x 都可以，但 2.0 不行
- `~=4.0`：4.0 到 4.x.x 都可以，但 5.0 不行
- `==1.0`：必须是 1.0 版本
- `>=1.0`：1.0 及以上都可以

---

## 凭据配置详解

### 方式 1：使用 .pypirc 文件（推荐）

创建 `~/.pypirc` 文件：

**Linux/Mac**：`~/.pypirc`（即 `/home/用户名/.pypirc`）

**Windows**：`C:\Users\用户名\.pypirc`

文件内容：

```ini
[pypi]
  username = __token__
  password = pypi-你的API-Token
```

### 方式 2：使用环境变量

```bash
# Linux/Mac
export TWINE_USERNAME="__token__"
export TWINE_PASSWORD="pypi-你的API-Token"

# Windows (PowerShell)
$env:TWINE_USERNAME = "__token__"
$env:TWINE_PASSWORD = "pypi-你的API-Token"

# Windows (CMD)
set TWINE_USERNAME=__token__
set TWINE_PASSWORD=pypi-你的API-Token
```

### 如何获取 PyPI API Token？

1. 去 [PyPI 官网](https://pypi.org/) 注册并登录
2. 点击右上角账号 → Account settings
3. 滚动到 "API tokens" 部分
4. 点击 "Add API token"
5. 填写描述，选择范围（建议选 "Entire account"）
6. 点击 "Add token"
7. 复制生成的 token（格式类似 `pypi-AgEIcHlwaS5vcmcCJ...`）

### 凭据优先级

工具会按以下顺序查找凭据：

1. 环境变量 `TWINE_USERNAME` 和 `TWINE_PASSWORD`
2. 环境变量 `TWINE_API_KEY`
3. `~/.pypirc` 文件中的配置

---

## 常见问题解答

### Q1: 提示 "未找到 pyproject.toml"

**原因**：当前目录没有 `pyproject.toml` 文件。

**解决**：
- 确保在项目根目录运行命令
- 创建 `pyproject.toml` 文件

### Q2: 提示 "上传失败 403 Forbidden"

**原因**：包名已被其他人占用，或者 API Token 无效。

**解决**：
- 去 PyPI 搜索你的包名，看是否已存在
- 如果已存在，更换包名
- 检查 API Token 是否正确

### Q3: 提示 "twine check 失败"

**原因**：包的元数据有问题，比如 README 格式错误。

**解决**：
- 检查 `pyproject.toml` 中的配置
- 检查 `README.md` 的格式
- 确保所有必填字段都已配置

### Q4: 上传很慢或卡住

**原因**：网络问题。

**解决**：
- 检查网络连接
- 尝试使用代理
- 等待重试

### Q5: 如何更新已发布的包？

1. 修改代码
2. 更新 `pyproject.toml` 中的版本号
3. 重新运行 `release-pypi`

```bash
# 比如从 0.1.0 更新到 0.2.0
# 修改 pyproject.toml: version = "0.2.0"
release-pypi --yes
```

### Q6: 如何发布到 TestPyPI（测试仓库）？

TestPyPI 是 PyPI 的测试版本，可以用来测试发布流程。

1. 去 [TestPyPI](https://test.pypi.org/) 注册账号
2. 创建 API Token
3. 修改 `~/.pypirc`：

```ini
[distutils]
index-servers = pypi, testpypi

[pypi]
  username = __token__
  password = pypi-正式的token

[testpypi]
  repository = https://test.pypi.org/legacy/
  username = __token__
  password = pypi-测试的token
```

4. 使用 `--repository testpypi` 选项上传（需要修改代码支持）

---

## 高级用法

### 在 GitHub Actions 中自动发布

创建 `.github/workflows/release.yml`：

```yaml
name: Release

on:
  push:
    tags:
      - "v*"

jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.x"

      - name: Install release-pypi-cli
        run: pip install release-pypi-cli

      - name: Publish to PyPI
        env:
          TWINE_USERNAME: __token__
          TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
        run: release-pypi --yes
```

### 自定义构建工具版本

```bash
# 使用 build 1.2.x 版本
release-pypi --build-version "~=1.2"

# 使用 twine 5.x 版本
release-pypi --twine-version "~=5.0"

# 锁定具体版本（不推荐，仅用于测试）
release-pypi --build-version "==1.2.0" --twine-version "==5.0.0"
```

### 在虚拟环境中使用

```bash
# 创建虚拟环境
python -m venv .venv

# 激活虚拟环境
source .venv/bin/activate  # Linux/Mac
.venv\Scripts\activate     # Windows

# 安装并使用
pip install release-pypi-cli
release-pypi
```

---

## 开发指南

### 环境准备

```bash
# 克隆仓库
git clone https://github.com/codearts/release-pypi-cli.git
cd release-pypi-cli

# 创建虚拟环境
python -m venv .venv
source .venv/bin/activate  # Linux/Mac
.venv\Scripts\activate     # Windows

# 安装开发依赖
pip install -e ".[dev]"
```

### 运行测试

```bash
pytest
```

### 代码格式化

```bash
black src tests examples
```

### 代码检查

```bash
ruff check src tests examples
```

### 类型检查

```bash
mypy src
```

---

## 贡献指南

欢迎贡献代码！请按以下步骤操作：

1. Fork 本仓库
2. 创建特性分支：`git checkout -b feature/你的特性`
3. 提交修改：`git commit -m '添加了某某特性'`
4. 推送分支：`git push origin feature/你的特性`
5. 提交 Pull Request

### 贡献要求

- 代码必须通过 `black` 格式化
- 代码必须通过 `ruff` 检查
- 新功能必须添加测试
- 文档必须更新

---

## 许可证

本项目使用 MIT 许可证 - 详见 [LICENSE](LICENSE) 文件。


---

## 致谢

- 灵感来源：[twine](https://github.com/pypa/twine)
- 构建工具：[Typer](https://typer.tiangolo.com/)、[build](https://github.com/pypa/build)、[hatchling](https://github.com/pypa/hatch)

---

---

## 总结

**release-pypi-cli** 就是你的 PyPI 发布助手：

1. 📦 **打包**：自动把代码打包成标准格式
2. ✅ **检查**：自动验证包的完整性
3. 🚀 **上传**：安全上传到 PyPI
4. 🎯 **简单**：一条命令搞定所有步骤

现在，开始发布你的第一个 Python 包吧！

```bash
pip install release-pypi-cli
release-pypi
```
