Metadata-Version: 2.4
Name: bitool
Version: 0.1.16
Summary: Bitool - Rust + Python 混合架构工具集
Project-URL: Homepage, https://gitee.com/gooker_young/bitool
Project-URL: Issues, https://gitee.com/gooker_young/bitool/issues
Author-email: gooker_young <gooker_young@qq.com>
License: MIT
Classifier: Programming Language :: Python :: 3
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: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Rust
Requires-Python: >=3.8
Requires-Dist: attrs>=25.3.0
Requires-Dist: bitool[design]
Requires-Dist: bitool[gui]
Requires-Dist: cattrs>=24.1.3
Requires-Dist: rich>=14.3.4
Requires-Dist: sqlalchemy>=2.0.0
Requires-Dist: tomli-w>=1.0.0
Requires-Dist: tomli>=2.4.1; python_version < '3.11'
Requires-Dist: typing-extensions>=4.13.2
Provides-Extra: app
Requires-Dist: arcade>=2.3.15; extra == 'app'
Requires-Dist: cairosvg>=2.7.1; extra == 'app'
Requires-Dist: defusedxml>=0.7.1; extra == 'app'
Requires-Dist: ezdxf>=1.0.0; extra == 'app'
Requires-Dist: fastapi-offline>=1.7.6; extra == 'app'
Requires-Dist: fastapi>=0.109.0; extra == 'app'
Requires-Dist: flask>=3.0.0; extra == 'app'
Requires-Dist: matplotlib>=3.7.5; extra == 'app'
Requires-Dist: numpy<2.0,>=1.24.4; (python_version < '3.11') and extra == 'app'
Requires-Dist: numpy>=2.0; (python_version >= '3.11') and extra == 'app'
Requires-Dist: openpyxl>=3.1.5; extra == 'app'
Requires-Dist: pefile>=2024.8.26; extra == 'app'
Requires-Dist: pillow>=10.4.0; extra == 'app'
Requires-Dist: psutil>=7.2.2; extra == 'app'
Requires-Dist: pydantic>=2.5.0; extra == 'app'
Requires-Dist: pymupdf>=1.24.11; extra == 'app'
Requires-Dist: pyopengl-accelerate>=3.1.10; extra == 'app'
Requires-Dist: pyopengl>=3.1.10; extra == 'app'
Requires-Dist: pypdf>=5.9.0; extra == 'app'
Requires-Dist: pyqt5-stubs>=5.15.2; (python_version < '3.11' and python_version >= '3.9') and extra == 'app'
Requires-Dist: pyqt5>=5.15.2; (python_version < '3.11' and python_version >= '3.9') and extra == 'app'
Requires-Dist: pyqtwebengine-qt5>=5.15.2; (python_version < '3.11' and python_version >= '3.9') and extra == 'app'
Requires-Dist: pyside2-stubs>=5.15.2; (python_version <= '3.8') and extra == 'app'
Requires-Dist: pyside2>=5.15.2; (python_version <= '3.8') and extra == 'app'
Requires-Dist: pyside6>=6.5.2; (python_version >= '3.11') and extra == 'app'
Requires-Dist: pytesseract>=0.3.13; extra == 'app'
Requires-Dist: python-docx>=1.1.2; extra == 'app'
Requires-Dist: python-multipart>=0.0.20; extra == 'app'
Requires-Dist: python-pptx>=1.0.2; extra == 'app'
Requires-Dist: pywin32>=311; (sys_platform == 'win32') and extra == 'app'
Requires-Dist: rarfile>=4.2; extra == 'app'
Requires-Dist: scipy>=1.10.1; extra == 'app'
Requires-Dist: trimesh>=3.23.0; extra == 'app'
Requires-Dist: uvicorn[standard]>=0.27.0; extra == 'app'
Provides-Extra: build
Requires-Dist: hatch>=1.14.2; extra == 'build'
Requires-Dist: maturin<2.0,>=1.0; extra == 'build'
Requires-Dist: pip>=25.0.1; extra == 'build'
Requires-Dist: prek>=0.3.3; extra == 'build'
Requires-Dist: ruff>=0.15.1; extra == 'build'
Requires-Dist: setuptools>=75.3.4; extra == 'build'
Requires-Dist: twine>=6.1.0; extra == 'build'
Requires-Dist: wheel>=0.45.1; extra == 'build'
Provides-Extra: core
Provides-Extra: db
Requires-Dist: sqlalchemy>=2.0.0; extra == 'db'
Provides-Extra: design
Requires-Dist: ezdxf>=1.0.0; extra == 'design'
Requires-Dist: pyopengl-accelerate>=3.1.10; extra == 'design'
Requires-Dist: pyopengl>=3.1.10; extra == 'design'
Requires-Dist: trimesh>=3.23.0; extra == 'design'
Provides-Extra: dev
Requires-Dist: arcade>=2.3.15; extra == 'dev'
Requires-Dist: bandit>=1.7.10; extra == 'dev'
Requires-Dist: cairosvg>=2.7.1; extra == 'dev'
Requires-Dist: defusedxml>=0.7.1; extra == 'dev'
Requires-Dist: exceptiongroup>=1.0.0; (python_version < '3.11') and extra == 'dev'
Requires-Dist: ezdxf>=1.0.0; extra == 'dev'
Requires-Dist: fastapi-offline>=1.7.6; extra == 'dev'
Requires-Dist: fastapi>=0.109.0; extra == 'dev'
Requires-Dist: flask>=3.0.0; extra == 'dev'
Requires-Dist: hatch>=1.14.2; extra == 'dev'
Requires-Dist: matplotlib>=3.7.5; extra == 'dev'
Requires-Dist: maturin<2.0,>=1.0; extra == 'dev'
Requires-Dist: notebook>=7.3.3; extra == 'dev'
Requires-Dist: numpy<2.0,>=1.24.4; (python_version < '3.11') and extra == 'dev'
Requires-Dist: numpy>=2.0; (python_version >= '3.11') and extra == 'dev'
Requires-Dist: openpyxl>=3.1.5; extra == 'dev'
Requires-Dist: pefile>=2024.8.26; extra == 'dev'
Requires-Dist: pillow>=10.4.0; extra == 'dev'
Requires-Dist: pip>=25.0.1; extra == 'dev'
Requires-Dist: prek>=0.3.3; extra == 'dev'
Requires-Dist: psutil>=7.2.2; extra == 'dev'
Requires-Dist: py>=1.11.0; extra == 'dev'
Requires-Dist: pydantic>=2.5.0; extra == 'dev'
Requires-Dist: pymupdf>=1.24.11; extra == 'dev'
Requires-Dist: pyopengl-accelerate>=3.1.10; extra == 'dev'
Requires-Dist: pyopengl>=3.1.10; extra == 'dev'
Requires-Dist: pypdf>=5.9.0; extra == 'dev'
Requires-Dist: pyqt5-stubs>=5.15.2; (python_version < '3.11' and python_version >= '3.9') and extra == 'dev'
Requires-Dist: pyqt5>=5.15.2; (python_version < '3.11' and python_version >= '3.9') and extra == 'dev'
Requires-Dist: pyqtwebengine-qt5>=5.15.2; (python_version < '3.11' and python_version >= '3.9') and extra == 'dev'
Requires-Dist: pyside2-stubs>=5.15.2; (python_version <= '3.8') and extra == 'dev'
Requires-Dist: pyside2>=5.15.2; (python_version <= '3.8') and extra == 'dev'
Requires-Dist: pyside6>=6.5.2; (python_version >= '3.11') and extra == 'dev'
Requires-Dist: pysnooper>=1.2.3; extra == 'dev'
Requires-Dist: pytesseract>=0.3.13; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.24.0; extra == 'dev'
Requires-Dist: pytest-cov>=5.0.0; extra == 'dev'
Requires-Dist: pytest-html>=4.1.1; extra == 'dev'
Requires-Dist: pytest-mock>=3.14.0; extra == 'dev'
Requires-Dist: pytest-qt>=4.4.0; extra == 'dev'
Requires-Dist: pytest-timeout>=2.4.0; extra == 'dev'
Requires-Dist: pytest-xdist>=3.6.1; extra == 'dev'
Requires-Dist: pytest>=8.3.4; extra == 'dev'
Requires-Dist: python-docx>=1.1.2; extra == 'dev'
Requires-Dist: python-multipart>=0.0.20; extra == 'dev'
Requires-Dist: python-pptx>=1.0.2; extra == 'dev'
Requires-Dist: pywin32>=311; (sys_platform == 'win32') and extra == 'dev'
Requires-Dist: rarfile>=4.2; extra == 'dev'
Requires-Dist: ruff>=0.15.1; extra == 'dev'
Requires-Dist: scipy>=1.10.1; extra == 'dev'
Requires-Dist: setuptools>=75.3.4; extra == 'dev'
Requires-Dist: sphinx-autobuild>=2021.3.14; extra == 'dev'
Requires-Dist: sphinx-rtd-theme>=1.5.2; extra == 'dev'
Requires-Dist: tox-uv>=1.13.1; extra == 'dev'
Requires-Dist: tox>=4.25.0; extra == 'dev'
Requires-Dist: trimesh>=3.23.0; extra == 'dev'
Requires-Dist: twine>=6.1.0; extra == 'dev'
Requires-Dist: ty>=0.0.24; extra == 'dev'
Requires-Dist: uvicorn[standard]>=0.27.0; extra == 'dev'
Requires-Dist: wheel>=0.45.1; extra == 'dev'
Provides-Extra: doc
Requires-Dist: sphinx-autobuild>=2021.3.14; extra == 'doc'
Requires-Dist: sphinx-rtd-theme>=1.5.2; extra == 'doc'
Provides-Extra: game
Requires-Dist: arcade>=2.3.15; extra == 'game'
Provides-Extra: gui
Requires-Dist: pyqt5-stubs>=5.15.2; (python_version < '3.11' and python_version >= '3.9') and extra == 'gui'
Requires-Dist: pyqt5>=5.15.2; (python_version < '3.11' and python_version >= '3.9') and extra == 'gui'
Requires-Dist: pyqtwebengine-qt5>=5.15.2; (python_version < '3.11' and python_version >= '3.9') and extra == 'gui'
Requires-Dist: pyside2-stubs>=5.15.2; (python_version <= '3.8') and extra == 'gui'
Requires-Dist: pyside2>=5.15.2; (python_version <= '3.8') and extra == 'gui'
Requires-Dist: pyside6>=6.5.2; (python_version >= '3.11') and extra == 'gui'
Provides-Extra: image
Requires-Dist: cairosvg>=2.7.1; extra == 'image'
Requires-Dist: pillow>=10.4.0; extra == 'image'
Provides-Extra: ocr
Requires-Dist: pytesseract>=0.3.13; extra == 'ocr'
Provides-Extra: office
Requires-Dist: openpyxl>=3.1.5; extra == 'office'
Requires-Dist: python-docx>=1.1.2; extra == 'office'
Requires-Dist: python-pptx>=1.0.2; extra == 'office'
Provides-Extra: pdf
Requires-Dist: pymupdf>=1.24.11; extra == 'pdf'
Requires-Dist: pypdf>=5.9.0; extra == 'pdf'
Provides-Extra: sci
Requires-Dist: matplotlib>=3.7.5; extra == 'sci'
Requires-Dist: numpy<2.0,>=1.24.4; (python_version < '3.11') and extra == 'sci'
Requires-Dist: numpy>=2.0; (python_version >= '3.11') and extra == 'sci'
Requires-Dist: scipy>=1.10.1; extra == 'sci'
Provides-Extra: sys
Requires-Dist: pefile>=2024.8.26; extra == 'sys'
Requires-Dist: psutil>=7.2.2; extra == 'sys'
Requires-Dist: pywin32>=311; (sys_platform == 'win32') and extra == 'sys'
Provides-Extra: test
Requires-Dist: bandit>=1.7.10; extra == 'test'
Requires-Dist: exceptiongroup>=1.0.0; (python_version < '3.11') and extra == 'test'
Requires-Dist: py>=1.11.0; extra == 'test'
Requires-Dist: pysnooper>=1.2.3; extra == 'test'
Requires-Dist: pytest-asyncio>=0.24.0; extra == 'test'
Requires-Dist: pytest-cov>=5.0.0; extra == 'test'
Requires-Dist: pytest-html>=4.1.1; extra == 'test'
Requires-Dist: pytest-mock>=3.14.0; extra == 'test'
Requires-Dist: pytest-qt>=4.4.0; extra == 'test'
Requires-Dist: pytest-timeout>=2.4.0; extra == 'test'
Requires-Dist: pytest-xdist>=3.6.1; extra == 'test'
Requires-Dist: pytest>=8.3.4; extra == 'test'
Requires-Dist: tox-uv>=1.13.1; extra == 'test'
Requires-Dist: tox>=4.25.0; extra == 'test'
Provides-Extra: typecheck
Requires-Dist: ty>=0.0.24; extra == 'typecheck'
Provides-Extra: utils
Requires-Dist: defusedxml>=0.7.1; extra == 'utils'
Requires-Dist: rarfile>=4.2; extra == 'utils'
Provides-Extra: web
Requires-Dist: fastapi-offline>=1.7.6; extra == 'web'
Requires-Dist: fastapi>=0.109.0; extra == 'web'
Requires-Dist: flask>=3.0.0; extra == 'web'
Requires-Dist: pydantic>=2.5.0; extra == 'web'
Requires-Dist: python-multipart>=0.0.20; extra == 'web'
Requires-Dist: uvicorn[standard]>=0.27.0; extra == 'web'
Description-Content-Type: text/markdown

