devpi-server 6.11.0__tar.gz → 6.12.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_server-6.11.0 → devpi_server-6.12.0}/CHANGELOG +19 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/CHANGELOG.short.rst +21 -19
- {devpi_server-6.11.0 → devpi_server-6.12.0}/PKG-INFO +20 -26
- devpi_server-6.12.0/devpi_server/__init__.py +1 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/hookspecs.py +31 -1
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/views.py +48 -7
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server.egg-info/PKG-INFO +20 -26
- {devpi_server-6.11.0 → devpi_server-6.12.0}/setup.py +1 -1
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/functional.py +23 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/test_views.py +58 -0
- devpi_server-6.11.0/devpi_server/__init__.py +0 -1
- {devpi_server-6.11.0 → devpi_server-6.12.0}/.flake8 +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/AUTHORS +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/LICENSE +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/MANIFEST.in +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/README.rst +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/__main__.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/auth.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/auth_basic.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/auth_devpi.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/cfg/__init__.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/cfg/crontab.template +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/cfg/devpi.service.template +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/cfg/launchd-macos.txt.template +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/cfg/nginx-devpi-caching-http.conf.template +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/cfg/nginx-devpi-caching-location.conf.template +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/cfg/nginx-devpi-caching-proxy.conf.template +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/cfg/nginx-devpi-caching-server.conf.template +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/cfg/nginx-devpi.conf.template +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/cfg/supervisor-devpi.conf.template +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/cfg/supervisord.conf.template +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/cfg/windows-service.txt.template +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/config.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/exceptions.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/filestore.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/filestore_fs.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/fileutil.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/fsck.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/genconfig.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/importexport.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/init.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/interfaces.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/keyfs.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/keyfs_sqlite.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/keyfs_sqlite_fs.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/keyfs_types.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/log.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/main.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/markers.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/middleware.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/mirror.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/model.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/mythread.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/passwd.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/readonly.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/replica.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/sizeof.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/vendor/__init__.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/vendor/_pip.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/view_auth.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server.egg-info/SOURCES.txt +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server.egg-info/dependency_links.txt +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server.egg-info/entry_points.txt +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server.egg-info/not-zip-safe +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server.egg-info/requires.txt +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server.egg-info/top_level.txt +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/pyproject.toml +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/pytest_devpi_server/__init__.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/setup.cfg +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/__init__.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/conftest.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/example.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/importexportdata/badindexname/dataindex.json +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/importexportdata/badusername/dataindex.json +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/importexportdata/basescycle/dataindex.json +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/importexportdata/createdmodified/dataindex.json +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/importexportdata/deletedbase/dataindex.json +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/importexportdata/mirrordata/dataindex.json +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/importexportdata/mirrordata/root/pypi/dddttt/0.1.dev1/dddttt-0.1.dev1.tar.gz +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/importexportdata/modifiedpypi/dataindex.json +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/importexportdata/nocreatedmodified/dataindex.json +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/importexportdata/normalization/dataindex.json +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/importexportdata/normalization/root/dev/hello.pkg/hello.pkg-1.0.tar.gz +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/importexportdata/normalization_merge/dataindex.json +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/importexportdata/normalization_merge/root/dev/hello-pkg/hello.pkg-1.1.tar.gz +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/importexportdata/normalization_merge/root/dev/hello.pkg/hello.pkg-1.0.tar.gz +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/importexportdata/norootpypi/dataindex.json +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/importexportdata/nouser/dataindex.json +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/importexportdata/removedindexplugin/dataindex.json +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/importexportdata/removedindexplugin/user/dev/pkg/pkg-1.0.tar.gz +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/importexportdata/toxresult_naming_scheme/dataindex.json +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/importexportdata/toxresult_naming_scheme/root/dev/hello/0.9/hello-0.9.tar.gz +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/importexportdata/toxresult_naming_scheme/root/dev/hello/sha256=ed7002b439e9ac845f22357d822bac1444730fbdb6016d3ec9432297b9ec9f73/hello-0.9.tar.gz.toxresult0 +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/importexportdata/toxresult_upload_default/dataindex.json +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/plugin.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/reqmock.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/simpypi.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/test_auth.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/test_authcheck.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/test_config.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/test_conftest.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/test_filestore.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/test_fileutil.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/test_fsck.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/test_genconfig.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/test_importexport.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/test_keyfs.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/test_keyfs_sqlite_fs.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/test_log.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/test_main.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/test_mirror.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/test_mirror_no_project_list.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/test_model.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/test_mythread.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/test_nginx.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/test_nginx_replica.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/test_permissions.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/test_readonly.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/test_replica.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/test_replica_functional.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/test_reqmock.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/test_stage_customizer.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/test_streaming.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/test_streaming_nginx.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/test_streaming_replica.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/test_streaming_replica_nginx.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/test_view_auth.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/test_views_patch.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/test_views_push_external.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/test_views_status.py +0 -0
- {devpi_server-6.11.0 → devpi_server-6.12.0}/tox.ini +0 -0
|
@@ -2,6 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
.. towncrier release notes start
|
|
4
4
|
|
|
5
|
+
6.12.0 (2024-06-25)
|
|
6
|
+
===================
|
|
7
|
+
|
|
8
|
+
Features
|
|
9
|
+
--------
|
|
10
|
+
|
|
11
|
+
- Added ``devpiserver_on_toxresult_store`` hook to allow blocking or skipping a toxresult upload on more specific conditions as ``acl_toxresult_upload`` would allow.
|
|
12
|
+
|
|
13
|
+
- Added ``devpiserver_on_toxresult_upload_forbidden`` hook to allow returning a custom message and result (403 or 200).
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
Bug Fixes
|
|
18
|
+
---------
|
|
19
|
+
|
|
20
|
+
- Return json data if toxresult upload is forbidden.
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
5
24
|
6.11.0 (2024-04-20)
|
|
6
25
|
===================
|
|
7
26
|
|
|
@@ -9,6 +9,27 @@ Changelog
|
|
|
9
9
|
|
|
10
10
|
.. towncrier release notes start
|
|
11
11
|
|
|
12
|
+
6.11.0 (2024-04-20)
|
|
13
|
+
===================
|
|
14
|
+
|
|
15
|
+
Features
|
|
16
|
+
--------
|
|
17
|
+
|
|
18
|
+
- The ``devpi-fsck`` script now returns an error code when there have been missing files or checksum errors.
|
|
19
|
+
|
|
20
|
+
- Fix #983: Add plugin hook for mirror authentication header.
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
Bug Fixes
|
|
25
|
+
---------
|
|
26
|
+
|
|
27
|
+
- Preserve last modified of docs and toxresults during export/import.
|
|
28
|
+
|
|
29
|
+
- Fix #1033: Use ``int`` for ``--mirror-cache-expiry`` to fix value of ``proxy_cache_valid`` in nginx caching config.
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
12
33
|
6.10.0 (2023-12-19)
|
|
13
34
|
===================
|
|
14
35
|
|
|
@@ -74,22 +95,3 @@ Bug Fixes
|
|
|
74
95
|
|
|
75
96
|
- Fix wrong hash metadata introduced in 6.5.0 for toxresults which prevents replication. The metadata can be fixed by an export/import cycle.
|
|
76
97
|
|
|
77
|
-
|
|
78
|
-
6.8.0 (2022-12-05)
|
|
79
|
-
==================
|
|
80
|
-
|
|
81
|
-
Features
|
|
82
|
-
--------
|
|
83
|
-
|
|
84
|
-
- Fix #929: Cache normalized project names per transaction on mirror index instances.
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
Bug Fixes
|
|
88
|
-
---------
|
|
89
|
-
|
|
90
|
-
- Fix #914: add locking to list_projects_perstage of mirror indexes to prevent multiple slow concurrent updates of the full project name list.
|
|
91
|
-
|
|
92
|
-
- Catch exceptions in async_httpget analog to httpget.
|
|
93
|
-
|
|
94
|
-
- Add locking to mirror name cache to prevent race condition on updates.
|
|
95
|
-
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: devpi-server
|
|
3
|
-
Version: 6.
|
|
3
|
+
Version: 6.12.0
|
|
4
4
|
Summary: devpi-server: reliable private and pypi.org caching server
|
|
5
5
|
Home-page: https://devpi.net
|
|
6
6
|
Maintainer: Florian Schulze
|
|
@@ -119,6 +119,25 @@ Changelog
|
|
|
119
119
|
|
|
120
120
|
.. towncrier release notes start
|
|
121
121
|
|
|
122
|
+
6.12.0 (2024-06-25)
|
|
123
|
+
===================
|
|
124
|
+
|
|
125
|
+
Features
|
|
126
|
+
--------
|
|
127
|
+
|
|
128
|
+
- Added ``devpiserver_on_toxresult_store`` hook to allow blocking or skipping a toxresult upload on more specific conditions as ``acl_toxresult_upload`` would allow.
|
|
129
|
+
|
|
130
|
+
- Added ``devpiserver_on_toxresult_upload_forbidden`` hook to allow returning a custom message and result (403 or 200).
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
Bug Fixes
|
|
135
|
+
---------
|
|
136
|
+
|
|
137
|
+
- Return json data if toxresult upload is forbidden.
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
|
|
122
141
|
6.11.0 (2024-04-20)
|
|
123
142
|
===================
|
|
124
143
|
|
|
@@ -180,28 +199,3 @@ Bug Fixes
|
|
|
180
199
|
|
|
181
200
|
- Fix #980: Remove long deprecated backward compatibility for old pluggy versions to fix error with pluggy 1.1.0.
|
|
182
201
|
|
|
183
|
-
|
|
184
|
-
6.9.0 (2023-05-23)
|
|
185
|
-
==================
|
|
186
|
-
|
|
187
|
-
Features
|
|
188
|
-
--------
|
|
189
|
-
|
|
190
|
-
- Support export directory layout for ``--replica-file-search-path`` option.
|
|
191
|
-
|
|
192
|
-
- Fix #931: Add ``mirror_no_project_list`` setting for mirror indexes that have no full project list like google cloud artifacts or if you want to prevent downloading the full list for huge indexes like PyPI.
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
Bug Fixes
|
|
196
|
-
---------
|
|
197
|
-
|
|
198
|
-
- Keep a reference to async tasks to avoid their removal mid execution.
|
|
199
|
-
|
|
200
|
-
- Support changed default of ``enforce_content_length`` in urllib3 >= 2.
|
|
201
|
-
|
|
202
|
-
- Fix #934: Properly set PATH_INFO when outside URL is used with sub-path.
|
|
203
|
-
|
|
204
|
-
- Fix #945: Adapt FatalError to be usable as an async HTTP response when updating a project on a mirror.
|
|
205
|
-
|
|
206
|
-
- Fix wrong hash metadata introduced in 6.5.0 for toxresults which prevents replication. The metadata can be fixed by an export/import cycle.
|
|
207
|
-
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = '6.12.0'
|
|
@@ -1,5 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
from __future__ import annotations
|
|
2
2
|
from pluggy import HookspecMarker
|
|
3
|
+
from typing import Optional
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from devpi_server.views import ToxResultHandling
|
|
9
|
+
from pyramid.request import Request
|
|
10
|
+
|
|
3
11
|
|
|
4
12
|
hookspec = HookspecMarker("devpiserver")
|
|
5
13
|
|
|
@@ -255,6 +263,28 @@ def devpiserver_on_replicated_file(stage, project, version, link, serial, back_s
|
|
|
255
263
|
"""Called when a file was downloaded from master on replica."""
|
|
256
264
|
|
|
257
265
|
|
|
266
|
+
@hookspec(firstresult=True)
|
|
267
|
+
def devpiserver_on_toxresult_store(request: Request, tox_result_handling: ToxResultHandling) -> Optional[ToxResultHandling]:
|
|
268
|
+
"""Called when a toxresult is about to be stored.
|
|
269
|
+
|
|
270
|
+
Stops at first non-None result.
|
|
271
|
+
|
|
272
|
+
:returns: A ToxResultHandling object which determines how the upload is processed.
|
|
273
|
+
"""
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
@hookspec(firstresult=True)
|
|
277
|
+
def devpiserver_on_toxresult_upload_forbidden(request: Request, tox_result_handling: ToxResultHandling) -> Optional[str]:
|
|
278
|
+
"""Called when the permission check for toxresult upload failed.
|
|
279
|
+
|
|
280
|
+
Stops at first non-None result.
|
|
281
|
+
|
|
282
|
+
:returns: A ToxResultHandling object which determines whether an error
|
|
283
|
+
with message (default using ``block``) or a success with a message
|
|
284
|
+
(using ``skip``) is returned.
|
|
285
|
+
"""
|
|
286
|
+
|
|
287
|
+
|
|
258
288
|
@hookspec
|
|
259
289
|
def devpiserver_metrics(request):
|
|
260
290
|
""" called for status view.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
1
2
|
import contextlib
|
|
2
3
|
import os
|
|
3
4
|
import re
|
|
@@ -50,6 +51,7 @@ from .readonly import get_mutable_deepcopy
|
|
|
50
51
|
from .log import thread_push_log, thread_pop_log, threadlog
|
|
51
52
|
|
|
52
53
|
from .auth import Auth
|
|
54
|
+
import attrs
|
|
53
55
|
|
|
54
56
|
devpiweb_hookimpl = HookimplMarker("devpiweb")
|
|
55
57
|
server_version = devpi_server.__version__
|
|
@@ -412,6 +414,34 @@ def devpiserver_authcheck_forbidden(request):
|
|
|
412
414
|
return True
|
|
413
415
|
|
|
414
416
|
|
|
417
|
+
TOXRESULT_UPLOAD_FORBIDDEN = (
|
|
418
|
+
"No permission to upload tox results. "
|
|
419
|
+
"You can use the devpi test --no-upload option to skip the upload.")
|
|
420
|
+
|
|
421
|
+
|
|
422
|
+
@attrs.define(frozen=True)
|
|
423
|
+
class ToxResultHandling:
|
|
424
|
+
_block: bool = attrs.field(default=False, alias="_block")
|
|
425
|
+
_skip: bool = attrs.field(default=False, alias="_skip")
|
|
426
|
+
msg: None | str = None
|
|
427
|
+
|
|
428
|
+
def block(self, msg=TOXRESULT_UPLOAD_FORBIDDEN):
|
|
429
|
+
return ToxResultHandling(_block=True, msg=msg)
|
|
430
|
+
|
|
431
|
+
def skip(self, msg=None):
|
|
432
|
+
return ToxResultHandling(_skip=True, msg=msg)
|
|
433
|
+
|
|
434
|
+
|
|
435
|
+
@hookimpl(trylast=True)
|
|
436
|
+
def devpiserver_on_toxresult_store(request, tox_result_handling):
|
|
437
|
+
return tox_result_handling
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
@hookimpl(trylast=True)
|
|
441
|
+
def devpiserver_on_toxresult_upload_forbidden(request, tox_result_handling):
|
|
442
|
+
return tox_result_handling
|
|
443
|
+
|
|
444
|
+
|
|
415
445
|
def version_in_filename(version, filename):
|
|
416
446
|
if version is None:
|
|
417
447
|
# no version set, so skip check
|
|
@@ -530,14 +560,25 @@ class PyPIView:
|
|
|
530
560
|
|
|
531
561
|
@view_config(
|
|
532
562
|
route_name="/{user}/{index}/+f/{relpath:.*}",
|
|
533
|
-
request_method="POST"
|
|
534
|
-
permission="toxresult_upload")
|
|
563
|
+
request_method="POST")
|
|
535
564
|
def post_toxresult(self):
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
565
|
+
if not self.request.has_permission("toxresult_upload"):
|
|
566
|
+
default_tox_result_handling = ToxResultHandling().block(TOXRESULT_UPLOAD_FORBIDDEN)
|
|
567
|
+
tox_result_handling = self.xom.config.hook.devpiserver_on_toxresult_upload_forbidden(
|
|
568
|
+
request=self.request, tox_result_handling=default_tox_result_handling)
|
|
569
|
+
else:
|
|
570
|
+
stage = self.context.stage
|
|
571
|
+
relpath = self.request.path_info.strip("/")
|
|
572
|
+
link = stage.get_link_from_entrypath(relpath)
|
|
573
|
+
if link is None or link.rel != "releasefile":
|
|
574
|
+
apireturn(404, message="no release file found at %s" % relpath)
|
|
575
|
+
default_tox_result_handling = ToxResultHandling()
|
|
576
|
+
tox_result_handling = self.xom.config.hook.devpiserver_on_toxresult_store(
|
|
577
|
+
request=self.request, tox_result_handling=default_tox_result_handling)
|
|
578
|
+
if tox_result_handling._block:
|
|
579
|
+
apireturn(403, tox_result_handling.msg)
|
|
580
|
+
if tox_result_handling._skip:
|
|
581
|
+
apireturn(200, tox_result_handling.msg)
|
|
541
582
|
# the getjson call validates that we got valid json
|
|
542
583
|
getjson(self.request)
|
|
543
584
|
# but we store the original body
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: devpi-server
|
|
3
|
-
Version: 6.
|
|
3
|
+
Version: 6.12.0
|
|
4
4
|
Summary: devpi-server: reliable private and pypi.org caching server
|
|
5
5
|
Home-page: https://devpi.net
|
|
6
6
|
Maintainer: Florian Schulze
|
|
@@ -119,6 +119,25 @@ Changelog
|
|
|
119
119
|
|
|
120
120
|
.. towncrier release notes start
|
|
121
121
|
|
|
122
|
+
6.12.0 (2024-06-25)
|
|
123
|
+
===================
|
|
124
|
+
|
|
125
|
+
Features
|
|
126
|
+
--------
|
|
127
|
+
|
|
128
|
+
- Added ``devpiserver_on_toxresult_store`` hook to allow blocking or skipping a toxresult upload on more specific conditions as ``acl_toxresult_upload`` would allow.
|
|
129
|
+
|
|
130
|
+
- Added ``devpiserver_on_toxresult_upload_forbidden`` hook to allow returning a custom message and result (403 or 200).
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
Bug Fixes
|
|
135
|
+
---------
|
|
136
|
+
|
|
137
|
+
- Return json data if toxresult upload is forbidden.
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
|
|
122
141
|
6.11.0 (2024-04-20)
|
|
123
142
|
===================
|
|
124
143
|
|
|
@@ -180,28 +199,3 @@ Bug Fixes
|
|
|
180
199
|
|
|
181
200
|
- Fix #980: Remove long deprecated backward compatibility for old pluggy versions to fix error with pluggy 1.1.0.
|
|
182
201
|
|
|
183
|
-
|
|
184
|
-
6.9.0 (2023-05-23)
|
|
185
|
-
==================
|
|
186
|
-
|
|
187
|
-
Features
|
|
188
|
-
--------
|
|
189
|
-
|
|
190
|
-
- Support export directory layout for ``--replica-file-search-path`` option.
|
|
191
|
-
|
|
192
|
-
- Fix #931: Add ``mirror_no_project_list`` setting for mirror indexes that have no full project list like google cloud artifacts or if you want to prevent downloading the full list for huge indexes like PyPI.
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
Bug Fixes
|
|
196
|
-
---------
|
|
197
|
-
|
|
198
|
-
- Keep a reference to async tasks to avoid their removal mid execution.
|
|
199
|
-
|
|
200
|
-
- Support changed default of ``enforce_content_length`` in urllib3 >= 2.
|
|
201
|
-
|
|
202
|
-
- Fix #934: Properly set PATH_INFO when outside URL is used with sub-path.
|
|
203
|
-
|
|
204
|
-
- Fix #945: Adapt FatalError to be usable as an async HTTP response when updating a project on a mirror.
|
|
205
|
-
|
|
206
|
-
- Fix wrong hash metadata introduced in 6.5.0 for toxresults which prevents replication. The metadata can be fixed by an export/import cycle.
|
|
207
|
-
|
|
@@ -57,7 +57,7 @@ if __name__ == "__main__":
|
|
|
57
57
|
'Documentation': 'https://doc.devpi.net',
|
|
58
58
|
'Source Code': 'https://github.com/devpi/devpi'
|
|
59
59
|
},
|
|
60
|
-
version='6.
|
|
60
|
+
version='6.12.0',
|
|
61
61
|
maintainer="Florian Schulze",
|
|
62
62
|
maintainer_email="mail@pyfidelity.com",
|
|
63
63
|
packages=[
|
|
@@ -367,6 +367,29 @@ class TestProjectThings:
|
|
|
367
367
|
r = mapp.downloadrelease(200, toxresult_url)
|
|
368
368
|
assert json.loads(r.decode('utf-8')) == tox_result_data
|
|
369
369
|
|
|
370
|
+
def test_toxresult_forbidden(self, mapp, server_version):
|
|
371
|
+
import json
|
|
372
|
+
mapp.create_and_use('pruser2/dev')
|
|
373
|
+
mapp.modify_index("pruser2/dev", ['acl_toxresult_upload='])
|
|
374
|
+
info = mapp.getjson(f"/{mapp.api.stagename}")
|
|
375
|
+
assert info['result']['acl_toxresult_upload'] == []
|
|
376
|
+
content = mapp.makepkg("hello-1.0.tar.gz", b"content", "hello", "1.0")
|
|
377
|
+
mapp.upload_file_pypi("hello-1.0.tar.gz", content, "hello", "1.0")
|
|
378
|
+
(pkg_url,) = mapp.getreleaseslist("hello")
|
|
379
|
+
tox_result_data = dict(foo="bar")
|
|
380
|
+
result = mapp.upload_toxresult(pkg_url, json.dumps(tox_result_data), code=403)
|
|
381
|
+
if server_version >= parse_version("6.11dev"):
|
|
382
|
+
# in devpi-client tests we don't have the result.content_type helper
|
|
383
|
+
assert result.headers.get('content-type', '').lower().startswith('application/json')
|
|
384
|
+
data = result.json
|
|
385
|
+
if callable(data):
|
|
386
|
+
# in devpi-client .json is a method
|
|
387
|
+
data = data()
|
|
388
|
+
assert 'no permission to upload tox results' in data['message'].lower()
|
|
389
|
+
info = mapp.getjson(f"/{mapp.api.stagename}/hello")
|
|
390
|
+
(href,) = (x['href'] for x in info["result"]["1.0"]["+links"])
|
|
391
|
+
assert 'toxresult' not in href
|
|
392
|
+
|
|
370
393
|
|
|
371
394
|
@pytest.mark.nomocking
|
|
372
395
|
class TestMirrorIndexThings:
|
|
@@ -2178,6 +2178,64 @@ def test_delete_removed_toxresult(mapp, testapp, tox_result_data):
|
|
|
2178
2178
|
testapp.delete(toxlink2.href, status=410)
|
|
2179
2179
|
|
|
2180
2180
|
|
|
2181
|
+
def test_plugin_toxresult_upload_block(makemapp, maketestapp, makexom, tox_result_data):
|
|
2182
|
+
class Plugin:
|
|
2183
|
+
@hookimpl
|
|
2184
|
+
def devpiserver_on_toxresult_store(self, tox_result_handling):
|
|
2185
|
+
return tox_result_handling.block("custom block")
|
|
2186
|
+
xom = makexom(plugins=[Plugin()])
|
|
2187
|
+
testapp = maketestapp(xom)
|
|
2188
|
+
mapp = makemapp(testapp)
|
|
2189
|
+
api = mapp.create_and_use()
|
|
2190
|
+
mapp.upload_file_pypi("pkg6-2.6.tgz", b"123", "pkg6", "2.6")
|
|
2191
|
+
vv = get_view_version_links(testapp, api.index, "pkg6", "2.6")
|
|
2192
|
+
(link1,) = vv.get_links()
|
|
2193
|
+
r = mapp.upload_toxresult(link1.href, json.dumps(tox_result_data), code=403)
|
|
2194
|
+
assert r.json['message'] == 'custom block'
|
|
2195
|
+
# make sure the upload was blocked
|
|
2196
|
+
(link2,) = vv.get_links()
|
|
2197
|
+
assert link1.href == link2.href
|
|
2198
|
+
|
|
2199
|
+
|
|
2200
|
+
def test_plugin_toxresult_upload_forbidden_skip(makemapp, maketestapp, makexom, tox_result_data):
|
|
2201
|
+
class Plugin:
|
|
2202
|
+
@hookimpl
|
|
2203
|
+
def devpiserver_on_toxresult_upload_forbidden(self, tox_result_handling):
|
|
2204
|
+
return tox_result_handling.skip("custom message")
|
|
2205
|
+
xom = makexom(plugins=[Plugin()])
|
|
2206
|
+
testapp = maketestapp(xom)
|
|
2207
|
+
mapp = makemapp(testapp)
|
|
2208
|
+
api = mapp.create_and_use(indexconfig=dict(acl_toxresult_upload=''))
|
|
2209
|
+
mapp.upload_file_pypi("pkg6-2.6.tgz", b"123", "pkg6", "2.6")
|
|
2210
|
+
vv = get_view_version_links(testapp, api.index, "pkg6", "2.6")
|
|
2211
|
+
(link1,) = vv.get_links()
|
|
2212
|
+
r = mapp.upload_toxresult(link1.href, json.dumps(tox_result_data), code=200)
|
|
2213
|
+
assert r.json['message'] == 'custom message'
|
|
2214
|
+
# make sure the upload was blocked
|
|
2215
|
+
(link2,) = vv.get_links()
|
|
2216
|
+
assert link1.href == link2.href
|
|
2217
|
+
|
|
2218
|
+
|
|
2219
|
+
def test_plugin_toxresult_upload_skip(makemapp, maketestapp, makexom, tox_result_data):
|
|
2220
|
+
class Plugin:
|
|
2221
|
+
@hookimpl
|
|
2222
|
+
def devpiserver_on_toxresult_store(self, tox_result_handling):
|
|
2223
|
+
return tox_result_handling.skip("custom skip")
|
|
2224
|
+
xom = makexom(plugins=[Plugin()])
|
|
2225
|
+
testapp = maketestapp(xom)
|
|
2226
|
+
mapp = makemapp(testapp)
|
|
2227
|
+
api = mapp.create_and_use()
|
|
2228
|
+
mapp.upload_file_pypi("pkg6-2.6.tgz", b"123", "pkg6", "2.6")
|
|
2229
|
+
vv = get_view_version_links(testapp, api.index, "pkg6", "2.6")
|
|
2230
|
+
(link1,) = vv.get_links()
|
|
2231
|
+
r = mapp.upload_toxresult(link1.href, json.dumps(tox_result_data), code=200)
|
|
2232
|
+
assert r.json['message'] == 'custom skip'
|
|
2233
|
+
vv = get_view_version_links(testapp, api.index, "pkg6", "2.6")
|
|
2234
|
+
# make sure the upload was skipped
|
|
2235
|
+
(link2,) = vv.get_links()
|
|
2236
|
+
assert link1.href == link2.href
|
|
2237
|
+
|
|
2238
|
+
|
|
2181
2239
|
@proj
|
|
2182
2240
|
def test_upload_docs_no_version(mapp, testapp, proj):
|
|
2183
2241
|
api = mapp.create_and_use()
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = '6.11.0'
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/cfg/nginx-devpi-caching-http.conf.template
RENAMED
|
File without changes
|
|
File without changes
|
{devpi_server-6.11.0 → devpi_server-6.12.0}/devpi_server/cfg/nginx-devpi-caching-proxy.conf.template
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/importexportdata/nouser/dataindex.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/test_mirror_no_project_list.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{devpi_server-6.11.0 → devpi_server-6.12.0}/test_devpi_server/test_streaming_replica_nginx.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|