Skip to content

Commit d460355

Browse files
authored
PEP 694: Several updates based on Michał Górny's feedback on DPO (#4323)
* Several updates based on Michal Gorny's feedback on DPO https://discuss.python.org/t/pep-694-pypi-upload-api-2-0/76316/2 Summary: * Add some error return code descriptions where they were underspecified * Fix some misspellings and poorly worded text * Combine the canceling and deleting of upload files sections * Simplify the rules for replacing a staged but not yet published file * Add open question about deferring stage previews * Fix a typo * The last chunk can be accepted asynchronously * Be explicit that the server MAY accepted parallel file uploads * Post-History * Fix reference link typo The server is allowed to respond with a 202 for the last chunk, to indicate it's processing that last chunk asynchronously. This fleshes out the process for checking for completed process of the file in that case, and improves the file status key definitions.
1 parent e61cfb1 commit d460355

File tree

1 file changed

+55
-41
lines changed

1 file changed

+55
-41
lines changed

peps/pep-0694.rst

Lines changed: 55 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ Status: Draft
66
Type: Standards Track
77
Topic: Packaging
88
Created: 11-Jun-2022
9-
Post-History: `27-Jun-2022 <https://discuss.python.org/t/pep-694-upload-2-0-api-for-python-package-repositories/16879>`__
9+
Post-History: `27-Jun-2022 <https://discuss.python.org/t/pep-694-upload-2-0-api-for-python-package-repositories/16879>`__,
10+
`06-Jan-2025 <https://discuss.python.org/t/pep-694-pypi-upload-api-2-0/76316>`__
11+
`14-Apr-2025 <https://discuss.python.org/t/pep-694-pypi-upload-api-2-0/76316/9>`__
1012

1113

1214
Abstract
@@ -297,6 +299,7 @@ the following keys:
297299
wishes to communicate to the end user. These notices are specific to the overall session, not
298300
to any particular file in the session.
299301

302+
300303
.. _session-links:
301304

302305
Session Links
@@ -329,8 +332,15 @@ The ``files`` key contains a mapping from the names of the files uploaded in thi
329332
sub-mapping with the following keys:
330333

331334
``status``
332-
A string with the same values and semantics as the :ref:`session status key <session-status>`,
333-
except that it indicates the status of the specific referenced file.
335+
A string with valid values ``partial``, ``pending``, ``complete``, and ``error``. If a file
336+
upload has not seen an ``Upload-Complete: ?1`` header, then ``partial`` will be returned. If
337+
``Upload-Complete: ?1`` resulted in a ``202 Accepted``, then ``pending`` will be returned until
338+
asynchronous processing of the last chunk and the full file has been completed. If a ``201
339+
Created`` was returned, or the last chunk processing is finished, ``complete`` will be returned.
340+
If there was an error during upload, then clients should not assume the file is in any usable
341+
state, ``error`` will be returned and it's best to :ref:`cancel or delete <cancel-an-upload>`
342+
the file and start over. This action would remove the file name from the ``files`` key of the
343+
:ref:`session status response body <session-response>`.
334344

335345
``link``
336346
The *absolute* URL that the client should use to reference this specific file. This URL is used
@@ -409,6 +419,9 @@ If the server determines that upload should proceed, it will return a ``201 Crea
409419
an empty body, and a ``Location`` header pointing to the URL that the file content should be
410420
uploaded to. The :ref:`status <session-status>` of the session will also include the filename in
411421
the ``files`` mapping, with the above ``Location`` URL included in under the ``link`` sub-key.
422+
If the server determines the upload cannot proceed, it **MUST** return a ``409 Conflict``. The
423+
server **MAY** allow parallel uploads of files, but is not required to.
424+
412425

413426
.. IMPORTANT::
414427

@@ -521,15 +534,18 @@ For the second chunk representing bytes 1000 through 1999, include the following
521534
These requests would continue sequentially until the last chunk is ready to be uploaded.
522535

523536
For each successful chunk, the server **MUST** respond with a ``202 Accepted`` header, except for
524-
the final chunk, which **MUST** be a ``201 Created``, and as with non-chunked uploads, the body of
525-
these responses has no content.
537+
the final chunk, which **MUST** be either:
526538

527-
.. _complete-the-upload:
539+
* ``201 Created`` if the server accepts and processes the last chunk synchronously, completing the
540+
file upload.
541+
* ``202 Accepted`` if the server accepts the last chunk, but must process it asynchronously. In
542+
this case, the client should query the :ref:`session status <session-response>` periodically until
543+
the uploaded :ref:`file status <session-files>` transitions to ``complete``.
528544

529545
The final chunk of data **MUST** include the ``Upload-Complete: ?1`` header, since at that point the
530546
entire file has been uploaded.
531547

532-
With both chunked and non-chunked uploads, once completed successfully, the file **MUST** not be
548+
With both chunked and non-chunked uploads, once completed successfully, the file **MUST NOT** be
533549
publicly visible in the repository, but merely staged until the upload session is :ref:`completed
534550
<publish-session>`. If the server supports :ref:`previews <staged-preview>`, the file **MUST** be
535551
visible at the ``stage`` :ref:`URL <session-links>`. Partially uploaded chunked files **SHOULD
@@ -541,9 +557,9 @@ multiple chunks:
541557
- A client **MUST NOT** perform multiple ``POST`` requests in parallel for the same file to avoid
542558
race conditions and data loss or corruption.
543559