# Bitool

基于 Maturin 的 Rust + Python 混合架构工具集，将性能瓶颈和共性部分使用 Rust 实现，接口和逻辑部分使用 Python 实现。

## 特性

- **高性能**：核心计算和 I/O 操作使用 Rust 实现（文件操作、文本处理、PDF 处理、加密等）
- **易用性**：Python 提供简洁的 API 接口和 CLI 工具
- **可扩展**：命令模式 + 技能注册表，支持功能扩展
- **跨平台**：支持 Windows、Linux、macOS
- **双模式**：CLI 和 GUI 双模式，满足不同使用场景

## 安装

```bash
pip install bitool
```

> 安装 GUI 应用需额外安装可选依赖：`pip install bitool[app]`

## 应用一览

Bitool 内置 16 个独立应用，覆盖文件处理、文档工具、多媒体、LLM 等领域：

| 应用 | 命令 | 说明 | 模式 |
|------|------|------|:----:|
| 数字闹钟 | `alarmclk` | 桌面数字闹钟，支持贪睡延时 | GUI |
| Word 文档比较 | `docdiff` | 比较两个 Word 文档差异，生成修订版 | CLI |
| 文件扫描器 | `filescanw` | 多格式文件内容扫描（PDF/DOCX/XLSX/PPTX 等） | GUI |
| 图像转 ICO | `img2ico` / `img2icow` | 将图像转换为多尺寸 ICO 图标 | CLI/GUI |
| 图像转 PDF | `img2pdfw` | 将目录中的图像合并为单个 PDF | GUI |
| LLM 聊天客户端 | `llmcliw` | 本地大语言模型图形界面聊天客户端 | GUI |
| GGUF 模型量化 | `llmqntw` | 将 LLM 模型量化转换为 GGUF 格式 | GUI |
| LLM 推理服务器 | `llmsvrw` | 本地 LLM 模型推理 HTTP 服务 | GUI |
| LSC 曲线优化 | `lscopt` / `lscoptw` | 最小二乘曲线拟合优化工具 | CLI/GUI |
| PDF 加密解密 | `pdfcrypt` | 批量 PDF 加密/解密（128 位加密） | CLI |
| PDF 拆分 | `pdfsplit` | 按份数/页数/页码范围拆分 PDF | CLI |
| 通用答题系统 | `quizbasew` | 多题型答题系统，支持自适应学习 | GUI |
| 在线答题训练 | `quiztrainer` | 基于 Web 的答题训练平台（Flask） | Web |
| 视频格式转换 | `videoconv` / `videoconvw` | 基于 FFmpeg 的视频格式转换 | CLI/GUI |
| ZIP 加密 | `zipenc` | 批量加密为密码保护 ZIP（AES256） | CLI |
| RimWorld Mod 管理 | `rimmodw` | RimWorld 游戏 Mod 启用/禁用/排序管理 | GUI |

