Repository navigation
v0.5.0
[0.5.0] - 2026-09-08
This release makes order handling safer: unknown nested request fields that were silently
dropped now raise validation errors, and acknowledgements without a usable status raise
OrderStatusUnknownError. Migrate shared request DTOs to their Request<Name> variants,
replace entry-point plugins with explicitly constructed resources, and update deprecated
resource names. Migration notes cover
request DTO conversion,
acknowledgement errors and affected endpoints,
configuration validation,
and extension migration;
resource renames are listed below.
Added
status_decodercan receive the endpointdomainkeyword; legacy two-argument callables
remain supported, including replacement after client construction.
Migrate existing two-argumentStatusDecoderannotations toLegacyStatusDecoderfrom
stonepy._core.status;StatusDecoderis now a protocol requiringdomain.
Signature normalization raisesTypeError("status_decoder must accept (status, status_reason) or (status, status_reason, *, domain)")
when an inspectable signature accepts neither form; uninspectable signatures retain
two-argument invocation.CallContext.utc_nowprovides an injectable UTC source for HTTP-dateRetry-After
interpretation.FakeClockgained a timezone-awareutc_startargument andutcnow();
passclock.utcnowasutc_nowto drive HTTP-date retries with virtual time.- Public exceptions support pickle round-trips with arguments and diagnostic attributes intact.
- Added
client_application,fixed_margin, andtrading_advisorclient properties and
order.get_order_including_closed(order_id, client_account_id)on both clients. - Public
stonepy.extensionsexportsBaseResource,CallContext,EndpointSpec,Param,
AuthPolicy, andStatusDomain. Clients and resources expose a read-onlycall_context
property for explicitly constructed resources. - Export
ClientConfigOverrides, a TypedDict used byClientConfig.from_env()through
Unpackso static checkers can reject unknown keywords and incompatible values. Annotate
dynamic override dictionaries withClientConfigOverrides. Consumer typing probes and an
advisory pyright CI job were added; the job is non-blocking and currently reports 8 diagnostics.
Changed
- BREAKING: Request DTOs that embed shared DTOs now use strict
Request<Name>variants;
unknown keys and tolerant instances in request positions raiseValidationError. Variant keys
must be the exact alias or Python name. The original tolerant DTOs remain available. Mappings:
ApiClientAccountWatchlistDTO->RequestApiClientAccountWatchlistDTO,
ApiClientAccountWatchlistItemDTO->RequestApiClientAccountWatchlistItemDTO,
ApiClientPreferencesOverriddenSettingSaveDTO->RequestApiClientPreferencesOverriddenSettingSaveDTO,
ApiClientPreferencesOverriddenSettingsSaveDTO->RequestApiClientPreferencesOverriddenSettingsSaveDTO,
ApiClientPreferencesOverridenSettingSaveDTO->RequestApiClientPreferencesOverridenSettingSaveDTO,
ApiClientPreferencesOverridenSettingsSaveDTO->RequestApiClientPreferencesOverridenSettingsSaveDTO,
ApiDateTimeOffsetDTO->RequestApiDateTimeOffsetDTO,
ApiFxFinancingDTO->RequestApiFxFinancingDTO,
ApiIfDoneDTOv2->RequestApiIfDoneDTOv2,
ApiKnockoutDTO->RequestApiKnockoutDTO,
ApiMarketEodDTO->RequestApiMarketEodDTO,
ApiMarketInformationDTOv2->RequestApiMarketInformationDTOv2,
ApiMarketInformationSaveDTO->RequestApiMarketInformationSaveDTO,
ApiMarketSpreadDTO->RequestApiMarketSpreadDTO,
ApiStepMarginBandDTO->RequestApiStepMarginBandDTO,
ApiStepMarginDTO->RequestApiStepMarginDTO,
ApiStopLimitOrderDTOv2->RequestApiStopLimitOrderDTOv2,
ApiTradingDayTimesDTO->RequestApiTradingDayTimesDTO,
ClientPreferenceKeyDTO->RequestClientPreferenceKeyDTO,
CorporateActionsDTO->RequestCorporateActionsDTO,
IdentifierDTO->RequestIdentifierDTO,
MarketPricesDTO->RequestMarketPricesDTO,
OrderRequestDTO->RequestOrderRequestDTO,
PreferenceDTO->RequestPreferenceDTO,
Timestamp->RequestTimestamp. - BREAKING: INSTRUCTION, ORDER, and EXECUTION_TEXT acknowledgements with missing, empty,
null, boolean, or malformed statuses raiseOrderStatusUnknownErrorbefore model validation;
itsstatusmay beNone. Empty acknowledgement bodies also raise this error. Raw checks
follow the model's first-wins key remapping, and the validated model must retain a usable
status.status_decoder=Nonebypasses acknowledgement checks, but an empty acknowledgement
body still raisesResponseParseErrorduring validation. - BREAKING:
preference.delete_user_preference,preference.save_user_preference, and
price_alert.save_pareturnstonepy.UnspecifiedResponse; import it with
from stonepy import UnspecifiedResponsefor annotations orisinstance()checks.
Empty bodies and JSON null become empty models; unexpected object fields are retained in
model_extra. The privatePassthroughResponseModelwas renamed to this class. - BREAKING:
ClientConfigvalidates base URLs, numeric types, ranges, and finiteness on
construction, raising builtinTypeErrororValueError. - BREAKING:
ClientConfigrepr omitsapp_key,password, andproxy. - BREAKING: Async paths require an
AsyncClock.CallContext.ainvoke()requires a
transport withasend()and no longer falls back to synchronous invocation; synchronous-only
clocks or transports raiseTypeError. For hand-built contexts usingAsyncSessionManager,
supply analogoncallable returning an awaitable: when refresh needs that callback,
alogon=NoneraisesTypeErrorinstead of falling back to synchronouslogon.
Prefer reusingAsyncStoneXClient.call_context. - BREAKING: Sending through an
AsyncTransportafteraclose()raisesRuntimeError,
including if it was never used. - BREAKING: The pydantic minimum is now 2.12 on Python 3.14 and newer; earlier Python versions
retain the 2.7 minimum. - Package version, default user agent, and build metadata use the single version source in
stonepy/_version.py. - The internal
safe_reprhelper redacts secret-named mapping values and uses ordinary repr
for other objects. - Source distribution includes are anchored to the package and release metadata.
- Endpoint generation rejects unresolved response types and unreviewed missing response contracts
before deleting endpoint output, including when unresolved catalog references are otherwise allowed. - Request-type generation rejects unsupported compound request parameter annotations embedding
non-root DTOs and catalog names that collide with a generated request variant.
Before regenerating, use supported request DTO bindings and resolve colliding catalog names. - Coverage now measures branches, and pre-commit hooks run ruff, format, and mypy through
the locked uv environment. - CI uses
uv sync --lockedand uv 0.12.10, checks client-regeneration drift, and requires
lowest-direct dependency tests on Python 3.11 and 3.14 plus the complete installed-wheel
smoke test directory. - Releases use pinned uv and verification tools from the locked environment, require the
same-commit reusable CI workflow, and publish exactly the verified artifacts after checking
source, tag, and distribution versions. - Documentation deployment validates strictly before publishing, and manual release versions
must match an existing tag and its source version. - Live tests require
STONEX_LIVE=1, credentials, an allowlisted HTTPS host and port, and
STONEX_LIVE_CLIENT_ACCOUNT_IDmatching the first returned client account. Missing credentials
or the account id fail collection after opt-in; disallowed targets or account mismatches fail
at setup. Runs withoutSTONEX_LIVE=1skip live tests.
Configure contributor runs using the live-test recipe.
Deprecated
clientapplication,fixedmargin,tradingadvisor, and
order_including_closedclient properties now emitDeprecationWarning. Migrate to
client_application,fixed_margin,trading_advisor, and
client.order.get_order_including_closed, respectively.
The old names still work, but their warnings become errors under-W erroror
filterwarnings = ["error"].
Removed
- BREAKING: Removed entry-point plugin discovery,
ClientConfig.enable_plugins,
ClientConfig.allow_overrides,client.plugin(),requires_stonepy, andABI_VERSION.
Remove plugin registrations and configuration; importBaseResourcefrom
stonepy.extensionsand constructMyResource(client.call_context)instead. - Removed the private
BucketedSlidingWindowLimiterhelper.
Fixed
- BREAKING:
price_alert.get_panow sends its filters in the query string. A demo API
probe confirmed that queryalertIdfiltered the results while the previous body binding
returned both probe alerts regardless of it. - Session managers expose atomic generation/header snapshots, which authentication replay
uses to prevent a peer refresh from causing a stale token to be replayed without refreshing it. - Manual logon snapshots its validated request; session managers commit its token and replay
callback together. The callback survives logoff and is replaced only by a successful manual
logon; failed refreshes leave session state intact and only successful refreshes coalesce. ClientConfig.from_env()uses dataclass defaults for fields not provided by the environment
or overrides. Unknown override names still raiseTypeError, even when their value isNone.
Invalid non-Nonebase_urloverrides now reach constructor validation and raise
TypeError("base_url must be a string")instead ofAttributeError.- Generator Ruff formatting is independent of the current working directory and uses the
source checkout's absolute project configuration. --allow-unfrozen-catalogno longer silently skips override-consumption validation;
fixture and exploratory catalogs must explicitly pass--skip-override-validationto skip it.- Consistency lint validates override consumption and rejects missing or empty
resources directories; fixture catalogs can explicitly use--skip-override-validation. - Generated contract tests compare the first dump with independent expected values and assert
response-model identity, including list item and scalar wrapper types. ApiTradeOrderResponseDTO.Statusdocumentation names the instruction domain and distinguishes
nested order lifecycle status values.- Clarify frozen-catalog endpoint coverage, authentication replay with zero retries, non-2xx
ErrorCode 4011 handling, and httpx request logging at INFO in the documentation. - Document that the bundled generator requires dev tools and the repository
pyproject.toml;
run generator commands from a source checkout or editable install. The generator stays in the wheel. - Bound session concurrency test waits and isolate live preference and watchlist round-trips
with per-test names. - Require full commit SHA pins for workflow actions.
- GetPA live probes compare query and body filters using temporary alert ids, check the
production binding, and clean up by id. - Strict live xfails restrict expected failures to contract mismatches. MD-M5 probes classify
known contract rejections, including HTTP 404, while preserving authentication, throttling,
server, and transport failures.
Security
- BREAKING:
ClientConfigrejectsbase_urlvalues containing embedded credentials. - BREAKING: DTO validation errors hide input values; response parse errors report validation locations
and types or a generic decode failure. Fallback API errors report the reason phrase and body
length instead of echoing the body; raw bodies remain available in diagnostic attributes.
Use structured exception attributes instead of matching exception text. - Secret redaction uses one
SECRET_KEYSvocabulary for mappings, headers, URL queries,
and generated model representations.