dongtu_utils 0.1.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.
- dongtu_utils-0.1.0/PKG-INFO +248 -0
- dongtu_utils-0.1.0/README.md +239 -0
- dongtu_utils-0.1.0/pyproject.toml +21 -0
- dongtu_utils-0.1.0/pyproject.toml.orig +20 -0
- dongtu_utils-0.1.0/src/dongtu_utils/__init__.py +3 -0
- dongtu_utils-0.1.0/src/dongtu_utils/math.py +2 -0
- dongtu_utils-0.1.0/src/dongtu_utils/py.typed +0 -0
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: dongtu_utils
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Personal Python utility library
|
|
5
|
+
Author: aiden
|
|
6
|
+
Author-email: aiden <aidenpeng0504@gmail.com>
|
|
7
|
+
Requires-Python: >=3.11
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
|
|
10
|
+
# dongtu_utils
|
|
11
|
+
|
|
12
|
+
个人 Python 工具库 —— 用于学习 **包发布(打包 / 构建 / 上传 PyPI)** 与 **测试编写(pytest)**。
|
|
13
|
+
|
|
14
|
+
## 项目结构
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
dongtu_utils/
|
|
18
|
+
├── src/ # src 布局:源码统一放 src/ 下
|
|
19
|
+
│ └── dongtu_utils/
|
|
20
|
+
│ ├── __init__.py # 包入口,导出公共 API
|
|
21
|
+
│ ├── math.py # 数学工具函数
|
|
22
|
+
│ └── py.typed # 声明本包带类型标注(供 mypy / IDE 识别)
|
|
23
|
+
├── tests/
|
|
24
|
+
│ └── test_math.py # pytest 测试
|
|
25
|
+
├── pyproject.toml # 项目元数据 + 构建配置
|
|
26
|
+
├── uv.lock # 依赖锁文件
|
|
27
|
+
└── README.md
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## 常用命令
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
uv sync # 安装依赖(含 dev 组)
|
|
34
|
+
uv run pytest # 运行测试
|
|
35
|
+
uv build # 构建发行包(wheel + sdist 到 dist/)
|
|
36
|
+
uv run --env-file .env uv publish # 发布到 PyPI(自动从 .env 读 token)
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
> 以上命令已封装进 `Makefile`,可用 `make <target>` 调用:`make sync` / `make test` / `make build` / `make publish`。运行 `make`(或 `make help`)查看全部 target。
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## 一、发包流程
|
|
44
|
+
|
|
45
|
+
### 0. 前置:完善 pyproject.toml 元数据
|
|
46
|
+
|
|
47
|
+
`[project]` 表是包对外暴露的信息,发布前要填全:
|
|
48
|
+
|
|
49
|
+
| 字段 | 说明 |
|
|
50
|
+
|------|------|
|
|
51
|
+
| `name` | 包名,PyPI 全局唯一,决定 `pip install <name>` |
|
|
52
|
+
| `version` | 版本号(见下方「注意事项」,不可重复发布) |
|
|
53
|
+
| `description` | 一句话描述 |
|
|
54
|
+
| `authors` | 作者与邮箱 |
|
|
55
|
+
| `readme` | 指向 README.md(会渲染在 PyPI 项目页) |
|
|
56
|
+
| `requires-python` | 最低 Python 版本 |
|
|
57
|
+
|
|
58
|
+
构建后端在 `[build-system]` 声明,本项目用 `uv_build`:
|
|
59
|
+
|
|
60
|
+
```toml
|
|
61
|
+
[build-system]
|
|
62
|
+
requires = ["uv_build>=0.12.0,<0.13.0"]
|
|
63
|
+
build-backend = "uv_build"
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### 1. 构建
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
uv build
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
执行后在 `dist/` 生成两种产物:
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
dist/
|
|
76
|
+
├── dongtu_utils-0.1.0-py3-none-any.whl # 二进制发行包(wheel,安装快)
|
|
77
|
+
└── dongtu_utils-0.1.0.tar.gz # 源码发行包(sdist)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
> `uv build` 默认会在 `dist/` 里自动生成 `.gitignore`(内容 `*`),配合根目录 `.gitignore` 的 `dist/` 规则,构建产物不会被提交进 git。
|
|
81
|
+
|
|
82
|
+
### 2. 本地验证产物(发布前必做)
|
|
83
|
+
|
|
84
|
+
在隔离环境里安装刚构建的 wheel 并实际 import,确认打包内容正确:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
# --no-project 排除当前项目,--with 临时安装这个 wheel(版本号按实际文件名替换)
|
|
88
|
+
uv run --no-project --with dist/dongtu_utils-0.1.0-py3-none-any.whl \
|
|
89
|
+
python -c "from dongtu_utils import add; print(add(1, 2))"
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### 3. 预览要发布的内容
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
uv publish --dry-run
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
只列出会上传的文件,不真正上传。
|
|
99
|
+
|
|
100
|
+
### 4. 先发到 Test PyPI 验证
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
uv publish --publish-url https://test.pypi.org/legacy/ --token <TEST_PYPI_TOKEN>
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Test PyPI(`https://test.pypi.org`)与正式 PyPI 完全隔离,账号和 token 需单独注册。发布后用下面命令验证能否正常安装:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
pip install -i https://test.pypi.org/simple/ dongtu_utils
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### 5. 使用 API Token 发布到正式 PyPI
|
|
113
|
+
|
|
114
|
+
#### ① 获取 Token
|
|
115
|
+
|
|
116
|
+
1. 登录 <https://pypi.org> → 右上角账号 → **Account settings** → **API tokens** → **Add API token**。
|
|
117
|
+
2. **Scope(作用域)** 选「限制到指定项目」(只给 upload 权限),并填项目名 `dongtu_utils`,而不是「Entire account(整个账号)」——这样 token 一旦泄露,影响范围更小。
|
|
118
|
+
3. 生成后的 token 形如 `pypi-AgEIcHlwaS5vcmc...`,**只显示这一次**,当场复制保存。
|
|
119
|
+
4. Test PyPI 的 token 需要到 <https://test.pypi.org> 单独注册(入口相同)。
|
|
120
|
+
|
|
121
|
+
#### ② 把 Token 传给 uv publish
|
|
122
|
+
|
|
123
|
+
`uv publish` 只认两个来源:`--token` 参数,或 `UV_PUBLISH_TOKEN` 环境变量。
|
|
124
|
+
|
|
125
|
+
方式一:`--token` 参数(最直接,但 token 会留在 shell 历史里)
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
uv publish --token "pypi-AgEIcHlwaS5vcmc..."
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
方式二:环境变量(推荐,不落进 shell 历史)
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
export UV_PUBLISH_TOKEN="pypi-AgEIcHlwaS5vcmc..."
|
|
135
|
+
uv publish
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
#### ③ 用 .env 存 Token(本项目已配置好)
|
|
139
|
+
|
|
140
|
+
`uv publish` 本身**不会**自动读取 `.env`,但可以借 `uv run --env-file` 先把 `.env` 加载进环境再执行发布,一条命令搞定:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
uv run --env-file .env uv publish
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
`.env` 里变量名要叫 `UV_PUBLISH_TOKEN`(本项目已配好):
|
|
147
|
+
|
|
148
|
+
```
|
|
149
|
+
# .env
|
|
150
|
+
UV_PUBLISH_TOKEN=pypi-AgEIcHlwaS5vcmc...
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
不用 `uv run` 时的等价手动写法:
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
set -a; source .env; set +a # 把 .env 里的变量加载进当前 shell
|
|
157
|
+
uv publish
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
> 安全提醒:`.env` 已被 `.gitignore` 忽略,但务必确认它**从未被提交进 git**。若 token 曾泄露(截图、贴进聊天、误提交仓库),立刻去 PyPI 后台 **Revoke** 作废并重新生成。
|
|
161
|
+
|
|
162
|
+
发布成功后,任何人都可以 `pip install dongtu_utils`。
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## 二、发包注意事项
|
|
167
|
+
|
|
168
|
+
1. **版本号不可覆盖** —— PyPI 不允许删除或覆盖已发布的版本,同一版本号只能上传一次。每次发布前必须递增 `version`(如 `0.1.0 → 0.1.1`)。本地反复测试时用预发布版本号:`0.1.0.dev1`、`0.1.0rc1`。
|
|
169
|
+
|
|
170
|
+
2. **用 API Token,不要用密码** —— PyPI 已不支持用户名 + 密码上传,只支持 API token(或受信任发布者)。Token 形如 `pypi-...`,在 <https://pypi.org/manage/account/token/> 生成,**只显示一次,务必当场保存**。不要写进代码或提交到 git。具体用法见上方「使用 API Token 发布」。
|
|
171
|
+
|
|
172
|
+
3. **先测 Test PyPI** —— 正式发布前先走一遍 Test PyPI,验证打包、上传、安装全链路都没问题。
|
|
173
|
+
|
|
174
|
+
4. **别提交构建产物与虚拟环境** —— `dist/`、`.venv/`、`__pycache__/` 都应被 `.gitignore` 忽略(本项目根 `.gitignore` 已覆盖)。
|
|
175
|
+
|
|
176
|
+
5. **`py.typed` 要随包发布** —— 本项目带 `py.typed`(表示有类型标注),在 src 布局下会被自动打进包;后续若新增无标注的子模块,其类型信息会连带缺失。
|
|
177
|
+
|
|
178
|
+
6. **构建与发布分离** —— `uv build` 负责生成产物,`uv publish` 负责上传;上传前先 `uv build` 保证 `dist/` 是最新的(`uv publish` 默认上传 `dist/*`)。
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## 三、测试编写
|
|
183
|
+
|
|
184
|
+
### 1. 添加 pytest
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
uv add --dev pytest
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
pytest 会被加进 `[dependency-groups].dev`:
|
|
191
|
+
|
|
192
|
+
```toml
|
|
193
|
+
[dependency-groups]
|
|
194
|
+
dev = [
|
|
195
|
+
"build>=1.6.1",
|
|
196
|
+
"pytest>=9.1.1",
|
|
197
|
+
]
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### 2. 写测试文件
|
|
201
|
+
|
|
202
|
+
测试放 `tests/` 目录,文件名用 `test_*.py`。src 布局下,测试里**直接从包名导入**(uv 会以 editable 方式把项目装进环境):
|
|
203
|
+
|
|
204
|
+
```python
|
|
205
|
+
# tests/test_math.py
|
|
206
|
+
import pytest
|
|
207
|
+
|
|
208
|
+
from dongtu_utils import add
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def test_add():
|
|
212
|
+
assert add(1, 2) == 3
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
@pytest.mark.parametrize(("a", "b", "expected"), [(1, 2, 3), (0, 0, 0), (-1, 1, 0)])
|
|
216
|
+
def test_add_parametrized(a, b, expected):
|
|
217
|
+
assert add(a, b) == expected
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def test_add_raises():
|
|
221
|
+
with pytest.raises(TypeError):
|
|
222
|
+
add("1", 2)
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### 3. 运行
|
|
226
|
+
|
|
227
|
+
```bash
|
|
228
|
+
uv run pytest # 跑全部测试
|
|
229
|
+
uv run pytest -v # 详细输出(显示每个用例名)
|
|
230
|
+
uv run pytest tests/test_math.py # 只跑某个文件
|
|
231
|
+
uv run pytest -k add # 按名称过滤(跑名字含 "add" 的用例)
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### 4. 常用写法速查
|
|
235
|
+
|
|
236
|
+
| 需求 | 写法 |
|
|
237
|
+
|------|------|
|
|
238
|
+
| 参数化(同一测试跑多组输入) | `@pytest.mark.parametrize("a,b,expected", [...])` |
|
|
239
|
+
| 共享前置数据 / 资源 | `@pytest.fixture` |
|
|
240
|
+
| 断言抛异常 | `with pytest.raises(XxxError):` |
|
|
241
|
+
| 浮点近似比较 | `assert result == pytest.approx(3.14)` |
|
|
242
|
+
| 跳过某测试 | `@pytest.mark.skip(reason="...")` |
|
|
243
|
+
|
|
244
|
+
### 5. 命名约定
|
|
245
|
+
|
|
246
|
+
- 测试文件:`test_*.py`
|
|
247
|
+
- 测试函数:`test_*`
|
|
248
|
+
- 共享 fixture:`tests/conftest.py`(pytest 自动发现,无需手动 import)
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
# dongtu_utils
|
|
2
|
+
|
|
3
|
+
个人 Python 工具库 —— 用于学习 **包发布(打包 / 构建 / 上传 PyPI)** 与 **测试编写(pytest)**。
|
|
4
|
+
|
|
5
|
+
## 项目结构
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
dongtu_utils/
|
|
9
|
+
├── src/ # src 布局:源码统一放 src/ 下
|
|
10
|
+
│ └── dongtu_utils/
|
|
11
|
+
│ ├── __init__.py # 包入口,导出公共 API
|
|
12
|
+
│ ├── math.py # 数学工具函数
|
|
13
|
+
│ └── py.typed # 声明本包带类型标注(供 mypy / IDE 识别)
|
|
14
|
+
├── tests/
|
|
15
|
+
│ └── test_math.py # pytest 测试
|
|
16
|
+
├── pyproject.toml # 项目元数据 + 构建配置
|
|
17
|
+
├── uv.lock # 依赖锁文件
|
|
18
|
+
└── README.md
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## 常用命令
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
uv sync # 安装依赖(含 dev 组)
|
|
25
|
+
uv run pytest # 运行测试
|
|
26
|
+
uv build # 构建发行包(wheel + sdist 到 dist/)
|
|
27
|
+
uv run --env-file .env uv publish # 发布到 PyPI(自动从 .env 读 token)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
> 以上命令已封装进 `Makefile`,可用 `make <target>` 调用:`make sync` / `make test` / `make build` / `make publish`。运行 `make`(或 `make help`)查看全部 target。
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## 一、发包流程
|
|
35
|
+
|
|
36
|
+
### 0. 前置:完善 pyproject.toml 元数据
|
|
37
|
+
|
|
38
|
+
`[project]` 表是包对外暴露的信息,发布前要填全:
|
|
39
|
+
|
|
40
|
+
| 字段 | 说明 |
|
|
41
|
+
|------|------|
|
|
42
|
+
| `name` | 包名,PyPI 全局唯一,决定 `pip install <name>` |
|
|
43
|
+
| `version` | 版本号(见下方「注意事项」,不可重复发布) |
|
|
44
|
+
| `description` | 一句话描述 |
|
|
45
|
+
| `authors` | 作者与邮箱 |
|
|
46
|
+
| `readme` | 指向 README.md(会渲染在 PyPI 项目页) |
|
|
47
|
+
| `requires-python` | 最低 Python 版本 |
|
|
48
|
+
|
|
49
|
+
构建后端在 `[build-system]` 声明,本项目用 `uv_build`:
|
|
50
|
+
|
|
51
|
+
```toml
|
|
52
|
+
[build-system]
|
|
53
|
+
requires = ["uv_build>=0.12.0,<0.13.0"]
|
|
54
|
+
build-backend = "uv_build"
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### 1. 构建
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
uv build
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
执行后在 `dist/` 生成两种产物:
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
dist/
|
|
67
|
+
├── dongtu_utils-0.1.0-py3-none-any.whl # 二进制发行包(wheel,安装快)
|
|
68
|
+
└── dongtu_utils-0.1.0.tar.gz # 源码发行包(sdist)
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
> `uv build` 默认会在 `dist/` 里自动生成 `.gitignore`(内容 `*`),配合根目录 `.gitignore` 的 `dist/` 规则,构建产物不会被提交进 git。
|
|
72
|
+
|
|
73
|
+
### 2. 本地验证产物(发布前必做)
|
|
74
|
+
|
|
75
|
+
在隔离环境里安装刚构建的 wheel 并实际 import,确认打包内容正确:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
# --no-project 排除当前项目,--with 临时安装这个 wheel(版本号按实际文件名替换)
|
|
79
|
+
uv run --no-project --with dist/dongtu_utils-0.1.0-py3-none-any.whl \
|
|
80
|
+
python -c "from dongtu_utils import add; print(add(1, 2))"
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### 3. 预览要发布的内容
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
uv publish --dry-run
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
只列出会上传的文件,不真正上传。
|
|
90
|
+
|
|
91
|
+
### 4. 先发到 Test PyPI 验证
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
uv publish --publish-url https://test.pypi.org/legacy/ --token <TEST_PYPI_TOKEN>
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Test PyPI(`https://test.pypi.org`)与正式 PyPI 完全隔离,账号和 token 需单独注册。发布后用下面命令验证能否正常安装:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
pip install -i https://test.pypi.org/simple/ dongtu_utils
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### 5. 使用 API Token 发布到正式 PyPI
|
|
104
|
+
|
|
105
|
+
#### ① 获取 Token
|
|
106
|
+
|
|
107
|
+
1. 登录 <https://pypi.org> → 右上角账号 → **Account settings** → **API tokens** → **Add API token**。
|
|
108
|
+
2. **Scope(作用域)** 选「限制到指定项目」(只给 upload 权限),并填项目名 `dongtu_utils`,而不是「Entire account(整个账号)」——这样 token 一旦泄露,影响范围更小。
|
|
109
|
+
3. 生成后的 token 形如 `pypi-AgEIcHlwaS5vcmc...`,**只显示这一次**,当场复制保存。
|
|
110
|
+
4. Test PyPI 的 token 需要到 <https://test.pypi.org> 单独注册(入口相同)。
|
|
111
|
+
|
|
112
|
+
#### ② 把 Token 传给 uv publish
|
|
113
|
+
|
|
114
|
+
`uv publish` 只认两个来源:`--token` 参数,或 `UV_PUBLISH_TOKEN` 环境变量。
|
|
115
|
+
|
|
116
|
+
方式一:`--token` 参数(最直接,但 token 会留在 shell 历史里)
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
uv publish --token "pypi-AgEIcHlwaS5vcmc..."
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
方式二:环境变量(推荐,不落进 shell 历史)
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
export UV_PUBLISH_TOKEN="pypi-AgEIcHlwaS5vcmc..."
|
|
126
|
+
uv publish
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
#### ③ 用 .env 存 Token(本项目已配置好)
|
|
130
|
+
|
|
131
|
+
`uv publish` 本身**不会**自动读取 `.env`,但可以借 `uv run --env-file` 先把 `.env` 加载进环境再执行发布,一条命令搞定:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
uv run --env-file .env uv publish
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
`.env` 里变量名要叫 `UV_PUBLISH_TOKEN`(本项目已配好):
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
# .env
|
|
141
|
+
UV_PUBLISH_TOKEN=pypi-AgEIcHlwaS5vcmc...
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
不用 `uv run` 时的等价手动写法:
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
set -a; source .env; set +a # 把 .env 里的变量加载进当前 shell
|
|
148
|
+
uv publish
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
> 安全提醒:`.env` 已被 `.gitignore` 忽略,但务必确认它**从未被提交进 git**。若 token 曾泄露(截图、贴进聊天、误提交仓库),立刻去 PyPI 后台 **Revoke** 作废并重新生成。
|
|
152
|
+
|
|
153
|
+
发布成功后,任何人都可以 `pip install dongtu_utils`。
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## 二、发包注意事项
|
|
158
|
+
|
|
159
|
+
1. **版本号不可覆盖** —— PyPI 不允许删除或覆盖已发布的版本,同一版本号只能上传一次。每次发布前必须递增 `version`(如 `0.1.0 → 0.1.1`)。本地反复测试时用预发布版本号:`0.1.0.dev1`、`0.1.0rc1`。
|
|
160
|
+
|
|
161
|
+
2. **用 API Token,不要用密码** —— PyPI 已不支持用户名 + 密码上传,只支持 API token(或受信任发布者)。Token 形如 `pypi-...`,在 <https://pypi.org/manage/account/token/> 生成,**只显示一次,务必当场保存**。不要写进代码或提交到 git。具体用法见上方「使用 API Token 发布」。
|
|
162
|
+
|
|
163
|
+
3. **先测 Test PyPI** —— 正式发布前先走一遍 Test PyPI,验证打包、上传、安装全链路都没问题。
|
|
164
|
+
|
|
165
|
+
4. **别提交构建产物与虚拟环境** —— `dist/`、`.venv/`、`__pycache__/` 都应被 `.gitignore` 忽略(本项目根 `.gitignore` 已覆盖)。
|
|
166
|
+
|
|
167
|
+
5. **`py.typed` 要随包发布** —— 本项目带 `py.typed`(表示有类型标注),在 src 布局下会被自动打进包;后续若新增无标注的子模块,其类型信息会连带缺失。
|
|
168
|
+
|
|
169
|
+
6. **构建与发布分离** —— `uv build` 负责生成产物,`uv publish` 负责上传;上传前先 `uv build` 保证 `dist/` 是最新的(`uv publish` 默认上传 `dist/*`)。
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## 三、测试编写
|
|
174
|
+
|
|
175
|
+
### 1. 添加 pytest
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
uv add --dev pytest
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
pytest 会被加进 `[dependency-groups].dev`:
|
|
182
|
+
|
|
183
|
+
```toml
|
|
184
|
+
[dependency-groups]
|
|
185
|
+
dev = [
|
|
186
|
+
"build>=1.6.1",
|
|
187
|
+
"pytest>=9.1.1",
|
|
188
|
+
]
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### 2. 写测试文件
|
|
192
|
+
|
|
193
|
+
测试放 `tests/` 目录,文件名用 `test_*.py`。src 布局下,测试里**直接从包名导入**(uv 会以 editable 方式把项目装进环境):
|
|
194
|
+
|
|
195
|
+
```python
|
|
196
|
+
# tests/test_math.py
|
|
197
|
+
import pytest
|
|
198
|
+
|
|
199
|
+
from dongtu_utils import add
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def test_add():
|
|
203
|
+
assert add(1, 2) == 3
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
@pytest.mark.parametrize(("a", "b", "expected"), [(1, 2, 3), (0, 0, 0), (-1, 1, 0)])
|
|
207
|
+
def test_add_parametrized(a, b, expected):
|
|
208
|
+
assert add(a, b) == expected
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def test_add_raises():
|
|
212
|
+
with pytest.raises(TypeError):
|
|
213
|
+
add("1", 2)
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### 3. 运行
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
uv run pytest # 跑全部测试
|
|
220
|
+
uv run pytest -v # 详细输出(显示每个用例名)
|
|
221
|
+
uv run pytest tests/test_math.py # 只跑某个文件
|
|
222
|
+
uv run pytest -k add # 按名称过滤(跑名字含 "add" 的用例)
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### 4. 常用写法速查
|
|
226
|
+
|
|
227
|
+
| 需求 | 写法 |
|
|
228
|
+
|------|------|
|
|
229
|
+
| 参数化(同一测试跑多组输入) | `@pytest.mark.parametrize("a,b,expected", [...])` |
|
|
230
|
+
| 共享前置数据 / 资源 | `@pytest.fixture` |
|
|
231
|
+
| 断言抛异常 | `with pytest.raises(XxxError):` |
|
|
232
|
+
| 浮点近似比较 | `assert result == pytest.approx(3.14)` |
|
|
233
|
+
| 跳过某测试 | `@pytest.mark.skip(reason="...")` |
|
|
234
|
+
|
|
235
|
+
### 5. 命名约定
|
|
236
|
+
|
|
237
|
+
- 测试文件:`test_*.py`
|
|
238
|
+
- 测试函数:`test_*`
|
|
239
|
+
- 共享 fixture:`tests/conftest.py`(pytest 自动发现,无需手动 import)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "dongtu_utils"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Personal Python utility library"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.11"
|
|
7
|
+
dependencies = []
|
|
8
|
+
|
|
9
|
+
[[project.authors]]
|
|
10
|
+
name = "aiden"
|
|
11
|
+
email = "aidenpeng0504@gmail.com"
|
|
12
|
+
|
|
13
|
+
[build-system]
|
|
14
|
+
requires = ["uv_build>=0.12.0,<0.13.0"]
|
|
15
|
+
build-backend = "uv_build"
|
|
16
|
+
|
|
17
|
+
[dependency-groups]
|
|
18
|
+
dev = [
|
|
19
|
+
"build>=1.6.1",
|
|
20
|
+
"pytest>=9.1.1",
|
|
21
|
+
]
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "dongtu_utils"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Personal Python utility library"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
authors = [
|
|
7
|
+
{ name = "aiden", email = "aidenpeng0504@gmail.com" }
|
|
8
|
+
]
|
|
9
|
+
requires-python = ">=3.11"
|
|
10
|
+
dependencies = []
|
|
11
|
+
|
|
12
|
+
[build-system]
|
|
13
|
+
requires = ["uv_build>=0.12.0,<0.13.0"]
|
|
14
|
+
build-backend = "uv_build"
|
|
15
|
+
|
|
16
|
+
[dependency-groups]
|
|
17
|
+
dev = [
|
|
18
|
+
"build>=1.6.1",
|
|
19
|
+
"pytest>=9.1.1",
|
|
20
|
+
]
|
|
File without changes
|