fcmd 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.
- fcmd-0.1.0/.copier-answers.yml +21 -0
- fcmd-0.1.0/.github/workflows/ci.yml +63 -0
- fcmd-0.1.0/.github/workflows/release.yml +44 -0
- fcmd-0.1.0/.gitignore +35 -0
- fcmd-0.1.0/.pre-commit-config.yaml +21 -0
- fcmd-0.1.0/.python-version +1 -0
- fcmd-0.1.0/.readthedocs.yaml +23 -0
- fcmd-0.1.0/.trae/.ignore +15 -0
- fcmd-0.1.0/.trae/rules/rule-01-/345/274/200/345/217/221/346/265/201/347/250/213.md +19 -0
- fcmd-0.1.0/.trae/rules/rule-02-/350/207/252/351/251/261/345/274/200/345/217/221/345/216/237/345/210/231.md +57 -0
- fcmd-0.1.0/.trae/rules/rule-09-git/346/217/220/344/272/244/350/247/204/345/210/231.md +7 -0
- fcmd-0.1.0/.trae/rules/rule-11-python-standards.md +108 -0
- fcmd-0.1.0/.vscode/settings.json +35 -0
- fcmd-0.1.0/LICENSE +21 -0
- fcmd-0.1.0/Makefile +59 -0
- fcmd-0.1.0/PKG-INFO +135 -0
- fcmd-0.1.0/README.md +92 -0
- fcmd-0.1.0/docs/_static/.gitkeep +0 -0
- fcmd-0.1.0/docs/api.rst +7 -0
- fcmd-0.1.0/docs/changelog.rst +7 -0
- fcmd-0.1.0/docs/conf.py +69 -0
- fcmd-0.1.0/docs/index.rst +58 -0
- fcmd-0.1.0/pyproject.toml +145 -0
- fcmd-0.1.0/src/fcmd/__init__.py +7 -0
- fcmd-0.1.0/src/fcmd/cli.py +25 -0
- fcmd-0.1.0/src/fcmd/py.typed +0 -0
- fcmd-0.1.0/tests/__init__.py +0 -0
- fcmd-0.1.0/tests/test_fcmd.py +17 -0
- fcmd-0.1.0/tox.ini +21 -0
- fcmd-0.1.0/uv.lock +2525 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Changes here will be overwritten by Copier
|
|
2
|
+
_commit: v0.7.0
|
|
3
|
+
_src_path: https://gitee.com/gooker_young/coopie.git
|
|
4
|
+
author_email: gooker_young@qq.com
|
|
5
|
+
author_name: gooker_young
|
|
6
|
+
coverage_fail_under: 95
|
|
7
|
+
description: 极速 python 工具集。
|
|
8
|
+
initial_version: 0.1.0
|
|
9
|
+
license: MIT
|
|
10
|
+
max_python_version: '3.14'
|
|
11
|
+
min_python_version: '3.8'
|
|
12
|
+
package_name: fcmd
|
|
13
|
+
project_name: fcmd
|
|
14
|
+
project_type: cli
|
|
15
|
+
use_cicd: true
|
|
16
|
+
use_cli: true
|
|
17
|
+
use_docker: false
|
|
18
|
+
use_docs: true
|
|
19
|
+
use_domestic_mirrors: true
|
|
20
|
+
use_tox: true
|
|
21
|
+
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main, develop]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main, develop]
|
|
8
|
+
|
|
9
|
+
concurrency:
|
|
10
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
11
|
+
cancel-in-progress: true
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
lint:
|
|
15
|
+
name: Lint & Typecheck
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
timeout-minutes: 10
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v5
|
|
20
|
+
|
|
21
|
+
- name: Install uv
|
|
22
|
+
uses: astral-sh/setup-uv@v8.3.2
|
|
23
|
+
with:
|
|
24
|
+
enable-cache: true
|
|
25
|
+
cache-dependency-glob: "uv.lock"
|
|
26
|
+
|
|
27
|
+
- name: Sync dependencies
|
|
28
|
+
run: uv sync --frozen --extra lint
|
|
29
|
+
|
|
30
|
+
- name: Ruff check
|
|
31
|
+
run: uv run ruff check src tests
|
|
32
|
+
|
|
33
|
+
- name: Ruff format check
|
|
34
|
+
run: uv run ruff format --check src tests
|
|
35
|
+
|
|
36
|
+
- name: Pyrefly check
|
|
37
|
+
run: uv run pyrefly check
|
|
38
|
+
|
|
39
|
+
test:
|
|
40
|
+
name: Test (Python 3.8 & 3.14)
|
|
41
|
+
runs-on: ubuntu-latest
|
|
42
|
+
timeout-minutes: 15
|
|
43
|
+
strategy:
|
|
44
|
+
fail-fast: false
|
|
45
|
+
matrix:
|
|
46
|
+
python-version: ["3.8", "3.14"]
|
|
47
|
+
steps:
|
|
48
|
+
- uses: actions/checkout@v5
|
|
49
|
+
|
|
50
|
+
- name: Install uv
|
|
51
|
+
uses: astral-sh/setup-uv@v8.3.2
|
|
52
|
+
with:
|
|
53
|
+
enable-cache: true
|
|
54
|
+
cache-dependency-glob: "uv.lock"
|
|
55
|
+
|
|
56
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
57
|
+
run: uv python install ${{ matrix.python-version }}
|
|
58
|
+
|
|
59
|
+
- name: Sync dependencies
|
|
60
|
+
run: uv sync --frozen --extra test --python ${{ matrix.python-version }}
|
|
61
|
+
|
|
62
|
+
- name: Run tests
|
|
63
|
+
run: uv run pytest -m "not slow" --cov=fcmd --cov-fail-under=95 --cov-report=term-missing
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags: ['v*.*.*']
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: write
|
|
9
|
+
id-token: write
|
|
10
|
+
|
|
11
|
+
concurrency:
|
|
12
|
+
group: release-${{ github.ref }}
|
|
13
|
+
cancel-in-progress: false
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
release:
|
|
17
|
+
name: Build & Publish
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
environment: pypi
|
|
20
|
+
timeout-minutes: 10
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@v5
|
|
23
|
+
|
|
24
|
+
- name: Install uv
|
|
25
|
+
uses: astral-sh/setup-uv@v8.3.2
|
|
26
|
+
with:
|
|
27
|
+
enable-cache: true
|
|
28
|
+
cache-dependency-glob: "uv.lock"
|
|
29
|
+
|
|
30
|
+
- name: Build distributions
|
|
31
|
+
run: uv build
|
|
32
|
+
|
|
33
|
+
- name: Publish to PyPI (OIDC)
|
|
34
|
+
run: uv publish
|
|
35
|
+
|
|
36
|
+
- name: Create GitHub Release
|
|
37
|
+
env:
|
|
38
|
+
GH_TOKEN: ${{ github.token }}
|
|
39
|
+
TAG_NAME: ${{ github.ref_name }}
|
|
40
|
+
run: |
|
|
41
|
+
gh release create "$TAG_NAME" \
|
|
42
|
+
--title "Release $TAG_NAME" \
|
|
43
|
+
--generate-notes \
|
|
44
|
+
dist/*
|
fcmd-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Python-generated files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[oc]
|
|
4
|
+
build/
|
|
5
|
+
dist/
|
|
6
|
+
wheels/
|
|
7
|
+
*.egg-info
|
|
8
|
+
|
|
9
|
+
# Virtual environments
|
|
10
|
+
.venv
|
|
11
|
+
|
|
12
|
+
# 测试与覆盖率
|
|
13
|
+
.coverage
|
|
14
|
+
.coverage.*
|
|
15
|
+
htmlcov/
|
|
16
|
+
coverage.xml
|
|
17
|
+
.tox/
|
|
18
|
+
|
|
19
|
+
# 工具缓存
|
|
20
|
+
.ruff_cache/
|
|
21
|
+
.pyrefly_cache/
|
|
22
|
+
.mypy_cache/
|
|
23
|
+
.uv-cache/
|
|
24
|
+
|
|
25
|
+
# IDE
|
|
26
|
+
.idea/
|
|
27
|
+
*_profile.html
|
|
28
|
+
|
|
29
|
+
# 环境变量与凭证(勿提交)
|
|
30
|
+
.env
|
|
31
|
+
.env.*
|
|
32
|
+
|
|
33
|
+
# Sphinx 文档构建输出
|
|
34
|
+
docs/_build/
|
|
35
|
+
.trae/refs
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# prek / pre-commit 配置
|
|
2
|
+
# See https://pre-commit.com for more information
|
|
3
|
+
repos:
|
|
4
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
5
|
+
# Ruff 版本 - 与 pyproject.toml 保持同步
|
|
6
|
+
rev: v0.15.8
|
|
7
|
+
hooks:
|
|
8
|
+
# 运行 linter
|
|
9
|
+
- id: ruff
|
|
10
|
+
args: [--fix, --exit-non-zero-on-fix]
|
|
11
|
+
# 运行格式化
|
|
12
|
+
- id: ruff-format
|
|
13
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
14
|
+
rev: v5.0.0
|
|
15
|
+
hooks:
|
|
16
|
+
- id: check-merge-conflict
|
|
17
|
+
- id: debug-statements
|
|
18
|
+
- id: fix-byte-order-marker
|
|
19
|
+
- id: trailing-whitespace
|
|
20
|
+
args: [--markdown-linebreak-ext=md]
|
|
21
|
+
- id: end-of-file-fixer
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.8
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# ReadTheDocs 配置
|
|
2
|
+
# https://docs.readthedocs.io/en/stable/config-file/v2.html
|
|
3
|
+
version: 2
|
|
4
|
+
|
|
5
|
+
# 构建配置
|
|
6
|
+
build:
|
|
7
|
+
os: ubuntu-24.04
|
|
8
|
+
tools:
|
|
9
|
+
python: "3.8"
|
|
10
|
+
|
|
11
|
+
# Python 依赖与构建命令
|
|
12
|
+
python:
|
|
13
|
+
install:
|
|
14
|
+
- method: pip
|
|
15
|
+
path: .
|
|
16
|
+
extra_requirements:
|
|
17
|
+
- docs
|
|
18
|
+
|
|
19
|
+
# Sphinx 构建
|
|
20
|
+
sphinx:
|
|
21
|
+
configuration: docs/conf.py
|
|
22
|
+
builder: html
|
|
23
|
+
fail_on_warning: false
|
fcmd-0.1.0/.trae/.ignore
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# 开发流程约束
|
|
2
|
+
|
|
3
|
+
## 执行过程记录
|
|
4
|
+
|
|
5
|
+
- 每次迭代必须走完"计划 → 实现 → 测试 → 文档 → 验证"闭环,并记录到 `.trae/docs/iter-NN-<主题>.md`(`NN` 为零填充序号)。
|
|
6
|
+
- 记录内容至少包括:迭代目标、改动文件清单、关键决策与依据、验证结果、遗留事项。
|
|
7
|
+
- 每 5 次迭代后清理 `.trae/docs/` 和 `.trae/req/` 目录:长期保留内容归档到 `.trae/skills/skill-NN-<主题>.md`,仅保留最近未归档的记录。
|
|
8
|
+
|
|
9
|
+
## 需求分析
|
|
10
|
+
|
|
11
|
+
- 每次迭代前,必须与用户确认需求,确保理解无误。
|
|
12
|
+
- 需求必须记录到 `.trae/req/req-NN-<主题>.md`(`NN` 为零填充序号)。
|
|
13
|
+
- 需求记录按照`[] 需求描述`格式,其中`[]`为未完成标志,`[x]`为已完成标志。
|
|
14
|
+
- 开发前扫描 `.trae/req/` 目录,整理所有需求,与用户确认后制定开发计划。
|
|
15
|
+
|
|
16
|
+
## 规则变更约束
|
|
17
|
+
|
|
18
|
+
- 修改 `.trae/rules/` 下文件**必须先询问用户**,获授权后方可变动。
|
|
19
|
+
- 变动记录为 `rule-NN-<主题>.md`,并同步更新 `project_memory.md` 对应章节。
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
---
|
|
2
|
+
alwaysApply: true
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# 自驱动开发规则
|
|
6
|
+
|
|
7
|
+
初始确认后,Agent 自主完成"计划 → 实现 → 测试 → 文档 → 验证"迭代循环,直到整个项目目标达成。
|
|
8
|
+
|
|
9
|
+
## 核心原则
|
|
10
|
+
|
|
11
|
+
- **目标导向**:所有产出服务于用户最终目标。
|
|
12
|
+
- **闭环执行**:每个子任务走完五步,禁止跳步留半成品。
|
|
13
|
+
- **自主决策**:可逆操作(编辑文件、运行测试、修复 lint、调整实现)直接执行不询问;不可逆/高风险操作才暂停。
|
|
14
|
+
- **透明沟通**:阶段开始一句话说明意图;关键节点简短更新;不复述内部思考;收尾时直接输出总结,**不询问**"是否继续"或"是否提交"。
|
|
15
|
+
|
|
16
|
+
## 初始确认(一次性)
|
|
17
|
+
|
|
18
|
+
用 `AskUserQuestion` 确认:1. 目标与范围(含不在范围内的内容)2. 验收标准 3. 特殊约束 4. 测试要求(覆盖率门槛、slow 标记)。确认后固化进 `TaskCreate`,不再反复询问。
|
|
19
|
+
|
|
20
|
+
git commit/push 自动执行(分支已跟踪远程时 push;新分支跳过并在总结说明),仅破坏性操作(force-push/reset --hard/clean -f/改 git config)需暂停确认。
|
|
21
|
+
|
|
22
|
+
## 迭代循环
|
|
23
|
+
|
|
24
|
+
1. **计划**:用 Explore/Glob/Grep 研究既有模式;`TaskCreate` 拆分子任务,完成即 `TaskUpdate`;优先复用现有抽象;三处相似才考虑提取,不过早抽象。
|
|
25
|
+
2. **实现**:遵守 `rule-11-python-standards.md` 与既有风格;优先 Edit 现有文件;公共 API 须有完整类型注解与中文 docstring;不写未被要求的功能、不为未来预留扩展点。
|
|
26
|
+
3. **测试**:公共 API 配套测试,优先通过公共接口测试(故障注入可临时访问私有属性,docstring 注明);Mock 优先级:`monkeypatch` > 内联 stub > `unittest.mock` > `pytest-mock`,禁用 `@patch` 装饰器;必跑:`ruff check` + `pytest --cov`;失败时定位根因,不放宽断言或 `# pragma: no cover` 绕过;覆盖率不得低于上一次的值。
|
|
27
|
+
4. **文档**:同步更新 docstring/README;有价值决策追加到 memory(`project_memory.md` 或 `topics.md`);不主动新建 `*.md` 文档。
|
|
28
|
+
5. **验证**:逐条对照验收标准;全套门禁通过(ruff/pyrefly/pytest/coverage);给出变更清单。
|
|
29
|
+
|
|
30
|
+
未达标准回「计划」继续;达标准进入下一轮或收尾。
|
|
31
|
+
|
|
32
|
+
## 多阶段项目
|
|
33
|
+
|
|
34
|
+
初始确认目标是**整个项目**。阶段是里程碑不是边界——阶段完成后自动进入下一阶段「计划」,仅一句话说明"进入 Pn,重点:…"。仅所有阶段交付完毕才执行收尾。跨阶段需外部资源(新依赖审批、环境配置)时暂停;阶段范围需显著扩大或改变方向时暂停确认。
|
|
35
|
+
|
|
36
|
+
## 暂停条件(仅以下情况中断找用户)
|
|
37
|
+
|
|
38
|
+
1. **歧义无法自决**:多种合理解读且无既有约定可循。
|
|
39
|
+
2. **高风险/不可逆**:删除非临时文件、重命名公共模块/包、`force-push`、`reset --hard`、`clean -f`、修改 CI/git config、引入新依赖、修改 pre-commit/pyproject.toml 工具链配置、卸载或降级既有依赖。**普通 commit/push 不属于此类**(自动执行)。
|
|
40
|
+
3. **不可恢复的失败**:根因不在本仓库、需外部环境/权限配合、或两轮尝试仍无法定位。
|
|
41
|
+
4. **超出初始确认范围**:需显著扩大范围或改变方向。
|
|
42
|
+
5. **用户主动询问**。
|
|
43
|
+
|
|
44
|
+
**可直接自决**:测试/lint/类型错误修复、代码风格选择、文件编辑、运行校验命令、收尾总结输出、重命名局部变量以避免遮蔽。
|
|
45
|
+
|
|
46
|
+
"整个项目目标达成"不是暂停条件——单阶段完成应自动进入下一阶段。
|
|
47
|
+
|
|
48
|
+
## 沟通与工具
|
|
49
|
+
|
|
50
|
+
- 阶段切换一句话说明;完成子任务后一两句总结;阻塞时说明卡点与需求。
|
|
51
|
+
- 独立操作并行调用(多个 Read/Grep/Glob 一批发出);`TaskCreate`/`TaskUpdate` 维护进度;长命令后台运行。
|
|
52
|
+
- 文件操作用专用工具(Read/Edit/Write/Glob/Grep),不用 `cat`/`sed`/`grep`/`find`。
|
|
53
|
+
- 不用 emoji。
|
|
54
|
+
|
|
55
|
+
## 收尾
|
|
56
|
+
|
|
57
|
+
仅所有阶段交付后执行:输出总结(交付物、关键决策、遗留事项)→ 自动 `git add`(按文件名)+ `git commit`(遵循 `rule-09-git提交规则.md` 风格)+ `git push`(分支已跟踪远程时)→ 更新 memory。验收未满足则回「计划」继续,不停下询问。
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Python 开发规范
|
|
2
|
+
|
|
3
|
+
## 工具链(以 pyproject.toml 为准)
|
|
4
|
+
|
|
5
|
+
| 工具 | 配置要点 |
|
|
6
|
+
|------|---------|
|
|
7
|
+
| ruff | `line-length=120`,`target-version="py38"` |
|
|
8
|
+
| pyrefly | `preset="strict"`,`python-version="3.8"` |
|
|
9
|
+
| pytest | `asyncio_default_fixture_loop_scope="function"`,marker `slow` |
|
|
10
|
+
| coverage | `branch=true`,`fail_under=95`,`concurrency=["thread"]` |
|
|
11
|
+
| pre-commit | ruff `--fix` + trailing-whitespace + end-of-file-fixer |
|
|
12
|
+
|
|
13
|
+
验证(每次修改后):
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
uv run ruff check src tests
|
|
17
|
+
uv run ruff format --check src tests
|
|
18
|
+
uv run pyrefly check
|
|
19
|
+
uv run pytest -m "not slow" --cov=fcmd --cov-fail-under=95
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## 兼容性
|
|
23
|
+
|
|
24
|
+
- 最低 Python 3.8:用 `from __future__ import annotations` 延迟注解求值;按版本 `typing.List` → 内置泛型(3.9) → `X | Y`(3.10) → `typing.override`(3.12)。
|
|
25
|
+
- 版本守卫:`if sys.version_info >= (3, X):` 引入高版本 API;低版本回退加 `# pragma: no cover`。
|
|
26
|
+
- 优先标准库;`typing-extensions` 用于 `override`/`TypeVar` 前向兼容(`python_version < '3.13'` 时引入)。新增依赖须审慎。
|
|
27
|
+
|
|
28
|
+
## 类型注解
|
|
29
|
+
|
|
30
|
+
- 公共 API 必须有完整类型注解(含返回类型);私有函数也应有注解。
|
|
31
|
+
- `Mapping`/`Sequence` 用于只读参数,`dict`/`list` 用于可变返回。`Any` 仅用于真正动态场景。
|
|
32
|
+
- 禁用裸 `# type: ignore`,确需时加规则码(如 `# type: ignore[union-attr]`)。
|
|
33
|
+
- 仅类型检查的导入放 `if TYPE_CHECKING:` 块内。
|
|
34
|
+
- 类型收窄用 `assert isinstance(x, Y)`;`cast()` 仅用于类型系统无法表达的场景。
|
|
35
|
+
|
|
36
|
+
## 数据结构
|
|
37
|
+
|
|
38
|
+
- 配置/描述类用 `@dataclass(frozen=True)`;可变类属性标注 `RUF012` 豁免。
|
|
39
|
+
- 缓存:实例级 `functools.cached_property`,参数键控 `lru_cache`;不可哈希参数 try/except 回退;修改缓存源后手动清空。
|
|
40
|
+
- 接口用 `abc.ABC` + `@abstractmethod`;状态/标志值用 `enum.Enum`(`UPPER_SNAKE`),禁止裸字符串/魔术数字。
|
|
41
|
+
- 可变类实现 `__repr__`(含关键字段)。
|
|
42
|
+
|
|
43
|
+
## 模块与导入
|
|
44
|
+
|
|
45
|
+
- 单一职责;导入顺序(ruff isort):`__future__` → 标准库 → 第三方 → 本地,各组间空行。
|
|
46
|
+
- 惰性导入仅用于打破循环依赖(函数体内导入并注释)。
|
|
47
|
+
- 定义 `__all__` 显式声明导出符号(位置仅次于 `__future__`)。禁用 `from x import *`;避免 `utils.py`/`helpers.py`。
|
|
48
|
+
|
|
49
|
+
## 函数设计
|
|
50
|
+
|
|
51
|
+
- 模块级函数优于 Mixin;纯函数直接放模块级(慎用静态方法)。参数 ≤ 5 个,超出用 dataclass 封装。
|
|
52
|
+
- 异常范围要窄:只捕获预期异常(如 `(TypeError, ValueError, KeyError, AttributeError)`),**禁止** `except Exception`;捕获后至少 `logger.warning`。
|
|
53
|
+
- 可变默认参数用 `None` 哨兵或 `field(default_factory=list)`。
|
|
54
|
+
|
|
55
|
+
## 异常处理
|
|
56
|
+
|
|
57
|
+
- 自定义异常继承公共基类,按场景分类;`raise NewError(...) from exc` 保留因果链。
|
|
58
|
+
- 不吞异常:捕获后必须处理(记录/包装/重抛),禁止空 `except: pass`。第三方回调异常仅记录,不影响主流程。
|
|
59
|
+
|
|
60
|
+
## 并发
|
|
61
|
+
|
|
62
|
+
- `os.environ`/`os.chdir` 等进程全局状态用 `threading.RLock` 序列化。循环内多次 I/O 改为批量一次;按组限流用 `Semaphore`。
|
|
63
|
+
|
|
64
|
+
## 测试
|
|
65
|
+
|
|
66
|
+
- 覆盖率 ≥ 95%(branch),不得下降。
|
|
67
|
+
- 公共 API 优先通过公共接口测试;故障注入可临时访问私有属性(docstring 注明)。
|
|
68
|
+
- 命名 `test_<对象>_<场景>`;原生 `assert`,禁用 `self.assertEqual`;`pytest.raises` 必填 `match=`。
|
|
69
|
+
- Mock 优先级:`monkeypatch` > 内联 stub > `unittest.mock` > `pytest-mock`。禁用 `@patch` 装饰器、`mock.patch.object` 上下文、`pytest-mock` 的 `mocker` fixture。
|
|
70
|
+
- fixture 优先 `tmp_path`/`monkeypatch`/`capsys`;autouse 仅全局必需时用。耗时测试加 `@pytest.mark.slow`;`tests/**` 忽略 `ARG001`/`ARG002`。
|
|
71
|
+
|
|
72
|
+
## 代码风格
|
|
73
|
+
|
|
74
|
+
- 行宽 120;ruff 默认双引号;末尾单 `\n`、无尾随空格。
|
|
75
|
+
- 公共 API 必须有中文 docstring;使用中文打印和日志。
|
|
76
|
+
- 命名:`snake_case` 函数/变量,`PascalCase` 类,`UPPER_SNAKE` 常量,`_` 前缀私有。不用 emoji。
|
|
77
|
+
|
|
78
|
+
## Pythonic 风格
|
|
79
|
+
|
|
80
|
+
- 单例用 `is`,值用 `==`;EAFP 优于 LBYL;`if items:` 优于 `if len(items) > 0:`。
|
|
81
|
+
- 字符串首选 f-string(`%` 仅用于 logging 延迟格式化);推导式优于 `map`+`filter`(> 2 层拆显式循环)。
|
|
82
|
+
- `enumerate` 替代 `range(len())`;`zip` 并行迭代(3.10+ `strict=True`);解包优于索引;海象运算符不滥用。
|
|
83
|
+
|
|
84
|
+
## 日志
|
|
85
|
+
|
|
86
|
+
- 每模块 `logging.getLogger(__name__)`,禁用 `print` 调试残留。
|
|
87
|
+
- `extra={...}` 传字段;延迟格式化用 `%`;级别:DEBUG 诊断 / INFO 关键流程 / WARNING 可恢复 / ERROR 需介入。禁止日志密码/密钥,脱敏后记录。
|
|
88
|
+
|
|
89
|
+
## 路径与资源
|
|
90
|
+
|
|
91
|
+
- 优先 `pathlib.Path`(ruff `PTH` 强制),禁止字符串拼接路径;边界 `str` 立即包装。
|
|
92
|
+
- 文件/锁/连接用 `with` 或 `contextlib.contextmanager`;多资源用 `ExitStack`。循环内多次 acquire/release 改为批量一次。
|
|
93
|
+
|
|
94
|
+
## 安全
|
|
95
|
+
|
|
96
|
+
- 禁用 `eval`/`exec`(用 `ast.literal_eval`);`subprocess` 禁用 `shell=True`(优先 `list[str]`)。
|
|
97
|
+
- 凭证放 `.env`/环境变量,`.gitignore` 须含 `.env`;日志脱敏。`uv lock` 后审阅新增依赖避免已知 CVE。
|
|
98
|
+
|
|
99
|
+
## 性能
|
|
100
|
+
|
|
101
|
+
- 循环内查询缓存或预构建映射;`has(k)` + `get(k)` 改为单次 `get(k)` + `KeyError` 回退。
|
|
102
|
+
- 入口校验一次,下游不重复。生命周期事件 emit 完整,不留死分支(`# pragma: no cover` 应激活或删除)。
|
|
103
|
+
|
|
104
|
+
## Git 与提交
|
|
105
|
+
|
|
106
|
+
- 任务完成后自动 `git add`(按文件名)+ `git commit`(遵循 `rule-09-git提交规则.md` 风格)+ `git push`(分支已跟踪远程时;新分支跳过并在总结说明)。
|
|
107
|
+
- 不修改 git config;不运行破坏性命令(`push --force`/`reset --hard`/`clean -f`)除非用户明确要求。
|
|
108
|
+
- staging 按文件名添加,不用 `git add -A`/`git add .`。
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"[python]": {
|
|
3
|
+
"editor.codeActionsOnSave": {
|
|
4
|
+
"source.fixAll.ruff": "always",
|
|
5
|
+
"source.organizeImports.ruff": "always",
|
|
6
|
+
"source.sort.json": "always"
|
|
7
|
+
},
|
|
8
|
+
"editor.defaultFormatter": "charliermarsh.ruff",
|
|
9
|
+
"editor.formatOnSave": true
|
|
10
|
+
},
|
|
11
|
+
"[toml]": {
|
|
12
|
+
"editor.defaultFormatter": "tamasfe.even-better-toml",
|
|
13
|
+
"editor.formatOnSave": true
|
|
14
|
+
},
|
|
15
|
+
"evenBetterToml.formatter.alignComments": true,
|
|
16
|
+
"evenBetterToml.formatter.alignEntries": true,
|
|
17
|
+
"evenBetterToml.formatter.allowedBlankLines": 1,
|
|
18
|
+
"evenBetterToml.formatter.arrayAutoCollapse": true,
|
|
19
|
+
"evenBetterToml.formatter.arrayAutoExpand": true,
|
|
20
|
+
"evenBetterToml.formatter.arrayTrailingComma": true,
|
|
21
|
+
"evenBetterToml.formatter.compactEntries": false,
|
|
22
|
+
"evenBetterToml.formatter.indentEntries": false,
|
|
23
|
+
"evenBetterToml.formatter.indentTables": false,
|
|
24
|
+
"evenBetterToml.formatter.reorderArrays": true,
|
|
25
|
+
"evenBetterToml.formatter.reorderInlineTables": true,
|
|
26
|
+
"evenBetterToml.formatter.reorderKeys": true,
|
|
27
|
+
"python.languageServer": "None",
|
|
28
|
+
"python.testing.pytestArgs": [
|
|
29
|
+
"src",
|
|
30
|
+
"tests",
|
|
31
|
+
],
|
|
32
|
+
"python.testing.pytestEnabled": true,
|
|
33
|
+
"python.testing.unittestEnabled": false,
|
|
34
|
+
"ruff.importStrategy": "fromEnvironment"
|
|
35
|
+
}
|
fcmd-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 gooker_young
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
fcmd-0.1.0/Makefile
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Makefile - fcmd 项目快捷命令
|
|
2
|
+
# 运行 `make help` 查看所有可用命令
|
|
3
|
+
|
|
4
|
+
PACKAGE := fcmd
|
|
5
|
+
COV_THRESHOLD := 95
|
|
6
|
+
|
|
7
|
+
.PHONY: help sync build b clean c test cov lint typecheck check doc tox bump patch minor major push
|
|
8
|
+
|
|
9
|
+
help: ## 显示帮助信息
|
|
10
|
+
@awk 'BEGIN {FS = ":.*##"} /^[a-zA-Z].*:.*##/ {printf " \033[36m%-14s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)
|
|
11
|
+
|
|
12
|
+
sync: ## 安装开发依赖
|
|
13
|
+
uv sync --extra dev
|
|
14
|
+
|
|
15
|
+
build b: ## 构建分发包 (wheel + sdist)
|
|
16
|
+
uv build
|
|
17
|
+
|
|
18
|
+
clean c: ## 清理构建产物与缓存
|
|
19
|
+
rm -rf build/ dist/ wheels/ *.egg-info htmlcov/ .coverage .coverage.* coverage.xml docs/_build/ .tox/
|
|
20
|
+
rm -rf .ruff_cache/ .pyrefly_cache/ .mypy_cache/
|
|
21
|
+
find src tests -type d -name __pycache__ -exec rm -rf {} +
|
|
22
|
+
find src tests -type f -name "*.py[oc]" -delete
|
|
23
|
+
|
|
24
|
+
test: ## 运行测试(不含覆盖率)
|
|
25
|
+
uv run pytest -m "not slow"
|
|
26
|
+
|
|
27
|
+
cov: ## 运行测试并检查覆盖率
|
|
28
|
+
uv run pytest -m "not slow" --cov=$(PACKAGE) --cov-fail-under=$(COV_THRESHOLD)
|
|
29
|
+
|
|
30
|
+
lint: ## 代码风格检查 (ruff)
|
|
31
|
+
uv run ruff check src tests
|
|
32
|
+
uv run ruff format --check src tests
|
|
33
|
+
|
|
34
|
+
typecheck: ## 类型检查 (pyrefly)
|
|
35
|
+
uv run pyrefly check
|
|
36
|
+
|
|
37
|
+
check: lint typecheck cov ## 运行全套门禁 (lint + typecheck + cov)
|
|
38
|
+
|
|
39
|
+
doc: ## 构建 Sphinx 文档
|
|
40
|
+
uv run sphinx-build -b html docs docs/_build/html
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
tox: ## 多版本测试 (tox)
|
|
44
|
+
uvx tox -p auto
|
|
45
|
+
|
|
46
|
+
BUMP_PART := $(filter-out bump,$(MAKECMDGOALS))
|
|
47
|
+
|
|
48
|
+
bump: ## 版本号 bump (默认 patch,用法: make bump [minor|major])
|
|
49
|
+
@uvx bump-my-version bump $(if $(BUMP_PART),$(firstword $(BUMP_PART)),patch) --tag
|
|
50
|
+
|
|
51
|
+
patch minor major:
|
|
52
|
+
@:
|
|
53
|
+
|
|
54
|
+
pub: ## 推送到pypi
|
|
55
|
+
uvx twine upload ./dist/**
|
|
56
|
+
|
|
57
|
+
push: ## 推送代码到所有远程仓库
|
|
58
|
+
@set -e; for remote in $$(git remote); do echo "推送 $$remote..."; git push $$remote; git push $$remote --tags; done
|
|
59
|
+
|
fcmd-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: fcmd
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: 极速 python 工具集。
|
|
5
|
+
Author-email: gooker_young <gooker_young@qq.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
16
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
17
|
+
Requires-Python: >=3.8
|
|
18
|
+
Provides-Extra: dev
|
|
19
|
+
Requires-Dist: prek>=0.4.5; extra == 'dev'
|
|
20
|
+
Requires-Dist: pyrefly>=1.1.1; extra == 'dev'
|
|
21
|
+
Requires-Dist: pytest-asyncio>=0.24.0; extra == 'dev'
|
|
22
|
+
Requires-Dist: pytest-cov>=5.0.0; extra == 'dev'
|
|
23
|
+
Requires-Dist: pytest-html>=4.1.1; extra == 'dev'
|
|
24
|
+
Requires-Dist: pytest-xdist>=3.6.1; extra == 'dev'
|
|
25
|
+
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
26
|
+
Requires-Dist: ruff>=0.8.0; extra == 'dev'
|
|
27
|
+
Requires-Dist: tox-uv>=1.13.1; extra == 'dev'
|
|
28
|
+
Requires-Dist: tox>=4.25.0; extra == 'dev'
|
|
29
|
+
Provides-Extra: docs
|
|
30
|
+
Requires-Dist: myst-parser>=3.0; extra == 'docs'
|
|
31
|
+
Requires-Dist: sphinx-rtd-theme>=2.0; extra == 'docs'
|
|
32
|
+
Requires-Dist: sphinx>=7.0; extra == 'docs'
|
|
33
|
+
Provides-Extra: lint
|
|
34
|
+
Requires-Dist: pyrefly>=1.1.1; extra == 'lint'
|
|
35
|
+
Requires-Dist: ruff>=0.8.0; extra == 'lint'
|
|
36
|
+
Provides-Extra: test
|
|
37
|
+
Requires-Dist: pytest-asyncio>=0.24.0; extra == 'test'
|
|
38
|
+
Requires-Dist: pytest-cov>=5.0.0; extra == 'test'
|
|
39
|
+
Requires-Dist: pytest-html>=4.1.1; extra == 'test'
|
|
40
|
+
Requires-Dist: pytest-xdist>=3.6.1; extra == 'test'
|
|
41
|
+
Requires-Dist: pytest>=8.0.0; extra == 'test'
|
|
42
|
+
Description-Content-Type: text/markdown
|
|
43
|
+
|
|
44
|
+
# fcmd
|
|
45
|
+
|
|
46
|
+
> 极速 python 工具集。
|
|
47
|
+
|
|
48
|
+
[](https://pypi.org/project/fcmd/)
|
|
49
|
+
[](https://github.com/gooker_young/fcmd/actions/workflows/ci.yml)
|
|
50
|
+

|
|
51
|
+

|
|
52
|
+

|
|
53
|
+
|
|
54
|
+
## 特性
|
|
55
|
+
|
|
56
|
+
- **构建工具链**:hatchling + uv + ruff + pyrefly + pytest + coverage
|
|
57
|
+
- **Python 版本**:3.8 ~ 3.14
|
|
58
|
+
- **代码质量**:pre-commit 钩子 + ruff lint/format,覆盖率阈值 95%
|
|
59
|
+
- **CI/CD**:GitHub Actions(lint + typecheck + 多版本测试 + 自动发布到 PyPI)
|
|
60
|
+
- **文档**:Sphinx + ReadTheDocs(中文 zh_CN)
|
|
61
|
+
- **多版本测试**:tox + tox-uv(py38, py39, py310, py311, py312, py313, py314)
|
|
62
|
+
- **CLI 入口**:argparse + [project.scripts]
|
|
63
|
+
- **项目结构**:src layout + py.typed 类型标记
|
|
64
|
+
|
|
65
|
+
## 安装
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
pip install fcmd
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
或使用 [uv](https://docs.astral.sh/uv/):
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
uv add fcmd
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## 快速上手
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
import fcmd
|
|
81
|
+
|
|
82
|
+
print(fcmd.__version__)
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## 开发
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
# 安装开发依赖
|
|
89
|
+
uv sync --extra dev
|
|
90
|
+
|
|
91
|
+
# 运行测试(含覆盖率,阈值 95%)
|
|
92
|
+
uv run pytest -m "not slow" --cov=fcmd --cov-fail-under=95
|
|
93
|
+
|
|
94
|
+
# 类型检查
|
|
95
|
+
uv run pyrefly check .
|
|
96
|
+
|
|
97
|
+
# 代码风格
|
|
98
|
+
uv run ruff check src tests
|
|
99
|
+
uv run ruff format --check src tests
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Make 快捷命令
|
|
103
|
+
|
|
104
|
+
项目提供 Makefile 封装常用操作,运行 `make help` 查看全部命令:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
make sync # 安装开发依赖
|
|
108
|
+
make check # 全套门禁 (lint + typecheck + cov)
|
|
109
|
+
make build # 构建分发包
|
|
110
|
+
make clean # 清理构建产物
|
|
111
|
+
make bump PART=patch # 版本号 bump
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
## 文档
|
|
116
|
+
|
|
117
|
+
文档由 Sphinx 构建,托管在 ReadTheDocs:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
# 本地构建文档
|
|
121
|
+
make doc
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
## 多版本测试
|
|
126
|
+
|
|
127
|
+
使用 tox 在多个 Python 版本(py38, py39, py310, py311, py312, py313, py314)下运行测试:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
make tox
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## 许可证
|
|
134
|
+
|
|
135
|
+
MIT
|