devpi-server 6.19.0__tar.gz → 6.19.1__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.19.0 → devpi_server-6.19.1}/CHANGELOG +10 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/CHANGELOG.short.rst +10 -9
- {devpi_server-6.19.0 → devpi_server-6.19.1}/PKG-INFO +13 -10
- devpi_server-6.19.1/devpi_server/__init__.py +1 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/mirror.py +0 -1
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/model.py +0 -3
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/view_auth.py +5 -1
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server.egg-info/PKG-INFO +13 -10
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server.egg-info/requires.txt +1 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/pyproject.toml +2 -0
- devpi_server-6.19.1/test_devpi_server/__init__.py +0 -0
- devpi_server-6.19.1/test_devpi_server/py.typed +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/test_replica.py +119 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/test_stage_customizer.py +0 -11
- {devpi_server-6.19.0 → devpi_server-6.19.1}/tox.ini +1 -1
- devpi_server-6.19.0/devpi_server/__init__.py +0 -1
- devpi_server-6.19.0/devpi_server/py.typed +0 -1
- devpi_server-6.19.0/test_devpi_server/py.typed +0 -1
- {devpi_server-6.19.0 → devpi_server-6.19.1}/.flake8 +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/LICENSE +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/MANIFEST.in +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/README.rst +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/__main__.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/auth.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/auth_basic.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/auth_devpi.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/cfg/__init__.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/cfg/crontab.template +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/cfg/devpi.service.template +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/cfg/launchd-macos.txt.template +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/cfg/nginx-devpi-caching-http.conf.template +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/cfg/nginx-devpi-caching-location.conf.template +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/cfg/nginx-devpi-caching-proxy.conf.template +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/cfg/nginx-devpi-caching-server.conf.template +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/cfg/nginx-devpi.conf.template +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/cfg/supervisor-devpi.conf.template +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/cfg/supervisord.conf.template +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/cfg/windows-service.txt.template +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/compat.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/config.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/exceptions.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/filestore.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/filestore_db.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/filestore_fs.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/filestore_fs_base.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/filestore_hash_hl.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/fileutil.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/fsck.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/genconfig.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/hookspecs.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/htmlpage.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/httpclient.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/importexport.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/init.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/interfaces.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/keyfs.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/keyfs_sqlite.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/keyfs_sqlite_fs.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/keyfs_types.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/log.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/main.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/markers.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/middleware.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/mythread.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/normalized.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/passwd.py +0 -0
- /devpi_server-6.19.0/test_devpi_server/__init__.py → /devpi_server-6.19.1/devpi_server/py.typed +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/readonly.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/replica.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/sizeof.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server/views.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server.egg-info/SOURCES.txt +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server.egg-info/dependency_links.txt +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server.egg-info/entry_points.txt +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/devpi_server.egg-info/top_level.txt +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/mypy.ini +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/pytest_devpi_server/__init__.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/setup.cfg +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/conftest.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/example.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/functional.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/importexportdata/badindexname/dataindex.json +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/importexportdata/badusername/dataindex.json +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/importexportdata/basescycle/dataindex.json +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/importexportdata/createdmodified/dataindex.json +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/importexportdata/deletedbase/dataindex.json +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/importexportdata/mirrordata/dataindex.json +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/importexportdata/mirrordata/root/pypi/dddttt/0.1.dev1/dddttt-0.1.dev1.tar.gz +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/importexportdata/modifiedpypi/dataindex.json +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/importexportdata/nocreatedmodified/dataindex.json +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/importexportdata/normalization/dataindex.json +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/importexportdata/normalization/root/dev/hello.pkg/hello.pkg-1.0.tar.gz +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/importexportdata/normalization_merge/dataindex.json +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/importexportdata/normalization_merge/root/dev/hello-pkg/hello.pkg-1.1.tar.gz +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/importexportdata/normalization_merge/root/dev/hello.pkg/hello.pkg-1.0.tar.gz +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/importexportdata/norootpypi/dataindex.json +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/importexportdata/nouser/dataindex.json +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/importexportdata/removedindexplugin/dataindex.json +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/importexportdata/removedindexplugin/user/dev/pkg/pkg-1.0.tar.gz +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/importexportdata/toxresult_naming_scheme/dataindex.json +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/importexportdata/toxresult_naming_scheme/root/dev/hello/0.9/hello-0.9.tar.gz +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/importexportdata/toxresult_naming_scheme/root/dev/hello/sha256=ed7002b439e9ac845f22357d822bac1444730fbdb6016d3ec9432297b9ec9f73/hello-0.9.tar.gz.toxresult0 +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/importexportdata/toxresult_upload_default/dataindex.json +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/plugin.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/reqmock.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/simpypi.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/test_auth.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/test_authcheck.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/test_config.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/test_conftest.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/test_filestore.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/test_filestore_fs.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/test_fileutil.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/test_fsck.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/test_genconfig.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/test_importexport.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/test_keyfs.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/test_log.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/test_main.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/test_mirror.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/test_mirror_no_project_list.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/test_model.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/test_mythread.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/test_nginx.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/test_nginx_replica.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/test_permissions.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/test_readonly.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/test_replica_functional.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/test_streaming.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/test_streaming_nginx.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/test_streaming_replica.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/test_streaming_replica_nginx.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/test_view_auth.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/test_views.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/test_views_patch.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/test_views_push_external.py +0 -0
- {devpi_server-6.19.0 → devpi_server-6.19.1}/test_devpi_server/test_views_status.py +0 -0
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
.. towncrier release notes start
|
|
4
4
|
|
|
5
|
+
6.19.1 (2026-02-09)
|
|
6
|
+
===================
|
|
7
|
+
|
|
8
|
+
Bug Fixes
|
|
9
|
+
---------
|
|
10
|
+
|
|
11
|
+
- Pin setuptools as pyramid still requires pkg_resources.
|
|
12
|
+
|
|
13
|
+
- Always allow replicas to access deleted releases to get the proper ``410 Gone`` instead of ``403 Forbidden`` when ``devpi-lockdown`` is in use.
|
|
14
|
+
|
|
5
15
|
6.19.0 (2026-02-06)
|
|
6
16
|
===================
|
|
7
17
|
|
|
@@ -9,6 +9,16 @@ Changelog
|
|
|
9
9
|
|
|
10
10
|
.. towncrier release notes start
|
|
11
11
|
|
|
12
|
+
6.19.1 (2026-02-09)
|
|
13
|
+
===================
|
|
14
|
+
|
|
15
|
+
Bug Fixes
|
|
16
|
+
---------
|
|
17
|
+
|
|
18
|
+
- Pin setuptools as pyramid still requires pkg_resources.
|
|
19
|
+
|
|
20
|
+
- Always allow replicas to access deleted releases to get the proper ``410 Gone`` instead of ``403 Forbidden`` when ``devpi-lockdown`` is in use.
|
|
21
|
+
|
|
12
22
|
6.19.0 (2026-02-06)
|
|
13
23
|
===================
|
|
14
24
|
|
|
@@ -137,12 +147,3 @@ Bug Fixes
|
|
|
137
147
|
|
|
138
148
|
- Keep original metadata_version in database.
|
|
139
149
|
|
|
140
|
-
|
|
141
|
-
6.15.0 (2025-05-18)
|
|
142
|
-
===================
|
|
143
|
-
|
|
144
|
-
Features
|
|
145
|
-
--------
|
|
146
|
-
|
|
147
|
-
- Add ``--connection-limit`` option to devpi-server passed on to waitress.
|
|
148
|
-
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: devpi-server
|
|
3
|
-
Version: 6.19.
|
|
3
|
+
Version: 6.19.1
|
|
4
4
|
Summary: devpi-server: reliable, private, and pypi.org caching server
|
|
5
5
|
Maintainer-email: Florian Schulze <mail@pyfidelity.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -22,6 +22,7 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
22
22
|
Classifier: Programming Language :: Python :: 3.11
|
|
23
23
|
Classifier: Programming Language :: Python :: 3.12
|
|
24
24
|
Classifier: Programming Language :: Python :: 3.13
|
|
25
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
25
26
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
26
27
|
Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application
|
|
27
28
|
Classifier: Topic :: Internet :: WWW/HTTP
|
|
@@ -42,6 +43,7 @@ Requires-Dist: pluggy<2.0,>=0.6.0
|
|
|
42
43
|
Requires-Dist: py>=1.4.23
|
|
43
44
|
Requires-Dist: pyramid>=2
|
|
44
45
|
Requires-Dist: repoze.lru>=0.6
|
|
46
|
+
Requires-Dist: setuptools<=81
|
|
45
47
|
Requires-Dist: strenum; python_version < "3.11"
|
|
46
48
|
Requires-Dist: strictyaml
|
|
47
49
|
Requires-Dist: waitress>=1.0.1
|
|
@@ -122,6 +124,16 @@ Changelog
|
|
|
122
124
|
|
|
123
125
|
.. towncrier release notes start
|
|
124
126
|
|
|
127
|
+
6.19.1 (2026-02-09)
|
|
128
|
+
===================
|
|
129
|
+
|
|
130
|
+
Bug Fixes
|
|
131
|
+
---------
|
|
132
|
+
|
|
133
|
+
- Pin setuptools as pyramid still requires pkg_resources.
|
|
134
|
+
|
|
135
|
+
- Always allow replicas to access deleted releases to get the proper ``410 Gone`` instead of ``403 Forbidden`` when ``devpi-lockdown`` is in use.
|
|
136
|
+
|
|
125
137
|
6.19.0 (2026-02-06)
|
|
126
138
|
===================
|
|
127
139
|
|
|
@@ -250,12 +262,3 @@ Bug Fixes
|
|
|
250
262
|
|
|
251
263
|
- Keep original metadata_version in database.
|
|
252
264
|
|
|
253
|
-
|
|
254
|
-
6.15.0 (2025-05-18)
|
|
255
|
-
===================
|
|
256
|
-
|
|
257
|
-
Features
|
|
258
|
-
--------
|
|
259
|
-
|
|
260
|
-
- Add ``--connection-limit`` option to devpi-server passed on to waitress.
|
|
261
|
-
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "6.19.1"
|
|
@@ -740,7 +740,6 @@ class MirrorStage(BaseStage):
|
|
|
740
740
|
serial: int,
|
|
741
741
|
etag: str | None,
|
|
742
742
|
) -> None:
|
|
743
|
-
assert links != () # we don't store the old "Not Found" marker anymore
|
|
744
743
|
assert isinstance(serial, int)
|
|
745
744
|
assert project == normalize_name(project), project
|
|
746
745
|
data: CacheLinks = {
|
|
@@ -546,9 +546,6 @@ class BaseStageCustomizer:
|
|
|
546
546
|
principals = {':ANONYMOUS:'}
|
|
547
547
|
else:
|
|
548
548
|
principals = set(principals)
|
|
549
|
-
if self.stage.xom.is_primary():
|
|
550
|
-
# replicas always need to be able to download packages
|
|
551
|
-
principals.add("+replica")
|
|
552
549
|
# admins should always be able to read the packages
|
|
553
550
|
if restrict_modify is None:
|
|
554
551
|
principals.add("root")
|
|
@@ -6,6 +6,7 @@ from devpi_server.config import hookimpl
|
|
|
6
6
|
from devpi_server.config import traced_pluggy_call
|
|
7
7
|
from devpi_server.model import BaseStage
|
|
8
8
|
from devpi_server.model import UpstreamError
|
|
9
|
+
from devpi_server.replica import REPLICA_USER_NAME
|
|
9
10
|
from devpi_server.views import abort
|
|
10
11
|
from pyramid.authorization import ACLHelper
|
|
11
12
|
from pyramid.authorization import Allow
|
|
@@ -62,7 +63,10 @@ class RootFactory:
|
|
|
62
63
|
|
|
63
64
|
@cached_property
|
|
64
65
|
def __acl__(self):
|
|
65
|
-
acl = [
|
|
66
|
+
acl = [
|
|
67
|
+
(Allow, Everyone, "user_login"),
|
|
68
|
+
(Allow, REPLICA_USER_NAME, "pkg_read"),
|
|
69
|
+
]
|
|
66
70
|
if self.restrict_modify is None:
|
|
67
71
|
acl.extend(
|
|
68
72
|
[
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: devpi-server
|
|
3
|
-
Version: 6.19.
|
|
3
|
+
Version: 6.19.1
|
|
4
4
|
Summary: devpi-server: reliable, private, and pypi.org caching server
|
|
5
5
|
Maintainer-email: Florian Schulze <mail@pyfidelity.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -22,6 +22,7 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
22
22
|
Classifier: Programming Language :: Python :: 3.11
|
|
23
23
|
Classifier: Programming Language :: Python :: 3.12
|
|
24
24
|
Classifier: Programming Language :: Python :: 3.13
|
|
25
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
25
26
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
26
27
|
Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application
|
|
27
28
|
Classifier: Topic :: Internet :: WWW/HTTP
|
|
@@ -42,6 +43,7 @@ Requires-Dist: pluggy<2.0,>=0.6.0
|
|
|
42
43
|
Requires-Dist: py>=1.4.23
|
|
43
44
|
Requires-Dist: pyramid>=2
|
|
44
45
|
Requires-Dist: repoze.lru>=0.6
|
|
46
|
+
Requires-Dist: setuptools<=81
|
|
45
47
|
Requires-Dist: strenum; python_version < "3.11"
|
|
46
48
|
Requires-Dist: strictyaml
|
|
47
49
|
Requires-Dist: waitress>=1.0.1
|
|
@@ -122,6 +124,16 @@ Changelog
|
|
|
122
124
|
|
|
123
125
|
.. towncrier release notes start
|
|
124
126
|
|
|
127
|
+
6.19.1 (2026-02-09)
|
|
128
|
+
===================
|
|
129
|
+
|
|
130
|
+
Bug Fixes
|
|
131
|
+
---------
|
|
132
|
+
|
|
133
|
+
- Pin setuptools as pyramid still requires pkg_resources.
|
|
134
|
+
|
|
135
|
+
- Always allow replicas to access deleted releases to get the proper ``410 Gone`` instead of ``403 Forbidden`` when ``devpi-lockdown`` is in use.
|
|
136
|
+
|
|
125
137
|
6.19.0 (2026-02-06)
|
|
126
138
|
===================
|
|
127
139
|
|
|
@@ -250,12 +262,3 @@ Bug Fixes
|
|
|
250
262
|
|
|
251
263
|
- Keep original metadata_version in database.
|
|
252
264
|
|
|
253
|
-
|
|
254
|
-
6.15.0 (2025-05-18)
|
|
255
|
-
===================
|
|
256
|
-
|
|
257
|
-
Features
|
|
258
|
-
--------
|
|
259
|
-
|
|
260
|
-
- Add ``--connection-limit`` option to devpi-server passed on to waitress.
|
|
261
|
-
|
|
@@ -22,6 +22,7 @@ dependencies = [
|
|
|
22
22
|
"py>=1.4.23",
|
|
23
23
|
"pyramid>=2",
|
|
24
24
|
"repoze.lru>=0.6",
|
|
25
|
+
"setuptools<=81", # removed pkg_resources required by pyramid
|
|
25
26
|
"strenum;python_version<'3.11'",
|
|
26
27
|
"strictyaml",
|
|
27
28
|
"waitress>=1.0.1",
|
|
@@ -46,6 +47,7 @@ classifiers = [
|
|
|
46
47
|
"Programming Language :: Python :: 3.11",
|
|
47
48
|
"Programming Language :: Python :: 3.12",
|
|
48
49
|
"Programming Language :: Python :: 3.13",
|
|
50
|
+
"Programming Language :: Python :: 3.14",
|
|
49
51
|
"Programming Language :: Python :: Implementation :: PyPy",
|
|
50
52
|
"Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
|
|
51
53
|
"Topic :: Internet :: WWW/HTTP",
|
|
File without changes
|
|
File without changes
|
|
@@ -1305,6 +1305,125 @@ def test_replica_user_auth_before_other_plugins(makexom):
|
|
|
1305
1305
|
auth._get_auth_status(replica.REPLICA_USER_NAME, '')
|
|
1306
1306
|
|
|
1307
1307
|
|
|
1308
|
+
def test_pkg_read_permission(makemapp, maketestapp, makexom):
|
|
1309
|
+
from devpi_common.types import ensure_unicode
|
|
1310
|
+
from devpi_server.config import hookimpl
|
|
1311
|
+
from devpi_server.model import ACLList
|
|
1312
|
+
from webob.headers import ResponseHeaders
|
|
1313
|
+
import itsdangerous
|
|
1314
|
+
|
|
1315
|
+
class Plugin:
|
|
1316
|
+
@hookimpl
|
|
1317
|
+
def devpiserver_indexconfig_defaults(self, index_type): # noqa: ARG002
|
|
1318
|
+
return {"acl_pkg_read": ACLList(["root"])}
|
|
1319
|
+
|
|
1320
|
+
@hookimpl
|
|
1321
|
+
def devpiserver_stage_get_principals_for_pkg_read(self, ixconfig):
|
|
1322
|
+
return ixconfig.get("acl_pkg_read", None)
|
|
1323
|
+
|
|
1324
|
+
plugin = Plugin()
|
|
1325
|
+
xom = makexom(plugins=[plugin])
|
|
1326
|
+
xom.config.nodeinfo["role"] = "primary"
|
|
1327
|
+
testapp = maketestapp(xom)
|
|
1328
|
+
mapp = makemapp(testapp)
|
|
1329
|
+
auth_serializer = itsdangerous.TimedSerializer(mapp.xom.config.get_replica_secret())
|
|
1330
|
+
uuid = "111"
|
|
1331
|
+
api = mapp.create_and_use("someuser/dev")
|
|
1332
|
+
mapp.upload_file_pypi("hello-1.0.tar.gz", b"content", "hello", "1.0")
|
|
1333
|
+
(path,) = mapp.get_release_paths("hello")
|
|
1334
|
+
# replica should be able to access the release
|
|
1335
|
+
testapp.xget(
|
|
1336
|
+
200,
|
|
1337
|
+
"/+authcheck",
|
|
1338
|
+
headers=ResponseHeaders(
|
|
1339
|
+
{
|
|
1340
|
+
H_REPLICA_UUID: uuid,
|
|
1341
|
+
"X-Original-URI": path,
|
|
1342
|
+
"Authorization": f"Bearer {ensure_unicode(auth_serializer.dumps(uuid))}",
|
|
1343
|
+
}
|
|
1344
|
+
),
|
|
1345
|
+
)
|
|
1346
|
+
testapp.xget(
|
|
1347
|
+
200,
|
|
1348
|
+
path,
|
|
1349
|
+
headers=ResponseHeaders(
|
|
1350
|
+
{
|
|
1351
|
+
H_REPLICA_UUID: uuid,
|
|
1352
|
+
"Authorization": f"Bearer {ensure_unicode(auth_serializer.dumps(uuid))}",
|
|
1353
|
+
}
|
|
1354
|
+
),
|
|
1355
|
+
)
|
|
1356
|
+
# after project deletion the file is marked as gone
|
|
1357
|
+
mapp.delete_project("hello")
|
|
1358
|
+
testapp.xget(
|
|
1359
|
+
200,
|
|
1360
|
+
"/+authcheck",
|
|
1361
|
+
headers=ResponseHeaders(
|
|
1362
|
+
{
|
|
1363
|
+
H_REPLICA_UUID: uuid,
|
|
1364
|
+
"X-Original-URI": path,
|
|
1365
|
+
"Authorization": f"Bearer {ensure_unicode(auth_serializer.dumps(uuid))}",
|
|
1366
|
+
}
|
|
1367
|
+
),
|
|
1368
|
+
)
|
|
1369
|
+
testapp.xget(
|
|
1370
|
+
410,
|
|
1371
|
+
path,
|
|
1372
|
+
headers=ResponseHeaders(
|
|
1373
|
+
{
|
|
1374
|
+
H_REPLICA_UUID: uuid,
|
|
1375
|
+
"Authorization": f"Bearer {ensure_unicode(auth_serializer.dumps(uuid))}",
|
|
1376
|
+
}
|
|
1377
|
+
),
|
|
1378
|
+
)
|
|
1379
|
+
# after index deletion the file is still marked as gone
|
|
1380
|
+
mapp.delete_index(api.stagename)
|
|
1381
|
+
testapp.xget(
|
|
1382
|
+
200,
|
|
1383
|
+
"/+authcheck",
|
|
1384
|
+
headers=ResponseHeaders(
|
|
1385
|
+
{
|
|
1386
|
+
H_REPLICA_UUID: uuid,
|
|
1387
|
+
"X-Original-URI": path,
|
|
1388
|
+
"Authorization": f"Bearer {ensure_unicode(auth_serializer.dumps(uuid))}",
|
|
1389
|
+
}
|
|
1390
|
+
),
|
|
1391
|
+
)
|
|
1392
|
+
testapp.xget(
|
|
1393
|
+
410,
|
|
1394
|
+
path,
|
|
1395
|
+
headers=ResponseHeaders(
|
|
1396
|
+
{
|
|
1397
|
+
H_REPLICA_UUID: uuid,
|
|
1398
|
+
"Authorization": f"Bearer {ensure_unicode(auth_serializer.dumps(uuid))}",
|
|
1399
|
+
}
|
|
1400
|
+
),
|
|
1401
|
+
)
|
|
1402
|
+
# also after user deletion
|
|
1403
|
+
mapp.delete_user(api.user)
|
|
1404
|
+
testapp.xget(
|
|
1405
|
+
200,
|
|
1406
|
+
"/+authcheck",
|
|
1407
|
+
headers=ResponseHeaders(
|
|
1408
|
+
{
|
|
1409
|
+
H_REPLICA_UUID: uuid,
|
|
1410
|
+
"X-Original-URI": path,
|
|
1411
|
+
"Authorization": f"Bearer {ensure_unicode(auth_serializer.dumps(uuid))}",
|
|
1412
|
+
}
|
|
1413
|
+
),
|
|
1414
|
+
)
|
|
1415
|
+
testapp.xget(
|
|
1416
|
+
410,
|
|
1417
|
+
path,
|
|
1418
|
+
headers=ResponseHeaders(
|
|
1419
|
+
{
|
|
1420
|
+
H_REPLICA_UUID: uuid,
|
|
1421
|
+
"Authorization": f"Bearer {ensure_unicode(auth_serializer.dumps(uuid))}",
|
|
1422
|
+
}
|
|
1423
|
+
),
|
|
1424
|
+
)
|
|
1425
|
+
|
|
1426
|
+
|
|
1308
1427
|
class TestFileReplicationSharedData:
|
|
1309
1428
|
@pytest.fixture
|
|
1310
1429
|
def shared_data(self, replica_xom):
|
|
@@ -269,7 +269,6 @@ def test_package_filters(makemapp, maketestapp, makexom):
|
|
|
269
269
|
|
|
270
270
|
def test_pkg_read_permission(makemapp, maketestapp, makexom):
|
|
271
271
|
from devpi_server.model import ACLList
|
|
272
|
-
from devpi_server.replica import REPLICA_USER_NAME
|
|
273
272
|
from webob.headers import ResponseHeaders
|
|
274
273
|
import json
|
|
275
274
|
|
|
@@ -341,16 +340,6 @@ def test_pkg_read_permission(makemapp, maketestapp, makexom):
|
|
|
341
340
|
req = dict(name="hello", version="1.0", targetindex="otheruser/dev")
|
|
342
341
|
r = testapp.push("/someuser/dev", json.dumps(req))
|
|
343
342
|
assert r.status_code == 403
|
|
344
|
-
with xom.keyfs.read_transaction():
|
|
345
|
-
stage = xom.model.getstage(api1.stagename)
|
|
346
|
-
# by default get_principals_for_pkg_read returns just the set principals
|
|
347
|
-
assert stage.customizer.get_principals_for_pkg_read() == {
|
|
348
|
-
'root', 'someuser'}
|
|
349
|
-
# but if the server acts as a primary for replicas,
|
|
350
|
-
# then the special replica user is included
|
|
351
|
-
xom.config.nodeinfo['role'] = 'primary'
|
|
352
|
-
assert set(stage.customizer.get_principals_for_pkg_read()) == {
|
|
353
|
-
'root', 'someuser', REPLICA_USER_NAME}
|
|
354
343
|
|
|
355
344
|
|
|
356
345
|
def test_sro_skip_plugin(makemapp, maketestapp, makexom, pypistage):
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "6.19.0"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
partial
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
partial
|
|
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.19.0 → devpi_server-6.19.1}/devpi_server/cfg/nginx-devpi-caching-http.conf.template
RENAMED
|
File without changes
|
|
File without changes
|
{devpi_server-6.19.0 → devpi_server-6.19.1}/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
|
/devpi_server-6.19.0/test_devpi_server/__init__.py → /devpi_server-6.19.1/devpi_server/py.typed
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
|
{devpi_server-6.19.0 → devpi_server-6.19.1}/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.19.0 → devpi_server-6.19.1}/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
|
{devpi_server-6.19.0 → devpi_server-6.19.1}/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
|