Skip to content

Docs and migration guide for the ably-pubsub-server 4.0 split - #686

Draft
umair-ably wants to merge 5 commits into
pubsub-split/release-toolingfrom
pubsub-split/docs
Draft

Docs and migration guide for the ably-pubsub-server 4.0 split#686
umair-ably wants to merge 5 commits into
pubsub-split/release-toolingfrom
pubsub-split/docs

Conversation

@umair-ably

@umair-ably umair-ably commented Sep 3, 2026

Copy link
Copy Markdown

Stacked on #684 (which is stacked on #683).

Implements plan steps 19 and 20 — row 5 of the PR-stack table in step 10b. Docs only: no code changes.

What changed

  • README.md — PyPI badge and install line move to ably-pubsub-server; new Packages section stating that ably-pubsub-core is internal, that the side flag is what buys the MAU exemption, and that the two distributions are pinned in lockstep; three factory-door quickstarts (async realtime, async HTTP, sync HTTP) replacing the single bare AblyRealtime snippet; supported-platforms table raised to Python 3.8 through 3.14; a Migrating from ably 3.x section pointing at UPDATING.md. Removes the stale "Full Realtime support unavailable" section — realtime subscribe and presence have shipped, and it pointed people at the MQTT adapter. Repo links stay ably/ably-python on this branch; Update repository references for rename to ably-pubsub-python #682 handles the rename references and will be merged forward.
  • server/README.md (rendered on PyPI) — adds a "What this package is for" section (trusted runtimes, the wire agent shape, the MAU exemption), the oldcrypto extra, the exact factory signatures, and a Documentation section. Now spells out the ably support window.
  • core/README.md — condensed; adds the lockstep exact-pin statement and a direct "install ably-pubsub-server instead" line.
  • UPDATING.md — new top section "Version 3.x (ably) to 4.0.0 (ably-pubsub-server)". The existing 2.x→3.0 sections are untouched below it.
  • CHANGELOG.md — top ## [4.0.0](...) (unreleased) entry with the compare link v3.1.2...v4.0.0, matching the file's existing format.

CONTRIBUTING.md is untouched — #684 already rewrote its release sections.

The mapping table

3.x (ably) 4.0 (ably-pubsub-server)
pip install ably pip install ably-pubsub-server
pip install ably[crypto] pip install ably-pubsub-server[crypto]
from ably import AblyRest from ably_pubsub.server import create_http_client
AblyRest(key=...) create_http_client(key=...)
from ably import AblyRealtime from ably_pubsub.server import create_realtime_client
AblyRealtime(key=...) create_realtime_client(key=...)
from ably.sync import AblyRestSync from ably_pubsub.server.sync import create_http_client
AblyRestSync(key=...) create_http_client(key=...) (from ably_pubsub.server.sync)
from ably import X (any top-level name) from ably_pubsub.server import X
from ably.types.channeloptions import ChannelOptions from ably_pubsub.server import ChannelOptions
from ably.util.crypto import CipherParams from ably_pubsub.server import CipherParams
from ably.types.message import Message from ably_pubsub.server import Message

Plus a deep-import table with one row per 3.x submodule (ably.types.presence, ably.types.channeldetails, ably.types.channelstate, ably.types.connectionstate, ably.types.stats, ably.types.tokenrequest, ably.http.paginatedresult, ably.rest.channel, ably.realtime.channel, ably.realtime.connection, ably.realtime.presence) all collapsing to the flat from ably_pubsub.server import ..., the full __all__ listed verbatim, and what ably_pubsub.server.sync omits.

How the samples were verified

Every snippet was pasted into a scratch script and run against the workspace (UV_NO_CONFIG=1 uv run python), not eyeballed. The scripts are not committed.

  • Async realtime doorcreate_realtime_client(key=..., client_id='me', auto_connect=False) constructs, and the rendered header is exactly ably-pubsub-python/4.0.0 python/3.14.6 ably-pubsub-server.

  • Async HTTP doorasync with create_http_client(...) + channel.publish(...), with the transport mocked by respx, so the publish actually executed. Asserted the Ably-Agent request header on the outbound call: same value.

  • Sync HTTP doorably_pubsub.server.sync.create_http_client(...) + channels.get(...).publish(...) under respx; publish executed, same agent header. Confirmed close() exists, so the README sample closes the client.

  • Type re-exports — every name in ably_pubsub.server.__all__ (48 after the merge) and ably_pubsub.server.sync.__all__ resolves; ChannelOptions(cipher=None) constructs.

  • agents kwargcreate_http_client(key=..., agents={'my-sdk': '1.2.3'}) yields {'my-sdk': '1.2.3', 'ably-pubsub-server': None}, which is what UPDATING claims.

  • Needs a real key: the realtime quickstart's await connection.once_async('connected') / subscribe path and any HTTP call against the live endpoint. Construction, option handling and header assembly are covered above; the connected path is exercised by the integration suite, not by these scripts.

  • The 22 newly re-exported names — every row of the deep-import table executed as a real import from ably_pubsub.server, and the sync module asserted to omit the realtime and state types it should omit. AblyException('boom', 500, 50000) confirmed to expose code/status_code.

