devpi-server 6.13.0__tar.gz → 6.14.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.13.0 → devpi-server-6.14.0}/CHANGELOG +21 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/PKG-INFO +22 -22
- devpi-server-6.14.0/devpi_server/__init__.py +1 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/main.py +5 -2
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/views.py +46 -27
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server.egg-info/PKG-INFO +22 -22
- {devpi-server-6.13.0 → devpi-server-6.14.0}/setup.py +1 -1
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/plugin.py +7 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/test_views.py +86 -1
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/test_views_push_external.py +54 -24
- devpi-server-6.13.0/devpi_server/__init__.py +0 -1
- {devpi-server-6.13.0 → devpi-server-6.14.0}/.flake8 +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/AUTHORS +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/LICENSE +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/MANIFEST.in +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/README.rst +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/__main__.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/auth.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/auth_basic.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/auth_devpi.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/cfg/__init__.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/cfg/crontab.template +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/cfg/devpi.service.template +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/cfg/launchd-macos.txt.template +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/cfg/nginx-devpi-caching-http.conf.template +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/cfg/nginx-devpi-caching-location.conf.template +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/cfg/nginx-devpi-caching-proxy.conf.template +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/cfg/nginx-devpi-caching-server.conf.template +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/cfg/nginx-devpi.conf.template +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/cfg/supervisor-devpi.conf.template +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/cfg/supervisord.conf.template +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/cfg/windows-service.txt.template +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/config.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/exceptions.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/filestore.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/filestore_fs.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/fileutil.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/fsck.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/genconfig.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/hookspecs.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/importexport.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/init.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/interfaces.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/keyfs.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/keyfs_sqlite.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/keyfs_sqlite_fs.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/keyfs_types.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/log.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/markers.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/middleware.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/mirror.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/model.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/mythread.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/passwd.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/readonly.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/replica.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/sizeof.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/vendor/__init__.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/vendor/_pip.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server/view_auth.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server.egg-info/SOURCES.txt +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server.egg-info/dependency_links.txt +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server.egg-info/entry_points.txt +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server.egg-info/not-zip-safe +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server.egg-info/requires.txt +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/devpi_server.egg-info/top_level.txt +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/pyproject.toml +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/pytest_devpi_server/__init__.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/setup.cfg +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/__init__.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/conftest.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/example.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/functional.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/importexportdata/badindexname/dataindex.json +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/importexportdata/badusername/dataindex.json +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/importexportdata/basescycle/dataindex.json +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/importexportdata/createdmodified/dataindex.json +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/importexportdata/deletedbase/dataindex.json +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/importexportdata/mirrordata/dataindex.json +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/importexportdata/mirrordata/root/pypi/dddttt/0.1.dev1/dddttt-0.1.dev1.tar.gz +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/importexportdata/modifiedpypi/dataindex.json +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/importexportdata/nocreatedmodified/dataindex.json +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/importexportdata/normalization/dataindex.json +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/importexportdata/normalization/root/dev/hello.pkg/hello.pkg-1.0.tar.gz +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/importexportdata/normalization_merge/dataindex.json +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/importexportdata/normalization_merge/root/dev/hello-pkg/hello.pkg-1.1.tar.gz +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/importexportdata/normalization_merge/root/dev/hello.pkg/hello.pkg-1.0.tar.gz +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/importexportdata/norootpypi/dataindex.json +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/importexportdata/nouser/dataindex.json +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/importexportdata/removedindexplugin/dataindex.json +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/importexportdata/removedindexplugin/user/dev/pkg/pkg-1.0.tar.gz +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/importexportdata/toxresult_naming_scheme/dataindex.json +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/importexportdata/toxresult_naming_scheme/root/dev/hello/0.9/hello-0.9.tar.gz +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/importexportdata/toxresult_naming_scheme/root/dev/hello/sha256=ed7002b439e9ac845f22357d822bac1444730fbdb6016d3ec9432297b9ec9f73/hello-0.9.tar.gz.toxresult0 +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/importexportdata/toxresult_upload_default/dataindex.json +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/reqmock.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/simpypi.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/test_auth.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/test_authcheck.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/test_config.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/test_conftest.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/test_filestore.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/test_fileutil.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/test_fsck.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/test_genconfig.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/test_importexport.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/test_keyfs.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/test_keyfs_sqlite_fs.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/test_log.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/test_main.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/test_mirror.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/test_mirror_no_project_list.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/test_model.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/test_mythread.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/test_nginx.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/test_nginx_replica.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/test_permissions.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/test_readonly.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/test_replica.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/test_replica_functional.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/test_reqmock.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/test_stage_customizer.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/test_streaming.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/test_streaming_nginx.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/test_streaming_replica.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/test_streaming_replica_nginx.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/test_view_auth.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/test_views_patch.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/test_devpi_server/test_views_status.py +0 -0
- {devpi-server-6.13.0 → devpi-server-6.14.0}/tox.ini +0 -0
|
@@ -2,6 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
.. towncrier release notes start
|
|
4
4
|
|
|
5
|
+
6.14.0 (2024-10-16)
|
|
6
|
+
===================
|
|
7
|
+
|
|
8
|
+
Features
|
|
9
|
+
--------
|
|
10
|
+
|
|
11
|
+
- Allow pushing of versions which only have documentation and no releases.
|
|
12
|
+
|
|
13
|
+
- Allow pushing of release files only with no documentation. Requires devpi-client 7.2.0.
|
|
14
|
+
|
|
15
|
+
- Allow pushing of documentation only with no release files. Requires devpi-client 7.2.0.
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
Bug Fixes
|
|
20
|
+
---------
|
|
21
|
+
|
|
22
|
+
- No longer automatically "register" a project when pushing releases to PyPI. The reply changed from HTTP status 410 to 400 breaking the upload. With devpi-client 7.2.0 there is a ``--register-project`` option if it is still required for some other package registry.
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
5
26
|
6.13.0 (2024-09-19)
|
|
6
27
|
===================
|
|
7
28
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: devpi-server
|
|
3
|
-
Version: 6.
|
|
3
|
+
Version: 6.14.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
|
|
@@ -105,6 +105,27 @@ Changelog
|
|
|
105
105
|
|
|
106
106
|
.. towncrier release notes start
|
|
107
107
|
|
|
108
|
+
6.14.0 (2024-10-16)
|
|
109
|
+
===================
|
|
110
|
+
|
|
111
|
+
Features
|
|
112
|
+
--------
|
|
113
|
+
|
|
114
|
+
- Allow pushing of versions which only have documentation and no releases.
|
|
115
|
+
|
|
116
|
+
- Allow pushing of release files only with no documentation. Requires devpi-client 7.2.0.
|
|
117
|
+
|
|
118
|
+
- Allow pushing of documentation only with no release files. Requires devpi-client 7.2.0.
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
Bug Fixes
|
|
123
|
+
---------
|
|
124
|
+
|
|
125
|
+
- No longer automatically "register" a project when pushing releases to PyPI. The reply changed from HTTP status 410 to 400 breaking the upload. With devpi-client 7.2.0 there is a ``--register-project`` option if it is still required for some other package registry.
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
|
|
108
129
|
6.13.0 (2024-09-19)
|
|
109
130
|
===================
|
|
110
131
|
|
|
@@ -193,24 +214,3 @@ Bug Fixes
|
|
|
193
214
|
- Fix #1033: Use ``int`` for ``--mirror-cache-expiry`` to fix value of ``proxy_cache_valid`` in nginx caching config.
|
|
194
215
|
|
|
195
216
|
|
|
196
|
-
|
|
197
|
-
6.10.0 (2023-12-19)
|
|
198
|
-
===================
|
|
199
|
-
|
|
200
|
-
Features
|
|
201
|
-
--------
|
|
202
|
-
|
|
203
|
-
- Use ``Authorization`` header instead of adding username/password to URL when fetching from mirror.
|
|
204
|
-
|
|
205
|
-
- Fix #998: Use the pure Python httpx library instead of aiohttp to prevent delays in supporting newest Python releases.
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
Bug Fixes
|
|
210
|
-
---------
|
|
211
|
-
|
|
212
|
-
- Fix #996: support hashes other than sha256 in application/vnd.pypi.simple.v1+json responses.
|
|
213
|
-
|
|
214
|
-
- Only compare hostname instead of full URL prefix when parsing mirror packages to fix mirrors with basic authentication and absolute URLs. See #1006
|
|
215
|
-
|
|
216
|
-
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = '6.14.0'
|
|
@@ -365,9 +365,12 @@ class XOM:
|
|
|
365
365
|
|
|
366
366
|
@cached_property
|
|
367
367
|
def supported_features(self):
|
|
368
|
-
results =
|
|
368
|
+
results = {
|
|
369
|
+
'push-no-docs',
|
|
370
|
+
'push-only-docs',
|
|
371
|
+
'push-register-project',
|
|
369
372
|
'server-keyvalue-parsing',
|
|
370
|
-
|
|
373
|
+
}
|
|
371
374
|
for features in self.config.hook.devpiserver_get_features():
|
|
372
375
|
results.update(features)
|
|
373
376
|
return tuple(sorted(results))
|
|
@@ -10,6 +10,7 @@ from devpi_common.url import URL
|
|
|
10
10
|
from devpi_common.metadata import get_pyversion_filetype
|
|
11
11
|
import devpi_server
|
|
12
12
|
from html import escape
|
|
13
|
+
from http import HTTPStatus
|
|
13
14
|
from lazy import lazy
|
|
14
15
|
from operator import attrgetter
|
|
15
16
|
from pluggy import HookimplMarker
|
|
@@ -141,7 +142,7 @@ class HTTPResponse(HTTPSuccessful):
|
|
|
141
142
|
Exception.__init__(self)
|
|
142
143
|
|
|
143
144
|
|
|
144
|
-
def
|
|
145
|
+
def apiresult(code, message=None, result=None, type=None): # noqa: A002
|
|
145
146
|
d = dict()
|
|
146
147
|
if result is not None:
|
|
147
148
|
assert type is not None
|
|
@@ -151,7 +152,11 @@ def apireturn(code, message=None, result=None, type=None):
|
|
|
151
152
|
d["message"] = message
|
|
152
153
|
data = json.dumps(d, indent=2) + "\n"
|
|
153
154
|
headers = {"content-type": "application/json"}
|
|
154
|
-
|
|
155
|
+
return HTTPResponse(body=data, status=code, headers=headers)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def apireturn(code, message=None, result=None, type=None): # noqa: A002
|
|
159
|
+
raise apiresult(code, message=message, result=result, type=type)
|
|
155
160
|
|
|
156
161
|
|
|
157
162
|
def json_preferred(request):
|
|
@@ -1007,8 +1012,8 @@ class PyPIView:
|
|
|
1007
1012
|
stage = self.context.stage
|
|
1008
1013
|
pushdata = getjson(request)
|
|
1009
1014
|
try:
|
|
1010
|
-
name = pushdata
|
|
1011
|
-
version = pushdata
|
|
1015
|
+
name = pushdata.pop("name")
|
|
1016
|
+
version = pushdata.pop("version")
|
|
1012
1017
|
except KeyError:
|
|
1013
1018
|
apireturn(400, message="no name/version specified in json")
|
|
1014
1019
|
|
|
@@ -1018,14 +1023,21 @@ class PyPIView:
|
|
|
1018
1023
|
except stage.MissesRegistration:
|
|
1019
1024
|
apireturn(400, "there are no files for %s-%s on stage %s" % (
|
|
1020
1025
|
name, version, stage.name))
|
|
1026
|
+
rels = {'releasefile', 'doczip', 'toxresult'}
|
|
1027
|
+
no_docs = pushdata.pop("no_docs", False)
|
|
1028
|
+
only_docs = pushdata.pop("only_docs", False)
|
|
1029
|
+
if no_docs and only_docs:
|
|
1030
|
+
return apiresult(400, "can't use 'no_docs' and 'only_docs' together")
|
|
1031
|
+
if no_docs:
|
|
1032
|
+
rels.remove('doczip')
|
|
1033
|
+
elif only_docs:
|
|
1034
|
+
rels = {'doczip'}
|
|
1021
1035
|
links = {
|
|
1022
1036
|
rel: sorted(linkstore.get_links(rel=rel), key=attrgetter('basename'))
|
|
1023
|
-
for rel in
|
|
1024
|
-
if not links
|
|
1025
|
-
self.log.info("%s: no
|
|
1026
|
-
|
|
1027
|
-
apireturn(404, message="no release/files found for %s-%s" % (
|
|
1028
|
-
name, version))
|
|
1037
|
+
for rel in rels}
|
|
1038
|
+
if not any(links.values()):
|
|
1039
|
+
self.log.info("%s: no files for version %s %s", stage.name, name, version)
|
|
1040
|
+
apireturn(404, f"no release/files found for {name} {version}")
|
|
1029
1041
|
|
|
1030
1042
|
if not request.has_permission("pkg_read"):
|
|
1031
1043
|
abort(request, 403, "package read forbidden")
|
|
@@ -1033,8 +1045,11 @@ class PyPIView:
|
|
|
1033
1045
|
metadata = linkstore.metadata
|
|
1034
1046
|
|
|
1035
1047
|
results = []
|
|
1036
|
-
targetindex = pushdata.
|
|
1048
|
+
targetindex = pushdata.pop("targetindex", None)
|
|
1037
1049
|
if targetindex is not None: # in-server push
|
|
1050
|
+
if pushdata:
|
|
1051
|
+
keys = ', '.join(sorted(pushdata.keys()))
|
|
1052
|
+
return apiresult(400, f"unknown additional options: {keys}")
|
|
1038
1053
|
parts = targetindex.split("/")
|
|
1039
1054
|
if len(parts) != 2:
|
|
1040
1055
|
apireturn(400, message="targetindex not in format user/index")
|
|
@@ -1057,6 +1072,7 @@ class PyPIView:
|
|
|
1057
1072
|
return apireturn(502, e.args[0])
|
|
1058
1073
|
apireturn(200, result=results, type="actionlog")
|
|
1059
1074
|
else:
|
|
1075
|
+
register_project = pushdata.pop("register_project", False)
|
|
1060
1076
|
posturl = pushdata["posturl"]
|
|
1061
1077
|
username = pushdata["username"]
|
|
1062
1078
|
password = pushdata["password"]
|
|
@@ -1064,22 +1080,25 @@ class PyPIView:
|
|
|
1064
1080
|
# prepare metadata for submission
|
|
1065
1081
|
metadata[":action"] = "submit"
|
|
1066
1082
|
metadata["metadata_version"] = "2.1"
|
|
1067
|
-
self.log.info("registering %s-%s to %s", name, version, posturl)
|
|
1068
1083
|
session = new_requests_session(agent=("server", server_version))
|
|
1069
1084
|
with contextlib.closing(session):
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1085
|
+
ok_codes = {HTTPStatus.OK, HTTPStatus.CREATED}
|
|
1086
|
+
if register_project:
|
|
1087
|
+
self.log.info("registering %s-%s to %s", name, version, posturl)
|
|
1088
|
+
try:
|
|
1089
|
+
r = session.post(posturl, data=metadata, auth=pypiauth)
|
|
1090
|
+
r.close()
|
|
1091
|
+
except Exception as e: # noqa: BLE001
|
|
1092
|
+
exc_msg = ''.join(traceback.format_exception_only(e.__class__, e))
|
|
1093
|
+
results.append((-1, "exception on register:", exc_msg))
|
|
1094
|
+
apireturn(502, result=results, type="actionlog")
|
|
1095
|
+
self.log.debug("register returned: %s", r.status_code)
|
|
1096
|
+
results.append((r.status_code, "register", name, version))
|
|
1097
|
+
proceed = (r.status_code in ok_codes | {HTTPStatus.GONE})
|
|
1098
|
+
else:
|
|
1099
|
+
proceed = True
|
|
1081
1100
|
if proceed:
|
|
1082
|
-
for link in links
|
|
1101
|
+
for link in links.get("releasefile", ()):
|
|
1083
1102
|
entry = link.entry
|
|
1084
1103
|
file_metadata = metadata.copy()
|
|
1085
1104
|
file_metadata[":action"] = "file_upload"
|
|
@@ -1106,7 +1125,7 @@ class PyPIView:
|
|
|
1106
1125
|
results.append((
|
|
1107
1126
|
r.status_code, "upload", entry.relpath, text))
|
|
1108
1127
|
r.close()
|
|
1109
|
-
if links
|
|
1128
|
+
if links.get("doczip", ()):
|
|
1110
1129
|
doc_metadata = metadata.copy()
|
|
1111
1130
|
doc_metadata[":action"] = "doc_upload"
|
|
1112
1131
|
doczip = links["doczip"][0].entry.file_get_content()
|
|
@@ -1128,7 +1147,7 @@ class PyPIView:
|
|
|
1128
1147
|
|
|
1129
1148
|
def _push_links(self, links, target_stage, name, version):
|
|
1130
1149
|
stage = self.context.stage
|
|
1131
|
-
for link in links
|
|
1150
|
+
for link in links.get("releasefile", ()):
|
|
1132
1151
|
entry = link.entry
|
|
1133
1152
|
logs = link.get_logs()
|
|
1134
1153
|
del link
|
|
@@ -1170,7 +1189,7 @@ class PyPIView:
|
|
|
1170
1189
|
src=self.context.stage.name,
|
|
1171
1190
|
dst=target_stage.name)
|
|
1172
1191
|
yield (200, "store_toxresult", tlink.entrypath)
|
|
1173
|
-
for link in links
|
|
1192
|
+
for link in links.get("doczip", ()):
|
|
1174
1193
|
with link.entry.file_open_read() as doczip:
|
|
1175
1194
|
new_link = target_stage.store_doczip(
|
|
1176
1195
|
name, version, doczip, hashes=link.entry.hashes)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: devpi-server
|
|
3
|
-
Version: 6.
|
|
3
|
+
Version: 6.14.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
|
|
@@ -105,6 +105,27 @@ Changelog
|
|
|
105
105
|
|
|
106
106
|
.. towncrier release notes start
|
|
107
107
|
|
|
108
|
+
6.14.0 (2024-10-16)
|
|
109
|
+
===================
|
|
110
|
+
|
|
111
|
+
Features
|
|
112
|
+
--------
|
|
113
|
+
|
|
114
|
+
- Allow pushing of versions which only have documentation and no releases.
|
|
115
|
+
|
|
116
|
+
- Allow pushing of release files only with no documentation. Requires devpi-client 7.2.0.
|
|
117
|
+
|
|
118
|
+
- Allow pushing of documentation only with no release files. Requires devpi-client 7.2.0.
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
Bug Fixes
|
|
123
|
+
---------
|
|
124
|
+
|
|
125
|
+
- No longer automatically "register" a project when pushing releases to PyPI. The reply changed from HTTP status 410 to 400 breaking the upload. With devpi-client 7.2.0 there is a ``--register-project`` option if it is still required for some other package registry.
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
|
|
108
129
|
6.13.0 (2024-09-19)
|
|
109
130
|
===================
|
|
110
131
|
|
|
@@ -193,24 +214,3 @@ Bug Fixes
|
|
|
193
214
|
- Fix #1033: Use ``int`` for ``--mirror-cache-expiry`` to fix value of ``proxy_cache_valid`` in nginx caching config.
|
|
194
215
|
|
|
195
216
|
|
|
196
|
-
|
|
197
|
-
6.10.0 (2023-12-19)
|
|
198
|
-
===================
|
|
199
|
-
|
|
200
|
-
Features
|
|
201
|
-
--------
|
|
202
|
-
|
|
203
|
-
- Use ``Authorization`` header instead of adding username/password to URL when fetching from mirror.
|
|
204
|
-
|
|
205
|
-
- Fix #998: Use the pure Python httpx library instead of aiohttp to prevent delays in supporting newest Python releases.
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
Bug Fixes
|
|
210
|
-
---------
|
|
211
|
-
|
|
212
|
-
- Fix #996: support hashes other than sha256 in application/vnd.pypi.simple.v1+json responses.
|
|
213
|
-
|
|
214
|
-
- Only compare hostname instead of full URL prefix when parsing mirror packages to fix mirrors with basic authentication and absolute URLs. See #1006
|
|
215
|
-
|
|
216
|
-
|
|
@@ -59,7 +59,7 @@ if __name__ == "__main__":
|
|
|
59
59
|
'Funding': 'https://github.com/sponsors/devpi',
|
|
60
60
|
'Source Code': 'https://github.com/devpi/devpi'
|
|
61
61
|
},
|
|
62
|
-
version='6.
|
|
62
|
+
version='6.14.0',
|
|
63
63
|
maintainer="Florian Schulze",
|
|
64
64
|
maintainer_email="mail@pyfidelity.com",
|
|
65
65
|
packages=[
|
|
@@ -910,6 +910,13 @@ class Mapp(MappMixin):
|
|
|
910
910
|
assert r.status_code == code
|
|
911
911
|
if waithooks:
|
|
912
912
|
self._wait_for_serial_in_result(r)
|
|
913
|
+
|
|
914
|
+
# return the file url so users/callers can easily use it
|
|
915
|
+
# (probably the official server response should include the url)
|
|
916
|
+
r.file_url = make_file_url(basename, content, stagename=indexname)
|
|
917
|
+
r.file_url_no_hash = make_file_url(
|
|
918
|
+
basename, content, stagename=indexname, add_hash=False)
|
|
919
|
+
|
|
913
920
|
return r
|
|
914
921
|
|
|
915
922
|
def upload_toxresult(self, path, content, code=200, waithooks=False):
|
|
@@ -1389,8 +1389,57 @@ def test_upload_docs_for_version_without_release(mapp, testapp, monkeypatch):
|
|
|
1389
1389
|
mapp.upload_doc("pkg1-2.7.doc.zip", b'', "pkg1", "2.7")
|
|
1390
1390
|
|
|
1391
1391
|
|
|
1392
|
+
def test_upload_and_push_docs_only(mapp, testapp):
|
|
1393
|
+
mapp.create_and_login_user()
|
|
1394
|
+
mapp.create_index("prod")
|
|
1395
|
+
mapp.create_index("dev")
|
|
1396
|
+
mapp.upload_file_pypi("pkg1-2.6.tgz", b"123", "pkg1", "2.6")
|
|
1397
|
+
content26 = zip_dict({"index.html": "<html><body>2.6</body></html>"})
|
|
1398
|
+
mapp.upload_doc("pkg1.zip", content26, "pkg1", "")
|
|
1399
|
+
mapp.upload_file_pypi("pkg1-2.7.tgz", b"123", "pkg1", "2.7")
|
|
1400
|
+
content27 = zip_dict({"index.html": "<html><body>2.7</body></html>"})
|
|
1401
|
+
mapp.upload_doc("pkg1.zip", content27, "pkg1", "")
|
|
1402
|
+
req = dict(name="pkg1", version="2.6", targetindex="someuser/prod", only_docs=True)
|
|
1403
|
+
testapp.post("/someuser/dev", params=json.dumps(req), code=200)
|
|
1404
|
+
vv = get_view_version_links(testapp, "/someuser/prod", "pkg1", "2.6")
|
|
1405
|
+
(link,) = vv.get_links()
|
|
1406
|
+
assert link.basename == "pkg1-2.6.doc.zip"
|
|
1407
|
+
assert link.rel == "doczip"
|
|
1408
|
+
mapp.getjson("/someuser/prod/2.7", code=404)
|
|
1409
|
+
|
|
1410
|
+
|
|
1411
|
+
def test_upload_and_push_no_docs(mapp, testapp):
|
|
1412
|
+
mapp.create_and_login_user()
|
|
1413
|
+
mapp.create_index("prod")
|
|
1414
|
+
mapp.create_index("dev")
|
|
1415
|
+
mapp.upload_file_pypi("pkg1-2.6.tgz", b"123", "pkg1", "2.6")
|
|
1416
|
+
content26 = zip_dict({"index.html": "<html><body>2.6</body></html>"})
|
|
1417
|
+
mapp.upload_doc("pkg1.zip", content26, "pkg1", "")
|
|
1418
|
+
mapp.upload_file_pypi("pkg1-2.7.tgz", b"123", "pkg1", "2.7")
|
|
1419
|
+
content27 = zip_dict({"index.html": "<html><body>2.7</body></html>"})
|
|
1420
|
+
mapp.upload_doc("pkg1.zip", content27, "pkg1", "")
|
|
1421
|
+
req = dict(name="pkg1", version="2.6", targetindex="someuser/prod", no_docs=True)
|
|
1422
|
+
testapp.post("/someuser/dev", params=json.dumps(req), code=200)
|
|
1423
|
+
vv = get_view_version_links(testapp, "/someuser/prod", "pkg1", "2.6")
|
|
1424
|
+
(link,) = vv.get_links()
|
|
1425
|
+
assert link.basename == "pkg1-2.6.tgz"
|
|
1426
|
+
assert link.rel == "releasefile"
|
|
1427
|
+
mapp.getjson("/someuser/prod/2.7", code=404)
|
|
1428
|
+
|
|
1429
|
+
|
|
1430
|
+
def test_upload_and_push_no_docs_and_only_docs(mapp, testapp):
|
|
1431
|
+
mapp.create_and_login_user()
|
|
1432
|
+
mapp.create_index("dev")
|
|
1433
|
+
mapp.upload_file_pypi("pkg1-2.6.tgz", b"123", "pkg1", "2.6")
|
|
1434
|
+
content26 = zip_dict({"index.html": "<html><body>2.6</body></html>"})
|
|
1435
|
+
mapp.upload_doc("pkg1.zip", content26, "pkg1", "")
|
|
1436
|
+
req = dict(name="pkg1", version="2.6", targetindex="someuser/prod", no_docs=True, only_docs=True)
|
|
1437
|
+
r = testapp.post("/someuser/dev", params=json.dumps(req), code=400)
|
|
1438
|
+
assert r.json["message"] == "can't use 'no_docs' and 'only_docs' together"
|
|
1439
|
+
|
|
1440
|
+
|
|
1392
1441
|
@proj
|
|
1393
|
-
def test_upload_and_push_internal(mapp, testapp,
|
|
1442
|
+
def test_upload_and_push_internal(mapp, testapp, proj):
|
|
1394
1443
|
mapp.create_user("user1", "1")
|
|
1395
1444
|
mapp.create_and_login_user("user2")
|
|
1396
1445
|
mapp.create_index("prod", indexconfig=dict(acl_upload=["user1", "user2"]))
|
|
@@ -1449,6 +1498,42 @@ def test_upload_and_push_internal(mapp, testapp, monkeypatch, proj):
|
|
|
1449
1498
|
assert link.href.endswith("/pkg1-2.6.tgz")
|
|
1450
1499
|
|
|
1451
1500
|
|
|
1501
|
+
@proj
|
|
1502
|
+
def test_upload_and_push_internal_no_releases_but_docs(mapp, testapp, proj):
|
|
1503
|
+
mapp.create_user("user1", "1")
|
|
1504
|
+
mapp.create_and_login_user("user2")
|
|
1505
|
+
mapp.create_index("prod", indexconfig=dict(acl_upload=["user1", "user2"]))
|
|
1506
|
+
mapp.create_index("dev", indexconfig=dict(acl_upload=["user2"]))
|
|
1507
|
+
|
|
1508
|
+
mapp.login("user1", "1")
|
|
1509
|
+
mapp.create_index("dev")
|
|
1510
|
+
mapp.use("user1/dev")
|
|
1511
|
+
content = zip_dict({"index.html": "<html/>"})
|
|
1512
|
+
mapp.upload_doc("pkg1.zip", content, "pkg1", "2.6")
|
|
1513
|
+
|
|
1514
|
+
# check that push is authorized and executed towards user2/prod index
|
|
1515
|
+
req = dict(name="pkg1", version="2.6", targetindex="user2/prod")
|
|
1516
|
+
r = testapp.push("/user1/dev", json.dumps(req))
|
|
1517
|
+
assert r.status_code == 200
|
|
1518
|
+
vv = get_view_version_links(testapp, "/user2/prod", "pkg1", "2.6",
|
|
1519
|
+
proj=proj)
|
|
1520
|
+
(link,) = vv.get_links()
|
|
1521
|
+
assert link.rel == "doczip"
|
|
1522
|
+
history_log = link.log
|
|
1523
|
+
assert len(history_log) == 2
|
|
1524
|
+
assert history_log[0]['what'] == 'upload'
|
|
1525
|
+
assert history_log[0]['who'] == 'user1'
|
|
1526
|
+
assert history_log[0]['dst'] == 'user1/dev'
|
|
1527
|
+
assert history_log[1]['what'] == 'push'
|
|
1528
|
+
assert history_log[1]['who'] == 'user1'
|
|
1529
|
+
assert history_log[1]['src'] == 'user1/dev'
|
|
1530
|
+
assert history_log[1]['dst'] == 'user2/prod'
|
|
1531
|
+
assert link.href.endswith("/pkg1-2.6.doc.zip")
|
|
1532
|
+
r = testapp.get(link.href)
|
|
1533
|
+
archive = Archive(BytesIO(r.body))
|
|
1534
|
+
assert 'index.html' in archive.namelist()
|
|
1535
|
+
|
|
1536
|
+
|
|
1452
1537
|
def test_acl_toxresults_upload(mapp, testapp, tox_result_data):
|
|
1453
1538
|
mapp.create_and_login_user("user1", "1")
|
|
1454
1539
|
mapp.create_index("prod")
|
|
@@ -33,7 +33,7 @@ def test_upload_and_push_external(mapp, testapp, reqmock):
|
|
|
33
33
|
|
|
34
34
|
# push OK
|
|
35
35
|
req = dict(name="pkg1", version="2.6", posturl="http://whatever.com/",
|
|
36
|
-
username="user", password="password")
|
|
36
|
+
username="user", password="password", register_project=True)
|
|
37
37
|
rec = reqmock.mockresponse(url=None, code=200, method="POST", data="msg")
|
|
38
38
|
body = json.dumps(req).encode("utf-8")
|
|
39
39
|
r = testapp.request(api.index, method="POST", body=body,
|
|
@@ -56,7 +56,7 @@ def test_upload_and_push_external(mapp, testapp, reqmock):
|
|
|
56
56
|
rec = reqmock.mockresponse(url=None, code=410, method="POST", data="msg")
|
|
57
57
|
r = testapp.request(api.index, method="POST", body=body,
|
|
58
58
|
expect_errors=True)
|
|
59
|
-
assert r.status_code ==
|
|
59
|
+
assert r.status_code == 502
|
|
60
60
|
(action_register, action_upload, action_docfile) = r.json["result"]
|
|
61
61
|
assert action_register == [410, 'register', 'pkg1', '2.6']
|
|
62
62
|
assert action_upload == [
|
|
@@ -73,6 +73,41 @@ def test_upload_and_push_external(mapp, testapp, reqmock):
|
|
|
73
73
|
assert result[0][1] == 'register'
|
|
74
74
|
|
|
75
75
|
|
|
76
|
+
def test_upload_and_push_external_no_docs(mapp, testapp, reqmock):
|
|
77
|
+
from devpi_server.filestore import relpath_prefix
|
|
78
|
+
api = mapp.create_and_use()
|
|
79
|
+
content = b"123"
|
|
80
|
+
hashdir = relpath_prefix(content)
|
|
81
|
+
mapp.upload_file_pypi("pkg1-2.6.tgz", content, "pkg1", "2.6")
|
|
82
|
+
zipcontent = zip_dict({"index.html": "<html/>"})
|
|
83
|
+
mapp.upload_doc("pkg1.zip", zipcontent, "pkg1", "")
|
|
84
|
+
req = dict(name="pkg1", version="2.6", posturl="http://whatever.com/",
|
|
85
|
+
username="user", password="password", no_docs=True)
|
|
86
|
+
reqmock.mockresponse(url=None, code=200, method="POST", data="msg")
|
|
87
|
+
body = json.dumps(req).encode()
|
|
88
|
+
r = testapp.request(api.index, method="POST", body=body)
|
|
89
|
+
assert r.status_code == 200
|
|
90
|
+
(action_upload,) = r.json["result"]
|
|
91
|
+
assert action_upload == [
|
|
92
|
+
200, 'upload', f'user1/dev/+f/{hashdir}/pkg1-2.6.tgz', '']
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def test_upload_and_push_external_only_docs(mapp, testapp, reqmock):
|
|
96
|
+
api = mapp.create_and_use()
|
|
97
|
+
content = b"123"
|
|
98
|
+
mapp.upload_file_pypi("pkg1-2.6.tgz", content, "pkg1", "2.6")
|
|
99
|
+
zipcontent = zip_dict({"index.html": "<html/>"})
|
|
100
|
+
mapp.upload_doc("pkg1.zip", zipcontent, "pkg1", "")
|
|
101
|
+
req = dict(name="pkg1", version="2.6", posturl="http://whatever.com/",
|
|
102
|
+
username="user", password="password", only_docs=True)
|
|
103
|
+
reqmock.mockresponse(url=None, code=200, method="POST", data="msg")
|
|
104
|
+
body = json.dumps(req).encode()
|
|
105
|
+
r = testapp.request(api.index, method="POST", body=body)
|
|
106
|
+
assert r.status_code == 200
|
|
107
|
+
(action_docfile,) = r.json["result"]
|
|
108
|
+
assert action_docfile == [200, 'docfile', 'pkg1']
|
|
109
|
+
|
|
110
|
+
|
|
76
111
|
def test_upload_and_push_external_exception(mapp, testapp, reqmock):
|
|
77
112
|
import requests
|
|
78
113
|
api = mapp.create_and_use()
|
|
@@ -89,7 +124,7 @@ def test_upload_and_push_external_exception(mapp, testapp, reqmock):
|
|
|
89
124
|
|
|
90
125
|
# first test should fail during register
|
|
91
126
|
req = dict(name="pkg1", version="2.6", posturl="http://whatever.com/",
|
|
92
|
-
username="user", password="password")
|
|
127
|
+
username="user", password="password", register_project=True)
|
|
93
128
|
body = json.dumps(req).encode("utf-8")
|
|
94
129
|
r = testapp.request(api.index, method="POST", body=body,
|
|
95
130
|
expect_errors=True)
|
|
@@ -106,11 +141,11 @@ def test_upload_and_push_external_exception(mapp, testapp, reqmock):
|
|
|
106
141
|
status=410, preload_content=False,
|
|
107
142
|
reason="Project pre-registration is no longer required or supported, so continue directly to uploading files."))
|
|
108
143
|
req = dict(name="pkg1", version="2.6", posturl="http://whatever.com/",
|
|
109
|
-
username="user", password="password")
|
|
144
|
+
username="user", password="password", register_project=True)
|
|
110
145
|
body = json.dumps(req).encode("utf-8")
|
|
111
146
|
r = testapp.request(api.index, method="POST", body=body,
|
|
112
147
|
expect_errors=True)
|
|
113
|
-
assert r.status_code ==
|
|
148
|
+
assert r.status_code == 502
|
|
114
149
|
assert r.json['type'] == 'actionlog'
|
|
115
150
|
assert len(r.json['result']) == 2
|
|
116
151
|
assert r.json['result'][0][0] == 410
|
|
@@ -132,18 +167,16 @@ def test_upload_and_push_external_metadata12(mapp, reqmock, testapp):
|
|
|
132
167
|
assert verdata['requires_python'] == ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
|
133
168
|
req = dict(name="pkg1", version="2.6", posturl="http://whatever.com/",
|
|
134
169
|
username="user", password="password")
|
|
135
|
-
|
|
170
|
+
rep = reqmock.mockresponse(url=None, code=200, method="POST", data="msg")
|
|
136
171
|
body = json.dumps(req).encode("utf-8")
|
|
137
172
|
r = testapp.request(api.index, method="POST", body=body,
|
|
138
173
|
expect_errors=True)
|
|
139
174
|
assert r.status_code == 200
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
assert rec.requests[i].url == req["posturl"]
|
|
143
|
-
req = rec.requests[1]
|
|
175
|
+
(rec,) = rep.requests
|
|
176
|
+
assert rec.url == req["posturl"]
|
|
144
177
|
fs = cgi_FieldStorage(
|
|
145
|
-
fp=BytesIO(
|
|
146
|
-
headers=
|
|
178
|
+
fp=BytesIO(rec.body),
|
|
179
|
+
headers=rec.headers,
|
|
147
180
|
environ={
|
|
148
181
|
'REQUEST_METHOD': 'POST'})
|
|
149
182
|
assert fs.getvalue('metadata_version') == "2.1"
|
|
@@ -162,18 +195,16 @@ def test_upload_and_push_external_metadata21(mapp, reqmock, testapp):
|
|
|
162
195
|
assert verdata['description_content_type'] == "text/plain"
|
|
163
196
|
req = dict(name="pkg1", version="2.6", posturl="http://whatever.com/",
|
|
164
197
|
username="user", password="password")
|
|
165
|
-
|
|
198
|
+
rep = reqmock.mockresponse(url=None, code=200, method="POST", data="msg")
|
|
166
199
|
body = json.dumps(req).encode("utf-8")
|
|
167
200
|
r = testapp.request(api.index, method="POST", body=body,
|
|
168
201
|
expect_errors=True)
|
|
169
202
|
assert r.status_code == 200
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
assert rec.requests[i].url == req["posturl"]
|
|
173
|
-
req = rec.requests[1]
|
|
203
|
+
(rec,) = rep.requests
|
|
204
|
+
assert rec.url == req["posturl"]
|
|
174
205
|
fs = cgi_FieldStorage(
|
|
175
|
-
fp=BytesIO(
|
|
176
|
-
headers=
|
|
206
|
+
fp=BytesIO(rec.body),
|
|
207
|
+
headers=rec.headers,
|
|
177
208
|
environ={
|
|
178
209
|
'REQUEST_METHOD': 'POST'})
|
|
179
210
|
assert fs.getvalue('metadata_version') == "2.1"
|
|
@@ -221,7 +252,7 @@ def test_upload_and_push_warehouse(mapp, testapp, reqmock):
|
|
|
221
252
|
|
|
222
253
|
# push OK
|
|
223
254
|
req = dict(name="pkg1", version="2.6", posturl="http://whatever.com/",
|
|
224
|
-
username="user", password="password")
|
|
255
|
+
username="user", password="password", register_project=True)
|
|
225
256
|
body = json.dumps(req).encode("utf-8")
|
|
226
257
|
r = testapp.request(api.index, method="POST", body=body,
|
|
227
258
|
expect_errors=True)
|
|
@@ -250,9 +281,8 @@ def test_upload_and_push_egg(mapp, testapp, reqmock):
|
|
|
250
281
|
# push
|
|
251
282
|
req = dict(name="pkg2", version="1.0", posturl="http://whatever.com/",
|
|
252
283
|
username="user", password="password")
|
|
253
|
-
|
|
284
|
+
rep = reqmock.mockresponse(url=None, data=b"msg", code=200)
|
|
254
285
|
r = testapp.push(api.index, json.dumps(req))
|
|
255
286
|
assert r.status_code == 200
|
|
256
|
-
|
|
257
|
-
assert rec.
|
|
258
|
-
assert rec.requests[1].url == req["posturl"]
|
|
287
|
+
(rec,) = rep.requests
|
|
288
|
+
assert rec.url == req["posturl"]
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = '6.13.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.13.0 → devpi-server-6.14.0}/devpi_server/cfg/nginx-devpi-caching-http.conf.template
RENAMED
|
File without changes
|
|
File without changes
|
{devpi-server-6.13.0 → devpi-server-6.14.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
|
|
File without changes
|
{devpi-server-6.13.0 → devpi-server-6.14.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
|
{devpi-server-6.13.0 → devpi-server-6.14.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.13.0 → devpi-server-6.14.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
|