Skip to content

feat: initial Python SDK workspace - #1

Merged
calvin-archastro merged 2 commits into
mainfrom
feat/initial-setup
Apr 17, 2026
Merged

feat: initial Python SDK workspace#1
calvin-archastro merged 2 commits into
mainfrom
feat/initial-setup

Conversation

@calvin-archastro

Copy link
Copy Markdown
Contributor

Summary

First PR for this repo. Moves the Python Platform SDK out of firstlanding-wt5/src/python/platform-sdk and wires it to regenerate via the now-standalone @archastro/sdk-generator and @archastro/channel-harness tools on npmjs.com. Same pattern we landed in archastro-js.

Layout

Path What
src/archastro/ Generated SDK — Pydantic models, resources, channel classes, auth helpers. Regenerated by scripts/regenerate_sdk.sh.
src/phx_channel/ Hand-written Phoenix Channels client (Socket, Channel, HarnessServiceClient) + unit tests.
specs/platform-openapi.json Local copy of the spec pulled from ArchAstro/archastro-openapi.
tests/test_http_client.py Unit tests for the HttpClient 401 auto-refresh.
tests/harness/ Drives HarnessServiceClient against a real @archastro/channel-harness subprocess using the LiveDoc fixture spec.
tests/contract/ Auto-generated REST + channel contract suites.

Regeneration flow

scripts/regenerate_sdk.sh curls the spec from archastro-openapi@main (override with ARCHASTRO_OPENAPI_REF), runs npx @archastro/sdk-generator@latest for both --lang python and --lang contract-tests-py, then applies ruff --fix + ruff format so the committed output matches CI's style gate. ARCHASTRO_SDK_GENERATOR env var pins the generator version for release branches.

JS tooling deps

Contract tests spawn Node subprocesses, so the repo carries a package.json:

  • @archastro/channel-harness@^0.1.0 — the harness subprocess
  • @stoplight/prism-cli@5.14.2 — Prism mock server for REST contract tests. Pinned to 5.14.2 because 5.15.x ships broken tarballs without dist/. Also uses overrides to pin @stoplight/prism-core / prism-http / prism-http-server to known-good versions so a fresh npm ci doesn't pull the broken 5.15 peers.

CI

Matrix on Python 3.11 + 3.12:

  1. npm ci (channel-harness + prism)
  2. uv sync --all-extras
  3. ruff check
  4. ruff format --check
  5. Unit tests
  6. Harness-client integration tests
  7. Contract tests with ARCHASTRO_RUN_CHANNEL_CONTRACT_TESTS=1 — real harness subprocess over WebSocket + HTTP

Dropped from the firstlanding copy

  • tests/test_synthetic.py and tests/conftest.py — needed a running local platform-rs for credentials bootstrap.
  • src/phx_channel/tests/test_channel.py and its conftest — needed an Elixir Phoenix test server at src/elixir/test/channel_test_server. The same wire contract is exercised by tests/harness/ and tests/contract/channels/ through the published @archastro/channel-harness.
  • aster.toml — firstlanding-internal.

Scope / risk

Full-stack new repo, no consumers yet. Low risk. The firstlanding copy is untouched; when the consumer cutover lands, the old tree can be retired.

Testing

  • uv run pytest tests/test_http_client.py src/phx_channel/tests/test_unit.py tests/harness49 passed
  • ARCHASTRO_RUN_CHANNEL_CONTRACT_TESTS=1 uv run pytest tests/contract641 passed (incl. all 3 channel contract suites over a real harness subprocess)
  • uv run ruff check && uv run ruff format --check → clean
  • CI matrix will verify on both Python 3.11 and 3.12

Follow-ups

  • Publish archastro-platform-sdk to PyPI (first release from this repo: 0.77.0).
  • Retire src/python/platform-sdk/ in firstlanding-wt5 once downstream consumers are cut over.

🤖 Generated with Claude Code

First PR for this repo. Moves the Python Platform SDK out of the
firstlanding monorepo and wires it to regenerate via the now-standalone
@archastro/sdk-generator and @archastro/channel-harness tools published
on npmjs.com.

Layout:

  src/archastro/          Generated SDK: Pydantic models, resources,
                          channel classes, auth helpers. Produced by
                          scripts/regenerate_sdk.sh — DO NOT hand-edit.
  src/phx_channel/        Hand-written Phoenix Channels client the
                          generated channel classes run on top of:
                          Socket, Channel, HarnessServiceClient, plus
                          pure-unit tests.
  specs/                  Local copy of platform-openapi.json pulled
                          from ArchAstro/archastro-openapi.
  tests/                  test_http_client.py (unit), harness/ (drives
                          @archastro/channel-harness with the LiveDoc
                          fixture), contract/ (generated REST + channel
                          contract suites).

