Release v0.25.0
Merged
LC
19d ago+15468+15468+01234567890123456789012345678901234567890123456789-1096-1096-0123456789012345678901234567890123456789
Release v0.25.0
Bumps version from 0.24.0 to 0.25.0. Promotes dev ā main.
Changelog
Added
- The core error registry, generated:
mthds.protocol.problem.registryis generated from the standard's core error registry8.0.0, vendored byte for byte from the standard'sv8.0.0release invendor/mthds-error-registry/with its source tag and commit, and gives a constant per core code (CoreCode), a typed parameters model per code, reading a number strictly asJsonIntegerandJsonNumber(mthds.protocol.problem.json_types) do, never from a string or a boolean, each code's entry (CORE_CODE_SPECS) and the readings a client falls back on;CORE_ERROR_REGISTRY_VERSIONinmthds.protocol.protocoldeclares the version, andmake check-error-registryfails when the vendored files, the declared version and the generated module disagree. ProblemandProblemItem:mthds.protocol.problem.modelsreads the protocol's problem document as received, its undeclared members onmodel_extra, witheffective_domainandeffective_step_kindreading a value the protocol does not list by the code's family,effective_retryreading an unknown verdict asno,is_retryabletrue only for a retry ofyes,outcome_is_unknown,params_asto read the parameters as the code's model, and each fault oferrorsand itssuggested_fixtyped;make_client_probleminmthds.protocol.problem.client_problemsstates a client's own problem from the registry.
Changed
- Standard version
8.0.0and Protocol2.0.0(Breaking):MTHDS_STANDARD_VERSIONmoved from7.0.0to8.0.0andPROTOCOL_VERSIONfrom1.0.0to2.0.0, the release of the standard in which every error is a problem document, so a manifest'smthds_versionis evaluated against8.0.0, and^7.0.0,~7.0.0,7.*or an exact7.0.0no longer pass. - Every request error carries a problem (Breaking):
PipelineRequestError(message, *, problem)requires the failure as aProblem, read onexc.problem, and every error this package raises carries one under a registered code: an argument refused before any request leaves, byoptions,method_filesor the client, carriesclient.argument_invalidnaming the argument and the reason, andRunStillRunningError, raised on a202fromexecutethat names its run, carriesclient.follow_failedwith the run as the problem'spipeline_run_id, while a202naming no run raisesApiResponseErrorcarryingclient.outcome_unknown, since the run may exist.BlobUploadError, raised when an upload target refuses a blob, carries the target's own problem document, or else the problem its status names, its message never quoting the target's body, which an object store's refusal such as S3'sSignatureDoesNotMatchfills with the presigned signature and query that grant the write, whileresponse_bodykeeps it whole, and an upload that gets no usable answer raises it too, withstatus,status_textandresponse_bodyNone, carryingclient.unreachableorclient.timeoutas a request that creates nothing does, since a blob's upload is safe to repeat, orclient.response_unreadablewhen the target is malformed, no URL the client can send to or a header it cannot write, such as a value not in ASCII or holding a line break, its headers never quoted, and amissing_blobsanswer naming a blob the request did not list raisesApiResponseErrorcarryingclient.response_unreadable, as any success that is not its route's answer does. A subclass built elsewhere passes a problem to the constructor, and every error, thePipelineRequestErrorthatmake_argument_invalid_errorraises for a refused argument included, endsstr(exc)on the problem's next step, on a line of its own. ApiResponseErrorreads every answer as a problem by its code (Breaking): a failed answer raisesApiResponseErrorcarrying the runtime's problem document, withstatusandretry_afterfilled from the answer when the body leaves them out, and an answer that is no problem document reads asclient.outcome_unknownwhen it is a5xxonexecuteorstart, where a gateway may stand in front of a run that started, as the problem its status names for503on a route that creates nothing and for405on any route, and else asclient.response_unreadable. A success whose body is not the route's answer reads asclient.response_unreadableon a route that creates nothing, and onexecuteorstart, where the runtime accepted the request and the run may exist, asclient.outcome_unknown, naming the run as itspipeline_run_idwhen the body gives the run's id as a non-empty string; anexecuteorstartanswer whosepipeline_run_idis empty names no run, so it reads asclient.outcome_unknownnaming none, as a202onexecutedoes. Neither raises a pydantic or JSON error, andstr(exc)then quotes the start of the body the server sent, except amissing_blobssuccess's, whose upload URLs carry the permission to write and which onlyresponse_bodykeeps. An error body is decoded refusingNaN,Infinity, a number past the range of a double and nesting deeper thanMAX_BODY_NESTING(512 levels, checked before parsing), and reads an integral number such as2.0as the integer2, as a JavaScript client reads it, while a success body is decoded from its bytes asResponse.json()decodes it (decode_success_json): strictly as UTF-8, so that a body that is not UTF-8 is unreadable rather than read with its bytes replaced, refusingNaNandInfinity, and otherwise within Python's own limits, so that a run's output nested deeper or holding an integer past a double's range reads whole and its numbers stay as written, a pipe output's10.0reaching the caller as a float. The memberstype_uri,title,instance,server_message,error_type,error_domain,retryable,user_actionandvalidation_errorsare gone, read fromexc.probleminstead, and so areProblemDocumentandUserAction, whilerequest_idstays, the problem's ownrequest_idmember or else theX-Request-IDheader;mthds.runners.api.problem.read_error_answerreads an answer as anAnswerReading, its problem and whether that problem is the body's own, asmthds.protocol.problem.answers.read_answerdoes, and the protected_raise_api_response_errorreceives the problem andproblem_from_body.- A request that gets no answer raises
ApiTransportError(Breaking): httpx's transport and decoding exceptions no longer escape a route; the request raisesApiTransportError, carryingclient.unreachablewhen no request left,client.timeoutwhen none came back in time, and onexecuteandstartclient.outcome_unknownonce the request has left, since the run may exist. An answer whose body cannot be read, such as one whose content encoding cannot be decoded, is no usable answer either, whatever its status: it raisesApiTransportErrorcarryingclient.outcome_unknownonexecuteandstartandclient.unreachableon any other route, as the TypeScript client reads it. The client never repeats a request by itself. ClientNotConfiguredErrorreplacesClientAuthenticationError(Breaking): the client raises it, aPipelineRequestErrorcarryingclient.not_configuredand the setting, when no API key or base URL resolves at construction, when the API key holds a character an HTTP header cannot carry, such as a line break or a space at its end, which httpx would refuse to write at every request, when the base URL does not make a valid URL or does not start withhttp://orhttps://, or whenrequest_timeout_secondsis set to anything but anintor afloat, never abool, holding a finite number of seconds a float can hold, never negative, each reading as a setting to fix rather than as an unreachable runtime to retry; the key is never quoted, and neither is auser:password@written in the base URL, which this error's message andclient.unreachablename without its userinfo, query and fragment.- The validate verdict's items are problem items (Breaking):
InvalidValidationReport.errorsreplacesvalidation_errors, each fault aProblemItemwith itscode,detail,params,locationandsuggested_fix, both arms carry advisorywarningsin the same schema, and the invalid arm'smessageis optional; the reports are generic over the item type, andValidationDiagnosticis gone.
š¤ Generated with Claude Code
https://claude.ai/code/session_01MTPBJkbpj7cQMqEfePgfDU
Summary by cubic
Promotes dev to main for the v0.25.0 release: bumps the version to 0.25.0 and implements the MTHDS standard 8.0.0 and Protocol 2.0.0, in which every error is a problem document. This is a breaking release.
Breaking changes
PipelineRequestErrornow requires aproblem; every error this package raises carries one under a registered code.ApiResponseErrorreads any answer as a problem by code; run routes that get a202naming no run, or an unreadable success, raiseclient.outcome_unknown.- Requests that get no usable answer raise
ApiTransportError(client.unreachable,client.timeout, orclient.outcome_unknown) instead of leaking httpx exceptions. ClientAuthenticationErroris replaced byClientNotConfiguredError, carryingclient.not_configured.- A validate verdict's
validation_errorsbecomeerrorsofProblemItems;ProblemDocumentandUserActionare removed. - A manifest's
mthds_versionis now evaluated against8.0.0, so^7.0.0,~7.0.0,7.*, and7.0.0no longer pass.
New
- Vendors the core error registry 8.0.0 and generates
mthds.protocol.problem.registry: a constant (CoreCode) and typed parameters model per code, strictJsonInteger/JsonNumberreading, and amake check-error-registrygate that fails when the vendored files, declared version, and generated module disagree. ProblemandProblemItemread documents as received, keeping undeclared members onmodel_extra.BlobUploadErrornow carries problems too: an object store's refusal, an unrequested blob in amissing_blobsanswer, or an upload target the client cannot send to.