devpi-admin 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,4 @@
1
+ try:
2
+ from devpi_admin._version import __version__
3
+ except ImportError:
4
+ __version__ = "0.0.0"
@@ -0,0 +1,24 @@
1
+ # file generated by vcs-versioning
2
+ # don't change, don't track in version control
3
+ from __future__ import annotations
4
+
5
+ __all__ = [
6
+ "__version__",
7
+ "__version_tuple__",
8
+ "version",
9
+ "version_tuple",
10
+ "__commit_id__",
11
+ "commit_id",
12
+ ]
13
+
14
+ version: str
15
+ __version__: str
16
+ __version_tuple__: tuple[int | str, ...]
17
+ version_tuple: tuple[int | str, ...]
18
+ commit_id: str | None
19
+ __commit_id__: str | None
20
+
21
+ __version__ = version = '1.0.0'
22
+ __version_tuple__ = version_tuple = (1, 0, 0)
23
+
24
+ __commit_id__ = commit_id = None
devpi_admin/main.py ADDED
@@ -0,0 +1,70 @@
1
+ """devpi-admin: web UI plugin for devpi-server.
2
+
3
+ Installs a single-page application that replaces devpi-web. The SPA is served
4
+ under ``/+admin/`` and browser requests to ``/`` are redirected there. All
5
+ existing devpi REST API endpoints are left untouched — the JS app talks to
6
+ the standard devpi JSON API (``/+login``, ``/<user>/<index>``, ...).
7
+ """
8
+ from pathlib import Path
9
+
10
+ from pyramid.httpexceptions import HTTPFound
11
+ from pyramid.response import FileResponse
12
+
13
+
14
+ STATIC_DIR = Path(__file__).parent / "static"
15
+
16
+
17
+ def devpiserver_get_features():
18
+ # Advertise the plugin to devpi-server
19
+ return {"devpi-admin"}
20
+
21
+
22
+ def devpiserver_pyramid_configure(config, pyramid_config):
23
+ # Serve bundled static assets (index.html, css/, js/) under /+admin/.
24
+ pyramid_config.add_static_view(
25
+ name="+admin", path="devpi_admin:static")
26
+
27
+ # Serve index.html on /+admin/ (with trailing slash). add_static_view
28
+ # does not auto-resolve directory index files.
29
+ pyramid_config.add_route("devpi_admin_spa", "/+admin/")
30
+ pyramid_config.add_view(_serve_index, route_name="devpi_admin_spa")
31
+
32
+ # Bare /+admin (no slash) → redirect so relative asset URLs resolve.
33
+ pyramid_config.add_route("devpi_admin_spa_noslash", "/+admin")
34
+ pyramid_config.add_view(
35
+ lambda request: HTTPFound("/+admin/"),
36
+ route_name="devpi_admin_spa_noslash")
37
+
38
+ # Redirect browser visits to "/" to the SPA. Other routes (JSON API
39
+ # calls, CLI requests) pass through untouched because they send
40
+ # Accept: application/json.
41
+ pyramid_config.add_tween(
42
+ "devpi_admin.main.devpi_admin_tween_factory")
43
+
44
+
45
+ def _serve_index(request):
46
+ return FileResponse(
47
+ str(STATIC_DIR / "index.html"),
48
+ request=request,
49
+ content_type="text/html")
50
+
51
+
52
+ def devpi_admin_tween_factory(handler, registry):
53
+ def tween(request):
54
+ if (request.method == "GET"
55
+ and request.path == "/"
56
+ and _wants_html(request)):
57
+ return HTTPFound("/+admin/")
58
+ return handler(request)
59
+ return tween
60
+
61
+
62
+ def _wants_html(request):
63
+ accept = request.headers.get("Accept") or ""
64
+ if not accept:
65
+ return False
66
+ # Browsers send "text/html,application/xhtml+xml,...". JSON clients
67
+ # (our SPA, devpi CLI) send "application/json".
68
+ if "application/json" in accept and "text/html" not in accept:
69
+ return False
70
+ return "text/html" in accept or "*/*" in accept