feat: aignostics-sdk v2 — consolidated integration branch [PYSDK-133]#661
Draft
ari-nz wants to merge 39 commits into
Draft
feat: aignostics-sdk v2 — consolidated integration branch [PYSDK-133]#661ari-nz wants to merge 39 commits into
ari-nz wants to merge 39 commits into
Conversation
…ease - Replace single uv publish step with sequential build+publish for aignostics-sdk (first) then aignostics (second) to respect dependency order - Add pre-publish lockstep version consistency check that fails fast if the two packages diverge - Add informational smoke_test_slim job (continue-on-error) that installs aignostics-sdk from PyPI after publish and asserts the CLI works, the slim import succeeds, and heavy deps (openslide) are absent - Update noxfile dist() session to build both packages into dist/ so make dist stays consistent with the new publish flow - GitHub release glob ./dist/* already covers both wheels since both are built into dist/
Adds documentation for the v2 dual-package distribution that splits the SDK into aignostics-sdk (slim API client) and aignostics (full SDK), including migration guide for users upgrading from v1.
…tics Move heavy/domain-specific dependencies from aignostics-sdk to aignostics, leaving only platform+utils runtime dependencies in the slim package. Slim (aignostics-sdk): platform auth, HTTP, JWT, logging, MCP, nicegui, fastapi, pydantic, typer, sentry, retry, jsonschema/jsf, tqdm — 28 deps. Heavy (aignostics): WSI (openslide, wsidicom, pydicom), cloud storage (boto3, google-cloud-storage), data (duckdb, pandas, fastparquet/pyarrow), DICOM validation, IDC index, shapely, procrastinate, html-sanitizer, humanize, pyyaml, packaging, python-dateutil, defusedxml — 30 deps. CVE transitive overrides split accordingly (slim vs heavy deps). Deviations from task guidance (import-trace is authoritative): - tqdm kept in slim: imported by platform/_utils.py for upload progress - humanize/pyyaml/packaging/python-dateutil/jsf moved to heavy (or left in slim as appropriate): not imported by platform/ or utils/ directly - jsf kept in slim: used for JSON schema generation (jsonschema companion)
Update mypy, pyright, coverage, pytest, and dist build configs to target packages/aignostics-sdk/src and packages/aignostics/src instead of the legacy src/ layout introduced by PYSDK-134 workspace scaffolding. Also fix four Pylance type-narrowing errors in noxfile.py latexmk version detection (session.error() is not NoReturn in nox's type stubs).
- platform/ and utils/ → packages/aignostics-sdk/src/aignostics_sdk/ - application/, wsi/, dataset/, bucket/, qupath/, notebook/, gui/, system/, third_party/, cli.py → packages/aignostics/src/aignostics/ - constants.py split: INTERNAL_ORGS → aignostics-sdk/constants.py; remaining constants → aignostics/constants.py - Created symlink packages/aignostics-sdk/src/aignx → codegen/out/aignx to bundle codegen into slim wheel - Updated packages/aignostics-sdk/pyproject.toml: packages = [\"src/aignostics_sdk\", \"src/aignx\"] - Updated packages/aignostics-sdk/src/aignostics_sdk/__init__.py with real module docstring - Moved packages/aignostics/src/aignostics/__init__.py from src/aignostics/ (preserving full content) Note: imports are intentionally broken at this stage. Import rewrites (aignostics.* → aignostics_sdk.* for slim-module consumers) are deferred to PYSDK-136.
- platform/ and utils/ → packages/aignostics-sdk/src/aignostics_sdk/ - application/, wsi/, dataset/, bucket/, qupath/, notebook/, gui/, system/, third_party/, cli.py → packages/aignostics/src/aignostics/ - constants.py split: INTERNAL_ORGS → aignostics-sdk/constants.py; remaining constants → aignostics/constants.py - Created symlink packages/aignostics-sdk/src/aignx → codegen/out/aignx to bundle codegen into slim wheel - Updated packages/aignostics-sdk/pyproject.toml: packages = ["src/aignostics_sdk", "src/aignx"] - Updated packages/aignostics-sdk/src/aignostics_sdk/__init__.py with real module docstring - Moved packages/aignostics/src/aignostics/__init__.py from src/aignostics/ (preserving full content) Note: imports are intentionally broken at this stage. Import rewrites (aignostics.* → aignostics_sdk.* for slim-module consumers) are deferred to PYSDK-136.
…sdk.*
- Mechanically rewrites 206 import statements across 91 files in
packages/aignostics-sdk/, packages/aignostics/, and tests/ so that
platform and utils references point at the new aignostics_sdk package
- Fixes two classes of non-obvious imports missed by naive sed:
* from ..utils import (relative two-level imports in heavy modules)
* from .utils.boot import boot (relative import in aignostics __init__)
- Restores aignostics.constants imports where heavy constants
(WINDOW_TITLE, HETA_APPLICATION_ID, etc.) live, since aignostics_sdk.constants
only carries the slim subset (INTERNAL_ORGS)
- Patches utils/_constants.py to preserve backward compat:
* __project_name__ = "aignostics" (keeps ~/.aignostics token cache
and AIGNOSTICS_* env-var prefix)
* _package_name derives from __name__.split(".")[0] = "aignostics_sdk"
* All three importlib.metadata calls now use _package_name so they
resolve against the correct installed distribution
- 900 tests collect successfully after the rewrite (0 collection errors)
- PYSDK-137 (slim CLI) and PYSDK-141 (tests) build on top of this change
…_sdk.platform._sdk_metadata
…d by initial sweep
…rce migration - Add packages/aignostics/src/aignostics/wsi/_pydicom_handler.py and packages/aignostics/src/aignostics/notebook/_notebook.py to ignore list (both were previously ignored under src/ but moved in PYSDK-135) - Exclude examples/ from pyright (pre-existing errors from before the split) - Remove stale extraPaths pointing at old src/ layout
Creates packages/aignostics-sdk/src/aignostics_sdk/cli.py with a trimmed Typer app exposing only the platform CLI commands (user, sdk). Deliberately avoids calling prepare_cli() to prevent auto-discovery of heavy domain modules (application, wsi, dataset, bucket, qupath, system) via locate_implementations(typer.Typer). Instead, applies epilog and no-args-is-help behaviour directly by calling the private helpers _add_epilog_recursively and _no_args_is_help_recursively.
…plit [PYSDK-141]
- Add `slim` pytest marker to pyproject.toml for aignostics-sdk package tests
- Create tests/aignostics_sdk/__init__.py and smoke_test.py
- 5 smoke tests verify importability of aignostics_sdk.platform.Client,
aignostics_sdk.utils.{BaseService,Health}, aignx.codegen.exceptions.ApiException,
__project_name__ backward-compat constant, and __version__ availability
- 1 xfail test documents missing aignostics_sdk.cli module (pending PYSDK-137)
- No stale `from aignostics.platform` / `from aignostics.utils` imports in tests/
- Collection: 904 tests collected (0 collection errors)
- Pre-existing failures in base branch (stale patch() paths from PYSDK-136
import rewrite) are not introduced by this PR; they will be tracked separately
…ation Hatchling builds packages in an isolated environment and cannot follow relative paths outside the package root (e.g. ../../LICENSE). Copy LICENSE and README.md into each package directory and update pyproject.toml references from ../../LICENSE/README.md to ./LICENSE/README.md. This unblocks `uv build --package` for the integration branch validation.
…kspace migration - ruff: ignore PLW0717 (try clause too many statements) and RUF075 (fallible context manager) — introduced in ruff 0.15.13 by the dep version bump in PYSDK-138; pre-existing code patterns, to be addressed in individual PRs - mypy: exclude packages/aignostics-sdk/src/aignx (codegen symlink) and add follow_imports=skip override for aignx.* to prevent imported codegen types from causing errors in caller code; aignx is not part of the SDK source - pyright: add **/aignx/** to exclude list so the codegen symlink is not type-checked by pyright These are integration-branch compatibility fixes, not feature changes.
4 tasks
This was referenced May 28, 2026
|
…s.py for file upload checksums
…CLI entry points
Changes:
- Move packages/aignostics-sdk/src/aignostics_sdk/ to src/aignostics_sdk/
and add symlink at packages/aignostics-sdk/src/aignostics_sdk -> ../../../src/aignostics_sdk
- Update _constants.py: rename __project_name__ to "aignostics-sdk" (PYSDK-136),
introduce ENV_PREFIX ("AIGNOSTICS_SDK") for env var names to avoid hyphens,
add _package_name for importlib.metadata calls
- Update _di.py: scan both "aignostics_sdk" and "aignostics" packages for DI
discovery so heavy-module CLIs/services are still found
- Update _cli.py: prevent duplicate Typer registration in prepare_cli by
checking already-registered sub-typers before adding discovered ones
- Trim utils __init__.py: remove _nav/_gui/_mcp/_di from __all__ (they
belong to the heavy package), keep them accessible for backward compat;
re-export ENV_PREFIX, locate_subclasses, NavItem, mcp_run etc. since
the heavy package imports them
- Add [project.entry-points."aignostics.cli"] to aignostics-sdk pyproject.toml
registering user and sdk sub-commands
- Update aignostics/cli.py to mount slim commands via entry-point discovery
instead of direct imports
- Update aignostics cli.py: change lazy _gui/_mcp imports to public API
- Update all heavy-package settings files (_constants.py users) to use
ENV_PREFIX instead of __project_name__.upper() (which would produce
invalid "AIGNOSTICS-SDK" env var names with hyphens)
- Update GUI/nav imports across heavy package to use public aignostics_sdk.utils API
- Update slim cli.py display strings to say "aignostics-sdk"
…PREFIX to AIGNOSTICS - Revert ENV_PREFIX from "AIGNOSTICS_SDK" back to "AIGNOSTICS" for backward compatibility with all existing env var consumers - Move _nav.py, _gui.py, _mcp.py, _di.py from slim aignostics_sdk.utils to heavy aignostics.utils to keep heavy dependencies out of the slim package - Create aignostics/utils/__init__.py that re-exports all slim symbols plus the four moved modules (locate_implementations, locate_subclasses, gui_run, BasePageBuilder, GUILocalFilePicker, mcp_run, etc.) - Update all heavy-package consumers to import heavy symbols from aignostics.utils instead of aignostics_sdk.utils - Fix prepare_cli in slim to lazily import locate_implementations from aignostics.utils to avoid circular dependency at module load time
- git mv application and system from packages/aignostics into
packages/aignostics-sdk/src/aignostics_sdk/
- Fix all internal imports: aignostics.{platform,utils,constants} →
aignostics_sdk.{platform,utils,constants}; aignostics.system →
aignostics_sdk.system
- Make heavy-only imports lazy (bucket, wsi, gui.frame, utils.BasePageBuilder,
utils.GUILocalFilePicker, utils.gui_run, utils.locate_subclasses) so the
slim package imports cleanly without the full aignostics package installed
- Add HETA_APPLICATION_ID, TEST_APP_APPLICATION_ID,
WSI_SUPPORTED_FILE_EXTENSIONS, WSI_SUPPORTED_FILE_EXTENSIONS_TEST_APP,
and API_VERSIONS to aignostics_sdk.constants
- Create re-export shims in packages/aignostics/src/aignostics/application
and system so existing aignostics.application / aignostics.system
import paths continue to work
- Register application and system as aignostics.cli entry points in
packages/aignostics-sdk/pyproject.toml
- Wire application_cli and system_cli into aignostics_sdk.cli
- Update tests: fix module-level imports and mock patch paths from
aignostics.application.* / aignostics.system.* →
aignostics_sdk.application.* / aignostics_sdk.system.*
- Remove xfail from smoke_test for test_slim_cli_entry_point (now passes)
and add application/system assertions
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 139 out of 224 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
packages/aignostics/src/aignostics/utils/init.py:108
find_spec("sentry")checks for a top-level package namedsentry, which does not exist on PyPI — the Sentry SDK distributes assentry_sdk. As a result,SentrySettingsis never re-exported (and the corresponding block in the slimaignostics_sdk/utils/__init__.pyis also dead code). This should probably befind_spec("sentry_sdk").
Comment on lines
+15
to
+17
| from aignostics_sdk.utils._constants import __version__ # noqa: E402 | ||
|
|
||
| API_VERSIONS: dict[str, str] = {"v1": __version__} |
| mock.patch.object(Service, "_get_public_ipv4", return_value=None), | ||
| mock.patch.object(Service, "_collect_all_settings", return_value={}), | ||
| mock.patch("aignostics.system._service.locate_subclasses", return_value=[]), | ||
| mock.patch("aignostics.utils.locate_subclasses", return_value=[]), |
Comment on lines
+78
to
+81
| if find_spec("sentry"): | ||
| from ._sentry import SentrySettings | ||
|
|
||
| __all__ += ["SentrySettings"] |
Startup time: platform import 3400ms→477ms, app._cli 4100ms→60ms.
Lazy-loading (platform/__init__.py, application/__init__.py, _client.py):
- PEP 562 __getattr__ on platform and application __init__ modules so
importing the package loads 0 codegen modules at startup
- _client.py defers ApiClient, _AuthenticatedApi, resource imports into
get_api_client() and method bodies
- application/_cli.py: _Service() lazy factory, RunState/DownloadProgress
deferred to function scope; _utils.py TYPE_CHECKING for annotation-only
platform types, runtime lazy imports inside functions
- All annotation-only codegen imports moved to TYPE_CHECKING blocks with
from __future__ import annotations across platform/ and application/
Bug fixes (downstream feedback):
- Fix aignostics.qupath conditional import: guard now checks
find_spec("aignostics.qupath") to prevent crash in slim-only envs
with ijson installed
- Rename aignx.codegen → aignostics_sdk._codegen (eliminates namespace
collision with aignx-cora-client / aignx-demeter-client); exclude
_codegen from ruff/mypy/pyright and coverage
- ENV_PREFIX = "AIGNOSTICS" kept for backward compat; __project_name__
correctly set to "aignostics-sdk" (distribution name); tests updated
to use ENV_PREFIX for env-var key construction
- Fix all mock patch() paths in tests from aignostics.* to aignostics_sdk.*
Heavy package fixes:
- GUI relative imports (.._service, .._models, .._utils) replaced with
absolute aignostics_sdk.* imports + noqa: PLC2701
- system/_gui.py: resolve assets path via _service.__file__ to work
through symlink
- application/__init__.py: PageBuilder from heavy _gui._page_builder,
not slim package
- nicegui moved from hard dep to optional [gui] extra in slim pyproject
- Boot time logging: startup_ms in trace message, DEBUG warning >2000ms
- system/_service.py: use Path(__file__).resolve() for openapi.json
Version: 1.4.3 published to GAR
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.




Purpose
This is a wiring-verification branch that merges all 9 PYSDK-133 feature branches in sequence, so the overall workspace layout can be inspected end-to-end. It is NOT the final merge path — the individual phase PRs will be reviewed separately and merged one-by-one into `feat/PYSDK-133/python-sdk-slim`. This integration branch will be rebased/recreated once all phases have landed.
Branches merged (in order)
Conflict resolutions
Agent-added fixup commits
Two commits were added on top of the 9 merge commits to make the workspace pass `uv build` and `make lint`. These represent known issues that individual phase PRs will need to address properly:
`fix(packaging): resolve LICENSE/README paths for hatchling build isolation`
Hatchling cannot follow `../../LICENSE` paths outside the package root during build isolation. Workaround: copied `LICENSE` and `README.md` into each package dir and updated references. The intended solution (a hatchling build hook, or accepted duplication) should be finalised in PYSDK-134 or PYSDK-138.
`fix(tooling): suppress new ruff/mypy/pyright issues introduced by workspace migration`
Three sub-fixes:
Validation results
Note for reviewers
Do not merge this PR directly. Review and approve the 9 individual phase PRs targeting `feat/PYSDK-133/python-sdk-slim` instead. This branch exists solely to show the full picture assembled together.