aadt


Nameaadt JSON
Version 1.6.1 PyPI version JSON
download
home_pageNone
SummaryAnki Addon Dev ToolKit
upload_time2025-07-23 12:53:04
maintainerNone
docs_urlNone
authorLibukai
requires_python>=3.13
licenseAGPL-3.0-or-later
keywords anki development build-tools
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Anki Add-on Dev ToolKit (AADT)

<a title="License: GNU AGPLv3" href="https://github.com/glutanimate/anki-addon-builder/blob/master/LICENSE"><img src="https://img.shields.io/badge/license-GNU AGPLv3-green.svg"></a>
<a href="https://pypi.org/project/aadt/"><img src="https://img.shields.io/pypi/v/aadt.svg"></a>
<img src="https://img.shields.io/pypi/status/aadt.svg">

**Modern, AI-driven, focused on Anki new versions (2025.06+) add-on development and build toolkit with complete type safety and modern Python practices.**

English | [中文](#中文版)

## 🚀 Features

- **Python 3.13** Compatible with Anki 2025.06+
- **Qt6 Exclusive Support** Adapted for Anki 2025.06+ versions
- **Elegant Dependency Management** Fully based on uv for environment and dependency management
- **Code Quality Tools** Integrated ruff and ty for code quality enhancement
- **Comprehensive CLI Commands** Covering the entire workflow from initialization to release
- **Convenient Build and Distribution** Support for AnkiWeb and local distribution

## 📋 Table of Contents

- [Prerequisites](#prerequisites)
- [Quick Start](#quick-start)
- [Command Details](#command-details)
- [CI/CD Support](#cicd-support)
- [UI Development](#ui-development)
- [Code Quality](#code-quality)
- [Unit Testing](#unit-testing)
- [Git Integration](#git-integration)
- [License](#license)

## 🔧 Prerequisites

Install uv locally via `curl -LsSf https://astral.sh/uv/install.sh | sh`.

## ⚡ Quick Start

### 1. Initialize Add-on Project

Use `uvx` to run the latest version of the `init` command to quickly initialize your project:

```bash
# Create directory
mkdir my-addon
cd my-addon

# Interactive setup
uvx aadt init
```

The default initialization creates a basic but complete add-on project, including:

- Interactive collection of add-on information
- Application of template files and generation of project structure
- Development environment configuration and dependency installation via uv
- Git repository creation and initialization

After initialization, the project directory structure is as follows:

```
my_addon/
├── addon.json          # Add-on configuration file
├── src/                # Source code
│   └── my_addon/       # Main module
│       └── __init__.py # Main module initialization file
├── ui/                 # UI design
│   ├── designer/       # Qt Designer .ui files
│   └── resources/      # UI resources (icons, styles)
├── README.md           # Project documentation
├── ANKI.md             # Anki core library documentation
├── pyproject.toml      # Project configuration
├── uv.lock             # uv lock file
├── .python-version     # Specify Python version
├── .git/               # Git repository
└── .gitignore          # Ignore files
```

**💡 Tip**: After initialization, it's recommended to immediately run `uv run aadt claude` to generate the AI assistant memory file, which will provide complete modern Anki development guidance and help Claude AI better assist your add-on development work.

### 2. Development

To improve Add-on development efficiency, it's strongly recommended to use AI-assisted programming during development. AADT provides the `claude` command to generate specialized Claude Code guidance files:

```bash
# Generate CLAUDE.md file
aadt claude
```

This command will generate a CLAUDE.md file in the root directory based on your project configuration, including core guidance for Anki 25.06+ Add-on development, helping Claude AI better understand your project and provide precise development suggestions.

Additionally, there's an ANKI.md file in the root directory containing detailed documentation of modern Anki 25.06+ source code analysis and best practices, helping human programmers better understand Anki's overall architecture and development approach.

### 3. Testing

For convenient testing in the development environment, AADT provides the `test` command for testing add-ons in Anki.

```bash
aadt test
```

Running the `test` command will first create a soft link from the `src/` directory's project folder to Anki's add-on directory, then automatically start Anki and load the add-on.

AADT also provides the `link` command to manage operations for soft linking the project source code folder to Anki's add-on directory.

```bash
# Create soft link
aadt link

# Remove soft link
aadt link --unlink
```

### 4. Build

AADT provides the `build` command for building add-ons.

```bash
aadt build
```

The build command depends on a git repository and will by default find the latest git tag and build the corresponding commit version, making it easy to distinguish between test versions and official versions.

The generated add-on package is stored in the `dist` directory and can be used for direct installation or upload to AnkiWeb for distribution.

## 🔧 Command Details

### `init` - Initialize Add-on Project
```bash
# Initialize in current directory (interactive)
aadt init

# Initialize in specified directory
aadt init my-addon

# Use default values (non-interactive)
aadt init -y
```

**Features:**
- Interactive collection of add-on information (name, author, description, etc.)
- Generate complete project structure and apply template files
- Configure Python environment and dependency management using uv
- Initialize Git repository

### `ui` - Compile User Interface
```bash
# Compile all UI files
aadt ui
```

**Features:**
- Compile `.ui` files from `ui/designer/` to `src/module_name/gui/forms/qt6/`
- Automatically copy resource files from `ui/resources/` to `src/module_name/gui/resources/`
- Auto-generate `__init__.py` for resources package to support importlib.resources
- Support for icons, stylesheets, and various resource files

### `test` - Launch Testing
```bash
# Link add-on and start Anki testing
aadt test
```

**Features:**
- Automatically execute `aadt link` to create soft links
- Start Anki program to load add-on
- One-click testing workflow

### `link` - Development Environment Linking
```bash
# Create soft link to Anki add-on directory
aadt link

# Remove soft link
aadt link --unlink
```

**Features:**
- Soft link the add-on project folder under `src/` to Anki's add-on directory
- Convenient for launching Anki instances for real-time testing during development

### `claude` - Generate Claude AI Assistant Memory File
```bash
# Generate CLAUDE.md file
aadt claude

# Force overwrite existing file
aadt claude --force
```

**Features:**
- Automatically generate `CLAUDE.md` file based on project `addon.json` configuration
- Includes modern Anki 25.06+ development best practices and guidance
- Prevents accidental overwriting of existing CLAUDE.md files, supports `--force` for forced overwriting

### `build` - Build and Package Add-on
```bash
# Build latest tag version (default)
aadt build

# Build specific version
aadt build v1.2.0        # Specific git tag
aadt build dev           # Working directory (including uncommitted changes)
aadt build current       # Latest commit
aadt build release       # Latest tag (default)

# Specify distribution type
aadt build -d local      # Local development version
aadt build -d ankiweb    # AnkiWeb submission version
aadt build -d all        # Build both types simultaneously

# Combined usage
aadt build v1.2.0 -d local
```

**Distribution Type Description:**
- `local`: Suitable for local development, retains debug information
- `ankiweb`: Suitable for AnkiWeb submission, optimized file size
- `all`: Generate both versions simultaneously

**Features:**
- Generate `manifest.json` required by AnkiWeb based on `addon.json` configuration
- Include add-on metadata, dependencies, and other information

### `manifest` - Generate Manifest File
```bash
# Generate manifest.json
aadt manifest
```

### `clean` - Clean Build Files
```bash
# Clean all build artifacts
aadt clean
```

**Features:**
- Delete `dist/` directory and its contents
- Clean temporary files and cache

## 🚀 CI/CD Support

These commands provide finer build control, suitable for automated build pipelines:

### `create_dist` - Prepare Source Code Tree
```bash
aadt create_dist [version]
```

**Features:**
- Prepare source code tree to `dist/build` directory
- Handle version control and file archiving
- Prepare for subsequent build steps

#### `build_dist` - Build Source Code
```bash
aadt build_dist
```

**Features:**
- Process source code in `dist/build`
- Compile UI files, generate manifest files
- Execute all necessary code post-processing

#### `package_dist` - Package Distribution
```bash
aadt package_dist
```

**Features:**
- Package built files into `.ankiaddon` format
- Generate final distribution package

## 🎨 UI Development

### Using Qt Designer

AADT provides seamless integration for Qt Designer UI development with **intelligent PyQt6 to aqt.qt conversion** functionality:

1. **Design UI**: Create `.ui` files in `ui/designer/`
2. **Add Resources**: Place images and icons in `ui/resources/`
3. **Reference Resources**: Reference files in `ui/resources/` in Qt Designer
4. **Build UI**: Run `aadt ui` to automatically compile and copy resources

```bash
# Your project structure
my-addon/
├── ui/
│   ├── designer/
│   │   └── dialog.ui          # References ../resources/icon.png
│   └── resources/
│       └── icon.png           # Your resource file
└── src/my_addon/

# After running 'aadt ui'
my-addon/
├── src/my_addon/
│   ├── gui/forms/qt6/
│   │   └── dialog.py          # Compiled UI, using aqt.qt imports
│   └── gui/resources/
│       ├── __init__.py        # Auto-generated, supports importlib.resources
│       └── icon.png           # Automatically copied resource
```

### 🧠 Intelligent PyQt6 to aqt.qt Conversion

During the conversion process, AADT automatically converts pyuic6 output to Anki-compatible format and provides precise type annotations:

**Original Conversion (pyuic6 output):**
```python
from PyQt6 import QtCore, QtGui, QtWidgets

class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")
        self.verticalLayout = QtWidgets.QVBoxLayout(Dialog)
        self.label = QtWidgets.QLabel(Dialog)
        # ...
```

**Specialized Conversion (AADT intelligent conversion):**
```python
from aqt.qt import QDialog, QVBoxLayout, QLabel, QMetaObject

class Ui_Dialog(object):
    def setupUi(self, Dialog: QDialog) -> None:
        Dialog.setObjectName("Dialog")
        self.verticalLayout = QVBoxLayout(Dialog)
        self.label = QLabel(Dialog)
        # ...
```

### 🎯 Intelligent Type Inference

AADT analyzes your UI files and provides **precise type annotations** based on aqt.qt's actual type system:

- **`Ui_Dialog`** → `QDialog` type annotation
- **`Ui_MainWindow`** → `QMainWindow` type annotation
- **`Ui_CustomWidget`** → `QWidget` type annotation
- **`Ui_SettingsFrame`** → `QFrame` type annotation

### **Main Advantages:**
- ✅ **Anki Compatible Imports**: Use `from aqt.qt import ...` instead of `from PyQt6 import ...`
- ✅ **Intelligent Type Inference**: Automatically determine correct Qt widget types
- ✅ **Type Safe**: Generated code passes strict type checking
- ✅ **Minimized Imports**: Only import classes actually used in UI files
- ✅ **Automatic Resource Copying**: Resource files automatically copied to final package
- ✅ **Clean References**: No need for complex QRC compilation
- ✅ **Direct File Paths**: Use standard file paths in Python code
- ✅ **Development Friendly**: Resources immediately available for testing

## Code Quality

AADT includes modern development tools, strongly recommended for use during development to improve code quality and type safety, providing complete type annotations:

```bash
# Use ruff for code checking
uv run ruff check src/aadt/
uv run ruff format src/aadt/

# Use ty for type checking  
uv run ty check src/aadt/

# Run all checks
uv run ruff check src/aadt/ && uv run ty check src/aadt/
```

## Unit Testing

```bash
# Run tests
pytest

# Include coverage
pytest --cov=aadt
```

## 🚀 Git Integration

AADT is designed to work best in Git repositories, but **Git is not required**:

### When Git is Available (Recommended)
- **Version Detection**: Use Git tags and commits for version control
- **Source Archiving**: Use `git archive` for clean source extraction
- **Modification Time**: Use Git commit timestamps

### Non-Git Environment (Fallback Mode)
- **Version Detection**: Read from `pyproject.toml`, `VERSION` files, or generate timestamp-based versions
- **Source Archiving**: Copy current directory with intelligent exclusion (`.git`, `__pycache__`, etc.)
- **Modification Time**: Use current timestamp

### Usage Examples

```bash
# In Git repository (auto-detection)
aadt build -d local

# In non-Git directory (auto-fallback)
aadt build -d local  # Still works!

# Explicit version specification (works anywhere)
aadt build v1.2.0 -d local
```

The tool automatically detects your environment and chooses the appropriate method.

## 📚 Examples

Check the `tests/` directory for example configurations and usage patterns.

## 🎯 Design Philosophy

AADT follows these principles:

1. **Modern Python First**: Use latest language features (3.12+)
2. **Type Safety**: Complete type annotations and type checking validation
3. **Qt6 Focus**: No legacy Qt5 baggage, designed for current Anki
4. **Fast Build**: uv-based dependency management
5. **Developer Experience**: Clear CLI, good error messages, useful validation

## 📄 License

This project is licensed under the GNU AGPLv3 License. See the [LICENSE](LICENSE) file for details.

---

**Built with ❤️ for the Anki Community**

> This project is inspired by the [aab](https://github.com/glutanimate/anki-addon-builder) project, focusing on providing the best development experience for new version Anki add-on developers who are about to officially launch.

---

# 中文版

**现代化的、AI 驱动的、专注于 Anki 新版本(2025.06+)的插件开发和构建工具包,具备完整类型安全和现代 Python 实践。**

[English](#anki-add-on-dev-toolkit-aadt) | 中文

## 🚀 特性

- **Python 3.13** 与 Anki 2025.06+ 保持一致
- **Qt6 专用支持** 适配 Anki 2025.06+ 版本  
- **优雅依赖管理** 完全基于 uv 管理环境和依赖
- **代码质量工具** 集成 ruff 和 ty 提升代码质量
- **全面的 CLI 命令** 覆盖从初始化到发布的全流程
- **便捷构建和分发** 支持 AnkiWeb 和本地分发

## 📋 目录

- [前置要求](#前置要求)
- [快速开始](#快速开始)
- [命令详解](#命令详解)
- [CI/CD支持](#CI/CD支持)
- [UI开发](#UI开发)
- [代码质量](#代码质量)
- [单元测试](#单元测试)
- [Git 集成](#Git集成)
- [更新日志](#更新日志)
- [协议](#协议)

## 🔧 前置要求

通过 `curl -LsSf https://astral.sh/uv/install.sh | sh` 在本地安装 uv。

## ⚡ 快速开始

### 1. 初始化插件项目

使用 `uvx` 方式使用最新版本运行 `init` 命令快速初始化项目:

```bash
# 创建目录
mkdir my-addon
cd my-addon

# 交互式设置
uvx aadt init
```

默认的初始化会创建一个基础但完整的插件项目,包括:

- 通过交互方式搜集插件信息
- 应用模板文件,生成项目结构
- 通过 uv 配置开发环境并安装依赖
- 创建 git 仓库并初始化

初始化完成之后,项目的目录结构如下:

```
my_addon/
├── addon.json          # Addon 配置文件
├── src/                # 源代码
│   └── my_addon/       # 主模块
│       └── __init__.py # 主模块初始化文件
├── ui/                 # UI 设计
│   ├── designer/       # Qt Designer .ui 文件
│   └── resources/      # UI 资源(图标、样式)
├── README.md           # 项目说明
├── ANKI.md             # Anki 核心库详解
├── pyproject.toml      # 项目配置
├── uv.lock             # uv 锁定文件
├── .python-version     # 指定Python版本
├── .git/               # Git仓库
└── .gitignore          # 忽略文件

```

### 2. 开发

为提升 Addon 开发效率,强烈建议在开发过程中使用 AI 辅助编程。AADT 提供了 `claude` 命令来生成专门的 Claude Code 指引文件:

```bash
# 生成 CLAUDE.md 文件
aadt claude
```

这个命令会根据你的项目配置,在根目录下生成一个 CLAUDE.md 文件,其中包括了 Anki 25.06+ Addon 开发的核心指引,能帮助 Claude AI 更好地理解你的项目并提供精准的开发建议。

此外,还会在根目录下生成一个 ANKI.md 文件,其中包含现代 Anki 25.06+ 的源代码详细分析和最佳实践的详细文档,帮助 AI 和人类程序员更好地理解 Anki 的整体架构和开发方式。

### 3. 测试

为了方便开发环境下的测试,AADT 提供了 `test` 命令,用于在 Anki 中进行插件的测试。

```bash
aadt test
```

运行 `test` 命令会先将 `src/` 目录下的项目文件夹软链接到 Anki 的插件目录,然后自动启动 Anki 并加载插件。

同时,AADT 还提供了 `link` 命令,用于手动管理项目源代码文件夹软链接到 Anki 插件目录的操作。

```bash
# 创建软链接
aadt link

# 删除软链接
aadt link --unlink
```

### 4. 构建

AADT 提供了 `build` 命令,用于构建插件。

```bash
aadt build
```

构建命令依赖于 git 仓库,默认会查找最新的 git tag 并构建对应的 commit 版本,便于将测试版本和正式版本区分。

生成的插件包会存储在 `dist` 目录下,可以用于直接安装或者上传到 AnkiWeb 进行分发。

## 🔧 命令详解

### `init` - 初始化插件项目
```bash
# 在当前目录初始化(交互式)
aadt init

# 在指定目录初始化
aadt init my-addon

# 使用默认值(非交互式)
aadt init -y
```

**功能:**
- 交互式收集插件信息(名称、作者、描述等)
- 生成完整的项目结构和应用模板生成文件
- 使用 uv配置 Python 环境和依赖管理
- 初始化 Git 仓库

### `ui` - 编译用户界面
```bash
# 编译所有 UI 文件
aadt ui
```

**功能:**
- 编译 `ui/designer/` 中的 `.ui` 文件到 `src/模块名/gui/forms/qt6/`
- 复制 `ui/resources/` 中的资源文件到 `src/模块名/gui/resources/`,并进行路径初始化
- 支持图标、样式表等各种资源文件

### `test` - 启动测试
```bash
# 链接插件并启动 Anki 测试
aadt test
```

**功能:**
- 自动执行 `aadt link` 创建软链接
- 启动 Anki 程序加载插件
- 一键测试工作流

### `link` - 开发环境链接
```bash
# 创建软链接到 Anki 插件目录
aadt link

# 删除软链接
aadt link --unlink
```

**功能:**
- 将 `src/` 下的插件项目文件夹软链接到 Anki 插件目录
- 方便开发期间启动 Anki 实例进行实时测试

### `claude` - 生成 Claude AI 助手记忆文件
```bash
# 生成 CLAUDE.md 文件
aadt claude

# 强制覆盖现有 CLAUDE.md 文件
aadt claude --force
```

**功能:**
- 根据项目 `addon.json` 配置自动生成 `CLAUDE.md` 文件
- 包含现代 Anki 25.06+ 开发最佳实践和指导
- 防止意外覆盖现有文件,支持 `--force` 强制覆盖

### `build` - 构建和打包插件
```bash
# 构建最新标签版本(默认)
aadt build

# 构建特定版本
aadt build v1.2.0        # 特定 git 标签
aadt build dev           # 工作目录(包含未提交更改)
aadt build current       # 最新提交
aadt build release       # 最新标签(默认)

# 指定分发类型
aadt build -d local      # 本地开发版本
aadt build -d ankiweb    # AnkiWeb 提交版本
aadt build -d all        # 同时构建两种类型

# 组合使用
aadt build v1.2.0 -d local
```

**分发类型说明:**
- `local`: 适用于本地开发,保留调试信息
- `ankiweb`: 适用于 AnkiWeb 提交,优化文件大小
- `all`: 同时生成两种版本

**功能:**
- 根据 `addon.json` 配置生成 AnkiWeb 所需的 `manifest.json`
- 包含插件元数据、依赖关系等信息

### `manifest` - 生成清单文件
```bash
# 生成 manifest.json
aadt manifest
```

### `clean` - 清理构建文件
```bash
# 清理所有构建产物
aadt clean
```

**功能:**
- 删除 `dist/` 目录及其内容
- 清理临时文件和缓存

## 🚀 CI/CD 支持

这些命令提供更精细的构建控制,适用于自动化构建流水线:

### `create_dist` - 准备源代码树
```bash
aadt create_dist [version]
```

**功能:**
- 准备源代码树到 `dist/build` 目录
- 处理版本控制和文件归档
- 为后续构建步骤做准备

#### `build_dist` - 构建源代码
```bash
aadt build_dist
```

**功能:**
- 处理 `dist/build` 中的源代码
- 编译 UI 文件,生成清单文件
- 执行所有必要的代码后处理

#### `package_dist` - 打包分发
```bash
aadt package_dist
```

**功能:**
- 将构建好的文件打包成 `.ankiaddon` 格式
- 生成最终的分发包

## 🎨 UI 开发

### 使用 Qt Designer

AADT 为 Qt Designer UI 开发提供无缝集成,具备**智能 PyQt6 到 aqt.qt 转换**功能:

1. **设计UI**: 在 `ui/designer/` 中创建 `.ui` 文件
2. **添加资源**: 将图片、图标放在 `ui/resources/` 中
3. **引用资源**: 在 Qt Designer 中引用 `ui/resources/` 中的文件
4. **构建UI**: 运行 `aadt ui` 自动编译并复制资源

```bash
# 你的项目结构
my-addon/
├── ui/
│   ├── designer/
│   │   └── dialog.ui          # 引用 ../resources/icon.png
│   └── resources/
│       └── icon.png           # 你的资源文件
└── src/my_addon/

# 运行 'aadt ui' 后
my-addon/
├── src/my_addon/
│   ├── gui/forms/qt6/
│   │   └── dialog.py          # 编译后的UI,使用aqt.qt导入
│   └── gui/resources/
│       ├── __init__.py        # 自动生成,支持importlib.resources
│       └── icon.png           # 自动复制的资源
```

### 🧠 智能 PyQt6 到 aqt.qt 转换

在转化的过程中,AADT 使用 pyuic6 将 ui 文件输出转换为 Anki 兼容格式,并提供精确的类型注解:

**原始转化 (pyuic6 输出):**
```python
from PyQt6 import QtCore, QtGui, QtWidgets

class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")
        self.verticalLayout = QtWidgets.QVBoxLayout(Dialog)
        self.label = QtWidgets.QLabel(Dialog)
        # ...
```

**专用转化 (AADT 智能转换):**
```python
from aqt.qt import QDialog, QVBoxLayout, QLabel, QMetaObject

class Ui_Dialog(object):
    def setupUi(self, Dialog: QDialog) -> None:
        Dialog.setObjectName("Dialog")
        self.verticalLayout = QVBoxLayout(Dialog)
        self.label = QLabel(Dialog)
        # ...
```

### 🎯 智能类型推断

AADT 分析你的 UI 文件,基于 aqt.qt 的实际类型系统提供**精确的类型注解**:

- **`Ui_Dialog`** → `QDialog` 类型注解
- **`Ui_MainWindow`** → `QMainWindow` 类型注解  
- **`Ui_CustomWidget`** → `QWidget` 类型注解
- **`Ui_SettingsFrame`** → `QFrame` 类型注解

### **主要优势:**
- ✅ **Anki 兼容导入**: 使用 `from aqt.qt import ...` 替代 `from PyQt6 import ...`
- ✅ **智能类型推断**: 自动确定正确的 Qt 控件类型
- ✅ **mypy 兼容**: 生成的代码通过严格类型检查
- ✅ **最小化导入**: 只导入 UI 文件中实际使用的类
- ✅ **自动资源复制**: 资源文件自动复制到最终包中
- ✅ **清洁引用**: 无需复杂的QRC编译
- ✅ **直接文件路径**: 在Python代码中使用标准文件路径
- ✅ **开发友好**: 资源立即可用于测试

## 代码质量

AADT 包含现代开发工具,强烈建议在开发过程中使用,提升代码质量和类型安全,并提供完整的类型注解:

```bash
# 使用ruff进行代码检查
uv run ruff check src/aadt/
uv run ruff format src/aadt/

# 使用ty进行类型检查  
uv run ty check src/aadt/

# 运行所有检查
uv run ruff check src/aadt/ && uv run ty check src/aadt/
```

## 单元测试

```bash
# 运行测试
pytest

# 包含覆盖率
pytest --cov=aadt
```

## 🚀 Git 集成

AADT 设计为在 Git 仓库中工作最佳,但**不需要 Git**:

### Git 可用时(推荐)
- **版本检测**: 使用 Git 标签和提交进行版本控制
- **源码归档**: 使用 `git archive` 进行干净的源码提取
- **修改时间**: 使用 Git 提交时间戳

### 非Git环境(降级模式)
- **版本检测**: 从 `pyproject.toml`、`VERSION` 文件读取,或生成基于时间戳的版本
- **源码归档**: 复制当前目录并智能排除(`.git`、`__pycache__` 等)
- **修改时间**: 使用当前时间戳

### 使用示例

```bash
# 自动检测环境并构建
aadt build

# 在 Git 仓库中(自动检测)
aadt build -d local

# 在非 Git 目录中(自动降级)
aadt build -d local  # 仍然可以工作!

# 显式版本指定(任何地方都可以工作)
aadt build v1.2.0 -d local
```

工具会自动检测你的环境并选择适当的方法。

## 📚 示例

查看 `tests/` 目录获取示例配置和使用模式。

## 📄 协议

本项目基于GNU AGPLv3协议。详见[LICENSE](LICENSE)文件。

---

**为Anki社区用❤️构建**

> 本项目受 [aab](https://github.com/glutanimate/anki-addon-builder) 项目启发,专注于为即将正式上线的新版  Anki 插件开发者提供最佳的开发体验。

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "aadt",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.13",
    "maintainer_email": null,
    "keywords": "anki, development, build-tools",
    "author": "Libukai",
    "author_email": null,
    "download_url": "https://files.pythonhosted.org/packages/25/e9/146aeffd96777729462f2957a4563429343c89ad3fbb88ef77727ec64c76/aadt-1.6.1.tar.gz",
    "platform": null,
    "description": "# Anki Add-on Dev ToolKit (AADT)\n\n<a title=\"License: GNU AGPLv3\" href=\"https://github.com/glutanimate/anki-addon-builder/blob/master/LICENSE\"><img src=\"https://img.shields.io/badge/license-GNU AGPLv3-green.svg\"></a>\n<a href=\"https://pypi.org/project/aadt/\"><img src=\"https://img.shields.io/pypi/v/aadt.svg\"></a>\n<img src=\"https://img.shields.io/pypi/status/aadt.svg\">\n\n**Modern, AI-driven, focused on Anki new versions (2025.06+) add-on development and build toolkit with complete type safety and modern Python practices.**\n\nEnglish | [\u4e2d\u6587](#\u4e2d\u6587\u7248)\n\n## \ud83d\ude80 Features\n\n- **Python 3.13** Compatible with Anki 2025.06+\n- **Qt6 Exclusive Support** Adapted for Anki 2025.06+ versions\n- **Elegant Dependency Management** Fully based on uv for environment and dependency management\n- **Code Quality Tools** Integrated ruff and ty for code quality enhancement\n- **Comprehensive CLI Commands** Covering the entire workflow from initialization to release\n- **Convenient Build and Distribution** Support for AnkiWeb and local distribution\n\n## \ud83d\udccb Table of Contents\n\n- [Prerequisites](#prerequisites)\n- [Quick Start](#quick-start)\n- [Command Details](#command-details)\n- [CI/CD Support](#cicd-support)\n- [UI Development](#ui-development)\n- [Code Quality](#code-quality)\n- [Unit Testing](#unit-testing)\n- [Git Integration](#git-integration)\n- [License](#license)\n\n## \ud83d\udd27 Prerequisites\n\nInstall uv locally via `curl -LsSf https://astral.sh/uv/install.sh | sh`.\n\n## \u26a1 Quick Start\n\n### 1. Initialize Add-on Project\n\nUse `uvx` to run the latest version of the `init` command to quickly initialize your project:\n\n```bash\n# Create directory\nmkdir my-addon\ncd my-addon\n\n# Interactive setup\nuvx aadt init\n```\n\nThe default initialization creates a basic but complete add-on project, including:\n\n- Interactive collection of add-on information\n- Application of template files and generation of project structure\n- Development environment configuration and dependency installation via uv\n- Git repository creation and initialization\n\nAfter initialization, the project directory structure is as follows:\n\n```\nmy_addon/\n\u251c\u2500\u2500 addon.json          # Add-on configuration file\n\u251c\u2500\u2500 src/                # Source code\n\u2502   \u2514\u2500\u2500 my_addon/       # Main module\n\u2502       \u2514\u2500\u2500 __init__.py # Main module initialization file\n\u251c\u2500\u2500 ui/                 # UI design\n\u2502   \u251c\u2500\u2500 designer/       # Qt Designer .ui files\n\u2502   \u2514\u2500\u2500 resources/      # UI resources (icons, styles)\n\u251c\u2500\u2500 README.md           # Project documentation\n\u251c\u2500\u2500 ANKI.md             # Anki core library documentation\n\u251c\u2500\u2500 pyproject.toml      # Project configuration\n\u251c\u2500\u2500 uv.lock             # uv lock file\n\u251c\u2500\u2500 .python-version     # Specify Python version\n\u251c\u2500\u2500 .git/               # Git repository\n\u2514\u2500\u2500 .gitignore          # Ignore files\n```\n\n**\ud83d\udca1 Tip**: After initialization, it's recommended to immediately run `uv run aadt claude` to generate the AI assistant memory file, which will provide complete modern Anki development guidance and help Claude AI better assist your add-on development work.\n\n### 2. Development\n\nTo improve Add-on development efficiency, it's strongly recommended to use AI-assisted programming during development. AADT provides the `claude` command to generate specialized Claude Code guidance files:\n\n```bash\n# Generate CLAUDE.md file\naadt claude\n```\n\nThis command will generate a CLAUDE.md file in the root directory based on your project configuration, including core guidance for Anki 25.06+ Add-on development, helping Claude AI better understand your project and provide precise development suggestions.\n\nAdditionally, there's an ANKI.md file in the root directory containing detailed documentation of modern Anki 25.06+ source code analysis and best practices, helping human programmers better understand Anki's overall architecture and development approach.\n\n### 3. Testing\n\nFor convenient testing in the development environment, AADT provides the `test` command for testing add-ons in Anki.\n\n```bash\naadt test\n```\n\nRunning the `test` command will first create a soft link from the `src/` directory's project folder to Anki's add-on directory, then automatically start Anki and load the add-on.\n\nAADT also provides the `link` command to manage operations for soft linking the project source code folder to Anki's add-on directory.\n\n```bash\n# Create soft link\naadt link\n\n# Remove soft link\naadt link --unlink\n```\n\n### 4. Build\n\nAADT provides the `build` command for building add-ons.\n\n```bash\naadt build\n```\n\nThe build command depends on a git repository and will by default find the latest git tag and build the corresponding commit version, making it easy to distinguish between test versions and official versions.\n\nThe generated add-on package is stored in the `dist` directory and can be used for direct installation or upload to AnkiWeb for distribution.\n\n## \ud83d\udd27 Command Details\n\n### `init` - Initialize Add-on Project\n```bash\n# Initialize in current directory (interactive)\naadt init\n\n# Initialize in specified directory\naadt init my-addon\n\n# Use default values (non-interactive)\naadt init -y\n```\n\n**Features:**\n- Interactive collection of add-on information (name, author, description, etc.)\n- Generate complete project structure and apply template files\n- Configure Python environment and dependency management using uv\n- Initialize Git repository\n\n### `ui` - Compile User Interface\n```bash\n# Compile all UI files\naadt ui\n```\n\n**Features:**\n- Compile `.ui` files from `ui/designer/` to `src/module_name/gui/forms/qt6/`\n- Automatically copy resource files from `ui/resources/` to `src/module_name/gui/resources/`\n- Auto-generate `__init__.py` for resources package to support importlib.resources\n- Support for icons, stylesheets, and various resource files\n\n### `test` - Launch Testing\n```bash\n# Link add-on and start Anki testing\naadt test\n```\n\n**Features:**\n- Automatically execute `aadt link` to create soft links\n- Start Anki program to load add-on\n- One-click testing workflow\n\n### `link` - Development Environment Linking\n```bash\n# Create soft link to Anki add-on directory\naadt link\n\n# Remove soft link\naadt link --unlink\n```\n\n**Features:**\n- Soft link the add-on project folder under `src/` to Anki's add-on directory\n- Convenient for launching Anki instances for real-time testing during development\n\n### `claude` - Generate Claude AI Assistant Memory File\n```bash\n# Generate CLAUDE.md file\naadt claude\n\n# Force overwrite existing file\naadt claude --force\n```\n\n**Features:**\n- Automatically generate `CLAUDE.md` file based on project `addon.json` configuration\n- Includes modern Anki 25.06+ development best practices and guidance\n- Prevents accidental overwriting of existing CLAUDE.md files, supports `--force` for forced overwriting\n\n### `build` - Build and Package Add-on\n```bash\n# Build latest tag version (default)\naadt build\n\n# Build specific version\naadt build v1.2.0        # Specific git tag\naadt build dev           # Working directory (including uncommitted changes)\naadt build current       # Latest commit\naadt build release       # Latest tag (default)\n\n# Specify distribution type\naadt build -d local      # Local development version\naadt build -d ankiweb    # AnkiWeb submission version\naadt build -d all        # Build both types simultaneously\n\n# Combined usage\naadt build v1.2.0 -d local\n```\n\n**Distribution Type Description:**\n- `local`: Suitable for local development, retains debug information\n- `ankiweb`: Suitable for AnkiWeb submission, optimized file size\n- `all`: Generate both versions simultaneously\n\n**Features:**\n- Generate `manifest.json` required by AnkiWeb based on `addon.json` configuration\n- Include add-on metadata, dependencies, and other information\n\n### `manifest` - Generate Manifest File\n```bash\n# Generate manifest.json\naadt manifest\n```\n\n### `clean` - Clean Build Files\n```bash\n# Clean all build artifacts\naadt clean\n```\n\n**Features:**\n- Delete `dist/` directory and its contents\n- Clean temporary files and cache\n\n## \ud83d\ude80 CI/CD Support\n\nThese commands provide finer build control, suitable for automated build pipelines:\n\n### `create_dist` - Prepare Source Code Tree\n```bash\naadt create_dist [version]\n```\n\n**Features:**\n- Prepare source code tree to `dist/build` directory\n- Handle version control and file archiving\n- Prepare for subsequent build steps\n\n#### `build_dist` - Build Source Code\n```bash\naadt build_dist\n```\n\n**Features:**\n- Process source code in `dist/build`\n- Compile UI files, generate manifest files\n- Execute all necessary code post-processing\n\n#### `package_dist` - Package Distribution\n```bash\naadt package_dist\n```\n\n**Features:**\n- Package built files into `.ankiaddon` format\n- Generate final distribution package\n\n## \ud83c\udfa8 UI Development\n\n### Using Qt Designer\n\nAADT provides seamless integration for Qt Designer UI development with **intelligent PyQt6 to aqt.qt conversion** functionality:\n\n1. **Design UI**: Create `.ui` files in `ui/designer/`\n2. **Add Resources**: Place images and icons in `ui/resources/`\n3. **Reference Resources**: Reference files in `ui/resources/` in Qt Designer\n4. **Build UI**: Run `aadt ui` to automatically compile and copy resources\n\n```bash\n# Your project structure\nmy-addon/\n\u251c\u2500\u2500 ui/\n\u2502   \u251c\u2500\u2500 designer/\n\u2502   \u2502   \u2514\u2500\u2500 dialog.ui          # References ../resources/icon.png\n\u2502   \u2514\u2500\u2500 resources/\n\u2502       \u2514\u2500\u2500 icon.png           # Your resource file\n\u2514\u2500\u2500 src/my_addon/\n\n# After running 'aadt ui'\nmy-addon/\n\u251c\u2500\u2500 src/my_addon/\n\u2502   \u251c\u2500\u2500 gui/forms/qt6/\n\u2502   \u2502   \u2514\u2500\u2500 dialog.py          # Compiled UI, using aqt.qt imports\n\u2502   \u2514\u2500\u2500 gui/resources/\n\u2502       \u251c\u2500\u2500 __init__.py        # Auto-generated, supports importlib.resources\n\u2502       \u2514\u2500\u2500 icon.png           # Automatically copied resource\n```\n\n### \ud83e\udde0 Intelligent PyQt6 to aqt.qt Conversion\n\nDuring the conversion process, AADT automatically converts pyuic6 output to Anki-compatible format and provides precise type annotations:\n\n**Original Conversion (pyuic6 output):**\n```python\nfrom PyQt6 import QtCore, QtGui, QtWidgets\n\nclass Ui_Dialog(object):\n    def setupUi(self, Dialog):\n        Dialog.setObjectName(\"Dialog\")\n        self.verticalLayout = QtWidgets.QVBoxLayout(Dialog)\n        self.label = QtWidgets.QLabel(Dialog)\n        # ...\n```\n\n**Specialized Conversion (AADT intelligent conversion):**\n```python\nfrom aqt.qt import QDialog, QVBoxLayout, QLabel, QMetaObject\n\nclass Ui_Dialog(object):\n    def setupUi(self, Dialog: QDialog) -> None:\n        Dialog.setObjectName(\"Dialog\")\n        self.verticalLayout = QVBoxLayout(Dialog)\n        self.label = QLabel(Dialog)\n        # ...\n```\n\n### \ud83c\udfaf Intelligent Type Inference\n\nAADT analyzes your UI files and provides **precise type annotations** based on aqt.qt's actual type system:\n\n- **`Ui_Dialog`** \u2192 `QDialog` type annotation\n- **`Ui_MainWindow`** \u2192 `QMainWindow` type annotation\n- **`Ui_CustomWidget`** \u2192 `QWidget` type annotation\n- **`Ui_SettingsFrame`** \u2192 `QFrame` type annotation\n\n### **Main Advantages:**\n- \u2705 **Anki Compatible Imports**: Use `from aqt.qt import ...` instead of `from PyQt6 import ...`\n- \u2705 **Intelligent Type Inference**: Automatically determine correct Qt widget types\n- \u2705 **Type Safe**: Generated code passes strict type checking\n- \u2705 **Minimized Imports**: Only import classes actually used in UI files\n- \u2705 **Automatic Resource Copying**: Resource files automatically copied to final package\n- \u2705 **Clean References**: No need for complex QRC compilation\n- \u2705 **Direct File Paths**: Use standard file paths in Python code\n- \u2705 **Development Friendly**: Resources immediately available for testing\n\n## Code Quality\n\nAADT includes modern development tools, strongly recommended for use during development to improve code quality and type safety, providing complete type annotations:\n\n```bash\n# Use ruff for code checking\nuv run ruff check src/aadt/\nuv run ruff format src/aadt/\n\n# Use ty for type checking  \nuv run ty check src/aadt/\n\n# Run all checks\nuv run ruff check src/aadt/ && uv run ty check src/aadt/\n```\n\n## Unit Testing\n\n```bash\n# Run tests\npytest\n\n# Include coverage\npytest --cov=aadt\n```\n\n## \ud83d\ude80 Git Integration\n\nAADT is designed to work best in Git repositories, but **Git is not required**:\n\n### When Git is Available (Recommended)\n- **Version Detection**: Use Git tags and commits for version control\n- **Source Archiving**: Use `git archive` for clean source extraction\n- **Modification Time**: Use Git commit timestamps\n\n### Non-Git Environment (Fallback Mode)\n- **Version Detection**: Read from `pyproject.toml`, `VERSION` files, or generate timestamp-based versions\n- **Source Archiving**: Copy current directory with intelligent exclusion (`.git`, `__pycache__`, etc.)\n- **Modification Time**: Use current timestamp\n\n### Usage Examples\n\n```bash\n# In Git repository (auto-detection)\naadt build -d local\n\n# In non-Git directory (auto-fallback)\naadt build -d local  # Still works!\n\n# Explicit version specification (works anywhere)\naadt build v1.2.0 -d local\n```\n\nThe tool automatically detects your environment and chooses the appropriate method.\n\n## \ud83d\udcda Examples\n\nCheck the `tests/` directory for example configurations and usage patterns.\n\n## \ud83c\udfaf Design Philosophy\n\nAADT follows these principles:\n\n1. **Modern Python First**: Use latest language features (3.12+)\n2. **Type Safety**: Complete type annotations and type checking validation\n3. **Qt6 Focus**: No legacy Qt5 baggage, designed for current Anki\n4. **Fast Build**: uv-based dependency management\n5. **Developer Experience**: Clear CLI, good error messages, useful validation\n\n## \ud83d\udcc4 License\n\nThis project is licensed under the GNU AGPLv3 License. See the [LICENSE](LICENSE) file for details.\n\n---\n\n**Built with \u2764\ufe0f for the Anki Community**\n\n> This project is inspired by the [aab](https://github.com/glutanimate/anki-addon-builder) project, focusing on providing the best development experience for new version Anki add-on developers who are about to officially launch.\n\n---\n\n# \u4e2d\u6587\u7248\n\n**\u73b0\u4ee3\u5316\u7684\u3001AI \u9a71\u52a8\u7684\u3001\u4e13\u6ce8\u4e8e Anki \u65b0\u7248\u672c\uff082025.06+\uff09\u7684\u63d2\u4ef6\u5f00\u53d1\u548c\u6784\u5efa\u5de5\u5177\u5305\uff0c\u5177\u5907\u5b8c\u6574\u7c7b\u578b\u5b89\u5168\u548c\u73b0\u4ee3 Python \u5b9e\u8df5\u3002**\n\n[English](#anki-add-on-dev-toolkit-aadt) | \u4e2d\u6587\n\n## \ud83d\ude80 \u7279\u6027\n\n- **Python 3.13** \u4e0e Anki 2025.06+ \u4fdd\u6301\u4e00\u81f4\n- **Qt6 \u4e13\u7528\u652f\u6301** \u9002\u914d Anki 2025.06+ \u7248\u672c  \n- **\u4f18\u96c5\u4f9d\u8d56\u7ba1\u7406** \u5b8c\u5168\u57fa\u4e8e uv \u7ba1\u7406\u73af\u5883\u548c\u4f9d\u8d56\n- **\u4ee3\u7801\u8d28\u91cf\u5de5\u5177** \u96c6\u6210 ruff \u548c ty \u63d0\u5347\u4ee3\u7801\u8d28\u91cf\n- **\u5168\u9762\u7684 CLI \u547d\u4ee4** \u8986\u76d6\u4ece\u521d\u59cb\u5316\u5230\u53d1\u5e03\u7684\u5168\u6d41\u7a0b\n- **\u4fbf\u6377\u6784\u5efa\u548c\u5206\u53d1** \u652f\u6301 AnkiWeb \u548c\u672c\u5730\u5206\u53d1\n\n## \ud83d\udccb \u76ee\u5f55\n\n- [\u524d\u7f6e\u8981\u6c42](#\u524d\u7f6e\u8981\u6c42)\n- [\u5feb\u901f\u5f00\u59cb](#\u5feb\u901f\u5f00\u59cb)\n- [\u547d\u4ee4\u8be6\u89e3](#\u547d\u4ee4\u8be6\u89e3)\n- [CI/CD\u652f\u6301](#CI/CD\u652f\u6301)\n- [UI\u5f00\u53d1](#UI\u5f00\u53d1)\n- [\u4ee3\u7801\u8d28\u91cf](#\u4ee3\u7801\u8d28\u91cf)\n- [\u5355\u5143\u6d4b\u8bd5](#\u5355\u5143\u6d4b\u8bd5)\n- [Git \u96c6\u6210](#Git\u96c6\u6210)\n- [\u66f4\u65b0\u65e5\u5fd7](#\u66f4\u65b0\u65e5\u5fd7)\n- [\u534f\u8bae](#\u534f\u8bae)\n\n## \ud83d\udd27 \u524d\u7f6e\u8981\u6c42\n\n\u901a\u8fc7 `curl -LsSf https://astral.sh/uv/install.sh | sh` \u5728\u672c\u5730\u5b89\u88c5 uv\u3002\n\n## \u26a1 \u5feb\u901f\u5f00\u59cb\n\n### 1. \u521d\u59cb\u5316\u63d2\u4ef6\u9879\u76ee\n\n\u4f7f\u7528 `uvx` \u65b9\u5f0f\u4f7f\u7528\u6700\u65b0\u7248\u672c\u8fd0\u884c `init` \u547d\u4ee4\u5feb\u901f\u521d\u59cb\u5316\u9879\u76ee\uff1a\n\n```bash\n# \u521b\u5efa\u76ee\u5f55\nmkdir my-addon\ncd my-addon\n\n# \u4ea4\u4e92\u5f0f\u8bbe\u7f6e\nuvx aadt init\n```\n\n\u9ed8\u8ba4\u7684\u521d\u59cb\u5316\u4f1a\u521b\u5efa\u4e00\u4e2a\u57fa\u7840\u4f46\u5b8c\u6574\u7684\u63d2\u4ef6\u9879\u76ee\uff0c\u5305\u62ec\uff1a\n\n- \u901a\u8fc7\u4ea4\u4e92\u65b9\u5f0f\u641c\u96c6\u63d2\u4ef6\u4fe1\u606f\n- \u5e94\u7528\u6a21\u677f\u6587\u4ef6\uff0c\u751f\u6210\u9879\u76ee\u7ed3\u6784\n- \u901a\u8fc7 uv \u914d\u7f6e\u5f00\u53d1\u73af\u5883\u5e76\u5b89\u88c5\u4f9d\u8d56\n- \u521b\u5efa git \u4ed3\u5e93\u5e76\u521d\u59cb\u5316\n\n\u521d\u59cb\u5316\u5b8c\u6210\u4e4b\u540e\uff0c\u9879\u76ee\u7684\u76ee\u5f55\u7ed3\u6784\u5982\u4e0b\uff1a\n\n```\nmy_addon/\n\u251c\u2500\u2500 addon.json          # Addon \u914d\u7f6e\u6587\u4ef6\n\u251c\u2500\u2500 src/                # \u6e90\u4ee3\u7801\n\u2502   \u2514\u2500\u2500 my_addon/       # \u4e3b\u6a21\u5757\n\u2502       \u2514\u2500\u2500 __init__.py # \u4e3b\u6a21\u5757\u521d\u59cb\u5316\u6587\u4ef6\n\u251c\u2500\u2500 ui/                 # UI \u8bbe\u8ba1\n\u2502   \u251c\u2500\u2500 designer/       # Qt Designer .ui \u6587\u4ef6\n\u2502   \u2514\u2500\u2500 resources/      # UI \u8d44\u6e90\uff08\u56fe\u6807\u3001\u6837\u5f0f\uff09\n\u251c\u2500\u2500 README.md           # \u9879\u76ee\u8bf4\u660e\n\u251c\u2500\u2500 ANKI.md             # Anki \u6838\u5fc3\u5e93\u8be6\u89e3\n\u251c\u2500\u2500 pyproject.toml      # \u9879\u76ee\u914d\u7f6e\n\u251c\u2500\u2500 uv.lock             # uv \u9501\u5b9a\u6587\u4ef6\n\u251c\u2500\u2500 .python-version     # \u6307\u5b9aPython\u7248\u672c\n\u251c\u2500\u2500 .git/               # Git\u4ed3\u5e93\n\u2514\u2500\u2500 .gitignore          # \u5ffd\u7565\u6587\u4ef6\n\n```\n\n### 2. \u5f00\u53d1\n\n\u4e3a\u63d0\u5347 Addon \u5f00\u53d1\u6548\u7387\uff0c\u5f3a\u70c8\u5efa\u8bae\u5728\u5f00\u53d1\u8fc7\u7a0b\u4e2d\u4f7f\u7528 AI \u8f85\u52a9\u7f16\u7a0b\u3002AADT \u63d0\u4f9b\u4e86 `claude` \u547d\u4ee4\u6765\u751f\u6210\u4e13\u95e8\u7684 Claude Code \u6307\u5f15\u6587\u4ef6\uff1a\n\n```bash\n# \u751f\u6210 CLAUDE.md \u6587\u4ef6\naadt claude\n```\n\n\u8fd9\u4e2a\u547d\u4ee4\u4f1a\u6839\u636e\u4f60\u7684\u9879\u76ee\u914d\u7f6e\uff0c\u5728\u6839\u76ee\u5f55\u4e0b\u751f\u6210\u4e00\u4e2a CLAUDE.md \u6587\u4ef6\uff0c\u5176\u4e2d\u5305\u62ec\u4e86 Anki 25.06+ Addon \u5f00\u53d1\u7684\u6838\u5fc3\u6307\u5f15\uff0c\u80fd\u5e2e\u52a9 Claude AI \u66f4\u597d\u5730\u7406\u89e3\u4f60\u7684\u9879\u76ee\u5e76\u63d0\u4f9b\u7cbe\u51c6\u7684\u5f00\u53d1\u5efa\u8bae\u3002\n\n\u6b64\u5916\uff0c\u8fd8\u4f1a\u5728\u6839\u76ee\u5f55\u4e0b\u751f\u6210\u4e00\u4e2a ANKI.md \u6587\u4ef6\uff0c\u5176\u4e2d\u5305\u542b\u73b0\u4ee3 Anki 25.06+ \u7684\u6e90\u4ee3\u7801\u8be6\u7ec6\u5206\u6790\u548c\u6700\u4f73\u5b9e\u8df5\u7684\u8be6\u7ec6\u6587\u6863\uff0c\u5e2e\u52a9 AI \u548c\u4eba\u7c7b\u7a0b\u5e8f\u5458\u66f4\u597d\u5730\u7406\u89e3 Anki \u7684\u6574\u4f53\u67b6\u6784\u548c\u5f00\u53d1\u65b9\u5f0f\u3002\n\n### 3. \u6d4b\u8bd5\n\n\u4e3a\u4e86\u65b9\u4fbf\u5f00\u53d1\u73af\u5883\u4e0b\u7684\u6d4b\u8bd5\uff0cAADT \u63d0\u4f9b\u4e86 `test` \u547d\u4ee4\uff0c\u7528\u4e8e\u5728 Anki \u4e2d\u8fdb\u884c\u63d2\u4ef6\u7684\u6d4b\u8bd5\u3002\n\n```bash\naadt test\n```\n\n\u8fd0\u884c `test` \u547d\u4ee4\u4f1a\u5148\u5c06 `src/` \u76ee\u5f55\u4e0b\u7684\u9879\u76ee\u6587\u4ef6\u5939\u8f6f\u94fe\u63a5\u5230 Anki \u7684\u63d2\u4ef6\u76ee\u5f55\uff0c\u7136\u540e\u81ea\u52a8\u542f\u52a8 Anki \u5e76\u52a0\u8f7d\u63d2\u4ef6\u3002\n\n\u540c\u65f6\uff0cAADT \u8fd8\u63d0\u4f9b\u4e86 `link` \u547d\u4ee4\uff0c\u7528\u4e8e\u624b\u52a8\u7ba1\u7406\u9879\u76ee\u6e90\u4ee3\u7801\u6587\u4ef6\u5939\u8f6f\u94fe\u63a5\u5230 Anki \u63d2\u4ef6\u76ee\u5f55\u7684\u64cd\u4f5c\u3002\n\n```bash\n# \u521b\u5efa\u8f6f\u94fe\u63a5\naadt link\n\n# \u5220\u9664\u8f6f\u94fe\u63a5\naadt link --unlink\n```\n\n### 4. \u6784\u5efa\n\nAADT \u63d0\u4f9b\u4e86 `build` \u547d\u4ee4\uff0c\u7528\u4e8e\u6784\u5efa\u63d2\u4ef6\u3002\n\n```bash\naadt build\n```\n\n\u6784\u5efa\u547d\u4ee4\u4f9d\u8d56\u4e8e git \u4ed3\u5e93\uff0c\u9ed8\u8ba4\u4f1a\u67e5\u627e\u6700\u65b0\u7684 git tag \u5e76\u6784\u5efa\u5bf9\u5e94\u7684 commit \u7248\u672c\uff0c\u4fbf\u4e8e\u5c06\u6d4b\u8bd5\u7248\u672c\u548c\u6b63\u5f0f\u7248\u672c\u533a\u5206\u3002\n\n\u751f\u6210\u7684\u63d2\u4ef6\u5305\u4f1a\u5b58\u50a8\u5728 `dist` \u76ee\u5f55\u4e0b\uff0c\u53ef\u4ee5\u7528\u4e8e\u76f4\u63a5\u5b89\u88c5\u6216\u8005\u4e0a\u4f20\u5230 AnkiWeb \u8fdb\u884c\u5206\u53d1\u3002\n\n## \ud83d\udd27 \u547d\u4ee4\u8be6\u89e3\n\n### `init` - \u521d\u59cb\u5316\u63d2\u4ef6\u9879\u76ee\n```bash\n# \u5728\u5f53\u524d\u76ee\u5f55\u521d\u59cb\u5316\uff08\u4ea4\u4e92\u5f0f\uff09\naadt init\n\n# \u5728\u6307\u5b9a\u76ee\u5f55\u521d\u59cb\u5316\naadt init my-addon\n\n# \u4f7f\u7528\u9ed8\u8ba4\u503c\uff08\u975e\u4ea4\u4e92\u5f0f\uff09\naadt init -y\n```\n\n**\u529f\u80fd\uff1a**\n- \u4ea4\u4e92\u5f0f\u6536\u96c6\u63d2\u4ef6\u4fe1\u606f\uff08\u540d\u79f0\u3001\u4f5c\u8005\u3001\u63cf\u8ff0\u7b49\uff09\n- \u751f\u6210\u5b8c\u6574\u7684\u9879\u76ee\u7ed3\u6784\u548c\u5e94\u7528\u6a21\u677f\u751f\u6210\u6587\u4ef6\n- \u4f7f\u7528 uv\u914d\u7f6e Python \u73af\u5883\u548c\u4f9d\u8d56\u7ba1\u7406\n- \u521d\u59cb\u5316 Git \u4ed3\u5e93\n\n### `ui` - \u7f16\u8bd1\u7528\u6237\u754c\u9762\n```bash\n# \u7f16\u8bd1\u6240\u6709 UI \u6587\u4ef6\naadt ui\n```\n\n**\u529f\u80fd\uff1a**\n- \u7f16\u8bd1 `ui/designer/` \u4e2d\u7684 `.ui` \u6587\u4ef6\u5230 `src/\u6a21\u5757\u540d/gui/forms/qt6/`\n- \u590d\u5236 `ui/resources/` \u4e2d\u7684\u8d44\u6e90\u6587\u4ef6\u5230 `src/\u6a21\u5757\u540d/gui/resources/`\uff0c\u5e76\u8fdb\u884c\u8def\u5f84\u521d\u59cb\u5316\n- \u652f\u6301\u56fe\u6807\u3001\u6837\u5f0f\u8868\u7b49\u5404\u79cd\u8d44\u6e90\u6587\u4ef6\n\n### `test` - \u542f\u52a8\u6d4b\u8bd5\n```bash\n# \u94fe\u63a5\u63d2\u4ef6\u5e76\u542f\u52a8 Anki \u6d4b\u8bd5\naadt test\n```\n\n**\u529f\u80fd\uff1a**\n- \u81ea\u52a8\u6267\u884c `aadt link` \u521b\u5efa\u8f6f\u94fe\u63a5\n- \u542f\u52a8 Anki \u7a0b\u5e8f\u52a0\u8f7d\u63d2\u4ef6\n- \u4e00\u952e\u6d4b\u8bd5\u5de5\u4f5c\u6d41\n\n### `link` - \u5f00\u53d1\u73af\u5883\u94fe\u63a5\n```bash\n# \u521b\u5efa\u8f6f\u94fe\u63a5\u5230 Anki \u63d2\u4ef6\u76ee\u5f55\naadt link\n\n# \u5220\u9664\u8f6f\u94fe\u63a5\naadt link --unlink\n```\n\n**\u529f\u80fd\uff1a**\n- \u5c06 `src/` \u4e0b\u7684\u63d2\u4ef6\u9879\u76ee\u6587\u4ef6\u5939\u8f6f\u94fe\u63a5\u5230 Anki \u63d2\u4ef6\u76ee\u5f55\n- \u65b9\u4fbf\u5f00\u53d1\u671f\u95f4\u542f\u52a8 Anki \u5b9e\u4f8b\u8fdb\u884c\u5b9e\u65f6\u6d4b\u8bd5\n\n### `claude` - \u751f\u6210 Claude AI \u52a9\u624b\u8bb0\u5fc6\u6587\u4ef6\n```bash\n# \u751f\u6210 CLAUDE.md \u6587\u4ef6\naadt claude\n\n# \u5f3a\u5236\u8986\u76d6\u73b0\u6709 CLAUDE.md \u6587\u4ef6\naadt claude --force\n```\n\n**\u529f\u80fd\uff1a**\n- \u6839\u636e\u9879\u76ee `addon.json` \u914d\u7f6e\u81ea\u52a8\u751f\u6210 `CLAUDE.md` \u6587\u4ef6\n- \u5305\u542b\u73b0\u4ee3 Anki 25.06+ \u5f00\u53d1\u6700\u4f73\u5b9e\u8df5\u548c\u6307\u5bfc\n- \u9632\u6b62\u610f\u5916\u8986\u76d6\u73b0\u6709\u6587\u4ef6\uff0c\u652f\u6301 `--force` \u5f3a\u5236\u8986\u76d6\n\n### `build` - \u6784\u5efa\u548c\u6253\u5305\u63d2\u4ef6\n```bash\n# \u6784\u5efa\u6700\u65b0\u6807\u7b7e\u7248\u672c\uff08\u9ed8\u8ba4\uff09\naadt build\n\n# \u6784\u5efa\u7279\u5b9a\u7248\u672c\naadt build v1.2.0        # \u7279\u5b9a git \u6807\u7b7e\naadt build dev           # \u5de5\u4f5c\u76ee\u5f55\uff08\u5305\u542b\u672a\u63d0\u4ea4\u66f4\u6539\uff09\naadt build current       # \u6700\u65b0\u63d0\u4ea4\naadt build release       # \u6700\u65b0\u6807\u7b7e\uff08\u9ed8\u8ba4\uff09\n\n# \u6307\u5b9a\u5206\u53d1\u7c7b\u578b\naadt build -d local      # \u672c\u5730\u5f00\u53d1\u7248\u672c\naadt build -d ankiweb    # AnkiWeb \u63d0\u4ea4\u7248\u672c\naadt build -d all        # \u540c\u65f6\u6784\u5efa\u4e24\u79cd\u7c7b\u578b\n\n# \u7ec4\u5408\u4f7f\u7528\naadt build v1.2.0 -d local\n```\n\n**\u5206\u53d1\u7c7b\u578b\u8bf4\u660e\uff1a**\n- `local`: \u9002\u7528\u4e8e\u672c\u5730\u5f00\u53d1\uff0c\u4fdd\u7559\u8c03\u8bd5\u4fe1\u606f\n- `ankiweb`: \u9002\u7528\u4e8e AnkiWeb \u63d0\u4ea4\uff0c\u4f18\u5316\u6587\u4ef6\u5927\u5c0f\n- `all`: \u540c\u65f6\u751f\u6210\u4e24\u79cd\u7248\u672c\n\n**\u529f\u80fd\uff1a**\n- \u6839\u636e `addon.json` \u914d\u7f6e\u751f\u6210 AnkiWeb \u6240\u9700\u7684 `manifest.json`\n- \u5305\u542b\u63d2\u4ef6\u5143\u6570\u636e\u3001\u4f9d\u8d56\u5173\u7cfb\u7b49\u4fe1\u606f\n\n### `manifest` - \u751f\u6210\u6e05\u5355\u6587\u4ef6\n```bash\n# \u751f\u6210 manifest.json\naadt manifest\n```\n\n### `clean` - \u6e05\u7406\u6784\u5efa\u6587\u4ef6\n```bash\n# \u6e05\u7406\u6240\u6709\u6784\u5efa\u4ea7\u7269\naadt clean\n```\n\n**\u529f\u80fd\uff1a**\n- \u5220\u9664 `dist/` \u76ee\u5f55\u53ca\u5176\u5185\u5bb9\n- \u6e05\u7406\u4e34\u65f6\u6587\u4ef6\u548c\u7f13\u5b58\n\n## \ud83d\ude80 CI/CD \u652f\u6301\n\n\u8fd9\u4e9b\u547d\u4ee4\u63d0\u4f9b\u66f4\u7cbe\u7ec6\u7684\u6784\u5efa\u63a7\u5236\uff0c\u9002\u7528\u4e8e\u81ea\u52a8\u5316\u6784\u5efa\u6d41\u6c34\u7ebf\uff1a\n\n### `create_dist` - \u51c6\u5907\u6e90\u4ee3\u7801\u6811\n```bash\naadt create_dist [version]\n```\n\n**\u529f\u80fd\uff1a**\n- \u51c6\u5907\u6e90\u4ee3\u7801\u6811\u5230 `dist/build` \u76ee\u5f55\n- \u5904\u7406\u7248\u672c\u63a7\u5236\u548c\u6587\u4ef6\u5f52\u6863\n- \u4e3a\u540e\u7eed\u6784\u5efa\u6b65\u9aa4\u505a\u51c6\u5907\n\n#### `build_dist` - \u6784\u5efa\u6e90\u4ee3\u7801\n```bash\naadt build_dist\n```\n\n**\u529f\u80fd\uff1a**\n- \u5904\u7406 `dist/build` \u4e2d\u7684\u6e90\u4ee3\u7801\n- \u7f16\u8bd1 UI \u6587\u4ef6\uff0c\u751f\u6210\u6e05\u5355\u6587\u4ef6\n- \u6267\u884c\u6240\u6709\u5fc5\u8981\u7684\u4ee3\u7801\u540e\u5904\u7406\n\n#### `package_dist` - \u6253\u5305\u5206\u53d1\n```bash\naadt package_dist\n```\n\n**\u529f\u80fd\uff1a**\n- \u5c06\u6784\u5efa\u597d\u7684\u6587\u4ef6\u6253\u5305\u6210 `.ankiaddon` \u683c\u5f0f\n- \u751f\u6210\u6700\u7ec8\u7684\u5206\u53d1\u5305\n\n## \ud83c\udfa8 UI \u5f00\u53d1\n\n### \u4f7f\u7528 Qt Designer\n\nAADT \u4e3a Qt Designer UI \u5f00\u53d1\u63d0\u4f9b\u65e0\u7f1d\u96c6\u6210\uff0c\u5177\u5907**\u667a\u80fd PyQt6 \u5230 aqt.qt \u8f6c\u6362**\u529f\u80fd\uff1a\n\n1. **\u8bbe\u8ba1UI**: \u5728 `ui/designer/` \u4e2d\u521b\u5efa `.ui` \u6587\u4ef6\n2. **\u6dfb\u52a0\u8d44\u6e90**: \u5c06\u56fe\u7247\u3001\u56fe\u6807\u653e\u5728 `ui/resources/` \u4e2d\n3. **\u5f15\u7528\u8d44\u6e90**: \u5728 Qt Designer \u4e2d\u5f15\u7528 `ui/resources/` \u4e2d\u7684\u6587\u4ef6\n4. **\u6784\u5efaUI**: \u8fd0\u884c `aadt ui` \u81ea\u52a8\u7f16\u8bd1\u5e76\u590d\u5236\u8d44\u6e90\n\n```bash\n# \u4f60\u7684\u9879\u76ee\u7ed3\u6784\nmy-addon/\n\u251c\u2500\u2500 ui/\n\u2502   \u251c\u2500\u2500 designer/\n\u2502   \u2502   \u2514\u2500\u2500 dialog.ui          # \u5f15\u7528 ../resources/icon.png\n\u2502   \u2514\u2500\u2500 resources/\n\u2502       \u2514\u2500\u2500 icon.png           # \u4f60\u7684\u8d44\u6e90\u6587\u4ef6\n\u2514\u2500\u2500 src/my_addon/\n\n# \u8fd0\u884c 'aadt ui' \u540e\nmy-addon/\n\u251c\u2500\u2500 src/my_addon/\n\u2502   \u251c\u2500\u2500 gui/forms/qt6/\n\u2502   \u2502   \u2514\u2500\u2500 dialog.py          # \u7f16\u8bd1\u540e\u7684UI\uff0c\u4f7f\u7528aqt.qt\u5bfc\u5165\n\u2502   \u2514\u2500\u2500 gui/resources/\n\u2502       \u251c\u2500\u2500 __init__.py        # \u81ea\u52a8\u751f\u6210\uff0c\u652f\u6301importlib.resources\n\u2502       \u2514\u2500\u2500 icon.png           # \u81ea\u52a8\u590d\u5236\u7684\u8d44\u6e90\n```\n\n### \ud83e\udde0 \u667a\u80fd PyQt6 \u5230 aqt.qt \u8f6c\u6362\n\n\u5728\u8f6c\u5316\u7684\u8fc7\u7a0b\u4e2d\uff0cAADT \u4f7f\u7528 pyuic6 \u5c06 ui \u6587\u4ef6\u8f93\u51fa\u8f6c\u6362\u4e3a Anki \u517c\u5bb9\u683c\u5f0f\uff0c\u5e76\u63d0\u4f9b\u7cbe\u786e\u7684\u7c7b\u578b\u6ce8\u89e3\uff1a\n\n**\u539f\u59cb\u8f6c\u5316 (pyuic6 \u8f93\u51fa):**\n```python\nfrom PyQt6 import QtCore, QtGui, QtWidgets\n\nclass Ui_Dialog(object):\n    def setupUi(self, Dialog):\n        Dialog.setObjectName(\"Dialog\")\n        self.verticalLayout = QtWidgets.QVBoxLayout(Dialog)\n        self.label = QtWidgets.QLabel(Dialog)\n        # ...\n```\n\n**\u4e13\u7528\u8f6c\u5316 (AADT \u667a\u80fd\u8f6c\u6362):**\n```python\nfrom aqt.qt import QDialog, QVBoxLayout, QLabel, QMetaObject\n\nclass Ui_Dialog(object):\n    def setupUi(self, Dialog: QDialog) -> None:\n        Dialog.setObjectName(\"Dialog\")\n        self.verticalLayout = QVBoxLayout(Dialog)\n        self.label = QLabel(Dialog)\n        # ...\n```\n\n### \ud83c\udfaf \u667a\u80fd\u7c7b\u578b\u63a8\u65ad\n\nAADT \u5206\u6790\u4f60\u7684 UI \u6587\u4ef6\uff0c\u57fa\u4e8e aqt.qt \u7684\u5b9e\u9645\u7c7b\u578b\u7cfb\u7edf\u63d0\u4f9b**\u7cbe\u786e\u7684\u7c7b\u578b\u6ce8\u89e3**\uff1a\n\n- **`Ui_Dialog`** \u2192 `QDialog` \u7c7b\u578b\u6ce8\u89e3\n- **`Ui_MainWindow`** \u2192 `QMainWindow` \u7c7b\u578b\u6ce8\u89e3  \n- **`Ui_CustomWidget`** \u2192 `QWidget` \u7c7b\u578b\u6ce8\u89e3\n- **`Ui_SettingsFrame`** \u2192 `QFrame` \u7c7b\u578b\u6ce8\u89e3\n\n### **\u4e3b\u8981\u4f18\u52bf\uff1a**\n- \u2705 **Anki \u517c\u5bb9\u5bfc\u5165**: \u4f7f\u7528 `from aqt.qt import ...` \u66ff\u4ee3 `from PyQt6 import ...`\n- \u2705 **\u667a\u80fd\u7c7b\u578b\u63a8\u65ad**: \u81ea\u52a8\u786e\u5b9a\u6b63\u786e\u7684 Qt \u63a7\u4ef6\u7c7b\u578b\n- \u2705 **mypy \u517c\u5bb9**: \u751f\u6210\u7684\u4ee3\u7801\u901a\u8fc7\u4e25\u683c\u7c7b\u578b\u68c0\u67e5\n- \u2705 **\u6700\u5c0f\u5316\u5bfc\u5165**: \u53ea\u5bfc\u5165 UI \u6587\u4ef6\u4e2d\u5b9e\u9645\u4f7f\u7528\u7684\u7c7b\n- \u2705 **\u81ea\u52a8\u8d44\u6e90\u590d\u5236**: \u8d44\u6e90\u6587\u4ef6\u81ea\u52a8\u590d\u5236\u5230\u6700\u7ec8\u5305\u4e2d\n- \u2705 **\u6e05\u6d01\u5f15\u7528**: \u65e0\u9700\u590d\u6742\u7684QRC\u7f16\u8bd1\n- \u2705 **\u76f4\u63a5\u6587\u4ef6\u8def\u5f84**: \u5728Python\u4ee3\u7801\u4e2d\u4f7f\u7528\u6807\u51c6\u6587\u4ef6\u8def\u5f84\n- \u2705 **\u5f00\u53d1\u53cb\u597d**: \u8d44\u6e90\u7acb\u5373\u53ef\u7528\u4e8e\u6d4b\u8bd5\n\n## \u4ee3\u7801\u8d28\u91cf\n\nAADT \u5305\u542b\u73b0\u4ee3\u5f00\u53d1\u5de5\u5177\uff0c\u5f3a\u70c8\u5efa\u8bae\u5728\u5f00\u53d1\u8fc7\u7a0b\u4e2d\u4f7f\u7528\uff0c\u63d0\u5347\u4ee3\u7801\u8d28\u91cf\u548c\u7c7b\u578b\u5b89\u5168\uff0c\u5e76\u63d0\u4f9b\u5b8c\u6574\u7684\u7c7b\u578b\u6ce8\u89e3\uff1a\n\n```bash\n# \u4f7f\u7528ruff\u8fdb\u884c\u4ee3\u7801\u68c0\u67e5\nuv run ruff check src/aadt/\nuv run ruff format src/aadt/\n\n# \u4f7f\u7528ty\u8fdb\u884c\u7c7b\u578b\u68c0\u67e5  \nuv run ty check src/aadt/\n\n# \u8fd0\u884c\u6240\u6709\u68c0\u67e5\nuv run ruff check src/aadt/ && uv run ty check src/aadt/\n```\n\n## \u5355\u5143\u6d4b\u8bd5\n\n```bash\n# \u8fd0\u884c\u6d4b\u8bd5\npytest\n\n# \u5305\u542b\u8986\u76d6\u7387\npytest --cov=aadt\n```\n\n## \ud83d\ude80 Git \u96c6\u6210\n\nAADT \u8bbe\u8ba1\u4e3a\u5728 Git \u4ed3\u5e93\u4e2d\u5de5\u4f5c\u6700\u4f73\uff0c\u4f46**\u4e0d\u9700\u8981 Git**\uff1a\n\n### Git \u53ef\u7528\u65f6\uff08\u63a8\u8350\uff09\n- **\u7248\u672c\u68c0\u6d4b**: \u4f7f\u7528 Git \u6807\u7b7e\u548c\u63d0\u4ea4\u8fdb\u884c\u7248\u672c\u63a7\u5236\n- **\u6e90\u7801\u5f52\u6863**: \u4f7f\u7528 `git archive` \u8fdb\u884c\u5e72\u51c0\u7684\u6e90\u7801\u63d0\u53d6\n- **\u4fee\u6539\u65f6\u95f4**: \u4f7f\u7528 Git \u63d0\u4ea4\u65f6\u95f4\u6233\n\n### \u975eGit\u73af\u5883\uff08\u964d\u7ea7\u6a21\u5f0f\uff09\n- **\u7248\u672c\u68c0\u6d4b**: \u4ece `pyproject.toml`\u3001`VERSION` \u6587\u4ef6\u8bfb\u53d6\uff0c\u6216\u751f\u6210\u57fa\u4e8e\u65f6\u95f4\u6233\u7684\u7248\u672c\n- **\u6e90\u7801\u5f52\u6863**: \u590d\u5236\u5f53\u524d\u76ee\u5f55\u5e76\u667a\u80fd\u6392\u9664\uff08`.git`\u3001`__pycache__` \u7b49\uff09\n- **\u4fee\u6539\u65f6\u95f4**: \u4f7f\u7528\u5f53\u524d\u65f6\u95f4\u6233\n\n### \u4f7f\u7528\u793a\u4f8b\n\n```bash\n# \u81ea\u52a8\u68c0\u6d4b\u73af\u5883\u5e76\u6784\u5efa\naadt build\n\n# \u5728 Git \u4ed3\u5e93\u4e2d\uff08\u81ea\u52a8\u68c0\u6d4b\uff09\naadt build -d local\n\n# \u5728\u975e Git \u76ee\u5f55\u4e2d\uff08\u81ea\u52a8\u964d\u7ea7\uff09\naadt build -d local  # \u4ecd\u7136\u53ef\u4ee5\u5de5\u4f5c\uff01\n\n# \u663e\u5f0f\u7248\u672c\u6307\u5b9a\uff08\u4efb\u4f55\u5730\u65b9\u90fd\u53ef\u4ee5\u5de5\u4f5c\uff09\naadt build v1.2.0 -d local\n```\n\n\u5de5\u5177\u4f1a\u81ea\u52a8\u68c0\u6d4b\u4f60\u7684\u73af\u5883\u5e76\u9009\u62e9\u9002\u5f53\u7684\u65b9\u6cd5\u3002\n\n## \ud83d\udcda \u793a\u4f8b\n\n\u67e5\u770b `tests/` \u76ee\u5f55\u83b7\u53d6\u793a\u4f8b\u914d\u7f6e\u548c\u4f7f\u7528\u6a21\u5f0f\u3002\n\n## \ud83d\udcc4 \u534f\u8bae\n\n\u672c\u9879\u76ee\u57fa\u4e8eGNU AGPLv3\u534f\u8bae\u3002\u8be6\u89c1[LICENSE](LICENSE)\u6587\u4ef6\u3002\n\n---\n\n**\u4e3aAnki\u793e\u533a\u7528\u2764\ufe0f\u6784\u5efa**\n\n> \u672c\u9879\u76ee\u53d7 [aab](https://github.com/glutanimate/anki-addon-builder) \u9879\u76ee\u542f\u53d1\uff0c\u4e13\u6ce8\u4e8e\u4e3a\u5373\u5c06\u6b63\u5f0f\u4e0a\u7ebf\u7684\u65b0\u7248  Anki \u63d2\u4ef6\u5f00\u53d1\u8005\u63d0\u4f9b\u6700\u4f73\u7684\u5f00\u53d1\u4f53\u9a8c\u3002\n",
    "bugtrack_url": null,
    "license": "AGPL-3.0-or-later",
    "summary": "Anki Addon Dev ToolKit",
    "version": "1.6.1",
    "project_urls": {
        "Homepage": "https://github.com/libukai/Anki-Addon-Dev-ToolKit",
        "Repository": "https://github.com/libukai/Anki-Addon-Dev-ToolKit"
    },
    "split_keywords": [
        "anki",
        " development",
        " build-tools"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "48b1da116131fb6a3e76cae354d25c4a219cc09418c201a9df21187e03847fd2",
                "md5": "0bfc54d1198ab08d2d43b0835a7a22e7",
                "sha256": "c502584477ffa4b8266304e4e42efed6d2568cbfe43606d0c1fcf8e660de5b19"
            },
            "downloads": -1,
            "filename": "aadt-1.6.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "0bfc54d1198ab08d2d43b0835a7a22e7",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.13",
            "size": 5647115,
            "upload_time": "2025-07-23T12:53:01",
            "upload_time_iso_8601": "2025-07-23T12:53:01.225528Z",
            "url": "https://files.pythonhosted.org/packages/48/b1/da116131fb6a3e76cae354d25c4a219cc09418c201a9df21187e03847fd2/aadt-1.6.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "25e9146aeffd96777729462f2957a4563429343c89ad3fbb88ef77727ec64c76",
                "md5": "b864fbab815f8274409217b2fde43adf",
                "sha256": "eaec68f73016ec0eb986ffb20ebe278b267d343da23f2c5be59095e500b41633"
            },
            "downloads": -1,
            "filename": "aadt-1.6.1.tar.gz",
            "has_sig": false,
            "md5_digest": "b864fbab815f8274409217b2fde43adf",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.13",
            "size": 4286999,
            "upload_time": "2025-07-23T12:53:04",
            "upload_time_iso_8601": "2025-07-23T12:53:04.300031Z",
            "url": "https://files.pythonhosted.org/packages/25/e9/146aeffd96777729462f2957a4563429343c89ad3fbb88ef77727ec64c76/aadt-1.6.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-07-23 12:53:04",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "libukai",
    "github_project": "Anki-Addon-Dev-ToolKit",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "aadt"
}
        
Elapsed time: 0.52591s