Regeneration
  scripts/regenerate_sdk.sh curls the spec from archastro-openapi@main
  (overridable with ARCHASTRO_OPENAPI_REF) and runs npx
  @archastro/sdk-generator for both the SDK and contract-test tree,
  then applies ruff --fix + ruff format so the committed output matches
  CI's style gate. Tool version overridable via ARCHASTRO_SDK_GENERATOR.

JS tooling deps (for contract tests to spawn the harness and Prism):
  @archastro/channel-harness@^0.1.0
  @stoplight/prism-cli@5.14.2 (pinned — 5.15.x ships broken tarballs)
  overrides pin the prism-core / prism-http trio to working versions so
  a fresh `npm ci` doesn't pull the broken 5.15 deps.

CI (Python 3.11 + 3.12 matrix): ruff check, ruff format --check, unit
tests, harness-client integration tests, REST+channel contract tests
over a real channel-harness subprocess.

Dropped from the firstlanding copy
  - tests/test_synthetic.py and tests/conftest.py — depended on a
    running local platform-rs for credentials bootstrap.
  - src/phx_channel/tests/test_channel.py and its conftest — depended
    on an Elixir Phoenix test server at src/elixir/test/channel_test_server.
    The same channel wire contract is exercised by tests/harness/ and
    tests/contract/channels/ through the npm-installed channel-harness.
  - aster.toml — firstlanding-internal.

Local verification
  49 non-contract tests pass (http_client unit, phx_channel unit,
  harness-client integration); 641 contract tests pass including the
  three channel contract suites over a real WebSocket + HTTP harness
  subprocess; ruff clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

self._state = "joining"
ref = self._socket._make_ref()
self._join_ref = ref

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

asyncio.get_event_loop().create_future() is deprecated since Python 3.10 and raises a DeprecationWarning (eventually a hard error) when called outside a running loop — which can happen in certain test runners and Python 3.12 edge cases; use asyncio.get_running_loop().create_future() here and on the identical call sites at lines 108 and 139.

return await self._on_refresh_token() # type: ignore[misc]
finally:
self._refresh_task = None

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_refresh_task is nulled in the finally block before all concurrent waiters have latched the result: waiter A and B both await self._refresh_task, but a waiter C that gets a 401 after the finally fires but before A/B retry will see _refresh_task is None and start a second refresh call — defeating the "one refresh at a time" invariant the test suite verifies. Fix: clear _refresh_task only after every pending waiter has resolved (e.g. clear it at the callsite after await self._refresh_task completes, protected by a lock, or store the result before nulling the task).

Comment thread .gitignore Outdated
.pytest_cache/
.ruff_cache/
.venv/
uv.lock

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

uv.lock is gitignored — every CI run resolves fresh deps, meaning two matrix jobs on the same commit can install different transitive versions and you lose the reproducibility that's the whole point of using uv; commit the lockfile and remove this line.

Comment thread README.md
uv sync # Python deps + dev deps (pytest, ruff)
```

### Running tests

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

src/phx_channel/tests/unit.test.py doesn't exist — the actual file is src/phx_channel/tests/test_unit.py; this command will fail for anyone who copies it.

The `setup-uv` action's default cache key is `**/uv.lock`; without a
committed lockfile the first step fails with
"No matches found for glob". Committing the lock is also standard
practice for a uv-managed library repo — CI gets reproducible
installs and dep changes show up in PR diffs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@calvin-archastro
calvin-archastro merged commit 231f470 into main Apr 17, 2026
2 checks passed
calvin-archastro added a commit that referenced this pull request Apr 17, 2026
Fresh-start rename — ship as archastro-sdk 0.1.0 rather than inheriting
archastro-platform-sdk 0.77.0 from the firstlanding import. These
changes were on feat/initial-setup but got left behind when PR #1
merged; rebasing onto main now that PR #2's flake fix is in.

- pyproject.toml: name → archastro-sdk, version → 0.1.0
- scripts/sdk-generator-config.json: matches
- README: pip install archastro-sdk
- src/archastro/platform/__init__.py: patched to look up
  \"archastro-sdk\" via importlib.metadata. This file is
  auto-generated; the generator fix that will make this automatic is
  ArchAstro/archastro-openapi#4 — once that ships in
  @archastro/sdk-generator@0.1.1+, future regens produce the right
  output without patching.
- uv.lock: regenerated

The Python import path (`archastro`) is unchanged — only the
pip-install name and the __version__ lookup key change.

Local verification
  uv run python -c \"import archastro.platform; print(archastro.platform.__version__)\"
  → 0.1.0

Test suite: 51 non-contract tests + 641 contract tests (incl. channel
suites over a real @archastro/channel-harness subprocess) all pass;
ruff check + format clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant