From 547ef1a05cb4ad78e9e6ebbbbf440402bf595d14 Mon Sep 17 00:00:00 2001
From: Sumana Harihareswara
Date: Thu, 8 Mar 2018 10:28:15 -0500
Subject: [PATCH] Add journal usage guidance, remove download methods in API
docs (#3173)
* Add security and feed information to docs
Ref. #1323
* Update XML-RPC API docs fields, usage info
After testing, update fields and briefly describe responses.
* Update API docs since PyPI no longer offers download stats
* Add API link to user help
Ref: #2413.
---
docs/api-reference/feeds.rst | 52 ++++++++++++++++++++++-
docs/api-reference/legacy.rst | 1 +
docs/api-reference/xml-rpc.rst | 65 ++++++++++++++++-------------
docs/security.rst | 7 ++++
warehouse/templates/pages/help.html | 8 ++++
5 files changed, 103 insertions(+), 30 deletions(-)
diff --git a/docs/api-reference/feeds.rst b/docs/api-reference/feeds.rst
index d325640b243f..af07cf547395 100644
--- a/docs/api-reference/feeds.rst
+++ b/docs/api-reference/feeds.rst
@@ -2,7 +2,7 @@ Feeds
=====
PyPI offers two RSS feeds, the `Newest Packages Feed`_ and the `Latest Updates
-Feed`_.
+Feed`_. You can also call its APIs to get more details on project activity.
Newest Packages Feed
@@ -19,3 +19,53 @@ Latest Updates Feed
Available at https://pypi.org/rss/updates.xml, this feed provides the latest
newly created releases for individual projects on PyPI, including the project
name and description, release version, and a link to the release page.
+
+Project and release activity details
+------------------------------------
+
+PyPI publishes a "journal" of all project, package, and release
+activity (including Owner and Maintainer additions and removals, and
+source file and release additions and removals). You can query it with
+a mix of :ref:`changelog-since` and :ref:`simple-api`. Call
+``changelog_last_serial()`` (in :doc:`xml-rpc`) to get the current
+revision of the journal (the last event's serial ID), then look at
+``/simple/`` to get a list of all packages that currently
+exist. Subsequently, you can call
+``changelog_since_serial(since_serial)`` with the serial ID you
+retrieved, and get the list of all actions that have occurred since
+then.
+
+Example usage::
+
+ >>> import xmlrpc.client
+ >>> import arrow
+ >>> client = xmlrpc.client.ServerProxy('https://test.pypi.org/pypi')
+ >>> latefeb = arrow.get('2018-02-20 10:00:00')
+ >>> latefeb.timestamp
+ 1519120800
+ >>> latefebstamp = latefeb.timestamp
+ >>> recentchanges = client.changelog(latefebstamp)
+ >>> len(recentchanges)
+ 7322
+ >>> for entry in recentchanges:
+ ... if entry[0] == 'twine':
+ ... print(entry[1], " ", entry[3], " ", entry[2])
+ ...
+ ...
+ ...
+ None add Owner brainwane 1519952529
+ 1.10.0 add py2.py3 file twine-1.10.0-py2.py3-none-any.whl 1520023899
+ 1.10.0 new release 1520023899
+ 1.10.0rc1 add py2.py3 file twine-1.10.0rc1-py2.py3-none-any.whl 1520023900
+ 1.10.0rc1 new release 1520023900
+ 1.10.0rc1 add source file twine-1.10.0rc1.tar.gz 1520023902
+ 1.10.0 add source file twine-1.10.0.tar.gz 1520023903
+ 1.10.0 remove file twine-1.10.0.tar.gz 1520024758
+ 1.10.0 remove file twine-1.10.0-py2.py3-none-any.whl 1520024797
+ 1.10.0 remove 1520025270
+
+
+You could also request ``GET /simple/``, and record the ``ETag``, and
+then periodically do a conditional HTTP GET to ``/simple/`` with that
+ETag included. A 200 OK response indicates something has been added or
+removed; if you get a 304 Not Modified, then nothing has changed.
diff --git a/docs/api-reference/legacy.rst b/docs/api-reference/legacy.rst
index e86056448a24..bf135b7987ce 100644
--- a/docs/api-reference/legacy.rst
+++ b/docs/api-reference/legacy.rst
@@ -4,6 +4,7 @@ Legacy API
The "Legacy API" provides feature parity with `pypi-legacy`_, hence the term
"legacy".
+.. _simple-api:
Simple Project API
------------------
diff --git a/docs/api-reference/xml-rpc.rst b/docs/api-reference/xml-rpc.rst
index 168e74cd43ed..fd7726b04b8f 100644
--- a/docs/api-reference/xml-rpc.rst
+++ b/docs/api-reference/xml-rpc.rst
@@ -40,6 +40,11 @@ returned.
``release_data`` The `stable_version` flag is always an empty string. It was
never fully supported anyway.
+``release_downloads`` and ``top_packages`` No longer supported. Please
+use `Google BigQuery
+`_
+instead (`tips
+`_).
Package Querying
----------------
@@ -62,23 +67,21 @@ Package Querying
Retrieve a list of `[role, package_name]` for a given `user`.
Role is either `Maintainer` or `Owner`.
-``release_downloads(package_name, release_version)``
- Retrieve a list of `[filename, download_count]` for a given `package_name`
- and `release_version`.
-
``release_urls(package_name, release_version)``
Retrieve a list of download URLs for the given `release_version`.
Returns a list of dicts with the following keys:
- * url
- * packagetype ('sdist', 'bdist_wheel', etc)
* filename
- * size
- * md5_digest
- * downloads
- * has_sig
+ * packagetype ('sdist', 'bdist_wheel', etc)
* python_version (required version, or 'source', or 'any')
+ * size (an ``int``)
+ * md5_digest
+ * digests (a dict with two keys, "md5" and "sha256")
+ * has_sig (a boolean)
+ * upload_time (a ``DateTime`` object)
* comment_text
+ * downloads (always says "-1")
+ * url
``release_data(package_name, release_version)``
Retrieve metadata describing a specific `release_version`.
@@ -86,29 +89,35 @@ Package Querying
* name
* version
- * stable_version (always an empty string)
+ * stable_version (always an empty string or None)
+ * bugtrack_url
+ * package_url
+ * release_url
+ * docs_url (URL of the packages.python.org docs if they've been supplied)
+ * home_page
+ * download_url
+ * project_url
* author
* author_email
* maintainer
* maintainer_email
- * home_page
- * license
* summary
- * description
+ * description (string, sometimes the entirety of a ``README``)
+ * license
* keywords
* platform
- * download_url
* classifiers (list of classifier strings)
* requires
* requires_dist
* provides
* provides_dist
- * requires_external
- * requires_python
* obsoletes
* obsoletes_dist
- * project_url
- * docs_url (URL of the packages.python.org docs if they've been supplied)
+ * requires_python
+ * requires_external
+ * _pypi_ordering
+ * _pypi_hidden
+ * downloads (``{'last_day': 0, 'last_week': 0, 'last_month': 0}``)
If the release does not exist, an empty dictionary is returned.
@@ -146,10 +155,6 @@ Package Querying
the given classifiers. `classifiers` must be a list of Trove classifier
strings.
-``top_packages([number])``
- Retrieve the sorted list of packages ranked by number of downloads.
- Optionally limit the list to the `number` given.
-
``updated_releases(since)``
Retrieve a list of package releases made since the given timestamp. The
releases will be listed in descending release date.
@@ -159,22 +164,24 @@ Package Querying
since the given timestamp. The packages will be listed in descending date
of most recent change.
+.. _changelog-since:
Mirroring Support
-----------------
``changelog(since, with_ids=False)``
- Retrieve a list of `[name, version, timestamp, action]`, or
- `[name, version, timestamp, action, id]` if `with_ids=True`, since the given
- `since`. All `since` timestamps are UTC values. The argument is a UTC integer
- seconds since the epoch.
+ Retrieve a list of `[name, version, timestamp, action]`, or `[name,
+ version, timestamp, action, id]` if `with_ids=True`, since the given
+ `since`. All `since` timestamps are UTC values. The argument is a
+ UTC integer seconds since the epoch (e.g., the ``timestamp`` method
+ to a ``datetime.datetime`` object).
``changelog_last_serial()``
- Retrieve the last event's serial id.
+ Retrieve the last event's serial id (an ``int``).
``changelog_since_serial(since_serial)``
Retrieve a list of `(name, version, timestamp, action, serial)` since the
- event identified by the given `since_serial` All timestamps are UTC
+ event identified by the given ``since_serial``. All timestamps are UTC
values. The argument is a UTC integer seconds since the epoch.
``list_packages_with_serial()``
diff --git a/docs/security.rst b/docs/security.rst
index 786f3d59b1aa..d3bdae664c57 100644
--- a/docs/security.rst
+++ b/docs/security.rst
@@ -3,7 +3,14 @@
Security
========
+Security policy
+---------------
To read the most up to date version of our security policy, please visit
the application security page, available via the site_ footer.
+Project and release activity details
+------------------------------------
+Please see :doc:`api-reference/feeds` for how to track new and updated
+releases on PyPI.
+
.. _site: https://pypi.org
diff --git a/warehouse/templates/pages/help.html b/warehouse/templates/pages/help.html
index 66bc52e640e4..42f7c86e47d8 100644
--- a/warehouse/templates/pages/help.html
+++ b/warehouse/templates/pages/help.html
@@ -38,6 +38,7 @@
{% macro private_indices() %}How can I publish my private packages to PyPI?{% endmacro %}
{% macro admin_intervention() %}Why did my package or user registration get blocked?{% endmacro %}
{% macro file_name_reuse() %}Why am I getting "File already exists" error?{% endmacro %}
+{% macro APIs() %}Does PyPI have APIs I can use?{% endmacro %}
{% block title %}Help{% endblock %}
{% block content %}
@@ -64,6 +65,7 @@ Common Questions
{{ private_indices() }}
{{ admin_intervention() }}
{{ file_name_reuse() }}
+ {{ APIs() }}
+