You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Merge origin/master into feat/split-api-workspaces-25
Integrates PR #30 (typed models + schema validation) with PR #31's
services-split structure. Conflicts in api/composers.py and
api/workspaces.py because both PRs touched the same read paths from
different angles: #30 added Bubble.from_dict / Composer.from_dict /
Workspace.from_dict gates inline in api/, #31 extracted those read
paths into services/ before #30's gates landed.
Resolution:
* api/composers.py — took master's version wholesale. Master already
has both #31's simplification (uses utils.workspace_descriptor._read_json_file
instead of an inline copy) AND #30's typed-model gates. Nothing to
merge structurally; the file is what #30 produced over #31's earlier
cleanup.
* api/workspaces.py — kept HEAD's 146-line services-split structure
(the whole point of #31). Added two re-exports for the test harness:
`from models import Bubble, Composer, Workspace` so that #30's
spy-based regression tests in test_models_wired_at_read_sites.py
can resolve `workspaces_mod.Bubble.from_dict` etc.; and
`_get_workspace_display_name` re-exported from services.workspace_resolver
so test_workspace_display_name_calls_workspace_from_dict still works.
Services rewiring (so #30's contract holds after the #31 structural
split — the from_dict gates have to live wherever the read paths
actually run):
* services/workspace_tabs.py:
- bubble loader now goes through `Bubble.from_dict(...)` with
`except SchemaError -> print drift line + skip`,
`except (JSONDecodeError, ValueError) -> silent skip`. Matches
the pattern api/workspaces.py used to have inline.
- composer loader goes through `Composer.from_dict(...)` with the
same try/except split.
- renamed local `bubble = Bubble.from_dict(...)` to `bubble_obj`
because the same function scope later has `bubble = bubble_map.get(...)`
pulling raw dicts back out, and the shadowing tripped mypy.
* services/workspace_resolver.py:
- `_get_workspace_display_name` now validates the workspace.json
payload via `Workspace.from_dict(...)` with narrow
`(SchemaError, OSError, ValueError)` catch instead of bare
`except Exception`. Same shape as the api/workspaces.py inline
version master has today.
Verified locally on the merged tree:
- mypy --ignore-missing-imports --no-strict-optional . → Success
- ruff check api/ utils/ scripts/export.py app.py services/ → All checks passed
- unittest discover tests → 253 / 253 OK (including all 11 typed-model
wiring regression tests from #30 — Bubble.from_dict / Composer.from_dict
/ Workspace.from_dict / WorkspaceLocalComposer.from_dict are now
verifiably called from the services-side read paths)
0 commit comments