devpi-admin 1.0.0__tar.gz

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,15 @@
1
+ __pycache__
2
+ build
3
+ *.egg-info
4
+ *.venv
5
+ *.whl
6
+ .DS_Store
7
+ .uuid
8
+ *.pyc
9
+ .*
10
+ !.gitignore
11
+ !.github
12
+ !.gitea
13
+ src/devpi_admin/_version.py
14
+ *.md
15
+ !README*.md
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Pavel Revak <pavelrevak@gmail.com>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,154 @@
1
+ Metadata-Version: 2.4
2
+ Name: devpi-admin
3
+ Version: 1.0.0
4
+ Summary: Modern web UI plugin for devpi-server — drop-in replacement for devpi-web
5
+ Author-email: Pavel Revak <pavelrevak@gmail.com>
6
+ License: MIT
7
+ License-File: LICENSE
8
+ Keywords: admin,devpi,pypi,ui,web
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Framework :: Pyramid
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Intended Audience :: System Administrators
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Topic :: Software Development :: Libraries
17
+ Classifier: Topic :: System :: Software Distribution
18
+ Requires-Python: >=3.9
19
+ Requires-Dist: devpi-server>=6.0
20
+ Description-Content-Type: text/markdown
21
+
22
+ # devpi-admin
23
+
24
+ A modern web UI plugin for [devpi-server](https://devpi.net/) — a drop-in replacement for
25
+ `devpi-web`. Ships as a Python package that registers itself as a devpi-server plugin via the
26
+ standard entry point mechanism, so a single `pip install devpi-admin` is enough.
27
+
28
+ The UI itself is a bundled single-page application (pure HTML + CSS + vanilla JavaScript, no
29
+ build step) served under `/+admin/`. All devpi REST API endpoints remain untouched — the SPA
30
+ talks to the standard devpi JSON API directly.
31
+
32
+ ## Features
33
+
34
+ - **Dashboard** with server info and cache metrics (`/+status`)
35
+ - **Index browser** with visual cards color-coded by type (stage / volatile / mirror)
36
+ - **Users** management — create, edit, delete (admin only)
37
+ - **Index** management — create / edit / delete, configure `bases` (drag & drop priority,
38
+ transitive inheritance detection), `volatile`, `acl_upload` (tag picker), `mirror_url`
39
+ - **Package browser** with client-side search and pagination, including an explicit
40
+ download prompt for huge mirrors (e.g. `root/pypi`'s ~780 k packages / 17 MB index)
41
+ - **Package detail** in a PyPI-like layout: sidebar with metadata, version list, install
42
+ command, file downloads; main area renders the README (markdown via `marked.js`)
43
+ - **Copy-to-clipboard `pip install`** commands with a `pip.conf` toggle
44
+ (short form vs. full `--index-url` / `--trusted-host`)
45
+ - **`pip.conf` generator** — download a ready-to-use config per index
46
+ - **Anonymous browsing** — visitors can explore public indexes without logging in; admin
47
+ actions appear only after authentication
48
+ - **Dark / light / auto theme**, responsive mobile menu, ESC + outside-click dismissal of
49
+ dialogs
50
+
51
+ ## Installation
52
+
53
+ ```bash
54
+ pip install devpi-admin
55
+ ```
56
+
57
+ This pulls in `devpi-server` as a dependency. If you are using devpi in a dedicated venv
58
+ (recommended), install the plugin into the same venv:
59
+
60
+ ```bash
61
+ /var/lib/pypi/venv/bin/pip install devpi-admin
62
+ systemctl --user restart devpi # or however you run devpi-server
63
+ ```
64
+
65
+ You should uninstall `devpi-web` first — `devpi-admin` provides all the web UI you need:
66
+
67
+ ```bash
68
+ pip uninstall devpi-web
69
+ ```
70
+
71
+ ## Usage
72
+
73
+ After restart, open:
74
+
75
+ ```
76
+ http://<your-devpi-host>:3141/
77
+ ```
78
+
79
+ Browser visits to `/` are redirected to `/+admin/`, which serves the SPA. Direct links like
80
+ `http://<host>:3141/+admin/#packages/ci/testing` work and can be bookmarked.
81
+
82
+ devpi CLI tools and other JSON clients are unaffected — they send `Accept: application/json`
83
+ and bypass the redirect.
84
+
85
+ ## How it works
86
+
87
+ `devpi-admin` registers a `devpi_server` entry point that hooks into `devpiserver_pyramid_configure`
88
+ to:
89
+
90
+ 1. Serve the bundled static assets under `/+admin/` via a Pyramid static view.
91
+ 2. Add an explicit view at `/+admin/` that returns `index.html` (so the directory itself
92
+ resolves to the SPA entry point).
93
+ 3. Install a tween that redirects HTML browser requests on `/` to `/+admin/` while leaving
94
+ JSON requests intact.
95
+
96
+ No changes are made to the devpi REST API.
97
+
98
+ ## Requirements
99
+
100
+ - Python 3.9+
101
+ - devpi-server 6.0+
102
+ - A browser with ES6 support and `Promise`, `fetch`, `sessionStorage`
103
+
104
+ ## Routes (UI)
105
+
106
+ Routing is hash-based, so any of these URLs can be bookmarked or shared:
107
+
108
+ - `/+admin/#` — Status dashboard (default)
109
+ - `/+admin/#indexes` — all indexes
110
+ - `/+admin/#indexes/<user>` — filtered to one user
111
+ - `/+admin/#packages/<user>/<index>` — packages in an index
112
+ - `/+admin/#package/<user>/<index>/<name>` — package detail (latest version)
113
+ - `/+admin/#package/<user>/<index>/<name>?version=<ver>` — specific version
114
+ - `/+admin/#users` — users admin (requires login)
115
+
116
+ ## Project layout
117
+
118
+ ```
119
+ devpi-admin/
120
+ ├── pyproject.toml
121
+ ├── README.md
122
+ └── src/
123
+ └── devpi_admin/
124
+ ├── __init__.py
125
+ ├── main.py — Pyramid hooks & tween
126
+ └── static/
127
+ ├── index.html — SPA entry
128
+ ├── css/style.css
129
+ └── js/
130
+ ├── api.js — devpi REST wrapper
131
+ ├── theme.js — theme toggle (light/dark/auto)
132
+ ├── marked.min.js — vendored markdown renderer
133
+ └── app.js — routing, views, rendering
134
+ ```
135
+
136
+ ## Development
137
+
138
+ ```bash
139
+ git clone <repo>
140
+ cd devpi-admin
141
+ pip install -e .
142
+ ```
143
+
144
+ The static files live at `src/devpi_admin/static/` and can be edited in place — changes
145
+ show up on the next browser reload, no restart of devpi-server required (static views
146
+ read from disk on each request).
147
+
148
+ ## Author
149
+
150
+ Pavel Revak <pavelrevak@gmail.com>
151
+
152
+ ## License
153
+
154
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,133 @@
1
+ # devpi-admin
2
+
3
+ A modern web UI plugin for [devpi-server](https://devpi.net/) — a drop-in replacement for
4
+ `devpi-web`. Ships as a Python package that registers itself as a devpi-server plugin via the
5
+ standard entry point mechanism, so a single `pip install devpi-admin` is enough.
6
+
7
+ The UI itself is a bundled single-page application (pure HTML + CSS + vanilla JavaScript, no
8
+ build step) served under `/+admin/`. All devpi REST API endpoints remain untouched — the SPA
9
+ talks to the standard devpi JSON API directly.
10
+
11
+ ## Features
12
+
13
+ - **Dashboard** with server info and cache metrics (`/+status`)
14
+ - **Index browser** with visual cards color-coded by type (stage / volatile / mirror)
15
+ - **Users** management — create, edit, delete (admin only)
16
+ - **Index** management — create / edit / delete, configure `bases` (drag & drop priority,
17
+ transitive inheritance detection), `volatile`, `acl_upload` (tag picker), `mirror_url`
18
+ - **Package browser** with client-side search and pagination, including an explicit
19
+ download prompt for huge mirrors (e.g. `root/pypi`'s ~780 k packages / 17 MB index)
20
+ - **Package detail** in a PyPI-like layout: sidebar with metadata, version list, install
21
+ command, file downloads; main area renders the README (markdown via `marked.js`)
22
+ - **Copy-to-clipboard `pip install`** commands with a `pip.conf` toggle
23
+ (short form vs. full `--index-url` / `--trusted-host`)
24
+ - **`pip.conf` generator** — download a ready-to-use config per index
25
+ - **Anonymous browsing** — visitors can explore public indexes without logging in; admin
26
+ actions appear only after authentication
27
+ - **Dark / light / auto theme**, responsive mobile menu, ESC + outside-click dismissal of
28
+ dialogs
29
+
30
+ ## Installation
31
+
32
+ ```bash
33
+ pip install devpi-admin
34
+ ```
35
+
36
+ This pulls in `devpi-server` as a dependency. If you are using devpi in a dedicated venv
37
+ (recommended), install the plugin into the same venv:
38
+
39
+ ```bash
40
+ /var/lib/pypi/venv/bin/pip install devpi-admin
41
+ systemctl --user restart devpi # or however you run devpi-server
42
+ ```
43
+
44
+ You should uninstall `devpi-web` first — `devpi-admin` provides all the web UI you need:
45
+
46
+ ```bash
47
+ pip uninstall devpi-web
48
+ ```
49
+
50
+ ## Usage
51
+
52
+ After restart, open:
53
+
54
+ ```
55
+ http://<your-devpi-host>:3141/
56
+ ```
57
+
58
+ Browser visits to `/` are redirected to `/+admin/`, which serves the SPA. Direct links like
59
+ `http://<host>:3141/+admin/#packages/ci/testing` work and can be bookmarked.
60
+
61
+ devpi CLI tools and other JSON clients are unaffected — they send `Accept: application/json`
62
+ and bypass the redirect.
63
+
64
+ ## How it works
65
+
66
+ `devpi-admin` registers a `devpi_server` entry point that hooks into `devpiserver_pyramid_configure`
67
+ to:
68
+
69
+ 1. Serve the bundled static assets under `/+admin/` via a Pyramid static view.
70
+ 2. Add an explicit view at `/+admin/` that returns `index.html` (so the directory itself
71
+ resolves to the SPA entry point).
72
+ 3. Install a tween that redirects HTML browser requests on `/` to `/+admin/` while leaving
73
+ JSON requests intact.
74
+
75
+ No changes are made to the devpi REST API.
76
+
77
+ ## Requirements
78
+
79
+ - Python 3.9+
80
+ - devpi-server 6.0+
81
+ - A browser with ES6 support and `Promise`, `fetch`, `sessionStorage`
82
+
83
+ ## Routes (UI)
84
+
85
+ Routing is hash-based, so any of these URLs can be bookmarked or shared:
86
+
87
+ - `/+admin/#` — Status dashboard (default)
88
+ - `/+admin/#indexes` — all indexes
89
+ - `/+admin/#indexes/<user>` — filtered to one user
90
+ - `/+admin/#packages/<user>/<index>` — packages in an index
91
+ - `/+admin/#package/<user>/<index>/<name>` — package detail (latest version)
92
+ - `/+admin/#package/<user>/<index>/<name>?version=<ver>` — specific version
93
+ - `/+admin/#users` — users admin (requires login)
94
+
95
+ ## Project layout
96
+
97
+ ```
98
+ devpi-admin/
99
+ ├── pyproject.toml
100
+ ├── README.md
101
+ └── src/
102
+ └── devpi_admin/
103
+ ├── __init__.py
104
+ ├── main.py — Pyramid hooks & tween
105
+ └── static/
106
+ ├── index.html — SPA entry
107
+ ├── css/style.css
108
+ └── js/
109
+ ├── api.js — devpi REST wrapper
110
+ ├── theme.js — theme toggle (light/dark/auto)
111
+ ├── marked.min.js — vendored markdown renderer
112
+ └── app.js — routing, views, rendering
113
+ ```
114
+
115
+ ## Development
116
+
117
+ ```bash
118
+ git clone <repo>
119
+ cd devpi-admin
120
+ pip install -e .
121
+ ```
122
+
123
+ The static files live at `src/devpi_admin/static/` and can be edited in place — changes
124
+ show up on the next browser reload, no restart of devpi-server required (static views
125
+ read from disk on each request).
126
+
127
+ ## Author
128
+
129
+ Pavel Revak <pavelrevak@gmail.com>
130
+
131
+ ## License
132
+
133
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,51 @@
1
+ [build-system]
2
+ requires = ["hatchling", "hatch-vcs"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "devpi-admin"
7
+ dynamic = ["version"]
8
+ description = "Modern web UI plugin for devpi-server — drop-in replacement for devpi-web"
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = { text = "MIT" }
12
+ authors = [
13
+ { name = "Pavel Revak", email = "pavelrevak@gmail.com" },
14
+ ]
15
+ keywords = ["devpi", "pypi", "admin", "web", "ui"]
16
+ classifiers = [
17
+ "Development Status :: 4 - Beta",
18
+ "Framework :: Pyramid",
19
+ "Intended Audience :: Developers",
20
+ "Intended Audience :: System Administrators",
21
+ "License :: OSI Approved :: MIT License",
22
+ "Operating System :: OS Independent",
23
+ "Programming Language :: Python :: 3",
24
+ "Topic :: Software Development :: Libraries",
25
+ "Topic :: System :: Software Distribution",
26
+ ]
27
+ dependencies = [
28
+ "devpi-server>=6.0",
29
+ ]
30
+
31
+ [project.entry-points.devpi_server]
32
+ devpi-admin = "devpi_admin.main"
33
+
34
+ [tool.hatch.version]
35
+ source = "vcs"
36
+ fallback-version = "0.0.0"
37
+
38
+ [tool.hatch.build.hooks.vcs]
39
+ version-file = "src/devpi_admin/_version.py"
40
+
41
+ [tool.hatch.build.targets.wheel]
42
+ packages = ["src/devpi_admin"]
43
+
44
+ [tool.hatch.build.targets.sdist]
45
+ include = [
46
+ "src/devpi_admin",
47
+ "tests",
48
+ "README.md",
49
+ "pyproject.toml",
50
+ "LICENSE",
51
+ ]
@@ -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
@@ -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