## Skills 工具集

Bitool 提供 20+ 个 CLI 技能工具，覆盖开发工作流的各个环节：

### 环境配置

| 命令 | 说明 |
|------|------|
| `envpy` | 一键配置 pip/UV/Conda 国内镜像源（清华/阿里云） |
| `envrs` | 一键配置 Rustup/Cargo 国内镜像源并安装 Rust |

### 构建与打包

| 命令 | 说明 |
|------|------|
| `pymake` | 替代 Makefile 的构建工具，支持 Python+Rust 双包构建、测试、发布 |
| `pypack` | Python 项目完整打包工具（嵌入式 Python + 依赖 + 加载器） |
| `pyembedinstall` | 下载安装嵌入式 Python |
| `pylibpack` | 项目依赖库下载与打包 |
| `pysourcepack` | 源代码打包 |
| `pyloadergen` | C 语言加载器生成与编译 |
| `pyarchive` | 多格式归档（zip/tar/7z） |

### 版本与 Git

| 命令 | 说明 |
|------|------|
| `bumpversion` | 语义化版本号自动递增（patch/minor/major），支持 Git 标签和提交 |
| `gitt` | Git 仓库常用操作封装（init/add/commit/push/pull/clean） |

### 包管理

| 命令 | 说明 |
|------|------|
| `pipt` | pip 操作封装，支持在线/离线模式和通配符卸载 |

