feat(pixel-perfect): expose standalone native tool API - #496
Open
huyanxius wants to merge 21 commits into
Open
Conversation
The application needs a minimal boundary for local grid detection and reconstruction. Add immutable result types and stable input, busy, and unavailable error classes. Later adapters can compose the native modules without importing business services.
The tool API must invoke fixed local binaries without unbounded subprocess resources. Add six-field detector parsing, explicit reconstructor arguments, output limits, timeouts, and exit classification. Native failures now map to controlled tool errors instead of leaking process behavior.
Automatic and manual modes need one application boundary that remains outside generation. Compose detection and explicit reconstruction with finite parameters, bounded concurrency, and PNG validation. The tool can run independently while rejecting unsupported sub-three-pixel auto results.
Browsers need an explicit endpoint that never touches storage or generation workflows. Add streamed request limits, local-tool error mapping, PNG metadata headers, and composition-root registration. The authenticated endpoint now returns the rebuilt image directly with bounded upload concurrency.
The app package inspects upload and reconstruction dimensions at its own boundary. Declare Pillow directly and update only the corresponding workspace lock metadata. Runtime dependency ownership no longer relies on the unrelated AI engine package.
The new tool must remain separate from existing generation and infrastructure modules. Add bidirectional forbidden-import contracts for the tool, orchestrator, generation API, and worker. Future coupling attempts now fail the existing architecture gate.
Production needs both standalone Rust modules without shipping a Rust runtime or source tree. Build each locked crate in a separate stage and copy only binaries plus MIT licenses into the image. The Python runtime can invoke fixed local tools through explicit environment paths.
The explicit API needs regression evidence for composition, resources, and failure mapping. Cover uploads, manual bypass, sub-three-pixel rejection, native limits, concurrency, CORS, and OpenAPI. Tool regressions now fail without exercising storage, generation, databases, or external services.
The repository OpenAPI artifact must match the newly registered multipart endpoint. Export the PNG success response, business-error JSON, form parameters, and validation schema. Clients and CI now see the same explicit tool contract as the running application.
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
Contributor
There was a problem hiding this comment.
Review conclusion
The standalone API boundary, subprocess adapter, packaging changes, OpenAPI export, and architecture contracts were reviewed against the fixed SHA range. The targeted 20-test suite, Ruff checks, formatting check, and all four import-linter contracts pass. One integration-level upload-limit path does not preserve the API's documented business-error envelope, as detailed inline.
4 tasks
The backend adapter should not spawn Rust binaries for each request. Load the PyO3 module lazily and map its typed results into existing tool contracts. Missing native code affects only this explicit endpoint, not application startup.
The backend needs a stable boundary for detector and reconstructor extension calls. Replace process-protocol cases with direct-call, input-error, and lazy-load coverage. Tests now exercise the selected native-extension integration shape.
The backend adapter needs a native module that can link both independent Rust crates. Add the locked Cargo and maturin package metadata for an abi3 Python 3.12 extension. This gives the binding a reproducible package boundary without changing either algorithm.
The Python adapter should call the independent detector and reconstructor without subprocess overhead. Expose byte-oriented detect and reconstruct functions while releasing the interpreter during Rust work. The extension preserves the existing algorithm inputs and maps invalid native input to ValueError.
The extension boundary needs direct coverage apart from the FastAPI adapter tests. Exercise detector metadata, explicit-grid reconstruction, and invalid-input error mapping. This protects the Python-facing ABI without changing detector or reconstructor behavior.
Backend contributors need a short reference for building and calling the extension locally. Document the two byte-oriented functions, the maturin command, and error ownership. This keeps the native boundary discoverable without adding generation-pipeline guidance.
Local maturin and Cargo verification creates target artifacts beside the binding crate. Exclude the crate target directory from version control. This keeps local native builds from polluting the adapter branch.
The backend and worker images need the PyO3 module while keeping Rust tooling out of runtime. Build a locked wheel in a dedicated stage and install it through the repository-root build context. Both services now share the packaged extension and retain only required native licenses at runtime.
Starlette converts multipart receive failures into its own HTTP 400 response. Suppress that parser response after the byte limit trips and emit the existing business envelope. Oversized uploads now retain the endpoint contract without weakening the pre-spool limit.
The direct middleware test did not exercise Starlette multipart error handling. Send an upload above the ASGI limit through the authenticated TestClient endpoint. The regression now guards the HTTP 200 business-error envelope at the real API boundary.
The same environment variable was parsed independently by the tool factory and middleware wiring. Define one framework settings object and inject its validated value from the composition root. The feature module stays framework-independent while both resource guards share one setting.
Deployers need to discover the resource limit without reading application wiring. Add the validated PIXEL_PERFECT_CONCURRENCY key to the environment template. Local and container deployments can now tune the explicit tool from the documented config surface.
xyh202131
approved these changes
Aug 21, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
将独立完美像素工具的 Python 调用边界改为 PyO3 原生扩展,并完成 binding、后端适配与容器 wheel 构建接线;工具仍保持在生成管线之外。
Why
每次请求启动 Rust 子进程会增加进程创建、管道传输和生命周期管理成本,也会把 Rust 二进制路径扩散进 Python 后端配置。后端只需要依赖稳定的原生模块接口,同时不能让该工具耦合现有生成或工作流系统。
Changes
windup_pixel_perfect_nativePyO3 binding,直接组合 feat(pixel-grid): add independent native grid detector #493 检测器与 feat(pixel-grid): add independent native grid reconstructor #495 重建器。detect/reconstruct,删除子进程与二进制路径配置。ValueError。Implementation
native/pixel-perfect/bindings/python,仅暴露两个 byte-oriented 函数,不修改算法。windup_app.server.pixel_perfect.native只负责 PyO3 返回值与现有 Python 契约的转换。#493 → #495 → #496顺序 rebase。Verification
cargo fmt --check --manifest-path native/pixel-perfect/bindings/python/Cargo.toml:通过。cargo check --release --locked --manifest-path native/pixel-perfect/bindings/python/Cargo.toml:通过。pytest -q native/pixel-perfect/bindings/python/tests/test_binding.py:3 项通过。pytest -q backend/tests/test_pixel_perfect_api.py:20 项通过。pytest -q backend/tests/test_env_example_keys_are_live.py:2 项通过。lint-imports:4 条架构契约通过。ruff check与ruff format --check:通过。docker build -f backend/Dockerfile -t windup-pixel-perfect-pyo3:final .:在 feat(pixel-grid): add independent native grid detector #493 + feat(pixel-grid): add independent native grid reconstructor #495 + feat(pixel-perfect): expose standalone native tool API #496 组合树通过。windup_pixel_perfect_native:通过。cargo、rustc、算法源码目录,并保留两份许可证:通过。git diff --check:通过。Scope
<3px自动检测边界保持现状,后续另行处理。Related Issues
Closes #492
Refs #489
Refs #493
Refs #495