From da131037fdb37efbdee363545a7429e12ab4f1eb Mon Sep 17 00:00:00 2001 From: Donald Stufft Date: Fri, 17 Jun 2022 19:27:44 -0400 Subject: [PATCH] PEP691: Switch to a List for Project, Address more Feedback (#2653) --- pep-0691.rst | 180 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 168 insertions(+), 12 deletions(-) diff --git a/pep-0691.rst b/pep-0691.rst index 8a5d7996e2e..ecfebcc3230 100644 --- a/pep-0691.rst +++ b/pep-0691.rst @@ -35,7 +35,7 @@ There are two major issues with an HTML-based API: fully support HTML5. - HTML5 is primarily designed as a markup language to present documents for human - consumption. Our use of it is driven largely for historical reasons and accidental + consumption. Our use of it is driven largely for historical and accidental reasons, and it's unlikely anyone would design an API that relied on it if they were starting from scratch. @@ -178,10 +178,9 @@ Project List ~~~~~~~~~~~~ The root URL ``/`` for this PEP (which represents the base URL) will be a JSON encoded -dictionary which has a single key, ``projects``, which is itself a dictionary where each -key is a string of the normalized project name, and the value is a dictionary with a -single key, ``url``, which represents the URL that the project can be fetched from. As -an example: +dictionary which has a single key, ``projects``, which is an array where each entry +is a dictionary with a single key, ``name``, which represents string of the project +name. As an example: .. code-block:: json @@ -189,13 +188,31 @@ an example: "meta": { "api-version": "1.0" }, - "projects": { - "frob": {"url": "/frob/"}, - "spamspamspam": {"url": "/spamspamspam/"} - } + "projects": [ + {"name": "Frob"}, + {"name": "spamspamspam"}, + ] } +.. note:: + + The ``name`` field is the same as the one from :pep:`503`, which does not specify + whether it is the non-normalized display name or the normalized name. In practice + different implementations of these PEPs are choosing differently here, so relying + on it being either non-normalized or normalized is relying on an implementation + detail of the repository in question. + + +.. note:: + + While the ``projects`` key is an array, and thus is required to be in some kind + of an order, neither :pep:`503` nor this PEP requires any specific ordering nor + that the ordering is consistent from one request to the next. Mentally this is + best thought of as a set, but both JSON and HTML lack the functionality to have + sets. + + Project Detail ~~~~~~~~~~~~~~ @@ -286,6 +303,15 @@ As an example: } +.. note:: + + While the ``files`` key is an array, and thus is required to be in some kind + of an order, neither :pep:`503` nor this PEP requires any specific ordering nor + that the ordering is consistent from one request to the next. Mentally this is + best thought of as a set, but both JSON and HTML lack the functionality to have + sets. + + Content-Types ------------- @@ -336,10 +362,11 @@ negotiation, the flow is roughly: 1. The client makes an HTTP request containing an ``Accept`` header listing all of the version+format content types that they are able to understand. 2. The server inspects that header, selects one of the listed content types, - then returns a response using that content type. + then returns a response using that content type (treating the absence of + an ``Accept`` header as ``Accept: */*``). 3. If the server does not support any of the content types in the ``Accept`` - header or if the client did not provide an ``Accept`` header at all, then - they are able to choose between 3 different options for how to respond: + header then they are able to choose between 3 different options for how to + respond: a. Select a default content type other than what the client has requested and return a response with that. @@ -828,6 +855,41 @@ with each other. Overall I think it's more confusing if the ``+html`` version do exist. +Why v1.0 and not v1.1 or v2.0? +------------------------------ + +This PEP is still wholly backwards compatible with clients that could read the +existing v1.0 API, can still continue to read the API after these changes have +been made. In :pep:`629`, the qualification for a major version bump is: + + Incrementing the major version is used to signal a backwards incompatible + change such that existing clients would no longer be expected to be able to + meaningfully use the API. + +The changes in this PEP do not meet that bar, nothing has changed in a way that +existing clients would no longer be expected to be able to meaningfully use the +API. + +That means we should still be within the v1.x version line. + +The question of whether we should be v1.1 or v1.0 is a more interesting one, and +there are a few ways of looking at it: + +- We've exposed new features to the API (the project name on the project + page, multiple hashes), which is a sign that we should increment the minor + version. +- The new features exist wholly within the JSON serialization, which means that + no client that currently is requesting the HTML 1.0 page, would ever see any + of the new features anyways, so for them it is effectively still v1.0. +- No major client has implemented support for PEP 629 yet, which means that the + minor version numbering is largely academic at this point anyways, since it + exists to let clients provide feedback to end users. + +The second and third points above end up making the first point kind of +meaningless, and with that, it makes more sense to just call everything v1.0 +and be stricter about updating versions into the future. + + Appendix 1: Survey of use cases to cover ======================================== @@ -881,6 +943,100 @@ how they use the Simple + JSON APIs today or how they currently plan to use it: - XML-RPC Call: ``list_packages_with_serial`` +Appendix 2: Rough Underlying Data Models +======================================== + +These are not intended to perfectly match the server, client, or wire +formats. Rather, these are concpetual models, put to code to make them +more explicit as to the abstract models underlining the repository API +as it evolved through :pep:`503`, :pep:`529`, :pep:`629`, :pep:`658`, +and now this PEP, :pep:`691`. + +The existing HTML, and the new JSON serialization of these models then +represent how these underlying concpetual models get mapped onto the +actual wire formats. + +How servers or clients choose to model this data is out of scope for +this PEP. + +.. code-block:: python + + @dataclass + class Meta: + api_version: Literal["1.0"] + + + @dataclass + class Project: + # Normalized or Non-Normalized Name + name: str + # Computed in JSON, Included in HTML + url: str | None + + + @dataclass + class File: + filename: str + url: str + # Limited to a len() of 1 in HTML + hashes: dict[str, str] + gpg_sig: bool | None + requires_python: str | None + + + @dataclass + class PEP529File(File): + yanked: bool | str + + + # Simple Index page (/simple/) + @dataclass + class PEP503_Index: + projects: set[Project] + + + @dataclass + class PEP629_Index(PEP503_Index): + meta: Meta + + + @dataclass + class Index(PEP629_Index): + pass + + + # Simple Detail page (/simple/$PROJECT/) + @dataclass + class PEP503_Detail: + files: set[File] + + + @dataclass + class PEP529_Detail(PEP503_Detail): + files: set[PEP529File] + + + @dataclass + class PEP629_Detail(PEP529_Detail): + meta: Meta + + + @dataclass + class PEP658_Detail(PEP629_Detail): + # Limited to a len() of 1 in HTML + dist_info_metadata: bool | dict[str, str] + + + @dataclass + class PEP691_Detail(PEP658_Detail): + name: str # Normalized Name + + + @dataclass + class Detail(PEP691_Detail): + pass + + Copyright =========