### 文件处理

| 命令 | 说明 |
|------|------|
| `img2pdf` | 多图片合并为 PDF（CLI 版） |
| `pdf2img` | PDF 逐页转换为图片 |
| `filedate` | 移除文件日期前缀，替换为实际创建/修改时间 |
| `filelevel` | 文件等级后缀重命名（公开/内部/机密/绝密） |

### 系统工具

| 命令 | 说明 |
|------|------|
| `which` (`wch`) | 跨平台命令路径查找，支持模糊匹配 |
| `taskk` | 跨平台进程查找与终止，支持模糊匹配 |
| `cls` | 跨平台控制台清屏 |
| `sshcopyid` | SSH 公钥自动部署到远程服务器 |

## 开发

### 快速开始（推荐）

```bash
# 安装开发环境（自动构建 Rust + Python 双包）
pymake ia

# 验证安装
pymake t
```

### 常用命令

```bash
# 构建所有包（Rust + Python）
pymake ba

# 代码格式化与检查
pymake lint

# 运行测试
pymake t

# 清理所有构建产物
pymake ca

# 查看完整帮助
pymake help
```

### 手动构建（可选）

```bash
# 构建 Rust 核心模块
cd bitool-core && maturin develop

# 构建 Python 主包
cd .. && pip install -e .

# 构建发布包
cd bitool-core && maturin build -r
cd .. && python -m build
```

