Repository navigation
ENG-3760: export user-facing v2 names from the package root - #1167
Conversation
`aixplain/__init__.py` star-re-exports `aixplain.v2.__all__`, but several commonly used public classes were never in that list, so users, docs, tests and downstream repos had to write `from aixplain.v2.<module> import X`. Add the missing user-facing names to `aixplain/v2/__init__.py` (imports + `__all__`), so `from aixplain import Model, Integration, ModelResult, AgentRunResult, ToolResult, ActionSpec, ActionInputSpec, Result, Parameter, Usage, StreamChunk, Node, AUTO_DEFAULT_MODEL_ID, ...` works. The versioned path keeps working unchanged. Fix `aixplain.exceptions` shadowing: it carried v1-era `ValidationError`/`ResourceError` that nothing in `aixplain.v2` raised, so `from aixplain.exceptions import ValidationError` silently caught nothing. It now re-exports the v2 classes the SDK actually raises; v1-only types stay in `aixplain.exceptions.types`. - Add `tests/unit/v2/test_public_exports.py`: every public class in `aixplain/v2/` must be root-exported or on an explicit internal allowlist. - Rewrite SDK tests and docs to root imports; llms bundles use root imports. - Regenerate the API reference with a `from aixplain import ...` line on each page; `docs/import-paths.md` records the export-vs-internal rule. - CHANGELOG + MIGRATION "Import paths" carry the old -> new mapping. Breaking changes: - `aixplain.exceptions.ValidationError` / `ResourceError` now resolve to the v2 classes the SDK raises (previously v1 look-alikes that caught nothing). - `api_sidebar.js` drops stale `aixplain.v1.*` entries and `aixplain.utils.*` pages for modules that no longer exist (regenerated snapshot).
elsheikhams99
left a comment
There was a problem hiding this comment.
Self-review: request changes (small). The export change itself is correct: all 30 new root names are the same objects as the v2 originals, with no collisions. The guard test fails for each of the cases it targets. Two problems introduced by this PR should be fixed before review, plus a few nits. Fixes are coming in a follow-up commit on this branch.
Fix before review
1. aixplain.exceptions now mixes two hierarchies that disagree (aixplain/exceptions/__init__.py). I ran these checks on both base and branch:
| base | branch | |
|---|---|---|
isinstance(get_error_from_status_code(400), aixplain.exceptions.ValidationError) |
True | False |
same for 403/404/465 with ResourceError |
True | False |
ValidationError subclass of aixplain.exceptions.AixplainBaseException |
True | False |
aixplain.exceptions.ValidationError("x", status_code=400) |
works | TypeError |
The package's own helper now returns errors that its own ValidationError does not catch. It is the same "catches nothing" bug in the opposite direction. The only downstream user I found in the org is aixplain/agentification, which imports get_error_from_status_code. It catches with its own exception types, so nothing I could find breaks. Fix: document that get_error_from_status_code and AixplainBaseException belong to the v1 hierarchy, and list the constructor and base-class changes in the CHANGELOG/MIGRATION breaking-change notes.
2. docs/llms.txt lost its module descriptions. _extract_summary uses the first paragraph of each page, which is now the import line. As a result, 25 entries changed from text like "Agent module for aiXplain v2 SDK." to a bare `from aixplain import …` list. Fix: skip the import-line paragraph when extracting the summary.
Non-blocking
README.md:90still hasfrom aixplain.v2 import Inspector. Onlydocs/README.mdwas rewritten.docs/import-paths.md:24says*Typealiases,plain_datahelpers andcreate_operation_failed_errorare on the guard allowlist. The guard only inspectsclassstatements, andcreate_operation_failed_erroris exported fromaixplain.exceptions.__all__.- The guard only sees
classstatements. A functionalTypedDictorUnionalias would slip through. Nothing slips through today: every unexported non-class name is an internal constant orTypeVar. - No test pins
from . import exceptionsin the root__init__. Removing it leaves all 195 guard tests green, whileaixplain.exceptionsbecomes unbound afterimport aixplain. post_process_docs.pyis not idempotent: a second run adds a second import line to each page.docs/rfcs/rfc-static-graph-agents.md:128moves the not-yet-existingParallelNodeontoaixplain.v2.graph.docs/api-reference/.../v2/utility.mdis an orphan page for a removed module. This predates the PR.- The rewritten test imports add 8 lines over 120 characters.
- Most of the 9.7k-line
llms-full.txtdiff is catch-up regeneration, since docs were last regenerated on 2026-07-24. It is not caused by this change.
Verified
- Unit tests: 2602 passed and 3 failed on the branch, against 2407 passed and the same 3 failed on merge base
fb549f5c. The failures are intest_client.py::TestRateLimitAndJitteredRetryand come from the local urllib3, which lacksRetry.retry_after_max. The extra 195 are the new guard tests. - Guard mutation tests: the guard fails on an unexported new class, on
Modelremoved from__all__, and onexceptions/__init__.pyreverted to base. - Lint: ruff 0.12.12 is clean on
aixplain/v2. - Imports: importing
aixplain.exceptionsfirst causes no import cycle. The functional suite collects (186 tests). - Docs: all 180
from aixplain importnames in the changed docs resolve. Every page inapi_sidebar.jsexists (base had 135 dangling entries). Regeneratingllms*.txtand the API reference produces byte-identical output. - Not verified: the functional suite was not run (CI only ran
pre-commit). I did not check the Jira ticket or theaixplain-agentsfollow-up.
- Document that aixplain.exceptions holds two hierarchies: get_error_from_status_code returns the v1 classes from aixplain.exceptions.types, which the re-exported v2 ValidationError / ResourceError do not catch. CHANGELOG and MIGRATION now list the full breaking change (v2 constructor, no v1 attributes, no longer AixplainBaseException subclasses). - generate_llms_full.py: skip the `from aixplain import` line when extracting a module summary, so llms.txt keeps its descriptions. - post_process_docs.py: replace an existing root-import line instead of adding a second one, so the script can be re-run. - Tests: pin the root `aixplain.exceptions` binding (fresh interpreter) and the documented v1/v2 split; ruff-format the rewritten imports. - Docs: root README/docs README use `from aixplain import Aixplain, Inspector`; import-paths.md states the guard only checks classes; RFC imports ParallelNode from the root; drop the orphaned v2/utility.md page; regenerate the two exceptions API pages.
Resolve conflict in aixplain/v2/__init__.py with #1168: keep ToolResult alongside the new ToolBatch / SkillBatch exports.
Take development's README (#1161 removed the multi-agent section whose import this branch had rewritten).
- aixplain.exceptions exports only the v2 classes the SDK raises. The v1 hierarchy (AixplainBaseException, AuthenticationError, ..., get_error_from_status_code) is no longer re-exported, so the package no longer mixes two hierarchies whose same-named classes don't catch each other. It stays in aixplain.exceptions.types. CHANGELOG/MIGRATION list the removed re-exports. - Drop create_operation_failed_error from aixplain.exceptions; the ticket keeps it internal (aixplain.v2.exceptions). - AGENTS.md: point the exceptions rule at the v2 hierarchy and mention the public-exports guard test. - post_process_docs.py: read aixplain/v2/__init__.py next to the script and fail loudly if missing; drop a stale root-import line when a module no longer exports anything. - eval_dashboard/app.py, test_agent_eval.py: root imports. - Regenerate the API reference and llms files for the merged ToolBatch/SkillBatch (#1168) and progress (#1153) changes.
aixplain-agents imports the private aixplain.v2.resource._flatten_asset_info and re-implements Resource.get's deserialization by hand to build Model/Tool handles from cached batch rows. Add GetResourceMixin.from_row: on a client-bound class (aix.Model.from_row(row)) it does exactly what get() does with the response -- flatten assetInfo, from_dict, bind context, record server fields, mark saved -- without a request, and without mutating the row. Also move the tests merged from development (get_many, nested progress) to root imports, and regenerate the resource API page and llms-full.txt.
- Inspector: get() now goes through an overridden _from_row hook that adapts the guard model via from_guard_model, so aix.Inspector.from_row(row) builds the same configured guard as get() instead of deserializing the guard model as an Inspector. One hook means get and from_row cannot drift. - from_row deep-copies the row (as get_many does), so edits to the instance never reach a cached raw row. - test_public_exports: an exported name must be the class defined in that module, catching a same-named class in another v2 module. - docs/v2-plain-data.md: classify PromptTokensDetails and CompletionTokensDetails as output objects. - post_process_docs.py: sort and de-duplicate names per module. - aixplain/v2/__init__.py: ToolDict & co. are as_tool() output, not inputs.
Middle ground before dropping the v1 hierarchy from aixplain.exceptions: - AixplainBaseException, AuthenticationError, AlreadyDeployedError, BillingError, SupplierError, NetworkError, ServiceError, InternalError and get_error_from_status_code resolve again from aixplain.exceptions through a module __getattr__ that emits a DeprecationWarning naming aixplain.exceptions.types and the 0.4.0 removal. They stay off __all__, so import aixplain and star-imports do not warn. - The v1 ValidationError / ResourceError in aixplain.exceptions.types also subclass the v2 classes, so except aixplain.ValidationError catches what get_error_from_status_code returns. AixplainBaseException.__init__ calls super() first so the v2 base cannot reset details. - CHANGELOG, MIGRATION and docs/import-paths.md describe the deprecation.
aixplain/__init__.pystar-re-exportsaixplain.v2.__all__, but several commonly used public classes were never in that list, so users, docs, tests and downstream repos had to writefrom aixplain.v2.<module> import X.Add the missing user-facing names to
aixplain/v2/__init__.py(imports +__all__), sofrom aixplain import Model, Integration, ModelResult, AgentRunResult, ToolResult, ActionSpec, ActionInputSpec, Result, Parameter, Usage, StreamChunk, Node, AUTO_DEFAULT_MODEL_ID, ...works. The versioned path keeps working unchanged.Fix
aixplain.exceptionsshadowing: it carried v1-eraValidationError/ResourceErrorthat nothing inaixplain.v2raised, sofrom aixplain.exceptions import ValidationErrorsilently caught nothing. It now re-exports the v2 classes the SDK actually raises; v1-only types stay inaixplain.exceptions.types.tests/unit/v2/test_public_exports.py: every public class inaixplain/v2/must be root-exported or on an explicit internal allowlist.from aixplain import ...line on each page;docs/import-paths.mdrecords the export-vs-internal rule.Breaking changes (old → new)
Needs a UI/docs team ack before merge (ENG-3760).
aixplain.exceptionsaixplain.exceptions.ValidationError/ResourceError: v1 classes → the v2 classes the SDK raises (same objects asaixplain.ValidationError/aixplain.ResourceError). The v2 constructor is(message, details=None), and the v1 attributes (status_code,error_code,category) are gone.aixplain.exceptions.{AixplainBaseException, AuthenticationError, AlreadyDeployedError, BillingError, SupplierError, NetworkError, ServiceError, InternalError, get_error_from_status_code}→ deprecated inaixplain.exceptions(still resolve, with aDeprecationWarning; removed in 0.4.0); import them fromaixplain.exceptions.types. The v1ValidationError/ResourceErrorthatget_error_from_status_codereturns now also subclass the v2 classes, soexcept aixplain.ValidationErrorcatches them.API reference pages /
api_sidebar.jsentries (docs/api-reference/python/...)aixplain/v1/**(124 sidebar entries) → removed (v1 was removed in 0.3.0)aixplain/utils/{asset_cache, cache_utils, convert_datatype_utils, evolve_utils, file_utils, llm_utils, request_utils, validation_utils}→ removed (modules no longer exist)aixplain/v2/utility(page and sidebar entry) → removed (module removed withaix.Utility)aixplain/v2/enums_include,aixplain/_compat,aixplain/cli_groups→ removed from the sidebar (no page existed)aixplain/v2/graph,aixplain/v2/plain_data,aixplain/utils/url_safetyaixplain/v2/<module>page now starts with a`from aixplain import ...`line. Module paths and file names are unchanged.Non-breaking (release notes only): 30 new root exports (see CHANGELOG).
from aixplain.v2.<module> import Xkeeps working.Follow-up: aixplain/aixplain-agents#461 switches agents to root imports and
from_row(draft; blocked until an SDK release contains this).