# qpip

`qpip` 是一个对 `python -m pip` 的轻量封装，默认使用更快的国内镜像，支持python包的安装、更新、卸载，提供面向项目开发的项目初始化、脚本运行等功能。

## 功能概览

- 始终通过当前 Python 解释器执行 `pip`，避免依赖独立的 `pip.exe`。
- 默认使用国内镜像，并支持 `ali`、`tsinghua`、`douban`、`pypi` 四个镜像别名。
- 支持 `qpip install` / `qpip i`。
- 支持 `qpip update` / `qpip up`，等价于 `pip install --upgrade ...`。
- 支持 `qpip uninstall` / `qpip un`，等价于 `pip uninstall ...`。
- 支持 `qpip run`，行为参考 `npm run`。
- 支持 `qpip init`，快速生成基础 `pyproject.toml` 和默认 scripts。
- 支持 `qpip venv`、`qpip active`、`qpip deactivate`，便于创建并切换项目虚拟环境。
- 帮助信息、错误提示和镜像列表输出均为中文。

## 安装

```bash
pip install qpip
```

## 镜像与基础用法

默认镜像是 `ali`。

```bash
qpip install requests
qpip i requests
```

指定镜像有两种方式：

```bash
qpip tsinghua install numpy
qpip pip install numpy
qpip --mirror douban install pandas
```

查看内置镜像：

```bash
qpip --list-mirrors
```

修改默认镜像可以设置环境变量 `QPIP_DEFAULT_MIRROR`：

```bash
set QPIP_DEFAULT_MIRROR=tsinghua
qpip install httpx
```

如果你已经显式传入 `--index-url`、`--extra-index-url`、`--find-links`、`--no-index`，`qpip` 不会再覆盖源配置。

## 安装、升级、卸载

### 安装

```bash
qpip install requests
qpip i requests
qpip i -r requirements.txt
```

### 升级

```bash
qpip update requests
qpip up requests
qpip up requests fastapi
qpip up -r requirements.txt
```

`qpip update` / `qpip up` 会自动转换成：

```bash
python -m pip install --upgrade ...
```

说明：

- 会继承和 `install` 相同的镜像注入规则。
- 需要至少提供一个包名，或使用 `-r/--requirement` 指定依赖文件。

### 卸载

```bash
qpip uninstall requests
qpip un requests
qpip un -y requests
qpip uninstall -r requirements.txt
```

`qpip uninstall` / `qpip un` 会自动转换成：

```bash
python -m pip uninstall ...
```

说明：

- 卸载命令不会注入镜像。
- 其他参数行为与原生 `pip uninstall` 一致。

## 项目脚本

`qpip run` 会读取当前目录的 `pyproject.toml`，脚本来源优先级如下：

1. `[tool.qpip.scripts]`
2. `[project.scripts]`
3. `[project.gui-scripts]`
4. `[tool.poetry.scripts]`

如果存在 `[tool.qpip.scripts]`，会优先使用它，不再回退到其他表。

### `tool.qpip.scripts` 示例

```toml
[tool.qpip.scripts]
test = "python -m unittest discover -s tests -v"
"lint:check" = "python -m ruff check ."
serve = "python app.py"
```

### 非 `qpip init` 项目兼容示例

```toml
[project.scripts]
serve = "demo.cli:main"

[project.gui-scripts]
desktop = "demo.gui:start"

[tool.poetry.scripts]
worker = "demo.worker:main"
```

### `run` 用法

列出当前项目脚本：

```bash
qpip run
```

执行脚本：

```bash
qpip run test
qpip run serve
qpip run lint:check
```

向脚本透传参数：

```bash
qpip run test -- -k api
qpip run serve -- --port 8000
```

说明：

- `qpip run <script>` 会在当前项目目录执行脚本。
- `qpip run <script> -- <args>` 会把 `--` 后面的参数追加到脚本命令后。
- 对于 `[project.scripts]`、`[project.gui-scripts]`、`[tool.poetry.scripts]`，`qpip` 会按 entry point 方式导入并执行目标函数。
- 如果脚本名包含 `:` 等特殊字符，TOML 里请给 key 加引号。
- 如果当前目录没有 `pyproject.toml`，或者没有任何兼容的 scripts 配置，命令会直接报错。

## 项目初始化

```bash
qpip init
qpip init -y
qpip init --yes
```

`qpip init` 会在当前目录生成一个基础的 `pyproject.toml`，并默认写入：

```toml
[tool.qpip.scripts]
test = "python -m unittest discover -s tests -v"
```

如果当前目录没有 `README.md`，还会额外创建一个最小 README。

### 交互式字段

交互模式下会依次询问：

- `项目名称`
- `版本`
- `描述`
- `Python 版本要求`
- `作者`
- `邮箱`
- `许可证`

直接回车可接受默认值。

默认值来源：

- `项目名称`：当前目录名的规范化结果
- `版本`：`0.1.0`
- `Python 版本要求`：`>=3.8`
- `作者`：优先 `QPIP_INIT_AUTHOR`、`GIT_AUTHOR_NAME`，否则回退系统用户名
- `邮箱`：优先 `QPIP_INIT_EMAIL`、`GIT_AUTHOR_EMAIL`
- `许可证`：`MIT`

交互模式会先预览即将写入的 `pyproject.toml`，然后确认：

```text
确认写入 pyproject.toml 吗？([Y]/n):
```

预览模式：

```bash
qpip --dry-run init -y
```

说明：

- 如果当前目录已存在 `pyproject.toml`，初始化会直接取消，避免覆盖现有配置。
- 当前 `init` 只支持 `-y` 和 `--yes` 两个专属参数。

## 虚拟环境

创建默认虚拟环境：

```bash
qpip venv
```

`qpip venv` 等价于：

```bash
python -m venv .venv
```

查看当前会话对应的激活命令：

```bash
qpip active
```

`qpip active` 会自动判断当前系统和终端，并输出对应命令：

- Linux / macOS: `source .venv/bin/activate`
- Windows PowerShell: `& .\.venv\Scripts\Activate.ps1`
- Windows Bash: `source .venv/Scripts/activate`

由于独立 CLI 进程不能直接修改父级 shell 会话，如果你要让当前终端立即生效，请这样执行：

```bash
eval "$(qpip active)"
```

PowerShell：

```powershell
qpip active | Invoke-Expression
```

退出虚拟环境：

```bash
qpip deactivate
```

`qpip deactivate` 会输出当前 shell 可直接执行的退出命令；若要在当前终端立即生效，可使用和 `active` 相同的执行方式。

## 其他命令

查看帮助：

```bash
qpip --help
```

如果你要把以 `-` 开头的参数直接传给 `pip`，请使用 `--`：

```bash
qpip -- --version
```

## 支持的镜像

- `ali`: `https://mirrors.aliyun.com/pypi/simple/`
- `tsinghua`: `https://pypi.tuna.tsinghua.edu.cn/simple/`
- `douban`: `https://pypi.doubanio.com/simple/`
- `pypi`: `https://pypi.org/simple/`（额外支持别名 `pip`、`official`）