## 项目结构

```
bitool/
├── bitool-core/                # Rust 核心模块（PyO3 + Maturin）
│   ├── src/
│   │   ├── core/               #   Rust 核心功能
│   │   │   ├── cmd_exec.rs     #     命令执行
│   │   │   ├── config.rs       #     配置管理
│   │   │   ├── crypto.rs       #     加密功能（AES/SHA2）
│   │   │   ├── file_ops.rs     #     文件操作
│   │   │   ├── pdf_ops.rs      #     PDF 处理
│   │   │   ├── profiler.rs     #     性能分析
│   │   │   └── text_proc.rs    #     文本处理（正则/搜索）
│   │   ├── plugins/            #   插件系统
│   │   └── python/             #   PyO3 Python 绑定
│   ├── Cargo.toml
│   └── pyproject.toml
├── src/
│   └── bitool/                 # Python 主包（src layout）
│       ├── apps/               #   独立应用程序（16 个）
│       ├── cmd/                #   命令系统（命令模式）
│       ├── core/               #   核心基础设施
│       │   ├── config.py       #     JSON 配置管理
│       │   ├── database.py     #     数据库连接池
│       │   ├── env.py          #     环境变量管理
│       │   ├── logger.py       #     日志系统
│       │   ├── registry.py     #     注册表模式
│       │   ├── statemachine.py #     状态机
│       │   └── url.py          #     URL 工具
│       ├── gui/                #   GUI 基础设施（PySide）
│       ├── skills/             #   CLI 技能工具集（20+ 个）
│       ├── utils/              #   通用工具（执行器/文件/分析器）
│       ├── consts.py           #   平台/架构常量
│       └── types.py            #   通用类型定义
├── tests/                      # 测试代码
├── pyproject.toml              # Python 包配置
└── README.md
```

