diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f38ee6..9550d8f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,13 +2,30 @@ QPyPack 项目的所有重要变更都将记录在此文件中。 -本日志格式基于 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.0.0/) 规范, -且本项目严格遵循 [语义化版本 (Semantic Versioning)](https://semver.org/lang/zh-CN/) 规范。 - [English Version](./CHANGELOG_EN.md) | **中文** --- +## [2.8.0] - 2026-08-31 + +### 新增 +- 支持直接拖入项目文件夹,自动识别工作区路径并关联根目录 `requirements.txt`。 +- 增加多入口脚本匹配机制,并在检测到多个候选入口文件时提供选择对话框供用户指定。 +- 增加跨层级模块引用检测,在单独载入脚本引用上级目录模块时输出工作区配置与项目导入建议。 + +### 变更 +- 扩展 AST 依赖分析范围至整个项目工作区,提升对子模块内部依赖的识别能力。 +- 引入本地模块与附加资源白名单机制,避免将项目内部模块识别为 PyPI 依赖并执行 pip 安装。 +- 扩充默认包名映射表与 Auto-Hooks 规则库,为 `pycryptodome`、`nacl`、`soundfile`、`pynput`、`keyring`、`pydantic_core` 等库补充自动收录参数。 +- 调整构建搜索路径配置,自动为 PyInstaller 传递 `--paths`(包含工作区与 `src` 目录)并为 Nuitka 设置 `PYTHONPATH`。 +- 调整 `requirements.txt` 解析逻辑,支持处理行内注释(`#`)及环境标记(`;`)等语法。 + +### 修复 +- 修复控制台暂停代码插入位置位于 `from __future__` 语句之前导致的 `SyntaxError` 语法错误。 +- 修复 `os.walk` 迭代变量名冲突覆盖全局翻译函数引发的 `TypeError: 'list' object is not callable` 异常。 + +--- + ### [2.7.14] - 2026-08-26 #### 修复 @@ -451,7 +468,12 @@ QPyPack 项目的所有重要变更都将记录在此文件中。 --- +本项目向以下规范靠拢。 +[Keep a Changelog](https://keepachangelog.com/zh-CN/1.0.0/) 规范, +[语义化版本 (Semantic Versioning)](https://semver.org/lang/zh-CN/) 规范。 + ## 📄 License +--- Copyright (C) 2026 QwejayHuang. Licensed under the [GNU General Public License v3.0](LICENSE). diff --git a/CHANGELOG_EN.md b/CHANGELOG_EN.md index 3a6a0d9..c33b6be 100644 --- a/CHANGELOG_EN.md +++ b/CHANGELOG_EN.md @@ -2,13 +2,30 @@ All notable changes to the **QPyPack** project will be documented in this file. -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - **English** | [中文版](./CHANGELOG.md) --- +## [2.8.0] - 2026-08-31 + +### Added +- Direct project directory drag-and-drop support, automatically recognizing workspace paths and associating the root `requirements.txt`. +- Multi-entry script matching mechanism with an entry selection dialog when multiple candidate entry files are detected. +- Cross-hierarchy module reference detection, providing workspace configuration and project import suggestions in the log when a standalone script references parent modules. + +### Changed +- Expanded the AST dependency analysis scope across the entire project workspace, improving detection of internal submodules and dynamic dependencies. +- Introduced a local module and additional resource whitelist mechanism to prevent project-internal packages from being misidentified as PyPI dependencies during pip install. +- Expanded the default package mapping table and Auto-Hooks rules to add automatic collection parameters for `pycryptodome`, `nacl`, `soundfile`, `pynput`, `keyring`, `pydantic_core`, and other libraries. +- Updated build search path configurations to automatically supply `--paths` (including workspace and `src` directories) to PyInstaller and configure `PYTHONPATH` for Nuitka. +- Refined `requirements.txt` parsing logic to support inline comments (`#`) and environment markers (`;`). + +### Fixed +- Fixed a `SyntaxError` caused by console pause code injection occurring prior to `from __future__` statements. +- Fixed a `TypeError: 'list' object is not callable` crash caused by an `os.walk` iteration variable shadowing the global translation function. + +--- + ### [2.7.14] - 2026-08-26 #### Fixed @@ -447,6 +464,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * **Custom PIP Mirror Support**: Added PIP mirror configuration defaulting to Tsinghua University mirrors, with immediate UI application and `QSettings` persistence. * **Unified Build Logic**: Virtual environment initialization and dependency resolution now strictly adhere to user-configured PIP mirrors. +--- +Strictly following the **[Keep a Changelog 1.0.0](https://keepachangelog.com/en/1.0.0/)** and **[Semantic Versioning 2.0.0](https://semver.org/)** specifications. --- ## 📄 License diff --git a/QUICKSTART.md b/QUICKSTART.md index 2b1ed36..7c93f1b 100644 --- a/QUICKSTART.md +++ b/QUICKSTART.md @@ -1,90 +1,310 @@ -# ⚡ QPyPack 快速入门指南 (Quick Start Guide) +# ⚡ QPyPack 快速入门指南 | Quick Start Guide -欢迎使用 **QPyPack**!本指南将带你在 3 分钟内掌握 QPyPack 的核心功能与打包流程,轻松将 Python 脚本转换为可独立运行的原生可执行程序 (`.exe` / macOS App / Linux 二进制)。 +
--- -## 📥 第一步:安装与启动 QPyPack +## 🇨🇳 简体中文 -你可以根据使用习惯选择以下任意一种方式启动 QPyPack: +欢迎使用 **QPyPack**!本指南将带你在 3 分钟内掌握 QPyPack 的核心功能与打包流程,轻松将 Python 脚本或复杂工程项目转换为独立运行的原生可执行程序 (`.exe` / macOS `.app` / Linux 二进制)。 -### 方式 A:通过 `pip` 安装(推荐开发者使用) +--- + +### 📥 第一步:安装与启动 + +你可以根据使用习惯选择以下任意一种方式获取并运行 QPyPack: + +#### 方式 A:通过包管理器安装(推荐开发者) 在已配置 Python (>= 3.8) 的终端中执行: ```bash -# 安装 QPyPack +# 1. 在线安装 pip install qpypack -# 在命令行直接启动 GUI 界面 +# 启动 GUI 界面 qpypack ``` -### 方式 B:使用预编译独立免安装版(适合无 Python 环境用户) +*若使用现代包管理器(免全局安装,隔离运行):* +```bash +# 使用 pipx 隔离运行 +pipx run qpypack -前往 [GitHub Releases](https://github.com/Qwejay/QPyPack/releases) 下载对应系统的可执行文件: -* **Windows**: 下载 `QPyPack.exe` 双击即可运行。 -* **macOS / Linux**: 下载对应的预编译应用程序或可执行文件。 +# 或使用 uv 极速启动 +uvx qpypack +``` + +*离线安装(使用 Releases 提供的 Wheel 包):* +```bash +pip install qpypack-2.8.0-py3-none-any.whl +``` + +#### 方式 B:下载 GitHub Releases 预编译包(适合无 Python 环境用户) + +前往 [GitHub Releases 页面](https://github.com/Qwejay/QPyPack/releases) 直接下载对应系统的预编译发布包(以下以QPyPack-2.8.0为例): + +| 操作系统 / 架构 | 发布包文件名 | 版本说明 | +| :--- | :--- | :--- | +| **Windows (x64)** | `QPyPack-2.8.0-windows-x64-Standalone.zip` | **单文件独立版**(解压即为一个干净的单个 `.exe` 文件) | +| **Windows (x64)** | `QPyPack-2.8.0-windows-x64-Portable.zip` | **便携目录版**(包含完整依赖目录,秒级启动,无临时解压延迟) | +| **Linux (x64)** | `QPyPack-2.8.0-linux-x64-Standalone.tar.gz` | **单文件独立版**(解压即用单可执行文件) | +| **Linux (x64)** | `QPyPack-2.8.0-linux-x64-Portable.tar.gz` | **便携目录版**(包含完整运行库目录) | +| **macOS (Apple Silicon)** | `QPyPack-2.8.0-macos-arm64.dmg` | **原生 DMG 镜像**(原生适配 Apple Silicon M1/M2/M3/M4 系列芯片) | +| **全平台 Python** | `qpypack-2.8.0-py3-none-any.whl` | **离线 Wheel 包**(适用于内网或离线环境 `pip install`) | --- -## 🎯 第二步:标准打包 5 步曲 - -启动 QPyPack 后,整体打包过程仅需简单点击几下: +### 🎯 第二步:标准打包 5 步流程 ``` - [1. 拖入源码] ➔ [2. 选择引擎与模式] ➔ [3. 依赖与环境] ➔ [4. 点击构建] ➔ [5. 获取产物] + [1. 载入文件/工程] ➔ [2. 引擎与模式] ➔ [3. 附加数据文件] ➔ [4. 依赖与环境] ➔ [5. 构建与产物] ``` -### 1. 拖入 Python 源码 -* 将你的主入口文件(如 `main.py` 或 `app.pyw`)**直接拖拽**到主界面的虚线拖拽区域内。 -* 软件将自动解析程序名称、自动比对脚本图标,并初始化工作空间。 +#### 1. 载入脚本文件或项目工程文件夹 +* **单脚本打包**:将主入口脚本(如 `main.py` 或 `app.pyw`)**直接拖入**主界面的虚线区域。 +* **多层级复杂工程打包**:直接将**整个项目总文件夹**拖入主界面,QPyPack 会自动锁定工作区根目录、识别根目录 `requirements.txt`,并自动匹配主入口脚本(若有多个候选入口会弹出点选框)。 -### 2. 选择打包引擎与模式 -切换到 **「构建设置」** 面板: +#### 2. 选择构建引擎与模式 +进入 **「构建设置」** 面板: * **构建引擎 (Engine)**: - * **PyInstaller**:打包速度极快,零配置,适合快速交付与常规应用。 - * **Nuitka**:将 Python 编译为 C/C++ 二进制,体积更小、运行更快且具有极强的抗反编译保护(无需手动配置 C 编译器,QPyPack 会自动托管)。 + * **PyInstaller**:构建速度快(通常 10~60 秒),零外部 C 编译器依赖,生态兼容性好。 + * **Nuitka**:将 Python 直接编译为 C/C++ 原生二进制,体积更小、启动更快,具备极强的代码防反编译保护(未检测到本地 C 编译器时,QPyPack 会自动下载托管 MinGW-w64)。 * **打包模式 (Packaging Mode)**: - * **单文件 (`--onefile`)**:生成单个 `.exe` / 可执行文件,干净便携。 - * **精简模式 (Lite Mode)**:动态排除开发/测试等冗余依赖,有效缩减产物体积(若失败可随时切回兼容模式)。 + * **单文件 (`--onefile`)**:生成单个独立的 `.exe` / 可执行文件,便携干净。 + * **文件夹 (`--onedir`)**:生成包含主程序与 `_internal` 依赖文件夹的目录,适合包含大量静态资源的复杂应用。 +* **精简模式 (Lite Mode)**:自动剔除未引用的重型模块并开启 LTO 链接优化,大幅压缩体积(若特殊动态导入报错,切回「兼容模式」即可)。 -### 3. 配置 Python 环境与依赖 -* **Python 解释器**:软件会自动检测系统默认 Python。若本地未安装 Python,可点击「查看 Python」一键自动下载并配置环境。 -* **虚拟环境 (推荐勾选)**:勾选「使用虚拟环境」可隔离本地污染;勾选「保留虚拟环境」可在多次重新打包时复用 `.qpypack_venv`,极大缩短后续构建时间。 -* **依赖扫描**:勾选「分析依赖 (原生 AST)」,QPyPack 会静态扫描源码中的隐式 `import`,彻底解决运行时 `ModuleNotFoundError`。 +#### 3. 配置附加资源(静态文件 / 资产) +如果你的程序需要读取额外的外部数据(图片、网页静态资源、配置文件、解密密钥等): +* 切换到 **【构建设置】 $\rightarrow$ 【附加资源】**; +* 点击「添加文件」或「添加目录」,也可直接把资源文件夹(如 `assets/`、`static/`)拖入列表; +* 支持双击修改打包后的相对存放路径。 -### 4. 开始构建 -* 点击底部的 **「开始构建」** 按钮。 -* 可以在界面下方的 **「执行日誌」** 查看实时编译状态,支持切换「精简模式/详细模式」。 +#### 4. 依赖管理与环境隔离 +* **Python 解释器**:自动检测系统 Python;若未安装,点击「查看 Python」可一键自动下载安装。 +* **虚拟环境沙盒 (推荐)**:勾选「使用虚拟环境」可隔离环境污染;勾选「保留虚拟环境」可在重复构建时复用 `.qpypack_venv` 缓存,大幅提速后续打包。 +* **智能依赖分析 (AST)**:勾选「分析依赖 (原生 AST)」,系统会自动穿透扫描源码中的隐式依赖,并自动处理包名映射(如 `Crypto` $\to$ `pycryptodome`、`cv2` $\to$ `opencv-python`),同时智能排除本地工程模块,防止 pip 误装报错。 -### 5. 获取打包产物 -* 构建成功后,点击 **「打开目录」** 即可直接跳转到生成的应用程序目录。 +#### 5. 开始构建与获取产物 +* 点击主界面底部的 **「开始构建」** 按钮; +* 展开下方的 **「执行日志」** 可实时查看编译输出; +* 构建成功后,点击 **「打开目录」** 即可直接定位到生成的成品程序。 --- -## 💡 典型应用场景配置推荐 +### 💡 典型应用场景配置推荐 -| 场景需求 | 推荐引擎 | 打包模式 | 关键设置 | +| 场景需求 | 推荐引擎 | 推荐形态 | 关键设置与建议 | | :--- | :--- | :--- | :--- | -| **日常小工具 / 快速脚本** | PyInstaller | 单文件 (`--onefile`) + 精简模式 | 自动提取图标 | -| **商业软件 / 防反编译源码** | Nuitka | 单文件 (`--onefile`) + 兼容模式 | 使用虚拟环境 + 保留虚拟环境 | -| **大型 GUI 框架 (PySide/PyQt)** | PyInstaller / Nuitka | 文件夹 (`--onedir`) | 勾选「分析依赖 (原生 AST)」 | -| **Playwright / 爬虫自动化** | PyInstaller | 单文件 (`--onefile`) | 自动拦截 Playwright 浏览器依赖 | +| **日常小工具 / 自动化脚本** | PyInstaller | 单文件 (`--onefile`) | 自动提取图标 + 勾选「精简模式」 | +| **Web 服务 (FastAPI / Flask)** | PyInstaller / Nuitka | 文件夹 (`--onedir`) | 拖入项目总文件夹 + 附加资源添加 `static/`、`templates/` | +| **商业软件 / 核心算法保护** | Nuitka | 单文件 (`--onefile`) | 勾选「使用虚拟环境」+ 开启数字签名 | +| **大型桌面 GUI (PySide6 / PyQt)** | PyInstaller / Nuitka | 文件夹 (`--onedir`) | 勾选「分析依赖 (原生 AST)」+ 开启「精简模式」剔除未使用子模块 | +| **加解密 / 复杂底层 C 扩展** | PyInstaller | 文件夹 (`--onedir`) | 保持「兼容模式」确保 C 扩展 `.pyd` 完整收录 | --- -## ❓ 常见问题排查 (FAQ) +### 📋 开发者最佳实践:资源文件路径寻址规范 -### Q1: 打包完成后运行报错 `ModuleNotFoundError`? -* **解决方法**:前往【构建设置】->【依赖管理】,勾选 **「分析依赖 (原生 AST)」** 或 **「扫描整个文件夹」**;也可在「隐式导入 (hidden-imports)」中手动填入缺失的包名(如 `pandas, PIL`)。 +在单文件模式(`--onefile`)下,打包后的数据文件会在运行时临时解压至特定沙盒目录。请在源码中统一采用以下标准函数获取资源绝对路径,避免路径报错: -### Q2: 精简模式 (Lite Mode) 构建失败怎么办? -* **解决方法**:精简模式会剔除不常用的动态依赖。如果构建失败,请在【构建设置】中将打包模式切回 **「兼容模式 (Compatibility Mode)」** 重新构建即可。 +```python +import os +import sys +from pathlib import Path -### Q3: 使用 Nuitka 引擎提示缺少 C 编译器? -* **解决方法**:不用担心!QPyPack 内置编译器智能托管,未检测到 MSVC 或 GCC 时会自动为你下载并配置 MinGW-w64 编译器工具链,全程无需手动干预。 +def get_asset_path(relative_path: str) -> Path: + """获取程序运行时资源的绝对路径(兼容本地开发、PyInstaller 与 Nuitka)""" + if hasattr(sys, "_MEIPASS"): + # PyInstaller 单文件临时解压目录 + base_path = Path(sys._MEIPASS) + elif "__compiled__" in globals(): + # Nuitka 二进制执行目录 + base_path = Path(sys.argv[0]).resolve().parent + else: + # 本地开发调试目录 + base_path = Path(__file__).resolve().parent + return base_path / relative_path + +# 使用示例: +# logo_path = get_asset_path("assets/logo.png") +# config_path = get_asset_path("config/settings.json") +``` --- -📖 **需要更详细的配置与高级优化说明?** 请参阅完整版 [README.md](README.md)。 +### ❓ 常见问题排查 (FAQ) + +#### Q1: 打包后运行报错 `ModuleNotFoundError: No module named 'xxx'`? +* **原因**:程序中使用了动态反射导入(如 `importlib`)或某些包的子模块未被静态检测到。 +* **解决办法**:在【构建设置】 $\rightarrow$ 【依赖管理】中的「隐式导入 (hidden-imports)」填入缺失的包名(逗号分隔);或在【附加资源】中将该本地源码包目录添加进去。 + +#### Q2: 静态资源(图片/配置文件)在单文件打包后读不到? +* **原因**:源码中使用了 `open("assets/config.json")` 相对当前工作目录寻址,而单文件解压到了临时路径。 +* **解决办法**:参考上方 [资源文件路径寻址规范](#-开发者最佳实践资源文件路径寻址规范),使用 `sys._MEIPASS` 兼容代码。对于大型 Web/数据项目,优先推荐使用 **文件夹模式 (`--onedir`)**。 + +#### Q3: Windows 下运行打包出的程序,瞬间弹出几百个窗口死机? +* **原因**:项目中使用了 `multiprocessing` 多进程,但在 Windows 上未加保护。 +* **解决办法**:在主入口文件的 `if __name__ == '__main__':` 块内第一行调用 `multiprocessing.freeze_support()`。 + +#### Q4: Nuitka 提示缺少 C/C++ 编译器? +* **解决办法**:完全无需手动配置环境变量!QPyPack 内置编译器自动托管机制。未检测到 MSVC 或 GCC 时,Nuitka 会自动下载并配置 MinGW-w64 编译器。 + +--- + +## 🇬🇧 English + +Welcome to **QPyPack**! This guide helps you master the core features and packaging workflow of QPyPack in 3 minutes, transforming Python scripts and complex projects into standalone native executables (`.exe` / macOS `.app` / Linux binaries). + +--- + +### 📥 Step 1: Installation & Launch + +Choose any of the following methods to obtain and launch QPyPack: + +#### Method A: Install via Package Manager (Recommended for Developers) + +Run in a terminal with Python (>= 3.8): + +```bash +# 1. Install via pip +pip install qpypack + +# Launch the GUI directly from command line +qpypack +``` + +*Run in an isolated environment via modern package managers (Zero global install):* +```bash +# Using pipx +pipx run qpypack + +# Or using uv for ultra-fast startup +uvx qpypack +``` + +*Offline installation (using the Release Wheel):* +```bash +pip install qpypack-2.8.0-py3-none-any.whl +``` + +#### Method B: Standalone Pre-built Releases (For Users without Python) + +Download the release asset for your platform from the [GitHub Releases page](https://github.com/Qwejay/QPyPack/releases): + +| OS / Architecture | Release Asset | Description | +| :--- | :--- | :--- | +| **Windows (x64)** | `QPyPack-2.8.0-windows-x64-Standalone.zip` | **Standalone Single-File** (Extracts to a single standalone `.exe`) | +| **Windows (x64)** | `QPyPack-2.8.0-windows-x64-Portable.zip` | **Portable Directory** (Full runtime directory, fast launch, zero extraction overhead) | +| **Linux (x64)** | `QPyPack-2.8.0-linux-x64-Standalone.tar.gz` | **Standalone Single-File** (Single executable binary) | +| **Linux (x64)** | `QPyPack-2.8.0-linux-x64-Portable.tar.gz` | **Portable Directory** (Extracted folder with full runtime libraries) | +| **macOS (Apple Silicon)** | `QPyPack-2.8.0-macos-arm64.dmg` | **Native DMG Image** (Native installer for Apple Silicon M1/M2/M3/M4 Macs) | +| **Universal Python** | `qpypack-2.8.0-py3-none-any.whl` | **Offline Wheel** (For offline environments via `pip install`) | + +--- + +### 🎯 Step 2: Standard 5-Step Packaging Workflow + +``` + [1. Load Script/Project] ➔ [2. Engine & Mode] ➔ [3. Data Files] ➔ [4. Dependencies] ➔ [5. Build & Output] +``` + +#### 1. Load Python Script or Project Directory +* **Single Script**: Drag and drop your main entry file (e.g., `main.py` or `app.pyw`) **directly into the drop zone**. +* **Multi-directory Projects**: Drag and drop the **entire project root folder** into the drop zone. QPyPack will automatically lock the workspace root, link the root `requirements.txt`, and match the entry point (prompting an entry selection dialog if multiple candidates exist). + +#### 2. Choose Packaging Engine & Mode +Navigate to the **"Build Settings"** panel: +* **Build Engine**: + * **PyInstaller**: Fast compilation (typically 10–60 seconds), zero compiler dependencies, and extensive ecosystem compatibility. + * **Nuitka**: Compiles Python directly into native C/C++ binaries, offering smaller output size, faster startup, and deep anti-decompilation protection (MinGW-w64 toolchain is automatically provisioned if no C compiler is detected). +* **Packaging Mode**: + * **Single-File (`--onefile`)**: Bundles everything into a single standalone executable file. + * **Directory Mode (`--onedir`)**: Generates an application folder containing the executable and `_internal` dependency tree, ideal for media/web apps with heavy assets. +* **Lite Mode**: Automatically excludes redundant testing/development modules and enables Link-Time Optimization (`--lto=yes`) to reduce binary footprint. + +#### 3. Configure Additional Resources (Static Assets) +If your application requires external data files (images, web templates, configs, encryption keys, etc.): +* Switch to **"Build Settings" $\rightarrow$ "Resources"**; +* Click "Add File" or "Add Dir", or drag resource directories (e.g., `assets/`, `static/`) directly into the list; +* Double-click any item to customize its relative bundle target path. + +#### 4. Dependency Management & Environment Isolation +* **Python Interpreter**: Automatically detects system Python. Click "View Python" to download and configure one if none is found. +* **Virtual Environment Sandbox (Recommended)**: Check "Use Virtual Environment" to prevent global package pollution. Check "Keep Local Venv" to reuse `.qpypack_venv` cache across builds. +* **AST Dependency Analysis**: Check "Analyze Dependencies (AST)". QPyPack recursively parses Abstract Syntax Trees to detect hidden imports, applies package name mappings (e.g., `Crypto` $\to$ `pycryptodome`, `cv2` $\to$ `opencv-python`), and isolates local modules from triggering redundant pip downloads. + +#### 5. Build and Obtain Binaries +* Click the **"Start Build"** button at the bottom; +* Expand the **"Execution Log"** to inspect real-time compiler outputs (switchable between Concise and Detailed modes); +* Upon completion, click **"Open Directory"** to navigate directly to your generated executable. + +--- + +### 💡 Recommended Configurations by Project Type + +| Scenario | Recommended Engine | Packaging Mode | Key Settings & Tips | +| :--- | :--- | :--- | :--- | +| **CLI Tools / Quick Scripts** | PyInstaller | Single-File (`--onefile`) | Auto Extract Icon + Enable Lite Mode | +| **Web Services (FastAPI / Flask)** | PyInstaller / Nuitka | Directory (`--onedir`) | Drag project root folder + Add `static/` & `templates/` to Resources | +| **Commercial Software / IP Protection** | Nuitka | Single-File (`--onefile`) | Use Virtual Environment + Enable Smart Code Signing | +| **Desktop GUI (PySide6 / PyQt)** | PyInstaller / Nuitka | Directory (`--onedir`) | Enable AST Analysis + Lite Mode to prune unused submodules | +| **C-Extensions / Cryptography** | PyInstaller | Directory (`--onedir`) | Use Compatibility Mode to ensure all binary `.pyd` files are retained | + +--- + +### 📋 Developer Best Practices: Runtime Asset Path Resolution + +In Single-File mode (`--onefile`), bundled data files are extracted to a temporary sandbox directory at runtime. Use the following standard helper function to resolve asset paths across development, PyInstaller, and Nuitka: + +```python +import os +import sys +from pathlib import Path + +def get_asset_path(relative_path: str) -> Path: + """Resolve absolute asset path across Dev, PyInstaller, and Nuitka.""" + if hasattr(sys, "_MEIPASS"): + # PyInstaller temporary extraction directory + base_path = Path(sys._MEIPASS) + elif "__compiled__" in globals(): + # Nuitka native binary directory + base_path = Path(sys.argv[0]).resolve().parent + else: + # Local development directory + base_path = Path(__file__).resolve().parent + return base_path / relative_path + +# Usage Example: +# logo_path = get_asset_path("assets/logo.png") +# config_path = get_asset_path("config/settings.json") +``` + +--- + +### ❓ Troubleshooting & FAQ + +#### Q1: Runtime error `ModuleNotFoundError: No module named 'xxx'` after building? +* **Cause**: Dynamic reflection imports (e.g., `importlib`) or submodules were missed during static analysis. +* **Solution**: In "Build Settings" $\rightarrow$ "Dependencies", add the missing package names to "Hidden Imports", or add the local package directory to "Additional Resources". + +#### Q2: Static asset files (images/configs) cannot be found in `--onefile` mode? +* **Cause**: The code uses relative paths like `open("assets/config.json")`, which evaluates relative to `os.getcwd()` rather than the extracted bundle directory. +* **Solution**: Follow the [Runtime Asset Path Resolution](#-developer-best-practices-runtime-asset-path-resolution) pattern using `sys._MEIPASS`. For complex web/data apps, prefer **Directory Mode (`--onedir`)**. + +#### Q3: Windows executable spawns hundreds of subprocess windows until crashing? +* **Cause**: The application uses `multiprocessing` without freeze protection on Windows. +* **Solution**: Call `multiprocessing.freeze_support()` as the very first line inside `if __name__ == '__main__':` in your entry script. + +#### Q4: Nuitka reports missing C/C++ compiler? +* **Solution**: No manual environment variable setup is required! QPyPack features automated compiler provisioning. If MSVC or GCC is absent, Nuitka will automatically download and manage a compatible MinGW-w64 toolchain. + +--- + +
+ 📖 Need more advanced optimizations and configuration details?
+ Please consult the comprehensive README.md or visit our GitHub Repository.
+
- Ein plattformübergreifendes GUI-Tool zur Paketierung von Python-Anwendungen basierend auf PyInstaller & Nuitka -
- -
+
-
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+ Modernes, einsatzbereites plattformübergreifendes GUI-Tool zur Paketierung von Python-Anwendungen
+ Angetrieben von PyInstaller und Nuitka, mit visueller Konfiguration, statischer Abhängigkeitsanalyse und automatisiertem Build-Workflow.
+
-
-
+
+
+
+
+
+
+
Copyright (C) 2026 QwejayHuang.
diff --git a/docs/readme/README_ES.md b/docs/readme/README_ES.md index 6915059..30c2070 100644 --- a/docs/readme/README_ES.md +++ b/docs/readme/README_ES.md @@ -14,70 +14,194 @@- Herramienta GUI multiplataforma para empaquetar aplicaciones Python basada en PyInstaller y Nuitka -
- -
+
-
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+ Herramienta GUI moderna y lista para usar para empaquetar aplicaciones Python multiplataforma
+ Impulsada por los motores PyInstaller y Nuitka, con configuración visual, análisis estático de dependencias y flujo de compilación automatizado.
+
-
-
+
+
+
+
+
+
+
Copyright (C) 2026 QwejayHuang.
diff --git a/docs/readme/README_FR.md b/docs/readme/README_FR.md index 9a11990..ea307d2 100644 --- a/docs/readme/README_FR.md +++ b/docs/readme/README_FR.md @@ -14,49 +14,121 @@- Un outil GUI multiplateforme pour empaqueter des applications Python basé sur PyInstaller & Nuitka -
- -
+
-
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+ Outil GUI moderne et prêt à l'emploi pour empaqueter des applications Python multiplateformes
+ Propulsé par PyInstaller et Nuitka, offrant configuration visuelle, analyse statique des dépendances et flux de compilation automatisé.
+
-
-
+
+
+
+
+
+
+
Copyright (C) 2026 QwejayHuang.
diff --git a/docs/readme/README_JA.md b/docs/readme/README_JA.md index b329eb6..a383beb 100644 --- a/docs/readme/README_JA.md +++ b/docs/readme/README_JA.md @@ -14,70 +14,196 @@- PyInstaller と Nuitka をベースにしたクロスプラットフォーム Python パッケージング GUI ツール -
- -
+
-
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+ モダンで使いやすいクロスプラットフォーム対応 Python アプリケーションパッケージング GUI ツール
+ PyInstaller と Nuitka のデュアルエンジンを搭載し、視覚的な設定、静的依存関係解析、自動ビルドパイプラインを提供
+
-
-
+
+
+
+
+
+
+
Copyright (C) 2026 QwejayHuang.
diff --git a/docs/readme/README_KO.md b/docs/readme/README_KO.md index 5e38792..31ae241 100644 --- a/docs/readme/README_KO.md +++ b/docs/readme/README_KO.md @@ -14,70 +14,196 @@- PyInstaller 및 Nuitka 기반의 크로스 플랫폼 Python 애플리케이션 패키징 GUI 도구 -
- -
+
-
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+ 현대적이고 즉시 사용 가능한 크로스 플랫폼 Python 애플리케이션 패키징 GUI 도구
+ PyInstaller 및 Nuitka 듀얼 엔진을 탑재하여 시각적 구성, 정적 의존성 분석 및 자동화된 빌드 워크플로 제공
+
-
-
+
+
+
+
+
+
+
Copyright (C) 2026 QwejayHuang.
diff --git a/docs/readme/README_PT.md b/docs/readme/README_PT.md index 24b1b48..3f88e0e 100644 --- a/docs/readme/README_PT.md +++ b/docs/readme/README_PT.md @@ -14,70 +14,194 @@- Uma ferramenta GUI multiplataforma para empacotar aplicações Python baseada no PyInstaller & Nuitka -
- -
+
-
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+ Ferramenta GUI moderna e pronta para uso para empacotar aplicações Python multiplataforma
+ Alimentada pelos motores PyInstaller e Nuitka, com configuração visual, análise estática de dependências e fluxo de compilação automatizado.
+
-
-
+
+
+
+
+
+
+
Copyright (C) 2026 QwejayHuang.
diff --git a/docs/readme/README_RU.md b/docs/readme/README_RU.md index ee52428..23c90f7 100644 --- a/docs/readme/README_RU.md +++ b/docs/readme/README_RU.md @@ -14,70 +14,194 @@- Кроссплатформенный GUI-инструмент упаковки Python-приложений на базе PyInstaller и Nuitka -
- -
+
-
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+ Современный кроссплатформенный GUI-инструмент для упаковки Python-приложений
+ На базе PyInstaller и Nuitka, с визуальной конфигурацией, статическим анализом зависимостей и автоматизацией сборки.
+
-
-
+
+
+
+
+
+
+
Copyright (C) 2026 QwejayHuang.
diff --git a/docs/readme/README_TW.md b/docs/readme/README_TW.md index 5a3340e..dcf030f 100644 --- a/docs/readme/README_TW.md +++ b/docs/readme/README_TW.md @@ -13,10 +13,6 @@ Português -- 基於 PyInstaller 與 Nuitka 的跨平台 Python 應用程式視覺化打包建置工具 -
- -QPyPack 是一款致力於簡化 Python 應用程式打包流程的視覺化工具。它深度整合了 **PyInstaller** 與 **Nuitka** 兩大主流編譯引擎,將繁瑣的終端機命令列參數轉化為直觀、極簡的圖形介面互動,協助開發者高效、高成功率地產生跨平台原生可執行程式。 +--- + +
+ 現代化、開箱即用的跨平台 Python 應用程式打包 GUI 工具
+ 基於 PyInstaller 與 Nuitka 雙引擎驅動,提供視覺化配置、靜態相依性分析與自動化建置工作流程
+
-
-
-
-
-
+
+
+
+
+
+
+
Copyright (C) 2026 QwejayHuang.
diff --git a/pyproject.toml b/pyproject.toml index 945001c..62b13ed 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "qpypack" -version = "2.7.14" +version = "2.8.0" description = "A cross-platform GUI packaging and compilation suite based on PyInstaller and Nuitka." readme = "README_EN.md" authors = [ diff --git a/qpypack/locales/ar_SA.json b/qpypack/locales/ar_SA.json index 2fcd972..949696c 100644 --- a/qpypack/locales/ar_SA.json +++ b/qpypack/locales/ar_SA.json @@ -87,6 +87,7 @@ "Description:": "الوصف:", "Desktop Application": "تطبيق سطح المكتب", "Detailed Mode": "الوضع المفصل", + "Detected multiple entry scripts in project. Please select one to build:": "تم اكتشاف عدة سكربتات إدخال في المشروع. يرجى تحديد واحد للبناء:", "Directory": "الدليل", "Discovered via scanner ({count}): {pkgs}": "تم اكتشافه عبر الماسح ({count}): {pkgs}", "Disk space critically low: {free:.1f}GB < {min:.1f}GB": "مساحة القرص منخفضة بشكل حرج: {free:.1f}GB < {min:.1f}GB", @@ -148,6 +149,7 @@ "Leave blank to auto-search requirements.txt in current directory": "اتركه فارغًا للبحث التلقائي عن requirements.txt في الدليل الحالي", "Legacy macOS Compatible": "متوافق مع macOS القديم", "Lite Mode (Smaller size)": "الوضع الخفيف (حجم أصغر)", + "Loaded Project: {name} | Entry: {entry}": "تم تحميل المشروع: {name} | الإدخال: {entry}", "Loaded: {filename}": "تم التحميل: {filename}", "Locally Detected Pythons": "إصدارات بايثون المكتشفة محليًا", "Lock Core Dependencies": "قفل التبعيات الأساسية", @@ -250,6 +252,7 @@ "Script loaded. You can drag asset folders or data files directly here to bundle them.": "تم تحميل البرنامج النصي. يمكنك سحب مجلدات الأصول أو ملفات البيانات مباشرة هنا لتجميعها.", "Select .pfx / .p12 certificate file": "حدد ملف الشهادة .pfx / .p12", "Select All": "تحديد الكل", + "Select Main Entry Script": "حدد سكربت الإدخال الرئيسي", "Select Python Version to Download:": "حدد إصدار Python للتنزيل:", "Select shared directory...": "تحديد الدليل المشترك...", "Self-Signed Certificate (*.pfx)": "شهادة موقعة ذاتيًا (*.pfx)", @@ -377,6 +380,7 @@ "[Syntax Error] Source code contains syntax errors, compilation aborted:\n - File: {file}\n - Type: {type}\n - Line: Line {line}\n - Detail: {desc}\n\nTip: Please ensure the source code runs locally before packaging.": "[Syntax Error] يحتوي الكود المصدري على أخطاء نحوية، تم إحباط التجميع:\n - الملف: {file}\n - النوع: {type}\n - السطر: السطر {line}\n - التفاصيل: {desc}\n\nنصيحة: يرجى التأكد من أن الكود المصدري يعمل محليًا قبل التعبئة.", "[Syntax Error] Source code syntax parsing failed, build aborted:\n - File: {file}\n - Detail: {desc}\n\nTip: This is usually NOT a fault of the packaging tool.\nPlease ensure the [Build Python Version] you selected matches the version you used to [Write/Test the Code].\nUsing newer syntax (e.g., walrus operator :=, type unions |, match-case) in an older Python environment will trigger this error.\nWe recommend going to [Build Settings] -> [Engine] to switch to the correct Python version.": "[Syntax Error] فشل تحليل بناء جملة الكود المصدري، تم إحباط البناء:\n - الملف: {file}\n - التفاصيل: {desc}\n\nنصيحة: هذا عادة ليس خطأ من أداة التعبئة.\nيرجى التأكد من أن [إصدار بايثون للبناء] الذي حددته يطابق الإصدار الذي استخدمته لـ [كتابة/اختبار الكود].\nاستخدام بناء جملة أحدث (مثل عامل الفظ :=، اتحادات الأنواع |، match-case) في بيئة بايثون أقدم سيؤدي إلى هذا الخطأ.\nنوصي بالانتقال إلى [إعدادات البناء] -> [المحرك] للتبديل إلى إصدار بايثون الصحيح.", "[Syntax Error] Source code syntax parsing failed, build aborted:\n - File: {file}\n - Line: Line {line}\n - Detail: {desc}\n\nTip: This is usually NOT a fault of the packaging tool.\nPlease ensure the [Build Python Version] you selected matches the version you used to [Write/Test the Code].\nUsing newer syntax (e.g., walrus operator :=, type unions |, match-case) in an older Python environment will trigger this error.\nWe recommend going to [Build Settings] -> [Engine] to switch to the correct Python version.": "[Syntax Error] فشل تحليل بناء جملة الكود المصدري، تم إحباط البناء:\n - الملف: {file}\n - السطر: السطر {line}\n - التفاصيل: {desc}\n\nنصيحة: هذا عادة ليس خطأ من أداة التعبئة.\nيرجى التأكد من أن [إصدار بايثون للبناء] الذي اخترته يطابق الإصدار الذي استخدمته [لكتابة/اختبار الكود].\nاستخدام بناء جملة أحدث (مثل عامل الفظ :=، اتحادات الأنواع |، match-case) في بيئة بايثون أقدم سيؤدي إلى هذا الخطأ.\nنوصي بالانتقال إلى [إعدادات البناء] -> [المحرك] لتبديل إصدار بايثون الصحيح.", + "[TIP] Script imports parent module '{mod}'. If build fails, try dragging the whole project folder here.": "[TIP] يستورد السكربت الوحدة الأصلية '{mod}'. إذا فشل البناء، حاول سحب مجلد المشروع بأكمله هنا.", "[WARN] 'multiprocessing' module detected. Ensure 'multiprocessing.freeze_support()' is called under 'if __name__ == \"__main__\":' to prevent infinite process loops (fork bombs).": "[WARN] تم اكتشاف وحدة 'multiprocessing'. تأكد من استدعاء 'multiprocessing.freeze_support()' تحت 'if __name__ == \"__main__\":' لمنع حلقات العمليات اللانهائية (قنابل الشوكة).", "[WARN] AST Analysis Exception: {error}": "[WARN] استثناء تحليل AST: {error}", "[WARN] Command timeout (>{timeout}s)": "[WARN] انتهت مهلة الأمر (>{timeout} ثانية)", @@ -405,5 +409,6 @@ "[WARN] Target project is in a Cloud Sync directory (e.g. OneDrive/Dropbox). Cloud sync may temporarily lock build files.": "[WARN] المشروع الهدف موجود في دليل مزامنة سحابية (مثل OneDrive/Dropbox). قد تؤدي المزامنة السحابية إلى قفل ملفات البناء مؤقتًا.", "[WARN] Timestamp server connection timed out, performing local fast signing...": "[WARN] انتهت مهلة الاتصال بخادم الطابع الزمني، يتم التوقيع السريع محليًا...", "[WARN] Usage of '__file__' detected. In PyInstaller One-File mode, use 'sys._MEIPASS' to reliably locate bundled resource files!": "[WARN] تم اكتشاف استخدام '__file__'. في وضع الملف الواحد لـ PyInstaller، استخدم 'sys._MEIPASS' لتحديد موقع ملفات الموارد المضمنة بشكل موثوق!", - "\\nProgram execution completed, press Enter to exit...": "\\nاكتمل تنفيذ البرنامج، اضغط Enter للخروج..." + "\\nProgram execution completed, press Enter to exit...": "\\nاكتمل تنفيذ البرنامج، اضغط Enter للخروج...", + "Package Mapping & Remediation": "تعيين الحزم والإصلاح" } diff --git a/qpypack/locales/de_DE.json b/qpypack/locales/de_DE.json index 71a68f9..561c284 100644 --- a/qpypack/locales/de_DE.json +++ b/qpypack/locales/de_DE.json @@ -87,6 +87,7 @@ "Description:": "Beschreibung:", "Desktop Application": "Desktop-Anwendung", "Detailed Mode": "Detaillierter Modus", + "Detected multiple entry scripts in project. Please select one to build:": "Mehrere Einstiegsskripte im Projekt erkannt. Bitte wählen Sie eines zum Erstellen aus:", "Directory": "Verzeichnis", "Discovered via scanner ({count}): {pkgs}": "Per Scanner entdeckt ({count}): {pkgs}", "Disk space critically low: {free:.1f}GB < {min:.1f}GB": "Festplattenspeicher kritisch niedrig: {free:.1f}GB < {min:.1f}GB", @@ -148,6 +149,7 @@ "Leave blank to auto-search requirements.txt in current directory": "Leer lassen, um automatisch requirements.txt im aktuellen Verzeichnis zu suchen", "Legacy macOS Compatible": "Legacy macOS-kompatibel", "Lite Mode (Smaller size)": "Lite-Modus (kleinere Größe)", + "Loaded Project: {name} | Entry: {entry}": "Geladenes Projekt: {name} | Einstieg: {entry}", "Loaded: {filename}": "Geladen: {filename}", "Locally Detected Pythons": "Lokal erkannte Pythons", "Lock Core Dependencies": "Kernabhängigkeiten sperren", @@ -250,6 +252,7 @@ "Script loaded. You can drag asset folders or data files directly here to bundle them.": "Skript geladen. Sie können Asset-Ordner oder Datendateien direkt hierher ziehen, um sie zu bündeln.", "Select .pfx / .p12 certificate file": "Wählen Sie .pfx / .p12 Zertifikatsdatei", "Select All": "Alle auswählen", + "Select Main Entry Script": "Haupt-Einstiegsskript auswählen", "Select Python Version to Download:": "Python-Version zum Herunterladen auswählen:", "Select shared directory...": "Gemeinsames Verzeichnis auswählen...", "Self-Signed Certificate (*.pfx)": "Selbstsigniertes Zertifikat (*.pfx)", @@ -377,6 +380,7 @@ "[Syntax Error] Source code contains syntax errors, compilation aborted:\n - File: {file}\n - Type: {type}\n - Line: Line {line}\n - Detail: {desc}\n\nTip: Please ensure the source code runs locally before packaging.": "[Syntax Error] Der Quellcode enthält Syntaxfehler, Kompilierung abgebrochen:\n - Datei: {file}\n - Typ: {type}\n - Zeile: Zeile {line}\n - Detail: {desc}\n\nTipp: Bitte stellen Sie sicher, dass der Quellcode lokal ausgeführt werden kann, bevor Sie ihn verpacken.", "[Syntax Error] Source code syntax parsing failed, build aborted:\n - File: {file}\n - Detail: {desc}\n\nTip: This is usually NOT a fault of the packaging tool.\nPlease ensure the [Build Python Version] you selected matches the version you used to [Write/Test the Code].\nUsing newer syntax (e.g., walrus operator :=, type unions |, match-case) in an older Python environment will trigger this error.\nWe recommend going to [Build Settings] -> [Engine] to switch to the correct Python version.": "[Syntax Error] Parsen des Quellcodes fehlgeschlagen, Build abgebrochen:\n - Datei: {file}\n - Detail: {desc}\n\nTipp: Dies ist normalerweise kein Fehler des Paketierungstools.\nBitte stellen Sie sicher, dass die ausgewählte [Build-Python-Version] mit der Version übereinstimmt, die Sie zum [Schreiben/Testen des Codes] verwendet haben.\nDie Verwendung neuerer Syntax (z.B. Walross-Operator :=, Typ-Unionen |, match-case) in einer älteren Python-Umgebung löst diesen Fehler aus.\nWir empfehlen, in den [Baueinstellungen] -> [Engine] zur korrekten Python-Version zu wechseln.", "[Syntax Error] Source code syntax parsing failed, build aborted:\n - File: {file}\n - Line: Line {line}\n - Detail: {desc}\n\nTip: This is usually NOT a fault of the packaging tool.\nPlease ensure the [Build Python Version] you selected matches the version you used to [Write/Test the Code].\nUsing newer syntax (e.g., walrus operator :=, type unions |, match-case) in an older Python environment will trigger this error.\nWe recommend going to [Build Settings] -> [Engine] to switch to the correct Python version.": "[Syntax Error] Die Syntaxanalyse des Quellcodes ist fehlgeschlagen, Build abgebrochen:\n - Datei: {file}\n - Zeile: Zeile {line}\n - Detail: {desc}\n\nTipp: Dies ist normalerweise KEIN Fehler des Verpackungstools.\nBitte stellen Sie sicher, dass die ausgewählte [Build-Python-Version] mit der Version übereinstimmt, die Sie zum [Schreiben/Testen des Codes] verwendet haben.\nDie Verwendung neuerer Syntax (z. B. Walross-Operator :=, Typ-Unionen |, match-case) in einer älteren Python-Umgebung führt zu diesem Fehler.\nWir empfehlen, unter [Buildeinstellungen] -> [Engine] zur korrekten Python-Version zu wechseln.", + "[TIP] Script imports parent module '{mod}'. If build fails, try dragging the whole project folder here.": "[TIP] Das Skript importiert das übergeordnete Modul '{mod}'. Wenn der Build fehlschlägt, versuchen Sie, den gesamten Projektordner hierher zu ziehen.", "[WARN] 'multiprocessing' module detected. Ensure 'multiprocessing.freeze_support()' is called under 'if __name__ == \"__main__\":' to prevent infinite process loops (fork bombs).": "[WARN] 'multiprocessing'-Modul erkannt. Stellen Sie sicher, dass 'multiprocessing.freeze_support()' unter 'if __name__ == \"__main__\":' aufgerufen wird, um Endlosschleifen (Fork-Bomben) zu verhindern.", "[WARN] AST Analysis Exception: {error}": "[WARN] AST-Analyse-Ausnahme: {error}", "[WARN] Command timeout (>{timeout}s)": "[WARN] Befehlszeitüberschreitung (>{timeout}s)", @@ -405,5 +409,6 @@ "[WARN] Target project is in a Cloud Sync directory (e.g. OneDrive/Dropbox). Cloud sync may temporarily lock build files.": "[WARN] Zielprojekt befindet sich in einem Cloud-Sync-Verzeichnis (z.B. OneDrive/Dropbox). Cloud-Sync kann Build-Dateien vorübergehend sperren.", "[WARN] Timestamp server connection timed out, performing local fast signing...": "[WARN] Zeitstempel-Server-Verbindung abgelaufen, lokale schnelle Signierung wird durchgeführt...", "[WARN] Usage of '__file__' detected. In PyInstaller One-File mode, use 'sys._MEIPASS' to reliably locate bundled resource files!": "[WARN] Verwendung von '__file__' erkannt. Im PyInstaller-Einzeldateimodus verwenden Sie 'sys._MEIPASS', um gebündelte Ressourcendateien zuverlässig zu finden!", - "\\nProgram execution completed, press Enter to exit...": "\\nProgrammausführung abgeschlossen, drücken Sie die Eingabetaste zum Beenden..." + "\\nProgram execution completed, press Enter to exit...": "\\nProgrammausführung abgeschlossen, drücken Sie die Eingabetaste zum Beenden...", + "Package Mapping & Remediation": "Paketzuordnung & Fehlerbehebung" } diff --git a/qpypack/locales/es_ES.json b/qpypack/locales/es_ES.json index 817ac8a..909903e 100644 --- a/qpypack/locales/es_ES.json +++ b/qpypack/locales/es_ES.json @@ -87,6 +87,7 @@ "Description:": "Descripción:", "Desktop Application": "Aplicación de escritorio", "Detailed Mode": "Modo detallado", + "Detected multiple entry scripts in project. Please select one to build:": "Se detectaron múltiples scripts de entrada en el proyecto. Seleccione uno para compilar:", "Directory": "Directorio", "Discovered via scanner ({count}): {pkgs}": "Descubierto mediante escáner ({count}): {pkgs}", "Disk space critically low: {free:.1f}GB < {min:.1f}GB": "Espacio en disco críticamente bajo: {free:.1f}GB < {min:.1f}GB", @@ -148,6 +149,7 @@ "Leave blank to auto-search requirements.txt in current directory": "Dejar en blanco para buscar automáticamente requirements.txt en el directorio actual", "Legacy macOS Compatible": "Compatible con macOS heredado", "Lite Mode (Smaller size)": "Modo ligero (tamaño más pequeño)", + "Loaded Project: {name} | Entry: {entry}": "Proyecto cargado: {name} | Entrada: {entry}", "Loaded: {filename}": "Cargado: {filename}", "Locally Detected Pythons": "Pythons detectados localmente", "Lock Core Dependencies": "Bloquear dependencias principales", @@ -250,6 +252,7 @@ "Script loaded. You can drag asset folders or data files directly here to bundle them.": "Script cargado. Puede arrastrar carpetas de activos o archivos de datos directamente aquí para incluirlos.", "Select .pfx / .p12 certificate file": "Seleccionar archivo de certificado .pfx / .p12", "Select All": "Seleccionar Todo", + "Select Main Entry Script": "Seleccionar script de entrada principal", "Select Python Version to Download:": "Seleccionar Versión de Python para Descargar:", "Select shared directory...": "Seleccionar directorio compartido...", "Self-Signed Certificate (*.pfx)": "Certificado Autofirmado (*.pfx)", @@ -377,6 +380,7 @@ "[Syntax Error] Source code contains syntax errors, compilation aborted:\n - File: {file}\n - Type: {type}\n - Line: Line {line}\n - Detail: {desc}\n\nTip: Please ensure the source code runs locally before packaging.": "[Syntax Error] El código fuente contiene errores de sintaxis, compilación abortada:\n - Archivo: {file}\n - Tipo: {type}\n - Línea: Línea {line}\n - Detalle: {desc}\n\nConsejo: Asegúrese de que el código fuente se ejecute localmente antes de empaquetar.", "[Syntax Error] Source code syntax parsing failed, build aborted:\n - File: {file}\n - Detail: {desc}\n\nTip: This is usually NOT a fault of the packaging tool.\nPlease ensure the [Build Python Version] you selected matches the version you used to [Write/Test the Code].\nUsing newer syntax (e.g., walrus operator :=, type unions |, match-case) in an older Python environment will trigger this error.\nWe recommend going to [Build Settings] -> [Engine] to switch to the correct Python version.": "[Syntax Error] Falló el análisis de sintaxis del código fuente, compilación abortada:\n - Archivo: {file}\n - Detalle: {desc}\n\nConsejo: Esto generalmente NO es un fallo de la herramienta de empaquetado.\nAsegúrese de que la [Versión de Python de compilación] seleccionada coincida con la versión que usó para [Escribir/Probar el código].\nUsar sintaxis más nueva (por ejemplo, operador morsa :=, uniones de tipos |, match-case) en un entorno Python más antiguo provocará este error.\nRecomendamos ir a [Configuración de compilación] -> [Motor] para cambiar a la versión correcta de Python.", "[Syntax Error] Source code syntax parsing failed, build aborted:\n - File: {file}\n - Line: Line {line}\n - Detail: {desc}\n\nTip: This is usually NOT a fault of the packaging tool.\nPlease ensure the [Build Python Version] you selected matches the version you used to [Write/Test the Code].\nUsing newer syntax (e.g., walrus operator :=, type unions |, match-case) in an older Python environment will trigger this error.\nWe recommend going to [Build Settings] -> [Engine] to switch to the correct Python version.": "[Syntax Error] Falló el análisis de sintaxis del código fuente, compilación abortada:\n - Archivo: {file}\n - Línea: Línea {line}\n - Detalle: {desc}\n\nConsejo: Esto generalmente NO es un fallo de la herramienta de empaquetado.\nAsegúrese de que la [Versión de Python de compilación] seleccionada coincida con la versión que usó para [Escribir/Probar el código].\nEl uso de sintaxis más nueva (por ejemplo, operador morsa :=, uniones de tipos |, match-case) en un entorno Python más antiguo provocará este error.\nRecomendamos ir a [Configuración de compilación] -> [Motor] para cambiar a la versión correcta de Python.", + "[TIP] Script imports parent module '{mod}'. If build fails, try dragging the whole project folder here.": "[TIP] El script importa el módulo padre '{mod}'. Si la compilación falla, intente arrastrar toda la carpeta del proyecto aquí.", "[WARN] 'multiprocessing' module detected. Ensure 'multiprocessing.freeze_support()' is called under 'if __name__ == \"__main__\":' to prevent infinite process loops (fork bombs).": "[WARN] Módulo 'multiprocessing' detectado. Asegúrese de que 'multiprocessing.freeze_support()' se llame dentro de 'if __name__ == \"__main__\":' para evitar bucles infinitos de procesos (fork bombs).", "[WARN] AST Analysis Exception: {error}": "[WARN] Excepción de análisis AST: {error}", "[WARN] Command timeout (>{timeout}s)": "[WARN] Tiempo de espera del comando agotado (>{timeout}s)", @@ -405,5 +409,6 @@ "[WARN] Target project is in a Cloud Sync directory (e.g. OneDrive/Dropbox). Cloud sync may temporarily lock build files.": "[WARN] El proyecto objetivo está en un directorio de sincronización en la nube (por ejemplo, OneDrive/Dropbox). La sincronización en la nube puede bloquear temporalmente los archivos de compilación.", "[WARN] Timestamp server connection timed out, performing local fast signing...": "[WARN] Tiempo de espera agotado en la conexión al servidor de marcas de tiempo, realizando firma rápida local...", "[WARN] Usage of '__file__' detected. In PyInstaller One-File mode, use 'sys._MEIPASS' to reliably locate bundled resource files!": "[WARN] Se detectó el uso de '__file__'. En el modo de un solo archivo de PyInstaller, use 'sys._MEIPASS' para localizar de manera confiable los archivos de recursos empaquetados.", - "\\nProgram execution completed, press Enter to exit...": "\\nEjecución del programa completada, presione Enter para salir..." + "\\nProgram execution completed, press Enter to exit...": "\\nEjecución del programa completada, presione Enter para salir...", + "Package Mapping & Remediation": "Mapeo de paquetes y corrección" } diff --git a/qpypack/locales/fr_FR.json b/qpypack/locales/fr_FR.json index b2385ff..9f204c4 100644 --- a/qpypack/locales/fr_FR.json +++ b/qpypack/locales/fr_FR.json @@ -87,6 +87,7 @@ "Description:": "Description :", "Desktop Application": "Application de bureau", "Detailed Mode": "Mode détaillé", + "Detected multiple entry scripts in project. Please select one to build:": "Plusieurs scripts d'entrée détectés dans le projet. Veuillez en sélectionner un à compiler :", "Directory": "Répertoire", "Discovered via scanner ({count}): {pkgs}": "Découvert via le scanner ({count}) : {pkgs}", "Disk space critically low: {free:.1f}GB < {min:.1f}GB": "Espace disque critique : {free:.1f} Go < {min:.1f} Go", @@ -148,6 +149,7 @@ "Leave blank to auto-search requirements.txt in current directory": "Laisser vide pour rechercher automatiquement requirements.txt dans le répertoire courant", "Legacy macOS Compatible": "Compatible macOS hérité", "Lite Mode (Smaller size)": "Mode léger (taille réduite)", + "Loaded Project: {name} | Entry: {entry}": "Projet chargé : {name} | Entrée : {entry}", "Loaded: {filename}": "Chargé : {filename}", "Locally Detected Pythons": "Pythons détectés localement", "Lock Core Dependencies": "Verrouiller les dépendances principales", @@ -250,6 +252,7 @@ "Script loaded. You can drag asset folders or data files directly here to bundle them.": "Script chargé. Vous pouvez glisser des dossiers d'actifs ou des fichiers de données directement ici pour les regrouper.", "Select .pfx / .p12 certificate file": "Sélectionner le fichier de certificat .pfx / .p12", "Select All": "Tout sélectionner", + "Select Main Entry Script": "Sélectionner le script d'entrée principal", "Select Python Version to Download:": "Sélectionner la version de Python à télécharger :", "Select shared directory...": "Sélectionner le répertoire partagé...", "Self-Signed Certificate (*.pfx)": "Certificat auto-signé (*.pfx)", @@ -377,6 +380,7 @@ "[Syntax Error] Source code contains syntax errors, compilation aborted:\n - File: {file}\n - Type: {type}\n - Line: Line {line}\n - Detail: {desc}\n\nTip: Please ensure the source code runs locally before packaging.": "[Syntax Error] Le code source contient des erreurs de syntaxe, compilation interrompue :\n - Fichier : {file}\n - Type : {type}\n - Ligne : Ligne {line}\n - Détail : {desc}\n\nAstuce : Veuillez vous assurer que le code source s'exécute localement avant l'empaquetage.", "[Syntax Error] Source code syntax parsing failed, build aborted:\n - File: {file}\n - Detail: {desc}\n\nTip: This is usually NOT a fault of the packaging tool.\nPlease ensure the [Build Python Version] you selected matches the version you used to [Write/Test the Code].\nUsing newer syntax (e.g., walrus operator :=, type unions |, match-case) in an older Python environment will trigger this error.\nWe recommend going to [Build Settings] -> [Engine] to switch to the correct Python version.": "[Syntax Error] L'analyse syntaxique du code source a échoué, build interrompu :\n - Fichier : {file}\n - Détail : {desc}\n\nAstuce : Ce n'est généralement pas une faute de l'outil d'empaquetage.\nAssurez-vous que la [Version Python de build] sélectionnée correspond à celle utilisée pour [Écrire/Tester le code].\nL'utilisation d'une syntaxe plus récente (par exemple, opérateur morse :=, unions de types |, match-case) dans un environnement Python plus ancien déclenchera cette erreur.\nNous recommandons d'aller dans [Paramètres de build] -> [Moteur] pour passer à la version Python correcte.", "[Syntax Error] Source code syntax parsing failed, build aborted:\n - File: {file}\n - Line: Line {line}\n - Detail: {desc}\n\nTip: This is usually NOT a fault of the packaging tool.\nPlease ensure the [Build Python Version] you selected matches the version you used to [Write/Test the Code].\nUsing newer syntax (e.g., walrus operator :=, type unions |, match-case) in an older Python environment will trigger this error.\nWe recommend going to [Build Settings] -> [Engine] to switch to the correct Python version.": "[Syntax Error] L'analyse syntaxique du code source a échoué, construction interrompue :\n - Fichier : {file}\n - Ligne : Ligne {line}\n - Détail : {desc}\n\nAstuce : Ce n'est généralement PAS une faute de l'outil d'empaquetage.\nVeuillez vous assurer que la [Version Python de construction] que vous avez sélectionnée correspond à celle utilisée pour [Écrire/Tester le code].\nL'utilisation d'une syntaxe plus récente (par exemple, l'opérateur morse :=, les unions de types |, match-case) dans un environnement Python plus ancien déclenchera cette erreur.\nNous recommandons d'aller dans [Paramètres de construction] -> [Moteur] pour passer à la version Python correcte.", + "[TIP] Script imports parent module '{mod}'. If build fails, try dragging the whole project folder here.": "[TIP] Le script importe le module parent '{mod}'. Si la compilation échoue, essayez de glisser le dossier du projet entier ici.", "[WARN] 'multiprocessing' module detected. Ensure 'multiprocessing.freeze_support()' is called under 'if __name__ == \"__main__\":' to prevent infinite process loops (fork bombs).": "[WARN] Module 'multiprocessing' détecté. Assurez-vous que 'multiprocessing.freeze_support()' est appelé sous 'if __name__ == \"__main__\":' pour éviter les boucles de processus infinies (bombes de fork).", "[WARN] AST Analysis Exception: {error}": "[WARN] Exception d'analyse AST : {error}", "[WARN] Command timeout (>{timeout}s)": "[WARN] Délai d'attente de la commande dépassé (>{timeout}s)", @@ -405,5 +409,6 @@ "[WARN] Target project is in a Cloud Sync directory (e.g. OneDrive/Dropbox). Cloud sync may temporarily lock build files.": "[WARN] Le projet cible se trouve dans un répertoire de synchronisation cloud (par ex. OneDrive/Dropbox). La synchronisation cloud peut temporairement verrouiller les fichiers de construction.", "[WARN] Timestamp server connection timed out, performing local fast signing...": "[WARN] Délai d'attente dépassé pour le serveur d'horodatage, signature rapide locale en cours...", "[WARN] Usage of '__file__' detected. In PyInstaller One-File mode, use 'sys._MEIPASS' to reliably locate bundled resource files!": "[WARN] Utilisation de '__file__' détectée. En mode fichier unique PyInstaller, utilisez 'sys._MEIPASS' pour localiser de manière fiable les fichiers de ressources inclus !", - "\\nProgram execution completed, press Enter to exit...": "\\nExécution du programme terminée, appuyez sur Entrée pour quitter..." + "\\nProgram execution completed, press Enter to exit...": "\\nExécution du programme terminée, appuyez sur Entrée pour quitter...", + "Package Mapping & Remediation": "Mappage de paquets et correction" } diff --git a/qpypack/locales/it_IT.json b/qpypack/locales/it_IT.json index 4d5e3bb..5802251 100644 --- a/qpypack/locales/it_IT.json +++ b/qpypack/locales/it_IT.json @@ -87,6 +87,7 @@ "Description:": "Descrizione:", "Desktop Application": "Applicazione desktop", "Detailed Mode": "Modalità dettagliata", + "Detected multiple entry scripts in project. Please select one to build:": "Rilevati più script di ingresso nel progetto. Selezionane uno da compilare:", "Directory": "Directory", "Discovered via scanner ({count}): {pkgs}": "Scoperte tramite scanner ({count}): {pkgs}", "Disk space critically low: {free:.1f}GB < {min:.1f}GB": "Spazio su disco criticamente basso: {free:.1f}GB < {min:.1f}GB", @@ -148,6 +149,7 @@ "Leave blank to auto-search requirements.txt in current directory": "Lasciare vuoto per cercare automaticamente requirements.txt nella directory corrente", "Legacy macOS Compatible": "Compatibile con macOS legacy", "Lite Mode (Smaller size)": "Modalità leggera (dimensioni ridotte)", + "Loaded Project: {name} | Entry: {entry}": "Progetto caricato: {name} | Ingresso: {entry}", "Loaded: {filename}": "Caricato: {filename}", "Locally Detected Pythons": "Python rilevati localmente", "Lock Core Dependencies": "Blocca dipendenze principali", @@ -250,6 +252,7 @@ "Script loaded. You can drag asset folders or data files directly here to bundle them.": "Script caricato. Puoi trascinare qui direttamente le cartelle di asset o i file di dati per includerli.", "Select .pfx / .p12 certificate file": "Seleziona file certificato .pfx / .p12", "Select All": "Seleziona Tutto", + "Select Main Entry Script": "Seleziona script di ingresso principale", "Select Python Version to Download:": "Seleziona Versione Python da Scaricare:", "Select shared directory...": "Seleziona directory condivisa...", "Self-Signed Certificate (*.pfx)": "Certificato Auto-Firmato (*.pfx)", @@ -377,6 +380,7 @@ "[Syntax Error] Source code contains syntax errors, compilation aborted:\n - File: {file}\n - Type: {type}\n - Line: Line {line}\n - Detail: {desc}\n\nTip: Please ensure the source code runs locally before packaging.": "[Syntax Error] Il codice sorgente contiene errori di sintassi, compilazione interrotta:\n - File: {file}\n - Tipo: {type}\n - Riga: Riga {line}\n - Dettaglio: {desc}\n\nSuggerimento: assicurarsi che il codice sorgente venga eseguito localmente prima dell'impacchettamento.", "[Syntax Error] Source code syntax parsing failed, build aborted:\n - File: {file}\n - Detail: {desc}\n\nTip: This is usually NOT a fault of the packaging tool.\nPlease ensure the [Build Python Version] you selected matches the version you used to [Write/Test the Code].\nUsing newer syntax (e.g., walrus operator :=, type unions |, match-case) in an older Python environment will trigger this error.\nWe recommend going to [Build Settings] -> [Engine] to switch to the correct Python version.": "[Syntax Error] Analisi della sintassi del codice sorgente fallita, build interrotta:\n - File: {file}\n - Dettaglio: {desc}\n\nSuggerimento: Di solito NON è un difetto dello strumento di packaging.\nAssicurati che la [Versione Python di build] selezionata corrisponda alla versione usata per [Scrivere/Testare il codice].\nL'uso di sintassi più recente (es. operatore tricheco :=, unioni di tipi |, match-case) in un ambiente Python più vecchio attiverà questo errore.\nTi consigliamo di andare in [Impostazioni di build] -> [Motore] per passare alla versione Python corretta.", "[Syntax Error] Source code syntax parsing failed, build aborted:\n - File: {file}\n - Line: Line {line}\n - Detail: {desc}\n\nTip: This is usually NOT a fault of the packaging tool.\nPlease ensure the [Build Python Version] you selected matches the version you used to [Write/Test the Code].\nUsing newer syntax (e.g., walrus operator :=, type unions |, match-case) in an older Python environment will trigger this error.\nWe recommend going to [Build Settings] -> [Engine] to switch to the correct Python version.": "[Syntax Error] Analisi della sintassi del codice sorgente non riuscita, build interrotta:\n - File: {file}\n - Riga: Riga {line}\n - Dettaglio: {desc}\n\nSuggerimento: di solito NON è un difetto dello strumento di impacchettamento.\nAssicurarsi che la [Versione Python di build] selezionata corrisponda alla versione utilizzata per [Scrivere/Testare il codice].\nL'uso di sintassi più recente (ad esempio operatore tricheco :=, unioni di tipi |, match-case) in un ambiente Python più vecchio attiverà questo errore.\nSi consiglia di andare su [Impostazioni di build] -> [Motore] per passare alla versione Python corretta.", + "[TIP] Script imports parent module '{mod}'. If build fails, try dragging the whole project folder here.": "[TIP] Lo script importa il modulo padre '{mod}'. Se la compilazione fallisce, prova a trascinare qui l'intera cartella del progetto.", "[WARN] 'multiprocessing' module detected. Ensure 'multiprocessing.freeze_support()' is called under 'if __name__ == \"__main__\":' to prevent infinite process loops (fork bombs).": "[WARN] Modulo 'multiprocessing' rilevato. Assicurarsi che 'multiprocessing.freeze_support()' venga chiamato sotto 'if __name__ == \"__main__\":' per prevenire cicli di processo infiniti (fork bomb).", "[WARN] AST Analysis Exception: {error}": "[WARN] Eccezione durante l'analisi AST: {error}", "[WARN] Command timeout (>{timeout}s)": "[WARN] Timeout del comando (>{timeout}s)", @@ -405,5 +409,6 @@ "[WARN] Target project is in a Cloud Sync directory (e.g. OneDrive/Dropbox). Cloud sync may temporarily lock build files.": "[WARN] Il progetto di destinazione si trova in una directory di sincronizzazione cloud (es. OneDrive/Dropbox). La sincronizzazione cloud potrebbe bloccare temporaneamente i file di build.", "[WARN] Timestamp server connection timed out, performing local fast signing...": "[WARN] Timeout della connessione al server timestamp, esecuzione di firma rapida locale...", "[WARN] Usage of '__file__' detected. In PyInstaller One-File mode, use 'sys._MEIPASS' to reliably locate bundled resource files!": "[WARN] Rilevato uso di '__file__'. In modalità One-File di PyInstaller, usa 'sys._MEIPASS' per individuare in modo affidabile i file di risorse inclusi!", - "\\nProgram execution completed, press Enter to exit...": "\\nEsecuzione del programma completata, premere Invio per uscire..." + "\\nProgram execution completed, press Enter to exit...": "\\nEsecuzione del programma completata, premere Invio per uscire...", + "Package Mapping & Remediation": "Mappatura pacchetti e correzione" } diff --git a/qpypack/locales/ja_JP.json b/qpypack/locales/ja_JP.json index 48e3687..15fea89 100644 --- a/qpypack/locales/ja_JP.json +++ b/qpypack/locales/ja_JP.json @@ -87,6 +87,7 @@ "Description:": "説明::", "Desktop Application": "デスクトップアプリケーション", "Detailed Mode": "詳細モード", + "Detected multiple entry scripts in project. Please select one to build:": "プロジェクト内に複数のエントリスクリプトが検出されました。ビルドするものを選択してください:", "Directory": "ディレクトリ", "Discovered via scanner ({count}): {pkgs}": "スキャナーで検出({count}):{pkgs}", "Disk space critically low: {free:.1f}GB < {min:.1f}GB": "ディスク容量が不足しています: {free:.1f}GB < {min:.1f}GB", @@ -147,6 +148,7 @@ "Leave blank to auto-search requirements.txt in current directory": "空白のままにすると現在のディレクトリの requirements.txt を自動検索します", "Legacy macOS Compatible": "レガシー macOS 互換", "Lite Mode (Smaller size)": "ライトモード(サイズ小)", + "Loaded Project: {name} | Entry: {entry}": "プロジェクトを読み込みました: {name} | エントリ: {entry}", "Loaded: {filename}": "読み込み済み: {filename}", "Locally Detected Pythons": "ローカルで検出された Python", "Lock Core Dependencies": "コア依存関係をロック", @@ -249,6 +251,7 @@ "Script loaded. You can drag asset folders or data files directly here to bundle them.": "スクリプトが読み込まれました。アセットフォルダやデータファイルをここに直接ドラッグしてバンドルできます。", "Select .pfx / .p12 certificate file": ".pfx / .p12 証明書ファイルを選択", "Select All": "すべて選択", + "Select Main Entry Script": "メインエントリスクリプトを選択", "Select Python Version to Download:": "ダウンロードする Python バージョンを選択:", "Select shared directory...": "共有ディレクトリを選択...", "Self-Signed Certificate (*.pfx)": "自己署名証明書 (*.pfx)", @@ -376,6 +379,7 @@ "[Syntax Error] Source code contains syntax errors, compilation aborted:\n - File: {file}\n - Type: {type}\n - Line: Line {line}\n - Detail: {desc}\n\nTip: Please ensure the source code runs locally before packaging.": "[Syntax Error] ソースコードに構文エラーが含まれているため、コンパイルを中止しました:\n - ファイル: {file}\n - 種類: {type}\n - 行: {line}行目\n - 詳細: {desc}\n\nヒント: パッケージ化する前に、ソースコードがローカルで実行できることを確認してください。", "[Syntax Error] Source code syntax parsing failed, build aborted:\n - File: {file}\n - Detail: {desc}\n\nTip: This is usually NOT a fault of the packaging tool.\nPlease ensure the [Build Python Version] you selected matches the version you used to [Write/Test the Code].\nUsing newer syntax (e.g., walrus operator :=, type unions |, match-case) in an older Python environment will trigger this error.\nWe recommend going to [Build Settings] -> [Engine] to switch to the correct Python version.": "[Syntax Error] ソースコードの構文解析に失敗しました。ビルドを中止します:\n - ファイル: {file}\n - 詳細: {desc}\n\nヒント: これは通常、パッケージングツールの欠陥ではありません。\n選択した[ビルドPythonバージョン]が、コードの[記述/テスト]に使用したバージョンと一致していることを確認してください。\n新しい構文(例: セイウチ演算子 :=、型ユニオン |、match-case)を古いPython環境で使用すると、このエラーが発生します。\n[ビルド設定] -> [エンジン]で正しいPythonバージョンに切り替えることをお勧めします。", "[Syntax Error] Source code syntax parsing failed, build aborted:\n - File: {file}\n - Line: Line {line}\n - Detail: {desc}\n\nTip: This is usually NOT a fault of the packaging tool.\nPlease ensure the [Build Python Version] you selected matches the version you used to [Write/Test the Code].\nUsing newer syntax (e.g., walrus operator :=, type unions |, match-case) in an older Python environment will trigger this error.\nWe recommend going to [Build Settings] -> [Engine] to switch to the correct Python version.": "[Syntax Error] ソースコードの構文解析に失敗したため、ビルドを中止しました:\n - ファイル: {file}\n - 行: {line}行目\n - 詳細: {desc}\n\nヒント: これは通常、パッケージ化ツールの欠陥ではありません。\n選択した[ビルドPythonバージョン]が、コードの[作成/テスト]に使用したバージョンと一致していることを確認してください。\n古いPython環境で新しい構文(例: セイウチ演算子 :=、型ユニオン |、match-case)を使用すると、このエラーが発生します。\n[ビルド設定] -> [エンジン]で正しいPythonバージョンに切り替えることをお勧めします。", + "[TIP] Script imports parent module '{mod}'. If build fails, try dragging the whole project folder here.": "[TIP] スクリプトが親モジュール '{mod}' をインポートしています。ビルドに失敗する場合は、プロジェクトフォルダ全体をここにドラッグしてみてください。", "[WARN] 'multiprocessing' module detected. Ensure 'multiprocessing.freeze_support()' is called under 'if __name__ == \"__main__\":' to prevent infinite process loops (fork bombs).": "[WARN] 'multiprocessing'モジュールが検出されました。無限プロセスループ(フォーク爆弾)を防ぐために、'if __name__ == \"__main__\":'の下で'multiprocessing.freeze_support()'を呼び出してください。", "[WARN] AST Analysis Exception: {error}": "[WARN] AST解析例外: {error}", "[WARN] Command timeout (>{timeout}s)": "[WARN] コマンドがタイムアウトしました (> {timeout}秒)", @@ -404,5 +408,7 @@ "[WARN] Target project is in a Cloud Sync directory (e.g. OneDrive/Dropbox). Cloud sync may temporarily lock build files.": "[WARN] ターゲットプロジェクトはクラウド同期ディレクトリ (例: OneDrive/Dropbox) にあります。クラウド同期によりビルドファイルが一時的にロックされる可能性があります。", "[WARN] Timestamp server connection timed out, performing local fast signing...": "[WARN] タイムスタンプサーバーへの接続がタイムアウトしました。ローカル高速署名を実行します...", "[WARN] Usage of '__file__' detected. In PyInstaller One-File mode, use 'sys._MEIPASS' to reliably locate bundled resource files!": "[WARN] '__file__' の使用が検出されました。PyInstallerのワンファイルモードでは、バンドルされたリソースファイルを確実に特定するために 'sys._MEIPASS' を使用してください!", - "\\nProgram execution completed, press Enter to exit...": "\\nプログラムの実行が完了しました。終了するにはEnterキーを押してください..." + "\\nProgram execution completed, press Enter to exit...": "\\nプログラムの実行が完了しました。終了するにはEnterキーを押してください...", + "Generate": "生成", + "Package Mapping & Remediation": "パッケージマッピングと修復" } diff --git a/qpypack/locales/ko_KR.json b/qpypack/locales/ko_KR.json index f71dccf..206d6ff 100644 --- a/qpypack/locales/ko_KR.json +++ b/qpypack/locales/ko_KR.json @@ -87,6 +87,7 @@ "Description:": "설명:", "Desktop Application": "데스크톱 애플리케이션", "Detailed Mode": "상세 모드", + "Detected multiple entry scripts in project. Please select one to build:": "프로젝트에서 여러 진입 스크립트가 감지되었습니다. 빌드할 항목을 선택하세요:", "Directory": "디렉터리", "Discovered via scanner ({count}): {pkgs}": "스캐너를 통해 발견됨 ({count}): {pkgs}", "Disk space critically low: {free:.1f}GB < {min:.1f}GB": "디스크 공간이 매우 부족합니다: {free:.1f}GB < {min:.1f}GB", @@ -148,6 +149,7 @@ "Leave blank to auto-search requirements.txt in current directory": "비워 두면 현재 디렉터리에서 requirements.txt 자동 검색", "Legacy macOS Compatible": "레거시 macOS 호환", "Lite Mode (Smaller size)": "라이트 모드 (더 작은 크기)", + "Loaded Project: {name} | Entry: {entry}": "로드된 프로젝트: {name} | 진입점: {entry}", "Loaded: {filename}": "로드됨: {filename}", "Locally Detected Pythons": "로컬에서 감지된 Python", "Lock Core Dependencies": "핵심 종속성 잠금", @@ -250,6 +252,7 @@ "Script loaded. You can drag asset folders or data files directly here to bundle them.": "스크립트가 로드되었습니다. 에셋 폴더나 데이터 파일을 여기에 직접 끌어다 놓아 번들할 수 있습니다.", "Select .pfx / .p12 certificate file": ".pfx / .p12 인증서 파일 선택", "Select All": "모두 선택", + "Select Main Entry Script": "메인 진입 스크립트 선택", "Select Python Version to Download:": "다운로드할 Python 버전 선택:", "Select shared directory...": "공유 디렉터리 선택...", "Self-Signed Certificate (*.pfx)": "자체 서명 인증서 (*.pfx)", @@ -377,6 +380,7 @@ "[Syntax Error] Source code contains syntax errors, compilation aborted:\n - File: {file}\n - Type: {type}\n - Line: Line {line}\n - Detail: {desc}\n\nTip: Please ensure the source code runs locally before packaging.": "[Syntax Error] 소스 코드에 구문 오류가 있어 컴파일이 중단되었습니다:\n - 파일: {file}\n - 유형: {type}\n - 줄: {line}번째 줄\n - 세부 정보: {desc}\n\n팁: 패키징 전에 소스 코드가 로컬에서 실행되는지 확인하세요.", "[Syntax Error] Source code syntax parsing failed, build aborted:\n - File: {file}\n - Detail: {desc}\n\nTip: This is usually NOT a fault of the packaging tool.\nPlease ensure the [Build Python Version] you selected matches the version you used to [Write/Test the Code].\nUsing newer syntax (e.g., walrus operator :=, type unions |, match-case) in an older Python environment will trigger this error.\nWe recommend going to [Build Settings] -> [Engine] to switch to the correct Python version.": "[Syntax Error] 소스 코드 구문 분석에 실패하여 빌드가 중단되었습니다:\n - 파일: {file}\n - 세부 정보: {desc}\n\n팁: 이는 일반적으로 패키징 도구의 문제가 아닙니다.\n선택한 [빌드 Python 버전]이 코드를 [작성/테스트]할 때 사용한 버전과 일치하는지 확인하세요.\n이전 Python 환경에서 최신 구문(예: 바다코끼리 연산자 :=, 타입 유니온 |, match-case)을 사용하면 이 오류가 발생합니다.\n[빌드 설정] -> [엔진]으로 이동하여 올바른 Python 버전으로 전환하는 것이 좋습니다.", "[Syntax Error] Source code syntax parsing failed, build aborted:\n - File: {file}\n - Line: Line {line}\n - Detail: {desc}\n\nTip: This is usually NOT a fault of the packaging tool.\nPlease ensure the [Build Python Version] you selected matches the version you used to [Write/Test the Code].\nUsing newer syntax (e.g., walrus operator :=, type unions |, match-case) in an older Python environment will trigger this error.\nWe recommend going to [Build Settings] -> [Engine] to switch to the correct Python version.": "[Syntax Error] 소스 코드 구문 분석에 실패하여 빌드가 중단되었습니다:\n - 파일: {file}\n - 줄: {line}번째 줄\n - 세부 정보: {desc}\n\n팁: 이는 일반적으로 패키징 도구의 문제가 아닙니다.\n선택한 [빌드 Python 버전]이 코드를 [작성/테스트]할 때 사용한 버전과 일치하는지 확인하세요.\n이전 Python 환경에서 최신 구문(예: 바다코끼리 연산자 :=, 타입 유니온 |, match-case)을 사용하면 이 오류가 발생합니다.\n[빌드 설정] -> [엔진]에서 올바른 Python 버전으로 전환하는 것을 권장합니다.", + "[TIP] Script imports parent module '{mod}'. If build fails, try dragging the whole project folder here.": "[TIP] 스크립트가 상위 모듈 '{mod}'을(를) 가져옵니다. 빌드가 실패하면 전체 프로젝트 폴더를 여기로 끌어다 놓으세요.", "[WARN] 'multiprocessing' module detected. Ensure 'multiprocessing.freeze_support()' is called under 'if __name__ == \"__main__\":' to prevent infinite process loops (fork bombs).": "[WARN] 'multiprocessing' 모듈이 감지되었습니다. 무한 프로세스 루프(포크 폭탄)를 방지하려면 'if __name__ == \"__main__\":' 아래에서 'multiprocessing.freeze_support()'를 호출하세요.", "[WARN] AST Analysis Exception: {error}": "[WARN] AST 분석 예외: {error}", "[WARN] Command timeout (>{timeout}s)": "[WARN] 명령 시간 초과(>{timeout}초)", @@ -405,5 +409,6 @@ "[WARN] Target project is in a Cloud Sync directory (e.g. OneDrive/Dropbox). Cloud sync may temporarily lock build files.": "[WARN] 대상 프로젝트가 클라우드 동기화 디렉터리(예: OneDrive/Dropbox)에 있습니다. 클라우드 동기화로 인해 빌드 파일이 일시적으로 잠길 수 있습니다.", "[WARN] Timestamp server connection timed out, performing local fast signing...": "[WARN] 타임스탬프 서버 연결 시간이 초과되어 로컬 빠른 서명을 수행합니다...", "[WARN] Usage of '__file__' detected. In PyInstaller One-File mode, use 'sys._MEIPASS' to reliably locate bundled resource files!": "[WARN] '__file__' 사용이 감지되었습니다. PyInstaller 원파일 모드에서는 'sys._MEIPASS'를 사용하여 번들 리소스 파일을 안정적으로 찾으십시오!", - "\\nProgram execution completed, press Enter to exit...": "\\n프로그램 실행이 완료되었습니다. 종료하려면 Enter를 누르십시오..." + "\\nProgram execution completed, press Enter to exit...": "\\n프로그램 실행이 완료되었습니다. 종료하려면 Enter를 누르십시오...", + "Package Mapping & Remediation": "패키지 매핑 및 수정" } diff --git a/qpypack/locales/nl_NL.json b/qpypack/locales/nl_NL.json index 8af7bdc..0438b2c 100644 --- a/qpypack/locales/nl_NL.json +++ b/qpypack/locales/nl_NL.json @@ -87,6 +87,7 @@ "Description:": "Beschrijving:", "Desktop Application": "Desktoptoepassing", "Detailed Mode": "Gedetailleerde modus", + "Detected multiple entry scripts in project. Please select one to build:": "Meerdere entry-scripts gedetecteerd in het project. Selecteer er een om te bouwen:", "Directory": "Map", "Discovered via scanner ({count}): {pkgs}": "Gevonden via scanner ({count}): {pkgs}", "Disk space critically low: {free:.1f}GB < {min:.1f}GB": "Schijfruimte kritiek laag: {free:.1f}GB < {min:.1f}GB", @@ -148,6 +149,7 @@ "Leave blank to auto-search requirements.txt in current directory": "Laat leeg om automatisch requirements.txt in de huidige map te zoeken", "Legacy macOS Compatible": "Legacy macOS-compatibel", "Lite Mode (Smaller size)": "Lite-modus (kleiner formaat)", + "Loaded Project: {name} | Entry: {entry}": "Project geladen: {name} | Entry: {entry}", "Loaded: {filename}": "Geladen: {filename}", "Locally Detected Pythons": "Lokaal gedetecteerde Pythons", "Lock Core Dependencies": "Kernafhankelijkheden vergrendelen", @@ -250,6 +252,7 @@ "Script loaded. You can drag asset folders or data files directly here to bundle them.": "Script geladen. U kunt assetmappen of gegevensbestanden hier direct naartoe slepen om ze te bundelen.", "Select .pfx / .p12 certificate file": "Selecteer .pfx / .p12 certificaatbestand", "Select All": "Alles selecteren", + "Select Main Entry Script": "Selecteer hoofd-entry-script", "Select Python Version to Download:": "Selecteer Python-versie om te downloaden:", "Select shared directory...": "Selecteer gedeelde map...", "Self-Signed Certificate (*.pfx)": "Zelfondertekend certificaat (*.pfx)", @@ -377,6 +380,7 @@ "[Syntax Error] Source code contains syntax errors, compilation aborted:\n - File: {file}\n - Type: {type}\n - Line: Line {line}\n - Detail: {desc}\n\nTip: Please ensure the source code runs locally before packaging.": "[Syntax Error] Broncode bevat syntaxfouten, compilatie afgebroken:\n - Bestand: {file}\n - Type: {type}\n - Regel: Regel {line}\n - Detail: {desc}\n\nTip: Zorg ervoor dat de broncode lokaal werkt voordat u deze verpakt.", "[Syntax Error] Source code syntax parsing failed, build aborted:\n - File: {file}\n - Detail: {desc}\n\nTip: This is usually NOT a fault of the packaging tool.\nPlease ensure the [Build Python Version] you selected matches the version you used to [Write/Test the Code].\nUsing newer syntax (e.g., walrus operator :=, type unions |, match-case) in an older Python environment will trigger this error.\nWe recommend going to [Build Settings] -> [Engine] to switch to the correct Python version.": "[Syntax Error] Broncode-syntaxparsing mislukt, bouwen afgebroken:\n - Bestand: {file}\n - Detail: {desc}\n\nTip: Dit is meestal GEEN fout van het verpakkingsprogramma.\nZorg ervoor dat de [Bouw Python-versie] die u selecteert overeenkomt met de versie die u gebruikte om de code te [schrijven/testen].\nHet gebruik van nieuwere syntax (bijv. walrus-operator :=, type-unies |, match-case) in een oudere Python-omgeving zal deze fout veroorzaken.\nWe raden aan om naar [Bouwinstellingen] -> [Engine] te gaan om over te schakelen naar de juiste Python-versie.", "[Syntax Error] Source code syntax parsing failed, build aborted:\n - File: {file}\n - Line: Line {line}\n - Detail: {desc}\n\nTip: This is usually NOT a fault of the packaging tool.\nPlease ensure the [Build Python Version] you selected matches the version you used to [Write/Test the Code].\nUsing newer syntax (e.g., walrus operator :=, type unions |, match-case) in an older Python environment will trigger this error.\nWe recommend going to [Build Settings] -> [Engine] to switch to the correct Python version.": "[Syntax Error] Parsen van broncodesyntax mislukt, build afgebroken:\n - Bestand: {file}\n - Regel: Regel {line}\n - Detail: {desc}\n\nTip: Dit is meestal GEEN fout van het verpakkingsprogramma.\nZorg ervoor dat de [Build Python-versie] die u selecteert overeenkomt met de versie die u gebruikte om de code te [schrijven/testen].\nHet gebruik van nieuwere syntax (bijv. walrus-operator :=, type-unies |, match-case) in een oudere Python-omgeving veroorzaakt deze fout.\nWe raden aan om naar [Build-instellingen] -> [Engine] te gaan om over te schakelen naar de juiste Python-versie.", + "[TIP] Script imports parent module '{mod}'. If build fails, try dragging the whole project folder here.": "[TIP] Het script importeert de bovenliggende module '{mod}'. Als de build mislukt, probeer dan de hele projectmap hierheen te slepen.", "[WARN] 'multiprocessing' module detected. Ensure 'multiprocessing.freeze_support()' is called under 'if __name__ == \"__main__\":' to prevent infinite process loops (fork bombs).": "[WARN] 'multiprocessing'-module gedetecteerd. Zorg ervoor dat 'multiprocessing.freeze_support()' wordt aangeroepen onder 'if __name__ == \"__main__\":' om oneindige processlussen (fork-bommen) te voorkomen.", "[WARN] AST Analysis Exception: {error}": "[WARN] AST-analyse-uitzondering: {error}", "[WARN] Command timeout (>{timeout}s)": "[WARN] Commandotime-out (>{timeout}s)", @@ -405,5 +409,6 @@ "[WARN] Target project is in a Cloud Sync directory (e.g. OneDrive/Dropbox). Cloud sync may temporarily lock build files.": "[WARN] Doelproject bevindt zich in een Cloud Sync-map (bijv. OneDrive/Dropbox). Cloud sync kan buildbestanden tijdelijk vergrendelen.", "[WARN] Timestamp server connection timed out, performing local fast signing...": "[WARN] Tijdstempelserververbinding is verlopen, lokale snelle ondertekening wordt uitgevoerd...", "[WARN] Usage of '__file__' detected. In PyInstaller One-File mode, use 'sys._MEIPASS' to reliably locate bundled resource files!": "[WARN] Gebruik van '__file__' gedetecteerd. In PyInstaller One-File modus, gebruik 'sys._MEIPASS' om gebundelde bronbestanden betrouwbaar te lokaliseren!", - "\\nProgram execution completed, press Enter to exit...": "\\nProgramma-uitvoering voltooid, druk op Enter om af te sluiten..." + "\\nProgram execution completed, press Enter to exit...": "\\nProgramma-uitvoering voltooid, druk op Enter om af te sluiten...", + "Package Mapping & Remediation": "Pakkettoewijzing & Herstel" } diff --git a/qpypack/locales/pl_PL.json b/qpypack/locales/pl_PL.json index 4fd010b..5d484be 100644 --- a/qpypack/locales/pl_PL.json +++ b/qpypack/locales/pl_PL.json @@ -87,6 +87,7 @@ "Description:": "Opis:", "Desktop Application": "Aplikacja desktopowa", "Detailed Mode": "Tryb szczegółowy", + "Detected multiple entry scripts in project. Please select one to build:": "Wykryto wiele skryptów wejściowych w projekcie. Wybierz jeden do zbudowania:", "Directory": "Katalog", "Discovered via scanner ({count}): {pkgs}": "Wykryto przez skaner ({count}): {pkgs}", "Disk space critically low: {free:.1f}GB < {min:.1f}GB": "Krytycznie mało miejsca na dysku: {free:.1f}GB < {min:.1f}GB", @@ -148,6 +149,7 @@ "Leave blank to auto-search requirements.txt in current directory": "Pozostaw puste, aby automatycznie wyszukać requirements.txt w bieżącym katalogu", "Legacy macOS Compatible": "Zgodność z legacy macOS", "Lite Mode (Smaller size)": "Tryb lekki (mniejszy rozmiar)", + "Loaded Project: {name} | Entry: {entry}": "Załadowano projekt: {name} | Wejście: {entry}", "Loaded: {filename}": "Załadowano: {filename}", "Locally Detected Pythons": "Lokalnie wykryte Pythony", "Lock Core Dependencies": "Zablokuj podstawowe zależności", @@ -250,6 +252,7 @@ "Script loaded. You can drag asset folders or data files directly here to bundle them.": "Skrypt załadowany. Możesz przeciągnąć foldery zasobów lub pliki danych bezpośrednio tutaj, aby je spakować.", "Select .pfx / .p12 certificate file": "Wybierz plik certyfikatu .pfx / .p12", "Select All": "Zaznacz wszystko", + "Select Main Entry Script": "Wybierz główny skrypt wejściowy", "Select Python Version to Download:": "Wybierz wersję Pythona do pobrania:", "Select shared directory...": "Wybierz katalog współdzielony...", "Self-Signed Certificate (*.pfx)": "Certyfikat self-signed (*.pfx)", @@ -377,6 +380,7 @@ "[Syntax Error] Source code contains syntax errors, compilation aborted:\n - File: {file}\n - Type: {type}\n - Line: Line {line}\n - Detail: {desc}\n\nTip: Please ensure the source code runs locally before packaging.": "[Syntax Error] Kod źródłowy zawiera błędy składni, kompilacja przerwana:\n - Plik: {file}\n - Typ: {type}\n - Linia: Linia {line}\n - Szczegóły: {desc}\n\nWskazówka: Upewnij się, że kod źródłowy działa lokalnie przed pakowaniem.", "[Syntax Error] Source code syntax parsing failed, build aborted:\n - File: {file}\n - Detail: {desc}\n\nTip: This is usually NOT a fault of the packaging tool.\nPlease ensure the [Build Python Version] you selected matches the version you used to [Write/Test the Code].\nUsing newer syntax (e.g., walrus operator :=, type unions |, match-case) in an older Python environment will trigger this error.\nWe recommend going to [Build Settings] -> [Engine] to switch to the correct Python version.": "[Syntax Error] Analiza składni kodu źródłowego nie powiodła się, budowanie przerwane:\n - Plik: {file}\n - Szczegóły: {desc}\n\nWskazówka: To zwykle NIE jest wina narzędzia do pakowania.\nUpewnij się, że wybrana [Wersja Pythona do budowania] odpowiada wersji, której używasz do [Pisania/Testowania kodu].\nUżycie nowszej składni (np. operator morsa :=, unie typów |, match-case) w starszym środowisku Pythona spowoduje ten błąd.\nZalecamy przejście do [Ustawienia budowania] -> [Silnik], aby przełączyć na właściwą wersję Pythona.", "[Syntax Error] Source code syntax parsing failed, build aborted:\n - File: {file}\n - Line: Line {line}\n - Detail: {desc}\n\nTip: This is usually NOT a fault of the packaging tool.\nPlease ensure the [Build Python Version] you selected matches the version you used to [Write/Test the Code].\nUsing newer syntax (e.g., walrus operator :=, type unions |, match-case) in an older Python environment will trigger this error.\nWe recommend going to [Build Settings] -> [Engine] to switch to the correct Python version.": "[Syntax Error] Analiza składni kodu źródłowego nie powiodła się, budowanie przerwane:\n - Plik: {file}\n - Linia: Linia {line}\n - Szczegóły: {desc}\n\nWskazówka: To zwykle NIE jest wina narzędzia do pakowania.\nUpewnij się, że wybrana [Wersja Pythona do budowania] odpowiada wersji użytej do [Pisania/Testowania kodu].\nUżycie nowszej składni (np. operator morsa :=, unie typów |, match-case) w starszym środowisku Python spowoduje ten błąd.\nZalecamy przejście do [Ustawienia budowania] -> [Silnik], aby przełączyć się na właściwą wersję Pythona.", + "[TIP] Script imports parent module '{mod}'. If build fails, try dragging the whole project folder here.": "[TIP] Skrypt importuje moduł nadrzędny '{mod}'. Jeśli budowanie nie powiedzie się, spróbuj przeciągnąć cały folder projektu tutaj.", "[WARN] 'multiprocessing' module detected. Ensure 'multiprocessing.freeze_support()' is called under 'if __name__ == \"__main__\":' to prevent infinite process loops (fork bombs).": "[WARN] Wykryto moduł 'multiprocessing'. Upewnij się, że 'multiprocessing.freeze_support()' jest wywoływane w bloku 'if __name__ == \"__main__\":', aby zapobiec nieskończonym pętlom procesów (bomby fork).", "[WARN] AST Analysis Exception: {error}": "[WARN] Wyjątek analizy AST: {error}", "[WARN] Command timeout (>{timeout}s)": "[WARN] Przekroczono limit czasu polecenia (>{timeout}s)", @@ -405,5 +409,6 @@ "[WARN] Target project is in a Cloud Sync directory (e.g. OneDrive/Dropbox). Cloud sync may temporarily lock build files.": "[WARN] Projekt docelowy znajduje się w katalogu synchronizacji chmurowej (np. OneDrive/Dropbox). Synchronizacja chmurowa może tymczasowo blokować pliki budowania.", "[WARN] Timestamp server connection timed out, performing local fast signing...": "[WARN] Przekroczono limit czasu połączenia z serwerem znaczników czasu, wykonywanie lokalnego szybkiego podpisywania...", "[WARN] Usage of '__file__' detected. In PyInstaller One-File mode, use 'sys._MEIPASS' to reliably locate bundled resource files!": "[WARN] Wykryto użycie '__file__'. W trybie jednego pliku PyInstaller, użyj 'sys._MEIPASS', aby niezawodnie zlokalizować dołączone pliki zasobów!", - "\\nProgram execution completed, press Enter to exit...": "\\nWykonywanie programu zakończone, naciśnij Enter, aby wyjść..." + "\\nProgram execution completed, press Enter to exit...": "\\nWykonywanie programu zakończone, naciśnij Enter, aby wyjść...", + "Package Mapping & Remediation": "Mapowanie pakietów i naprawa" } diff --git a/qpypack/locales/pt_BR.json b/qpypack/locales/pt_BR.json index a809673..91b7d52 100644 --- a/qpypack/locales/pt_BR.json +++ b/qpypack/locales/pt_BR.json @@ -87,6 +87,7 @@ "Description:": "Descrição:", "Desktop Application": "Aplicativo de Desktop", "Detailed Mode": "Modo Detalhado", + "Detected multiple entry scripts in project. Please select one to build:": "Detectados múltiplos scripts de entrada no projeto. Selecione um para compilar:", "Directory": "Diretório", "Discovered via scanner ({count}): {pkgs}": "Descoberto via scanner ({count}): {pkgs}", "Disk space critically low: {free:.1f}GB < {min:.1f}GB": "Espaço em disco criticamente baixo: {free:.1f}GB < {min:.1f}GB", @@ -148,6 +149,7 @@ "Leave blank to auto-search requirements.txt in current directory": "Deixe em branco para procurar automaticamente requirements.txt no diretório atual", "Legacy macOS Compatible": "Compatível com macOS Legado", "Lite Mode (Smaller size)": "Modo Leve (Tamanho menor)", + "Loaded Project: {name} | Entry: {entry}": "Projeto carregado: {name} | Entrada: {entry}", "Loaded: {filename}": "Carregado: {filename}", "Locally Detected Pythons": "Pythons Detectados Localmente", "Lock Core Dependencies": "Bloquear Dependências Principais", @@ -250,6 +252,7 @@ "Script loaded. You can drag asset folders or data files directly here to bundle them.": "Script carregado. Você pode arrastar pastas de assets ou arquivos de dados diretamente aqui para empacotá-los.", "Select .pfx / .p12 certificate file": "Selecionar arquivo de certificado .pfx / .p12", "Select All": "Selecionar Tudo", + "Select Main Entry Script": "Selecionar Script de Entrada Principal", "Select Python Version to Download:": "Selecione a Versão do Python para Baixar:", "Select shared directory...": "Selecionar diretório compartilhado...", "Self-Signed Certificate (*.pfx)": "Certificado Autoassinado (*.pfx)", @@ -377,6 +380,7 @@ "[Syntax Error] Source code contains syntax errors, compilation aborted:\n - File: {file}\n - Type: {type}\n - Line: Line {line}\n - Detail: {desc}\n\nTip: Please ensure the source code runs locally before packaging.": "[Syntax Error] O código-fonte contém erros de sintaxe, compilação abortada:\n - Arquivo: {file}\n - Tipo: {type}\n - Linha: Linha {line}\n - Detalhe: {desc}\n\nDica: Certifique-se de que o código-fonte seja executado localmente antes de empacotar.", "[Syntax Error] Source code syntax parsing failed, build aborted:\n - File: {file}\n - Detail: {desc}\n\nTip: This is usually NOT a fault of the packaging tool.\nPlease ensure the [Build Python Version] you selected matches the version you used to [Write/Test the Code].\nUsing newer syntax (e.g., walrus operator :=, type unions |, match-case) in an older Python environment will trigger this error.\nWe recommend going to [Build Settings] -> [Engine] to switch to the correct Python version.": "[Syntax Error] Falha na análise de sintaxe do código-fonte, build abortado:\n - Arquivo: {file}\n - Detalhe: {desc}\n\nDica: Isso geralmente NÃO é um defeito da ferramenta de empacotamento.\nCertifique-se de que a [Versão do Python de Build] selecionada corresponde à versão usada para [Escrever/Testar o Código].\nUsar sintaxe mais nova (ex.: operador walrus :=, uniões de tipos |, match-case) em um ambiente Python mais antigo acionará este erro.\nRecomendamos ir para [Configurações de Build] -> [Mecanismo] para mudar para a versão correta do Python.", "[Syntax Error] Source code syntax parsing failed, build aborted:\n - File: {file}\n - Line: Line {line}\n - Detail: {desc}\n\nTip: This is usually NOT a fault of the packaging tool.\nPlease ensure the [Build Python Version] you selected matches the version you used to [Write/Test the Code].\nUsing newer syntax (e.g., walrus operator :=, type unions |, match-case) in an older Python environment will trigger this error.\nWe recommend going to [Build Settings] -> [Engine] to switch to the correct Python version.": "[Syntax Error] Falha na análise de sintaxe do código-fonte, compilação abortada:\n - Arquivo: {file}\n - Linha: Linha {line}\n - Detalhe: {desc}\n\nDica: Isso geralmente NÃO é uma falha da ferramenta de empacotamento.\nCertifique-se de que a [Versão do Python de Compilação] selecionada corresponda à versão usada para [Escrever/Testar o Código].\nO uso de sintaxe mais recente (por exemplo, operador walrus :=, uniões de tipos |, match-case) em um ambiente Python mais antigo acionará este erro.\nRecomendamos ir para [Configurações de Compilação] -> [Mecanismo] para alternar para a versão correta do Python.", + "[TIP] Script imports parent module '{mod}'. If build fails, try dragging the whole project folder here.": "[TIP] O script importa o módulo pai '{mod}'. Se a compilação falhar, tente arrastar a pasta inteira do projeto para cá.", "[WARN] 'multiprocessing' module detected. Ensure 'multiprocessing.freeze_support()' is called under 'if __name__ == \"__main__\":' to prevent infinite process loops (fork bombs).": "[WARN] Módulo 'multiprocessing' detectado. Certifique-se de que 'multiprocessing.freeze_support()' seja chamado sob 'if __name__ == \"__main__\":' para evitar loops infinitos de processos (fork bombs).", "[WARN] AST Analysis Exception: {error}": "[WARN] Exceção na análise AST: {error}", "[WARN] Command timeout (>{timeout}s)": "[WARN] Tempo limite do comando excedido (>{timeout}s)", @@ -405,5 +409,6 @@ "[WARN] Target project is in a Cloud Sync directory (e.g. OneDrive/Dropbox). Cloud sync may temporarily lock build files.": "[WARN] O projeto alvo está em um diretório de sincronização em nuvem (ex.: OneDrive/Dropbox). A sincronização em nuvem pode bloquear temporariamente os arquivos de compilação.", "[WARN] Timestamp server connection timed out, performing local fast signing...": "[WARN] O servidor de carimbo de tempo expirou, realizando assinatura local rápida...", "[WARN] Usage of '__file__' detected. In PyInstaller One-File mode, use 'sys._MEIPASS' to reliably locate bundled resource files!": "[WARN] Uso de '__file__' detectado. No modo One-File do PyInstaller, use 'sys._MEIPASS' para localizar com confiabilidade os arquivos de recursos empacotados!", - "\\nProgram execution completed, press Enter to exit...": "\\nExecução do programa concluída, pressione Enter para sair..." + "\\nProgram execution completed, press Enter to exit...": "\\nExecução do programa concluída, pressione Enter para sair...", + "Package Mapping & Remediation": "Mapeamento de pacotes e correção" } diff --git a/qpypack/locales/ru_RU.json b/qpypack/locales/ru_RU.json index e43ec8e..bae180d 100644 --- a/qpypack/locales/ru_RU.json +++ b/qpypack/locales/ru_RU.json @@ -87,6 +87,7 @@ "Description:": "Описание:", "Desktop Application": "Настольное приложение", "Detailed Mode": "Подробный режим", + "Detected multiple entry scripts in project. Please select one to build:": "В проекте обнаружено несколько входных скриптов. Выберите один для сборки:", "Directory": "Каталог", "Discovered via scanner ({count}): {pkgs}": "Обнаружено сканером ({count}): {pkgs}", "Disk space critically low: {free:.1f}GB < {min:.1f}GB": "Критически мало места на диске: {free:.1f}ГБ < {min:.1f}ГБ", @@ -148,6 +149,7 @@ "Leave blank to auto-search requirements.txt in current directory": "Оставьте пустым для автоматического поиска requirements.txt в текущем каталоге", "Legacy macOS Compatible": "Совместимость с устаревшими macOS", "Lite Mode (Smaller size)": "Облегченный режим (меньший размер)", + "Loaded Project: {name} | Entry: {entry}": "Загружен проект: {name} | Вход: {entry}", "Loaded: {filename}": "Загружено: {filename}", "Locally Detected Pythons": "Локально обнаруженные Python", "Lock Core Dependencies": "Заблокировать основные зависимости", @@ -250,6 +252,7 @@ "Script loaded. You can drag asset folders or data files directly here to bundle them.": "Скрипт загружен. Вы можете перетащить папки с ресурсами или файлы данных прямо сюда, чтобы включить их в пакет.", "Select .pfx / .p12 certificate file": "Выберите файл сертификата .pfx / .p12", "Select All": "Выбрать все", + "Select Main Entry Script": "Выберите основной входной скрипт", "Select Python Version to Download:": "Выберите версию Python для загрузки:", "Select shared directory...": "Выберите общий каталог...", "Self-Signed Certificate (*.pfx)": "Самозаверяющий сертификат (*.pfx)", @@ -377,6 +380,7 @@ "[Syntax Error] Source code contains syntax errors, compilation aborted:\n - File: {file}\n - Type: {type}\n - Line: Line {line}\n - Detail: {desc}\n\nTip: Please ensure the source code runs locally before packaging.": "[Syntax Error] Исходный код содержит синтаксические ошибки, компиляция прервана:\n - Файл: {file}\n - Тип: {type}\n - Строка: строка {line}\n - Подробности: {desc}\n\nСовет. Убедитесь, что исходный код запускается локально перед упаковкой.", "[Syntax Error] Source code syntax parsing failed, build aborted:\n - File: {file}\n - Detail: {desc}\n\nTip: This is usually NOT a fault of the packaging tool.\nPlease ensure the [Build Python Version] you selected matches the version you used to [Write/Test the Code].\nUsing newer syntax (e.g., walrus operator :=, type unions |, match-case) in an older Python environment will trigger this error.\nWe recommend going to [Build Settings] -> [Engine] to switch to the correct Python version.": "[Syntax Error] Не удалось выполнить синтаксический анализ исходного кода, сборка прервана:\n - Файл: {file}\n - Подробности: {desc}\n\nСовет: Обычно это не вина инструмента упаковки.\nУбедитесь, что выбранная [Версия Python для сборки] соответствует версии, которую вы использовали для [Написания/Тестирования кода].\nИспользование нового синтаксиса (например, оператора моржа :=, объединения типов |, match-case) в более старой среде Python вызовет эту ошибку.\nРекомендуем перейти в [Настройки сборки] -> [Движок], чтобы переключиться на правильную версию Python.", "[Syntax Error] Source code syntax parsing failed, build aborted:\n - File: {file}\n - Line: Line {line}\n - Detail: {desc}\n\nTip: This is usually NOT a fault of the packaging tool.\nPlease ensure the [Build Python Version] you selected matches the version you used to [Write/Test the Code].\nUsing newer syntax (e.g., walrus operator :=, type unions |, match-case) in an older Python environment will trigger this error.\nWe recommend going to [Build Settings] -> [Engine] to switch to the correct Python version.": "[Syntax Error] Не удалось выполнить синтаксический анализ исходного кода, сборка прервана:\n - Файл: {file}\n - Строка: строка {line}\n - Подробности: {desc}\n\nСовет. Обычно это НЕ ошибка инструмента упаковки.\nУбедитесь, что выбранная [Версия Python для сборки] соответствует версии, которую вы использовали для [Написания/Тестирования кода].\nИспользование нового синтаксиса (например, оператор моржа :=, объединение типов |, match-case) в более старой среде Python вызовет эту ошибку.\nРекомендуем перейти в [Настройки сборки] -> [Движок], чтобы переключиться на правильную версию Python.", + "[TIP] Script imports parent module '{mod}'. If build fails, try dragging the whole project folder here.": "[TIP] Скрипт импортирует родительский модуль '{mod}'. Если сборка не удается, попробуйте перетащить сюда всю папку проекта.", "[WARN] 'multiprocessing' module detected. Ensure 'multiprocessing.freeze_support()' is called under 'if __name__ == \"__main__\":' to prevent infinite process loops (fork bombs).": "[WARN] Обнаружен модуль 'multiprocessing'. Убедитесь, что 'multiprocessing.freeze_support()' вызывается внутри 'if __name__ == \"__main__\":', чтобы предотвратить бесконечные циклы процессов (форк-бомбы).", "[WARN] AST Analysis Exception: {error}": "[WARN] Исключение при анализе AST: {error}", "[WARN] Command timeout (>{timeout}s)": "[WARN] Тайм-аут команды (>{timeout}с)", @@ -405,5 +409,6 @@ "[WARN] Target project is in a Cloud Sync directory (e.g. OneDrive/Dropbox). Cloud sync may temporarily lock build files.": "[WARN] Целевой проект находится в каталоге облачной синхронизации (например, OneDrive/Dropbox). Облачная синхронизация может временно блокировать файлы сборки.", "[WARN] Timestamp server connection timed out, performing local fast signing...": "[WARN] Истекло время ожидания соединения с сервером меток времени, выполняется локальная быстрая подпись...", "[WARN] Usage of '__file__' detected. In PyInstaller One-File mode, use 'sys._MEIPASS' to reliably locate bundled resource files!": "[WARN] Обнаружено использование '__file__'. В однофайловом режиме PyInstaller используйте 'sys._MEIPASS' для надежного поиска встроенных файлов ресурсов!", - "\\nProgram execution completed, press Enter to exit...": "\\nВыполнение программы завершено, нажмите Enter для выхода..." + "\\nProgram execution completed, press Enter to exit...": "\\nВыполнение программы завершено, нажмите Enter для выхода...", + "Package Mapping & Remediation": "Сопоставление пакетов и исправление" } diff --git a/qpypack/locales/th_TH.json b/qpypack/locales/th_TH.json index efe94aa..64467fc 100644 --- a/qpypack/locales/th_TH.json +++ b/qpypack/locales/th_TH.json @@ -87,6 +87,7 @@ "Description:": "คำอธิบาย:", "Desktop Application": "แอปพลิเคชันเดสก์ท็อป", "Detailed Mode": "โหมดรายละเอียด", + "Detected multiple entry scripts in project. Please select one to build:": "ตรวจพบสคริปต์ entry หลายตัวในโปรเจกต์ โปรดเลือกหนึ่งรายการเพื่อสร้าง:", "Directory": "ไดเรกทอรี", "Discovered via scanner ({count}): {pkgs}": "ค้นพบผ่านสแกนเนอร์ ({count}): {pkgs}", "Disk space critically low: {free:.1f}GB < {min:.1f}GB": "พื้นที่ดิสก์เหลือน้อยมาก: {free:.1f}GB < {min:.1f}GB", @@ -148,6 +149,7 @@ "Leave blank to auto-search requirements.txt in current directory": "เว้นว่างไว้เพื่อค้นหา requirements.txt ในไดเรกทอรีปัจจุบันอัตโนมัติ", "Legacy macOS Compatible": "เข้ากันได้กับ macOS รุ่นเก่า", "Lite Mode (Smaller size)": "โหมดไลต์ (ขนาดเล็กลง)", + "Loaded Project: {name} | Entry: {entry}": "โหลดโปรเจกต์: {name} | Entry: {entry}", "Loaded: {filename}": "โหลดแล้ว: {filename}", "Locally Detected Pythons": "Python ที่ตรวจพบในเครื่อง", "Lock Core Dependencies": "ล็อก Core Dependencies", @@ -250,6 +252,7 @@ "Script loaded. You can drag asset folders or data files directly here to bundle them.": "โหลดสคริปต์แล้ว คุณสามารถลากโฟลเดอร์ทรัพยากรหรือไฟล์ข้อมูลมาที่นี่เพื่อรวมเข้าด้วยกัน", "Select .pfx / .p12 certificate file": "เลือกไฟล์ใบรับรอง .pfx / .p12", "Select All": "เลือกทั้งหมด", + "Select Main Entry Script": "เลือกสคริปต์ Entry หลัก", "Select Python Version to Download:": "เลือกเวอร์ชัน Python ที่จะดาวน์โหลด:", "Select shared directory...": "เลือกไดเรกทอรีที่ใช้ร่วมกัน...", "Self-Signed Certificate (*.pfx)": "ใบรับรองที่เซ็นชื่อเอง (*.pfx)", @@ -375,6 +378,7 @@ "[SUCCESS] Compilation completed, output path: {path}": "[SUCCESS] การคอมไพล์เสร็จสมบูรณ์ พาธเอาต์พุต: {path}", "[SUCCESS] Digital signature applied successfully!": "[SUCCESS] ใช้ลายเซ็นดิจิทัลสำเร็จ!", "[Syntax Error] Source code contains syntax errors, compilation aborted:\n - File: {file}\n - Type: {type}\n - Line: Line {line}\n - Detail: {desc}\n\nTip: Please ensure the source code runs locally before packaging.": "[Syntax Error] ซอร์สโค้ดมีข้อผิดพลาดทางไวยากรณ์ การคอมไพล์ถูกยกเลิก:\n - ไฟล์: {file}\n - ประเภท: {type}\n - บรรทัด: บรรทัดที่ {line}\n - รายละเอียด: {desc}\n\nเคล็ดลับ: โปรดตรวจสอบให้แน่ใจว่าซอร์สโค้ดทำงานได้ในเครื่องก่อนแพ็กเกจ", + "[TIP] Script imports parent module '{mod}'. If build fails, try dragging the whole project folder here.": "[TIP] สคริปต์นำเข้าโมดูลหลัก '{mod}' หากการสร้างล้มเหลว ให้ลองลากโฟลเดอร์โปรเจกต์ทั้งหมดมาที่นี่", "[WARN] 'multiprocessing' module detected. Ensure 'multiprocessing.freeze_support()' is called under 'if __name__ == \"__main__\":' to prevent infinite process loops (fork bombs).": "[WARN] ตรวจพบโมดูล 'multiprocessing' โปรดตรวจสอบให้แน่ใจว่าได้เรียก 'multiprocessing.freeze_support()' ภายใต้ 'if __name__ == \"__main__\":' เพื่อป้องกันการวนซ้ำของกระบวนการไม่รู้จบ (fork bombs)", "[WARN] AST Analysis Exception: {error}": "[WARN] ข้อยกเว้นการวิเคราะห์ AST: {error}", "[WARN] Command timeout (>{timeout}s)": "[WARN] คำสั่งหมดเวลา (> {timeout} วินาที)", @@ -403,5 +407,8 @@ "[WARN] Target project is in a Cloud Sync directory (e.g. OneDrive/Dropbox). Cloud sync may temporarily lock build files.": "[WARN] โปรเจกต์เป้าหมายอยู่ในไดเรกทอรี Cloud Sync (เช่น OneDrive/Dropbox) การซิงก์คลาวด์อาจล็อกไฟล์ build ชั่วคราว", "[WARN] Timestamp server connection timed out, performing local fast signing...": "[WARN] การเชื่อมต่อกับเซิร์ฟเวอร์ timestamp หมดเวลา กำลังลงนามแบบเร็วในเครื่อง...", "[WARN] Usage of '__file__' detected. In PyInstaller One-File mode, use 'sys._MEIPASS' to reliably locate bundled resource files!": "[WARN] ตรวจพบการใช้ '__file__' ในโหมด One-File ของ PyInstaller ควรใช้ 'sys._MEIPASS' เพื่อค้นหาไฟล์ทรัพยากรที่รวมอยู่ได้อย่างน่าเชื่อถือ!", - "\\nProgram execution completed, press Enter to exit...": "\\nการทำงานของโปรแกรมเสร็จสิ้น กด Enter เพื่อออก..." + "\\nProgram execution completed, press Enter to exit...": "\\nการทำงานของโปรแกรมเสร็จสิ้น กด Enter เพื่อออก...", + "Package Mapping & Remediation": "การจับคู่แพ็กเกจและการแก้ไข", + "[Syntax Error] Source code syntax parsing failed, build aborted:\n - File: {file}\n - Detail: {desc}\n\nTip: This is usually NOT a fault of the packaging tool.\nPlease ensure the [Build Python Version] you selected matches the version you used to [Write/Test the Code].\nUsing newer syntax (e.g., walrus operator :=, type unions |, match-case) in an older Python environment will trigger this error.\nWe recommend going to [Build Settings] -> [Engine] to switch to the correct Python version.": "[Syntax Error] Source code syntax parsing failed, build aborted:\n - File: {file}\n - Detail: {desc}\n\nTip: This is usually NOT a fault of the packaging tool.\nPlease ensure the [Build Python Version] you selected matches the version you used to [Write/Test the Code].\nUsing newer syntax (e.g., walrus operator :=, type unions |, match-case) in an older Python environment will trigger this error.\nWe recommend going to [Build Settings] -> [Engine] to switch to the correct Python version.", + "[Syntax Error] Source code syntax parsing failed, build aborted:\n - File: {file}\n - Line: Line {line}\n - Detail: {desc}\n\nTip: This is usually NOT a fault of the packaging tool.\nPlease ensure the [Build Python Version] you selected matches the version you used to [Write/Test the Code].\nUsing newer syntax (e.g., walrus operator :=, type unions |, match-case) in an older Python environment will trigger this error.\nWe recommend going to [Build Settings] -> [Engine] to switch to the correct Python version.": "[Syntax Error] Source code syntax parsing failed, build aborted:\n - File: {file}\n - Line: Line {line}\n - Detail: {desc}\n\nTip: This is usually NOT a fault of the packaging tool.\nPlease ensure the [Build Python Version] you selected matches the version you used to [Write/Test the Code].\nUsing newer syntax (e.g., walrus operator :=, type unions |, match-case) in an older Python environment will trigger this error.\nWe recommend going to [Build Settings] -> [Engine] to switch to the correct Python version." } diff --git a/qpypack/locales/tr_TR.json b/qpypack/locales/tr_TR.json index eeb98ef..c9d5430 100644 --- a/qpypack/locales/tr_TR.json +++ b/qpypack/locales/tr_TR.json @@ -87,6 +87,7 @@ "Description:": "Açıklama:", "Desktop Application": "Masaüstü Uygulaması", "Detailed Mode": "Ayrıntılı Mod", + "Detected multiple entry scripts in project. Please select one to build:": "Projede birden fazla giriş betiği algılandı. Lütfen derlemek için birini seçin:", "Directory": "Dizin", "Discovered via scanner ({count}): {pkgs}": "Tarayıcıyla keşfedildi ({count}): {pkgs}", "Disk space critically low: {free:.1f}GB < {min:.1f}GB": "Disk alanı kritik düzeyde düşük: {free:.1f}GB < {min:.1f}GB", @@ -148,6 +149,7 @@ "Leave blank to auto-search requirements.txt in current directory": "Geçerli dizinde requirements.txt dosyasını otomatik aramak için boş bırakın", "Legacy macOS Compatible": "Eski macOS Uyumlu", "Lite Mode (Smaller size)": "Hafif Mod (Daha küçük boyut)", + "Loaded Project: {name} | Entry: {entry}": "Yüklenen Proje: {name} | Giriş: {entry}", "Loaded: {filename}": "Yüklendi: {filename}", "Locally Detected Pythons": "Yerel Olarak Algılanan Python'lar", "Lock Core Dependencies": "Çekirdek Bağımlılıkları Kilitle", @@ -250,6 +252,7 @@ "Script loaded. You can drag asset folders or data files directly here to bundle them.": "Betik yüklendi. Varlık klasörlerini veya veri dosyalarını doğrudan buraya sürükleyerek paketleyebilirsiniz.", "Select .pfx / .p12 certificate file": ".pfx / .p12 sertifika dosyası seçin", "Select All": "Tümünü Seç", + "Select Main Entry Script": "Ana Giriş Betiğini Seçin", "Select Python Version to Download:": "İndirilecek Python Sürümünü Seçin:", "Select shared directory...": "Paylaşılan dizini seç...", "Self-Signed Certificate (*.pfx)": "Kendi Kendine İmzalı Sertifika (*.pfx)", @@ -377,6 +380,7 @@ "[Syntax Error] Source code contains syntax errors, compilation aborted:\n - File: {file}\n - Type: {type}\n - Line: Line {line}\n - Detail: {desc}\n\nTip: Please ensure the source code runs locally before packaging.": "[Syntax Error] Kaynak kod sözdizimi hataları içeriyor, derleme iptal edildi:\n - Dosya: {file}\n - Tür: {type}\n - Satır: {line}. satır\n - Ayrıntı: {desc}\n\nİpucu: Paketlemeden önce kaynak kodun yerel olarak çalıştığından emin olun.", "[Syntax Error] Source code syntax parsing failed, build aborted:\n - File: {file}\n - Detail: {desc}\n\nTip: This is usually NOT a fault of the packaging tool.\nPlease ensure the [Build Python Version] you selected matches the version you used to [Write/Test the Code].\nUsing newer syntax (e.g., walrus operator :=, type unions |, match-case) in an older Python environment will trigger this error.\nWe recommend going to [Build Settings] -> [Engine] to switch to the correct Python version.": "[Syntax Error] Kaynak kod sözdizimi ayrıştırması başarısız oldu, derleme iptal edildi:\n - Dosya: {file}\n - Ayrıntı: {desc}\n\nİpucu: Bu genellikle paketleme aracının hatası değildir.\nSeçtiğiniz [Derleme Python Sürümü]'nün, kodu [Yazarken/Test Ederken] kullandığınız sürümle eşleştiğinden emin olun.\nDaha yeni sözdizimi (ör. walrus operatörü :=, tip birleşimleri |, match-case) daha eski bir Python ortamında kullanılırsa bu hata tetiklenir.\n[Derleme Ayarları] -> [Motor] bölümünden doğru Python sürümüne geçmenizi öneririz.", "[Syntax Error] Source code syntax parsing failed, build aborted:\n - File: {file}\n - Line: Line {line}\n - Detail: {desc}\n\nTip: This is usually NOT a fault of the packaging tool.\nPlease ensure the [Build Python Version] you selected matches the version you used to [Write/Test the Code].\nUsing newer syntax (e.g., walrus operator :=, type unions |, match-case) in an older Python environment will trigger this error.\nWe recommend going to [Build Settings] -> [Engine] to switch to the correct Python version.": "[Syntax Error] Kaynak kod sözdizimi ayrıştırılamadı, derleme iptal edildi:\n - Dosya: {file}\n - Satır: {line}. satır\n - Ayrıntı: {desc}\n\nİpucu: Bu genellikle paketleme aracının hatası DEĞİLDİR.\nSeçtiğiniz [Derleme Python Sürümü] ile [Kodu Yazarken/Test Ederken] kullandığınız sürümün eşleştiğinden emin olun.\nDaha yeni sözdizimi (ör. mors operatörü :=, tür birleşimleri |, match-case) kullanmak eski bir Python ortamında bu hatayı tetikler.\n[Derleme Ayarları] -> [Motor] bölümünden doğru Python sürümüne geçmenizi öneririz.", + "[TIP] Script imports parent module '{mod}'. If build fails, try dragging the whole project folder here.": "[TIP] Betik üst modülü '{mod}' içe aktarıyor. Derleme başarısız olursa, tüm proje klasörünü buraya sürüklemeyi deneyin.", "[WARN] 'multiprocessing' module detected. Ensure 'multiprocessing.freeze_support()' is called under 'if __name__ == \"__main__\":' to prevent infinite process loops (fork bombs).": "[WARN] 'multiprocessing' modülü algılandı. Sonsuz işlem döngülerini (fork bombaları) önlemek için 'multiprocessing.freeze_support()' çağrısının 'if __name__ == \"__main__\":' altında yapıldığından emin olun.", "[WARN] AST Analysis Exception: {error}": "[WARN] AST Analiz İstisnası: {error}", "[WARN] Command timeout (>{timeout}s)": "[WARN] Komut zaman aşımı (>{timeout}s)", @@ -405,5 +409,6 @@ "[WARN] Target project is in a Cloud Sync directory (e.g. OneDrive/Dropbox). Cloud sync may temporarily lock build files.": "[WARN] Hedef proje bir Bulut Senkronizasyon dizininde (örn. OneDrive/Dropbox). Bulut senkronizasyonu derleme dosyalarını geçici olarak kilitleyebilir.", "[WARN] Timestamp server connection timed out, performing local fast signing...": "[WARN] Zaman damgası sunucusu bağlantısı zaman aşımına uğradı, yerel hızlı imzalama yapılıyor...", "[WARN] Usage of '__file__' detected. In PyInstaller One-File mode, use 'sys._MEIPASS' to reliably locate bundled resource files!": "[WARN] '__file__' kullanımı algılandı. PyInstaller Tek Dosya modunda, paketlenmiş kaynak dosyalarını güvenilir şekilde bulmak için 'sys._MEIPASS' kullanın!", - "\\nProgram execution completed, press Enter to exit...": "\\nProgram yürütme tamamlandı, çıkmak için Enter'a basın..." + "\\nProgram execution completed, press Enter to exit...": "\\nProgram yürütme tamamlandı, çıkmak için Enter'a basın...", + "Package Mapping & Remediation": "Paket Eşleme ve Düzeltme" } diff --git a/qpypack/locales/vi_VN.json b/qpypack/locales/vi_VN.json index 854ec06..5e082a2 100644 --- a/qpypack/locales/vi_VN.json +++ b/qpypack/locales/vi_VN.json @@ -87,6 +87,7 @@ "Description:": "Mô tả:", "Desktop Application": "Ứng dụng máy tính để bàn", "Detailed Mode": "Chế độ chi tiết", + "Detected multiple entry scripts in project. Please select one to build:": "Phát hiện nhiều script khởi chạy trong dự án. Vui lòng chọn một để xây dựng:", "Directory": "Thư mục", "Discovered via scanner ({count}): {pkgs}": "Được phát hiện qua máy quét ({count}): {pkgs}", "Disk space critically low: {free:.1f}GB < {min:.1f}GB": "Dung lượng đĩa cực thấp: {free:.1f}GB < {min:.1f}GB", @@ -148,6 +149,7 @@ "Leave blank to auto-search requirements.txt in current directory": "Để trống để tự động tìm kiếm requirements.txt trong thư mục hiện tại", "Legacy macOS Compatible": "Tương Thích macOS Cũ", "Lite Mode (Smaller size)": "Chế Độ Gọn Nhẹ (Kích thước nhỏ hơn)", + "Loaded Project: {name} | Entry: {entry}": "Đã tải dự án: {name} | Điểm vào: {entry}", "Loaded: {filename}": "Đã tải: {filename}", "Locally Detected Pythons": "Python Được Phát Hiện Cục Bộ", "Lock Core Dependencies": "Khóa Các Phụ Thuộc Cốt Lõi", @@ -250,6 +252,7 @@ "Script loaded. You can drag asset folders or data files directly here to bundle them.": "Tập lệnh đã được tải. Bạn có thể kéo trực tiếp các thư mục tài sản hoặc tệp dữ liệu vào đây để đóng gói.", "Select .pfx / .p12 certificate file": "Chọn tệp chứng chỉ .pfx / .p12", "Select All": "Chọn tất cả", + "Select Main Entry Script": "Chọn Script Khởi Chạy Chính", "Select Python Version to Download:": "Chọn phiên bản Python để tải xuống:", "Select shared directory...": "Chọn thư mục dùng chung...", "Self-Signed Certificate (*.pfx)": "Chứng chỉ tự ký (*.pfx)", @@ -377,6 +380,7 @@ "[Syntax Error] Source code contains syntax errors, compilation aborted:\n - File: {file}\n - Type: {type}\n - Line: Line {line}\n - Detail: {desc}\n\nTip: Please ensure the source code runs locally before packaging.": "[Syntax Error] Mã nguồn chứa lỗi cú pháp, biên dịch bị hủy:\n - Tệp: {file}\n - Loại: {type}\n - Dòng: Dòng {line}\n - Chi tiết: {desc}\n\nMẹo: Vui lòng đảm bảo mã nguồn chạy cục bộ trước khi đóng gói.", "[Syntax Error] Source code syntax parsing failed, build aborted:\n - File: {file}\n - Detail: {desc}\n\nTip: This is usually NOT a fault of the packaging tool.\nPlease ensure the [Build Python Version] you selected matches the version you used to [Write/Test the Code].\nUsing newer syntax (e.g., walrus operator :=, type unions |, match-case) in an older Python environment will trigger this error.\nWe recommend going to [Build Settings] -> [Engine] to switch to the correct Python version.": "[Syntax Error] Phân tích cú pháp mã nguồn thất bại, hủy xây dựng:\n - Tệp: {file}\n - Chi tiết: {desc}\n\nMẹo: Đây thường KHÔNG phải lỗi của công cụ đóng gói.\nVui lòng đảm bảo [Phiên bản Python xây dựng] bạn chọn khớp với phiên bản bạn đã dùng để [Viết/Kiểm tra mã].\nSử dụng cú pháp mới hơn (ví dụ: toán tử walrus :=, union type |, match-case) trong môi trường Python cũ sẽ gây ra lỗi này.\nChúng tôi khuyên bạn nên đến [Cài đặt xây dựng] -> [Công cụ] để chuyển sang phiên bản Python chính xác.", "[Syntax Error] Source code syntax parsing failed, build aborted:\n - File: {file}\n - Line: Line {line}\n - Detail: {desc}\n\nTip: This is usually NOT a fault of the packaging tool.\nPlease ensure the [Build Python Version] you selected matches the version you used to [Write/Test the Code].\nUsing newer syntax (e.g., walrus operator :=, type unions |, match-case) in an older Python environment will trigger this error.\nWe recommend going to [Build Settings] -> [Engine] to switch to the correct Python version.": "[Syntax Error] Phân tích cú pháp mã nguồn thất bại, xây dựng bị hủy:\n - Tệp: {file}\n - Dòng: Dòng {line}\n - Chi tiết: {desc}\n\nMẹo: Đây thường KHÔNG phải lỗi của công cụ đóng gói.\nVui lòng đảm bảo [Phiên bản Python xây dựng] bạn chọn khớp với phiên bản bạn đã dùng để [Viết/Kiểm tra mã].\nSử dụng cú pháp mới hơn (ví dụ: toán tử hải mã :=, union kiểu |, match-case) trong môi trường Python cũ hơn sẽ gây ra lỗi này.\nChúng tôi khuyên bạn nên đến [Cài đặt xây dựng] -> [Công cụ] để chuyển sang phiên bản Python chính xác.", + "[TIP] Script imports parent module '{mod}'. If build fails, try dragging the whole project folder here.": "[TIP] Script nhập mô-đun cha '{mod}'. Nếu xây dựng thất bại, hãy thử kéo toàn bộ thư mục dự án vào đây.", "[WARN] 'multiprocessing' module detected. Ensure 'multiprocessing.freeze_support()' is called under 'if __name__ == \"__main__\":' to prevent infinite process loops (fork bombs).": "[WARN] Đã phát hiện mô-đun 'multiprocessing'. Đảm bảo gọi 'multiprocessing.freeze_support()' trong 'if __name__ == \"__main__\":' để tránh vòng lặp tiến trình vô hạn (fork bombs).", "[WARN] AST Analysis Exception: {error}": "[WARN] Ngoại lệ phân tích AST: {error}", "[WARN] Command timeout (>{timeout}s)": "[WARN] Hết thời gian chờ lệnh (>{timeout}s)", @@ -405,5 +409,6 @@ "[WARN] Target project is in a Cloud Sync directory (e.g. OneDrive/Dropbox). Cloud sync may temporarily lock build files.": "[WARN] Dự án mục tiêu nằm trong thư mục Đồng bộ đám mây (ví dụ: OneDrive/Dropbox). Đồng bộ đám mây có thể tạm thời khóa các tệp xây dựng.", "[WARN] Timestamp server connection timed out, performing local fast signing...": "[WARN] Kết nối máy chủ dấu thời gian hết thời gian chờ, thực hiện ký nhanh cục bộ...", "[WARN] Usage of '__file__' detected. In PyInstaller One-File mode, use 'sys._MEIPASS' to reliably locate bundled resource files!": "[WARN] Phát hiện việc sử dụng '__file__'. Trong chế độ Một tệp PyInstaller, hãy sử dụng 'sys._MEIPASS' để định vị đáng tin cậy các tệp tài nguyên được đóng gói!", - "\\nProgram execution completed, press Enter to exit...": "\\nChương trình đã thực thi xong, nhấn Enter để thoát..." + "\\nProgram execution completed, press Enter to exit...": "\\nChương trình đã thực thi xong, nhấn Enter để thoát...", + "Package Mapping & Remediation": "Ánh xạ gói & Khắc phục" } diff --git a/qpypack/locales/zh_TW.json b/qpypack/locales/zh_TW.json index 3216388..cbd793c 100644 --- a/qpypack/locales/zh_TW.json +++ b/qpypack/locales/zh_TW.json @@ -86,6 +86,7 @@ "Description:": "描述::", "Desktop Application": "桌面應用程式", "Detailed Mode": "詳細模式", + "Detected multiple entry scripts in project. Please select one to build:": "偵測到專案中有多個進入點腳本。請選擇一個來建置::", "Directory": "目錄", "Discovered via scanner ({count}): {pkgs}": "透過掃描器發現({count}):{pkgs}", "Disk space critically low: {free:.1f}GB < {min:.1f}GB": "磁碟空間嚴重不足:{free:.1f}GB < {min:.1f}GB", @@ -147,6 +148,7 @@ "Leave blank to auto-search requirements.txt in current directory": "留空以在目前目錄自動搜尋 requirements.txt", "Legacy macOS Compatible": "舊版 macOS 相容", "Lite Mode (Smaller size)": "精簡模式(較小體積)", + "Loaded Project: {name} | Entry: {entry}": "已載入專案:{name} | 進入點:{entry}", "Loaded: {filename}": "已載入:{filename}", "Locally Detected Pythons": "本機偵測到的 Python", "Lock Core Dependencies": "鎖定核心依賴項", @@ -249,6 +251,7 @@ "Script loaded. You can drag asset folders or data files directly here to bundle them.": "腳本已載入。您可以將資產資料夾或資料檔案直接拖曳到這裡以進行捆綁。", "Select .pfx / .p12 certificate file": "選擇 .pfx / .p12 憑證檔案", "Select All": "全選", + "Select Main Entry Script": "選擇主要進入點腳本", "Select Python Version to Download:": "選擇要下載的 Python 版本::", "Select shared directory...": "選擇共用目錄...", "Self-Signed Certificate (*.pfx)": "自簽憑證 (*.pfx)", @@ -375,6 +378,7 @@ "[Syntax Error] Source code contains syntax errors, compilation aborted:\n - File: {file}\n - Type: {type}\n - Line: Line {line}\n - Detail: {desc}\n\nTip: Please ensure the source code runs locally before packaging.": "[Syntax Error] 原始碼包含語法錯誤,編譯已中止:\n - 檔案:{file}\n - 類型:{type}\n - 行號:第 {line} 行\n - 詳細資訊:{desc}\n\n提示:請確保原始碼在打包前可於本機正常執行。", "[Syntax Error] Source code syntax parsing failed, build aborted:\n - File: {file}\n - Detail: {desc}\n\nTip: This is usually NOT a fault of the packaging tool.\nPlease ensure the [Build Python Version] you selected matches the version you used to [Write/Test the Code].\nUsing newer syntax (e.g., walrus operator :=, type unions |, match-case) in an older Python environment will trigger this error.\nWe recommend going to [Build Settings] -> [Engine] to switch to the correct Python version.": "[Syntax Error] 原始碼語法解析失敗,建置已中止:\n - 檔案:{file}\n - 詳細資訊:{desc}\n\n提示:這通常不是打包工具的錯誤。\n請確保您選擇的 [建置 Python 版本] 與您用來 [撰寫/測試程式碼] 的版本相符。\n在較舊的 Python 環境中使用較新的語法(例如海象運算子 :=、型別聯集 |、match-case)會觸發此錯誤。\n我們建議前往 [建置設定] -> [引擎] 切換到正確的 Python 版本。", "[Syntax Error] Source code syntax parsing failed, build aborted:\n - File: {file}\n - Line: Line {line}\n - Detail: {desc}\n\nTip: This is usually NOT a fault of the packaging tool.\nPlease ensure the [Build Python Version] you selected matches the version you used to [Write/Test the Code].\nUsing newer syntax (e.g., walrus operator :=, type unions |, match-case) in an older Python environment will trigger this error.\nWe recommend going to [Build Settings] -> [Engine] to switch to the correct Python version.": "[Syntax Error] 原始碼語法剖析失敗,建置已中止:\n - 檔案:{file}\n - 行號:第 {line} 行\n - 詳細資訊:{desc}\n\n提示:這通常不是打包工具的錯誤。\n請確保您選擇的 [建置 Python 版本] 與您 [撰寫/測試程式碼] 時使用的版本相符。\n在較舊的 Python 環境中使用較新的語法(例如海象運算子 :=、型別聯集 |、match-case)會觸發此錯誤。\n我們建議前往 [建置設定] -> [引擎] 切換至正確的 Python 版本。", + "[TIP] Script imports parent module '{mod}'. If build fails, try dragging the whole project folder here.": "[TIP] 腳本匯入了父模組「{mod}」。如果建置失敗,請嘗試將整個專案資料夾拖曳到此處。", "[WARN] 'multiprocessing' module detected. Ensure 'multiprocessing.freeze_support()' is called under 'if __name__ == \"__main__\":' to prevent infinite process loops (fork bombs).": "[WARN] 偵測到 'multiprocessing' 模組。請確保在 'if __name__ == \"__main__\":' 下呼叫 'multiprocessing.freeze_support()',以防止無限程序迴圈(fork 炸彈)。", "[WARN] AST Analysis Exception: {error}": "[WARN] AST 分析例外狀況:{error}", "[WARN] Command timeout (>{timeout}s)": "[WARN] 命令逾時(>{timeout} 秒)", @@ -403,5 +407,8 @@ "[WARN] Target project is in a Cloud Sync directory (e.g. OneDrive/Dropbox). Cloud sync may temporarily lock build files.": "[WARN] 目標專案位於雲端同步目錄(例如 OneDrive/Dropbox)。雲端同步可能暫時鎖定建置檔案。", "[WARN] Timestamp server connection timed out, performing local fast signing...": "[WARN] 時間戳伺服器連線逾時,執行本機快速簽章...", "[WARN] Usage of '__file__' detected. In PyInstaller One-File mode, use 'sys._MEIPASS' to reliably locate bundled resource files!": "[WARN] 偵測到 '__file__' 的使用。在 PyInstaller 單一檔案模式中,請使用 'sys._MEIPASS' 以可靠地定位捆綁的資源檔案!", - "\\nProgram execution completed, press Enter to exit...": "\\n程式執行完成,按 Enter 鍵退出..." + "\\nProgram execution completed, press Enter to exit...": "\\n程式執行完成,按 Enter 鍵退出...", + "Cancel": "取消", + "Package Mapping & Remediation": "套件對應與修復", + "Unknown": "未知" } diff --git a/qpypack/main.py b/qpypack/main.py index 1a72253..9eb99c1 100644 --- a/qpypack/main.py +++ b/qpypack/main.py @@ -125,7 +125,7 @@ except ImportError: HAS_QT_AUDIO = False __app_name__ = "QPyPack" -__version__ = "2.7.14" +__version__ = "2.8.0" __author__ = "QwejayHuang" __company__ = "QwejayHuang" __description__ = "Modern Cross-Platform Python Packaging GUI Powered by PyInstaller & Nuitka" @@ -587,6 +587,10 @@ ZH_CN_DICT = { "Nuitka Compiles source code into native C/C++ binary. Produces smaller package size, faster execution, and deep anti-decompilation protection (requires C compiler).": "Nuitka 将源代码编译为原生C/C++二进制文件。生成包体积更小,执行速度更快,并具有深度反反编译保护(需要C编译器)。", "PyInstaller Bundles Python interpreter and bytecode. Fast build speed, zero configuration (no C compiler needed), and excellent compatibility.": "PyInstaller 打包Python解释器和字节码。构建速度快,零配置(无需C编译器),兼容性极佳。", "Use Custom Commercial Cert (Optional) ": "使用自定义商业证书(可选)", + "Select Main Entry Script": "选择项目主入口脚本", + "Detected multiple entry scripts in project. Please select one to build:": "在项目目录下检测到多个 Python 脚本,请选择主程序入口:", + "Loaded Project: {name} | Entry: {entry}": "已载入项目: {name} | 入口: {entry}", + "[TIP] Script imports parent module '{mod}'. If build fails, try dragging the whole project folder here.": "[提示] 脚本引用了上级模块 '{mod}'。如构建报错,可直接将项目总文件夹拖入软件打包。", "Unknown": "未知" } @@ -774,27 +778,34 @@ PYPI_MIRRORS_GLOBAL = [ ] DEFAULT_MAPPINGS = { - "acoustid": "pyacoustid", + "crypto": "pycryptodome", + "Crypto": "pycryptodome", + "cryptodome": "pycryptodome", + "Cryptodome": "pycryptodome", + "nacl": "pynacl", + "jwt": "PyJWT", + "OpenSSL": "pyOpenSSL", + "cv2": "opencv-python", "PIL": "pillow", "Pillow": "pillow", "skimage": "scikit-image", - "vlc": "python-vlc", - "pyzbar": "pyzbar", - "OpenGL": "PyOpenGL", - "pyside6_addons": "PySide6", - "pyside6_essentials": "PySide6", - "pyside6-addons": "PySide6", - "pyside6-essentials": "PySide6", - "pyqt5-plugins": "PyQt5", - "pyqt5-tools": "PyQt5", - "pyqt5_plugins": "PyQt5", "fitz": "pymupdf", "docx": "python-docx", "pptx": "python-pptx", - "bs4": "beautifulsoup4", - "barcode": "python-barcode", "pdfplumber": "pdfplumber", + "barcode": "python-barcode", + "soundfile": "soundfile", + "mutagen": "mutagen", + "vlc": "python-vlc", + "pyzbar": "pyzbar", + "OpenGL": "PyOpenGL", + + "serial": "pyserial", + "usb": "pyusb", + "bluetooth": "pybluez", + "pynput": "pynput", + "magic": "python-magic", "win32com": "pywin32", "win32api": "pywin32", "win32con": "pywin32", @@ -811,33 +822,26 @@ DEFAULT_MAPPINGS = { "win32crypt": "pywin32", "pythoncom": "pywin32", "pywintypes": "pywin32", - "serial": "pyserial", - "usb": "pyusb", - "bluetooth": "pybluez", + + "bs4": "beautifulsoup4", "dns": "dnspython", "websocket": "websocket-client", "paho": "paho-mqtt", "socketio": "python-socketio", "engineio": "python-engineio", "kafka": "kafka-python", - "sklearn": "scikit-learn", - "yaml": "pyyaml", - "dateutil": "python-dateutil", - "jwt": "PyJWT", - "Crypto": "pycryptodome", - "wx": "wxPython", - "desktop_notifier": "desktop-notifier", "dotenv": "python-dotenv", "telegram": "python-telegram-bot", "git": "GitPython", "github": "PyGithub", "gitlab": "python-gitlab", "discord": "discord.py", - "OpenSSL": "pyOpenSSL", "ldap": "python-ldap", - "magic": "python-magic", - "slugify": "python-slugify", - "snappy": "python-snappy", + + "yaml": "pyyaml", + "dateutil": "python-dateutil", + "sklearn": "scikit-learn", + "wx": "wxPython", "attr": "attrs", "psycopg2": "psycopg2-binary", "pkg_resources": "setuptools", @@ -845,6 +849,9 @@ DEFAULT_MAPPINGS = { "cx_Oracle": "cx-Oracle", "mysql": "mysql-connector-python", "pydantic_core": "pydantic-core", + "slugify": "python-slugify", + "snappy": "python-snappy", + "acoustid": "pyacoustid", } DEFAULT_BACKPORT_RULES = { @@ -1180,7 +1187,6 @@ def is_cloud_sync_path(path_obj: Path) -> bool: ] return any(kw in path_str for kw in cloud_keywords) - def extract_project_imports_via_ast(target_path, scan_dir: bool = False) -> set: imports = set() target_path = Path(target_path) @@ -1189,9 +1195,9 @@ def extract_project_imports_via_ast(target_path, scan_dir: bool = False) -> set: files_to_scan = [target_path] if target_path.is_file() else [] else: files_to_scan = [] - for root, _, files in os.walk(target_path): + for root, _dirs, files in os.walk(target_path): path_parts = set(Path(root).parts) - if path_parts & {"__pycache__", ".qpypack_build", ".qpypack_venv", ".venv", "venv", "build", "dist", "env", ".env"}: + if path_parts & {"__pycache__", ".qpypack_build", ".qpypack_venv", ".venv", "venv", "build", "dist", "env", ".env", ".git"}: continue for file in files: if file.endswith((".py", ".pyw")): @@ -1200,17 +1206,24 @@ def extract_project_imports_via_ast(target_path, scan_dir: bool = False) -> set: for file_p in files_to_scan: try: code = safe_read_text(file_p) + if not code.strip(): + continue tree = ast.parse(code, filename=file_p.as_posix()) for node in ast.walk(tree): if isinstance(node, ast.Import): - imports.update(n.name.split(".")[0] for n in node.names) - elif isinstance(node, ast.ImportFrom) and node.level == 0 and node.module: - imports.add(node.module.split(".")[0]) + for n in node.names: + top_pkg = n.name.split(".")[0].strip() + if top_pkg: + imports.add(top_pkg) + elif isinstance(node, ast.ImportFrom): + if node.level == 0 and node.module: + top_pkg = node.module.split(".")[0].strip() + if top_pkg: + imports.add(top_pkg) except Exception: pass return imports - def query_target_env_packages(python_exe: str) -> dict: if not python_exe or not os.path.exists(python_exe): return {} @@ -1917,6 +1930,69 @@ def get_python_executable(): return find_system_python() +def get_all_local_modules(project_root: Path, script_dir: Path) -> set: + """全面扫描项目工作区与脚本目录内的所有本地模块/包名,防止被误判为 PyPI 第三方包去执行 pip install""" + local_modules = set() + scan_dirs = {project_root, script_dir} + if (project_root / "src").exists() and (project_root / "src").is_dir(): + scan_dirs.add(project_root / "src") + + for s_dir in scan_dirs: + try: + for p in s_dir.iterdir(): + if p.name.startswith((".", "__pycache__", "build", "dist", "venv", "env")): + continue + if p.is_file() and p.suffix.lower() in (".py", ".pyw", ".pyd", ".so"): + local_modules.add(p.stem.lower()) + elif p.is_dir(): + if (p / "__init__.py").exists() or any(p.glob("*.py")): + local_modules.add(p.name.lower()) + except Exception: + pass + return local_modules + + +class EntrySelectDialog(QDialog): + """当用户拖入文件夹且包含多个候选入口脚本时弹出的极简选择框""" + def __init__(self, parent, folder_path, py_files): + super().__init__(parent) + self.setWindowTitle(_("Select Main Entry Script")) + self.setMinimumWidth(420) + self.setStyleSheet(""" + QDialog { background-color: #ffffff; } + QLabel { font-size: 13px; color: #111827; font-weight: bold; } + QListWidget { border: 1px solid #d1d5db; border-radius: 6px; padding: 4px; font-family: Consolas, monospace; font-size: 12px; } + QListWidget::item { padding: 6px 10px; border-radius: 4px; } + QListWidget::item:selected { background-color: #2563eb; color: #ffffff; } + QPushButton { background-color: #2563eb; color: #ffffff; border: none; border-radius: 6px; font-size: 12px; font-weight: bold; padding: 6px 16px; min-width: 70px; } + QPushButton:hover { background-color: #1d4ed8; } + """) + lay = QVBoxLayout(self) + lay.setSpacing(10) + lay.setContentsMargins(20, 20, 20, 20) + + lay.addWidget(QLabel(_("Detected multiple entry scripts in project. Please select one to build:"))) + self.list_widget = QListWidget() + for f in py_files: + rel = f.relative_to(folder_path).as_posix() + item = QListWidgetItem(f"📄 {rel}") + item.setData(Qt.ItemDataRole.UserRole, f.as_posix()) + self.list_widget.addItem(item) + self.list_widget.setCurrentRow(0) + lay.addWidget(self.list_widget) + + btn_lay = QHBoxLayout() + btn_lay.addStretch() + btn_ok = QPushButton(_("OK")) + btn_ok.clicked.connect(self.accept) + btn_lay.addWidget(btn_ok) + lay.addLayout(btn_lay) + + def get_selected_script(self): + item = self.list_widget.currentItem() + return item.data(Qt.ItemDataRole.UserRole) if item else None + + def safe_read_text(path: Path) -> str: try: raw = path.read_bytes() @@ -2383,12 +2459,20 @@ class DropArea(QFrame): if not paths: return - py_files = [p for p in paths if p.lower().endswith((".py", ".pyw"))] + parent_win = self.window() + # 1. 优先判断是否直接拖入了项目主文件夹 + first_path = Path(paths[0]) + if len(paths) == 1 and first_path.is_dir(): + if hasattr(parent_win, "on_project_folder_selected"): + parent_win.on_project_folder_selected(first_path) + return + + # 2. 如果拖入的是单脚本文件 + py_files = [p for p in paths if p.lower().endswith((".py", ".pyw"))] if py_files: self.fileDropped.emit(py_files[0]) else: - parent_win = self.window() if hasattr(parent_win, "on_main_resources_dropped"): parent_win.on_main_resources_dropped(paths) @@ -4961,6 +5045,10 @@ class PackingThread(QThread): if extra_env: clean_env.update(extra_env) + proj_folder = self.params.get("project_folder") + if proj_folder and os.path.exists(proj_folder): + clean_env["PYTHONPATH"] = proj_folder + (os.pathsep + clean_env["PYTHONPATH"] if "PYTHONPATH" in clean_env else "") + try: kwargs = { "stdout": subprocess.PIPE, @@ -5115,12 +5203,31 @@ class PackingThread(QThread): "# -------------------------------------------\n\n" ) + try: + tree = ast.parse(code, filename=orig_path.as_posix()) + last_future_lineno = 0 + for node in tree.body: + if isinstance(node, ast.ImportFrom) and node.module == "__future__": + last_future_lineno = max(last_future_lineno, getattr(node, "end_lineno", node.lineno)) + elif isinstance(node, ast.Expr) and isinstance(node.value, ast.Constant) and isinstance(node.value.value, str): + last_future_lineno = max(last_future_lineno, getattr(node, "end_lineno", node.lineno)) + else: + break + + lines = code.splitlines(keepends=True) + if last_future_lineno > 0: + injected_code = "".join(lines[:last_future_lineno]) + "\n" + pause_code + "".join(lines[last_future_lineno:]) + else: + injected_code = pause_code + code + except Exception: + injected_code = pause_code + code + temp_file = orig_path.parent / f"_qpypack_temp_{orig_path.name}" try: - temp_file.write_text(pause_code + code, encoding="utf-8") + temp_file.write_text(injected_code, encoding="utf-8") except PermissionError: temp_file = Path(tempfile.gettempdir()) / f"_qpypack_temp_{orig_path.name}" - temp_file.write_text(pause_code + code, encoding="utf-8") + temp_file.write_text(injected_code, encoding="utf-8") os.environ["PYTHONPATH"] = orig_path.parent.as_posix() + os.pathsep + os.environ.get("PYTHONPATH", "") return temp_file, True, "" @@ -5502,19 +5609,20 @@ class PackingThread(QThread): pass def parse_req_line(line): - line = line.strip() - if not line or line.startswith(("#", "-")): + line = line.split("#")[0].strip() + if not line or line.startswith(("-", "@")): return None, None - m = re.match(r"^([a-zA-Z0-9_\-\.]+)(.*)$", line) + line_no_marker = line.split(";")[0].strip() + m = re.match(r"^([a-zA-Z0-9_\-\.]+)(.*)$", line_no_marker) if m: - pkg_raw = m.group(1) + pkg_raw = m.group(1).strip() canon_name = get_canonical_pypi_name(pkg_raw) if canon_name.lower() in target_std_libs: return None, None if canon_name.lower() != pkg_raw.lower(): - full_spec = canon_name + full_spec = canon_name + m.group(2).strip() else: - full_spec = line + full_spec = line_no_marker return canon_name, full_spec return None, None @@ -5541,11 +5649,12 @@ class PackingThread(QThread): except Exception as e: self.progress.emit(_("[WARN] Read requirements.txt warning: {error}", error=str(e))) - local_modules = { - p.stem.lower() - for p in script_dir.iterdir() - if (p.is_file() and p.suffix.lower() in (".py", ".pyw", ".pyd", ".so")) or (p.is_dir() and (p / "__init__.py").exists()) - } + proj_folder = self.params.get("project_folder") + project_root = Path(proj_folder).resolve() if (proj_folder and Path(proj_folder).exists()) else script_dir + + local_modules = get_all_local_modules(project_root, script_dir) + user_added_dirs = {Path(dst).parts[0].lower() for _r_type, src, dst in (self.params.get("add_data_list") or [])} + local_modules.update(user_added_dirs) for m in script_imports: if m.lower() in target_std_libs or m.lower() in local_modules: @@ -5697,19 +5806,17 @@ class PackingThread(QThread): self.progress.emit(_("[INFO] Scanning project source code via AST engine...")) - scan_dir_mode = self.params.get("use_pipreqs_dir", False) - if scan_dir_mode: - ast_discovered_imports = extract_project_imports_via_ast(script_dir, scan_dir=True) - else: - ast_discovered_imports = script_imports + scan_target = project_root if (project_root and project_root.exists()) else script_dir + ast_discovered_imports = extract_project_imports_via_ast(scan_target, scan_dir=True) env_pkg_map = query_target_env_packages(system_python_exe) for m in ast_discovered_imports: - if m.lower() in target_std_libs or m.lower() in local_modules: + m_lower = m.lower() + if m_lower in target_std_libs or m_lower in local_modules: continue - canon_name = (env_pkg_map.get(m) or get_canonical_pypi_name(m)).lower() - if canon_name not in target_std_libs: + canon_name = (env_pkg_map.get(m) or env_pkg_map.get(m_lower) or get_canonical_pypi_name(m)).lower() + if canon_name not in target_std_libs and canon_name not in local_modules: auto_detected_pkgs.add(canon_name) if canon_name not in final_dependencies: final_dependencies[canon_name] = canon_name @@ -5972,6 +6079,12 @@ class PackingThread(QThread): f"--name={app_name}", ] + cmd.append(f"--paths={project_root.as_posix()}") + if project_root != script_dir: + cmd.append(f"--paths={script_dir.as_posix()}") + if (project_root / "src").exists(): + cmd.append(f"--paths={(project_root / 'src').as_posix()}") + if self.params["onefile"]: cmd.append("--onefile") else: @@ -6054,28 +6167,43 @@ class PackingThread(QThread): hidden_list = [i.strip().lower() for i in (self.params.get("hidden_imports") or "").split(",") if i.strip()] all_imports_lower = imports_lower | set(hidden_list) + if any(k in all_imports_lower for k in ("crypto", "pycryptodome", "cryptography", "nacl", "pynacl")): + cmd.extend(["--collect-all", "Crypto"]) + cmd.extend(["--collect-all", "pycryptodome"]) + cmd.extend(["--collect-all", "cryptography"]) + cmd.extend(["--collect-all", "nacl"]) + + if "pynput" in all_imports_lower: + cmd.extend(["--collect-all", "pynput"]) + if "keyring" in all_imports_lower: + cmd.extend(["--collect-all", "keyring"]) + if "soundfile" in all_imports_lower: + cmd.extend(["--collect-all", "soundfile"]) + if "ttkbootstrap" in all_imports_lower: cmd.extend(["--collect-all", "ttkbootstrap"]) if "customtkinter" in all_imports_lower: cmd.extend(["--collect-all", "customtkinter"]) + if "gradio" in all_imports_lower: + cmd.extend(["--collect-all", "gradio"]) + if "matplotlib" in all_imports_lower or "seaborn" in all_imports_lower: + cmd.extend(["--collect-data", "matplotlib"]) + if "playwright" in all_imports_lower or has_playwright_pkg: cmd.extend(["--collect-all", "playwright"]) if "moviepy" in all_imports_lower: cmd.extend(["--collect-data", "moviepy"]) - if "gradio" in all_imports_lower: - cmd.extend(["--collect-all", "gradio"]) + if "pydantic" in all_imports_lower: cmd.extend(["--collect-submodules", "pydantic"]) - if "matplotlib" in all_imports_lower or "seaborn" in all_imports_lower: - cmd.extend(["--collect-data", "matplotlib"]) - - if any(lib in all_imports_lower for lib in ("requests", "httpx", "urllib3", "aiohttp")): + cmd.extend(["--collect-submodules", "pydantic_core"]) + if any(lib in all_imports_lower for lib in ("requests", "httpx", "urllib3", "aiohttp", "urllib")): cmd.extend(["--collect-data", "certifi"]) self.progress.emit( _("[WARN] Detected 'requests' or 'httpx'. Auto-bundling 'certifi' certificates to prevent SSL errors.") ) - for web_fw in ("fastapi", "uvicorn", "flask", "streamlit", "pywebio", "dash", "pyecharts", "pyppeteer"): + for web_fw in ("fastapi", "uvicorn", "flask", "starlette", "sqlalchemy", "tortoise", "streamlit", "pywebio", "dash", "pyecharts", "pyppeteer"): if web_fw in all_imports_lower: cmd.extend(["--collect-all", web_fw]) @@ -6091,6 +6219,10 @@ class PackingThread(QThread): f"--output-filename={app_name}{ext}", ] + for mod_name in local_modules: + if (project_root / mod_name).is_dir(): + cmd.append(f"--include-package={mod_name}") + base_nuitka_excludes = ["unittest", "doctest", "pdb", "pydoc", "test", "pytest", "IPython", "setuptools"] for ex in base_nuitka_excludes: cmd.append(f"--nofollow-import-to={ex}") @@ -6325,13 +6457,21 @@ class PackingThread(QThread): cmd.append("--include-package=playwright") cmd.append("--include-package-data=playwright") - if any(lib in imports_lower for lib in ("requests", "httpx", "urllib3", "aiohttp")): + if any(k in imports_lower for k in ("crypto", "pycryptodome", "cryptography", "nacl", "pynacl")): + cmd.append("--include-package=Crypto") + cmd.append("--include-package=cryptography") + if "pynput" in imports_lower: + cmd.append("--include-package=pynput") + if "soundfile" in imports_lower: + cmd.append("--include-package=soundfile") + + if any(lib in imports_lower for lib in ("requests", "httpx", "urllib3", "aiohttp", "urllib")): cmd.append("--include-package-data=certifi") self.progress.emit( _("[WARN] Detected 'requests' or 'httpx'. Auto-bundling 'certifi' certificates to prevent SSL errors.") ) - for web_fw in ("fastapi", "uvicorn", "flask", "streamlit", "pywebio", "dash", "pyecharts", "pyppeteer"): + for web_fw in ("fastapi", "uvicorn", "flask", "starlette", "sqlalchemy", "tortoise", "streamlit", "pywebio", "dash", "pyecharts", "pyppeteer"): if web_fw in imports_lower: if not is_lite: cmd.append(f"--include-package={web_fw}") @@ -6358,7 +6498,7 @@ class PackingThread(QThread): for excl in (self.params.get("exclude_modules") or "").split(","): if excl.strip(): - cmd.append(f"--nofollow-import-to={excl.strip()}") + cmd.extend(["--nofollow-import-to={excl.strip()}"]) if self.params.get("lite_mode"): self.progress.emit(_("[INFO] Lite mode enabled, applying bytecode optimization (-OO) and stripping dev modules...")) @@ -6972,6 +7112,7 @@ class MainWindow(QMainWindow): def __init__(self): super().__init__() self.script_path = "" + self.project_folder = None self.thread = None self.analysis_thread = None self.current_state = "idle" @@ -7492,12 +7633,58 @@ class MainWindow(QMainWindow): else: self.show_notification(_("[INFO] Added {count} resource item(s) to Additional Resources.", count=count)) + def on_project_folder_selected(self, folder_path: Path): + folder_path = folder_path.resolve() + candidates = [] + for root, _dirs, files in os.walk(folder_path): + parts = set(Path(root).parts) + if parts & {"__pycache__", ".git", ".venv", "venv", "build", "dist", ".qpypack_build", ".qpypack_venv"}: + continue + for f in files: + if f.endswith((".py", ".pyw")): + candidates.append(Path(root) / f) + + if not candidates: + self.show_error_log(_("[ERROR] Please load a valid Python source file first!")) + return + + priority_names = ["main.py", "app.py", "server.py", "run.py", "start.py", "unlocker.py", "gui.py", "cli.py"] + selected_script = None + + for p_name in priority_names: + matched = [c for c in candidates if c.name.lower() == p_name] + if matched: + selected_script = matched[0].as_posix() + break + + if not selected_script: + if len(candidates) == 1: + selected_script = candidates[0].as_posix() + else: + dlg = EntrySelectDialog(self, folder_path, candidates) + if dlg.exec() == QDialog.DialogCode.Accepted: + selected_script = dlg.get_selected_script() + else: + return + + if selected_script: + self.project_folder = folder_path.as_posix() + root_reqs = folder_path / "requirements.txt" + if root_reqs.exists(): + self.settings_panel.reqs_file_edit.setText(root_reqs.as_posix()) + + self.on_script_selected(selected_script) + self.show_notification(_("Loaded Project: {name} | Entry: {entry}", name=folder_path.name, entry=Path(selected_script).name), 6000) + def on_script_selected(self, path): path = Path(path).resolve().as_posix() if is_cloud_locked(path): self.show_error_log(_("[ERROR] Target file is locked or encrypted by cloud drive. Please decrypt and try again.")) return + if not getattr(self, "project_folder", None) or Path(self.project_folder) not in Path(path).parents: + self.project_folder = None + if self.script_path != path: self.settings_panel.icon_edit.clear() self.settings_panel.hidden_edit.clear() @@ -7633,6 +7820,18 @@ class MainWindow(QMainWindow): self.log_concise.clear() self.log_detailed.clear() self.append_log(_("Loaded: {filename}", filename=path)) + + if not self.project_folder: + script_path_obj = Path(path).resolve() + parent_dir = script_path_obj.parent.parent + if parent_dir and parent_dir != script_path_obj.parent: + for imp in script_imports: + top_m = imp.split(".")[0] + if (parent_dir / top_m).exists() or (parent_dir / f"{top_m}.py").exists(): + tip_text = _("[TIP] Script imports parent module '{mod}'. If build fails, try dragging the whole project folder here.", mod=top_m) + self.append_log(tip_text) + break + self.show_notification(_("Script loaded. You can drag asset folders or data files directly here to bundle them."), 6000) self.btn_main.setEnabled(True) self.update_ui_state("ready") @@ -7823,6 +8022,7 @@ class MainWindow(QMainWindow): "engine": engine, "python_exe": raw_py, "script_path": self.script_path, + "project_folder": self.project_folder, "enable_sign": sp.enable_sign_check.isChecked(), "cert_path": sp.cert_path_edit.text().strip(), "cert_pass": sp.cert_pass_edit.text().strip(), @@ -7966,6 +8166,7 @@ class MainWindow(QMainWindow): def reset_all(self): self.script_path = "" + self.project_folder = None self.settings_panel.name_edit.clear() self.settings_panel.icon_edit.clear() self.settings_panel.hidden_edit.clear() @@ -8253,4 +8454,4 @@ def main(): if __name__ == "__main__": - main() + main() \ No newline at end of file diff --git a/tests/test_check.py b/tests/test_check.py new file mode 100644 index 0000000..fcc0e05 --- /dev/null +++ b/tests/test_check.py @@ -0,0 +1,546 @@ +# -*- coding: utf-8 -*- +""" +============================================================================= + QPyPack 全功能终极一体化自检与双引擎真实打包验证系统 (UI 深度集成完整版) +============================================================================= + 特性: + - 深度集成:直接实例化 MainWindow 模拟用户拖拽与点击,完整测试 UI->Engine 链路 + - 前瞻兼容:不写死参数字典,直接读取 UI 界面控件生成的配置,随软件升级自动适配 + - 自动自净:测试开始前与结束后自动抹除一切 build/、spec、egg-info 残留 + - 全量覆盖:包含 AST 分析、I18N 多语言引擎、状态机逻辑等 8 大核心维度 +============================================================================= +""" + +import sys +import os +import re +import json +import time +import shutil +import zipfile +import tempfile +import subprocess +import traceback +from pathlib import Path + +# 全局开启 Qt 无头模式与 Windows 字体 (屏蔽无关警告) +os.environ["QT_QPA_PLATFORM"] = "offscreen" +if sys.platform == "win32": + os.environ["PYTHONIOENCODING"] = "utf-8" + if os.path.exists(r"C:\Windows\Fonts"): + os.environ["QT_QPA_FONTDIR"] = r"C:\Windows\Fonts" +os.environ["QT_LOGGING_RULES"] = "qt.qpa.fonts=false;qt.qpa.*=false;qt.multimedia*=false" + +current_path = Path(__file__).resolve() +if current_path.parent.name == "tests": + ROOT_DIR = current_path.parent.parent +else: + ROOT_DIR = current_path.parent + +PACKAGE_DIR = ROOT_DIR / "qpypack" +LOCALES_DIR = PACKAGE_DIR / "locales" +ICON_PATH = PACKAGE_DIR / "icon.ico" + +if str(ROOT_DIR) not in sys.path: + sys.path.insert(0, str(ROOT_DIR)) + + +class Colors: + CYAN = "\033[96m" + GREEN = "\033[92m" + YELLOW = "\033[93m" + RED = "\033[91m" + RESET = "\033[0m" + BOLD = "\033[1m" + + +def log_pass(msg): + print(f" {Colors.GREEN}✔ [PASS]{Colors.RESET} {msg}") + + +def log_warn(msg): + print(f" {Colors.YELLOW}⚠ [WARN]{Colors.RESET} {msg}") + + +def log_fail(msg): + print(f" {Colors.RED}✖ [FAIL]{Colors.RESET} {msg}") + + +def log_info(msg): + print(f" {Colors.CYAN}ℹ [INFO]{Colors.RESET} {msg}") + + +# ===================================================================== +# 垃圾自净机制 (自动清理根目录残留) +# ===================================================================== +def clean_project_junk(): + """扫描并强制清除项目根目录下的所有测试与构建残留""" + junk_patterns_dir = ["build", "dist", "*.egg-info", "__pycache__", ".pytest_cache"] + junk_patterns_file = ["*.spec", ".coverage"] + + # 清理目录 + for pattern in junk_patterns_dir: + for p in ROOT_DIR.glob(pattern): + if p.is_dir() and p != PACKAGE_DIR: + try: + shutil.rmtree(p, ignore_errors=True) + except Exception: + pass + for p in (ROOT_DIR / "tests").glob(pattern): + if p.is_dir(): + try: + shutil.rmtree(p, ignore_errors=True) + except Exception: + pass + + # 清理文件 + for pattern in junk_patterns_file: + for p in ROOT_DIR.glob(pattern): + if p.is_file(): + try: + p.unlink(missing_ok=True) + except Exception: + pass + for p in (ROOT_DIR / "tests").glob(pattern): + if p.is_file(): + try: + p.unlink(missing_ok=True) + except Exception: + pass + + +# 测试前先自净一次历史垃圾 +clean_project_junk() + + +# ===================================================================== +# 1. 静态资源与配置深度检测 +# ===================================================================== +def test_01_static_assets(): + """测试 1: 静态资源与配置物理合法性""" + print(f"\n{Colors.BOLD}{Colors.CYAN}>>> [测试 1/8] 静态资源与工程配置完整性检查...{Colors.RESET}") + + assert ICON_PATH.exists(), f"关键图标缺失: {ICON_PATH}" + assert ICON_PATH.stat().st_size > 1024, "icon.ico 文件大小异常" + with open(ICON_PATH, "rb") as f: + header = f.read(4) + assert header == b"\x00\x00\x01\x00", "icon.ico 不是有效的 Windows ICO 格式" + log_pass(f"图标格式与二进制签名正常 (大小: {ICON_PATH.stat().st_size} bytes)") + + toml_path = ROOT_DIR / "pyproject.toml" + assert toml_path.exists(), "pyproject.toml 缺失" + assert "qpypack" in toml_path.read_text(encoding="utf-8").lower() + log_pass("pyproject.toml 配置文件解析正常") + + +# ===================================================================== +# 2. 16 种多语言语法、Key 一致性与占位符检测 +# ===================================================================== +def test_02_locales_and_placeholders(): + """测试 2: 16 国多语言深度校验""" + print(f"\n{Colors.BOLD}{Colors.CYAN}>>> [测试 2/8] 16 国国际化语言包与语法占位符检测...{Colors.RESET}") + + assert LOCALES_DIR.is_dir(), "locales 目录不存在" + json_files = list(LOCALES_DIR.glob("*.json")) + assert len(json_files) == 16, f"应包含 16 种语言包,实际发现 {len(json_files)} 个" + log_pass(f"成功定位到全部 {len(json_files)} 个语言包文件") + + parsed = {} + for jf in json_files: + with open(jf, "r", encoding="utf-8") as f: + data = json.load(f) + assert isinstance(data, dict), f"{jf.name} 格式非合法字典" + parsed[jf.name] = data + log_pass("所有语言包 JSON 语法解析正常") + + base_data = parsed.get("zh_CN.json", {}) + assert base_data, "基准语言包 zh_CN.json 缺失或为空" + base_keys = set(base_data.keys()) + + missing_map = {} + for name, data in parsed.items(): + if name == "zh_CN.json": + continue + missing = base_keys - set(data.keys()) + if missing: + missing_map[name] = missing + + if missing_map: + for fname, keys in missing_map.items(): + log_warn(f"{fname} 缺少 {len(keys)} 个词条: {list(keys)[:3]}...") + else: + log_pass("16 国语言包与 zh_CN.json 词条保持 100% 完全对齐!") + + +# ===================================================================== +# 3. AST 语法分析与依赖提取算法测试 +# ===================================================================== +def test_03_ast_engine(): + """测试 3: AST 源码静态语法分析与依赖侦测 (QPyPack 原生算法)""" + print(f"\n{Colors.BOLD}{Colors.CYAN}>>> [测试 3/8] AST 静态分析与依赖侦测 (QPyPack 原生算法)...{Colors.RESET}") + + from qpypack.main import extract_project_imports_via_ast + + with tempfile.TemporaryDirectory() as tmpdir: + mock_file = Path(tmpdir) / "test_ast.py" + mock_file.write_text("import os, sys\nimport requests.auth\nfrom PyQt5.QtWidgets import QMainWindow", encoding="utf-8") + + modules = extract_project_imports_via_ast(mock_file, scan_dir=False) + assert {"requests", "PyQt5", "os", "sys"}.issubset(modules), f"QPyPack 原生提取异常: {modules}" + log_pass(f"QPyPack AST 引擎成功提取模块依赖: {modules}") + + +# ===================================================================== +# 4. 核心模块与入口健全性 (集成配置存储及多语言引擎联调) +# ===================================================================== +def test_04_core_logic(): + """测试 4: 核心配置管理与翻译引擎联调测试""" + print(f"\n{Colors.BOLD}{Colors.CYAN}>>> [测试 4/8] QPyPack 核心配置读取与多语言翻译引擎测试...{Colors.RESET}") + + from qpypack.main import load_config, I18N + + config = load_config(retry=True) + assert "Settings" in config, "配置生成或加载失败" + assert "Mappings" in config, "包名映射字典缺失" + + # 动态切换并断言多语言系统 + I18N.set_language("en_US") + assert I18N.t("Build Settings") == "Build Settings", "英文翻译错误" + I18N.set_language("zh_CN") + assert I18N.t("Build Settings") == "构建设置", "中文翻译未命中映射" + + log_pass("配置 I/O 系统与 I18N 多语言引擎运行正常") + + +# ===================================================================== +# 5. UI 控件与主窗口状态机独立交互测试 +# ===================================================================== +def test_05_ui_interaction(): + """测试 5: Qt UI 界面与控件状态机逻辑交互测试 (独立无打包)""" + print(f"\n{Colors.BOLD}{Colors.CYAN}>>> [测试 5/8] Qt UI 控件与状态机模拟交互测试...{Colors.RESET}") + + try: + from PySide6.QtWidgets import QApplication + app = QApplication.instance() or QApplication(["qp_test", "-platform", "offscreen"]) + except ImportError: + log_warn("未安装 PySide6,跳过 GUI 交互测试") + return + + from PySide6.QtCore import QEventLoop, QTimer + from qpypack.main import MainWindow + window = MainWindow() + + with tempfile.TemporaryDirectory() as tmp_dir: + mock_py = Path(tmp_dir) / "mock_app.py" + mock_py.write_text("print('hello')", encoding="utf-8") + + # 测试拖入脚本 + window.on_script_selected(str(mock_py)) + + # 等待后台 AST 解析子线程完成 + loop = QEventLoop() + timer = QTimer() + timer.timeout.connect(loop.quit) + timer.start(1000) + loop.exec() + timer.stop() + + assert window.current_state == "ready", "脚本载入后状态机未变为 ready" + assert window.settings_panel.name_edit.text() == "mock_app", "未成功解析推导出默认程序名" + + # 测试修改引擎配置 + window.settings_panel.engine_combo.setCurrentIndex(1) + assert window.settings_panel.engine_combo.currentText() == "Nuitka" + + log_pass("主窗口完成内存初始化,状态机推导与 UI 数据绑定响应正常") + + +# ===================================================================== +# 6. Wheel 分发包真实打包与解压内嵌资产验证 (沙箱环境零残留) +# ===================================================================== +def test_06_wheel_packaging(): + """测试 6: Wheel 包构建与资源嵌入""" + print(f"\n{Colors.BOLD}{Colors.CYAN}>>> [测试 6/8] Wheel (.whl) 分发包构建与资源嵌入深度检查...{Colors.RESET}") + + with tempfile.TemporaryDirectory(prefix="qp_whl_") as tmp_dist: + try: + build_cmd = [sys.executable, "-m", "build", "--wheel", "--outdir", tmp_dist, str(ROOT_DIR)] + result = subprocess.run(build_cmd, capture_output=True, text=True, cwd=tmp_dist) + + if result.returncode != 0: + result = subprocess.run( + [sys.executable, "-m", "pip", "wheel", "--no-deps", "-w", tmp_dist, str(ROOT_DIR)], + capture_output=True, text=True, cwd=tmp_dist + ) + assert result.returncode == 0, f"构建 Wheel 失败:\n{result.stderr}" + + wheels = list(Path(tmp_dist).glob("*.whl")) + assert wheels, "未找到生成的 .whl 文件" + wheel_file = wheels[0] + log_pass(f"成功构建 Wheel: {wheel_file.name}") + + with zipfile.ZipFile(wheel_file, "r") as zf: + names = zf.namelist() + assert any("icon.ico" in n for n in names), "icon.ico 漏打包进 Wheel!" + json_in_wheel = [n for n in names if "locales/" in n and n.endswith(".json")] + assert len(json_in_wheel) >= 16, f"语言包未全部嵌入 Wheel (仅 {len(json_in_wheel)} 个)!" + log_pass(f"icon.ico 及 16 个语言包已 100% 嵌入 Wheel 压缩包中") + finally: + clean_project_junk() + + +# ===================================================================== +# 辅助函数: 创建微型真实测试工程 & 产物实机拉起断言 +# ===================================================================== +def _create_mock_project(base_dir: Path) -> Path: + proj_dir = base_dir / "mock_app" + proj_dir.mkdir(parents=True, exist_ok=True) + assets_dir = proj_dir / "assets" + assets_dir.mkdir(exist_ok=True) + + with open(assets_dir / "data.json", "w", encoding="utf-8") as f: + json.dump({"engine_test": "QPYPACK_REAL_OK"}, f) + + with open(proj_dir / "calc.py", "w", encoding="utf-8") as f: + f.write("def multiply(a, b): return a * b\n") + + entry_file = proj_dir / "app_main.py" + with open(entry_file, "w", encoding="utf-8") as f: + f.write('''# -*- coding: utf-8 -*- +__version__ = "1.0.0" +__app_name__ = "MockTestApp" + +import sys, os, json, multiprocessing +from calc import multiply + +def get_res(rel): + if hasattr(sys, '_MEIPASS'): + return os.path.join(sys._MEIPASS, rel) + return os.path.join(os.path.dirname(os.path.abspath(__file__)), rel) + +if __name__ == '__main__': + multiprocessing.freeze_support() + calc_res = multiply(6, 7) + res_path = get_res(os.path.join("assets", "data.json")) + val = "FAIL" + if os.path.exists(res_path): + with open(res_path, "r", encoding="utf-8") as f: + val = json.load(f).get("engine_test", "CORRUPTED") + else: + val = f"NOT_FOUND:{res_path}" + print(f"__QP_ASSERT__|{calc_res}|{val}|__QP_ASSERT_END__") + sys.exit(0) +''') + return entry_file + + +def _get_size(path: Path): + if path.is_file(): + return path.stat().st_size + return sum(f.stat().st_size for f in path.rglob('*') if f.is_file()) + + +def _assert_executable_execution(exe_path: Path): + if sys.platform == "darwin" and exe_path.is_dir() and exe_path.name.endswith(".app"): + exe_path = exe_path / "Contents" / "MacOS" / exe_path.stem + + assert exe_path.exists(), f"未找到生成的 EXE/二进制 文件: {exe_path}" + start_t = time.time() + proc = subprocess.run([str(exe_path)], capture_output=True, text=True, timeout=20, cwd=str(exe_path.parent)) + + assert proc.returncode == 0, f"程序运行报错 (Code {proc.returncode}):\n{proc.stderr}" + assert "__QP_ASSERT__|42|QPYPACK_REAL_OK|__QP_ASSERT_END__" in proc.stdout, f"输出不符,资源提取失败:\n{proc.stdout}" + + size_mb = _get_size(exe_path) / (1024 * 1024) + log_pass(f"产物实机拉起验证通过!耗时: {time.time() - start_t:.2f}s | 体积: {size_mb:.2f} MB | 静态资源捆绑读取正常") + + +# ===================================================================== +# E2E 测试核心引擎: 完整模拟 MainWindow 界面交互与打包 +# ===================================================================== +def run_e2e_via_mainwindow(engine_name: str, tmp_dir: Path, is_onefile: bool): + """ + 通过直接实例化 MainWindow 并触发界面事件,模拟真实用户的打包全流程。 + 这能保证测试紧跟 UI 升级,覆盖完整的 "界面配置 -> 参数生成 -> 线程打包" 链路。 + """ + from PySide6.QtCore import QEventLoop, QTimer + from qpypack.main import MainWindow + + sandbox = Path(tmp_dir) + entry_file = _create_mock_project(sandbox) + + # 1. 实例化主窗口 (触发所有的初始化和配置读取) + window = MainWindow() + + # 2. 模拟用户拖拽源码文件到界面 + window.on_script_selected(str(entry_file)) + + # 等待分析线程(ScriptAnalysisThread)完成 + loop_wait = QEventLoop() + timer_wait = QTimer() + timer_wait.timeout.connect(loop_wait.quit) + timer_wait.start(1000) # 等待1秒确保分析完毕 + loop_wait.exec() + timer_wait.stop() + + assert window.current_state == "ready", "脚本载入后状态机未变为 ready" + + # 3. 模拟用户配置界面面板 (SettingsPanel) + sp = window.settings_panel + sp.engine_combo.setCurrentText(engine_name) + sp.rb_onefile.setChecked(is_onefile) + sp.rb_onedir.setChecked(not is_onefile) + sp.noconsole_check.setChecked(True) + sp.enable_sign_check.setChecked(False) # 测试环境关闭签名防阻断 + + # 设置输出目录到沙箱中 + sp.out_mode_combo.setCurrentIndex(1) + sp.out_dir_edit.setText(str(sandbox / "dist")) + + # 4. 模拟用户拖入附加资源 (assets 文件夹) + window.on_main_resources_dropped([str(entry_file.parent / "assets")]) + + # 5. 模拟点击【开始构建】 + window.start_pack() + assert window.current_state == "building", "启动打包后,主窗口未进入 building 状态" + + # 6. 使用事件循环等待 PackingThread 后台线程完成 + loop = QEventLoop() + def check_status(): + # 轮询状态机是否退出 building + if window.current_state in ("done", "failed"): + loop.quit() + + timer = QTimer() + timer.timeout.connect(check_status) + timer.start(500) + loop.exec() + timer.stop() + + assert window.current_state == "done", f"【{engine_name}】打包失败!详细日志如下:\n{window.log_detailed.toPlainText()}" + + # 7. 提取生成的程序名,并定位产物 + app_name = sp.name_edit.text().strip() or "MockTestApp" + ext = ".exe" if sys.platform == "win32" else "" + dist_dir = sandbox / "dist" + + if sys.platform == "darwin" and sp.noconsole_check.isChecked(): + exe_path = dist_dir / f"{app_name}.app" + else: + if is_onefile: + exe_path = dist_dir / f"{app_name}{ext}" + else: + # 文件夹模式:产物为 dist_dir/app_name/app_name.exe + exe_path = dist_dir / app_name / f"{app_name}{ext}" + + # 容错:Nuitka 在极少数情况下可能未重命名 .dist 文件夹,或者文件名带版本号 + if not exe_path.exists(): + fallback_dist = dist_dir / f"{app_name}.dist" / f"{app_name}{ext}" + if fallback_dist.exists(): + exe_path = fallback_dist + else: + # 终极兜底:直接在目录里搜索可执行文件 + possible_exes = list((dist_dir / app_name).glob(f"*{ext}")) + if possible_exes: + exe_path = possible_exes[0] + + # 8. 校验实机拉起 + _assert_executable_execution(exe_path) + + +# ===================================================================== +# 7. PyInstaller E2E 测试 +# ===================================================================== +def test_07_pyinstaller_real_build(): + """测试 7: 深度集成 UI 的 PyInstaller 真实打包与拉起测试""" + print(f"\n{Colors.BOLD}{Colors.CYAN}>>> [测试 7/8] 深度集成测试: UI 操作 -> PyInstaller 构建 -> 实机拉起...{Colors.RESET}") + try: + import PyInstaller + except ImportError: + log_warn("缺少 PyInstaller,跳过测试") + return + + from PySide6.QtWidgets import QApplication + app = QApplication.instance() or QApplication(["qp_test", "-platform", "offscreen"]) + + with tempfile.TemporaryDirectory(prefix="qp_e2e_pyi_") as tmp_dir: + start_t = time.time() + # 测试 PyInstaller 的单文件模式 + run_e2e_via_mainwindow("PyInstaller", Path(tmp_dir), is_onefile=True) + log_pass(f"PyInstaller E2E 完整链路测试通过,耗时: {time.time() - start_t:.2f}s") + + clean_project_junk() + + +# ===================================================================== +# 8. Nuitka E2E 测试 +# ===================================================================== +def test_08_nuitka_real_build(): + """测试 8: 深度集成 UI 的 Nuitka 原生编译与拉起测试""" + print(f"\n{Colors.BOLD}{Colors.CYAN}>>> [测试 8/8] 深度集成测试: UI 操作 -> Nuitka 原生编译 -> 实机拉起...{Colors.RESET}") + try: + import nuitka + except ImportError: + log_warn("缺少 Nuitka,跳过测试") + return + + from PySide6.QtWidgets import QApplication + app = QApplication.instance() or QApplication(["qp_test", "-platform", "offscreen"]) + + with tempfile.TemporaryDirectory(prefix="qp_e2e_nuitka_") as tmp_dir: + start_t = time.time() + # 测试 Nuitka 的文件夹模式 (Standalone) + run_e2e_via_mainwindow("Nuitka", Path(tmp_dir), is_onefile=False) + log_pass(f"Nuitka E2E 完整链路测试通过,耗时: {time.time() - start_t:.2f}s") + + clean_project_junk() + + +# ===================================================================== +# 主调度入口 +# ===================================================================== +def main(): + print(f""" +{Colors.CYAN}{Colors.BOLD}====================================================================== + 🚀 QPyPack 全功能终极一体化自检与双引擎真实打包验证系统 (UI深度集成版) +======================================================================{Colors.RESET}""") + + tests = [ + ("静态资源与工程配置", test_01_static_assets), + ("多语言包格式对齐与校验", test_02_locales_and_placeholders), + ("QPyPack 原生 AST 分析引擎", test_03_ast_engine), + ("QPyPack 核心配置与翻译引擎逻辑", test_04_core_logic), + ("Qt UI 主窗口状态机独立交互测试", test_05_ui_interaction), + ("Wheel 分发包沙箱构建测试", test_06_wheel_packaging), + ("PyInstaller E2E 链路验证 (单文件)", test_07_pyinstaller_real_build), + ("Nuitka E2E 链路验证 (文件夹)", test_08_nuitka_real_build), + ] + + failed = False + for title, func in tests: + try: + func() + except Exception as e: + failed = True + log_fail(f"【{title}】未通过!原因: {e}") + print(f"\n{Colors.RED}详细错误回溯:{Colors.RESET}") + traceback.print_exc() + break + + # 无论成功失败,强制执行纯净清理 + clean_project_junk() + + print(f"\n{Colors.BOLD}======================================================================{Colors.RESET}") + if not failed: + print(f"{Colors.GREEN}{Colors.BOLD} 🎉 [CONGRATULATIONS] 全部端到端深度集成测试 100% 顺利通过!{Colors.RESET}") + print(f"{Colors.GREEN} 💡 你的所有 UI 修改、功能迭代、参数注入均完美运行,且一切残留已被销毁!{Colors.RESET}") + print(f"{Colors.BOLD}======================================================================{Colors.RESET}\n") + sys.exit(0) + else: + print(f"{Colors.RED}{Colors.BOLD} 💥 [TEST FAILED] 发现程序缺陷!测试已中断,请根据上方回溯修复代码。{Colors.RESET}") + print(f"{Colors.BOLD}======================================================================{Colors.RESET}\n") + sys.exit(1) + + +if __name__ == "__main__": + main()