From 432727ff4704744a6535c1e6240cb6ee403b6a51 Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Fri, 15 Aug 2025 16:51:34 -0700 Subject: [PATCH 1/9] Begin to address William's feedback. * Require that `name` conform to the normalization rules, and include a link * Require that `version` conform to the version specs, and include a link * RFC 3399 instead of ISO 8601 as the timestamp spec. The RFC is a simpler format that subsets the ISO standard, and is more appropriate to our use case. * Adjust the gentoken() algorithm to be more resistant to tomfoolery. This may still change. * Require `filename` to conform to either the source or binary distribution file name convention, and include links --- peps/pep-0694.rst | 44 +++++++++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/peps/pep-0694.rst b/peps/pep-0694.rst index 0100d132c01..54cb0db9a17 100644 --- a/peps/pep-0694.rst +++ b/peps/pep-0694.rst @@ -339,10 +339,15 @@ The request includes the following top-level keys: ``api-version`` the value of which must be the string ``"2.0"``. ``name`` (**required**) - The name of the project that this session is attempting to release a new version of. + The name of the project that this session is attempting to release a new version of. The name + **MUST** conform to the `standard package name format + `__ + and the server **MUST** normalize the name. ``version`` (**required**) - The version of the project that this session is attempting to add files to. + The version of the project that this session is attempting to add files to. The version string + **MUST** conform to the `packaging version + `_ specification. ``nonce`` (**optional**) An additional client-side string input to the @@ -414,13 +419,14 @@ the following keys: If the index does *not* support stage previewing, this key **MUST** be omitted. ``expires-at`` - An ISO8601 formatted timestamp string representing when the server will expire this session, - and thus all of its content, including any uploaded files and the URL links related to the - session. The session **SHOULD** remain active until at least this time - unless the client itself has canceled or published the session. Servers **MAY** choose to - extend this expiration time, but should never move it earlier. - Clients can query the :ref:`session status ` - to get the current expiration time of the session. + An :rfc:`3339` formatted timestamp string; this string **MUST** represent a UTC timestamp using the + "Zulu" (i.e. ``Z``) marker, and use only whole seconds (i.e. no fractional seconds). This + timestamp represents when the server will expire this session, and thus all of its content, + including any uploaded files and the URL links related to the session. The session **SHOULD** + remain active until at least this time unless the client itself has canceled or published the + session. Servers **MAY** choose to extend this expiration time, but should never move it + earlier. Clients can query the :ref:`session status ` to get the current + expiration time of the session. ``status`` A string that contains one of ``pending``, ``published``, ``error``, or ``canceled``, @@ -585,8 +591,8 @@ following Python code as an example: def gentoken(name: bytes, version: bytes, nonce: bytes = b''): h = sha256() - h.update(name) - h.update(version) + h.update(f'{len(name)}'.encode('ascii') + name) + h.update(f'{len(version)}'.encode('ascii') + version) h.update(nonce) return h.hexdigest() @@ -634,7 +640,14 @@ The request looks like: Besides the standard ``meta`` key, the request JSON has the following additional keys: ``filename`` (**required**) - The name of the file being uploaded. + The name of the file being uploaded. The filename **MUST** conform to either the `source + distribution file name specification + `_ + or the `binary distribution file name convention + `_. + Indexes **SHOULD** validate these file names at the time of the request, returning a ``400 Bad + Request`` error code, as described in the :ref:`session-errors` section when the file names do + not conform. ``size`` (**required**) The size in bytes of the file being uploaded. @@ -722,9 +735,10 @@ the following keys: indicating the current state of the File Upload Session. ``expires-at`` - An ISO8601 formatted timestamp string representing when the server will expire this File Upload Session. - The session **SHOULD** remain active until at least this time - unless the client cancels or completes it. Servers **MAY** choose to + An :rfc:`3339` formatted timestamp string representing when the server will expire this File Upload + Session. This string **MUST** represent a UTC timestamp using the "Zulu" (i.e. ``Z``) marker, + and use only whole seconds (i.e. no fractional seconds). The session **SHOULD** remain active + until at least this time unless the client cancels or completes it. Servers **MAY** choose to extend this expiration time, but should never move it earlier. ``mechanism`` From bcc345b740e25f1fe24dea07ec093fbf708cc1e3 Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Thu, 21 Aug 2025 18:04:09 -0700 Subject: [PATCH 2/9] Further updates based on DPO thread * The addition of the ``Location`` header is now a **MUST**, and better worded to indicate that it can be polled in the case of a ``202 Accepted``. * Added a couple of **FIXME** tags to address removal of nonce and fleshing out the ``Errors`` section. See URLs in the text. DO NOT PROMOTE FROM DRAFT UNTIL THIS IS DONE. * Reformatted some text. --- peps/pep-0694.rst | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/peps/pep-0694.rst b/peps/pep-0694.rst index 54cb0db9a17..1ad78b169ad 100644 --- a/peps/pep-0694.rst +++ b/peps/pep-0694.rst @@ -81,12 +81,9 @@ In addition, there are a number of major issues with the legacy API: * Creation of new projects requires the uploading of at least one file, leading to "stub" uploads to claim a project namespace. -The new upload API proposed in this PEP provides ways to solve all of these problems, -either directly or through an extensible approach, -allowing servers to implement features such as resumable and parallel uploads. -This upload API this PEP proposes provides -better error reporting, -a more robust release testing experience, +The new upload API proposed in this PEP provides ways to solve all of these problems, either directly or +through an extensible approach, allowing servers to implement features such as resumable and parallel uploads. +This upload API this PEP proposes provides better error reporting, a more robust release testing experience, and atomic and simultaneous publishing of all release artifacts. Legacy API @@ -276,6 +273,8 @@ are determined by the index operator. Errors ------ +**FIXME**: https://discuss.python.org/t/pep-694-pypi-upload-api-2-0-round-2/101483/20 + All error responses that contain content look like: .. code-block:: json @@ -331,6 +330,8 @@ A release starts by creating a new Publishing Session. To create the session, a "nonce": "" } +**FIXME: (get rid of ``nonce``): https://discuss.python.org/t/pep-694-pypi-upload-api-2-0-round-2/101483/22 + The request includes the following top-level keys: @@ -528,10 +529,9 @@ If the server is able to immediately complete the Publishing Session, it may do (for instance, if it needs to do validation that may take longer than reasonable in a single HTTP request), then it may return a ``202 Accepted`` response. -In either case, the server should include a ``Location`` header pointing back to -the Publishing Session status URL, -and if the server returned a ``202 Accepted``, -the client may poll that URL to watch for the status to change. +The server **MUST** include a ``Location`` header in the response pointing back to the :ref:`Publishing +Session status ` URL, which can be used to query the current session status. If the server +returned a ``202 Accepted``, polling that URL can be used to watch for session status changes. If an error occurs, the appropriate ``4xx`` code should be returned, as described in the :ref:`session-errors` section. @@ -683,16 +683,12 @@ the file to be uploaded. These checks may include, but are not limited to: - checking if the contents of the ``metadata``, if provided, are valid. -If the server determines that upload should proceed, it will return a ``202 Accepted`` response, -with the response body below. -The :ref:`status ` of the session will also include -the filename in the ``files`` mapping. -If the server cannot proceed with an upload because -the ``mechanism`` supplied by the client is not supported -it **MUST** return a ``422 Unprocessable Entity``. -If the server determines the upload cannot proceed, -it **MUST** return a ``409 Conflict``. -The server **MAY** allow parallel uploads of files, but is not required to. +If the server determines that upload should proceed, it will return a ``202 Accepted`` response, with the +response body below. The :ref:`status ` of the session will also include the filename in the +``files`` mapping. If the server cannot proceed with an upload because the ``mechanism`` supplied by the +client is not supported it **MUST** return a ``422 Unprocessable Content``. The server **MAY** allow parallel +uploads of files, but is not required to. If the server determines the upload cannot proceed, it **MUST** +return a ``409 Conflict``. .. _file-upload-session-response: From 9c23652c84971ffed9c44535c82f5910698464b7 Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Thu, 21 Aug 2025 18:22:26 -0700 Subject: [PATCH 3/9] Fix markup --- peps/pep-0694.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/peps/pep-0694.rst b/peps/pep-0694.rst index 1ad78b169ad..7993186d804 100644 --- a/peps/pep-0694.rst +++ b/peps/pep-0694.rst @@ -330,7 +330,7 @@ A release starts by creating a new Publishing Session. To create the session, a "nonce": "" } -**FIXME: (get rid of ``nonce``): https://discuss.python.org/t/pep-694-pypi-upload-api-2-0-round-2/101483/22 +**FIXME**: (get rid of ``nonce``): https://discuss.python.org/t/pep-694-pypi-upload-api-2-0-round-2/101483/22 The request includes the following top-level keys: From d69686e6280b5a07d72b486534dd61b636f4af8c Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Fri, 22 Aug 2025 12:00:46 -0700 Subject: [PATCH 4/9] Remove all mention of the nonce Based on discussions here: https://discuss.python.org/t/pep-694-pypi-upload-api-2-0-round-2/101483/22 clients no longer supply a nonce to influence the session token and stage URL. The calculation of these is left to the index, but language is added that if provided, they must be cryptographically unguessable, and it must be possible to calculate the stage URL from the session token. --- peps/pep-0694.rst | 96 ++++++++++++++--------------------------------- 1 file changed, 29 insertions(+), 67 deletions(-) diff --git a/peps/pep-0694.rst b/peps/pep-0694.rst index 7993186d804..41c7d0d714b 100644 --- a/peps/pep-0694.rst +++ b/peps/pep-0694.rst @@ -327,12 +327,8 @@ A release starts by creating a new Publishing Session. To create the session, a }, "name": "foo", "version": "1.0", - "nonce": "" } -**FIXME**: (get rid of ``nonce``): https://discuss.python.org/t/pep-694-pypi-upload-api-2-0-round-2/101483/22 - - The request includes the following top-level keys: ``meta`` (**required**) @@ -350,12 +346,6 @@ The request includes the following top-level keys: **MUST** conform to the `packaging version `_ specification. -``nonce`` (**optional**) - An additional client-side string input to the - :ref:`"Publishing Session Token" ` algorithm. - Details are provided below, but if this key is omitted, - it is equivalent to passing the empty string. - Upon successful session creation, the server returns a ``201 Created`` response. If an error occurs, the appropriate ``4xx`` code will be returned, as described in the :ref:`session-errors` section. @@ -414,10 +404,10 @@ the following keys: At least one value is required. ``session-token`` - If the index supports :ref:`previewing staged releases `, - this key will contain the unique :ref:`"session token" ` - that can be provided to installers in order to preview the staged release before it's published. - If the index does *not* support stage previewing, this key **MUST** be omitted. + If the index supports :ref:`previewing staged releases `, this key will contain the unique + :ref:`"session token" ` that can be provided to installers in order to preview + the staged release before it's published. This token **MUST** be cryptographically unguessable. If the + index does *not* support stage previewing, this key **MUST** be omitted. ``expires-at`` An :rfc:`3339` formatted timestamp string; this string **MUST** represent a UTC timestamp using the @@ -455,9 +445,11 @@ For the ``links`` key in the success JSON, the following sub-keys are valid: for each file to be included in this session. ``stage`` - The endpoint where this staged release can be :ref:`previewed ` prior to - publishing the session. This can be used to download and verify the not-yet-public files. If - the index does not support previewing staged releases, this key **MUST** be omitted. + The endpoint where this staged release can be :ref:`previewed ` prior to publishing the + session. This can be used to download and verify the not-yet-public files. This URL **MUST** be + cryptographically unguessable and **MUST** use the above ``session-token`` to accomplish this. This + ``stage`` URL should be easily calculated using the ``session-token``, but the exact format of that URL is + index specific. If the index does not support previewing staged releases, this key **MUST** be omitted. ``session`` The endpoint where actions for this session can be performed, @@ -487,12 +479,11 @@ sub-mapping with the following keys: :ref:`session status response body `. ``link`` - The *absolute* URL that the client should use to reference this specific file. - This URL is used to retrieve, replace, or delete - the :ref:`referenced file `. - If a ``nonce`` was provided, this URL **MUST** be obfuscated - with a non-guessable token as described in the - :ref:`Publishing Session Token ` section. + The *absolute* URL that the client should use to reference this specific file. This URL is used to + retrieve, replace, or delete the :ref:`referenced file `. If a :ref:`preview stages + ` are supported, this URL **MUST** be cryptographically unguessable, and **MUST** use + the same :ref:`publishing session token ` to do ensure this constraint. The + exact format of the URL is left to the index, but **SHOULD** be documented. ``notices`` An optional key with similar format and semantics as the ``notices`` session key, except that @@ -560,50 +551,21 @@ extensions `. Publishing Session Token ~~~~~~~~~~~~~~~~~~~~~~~~ -When creating a Publishing Session, clients can provide a ``nonce`` in the -:ref:`initial session creation request `. -This nonce is a string with arbitrary content. The ``nonce`` is -optional, and if omitted, is equivalent to providing an empty string. - -In order to support previewing of staged uploads, the package ``name`` and ``version``, along with -this ``nonce`` are used as input into a hashing algorithm to produce a unique "session token". -This session token is valid for the life of the session -(i.e., until it is completed, either by cancellation or publishing), -and can be provided to supporting installers to gain access to the staged release. - -The use of the ``nonce`` allows clients to decide whether they want to -obscure the visibility of their staged releases or not, -and there can be good reasons for either choice. -For example, if a CI system wants to upload some wheels for a new release, -and wants to allow independent validation of a stage before it's published, -the client may opt for not including a nonce. -On the other hand, if a client would like to pre-seed a release which it publishes atomically -at the time of a public announcement, -that client will likely opt for providing a nonce. - -The `SHA256 algorithm `_ is used to -turn these inputs into a unique token, in the order ``name``, ``version``, ``nonce``, using the -following Python code as an example: - -.. code-block:: python - - from hashlib import sha256 - - def gentoken(name: bytes, version: bytes, nonce: bytes = b''): - h = sha256() - h.update(f'{len(name)}'.encode('ascii') + name) - h.update(f'{len(version)}'.encode('ascii') + version) - h.update(nonce) - return h.hexdigest() - -It should be evident that if no ``nonce`` is provided in the -:ref:`session creation request `, -then the session token is easily guessable from the package name and version number alone. -Clients can elect to omit the ``nonce`` (or set it to the empty string themselves) -if they want to allow previewing from anybody without access to the session token. -By providing a non-empty ``nonce``, -clients can elect for security-through-obscurity, -but this does not protect staged files behind any kind of authentication. +Indexes **SHOULD** support :ref:`preview stages ` so that uploaded files can be live tested +before publishing. E.g. a CI client could perform installation tests using pre-published wheels to ensure +that their new release works as expected before they publish the release publicly. + +Indexes advertise their support for staged previews by returning two key pieces of information in their +:ref:`response to publishing session creation `. Indexes which don't support +staged previews **MUST NOT** include these in their responses. + +The ``session-token`` is a short token which could be used as a convenience for installation tool UX, if they +want to support staged previews via a command line switch, e.g. ``$TOOL install --staging $SESSION_TOKEN``. +The ``links.stage`` key gives the full URL to the stage, which could be used in the CLI, e.g. ``pip +install --extra-index-url $STAGE_URL``. Both the session token and URL **MUST** be cryptographically +unguessable, but the algorithm for generating the token is left to the index. The stage URL **MUST** be +calculable from the session token, using a format documented by the index, but the exact format of the URL is +also left to the index. File Upload Session From 440a2a55cfdeade74e21e2212e3665ca58a663fa Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Fri, 22 Aug 2025 12:57:50 -0700 Subject: [PATCH 5/9] Move some text around so it flows better --- peps/pep-0694.rst | 167 +++++++++++++++++++++++----------------------- 1 file changed, 83 insertions(+), 84 deletions(-) diff --git a/peps/pep-0694.rst b/peps/pep-0694.rst index 41c7d0d714b..159de4239cf 100644 --- a/peps/pep-0694.rst +++ b/peps/pep-0694.rst @@ -346,8 +346,11 @@ The request includes the following top-level keys: **MUST** conform to the `packaging version `_ specification. -Upon successful session creation, the server returns a ``201 Created`` response. If an error -occurs, the appropriate ``4xx`` code will be returned, as described in the :ref:`session-errors` +Upon successful session creation, the server returns a ``201 Created`` response. The response **MUST** also +include a ``Location`` header containing the same URL as the :ref:`links.session ` +key in the :ref:`response body `. + +If an error occurs, the appropriate ``4xx`` code will be returned, as described in the :ref:`session-errors` section. If a session is created for a project which has no previous release, @@ -362,7 +365,6 @@ The session is owned by the user that created it, and all subsequent requests **MUST** be performed with the same credentials, otherwise a ``403 Forbidden`` will be returned on those subsequent requests. - .. _publishing-session-response: Response Body @@ -416,12 +418,12 @@ the following keys: including any uploaded files and the URL links related to the session. The session **SHOULD** remain active until at least this time unless the client itself has canceled or published the session. Servers **MAY** choose to extend this expiration time, but should never move it - earlier. Clients can query the :ref:`session status ` to get the current + earlier. Clients can query the :ref:`session status ` to get the current expiration time of the session. ``status`` A string that contains one of ``pending``, ``published``, ``error``, or ``canceled``, - representing the overall :ref:`status of the session `. + representing the overall :ref:`status of the session `. ``files`` A mapping containing the filenames that have been uploaded to this session, to a mapping @@ -432,6 +434,19 @@ the following keys: wishes to communicate to the end user. These notices are specific to the overall session, not to any particular file in the session. +.. _publishing-session-multiple: + +Multiple Session Creation Requests +++++++++++++++++++++++++++++++++++ + +If a second session is created for the same name-version pair while a session for that pair is in the +``pending``, ``processing``, or ``complete`` state, then the server **MUST** respond with a ``409 Conflict`` +and **MUST** include a ``Location`` header that points to the :ref:`session status URL +`. + +For sessions in the ``error`` or ``canceled`` state, a new session is created with same ``201 Created`` +response and payload, except that the :ref:`publishing session status URL `, +``session-token``, and ``links.stage`` values **MUST** be different. .. _publishing-session-links: @@ -440,6 +455,14 @@ Publishing Session Links For the ``links`` key in the success JSON, the following sub-keys are valid: +``session`` + The endpoint where actions for this session can be performed, + including :ref:`publishing this session `, + :ref:`canceling and discarding the session `, + :ref:`querying the current session status `, + and :ref:`requesting an extension of the session lifetime ` + (*if* the server supports it). + ``upload`` The endpoint session clients will use to initiate a :ref:`File Upload Session ` for each file to be included in this session. @@ -451,14 +474,6 @@ For the ``links`` key in the success JSON, the following sub-keys are valid: ``stage`` URL should be easily calculated using the ``session-token``, but the exact format of that URL is index specific. If the index does not support previewing staged releases, this key **MUST** be omitted. -``session`` - The endpoint where actions for this session can be performed, - including :ref:`publishing this session `, - :ref:`canceling and discarding the session `, - :ref:`querying the current session status `, - and :ref:`requesting an extension of the session lifetime ` - (*if* the server supports it). - .. _publishing-session-files: @@ -489,10 +504,6 @@ sub-mapping with the following keys: An optional key with similar format and semantics as the ``notices`` session key, except that these notices are specific to the referenced file. -If a second session is created for the same name-version pair while a session for that pair is in -the ``pending`` state, then the server **MUST** return the JSON status response for the already -existing session, along with the ``200 OK`` status code rather than creating a new, empty session. - .. _publishing-session-completion: @@ -521,16 +532,17 @@ If the server is able to immediately complete the Publishing Session, it may do request), then it may return a ``202 Accepted`` response. The server **MUST** include a ``Location`` header in the response pointing back to the :ref:`Publishing -Session status ` URL, which can be used to query the current session status. If the server +Session status ` URL, which can be used to query the current session status. If the server returned a ``202 Accepted``, polling that URL can be used to watch for session status changes. If an error occurs, the appropriate ``4xx`` code should be returned, as described in the :ref:`session-errors` section. + .. _publishing-session-cancellation: -Cancellation -~~~~~~~~~~~~ +Publishing Session Cancellation +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ To cancel a Publishing Session, a client issues a ``DELETE`` request to the ``session`` :ref:`link ` @@ -543,7 +555,53 @@ Future attempts to access that session URL or any of the Publishing Session URLs To prevent dangling sessions, servers may also choose to cancel timed-out sessions on their own accord. It is recommended that servers expunge their sessions after no less than a week, but each server may choose their own schedule. Servers **MAY** support client-directed :ref:`session -extensions `. +extensions `. + + +.. _publishing-session-status: + +Publishing Session Status +~~~~~~~~~~~~~~~~~~~~~~~~~ + +At any time, a client can query the status of a session by issuing a ``GET`` request to the URL given in the +:ref:`links.session ` URL (also provided in the :ref:`session creation response's +` ``Location`` header). + +The server will respond to this ``GET`` request with the same :ref:`publishing session creation response +`, that they got when they initially created the publishing session, except with +any changes to ``status``, ``expires-at``, or ``files`` reflected. + + +.. _publishing-session-extension: + +Publishing Session Extension +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Servers **MAY** allow clients to extend sessions, but the overall lifetime and number of extensions +allowed is left to the server. To extend a session, a client issues a ``POST`` request to the +:ref:`links.session ` URL (same as above, also the ``Location`` header). + +The request looks like: + +.. code-block:: json + + { + "meta": { + "api-version": "2.0" + }, + "action": "extend", + "extend-for": 3600 + } + +The number of seconds specified is just a suggestion to the server for the number of additional seconds to +extend the current session. For example, if the client wants to extend the current session for another hour, +``extend-for`` would be ``3600``. Upon successful extension, the server will respond with the same +:ref:`publishing session creation response body ` that they got when they +initially created the publishing session, except with any changes to ``status``, ``expires-at``, or ``files`` +reflected. + +If the server refuses to extend the session for the requested number of seconds, it **MUST** still return a +success response, and the ``expires-at`` key will simply reflect the current expiration time of the session. .. _publishing-session-token: @@ -646,7 +704,7 @@ the file to be uploaded. These checks may include, but are not limited to: - checking if the contents of the ``metadata``, if provided, are valid. If the server determines that upload should proceed, it will return a ``202 Accepted`` response, with the -response body below. The :ref:`status ` of the session will also include the filename in the +response body below. The :ref:`status ` of the session will also include the filename in the ``files`` mapping. If the server cannot proceed with an upload because the ``mechanism`` supplied by the client is not supported it **MUST** return a ``422 Unprocessable Content``. The server **MAY** allow parallel uploads of files, but is not required to. If the server determines the upload cannot proceed, it **MUST** @@ -666,7 +724,6 @@ The successful response includes the following: "api-version": "2.0" }, "links": { - "publishing-session": "...", "file-upload-session": "..." }, "status": "pending", @@ -712,14 +769,13 @@ File Upload Session Links For the ``links`` key in the success JSON, the following sub-keys are valid: -``publishing-session`` - The endpoint where actions for the parent Publishing Session can be performed. +**FIXME**: file-upload-session, rename and add status. ``file-upload-session`` The endpoint where actions for this file-upload-session can be performed. including :ref:`canceling and discarding the File Upload Session `, - :ref:`querying the current File Upload Session status `, - and :ref:`requesting an extension of the File Upload Session lifetime ` + :ref:`querying the current File Upload Session status `, + and :ref:`requesting an extension of the File Upload Session lifetime ` (*if* the server supports it). .. _file-upload-session-completion: @@ -795,63 +851,6 @@ This means providing the metadata request again to retrieve a new upload resourc Clients **MUST NOT** assume that the previous upload resource URL can be reused after deletion. -.. _session-status: - -Session Status --------------- - -At any time, a client can query the status of a session by issuing a ``GET`` request to the -``publishing-session`` :ref:`link ` -or ``file-upload-session`` :ref:`link ` -given in the :ref:`session creation response body ` -or :ref:`File Upload Session creation response body `, -respectively. - -The server will respond to this ``GET`` request with the same -:ref:`Publishing Session creation response body ` -or :ref:`File Upload Session creation response body `, -that they got when they initially created the Publishing Session or File Upload Session, -except with any changes to ``status``, ``expires-at``, or ``files`` reflected. - - -.. _session-extension: - -Session Extension ------------------ - -Servers **MAY** allow clients to extend sessions, but the overall lifetime and number of extensions -allowed is left to the server. To extend a session, a client issues a ``POST`` request to the -``publishing-session`` :ref:`link ` -or ``file-upload-session`` :ref:`link ` -given in the :ref:`Publishing Session creation response body ` -or :ref:`File Upload Session creation response body `, -respectively. - -The request looks like: - -.. code-block:: json - - { - "meta": { - "api-version": "2.0" - }, - "action": "extend", - "extend-for": 3600 - } - -The number of seconds specified is just a suggestion to the server for the number of additional -seconds to extend the current session. For example, if the client wants to extend the current -session for another hour, ``extend-for`` would be ``3600``. Upon successful extension, the server -will respond with the same -:ref:`Publishing Session creation response body ` -or :ref:`File Upload Session creation response body `, -that they got when they initially created the Publishing Session or File Upload Session, -except with any changes to ``status``, ``expires-at``, or ``files`` reflected. - -If the server refuses to extend the session for the requested number of seconds, it still returns a -success response, and the ``expires-at`` key will simply reflect the current expiration time of -the session. - .. _staged-preview: Stage Previews From cb99f7ef4d7c6ad249a23f864c1e97eeaeeed239 Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Fri, 22 Aug 2025 15:16:39 -0700 Subject: [PATCH 6/9] Capitalization consistency --- peps/pep-0694.rst | 111 ++++++++++++++++++++++------------------------ 1 file changed, 52 insertions(+), 59 deletions(-) diff --git a/peps/pep-0694.rst b/peps/pep-0694.rst index 159de4239cf..b592c916022 100644 --- a/peps/pep-0694.rst +++ b/peps/pep-0694.rst @@ -1,3 +1,4 @@ + PEP: 694 Title: Upload 2.0 API for Python Package Indexes Author: Barry Warsaw , Donald Stufft , Ee Durbin @@ -159,15 +160,15 @@ This PEP traces the root cause of most of the issues with the existing API to be To address these issues, this PEP proposes a multi-request workflow, which at a high level involves these steps: -#. Initiate an :ref:`Publishing Session `, creating a release stage. -#. Initiate :ref:`File Upload Session(s) ` to that stage - as part of the Publishing Session. -#. Negotiate the specific :ref:`File Upload Mechanism ` to use +#. Initiate a :ref:`publishing session `, creating a release stage. +#. Initiate :ref:`file upload session(s) ` to that stage + as part of the publishing session. +#. Negotiate the specific :ref:`file upload mechanism ` to use between client and server. -#. Execute File Upload Mechanism for the File Upload Session(s) using the negotiated mechanism(s). -#. Complete the File Upload Session(s), marking them as completed or canceled. -#. Complete the Publishing Session, publishing or discarding the stage. -#. Optionally check the status of a Publishing Session. +#. Execute File Upload Mechanism for the file upload session(s) using the negotiated mechanism(s). +#. Complete the file upload session(s), marking them as completed or canceled. +#. Complete the publishing session, publishing or discarding the stage. +#. Optionally check the status of a publishing session. .. _versioning: @@ -316,7 +317,7 @@ Publishing Session Create a Publishing Session ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -A release starts by creating a new Publishing Session. To create the session, a client submits a +A release starts by creating a new publishing session. To create the session, a client submits a ``POST`` request to the root URL like: .. code-block:: json @@ -464,7 +465,7 @@ For the ``links`` key in the success JSON, the following sub-keys are valid: (*if* the server supports it). ``upload`` - The endpoint session clients will use to initiate a :ref:`File Upload Session ` + The endpoint session clients will use to initiate a :ref:`file upload session ` for each file to be included in this session. ``stage`` @@ -489,7 +490,7 @@ sub-mapping with the following keys: If there was an error during upload, then clients should not assume the file is in any usable state, ``error`` will be returned and it's best to - :ref:`cancel or delete ` the file and start over. + :ref:`cancel or delete ` the file and start over. This action would remove the file name from the ``files`` key of the :ref:`session status response body `. @@ -526,8 +527,8 @@ The request looks like: } -If the server is able to immediately complete the Publishing Session, it may do so and return a -``201 Created`` response. If it is unable to immediately complete the Publishing Session +If the server is able to immediately complete the publishing session, it may do so and return a +``201 Created`` response. If it is unable to immediately complete the publishing session (for instance, if it needs to do validation that may take longer than reasonable in a single HTTP request), then it may return a ``202 Accepted`` response. @@ -544,12 +545,12 @@ If an error occurs, the appropriate ``4xx`` code should be returned, as describe Publishing Session Cancellation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -To cancel a Publishing Session, a client issues a ``DELETE`` request to +To cancel a publishing session, a client issues a ``DELETE`` request to the ``session`` :ref:`link ` given in the :ref:`session creation response body `. The server then marks the session as canceled, and **SHOULD** purge any data that was uploaded as part of that session. -Future attempts to access that session URL or any of the Publishing Session URLs +Future attempts to access that session URL or any of the publishing session URLs **MUST** return a ``404 Not Found``. To prevent dangling sessions, servers may also choose to cancel timed-out sessions on their own @@ -634,11 +635,10 @@ File Upload Session Create a File Upload Session ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -After creating a Publishing Session, the ``upload`` endpoint from the response's -:ref:`session links ` mapping -is used to begin the upload of new files into that session. -Clients **MUST** use the provided ``upload`` URL and -**MUST NOT** assume there is any pattern or commonality to those URLs from one session to the next. +After creating a publishing session, the ``upload`` endpoint from the response's :ref:`session links +` mapping is used to begin the upload of new files into that session. Clients +**MUST** use the provided ``upload`` URL and **MUST NOT** assume there is any pattern or commonality to those +URLs from one session to the next. To initiate a file upload, a client first sends a ``POST`` request to the ``upload`` URL. The request looks like: @@ -686,7 +686,7 @@ Besides the standard ``meta`` key, the request JSON has the following additional ``mechanism`` (**required**) The file-upload mechanisms the client intends to use for this file. This mechanism **SHOULD** be chosen from the list of mechanisms advertised in the - :ref:`Publishing Session response body `. + :ref:`publishing session creation response body `. A client **MAY** send a mechanism that is not advertised in cases where server operators have documented a new or upcoming mechanism that is available for use on a "pre-release" basis. @@ -698,9 +698,7 @@ Servers **MAY** use the data provided in this request to do some sanity checking the file to be uploaded. These checks may include, but are not limited to: - checking if the ``filename`` already exists in a published release; - - checking if the ``size`` would exceed any project or file quota; - - checking if the contents of the ``metadata``, if provided, are valid. If the server determines that upload should proceed, it will return a ``202 Accepted`` response, with the @@ -747,7 +745,7 @@ the following keys: ``status`` A string with valid values ``pending``, ``processing``, ``complete``, ``error``, and ``canceled`` - indicating the current state of the File Upload Session. + indicating the current state of the file upload session. ``expires-at`` An :rfc:`3339` formatted timestamp string representing when the server will expire this File Upload @@ -769,13 +767,11 @@ File Upload Session Links For the ``links`` key in the success JSON, the following sub-keys are valid: -**FIXME**: file-upload-session, rename and add status. - ``file-upload-session`` The endpoint where actions for this file-upload-session can be performed. - including :ref:`canceling and discarding the File Upload Session `, - :ref:`querying the current File Upload Session status `, - and :ref:`requesting an extension of the File Upload Session lifetime ` + including :ref:`canceling and discarding the file upload session `, + :ref:`querying the current file upload session status `, + and :ref:`requesting an extension of the file upload session lifetime ` (*if* the server supports it). .. _file-upload-session-completion: @@ -783,9 +779,9 @@ For the ``links`` key in the success JSON, the following sub-keys are valid: Complete a File Upload Session ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -To complete a File Upload Session, which indicates that the file upload mechanism has been executed +To complete a file upload session, which indicates that the file upload mechanism has been executed and did not produce an error, a client issues a ``POST`` to the ``file-upload-session`` link in the -File Upload Session creation response body. +file upload session creation response body. The requests looks like: @@ -798,40 +794,40 @@ The requests looks like: "action": "complete", } -If the server is able to immediately complete the File Upload Session, it may do so and return a -``201 Created`` response and set the status of the File Upload Session to ``complete``. -If it is unable to immediately complete the File Upload Session +If the server is able to immediately complete the file upload session, it may do so and return a +``201 Created`` response and set the status of the file upload session to ``complete``. +If it is unable to immediately complete the file upload session (for instance, if it needs to do validation that may take longer than reasonable in a single HTTP request), then it may return a ``202 Accepted`` response -and set the status of the File Upload Session to ``processing``. +and set the status of the file upload session to ``processing``. In either case, the server should include a ``Location`` header pointing back to the File Upload Session status URL. -Servers **MUST** allow clients to poll the File Upload Session status URL +Servers **MUST** allow clients to poll the file upload session status URL to watch for the status to change. If the server responds with a ``202 Accepted``, -clients may poll the File Upload Session status URL to watch for the status to change. +clients may poll the file upload session status URL to watch for the status to change. Clients **SHOULD** respect the ``Retry-After`` header value -of the File Upload Session status response. +of the file upload session status response. If an error occurs, the appropriate ``4xx`` code should be returned, as described in the :ref:`session-errors` section. -.. _file-upload-session-cancelation: +.. _file-upload-session-cancellation: Cancellation and Deletion ~~~~~~~~~~~~~~~~~~~~~~~~~ -A client can cancel an in-progress File Upload Session, or delete a file that has been +A client can cancel an in-progress file upload session, or delete a file that has been completely uploaded. In both cases, the client performs this by issuing a ``DELETE`` request to -the File Upload Session URL of the file they want to delete. +the file upload session URL of the file they want to delete. A successful deletion request **MUST** respond with a ``204 No Content``. Once canceled or deleted, a client **MUST NOT** assume that -the previous File Upload Session resource +the previous file upload session resource or associated file upload mechanisms can be reused. @@ -843,7 +839,7 @@ To replace a session file, the file upload **MUST** have been previously complet deleted. It is not possible to replace a file if the upload for that file is in-progress. To replace a session file, clients should -:ref:`cancel and delete the in-progress upload ` by +:ref:`cancel and delete the in-progress upload ` by issuing a ``DELETE`` to the upload resource URL for the file they want to replace. After this, the new file upload can be initiated by beginning the entire :ref:`file upload ` sequence over again. @@ -856,14 +852,13 @@ Clients **MUST NOT** assume that the previous upload resource URL can be reused Stage Previews -------------- -The ability to preview staged releases before they are published is an important feature of this -PEP, enabling an additional level of last-mile testing before the release is available to the -public. Indexes **MAY** provide this functionality through the URL provided in the ``stage`` -sub-key of the :ref:`links key ` returned when -the Publishing Session is created. -The ``stage`` URL can be passed to installers such as ``pip`` by setting the `--extra-index-url -`__ flag to this value. -Multiple stages can even be previewed by repeating this flag with multiple values. +The ability to preview staged releases before they are published is an important feature of this PEP, enabling +an additional level of last-mile testing before the release is available to the public. Indexes **MAY** +provide this functionality through the URL provided in the ``stage`` sub-key of the :ref:`links key +` returned when the publishing session is created. The ``stage`` URL can be passed +to installers such as ``pip`` by setting the `--extra-index-url +`__ flag to this value. Multiple +stages can even be previewed by repeating this flag with multiple values. If supported, the index will return views that expose the staged releases to the installer tool, making them available to download and install into virtual environments built for that last-mile @@ -903,7 +898,7 @@ the rest of the Upload 2.0 protocol endpoints. A client executes this mechanism by submitting a ``POST`` request to the ``file_url`` returned in the ``http-post-bytes`` map of the ``mechanism`` map of the -:ref:`File Upload Session creation response body ` like: +:ref:`file upload session creation response body ` like: .. code-block:: text @@ -914,9 +909,9 @@ returned in the ``http-post-bytes`` map of the ``mechanism`` map of the Servers **MAY** support uploading of digital attestations for files (see :pep:`740`). This support will be indicated by inclusion of an ``attestations_url`` key in the ``http-post-bytes`` map of the ``mechanism`` map of the -:ref:`File Upload Session creation response body `. +:ref:`file upload session creation response body `. Attestations **MUST** be uploaded to the ``attestations_url`` before -:ref:`File Upload Session completion `. +:ref:`file upload session completion `. To upload an attestation, a client submits a ``POST`` request to the ``attestations_url`` containing a JSON array of :pep:`attestation objects <740#attestation-objects>` like: @@ -994,11 +989,9 @@ Can I use the upload 2.0 API to reserve a project name? Yes! If you're not ready to upload files to make a release, you can still reserve a project name (assuming of course that the name doesn't already exist). -To do this, -:ref:`create a new Publishing Session `, -then :ref:`publish the session ` without uploading any files. -While the ``version`` key is required in the JSON body of the create session request, -you can simply use the placeholder version number ``"0.0.0"``. +To do this, :ref:`create a new publishing session `, then :ref:`publish the session +` without uploading any files. While the ``version`` key is required in the +JSON body of the create session request, you can simply use the placeholder version number ``"0.0.0"``. The user that created the session will become the owner of the new project. From 53b1fbd4dfc3e97cd5c6fa6e6f0e49263635ff44 Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Fri, 22 Aug 2025 17:27:51 -0700 Subject: [PATCH 7/9] Update the file upload session section --- peps/pep-0694.rst | 124 ++++++++++++++++++++++++++++++---------------- 1 file changed, 80 insertions(+), 44 deletions(-) diff --git a/peps/pep-0694.rst b/peps/pep-0694.rst index b592c916022..b4a508fe2fc 100644 --- a/peps/pep-0694.rst +++ b/peps/pep-0694.rst @@ -1,4 +1,3 @@ - PEP: 694 Title: Upload 2.0 API for Python Package Indexes Author: Barry Warsaw , Donald Stufft , Ee Durbin @@ -702,11 +701,11 @@ the file to be uploaded. These checks may include, but are not limited to: - checking if the contents of the ``metadata``, if provided, are valid. If the server determines that upload should proceed, it will return a ``202 Accepted`` response, with the -response body below. The :ref:`status ` of the session will also include the filename in the -``files`` mapping. If the server cannot proceed with an upload because the ``mechanism`` supplied by the -client is not supported it **MUST** return a ``422 Unprocessable Content``. The server **MAY** allow parallel -uploads of files, but is not required to. If the server determines the upload cannot proceed, it **MUST** -return a ``409 Conflict``. +response body below. The :ref:`status ` of the publishing session will also +include the filename in the ``files`` mapping. If the server cannot proceed with an upload because the +``mechanism`` supplied by the client is not supported it **MUST** return a ``422 Unprocessable Content``. The +server **MAY** allow parallel uploads of files, but is not required to. If the server determines the upload +cannot proceed, it **MUST** return a ``409 Conflict``. .. _file-upload-session-response: @@ -733,8 +732,8 @@ The successful response includes the following: } } -A ``Retry-After`` response header **MUST** be present -to indicate to clients when they should next poll for an updated status. +A ``Retry-After`` response header **MUST** be present to indicate to clients when they should next poll for an +updated status. Besides the ``meta`` key, which has the same format as the request JSON, the success response has the following keys: @@ -765,14 +764,14 @@ the following keys: File Upload Session Links +++++++++++++++++++++++++ -For the ``links`` key in the success JSON, the following sub-keys are valid: +For the ``links`` key in the response payload, the following sub-keys are valid: ``file-upload-session`` - The endpoint where actions for this file-upload-session can be performed. - including :ref:`canceling and discarding the file upload session `, - :ref:`querying the current file upload session status `, - and :ref:`requesting an extension of the file upload session lifetime ` - (*if* the server supports it). + The endpoint where actions for this file-upload-session can be performed. including :ref:`completing a + file upload session `, :ref:`canceling and discarding the file upload + session `, :ref:`querying the current file upload session status + `, and :ref:`requesting an extension of the file upload session lifetime + ` (*if* the server supports it). .. _file-upload-session-completion: @@ -794,25 +793,24 @@ The requests looks like: "action": "complete", } -If the server is able to immediately complete the file upload session, it may do so and return a -``201 Created`` response and set the status of the file upload session to ``complete``. -If it is unable to immediately complete the file upload session -(for instance, if it needs to do validation that may take longer than reasonable in a single HTTP -request), then it may return a ``202 Accepted`` response -and set the status of the file upload session to ``processing``. +If the server is able to immediately complete the file upload session, it may do so and return a ``201 +Created`` response and set the status of the file upload session to ``complete``. If it is unable to +immediately complete the file upload session (for instance, if it needs to do validation that may take longer +than reasonable in a single HTTP request), then it may return a ``202 Accepted`` response and set the status +of the file upload session to ``processing``. -In either case, the server should include a ``Location`` header pointing back to the File Upload -Session status URL. +In either case, the server should include a ``Location`` header pointing back to the :ref:`file upload session +status ` URL. -Servers **MUST** allow clients to poll the file upload session status URL -to watch for the status to change. -If the server responds with a ``202 Accepted``, -clients may poll the file upload session status URL to watch for the status to change. -Clients **SHOULD** respect the ``Retry-After`` header value -of the file upload session status response. +Servers **MUST** allow clients to poll the file upload session status URL to watch for the status to change. +If the server responds with a ``202 Accepted``, clients may poll the file upload session status URL to watch +for the status to change. Clients **SHOULD** respect the ``Retry-After`` header value of the file upload +session status response. -If an error occurs, the appropriate ``4xx`` code should be returned, as described in the -:ref:`session-errors` section. +**FIXME**: Errors + +If an error occurs, the appropriate ``4xx`` code should be returned, as described in the :ref:`session-errors` +section. .. _file-upload-session-cancellation: @@ -820,16 +818,15 @@ If an error occurs, the appropriate ``4xx`` code should be returned, as describe Cancellation and Deletion ~~~~~~~~~~~~~~~~~~~~~~~~~ -A client can cancel an in-progress file upload session, or delete a file that has been -completely uploaded. In both cases, the client performs this by issuing a ``DELETE`` request to -the file upload session URL of the file they want to delete. +A client can cancel an in-progress file upload session, or delete a file that has been completely uploaded. +In both cases, the client performs this by issuing a ``DELETE`` request to the ``links.file-upload-session`` +URL from the :ref:`file upload session creation response ` of the file they want +to delete. A successful deletion request **MUST** respond with a ``204 No Content``. -Once canceled or deleted, a client **MUST NOT** assume that -the previous file upload session resource -or associated file upload mechanisms -can be reused. +Once canceled or deleted, a client **MUST NOT** assume that the previous file upload session resource or +associated file upload mechanisms can be reused. Replacing a Partially or Fully Uploaded File @@ -838,13 +835,52 @@ Replacing a Partially or Fully Uploaded File To replace a session file, the file upload **MUST** have been previously completed, canceled, or deleted. It is not possible to replace a file if the upload for that file is in-progress. -To replace a session file, clients should -:ref:`cancel and delete the in-progress upload ` by -issuing a ``DELETE`` to the upload resource URL for the file they want to replace. -After this, the new file upload can be initiated by beginning -the entire :ref:`file upload ` sequence over again. -This means providing the metadata request again to retrieve a new upload resource URL. -Clients **MUST NOT** assume that the previous upload resource URL can be reused after deletion. +To replace a session file, clients should :ref:`cancel and delete the in-progress upload +` first. After this, the new file upload can be initiated by beginning the +entire :ref:`file upload ` sequence over again. This means providing the metadata +request again to retrieve a new upload resource URL. Clients **MUST NOT** assume that the previous upload +resource URL can be reused after deletion. + +.. _file-upload-session-status: + +File Upload Session Status +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The client can query status of the file upload session by issuing a ``GET`` request to the +``links.file-upload-session`` URL from the :ref:`file upload session creation response +`. The server responds to this request with the same payload as the file upload +session creation response, except with any changes ``status`` and ``expires-at`` reflected. + +.. _file-upload-session-extension: + +File Upload Session Extension +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Servers **MAY** allow clients to extend file upload sessions, but the overall lifetime and number of +extensions allowed is left to the server. To extend a file upload session, a client issues a ``POST`` request +to the ``links.file-upload-session`` URL from the :ref:`file upload session creation response +`. + +The request looks like: + +.. code-block:: json + + { + "meta": { + "api-version": "2.0" + }, + "action": "extend", + "extend-for": 3600 + } + +The number of seconds specified is just a suggestion to the server for the number of additional seconds to +extend the current file upload session. For example, if the client wants to extend session for another hour, +``extend-for`` would be ``3600``. Upon successful extension, the server will respond with the same :ref:`file +upload session creation response body ` that they got when they initially +created the publishing session, except with any changes to ``status`` or ``expires-at`` reflected. + +If the server refuses to extend the session for the requested number of seconds, it **MUST** still return a +success response, and the ``expires-at`` key will simply reflect the current expiration time of the session. .. _staged-preview: From 532aa499cce078662e4cc2818d136faf6759454d Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Fri, 22 Aug 2025 17:31:43 -0700 Subject: [PATCH 8/9] capitalization --- peps/pep-0694.rst | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/peps/pep-0694.rst b/peps/pep-0694.rst index b4a508fe2fc..709d0c8309f 100644 --- a/peps/pep-0694.rst +++ b/peps/pep-0694.rst @@ -164,7 +164,7 @@ these steps: as part of the publishing session. #. Negotiate the specific :ref:`file upload mechanism ` to use between client and server. -#. Execute File Upload Mechanism for the file upload session(s) using the negotiated mechanism(s). +#. Execute the file upload mechanism for the file upload session(s) using the negotiated mechanism(s). #. Complete the file upload session(s), marking them as completed or canceled. #. Complete the publishing session, publishing or discarding the stage. #. Optionally check the status of a publishing session. @@ -196,7 +196,7 @@ standard content type that describes what the content is, what version of the AP and what serialization format has been used. This standard request content type applies to all requests *except* for requests to execute -a File Upload Mechanism, which will be specified by the documentation for that mechanism. +a file upload mechanism, which will be specified by the documentation for that mechanism. The structure of the ``Content-Type`` header for all other requests is: @@ -747,17 +747,16 @@ the following keys: indicating the current state of the file upload session. ``expires-at`` - An :rfc:`3339` formatted timestamp string representing when the server will expire this File Upload - Session. This string **MUST** represent a UTC timestamp using the "Zulu" (i.e. ``Z``) marker, + An :rfc:`3339` formatted timestamp string representing when the server will expire this file upload + session. This string **MUST** represent a UTC timestamp using the "Zulu" (i.e. ``Z``) marker, and use only whole seconds (i.e. no fractional seconds). The session **SHOULD** remain active until at least this time unless the client cancels or completes it. Servers **MAY** choose to extend this expiration time, but should never move it earlier. ``mechanism`` - A mapping containing the necessary details for the supported mechanism - as negotiated by the client and server. - This mapping **MUST** contain a key ``identifier`` which maps to - the identifier string for the chosen File Upload Mechanism. + A mapping containing the necessary details for the supported mechanism as negotiated by the client and + server. This mapping **MUST** contain a key ``identifier`` which maps to the identifier string for the + chosen file upload mechanism. .. _file-upload-session-links: @@ -911,7 +910,7 @@ File Upload Mechanisms Servers **MUST** implement :ref:`required file upload mechanisms `. Such mechanisms serve as a fallback if no server specific implementations exist. -Each major version of the Upload API **MUST** specify at least one required File Upload Mechanism. +Each major version of the Upload API **MUST** specify at least one required file upload mechanism. New required mechanisms **MUST NOT** be added and existing required mechanisms **MUST NOT** be removed From bdbc5331a997d6d8f0d4f37310a427d1d8eaa796 Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Fri, 22 Aug 2025 18:31:21 -0700 Subject: [PATCH 9/9] Resolve some FIXMEs --- peps/pep-0694.rst | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/peps/pep-0694.rst b/peps/pep-0694.rst index 709d0c8309f..636479c1116 100644 --- a/peps/pep-0694.rst +++ b/peps/pep-0694.rst @@ -273,9 +273,9 @@ are determined by the index operator. Errors ------ -**FIXME**: https://discuss.python.org/t/pep-694-pypi-upload-api-2-0-round-2/101483/20 - -All error responses that contain content look like: +Clients in general should be prepared to handle `HTTP response error status codes +`_ which **MAY** contain payloads of the +the following format: .. code-block:: json @@ -305,6 +305,7 @@ Besides the standard ``meta`` key, this has the following top level keys: The ``message`` and ``source`` strings do not have any specific meaning, and are intended for human interpretation to aid in diagnosing underlying issue. +Some responses may return more specific HTTP status codes as described in the text below. .. _publishing-session: @@ -350,9 +351,6 @@ Upon successful session creation, the server returns a ``201 Created`` response. include a ``Location`` header containing the same URL as the :ref:`links.session ` key in the :ref:`response body `. -If an error occurs, the appropriate ``4xx`` code will be returned, as described in the :ref:`session-errors` -section. - If a session is created for a project which has no previous release, then the index **MAY** reserve the project name before the session is published, however it **MUST NOT** be possible to navigate to that project using @@ -535,10 +533,6 @@ The server **MUST** include a ``Location`` header in the response pointing back Session status ` URL, which can be used to query the current session status. If the server returned a ``202 Accepted``, polling that URL can be used to watch for session status changes. -If an error occurs, the appropriate ``4xx`` code should be returned, as described in the -:ref:`session-errors` section. - - .. _publishing-session-cancellation: Publishing Session Cancellation @@ -806,11 +800,6 @@ If the server responds with a ``202 Accepted``, clients may poll the file upload for the status to change. Clients **SHOULD** respect the ``Retry-After`` header value of the file upload session status response. -**FIXME**: Errors - -If an error occurs, the appropriate ``4xx`` code should be returned, as described in the :ref:`session-errors` -section. - .. _file-upload-session-cancellation: