ykcheungab 8a027bfcb9 接管 Studio 流水线迁移记录
将历史比较放回产品仓库并标明现行实现所有者。文档与仓库门禁通过,原记录正文保留。
2026-10-19 10:15:45 +08:00
2026-10-19 10:15:45 +08:00
2026-10-09 13:34:29 +08:00
2026-09-27 19:20:43 +08:00

orisys-app

Desktop applications that consume the Orisys SDK.

App Status Qt binding
apps/studio The customer-facing shell (theme / locale / prefs / logging, acquisition, 3D) PySide6
apps/autocal Internal 5-axis calibration platform control PySide6
apps/internal Stub, superseded by apps/autocal —

Both shipped apps are PySide6 — Qt's LGPLv3 binding. PyQt5's free option is GPLv3-or-commercial, which is why the studio was migrated off it: a closed-source product would otherwise need a licence purchase. The rule is enforced, not just documented: neither app may import PyQt5/PyQt6/PySide2, and shared/ (used by both) may import PySide6 and nothing else. See apps/studio/tests/test_studio_binding_purity.py and apps/autocal/tests/test_binding_purity.py.

One practical consequence: pyqtgraph binds to whichever toolkit it imports first, so a development environment that still has PyQt5 installed can build plots from the wrong binding. orisys_studio.main sets PYQTGRAPH_QT_LIB=PySide6 before anything imports it, and the purity test asserts that importing the app pulls in no other binding.

Layout

  • shared/ — common paths, prefs, theme, i18n, logging, and the ZMotion client
  • shared/resources/zmotion/ — vendored ZMotion runtime DLLs (internal use only)
  • apps/studio/config/ — locales, default prefs, editable sensors/ copies
  • apps/studio/outputs/ — generated logs and calibration exports (gitignored)
  • apps/autocal/ — internal platform control; see apps/autocal/README.md
  • build/ — Windows PyInstaller packaging (build/studio/build.ps1)

Selecting which app's paths resolve

orisys_app_shared.paths reads ORISYS_APP_ID (an apps/ directory name) to decide which product's config/, preference.json and outputs/ a process owns. Each app's launcher sets it before importing the shared package; when it is unset the studio is assumed, which keeps existing callers working unchanged. A named app whose config/ is missing raises rather than silently resolving another product's tree.

Run (studio shell)

cd D:\repo\orisys-app
python -m pip install -e .\shared -e .\apps\studio
python .\apps\studio\run.py

Or without install:

$env:PYTHONPATH = "D:\repo\orisys-app\shared\src;D:\repo\orisys-app\apps\studio\src"
python D:\repo\orisys-app\apps\studio\run.py

Local orisys SDK

orisys_app_shared.force imports orisys.calibration at module scope, so the studio app cannot start against an SDK build that predates that module (the published 0.5.2 wheel does not include it). When working from a repo checkout, install the SDK from source instead of from an index:

python -m pip install .\..\orisys-sdk          # same checkout that built this app

If a pip build is blocked by the environment, the equivalent manual install is to copy orisys-sdk/src/orisys/**/*.py over site-packages/orisys/ and delete the stale __init__.cp310-win_amd64.pyd (an extension module shadows the package __init__.py, which hides sibling modules such as calibration.py).

Verifying UI changes

Both tools render the real main window with the offscreen Qt platform — no display, camera or sensor hardware required:

python .\apps\studio\tools\ui_check.py                      # layout/theme assertions
python .\apps\studio\tools\ui_snapshot.py --theme light --demo `
    --sensor finger --panels cal,3d --size 1600x900 --out shot.png

ui_check.py needs only the runtime dependencies. The pytest suite in shared/tests and apps/studio/tests covers the same ground plus locale and preference-schema parity:

pip install pytest
python -m pytest

On Windows the offscreen platform finds no fonts unless QT_QPA_FONTDIR points at C:\Windows\Fonts; both tools set it automatically.

ui_check.py also runs the palette rules (WCAG contrast, colour separation, ramp monotonicity) that guard the brand tokens; see apps/studio/docs/ui-palette.md for the colour system, its relationship to the UI design spec, and every deliberate deviation from it.

Layout follows apps/studio/docs/ui-layout.md: which controller owns the arrangement, the fixed effect set every view change must apply, each view's pane priority and degradation order, when a numeric geometry argument is legitimate, and which of these rules are not yet mechanically enforced.

ui_check.py includes a record channel section as well; see apps/studio/docs/record-channel.md for why recording and calibration sampling no longer hang off the UI refresh timer, and for the data-reliability fixes that came with it.

The merge gate

One command runs everything a change must not break, and it is the only check that is meant to be unskippable:

powershell -NoProfile -ExecutionPolicy Bypass -File tools\gate.ps1

It runs tools/lint_gate.py over the changed files, then the full studio suite, the full shared suite, and ui_check.py at the same time (-Serial runs those three one after another with live output, for reading a failing stage); writes each one's output to .scratch/gate/gate-<run-id>/; and holds the run to three contracts — an empty tools/known_failures.txt, the skip ceilings and collection floors in tools/skip_budget.txt, and zero findings anywhere. It exits 0 only when all of that holds.

The lint step compares against a commit range, not only the dirty tree: -LintBase <ref> defaults to origin/main, so a pre-push run checks every commit about to be pushed. A ref that does not resolve is a configuration error (exit 2); the gate never quietly falls back to linting uncommitted files only.

The gate platform is Windows: the suites render real Qt widgets offscreen, and two checks are platform-sensitive (docs/test-repair-plan.zh.md §3 #11 and #13), so a green Linux run is not the same statement.

An optional pre-push hook calls it, so a failing gate blocks the push. It is deliberately not installed for you:

git config core.hooksPath .githooks     # enable; `git config --unset core.hooksPath` disables

Day-to-day development still uses targeted test runs (docs/test-execution-plan.zh.md); the gate is what runs before a change is committed or handed over.

Branding

Window / EXE icon: shared/resources/branding/logo.png
Top bar / About: shared/resources/branding/logo_topbar.png

Dark mode is the default. Logos currently sit on a black tile; a transparent (or light) variant may be needed for polished light mode later.

Versioning

  • Studio app version (orisys_studio.__version__) — shown in Help → About and used for releases.
  • Shared package version (orisys_app_shared.__version__) — internal library version.
  • Shared API (orisys_app_shared.API_VERSION) — compatibility tag. Studio declares REQUIRES_SHARED_API; startup logs a warning on mismatch.

Deferred

Run/Stop pipeline, arrow/force plots, units, calibration capture, Open3D finger mesh, sync-from-wheel for config/sensors, PyInstaller packaging, and the internal app.

S
Description
No description provided
Readme 68 MiB
Languages
Python 84.8%
HTML 11.7%
C 2.6%
PowerShell 0.8%
FreeBASIC 0.1%