All of the above were re-run after merging pubsub-split/release-tooling (which brought in #683's re-exports). UV_NO_CONFIG=1 uv run ruff check passes and uv run pytest test/unit is 106 passed.

Surface inaccuracies found (now fixed upstream)

  • Message, PresenceMessage, TokenRequest and ~19 other types were not re-exported from ably_pubsub.server, leaving ably_pubsub.core — which the docs simultaneously say never to import — as the only path. Fixed in Split Pub/Sub SDK into ably-pubsub-core and ably-pubsub-server #683 (c415b95) and merged forward; this branch merged it in and the migration guide now maps every one of them to the flat import.
  • There is no TokenParams class in this SDK, in 3.x or 4.0 — token params are plain dicts (auth.request_token(token_params={...}), signature confirmed as token_params: dict | None). UPDATING says so explicitly, since a reader coming from another SDK will look for it.
  • There is no separate ErrorInfo type either; AblyException (with code / status_code) is the equivalent and is exported. Also called out in UPDATING.
  • TokenDetails is re-exported from ably_pubsub.server even though it was not in ably's top level — a small superset, noted in UPDATING.

Follow-ups

  • 091d rename. If the public API renaming lands (AblyRestHttpClient etc.), every doc here needs a pass: the class names appear in the README quickstarts, the UPDATING re-export list, and the changelog entry. UPDATING carries a "naming may change before GA" draft note in the meantime, mirroring ably-ruby's.
  • LLM-facing docs and ably.com samples are a docs-team cross-SDK pass, not in this PR (plan step 20).
  • The PyPI badge at the top of the README only resolves once ably-pubsub-server exists on PyPI (plan step 15b/21). Expect a broken badge image until then.

🤖 Generated with Claude Code

umair-ably and others added 3 commits September 3, 2026 14:05
Root README: PyPI badge and install line move to ably-pubsub-server, a
Packages section stating that ably-pubsub-core is internal and the two
are versioned in lockstep, three factory-door quickstarts (async
realtime, async HTTP, sync HTTP), Python floor raised to 3.8 in the
supported-platforms table, and a pointer to the UPDATING migration
section. Drops the stale "Full Realtime support unavailable" section:
realtime subscribe and presence have shipped.

server/README.md and core/README.md are what PyPI renders for the two
distributions, so they say what each is for on their own: the server
README explains the MAU exemption the -server agent flag buys and the
exact factory signatures; the core README says not to depend on it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
New top section in UPDATING.md covering why the split happened
(PDR-091b, the MAU classification forcing function, the one-year
support window on `ably`), a mapping table that can be applied
mechanically, before/after examples for all three doors, and the
packaging changes: Python floor, extras, and the fact that `ably` and
`ably-pubsub-server` can be installed side by side because the import
packages differ.

The table is accurate against the branch rather than the plan: every
name `ably` exported at top level is re-exported from
`ably_pubsub.server`, but Message, PresenceMessage and TokenRequest are
reachable only under `ably_pubsub.core`, which the section flags as
unsupported with a request to open an issue.

Carries the same "naming may change before GA" draft note as
ably-ruby's, since 091d is still in review.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Matches the file's existing format (tree link heading, Full Changelog
compare link, "Breaking change" section pointing at UPDATING.md), marked
"(unreleased)" until the release workflow ships it.

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

coderabbitai Bot commented Sep 3, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

umair-ably added a commit that referenced this pull request Sep 3, 2026
The docs pass (#686) found the gap: 3.x users deep-imported `Message`,
`PresenceMessage` and `TokenRequest` from `ably.types.*`, and after the split
the only place those live is `ably_pubsub.core` — which the docs tell people
never to import. A type that is not re-exported here is not nameable at all by
supported means, which makes type hints and direct construction impossible.

Adds the value types a consumer legitimately names — the message, presence,
channel-detail, state-change and stats types, the two paginated result
containers, and `TokenRequest` — plus the four client-reachable object types
(`Channel`, `RealtimeChannel`, `Connection`, `RealtimePresence`) that turn up
in annotations. The sync door gets the same, minus the realtime types that have
no synchronous counterpart, and with unasync's renames applied
(`PaginatedResultSync`, `HttpPaginatedResponseSync`, `ChannelSync`).

Deliberately not included: transports, the connection manager, HTTP utilities,
encoding buffers and the encode/decode mixins. Those are implementation, and
091d may delete or reshape them.

`pubsub_reexport_test.py` now guards the list by name in both flavours, so a
future trim of the public surface has to drop a name on purpose rather than by
omission.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
umair-ably and others added 2 commits September 3, 2026 14:13
#683 added the missing re-exports, so the deep-import caveat is wrong:
Message, MessageAnnotations, Presence, PresenceMessage, PresenceAction,
TokenRequest, ChannelDetails/Status/Occupancy/Metrics, ChannelState,
ChannelStateChange, ConnectionState, ConnectionEvent,
ConnectionStateChange, PaginatedResult, HttpPaginatedResponse, Stats,
Channel, RealtimeChannel, Connection and RealtimePresence are all on
ably_pubsub.server now. Replaced the caveat with a deep-import mapping
table, one row per 3.x submodule, and listed the full supported surface
verbatim from __all__.

Also documents what the sync module omits (realtime and the state
types) and the three Sync-suffixed names, plus two names a reader will
go looking for and not find in either version: TokenParams is not a
class here (token params are plain dicts), and there is no separate
ErrorInfo -- AblyException carries code and status_code.

Every row was executed as an import against the workspace.

Co-Authored-By: Claude Opus 5 (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

Development

Successfully merging this pull request may close these issues.

1 participant