Conversation
types.py imports typing_extensions unconditionally, but the dependency was only declared for Python < 3.11. Installs on 3.11+ only worked when another package happened to pull it in transitively.
Bytes payloads (e.g. Django's request.body) were interpolated into an f-string, producing "t.b'...'" and always failing verification. The HMAC is now computed over the raw bytes. Non-ASCII signature header values no longer raise TypeError from hmac.compare_digest and fail as InvalidSignatureError. Non-UTF-8 bodies raise JsonDecodeError.
…enerator src/lettermint/_generated is written by the private lettermint/sdk-generator (emit python, next naming profile, spec 80d8ab2a2d). scripts/generate.py regenerates it, or with --check verifies it; without a generator checkout it verifies the generated headers only.
… tokens One client per mode, Lettermint and AsyncLettermint, with identical surfaces: sending_token for emails.*, team_token for every other part, no fallback between them, and a token string classified by its prefix. Sending stores no message state: emails.send/send_batch take the message and a per-call idempotency_key, and emails.compose() returns an immutable builder. The async layer is written once; scripts/unasync.py generates the sync layer from it, and the I/O-free core (request preparation, decoding, error mapping, query serialization, tag validation) is shared. Requests never follow redirects or retry, the timeout covers the whole request including the body, and every httpx exception is translated into an SDK exception with no chained request. Tokens never appear in repr, vars or pickles. Typed exceptions (APIError and subclasses, APITimeoutError, APIConnectionError, UnexpectedResponseError, RedirectError, LettermintConfigError, LettermintValidationError), typed nested query objects, iterate() generators that follow next_cursor, and a Webhook verifier that requires both signature headers, accepts any v1 and reports a reason. BREAKING CHANGE: Lettermint.email()/api(), ApiClient, AsyncApiClient, the endpoint classes, MessageTag, the 2.x exceptions and type names are removed; Python 3.10 or newer is required. See UPGRADE.md.
…l; set the release version in _version.py
UPGRADE.md has a before/after for every changed call, the full type rename table, the removed classes and types, and a ready-to-copy instruction for upgrading with a coding agent. The wheel ships UPGRADE.md inside the package.
The spec at lettermint/lettermint@0b4ecbdd23 (main, the #2582 merge) is identical to the previous pin; only the generated file headers change.
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.
Summary
A new major version, following the Lettermint SDK design agreed for all languages. The reference is the Node.js SDK 3.0 (lettermint/lettermint-node#36). Sending holds no state on the client, types are generated from the published API spec, and every SDK passes the same conformance suite.
What changes
sendingTokenand/orteamToken. A single token string is detected by prefix:lm_team_is a team token,lm_plus letters and digits is a sending token, and anything else is a config error. Each part uses its own token and never falls back to the other.emails.send(message, options),emails.sendBatch(…)and an immutable per-messagecompose()builder. The idempotency key is a per-call option. Attachments are objects.0b4ecbdd23) using its names. Enums are open, so new API values never break decoding.verify(rawBody, headers)requires bothX-Lettermint-SignatureandX-Lettermint-Delivery, accepts any matchingv1, uses a ±300 s tolerance, and keys the HMAC on the secret as-is. Reason codes are the same in every SDK.Specific to this SDK
LettermintandAsyncLetterminthave identical surfaces. The sync layer is generated from the async one withscripts/unasync.py, and CI checks that it is up to date.anyio(already pulled in by httpx).typing_extensionsis declared for every Python version; webhook verification acceptsbytes; a non-ASCII signature header no longer crashes..request.src/lettermint/_version.py, and the built wheel and sdist are checked against the tag.main(GH006). That is a repo setting, not code.Verification
--strict. 2.7.0 fails 8.Release
Publish a GitHub release
v3.0.0.Docs for all SDK majors: lettermint/lettermint#2594 (stacked on lettermint/lettermint#2590). Merge it after the releases.
🤖 Generated with Claude Code