544-
- If the offset provided in ``Upload-Offset`` is not ``0`` or correctly specifies the byte offset of
545-
the next chunk in an incomplete upload, then the server **MUST** respond with a ``409 Conflict``.
546-
This means that a client **MAY NOT** upload chunks out of order.
560+
- If the offset provided in ``Upload-Offset`` is not ``0`` and does not correctly specify the byte
561+
offset of the next chunk in an incomplete upload, then the server **MUST** respond with a ``409
562+
Conflict``. This means that a client **MUST NOT** upload chunks out of order.
547563

548564
- Once a file upload has completed successfully, you may initiate another upload for that file,
549565
which **once completed**, will replace that file. This is possible until the entire session is
@@ -578,47 +594,30 @@ multiple chunks as per the above protocol.
578594

579595
.. _cancel-an-upload:
580596

581-
Canceling an In-Progress Upload
582-
+++++++++++++++++++++++++++++++
583-
584-
If a client wishes to cancel an upload of a specific file, for instance because they need to upload
585-
a different file, they may do so by issuing a ``DELETE`` request to the upload resource URL of the
586-
file they want to delete.
587-
588-
A successful cancellation request **MUST** respond with a ``204 No Content``.
589-
590-
Once deleting, a client **MUST NOT** assume that the previous upload resource URL can be reused.
591-
592-
593-
Delete a Partial or Fully Uploaded File
594-
+++++++++++++++++++++++++++++++++++++++
597+
Canceling and Deleting File Uploads
598+
+++++++++++++++++++++++++++++++++++
595599

596-
Similarly, for files which have already been completely uploaded, clients can delete the file by
597-
issuing a ``DELETE`` request to the upload resource URL.
600+
A client can cancel an in-progress upload for a file, or delete a file that has been completely
601+
uploaded. In both cases, the client performs this by issuing a ``DELETE`` request to the upload
602+
resource URL of the file they want to delete.
598603

599604
A successful deletion request **MUST** response with a ``204 No Content``.
600605

601-
Once deleting, a client **MUST NOT** assume that the previous upload resource URL can be reused.
606+
Once canceled or deleted, a client **MUST NOT** assume that the previous upload resource URL can be reused.
602607

603608

604609
Replacing a Partially or Fully Uploaded File
605610
++++++++++++++++++++++++++++++++++++++++++++
606611

607-
To replace a session file, the file upload **MUST** have been previously completed or deleted. It
608-
is not possible to replace a file if the upload for that file is incomplete. Clients have two
609-
options to replace an incomplete upload:
612+
To replace a session file, the file upload **MUST** have been previously completed, canceled, or
613+
deleted. It is not possible to replace a file if the upload for that file is in-progress.
610614

611-
- :ref:`Cancel the in-progress upload <cancel-an-upload>` by issuing a ``DELETE`` to the upload
612-
resource URL for the file they want to replace. After this, the new file upload can be initiated
613-
by beginning the entire :ref:`file upload <file-uploads>` sequence over again. This means
614-
providing the metadata request again to retrieve a new upload resource URL. Client **MUST NOT**
615-
assume that the previous upload resource URL can be reused after deletion.
616-
617-
- :ref:`Complete the in-progress upload <complete-the-upload>` by uploading a zero-length chunk
618-
providing the ``Upload-Complete: ?1`` header. This effectively truncates and completes the
619-
in-progress upload, after which point the new upload can commence. In this case, clients
620-
**SHOULD** reuse the previous upload resource URL and do not need to begin the entire :ref:`file
621-
upload <file-uploads>` sequence over again.
615+
To replace a session file, clients should :ref:`cancel and delete the in-progress upload
616+
<cancel-an-upload>` by issuing a ``DELETE`` to the upload resource URL for the file they want to
617+
replace. After this, the new file upload can be initiated by beginning the entire :ref:`file upload
618+
<file-uploads>` sequence over again. This means providing the metadata request again to retrieve a
619+
new upload resource URL. Client **MUST NOT** assume that the previous upload resource URL can be
620+
reused after deletion.
622621

623622

624623
.. _session-status:
@@ -720,6 +719,9 @@ If a session is published that has no staged files, the operation is effectively
720719
where a new project name is being reserved. In this case, the new project is created, reserved, and
721720
owned by the user that created the session.
722721

722+
If an error occurs, the appropriate ``4xx`` code should be returned, as described in the
723+
:ref:`session-errors` section.
724+
723725

724726
.. _session-token:
725727

@@ -932,6 +934,18 @@ The user that created the session will become the owner of the new project.
932934
Open Questions
933935
==============
934936

937+
Defer Stage Previews
938+
--------------------
939+
940+
:ref:`Stage previews <staged-preview>` are an important and useful feature for testing new version
941+
wheel uploads before they are published. They'd allow us to effectively decommission
942+
``test.pypi.org``, which has well-known deficiencies.
943+
944+
However, the ability to preview stages before they're published does complicate the protocol and
945+
this proposal. We could defer this feature for later, although if we do, we should still keep the
946+
optional ``nonce`` for token generation, in order to be easily future proof.
947+
948+
935949
Multipart Uploads vs tus
936950
------------------------
937951

0 commit comments

Comments
 (0)