## 架构设计

Bitool 采用分层架构和 Rust+Python 混合设计：

```
┌─────────────────────────────────────────┐
│           Skills（技能层）               │  面向用户的 CLI 工具
│     BaseSkill / MultiCommandSkill       │  编排多个 Command
├─────────────────────────────────────────┤
│           Cmd（命令层）                  │  原子操作单元
│     BaseCommand + 条件守卫 + 依赖管理     │  Command Pattern
├─────────────────────────────────────────┤
│           Core（核心层）                 │  基础设施服务
│  配置 / 数据库 / 日志 / 注册表 / 状态机    │
├─────────────────────────────────────────┤
│  Python Utils  │  Rust Core (PyO3)      │  工具层
│  执行器/文件    │  文件/文本/PDF/加密/分析  │  性能关键路径
└─────────────────────────────────────────┘
```

**核心设计模式：**

- **命令模式**：`BaseCommand` 封装原子操作，支持条件守卫（allow/forbid）和依赖管理
- **模板方法模式**：`BaseSkill.run()` 定义固定执行流程，子类通过 `add_arguments` 和 `create_scheduler` 定制行为
- **注册表模式**：`Registry` / `SkillRegistry` 管理可扩展组件
- **混合架构**：Rust 处理计算密集型任务（文件 I/O、文本处理、PDF、加密），Python 负责编排和用户交互

## Python API 示例

```python
from bitool import CommandScheduler, Constants, profile

# 获取平台信息
print(Constants.is_windows)  # True/False
print(Constants.arch)  # 'amd64' / 'arm64'


# 使用性能分析装饰器
@profile
def heavy_task(): ...


# 使用命令调度器编排操作
from bitool.cmd import CommandScheduler, ReadFileCommand, WriteFileCommand, MergePdfsCommand, RunCommand

scheduler = CommandScheduler()
scheduler.add(ReadFileCommand(path="input.txt"))
scheduler.add(RunCommand(cmd="python process.py"))
scheduler.run()
```

## Rust 核心 API

```python
import bitool_core

# 文件操作
file_ops = bitool_core.PyFileOps()
files = file_ops.scan_directory("/path/to/dir")

# 文本处理
processor = bitool_core.PyTextProcessor()
result = processor.regex_search(pattern, text)

# PDF 操作
pdf_ops = bitool_core.PyPdfOps()
pdf_ops.merge_pdfs(["a.pdf", "b.pdf"], "merged.pdf")

# 性能分析
profiler = bitool_core.PyPerformanceProfiler()
profiler.start("task_name")
# ... 执行任务 ...
record = profiler.stop("task_name")
print(record.elapsed_ms)
```

## 许可证

MIT License
