PEP691: Switch to a List for Project, Address more Feedback (#2653)
This commit is contained in:
parent
1cba25dc56
commit
da131037fd
180
pep-0691.rst
180
pep-0691.rst
|
@ -35,7 +35,7 @@ There are two major issues with an HTML-based API:
|
||||||
fully support HTML5.
|
fully support HTML5.
|
||||||
|
|
||||||
- HTML5 is primarily designed as a markup language to present documents for human
|
- 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
|
reasons, and it's unlikely anyone would design an API that relied on it if
|
||||||
they were starting from scratch.
|
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
|
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
|
dictionary which has a single key, ``projects``, which is an array where each entry
|
||||||
key is a string of the normalized project name, and the value is a dictionary with a
|
is a dictionary with a single key, ``name``, which represents string of the project
|
||||||
single key, ``url``, which represents the URL that the project can be fetched from. As
|
name. As an example:
|
||||||
an example:
|
|
||||||
|
|
||||||
.. code-block:: json
|
.. code-block:: json
|
||||||
|
|
||||||
|
@ -189,13 +188,31 @@ an example:
|
||||||
"meta": {
|
"meta": {
|
||||||
"api-version": "1.0"
|
"api-version": "1.0"
|
||||||
},
|
},
|
||||||
"projects": {
|
"projects": [
|
||||||
"frob": {"url": "/frob/"},
|
{"name": "Frob"},
|
||||||
"spamspamspam": {"url": "/spamspamspam/"}
|
{"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
|
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
|
Content-Types
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
|
@ -336,10 +362,11 @@ negotiation, the flow is roughly:
|
||||||
1. The client makes an HTTP request containing an ``Accept`` header listing all
|
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.
|
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,
|
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``
|
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
|
header then they are able to choose between 3 different options for how to
|
||||||
they are able to choose between 3 different options for how to respond:
|
respond:
|
||||||
|
|
||||||
a. Select a default content type other than what the client has requested
|
a. Select a default content type other than what the client has requested
|
||||||
and return a response with that.
|
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.
|
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
|
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``
|
- 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
|
Copyright
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue