Merge pull request #395 from awachtler/master
added JSON Topic for use with micropython-upip
This commit is contained in:
commit
3713da9d66
26
README.rst
26
README.rst
|
@ -884,6 +884,32 @@ these steps:
|
|||
you may add the user under which ``pypiserver`` runs into the *shadow*
|
||||
group, with a command like this: ``sudo usermod -a -G shadow pypy-user``.
|
||||
|
||||
Use with MicroPython
|
||||
--------------------
|
||||
The MicroPython interpreter for embedded devices can install packages with the
|
||||
module ``upip.py``. The module uses a specialized json-endpoint to retrieve
|
||||
package information. This endpoint is supported by ``pypiserver``.
|
||||
|
||||
It can be tested with the UNIX port of ``micropython``::
|
||||
|
||||
cd micropython
|
||||
ports/unix/micropython -m tools.upip install -i http://my-server:8080 -p /tmp/mymodules micropython-foobar
|
||||
|
||||
Installing packages from the REPL of an embedded device works in this way:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import network
|
||||
import upip
|
||||
|
||||
sta_if = network.WLAN(network.STA_IF)
|
||||
sta_if.active(True)
|
||||
sta_if.connect('<your ESSID>', '<your password>')
|
||||
upip.index_urls = ["http://my-server:8080"]
|
||||
upip.install("micropython-foobar")
|
||||
|
||||
Further information on micropython-packaging can be found here: https://docs.micropython.org/en/latest/reference/packages.html
|
||||
|
||||
|
||||
Sources
|
||||
=======
|
||||
|
|
|
@ -8,6 +8,7 @@ import zipfile
|
|||
from collections import namedtuple
|
||||
from io import BytesIO
|
||||
from urllib.parse import urljoin, urlparse
|
||||
from json import dumps
|
||||
|
||||
from pypiserver.config import RunConfig
|
||||
from . import __version__
|
||||
|
@ -362,6 +363,34 @@ def server_static(filename):
|
|||
|
||||
return HTTPError(404, f"Not Found ({filename} does not exist)\n\n")
|
||||
|
||||
@app.route("/:project/json")
|
||||
@auth("list")
|
||||
def json_info(project):
|
||||
# PEP 503: require normalized project
|
||||
normalized = normalize_pkgname_for_url(project)
|
||||
if project != normalized:
|
||||
return redirect(f"/{normalized}/json", 301)
|
||||
|
||||
packages = sorted(
|
||||
config.backend.find_project_packages(project),
|
||||
key=lambda x: x.parsed_version, reverse=True
|
||||
)
|
||||
|
||||
if not packages:
|
||||
raise HTTPError(404, f"package {project} not found")
|
||||
|
||||
latest_version = packages[0].version
|
||||
releases = {}
|
||||
req_url = request.url
|
||||
for x in packages:
|
||||
releases[x.version] = [{"url": urljoin(req_url, "../../packages/" + x.relfn)}]
|
||||
rv = {
|
||||
"info" : {"version": latest_version},
|
||||
"releases" : releases
|
||||
}
|
||||
response.content_type = 'application/json'
|
||||
return dumps(rv)
|
||||
|
||||
|
||||
@app.route("/:project")
|
||||
@app.route("/:project/")
|
||||
|
|
|
@ -419,6 +419,39 @@ def test_simple_index_list_name_with_underscore_no_egg(root, testapp):
|
|||
assert hrefs == {"foo-bar/"}
|
||||
|
||||
|
||||
def test_json_info(root, testapp):
|
||||
root.join("foobar-1.0.zip").write("")
|
||||
root.join("foobar-1.1.zip").write("")
|
||||
root.join("foobarX-1.1.zip").write("")
|
||||
|
||||
resp = testapp.get("/foobar/json")
|
||||
assert "info" in resp.json
|
||||
assert "releases" in resp.json
|
||||
assert len(resp.json["info"]) == 1
|
||||
assert len(resp.json["releases"]) == 2
|
||||
|
||||
|
||||
def test_json_info_package_not_existing(root, testapp):
|
||||
resp = testapp.get("/foobar/json", status=404)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"package,normalized",
|
||||
[
|
||||
("FooBar", "foobar"),
|
||||
("Foo.Bar", "foo-bar"),
|
||||
("foo_bar", "foo-bar"),
|
||||
("Foo-Bar", "foo-bar"),
|
||||
("foo--_.bar", "foo-bar"),
|
||||
],
|
||||
)
|
||||
def test_json_info_normalized_name_redirect(testapp, package, normalized):
|
||||
resp = testapp.get("/{0}/json".format(package))
|
||||
assert resp.status_code >= 300
|
||||
assert resp.status_code < 400
|
||||
assert resp.location.endswith("/{0}/json".format(normalized))
|
||||
|
||||
|
||||
def test_no_cache_control_set(root, testapp):
|
||||
assert not testapp.app._pypiserver_config.cache_control
|
||||
root.join("foo_bar-1.0.tar.gz").write("")
|
||||
|
|
Loading…
Reference in New Issue