devpi-admin 1.0.0__tar.gz → 1.1.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.
- devpi_admin-1.1.0/PKG-INFO +228 -0
- devpi_admin-1.1.0/README.md +207 -0
- {devpi_admin-1.0.0 → devpi_admin-1.1.0}/src/devpi_admin/_version.py +2 -2
- devpi_admin-1.1.0/src/devpi_admin/main.py +326 -0
- {devpi_admin-1.0.0 → devpi_admin-1.1.0}/src/devpi_admin/static/css/style.css +94 -14
- {devpi_admin-1.0.0 → devpi_admin-1.1.0}/src/devpi_admin/static/js/app.js +486 -248
- devpi_admin-1.1.0/tests/__init__.py +0 -0
- devpi_admin-1.1.0/tests/test_cached_versions.py +91 -0
- devpi_admin-1.1.0/tests/test_helpers.py +101 -0
- devpi_admin-1.1.0/tests/test_hooks.py +55 -0
- devpi_admin-1.1.0/tests/test_json_safe.py +74 -0
- devpi_admin-1.0.0/PKG-INFO +0 -154
- devpi_admin-1.0.0/README.md +0 -133
- devpi_admin-1.0.0/src/devpi_admin/main.py +0 -70
- devpi_admin-1.0.0/tests/__init__.py +0 -8
- {devpi_admin-1.0.0 → devpi_admin-1.1.0}/.gitignore +0 -0
- {devpi_admin-1.0.0 → devpi_admin-1.1.0}/LICENSE +0 -0
- {devpi_admin-1.0.0 → devpi_admin-1.1.0}/pyproject.toml +0 -0
- {devpi_admin-1.0.0 → devpi_admin-1.1.0}/src/devpi_admin/__init__.py +0 -0
- {devpi_admin-1.0.0 → devpi_admin-1.1.0}/src/devpi_admin/static/index.html +0 -0
- {devpi_admin-1.0.0 → devpi_admin-1.1.0}/src/devpi_admin/static/js/api.js +0 -0
- {devpi_admin-1.0.0 → devpi_admin-1.1.0}/src/devpi_admin/static/js/marked.min.js +0 -0
- {devpi_admin-1.0.0 → devpi_admin-1.1.0}/src/devpi_admin/static/js/theme.js +0 -0
- {devpi_admin-1.0.0 → devpi_admin-1.1.0}/tests/test_package.py +0 -0
- {devpi_admin-1.0.0 → devpi_admin-1.1.0}/tests/test_tween.py +0 -0
- {devpi_admin-1.0.0 → devpi_admin-1.1.0}/tests/test_wants_html.py +0 -0
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: devpi-admin
|
|
3
|
+
Version: 1.1.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
|
|
35
|
+
- Server info with version of devpi-server and all installed plugins (auto-detected)
|
|
36
|
+
- Cache metrics with hit-rate bars (storage, changelog, relpath caches)
|
|
37
|
+
- Whoosh search index queue status
|
|
38
|
+
|
|
39
|
+
### Indexes
|
|
40
|
+
- Visual cards color-coded by type: green (stage), amber (volatile stage), blue (mirror)
|
|
41
|
+
- `pip install` command with copy-to-clipboard (click to copy, green flash feedback)
|
|
42
|
+
- `pip.conf` toggle — switch between short form and full `--index-url` / `--trusted-host`
|
|
43
|
+
- `pip.conf` generator — download a ready-to-use config per index
|
|
44
|
+
- Create / edit / delete indexes via modal dialogs
|
|
45
|
+
- `bases` editor with drag & drop priority ordering and transitive inheritance display
|
|
46
|
+
- `acl_upload` tag picker with user selection dropdown
|
|
47
|
+
- `volatile`, `mirror_url`, `title` configuration
|
|
48
|
+
|
|
49
|
+
### Users
|
|
50
|
+
- Create, edit (email, password), delete users (admin only)
|
|
51
|
+
|
|
52
|
+
### Packages
|
|
53
|
+
- Client-side search with PEP 503 name normalization
|
|
54
|
+
- Mirror indexes: shows only cached packages (fast filesystem scan, no 17 MB index download);
|
|
55
|
+
"Download full index" button available for complete browse
|
|
56
|
+
- Package cards with latest version and `pip install` command
|
|
57
|
+
|
|
58
|
+
### Package detail (PyPI-like layout)
|
|
59
|
+
- **Sidebar**: metadata (author, license, Python version, keywords, platform, maintainer,
|
|
60
|
+
extras, project URLs, dependencies), `pip install` command, file downloads with upload dates
|
|
61
|
+
- **Version list**: cached versions shown normally, uncached versions link to pypi.org (↗);
|
|
62
|
+
"Load all versions" button for mirrors
|
|
63
|
+
- **README**: rendered markdown (via `marked.js`); fetched from PyPI.org for mirror packages
|
|
64
|
+
where devpi doesn't cache the description
|
|
65
|
+
|
|
66
|
+
### General
|
|
67
|
+
- **Anonymous browsing** — visitors can explore public indexes without logging in; admin
|
|
68
|
+
actions (create/edit/delete) appear only after authentication
|
|
69
|
+
- **Dark / light / auto theme** with half-circle icon for auto mode
|
|
70
|
+
- **Responsive mobile menu** with hamburger toggle
|
|
71
|
+
- **ESC + outside-click** dismissal for modals, dropdown menus, mobile menu
|
|
72
|
+
- **Login via modal** — no separate login page
|
|
73
|
+
|
|
74
|
+
## Plugin API endpoints
|
|
75
|
+
|
|
76
|
+
In addition to serving the SPA, `devpi-admin` registers custom API endpoints under
|
|
77
|
+
`/+admin-api/` for features that the standard devpi REST API doesn't provide efficiently:
|
|
78
|
+
|
|
79
|
+
| Endpoint | Method | Description |
|
|
80
|
+
|----------|--------|-------------|
|
|
81
|
+
| `/+admin-api/cached/{user}/{index}` | GET | List cached package names for a mirror index (filesystem scan) |
|
|
82
|
+
| `/+admin-api/versions/{user}/{index}/{project}` | GET | Version list with cached/uncached distinction |
|
|
83
|
+
| `/+admin-api/versions/{user}/{index}/{project}?all=1` | GET | Include all upstream versions (mirrors) |
|
|
84
|
+
| `/+admin-api/versiondata/{user}/{index}/{project}/{version}` | GET | Metadata + file links for a single version |
|
|
85
|
+
|
|
86
|
+
## Installation
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
pip install devpi-admin
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
This pulls in `devpi-server` as a dependency. If you are using devpi in a dedicated venv
|
|
93
|
+
(recommended), install the plugin into the same venv:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
/var/lib/pypi/venv/bin/pip install devpi-admin
|
|
97
|
+
systemctl --user restart devpi # or however you run devpi-server
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
You should uninstall `devpi-web` — `devpi-admin` replaces it entirely:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
pip uninstall devpi-web
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Both plugins can technically coexist but it is not recommended. `devpi-admin` intercepts `/`
|
|
107
|
+
for HTML requests while `devpi-web` would still serve its own HTML on other routes like
|
|
108
|
+
`/<user>/<index>/<package>`, leading to a confusing mixed experience.
|
|
109
|
+
|
|
110
|
+
## Usage
|
|
111
|
+
|
|
112
|
+
After restart, open:
|
|
113
|
+
|
|
114
|
+
```
|
|
115
|
+
http://<your-devpi-host>:3141/
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Browser visits to `/` are redirected to `/+admin/`, which serves the SPA. Direct links like
|
|
119
|
+
`http://<host>:3141/+admin/#packages/ci/testing` work and can be bookmarked.
|
|
120
|
+
|
|
121
|
+
devpi CLI tools and other JSON clients are unaffected — they send `Accept: application/json`
|
|
122
|
+
and bypass the redirect.
|
|
123
|
+
|
|
124
|
+
## How it works
|
|
125
|
+
|
|
126
|
+
`devpi-admin` registers a `devpi_server` entry point that hooks into
|
|
127
|
+
`devpiserver_pyramid_configure` (with `@hookimpl` from pluggy) to:
|
|
128
|
+
|
|
129
|
+
1. Serve the bundled static assets under `/+admin/` via a Pyramid static view.
|
|
130
|
+
2. Add an explicit view at `/+admin/` that returns `index.html`.
|
|
131
|
+
3. Register custom API views under `/+admin-api/` for cached-package and per-version queries.
|
|
132
|
+
4. Install a tween that redirects HTML browser requests on `/` to `/+admin/` while leaving
|
|
133
|
+
JSON requests intact.
|
|
134
|
+
|
|
135
|
+
The plugin uses devpi-server internals (`xom.model.getstage`, `stage.list_versions`,
|
|
136
|
+
`stage.get_versiondata`, `stage.get_releaselinks`) and direct filesystem access
|
|
137
|
+
(`serverdir/+files/`) for the cached-packages API.
|
|
138
|
+
|
|
139
|
+
## Requirements
|
|
140
|
+
|
|
141
|
+
- Python 3.9+
|
|
142
|
+
- devpi-server 6.0+
|
|
143
|
+
- A browser with ES6 support (`Promise`, `fetch`, `sessionStorage`)
|
|
144
|
+
|
|
145
|
+
## Routes (UI)
|
|
146
|
+
|
|
147
|
+
Routing is hash-based, so any of these URLs can be bookmarked or shared:
|
|
148
|
+
|
|
149
|
+
| Hash | View |
|
|
150
|
+
|------|------|
|
|
151
|
+
| `#` | Status dashboard (default) |
|
|
152
|
+
| `#indexes` | All indexes |
|
|
153
|
+
| `#indexes/<user>` | Indexes filtered by user |
|
|
154
|
+
| `#packages/<user>/<index>` | Packages in an index |
|
|
155
|
+
| `#package/<user>/<index>/<name>` | Package detail (latest cached version) |
|
|
156
|
+
| `#package/<user>/<index>/<name>?version=<ver>` | Specific version |
|
|
157
|
+
| `#users` | User management (requires login) |
|
|
158
|
+
|
|
159
|
+
## Project layout
|
|
160
|
+
|
|
161
|
+
```
|
|
162
|
+
devpi-admin/
|
|
163
|
+
├── pyproject.toml
|
|
164
|
+
├── README.md
|
|
165
|
+
├── LICENSE
|
|
166
|
+
├── .github/workflows/
|
|
167
|
+
│ ├── tests.yml — CI on push/PR (Python 3.10 + 3.14)
|
|
168
|
+
│ └── publish.yml — publish to PyPI on release
|
|
169
|
+
├── src/
|
|
170
|
+
│ └── devpi_admin/
|
|
171
|
+
│ ├── __init__.py — version (from git tag via hatch-vcs)
|
|
172
|
+
│ ├── main.py — Pyramid hooks, tween, API views
|
|
173
|
+
│ └── static/
|
|
174
|
+
│ ├── index.html — SPA entry point
|
|
175
|
+
│ ├── css/style.css
|
|
176
|
+
│ └── js/
|
|
177
|
+
│ ├── api.js — devpi REST wrapper + auth
|
|
178
|
+
│ ├── theme.js — theme toggle (light/dark/auto)
|
|
179
|
+
│ ├── marked.min.js — vendored markdown renderer
|
|
180
|
+
│ └── app.js — routing, views, rendering
|
|
181
|
+
└── tests/
|
|
182
|
+
├── test_cached_versions.py — filesystem scan (tmpdir)
|
|
183
|
+
├── test_helpers.py — filename parsing, normalization
|
|
184
|
+
├── test_hooks.py — pluggy hook registration
|
|
185
|
+
├── test_json_safe.py — readonly view conversion
|
|
186
|
+
├── test_package.py — entry point, static files
|
|
187
|
+
├── test_tween.py — redirect behavior
|
|
188
|
+
└── test_wants_html.py — Accept header heuristic
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## Development
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
git clone <repo>
|
|
195
|
+
cd devpi-admin
|
|
196
|
+
python -m venv .venv
|
|
197
|
+
.venv/bin/pip install -e .
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
The static files live at `src/devpi_admin/static/` and can be edited in place — changes
|
|
201
|
+
show up on the next browser reload, no restart of devpi-server required (static views
|
|
202
|
+
read from disk on each request). Python changes (`main.py`) require a devpi-server restart.
|
|
203
|
+
|
|
204
|
+
Run the unit tests:
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
PYTHONWARNINGS="ignore::UserWarning" python -m unittest discover -v tests/
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
(The `PYTHONWARNINGS` shim hides an unrelated deprecation warning emitted by Pyramid 2.1
|
|
211
|
+
when it imports `pkg_resources`.)
|
|
212
|
+
|
|
213
|
+
## Releasing
|
|
214
|
+
|
|
215
|
+
Version is derived from the git tag via `hatch-vcs`. To release:
|
|
216
|
+
|
|
217
|
+
1. `git tag v0.1.0 && git push --tags`
|
|
218
|
+
2. On GitHub: Releases → Draft new release → select tag → Publish
|
|
219
|
+
3. The `publish.yml` workflow runs tests, builds wheel+sdist, and uploads to PyPI via trusted
|
|
220
|
+
publishing (no API tokens needed — configure the GitHub environment `pypi` in PyPI settings).
|
|
221
|
+
|
|
222
|
+
## Author
|
|
223
|
+
|
|
224
|
+
Pavel Revak <pavelrevak@gmail.com>
|
|
225
|
+
|
|
226
|
+
## License
|
|
227
|
+
|
|
228
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,207 @@
|
|
|
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
|
|
14
|
+
- Server info with version of devpi-server and all installed plugins (auto-detected)
|
|
15
|
+
- Cache metrics with hit-rate bars (storage, changelog, relpath caches)
|
|
16
|
+
- Whoosh search index queue status
|
|
17
|
+
|
|
18
|
+
### Indexes
|
|
19
|
+
- Visual cards color-coded by type: green (stage), amber (volatile stage), blue (mirror)
|
|
20
|
+
- `pip install` command with copy-to-clipboard (click to copy, green flash feedback)
|
|
21
|
+
- `pip.conf` toggle — switch between short form and full `--index-url` / `--trusted-host`
|
|
22
|
+
- `pip.conf` generator — download a ready-to-use config per index
|
|
23
|
+
- Create / edit / delete indexes via modal dialogs
|
|
24
|
+
- `bases` editor with drag & drop priority ordering and transitive inheritance display
|
|
25
|
+
- `acl_upload` tag picker with user selection dropdown
|
|
26
|
+
- `volatile`, `mirror_url`, `title` configuration
|
|
27
|
+
|
|
28
|
+
### Users
|
|
29
|
+
- Create, edit (email, password), delete users (admin only)
|
|
30
|
+
|
|
31
|
+
### Packages
|
|
32
|
+
- Client-side search with PEP 503 name normalization
|
|
33
|
+
- Mirror indexes: shows only cached packages (fast filesystem scan, no 17 MB index download);
|
|
34
|
+
"Download full index" button available for complete browse
|
|
35
|
+
- Package cards with latest version and `pip install` command
|
|
36
|
+
|
|
37
|
+
### Package detail (PyPI-like layout)
|
|
38
|
+
- **Sidebar**: metadata (author, license, Python version, keywords, platform, maintainer,
|
|
39
|
+
extras, project URLs, dependencies), `pip install` command, file downloads with upload dates
|
|
40
|
+
- **Version list**: cached versions shown normally, uncached versions link to pypi.org (↗);
|
|
41
|
+
"Load all versions" button for mirrors
|
|
42
|
+
- **README**: rendered markdown (via `marked.js`); fetched from PyPI.org for mirror packages
|
|
43
|
+
where devpi doesn't cache the description
|
|
44
|
+
|
|
45
|
+
### General
|
|
46
|
+
- **Anonymous browsing** — visitors can explore public indexes without logging in; admin
|
|
47
|
+
actions (create/edit/delete) appear only after authentication
|
|
48
|
+
- **Dark / light / auto theme** with half-circle icon for auto mode
|
|
49
|
+
- **Responsive mobile menu** with hamburger toggle
|
|
50
|
+
- **ESC + outside-click** dismissal for modals, dropdown menus, mobile menu
|
|
51
|
+
- **Login via modal** — no separate login page
|
|
52
|
+
|
|
53
|
+
## Plugin API endpoints
|
|
54
|
+
|
|
55
|
+
In addition to serving the SPA, `devpi-admin` registers custom API endpoints under
|
|
56
|
+
`/+admin-api/` for features that the standard devpi REST API doesn't provide efficiently:
|
|
57
|
+
|
|
58
|
+
| Endpoint | Method | Description |
|
|
59
|
+
|----------|--------|-------------|
|
|
60
|
+
| `/+admin-api/cached/{user}/{index}` | GET | List cached package names for a mirror index (filesystem scan) |
|
|
61
|
+
| `/+admin-api/versions/{user}/{index}/{project}` | GET | Version list with cached/uncached distinction |
|
|
62
|
+
| `/+admin-api/versions/{user}/{index}/{project}?all=1` | GET | Include all upstream versions (mirrors) |
|
|
63
|
+
| `/+admin-api/versiondata/{user}/{index}/{project}/{version}` | GET | Metadata + file links for a single version |
|
|
64
|
+
|
|
65
|
+
## Installation
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
pip install devpi-admin
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
This pulls in `devpi-server` as a dependency. If you are using devpi in a dedicated venv
|
|
72
|
+
(recommended), install the plugin into the same venv:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
/var/lib/pypi/venv/bin/pip install devpi-admin
|
|
76
|
+
systemctl --user restart devpi # or however you run devpi-server
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
You should uninstall `devpi-web` — `devpi-admin` replaces it entirely:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
pip uninstall devpi-web
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Both plugins can technically coexist but it is not recommended. `devpi-admin` intercepts `/`
|
|
86
|
+
for HTML requests while `devpi-web` would still serve its own HTML on other routes like
|
|
87
|
+
`/<user>/<index>/<package>`, leading to a confusing mixed experience.
|
|
88
|
+
|
|
89
|
+
## Usage
|
|
90
|
+
|
|
91
|
+
After restart, open:
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
http://<your-devpi-host>:3141/
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Browser visits to `/` are redirected to `/+admin/`, which serves the SPA. Direct links like
|
|
98
|
+
`http://<host>:3141/+admin/#packages/ci/testing` work and can be bookmarked.
|
|
99
|
+
|
|
100
|
+
devpi CLI tools and other JSON clients are unaffected — they send `Accept: application/json`
|
|
101
|
+
and bypass the redirect.
|
|
102
|
+
|
|
103
|
+
## How it works
|
|
104
|
+
|
|
105
|
+
`devpi-admin` registers a `devpi_server` entry point that hooks into
|
|
106
|
+
`devpiserver_pyramid_configure` (with `@hookimpl` from pluggy) to:
|
|
107
|
+
|
|
108
|
+
1. Serve the bundled static assets under `/+admin/` via a Pyramid static view.
|
|
109
|
+
2. Add an explicit view at `/+admin/` that returns `index.html`.
|
|
110
|
+
3. Register custom API views under `/+admin-api/` for cached-package and per-version queries.
|
|
111
|
+
4. Install a tween that redirects HTML browser requests on `/` to `/+admin/` while leaving
|
|
112
|
+
JSON requests intact.
|
|
113
|
+
|
|
114
|
+
The plugin uses devpi-server internals (`xom.model.getstage`, `stage.list_versions`,
|
|
115
|
+
`stage.get_versiondata`, `stage.get_releaselinks`) and direct filesystem access
|
|
116
|
+
(`serverdir/+files/`) for the cached-packages API.
|
|
117
|
+
|
|
118
|
+
## Requirements
|
|
119
|
+
|
|
120
|
+
- Python 3.9+
|
|
121
|
+
- devpi-server 6.0+
|
|
122
|
+
- A browser with ES6 support (`Promise`, `fetch`, `sessionStorage`)
|
|
123
|
+
|
|
124
|
+
## Routes (UI)
|
|
125
|
+
|
|
126
|
+
Routing is hash-based, so any of these URLs can be bookmarked or shared:
|
|
127
|
+
|
|
128
|
+
| Hash | View |
|
|
129
|
+
|------|------|
|
|
130
|
+
| `#` | Status dashboard (default) |
|
|
131
|
+
| `#indexes` | All indexes |
|
|
132
|
+
| `#indexes/<user>` | Indexes filtered by user |
|
|
133
|
+
| `#packages/<user>/<index>` | Packages in an index |
|
|
134
|
+
| `#package/<user>/<index>/<name>` | Package detail (latest cached version) |
|
|
135
|
+
| `#package/<user>/<index>/<name>?version=<ver>` | Specific version |
|
|
136
|
+
| `#users` | User management (requires login) |
|
|
137
|
+
|
|
138
|
+
## Project layout
|
|
139
|
+
|
|
140
|
+
```
|
|
141
|
+
devpi-admin/
|
|
142
|
+
├── pyproject.toml
|
|
143
|
+
├── README.md
|
|
144
|
+
├── LICENSE
|
|
145
|
+
├── .github/workflows/
|
|
146
|
+
│ ├── tests.yml — CI on push/PR (Python 3.10 + 3.14)
|
|
147
|
+
│ └── publish.yml — publish to PyPI on release
|
|
148
|
+
├── src/
|
|
149
|
+
│ └── devpi_admin/
|
|
150
|
+
│ ├── __init__.py — version (from git tag via hatch-vcs)
|
|
151
|
+
│ ├── main.py — Pyramid hooks, tween, API views
|
|
152
|
+
│ └── static/
|
|
153
|
+
│ ├── index.html — SPA entry point
|
|
154
|
+
│ ├── css/style.css
|
|
155
|
+
│ └── js/
|
|
156
|
+
│ ├── api.js — devpi REST wrapper + auth
|
|
157
|
+
│ ├── theme.js — theme toggle (light/dark/auto)
|
|
158
|
+
│ ├── marked.min.js — vendored markdown renderer
|
|
159
|
+
│ └── app.js — routing, views, rendering
|
|
160
|
+
└── tests/
|
|
161
|
+
├── test_cached_versions.py — filesystem scan (tmpdir)
|
|
162
|
+
├── test_helpers.py — filename parsing, normalization
|
|
163
|
+
├── test_hooks.py — pluggy hook registration
|
|
164
|
+
├── test_json_safe.py — readonly view conversion
|
|
165
|
+
├── test_package.py — entry point, static files
|
|
166
|
+
├── test_tween.py — redirect behavior
|
|
167
|
+
└── test_wants_html.py — Accept header heuristic
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## Development
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
git clone <repo>
|
|
174
|
+
cd devpi-admin
|
|
175
|
+
python -m venv .venv
|
|
176
|
+
.venv/bin/pip install -e .
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
The static files live at `src/devpi_admin/static/` and can be edited in place — changes
|
|
180
|
+
show up on the next browser reload, no restart of devpi-server required (static views
|
|
181
|
+
read from disk on each request). Python changes (`main.py`) require a devpi-server restart.
|
|
182
|
+
|
|
183
|
+
Run the unit tests:
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
PYTHONWARNINGS="ignore::UserWarning" python -m unittest discover -v tests/
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
(The `PYTHONWARNINGS` shim hides an unrelated deprecation warning emitted by Pyramid 2.1
|
|
190
|
+
when it imports `pkg_resources`.)
|
|
191
|
+
|
|
192
|
+
## Releasing
|
|
193
|
+
|
|
194
|
+
Version is derived from the git tag via `hatch-vcs`. To release:
|
|
195
|
+
|
|
196
|
+
1. `git tag v0.1.0 && git push --tags`
|
|
197
|
+
2. On GitHub: Releases → Draft new release → select tag → Publish
|
|
198
|
+
3. The `publish.yml` workflow runs tests, builds wheel+sdist, and uploads to PyPI via trusted
|
|
199
|
+
publishing (no API tokens needed — configure the GitHub environment `pypi` in PyPI settings).
|
|
200
|
+
|
|
201
|
+
## Author
|
|
202
|
+
|
|
203
|
+
Pavel Revak <pavelrevak@gmail.com>
|
|
204
|
+
|
|
205
|
+
## License
|
|
206
|
+
|
|
207
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '1.
|
|
22
|
-
__version_tuple__ = version_tuple = (1,
|
|
21
|
+
__version__ = version = '1.1.0'
|
|
22
|
+
__version_tuple__ = version_tuple = (1, 1, 0)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|