diff options
| author | Nicolas Graves <ngraves@ngraves.fr> | 2025-09-16 19:07:04 +0200 |
|---|---|---|
| committer | Ludovic Courtès <ludo@gnu.org> | 2025-10-01 11:00:35 +0200 |
| commit | f1a3bf940c6ea6784572f7e1e5fdbc82cab21e5d (patch) | |
| tree | eb672323d009e69aae2cf9c447f326b6707e539d /tests/import | |
| parent | 8bf8fed532090a3ae0e61d47b3b024651034a9bb (diff) | |
import: pypi: Move tests to tests/import/pypi.scm
* tests/pypi.scm: Move to tests/import/pypi.scm
* CODEOWNERS: Refresh it.
* Makefile.am: Refresh it.
* etc/teams.scm: Refresh it.
Signed-off-by: Ludovic Courtès <ludo@gnu.org>
Diffstat (limited to 'tests/import')
| -rw-r--r-- | tests/import/pypi.scm | 571 |
1 files changed, 571 insertions, 0 deletions
diff --git a/tests/import/pypi.scm b/tests/import/pypi.scm new file mode 100644 index 00000000000..2f6ec650a2d --- /dev/null +++ b/tests/import/pypi.scm | |||
| @@ -0,0 +1,571 @@ | |||
| 1 | ;;; GNU Guix --- Functional package management for GNU | ||
| 2 | ;;; Copyright © 2014 David Thompson <davet@gnu.org> | ||
| 3 | ;;; Copyright © 2016 Ricardo Wurmus <rekado@elephly.net> | ||
| 4 | ;;; Copyright © 2019 Maxim Cournoyer <maxim@guixotic.coop> | ||
| 5 | ;;; Copyright © 2021 Xinglu Chen <public@yoctocell.xyz> | ||
| 6 | ;;; Copyright © 2022 Vivien Kraus <vivien@planete-kraus.eu> | ||
| 7 | ;;; | ||
| 8 | ;;; This file is part of GNU Guix. | ||
| 9 | ;;; | ||
| 10 | ;;; GNU Guix is free software; you can redistribute it and/or modify it | ||
| 11 | ;;; under the terms of the GNU General Public License as published by | ||
| 12 | ;;; the Free Software Foundation; either version 3 of the License, or (at | ||
| 13 | ;;; your option) any later version. | ||
| 14 | ;;; | ||
| 15 | ;;; GNU Guix is distributed in the hope that it will be useful, but | ||
| 16 | ;;; WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 18 | ;;; GNU General Public License for more details. | ||
| 19 | ;;; | ||
| 20 | ;;; You should have received a copy of the GNU General Public License | ||
| 21 | ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. | ||
| 22 | |||
| 23 | (define-module (test-pypi) | ||
| 24 | #:use-module (guix import pypi) | ||
| 25 | #:use-module (guix base32) | ||
| 26 | #:use-module (guix memoization) | ||
| 27 | #:use-module (guix utils) | ||
| 28 | #:use-module ((guix base16) #:select (base16-string->bytevector)) | ||
| 29 | #:use-module (guix upstream) | ||
| 30 | #:use-module (gcrypt hash) | ||
| 31 | #:use-module (guix tests) | ||
| 32 | #:use-module (guix tests http) | ||
| 33 | #:use-module ((guix download) #:select (url-fetch)) | ||
| 34 | #:use-module (guix build-system python) | ||
| 35 | #:use-module ((guix build utils) | ||
| 36 | #:select (delete-file-recursively | ||
| 37 | which mkdir-p dump-port | ||
| 38 | with-directory-excursion)) | ||
| 39 | #:use-module ((guix diagnostics) #:select (guix-warning-port)) | ||
| 40 | #:use-module ((guix build syscalls) #:select (mkdtemp!)) | ||
| 41 | #:use-module (json) | ||
| 42 | #:use-module (srfi srfi-26) | ||
| 43 | #:use-module (srfi srfi-34) | ||
| 44 | #:use-module (srfi srfi-35) | ||
| 45 | #:use-module (srfi srfi-64) | ||
| 46 | #:use-module (ice-9 match) | ||
| 47 | #:use-module (ice-9 optargs)) | ||
| 48 | |||
| 49 | (define default-sha256 | ||
| 50 | "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") | ||
| 51 | (define default-sha256/base32 | ||
| 52 | (bytevector->nix-base32-string | ||
| 53 | (base16-string->bytevector default-sha256))) | ||
| 54 | |||
| 55 | (define* (foo-json #:key (name "foo") (name-in-url #f)) | ||
| 56 | "Create a JSON description of an example pypi package, named @var{name}, | ||
| 57 | optionally using a different @var{name in its URL}." | ||
| 58 | (scm->json-string | ||
| 59 | `((info | ||
| 60 | . ((version . "1.0.0") | ||
| 61 | (name . ,name) | ||
| 62 | (license . "GNU LGPL") | ||
| 63 | (summary . "summary") | ||
| 64 | (home_page . "http://example.com") | ||
| 65 | (classifiers . #()) | ||
| 66 | (download_url . ""))) | ||
| 67 | (urls . #()) | ||
| 68 | (releases | ||
| 69 | . ((1.0.0 | ||
| 70 | . #(((url . ,(format #f "~a/~a-1.0.0.egg" | ||
| 71 | (%local-url #:path "") | ||
| 72 | (or name-in-url name))) | ||
| 73 | (packagetype . "bdist_egg")) | ||
| 74 | ((url . ,(format #f "~a/~a-1.0.0.tar.gz" | ||
| 75 | (%local-url #:path "") | ||
| 76 | (or name-in-url name))) | ||
| 77 | (packagetype . "sdist") | ||
| 78 | (digests . (("sha256" . ,default-sha256)))) | ||
| 79 | ((url . ,(format #f "~a/~a-1.0.0-py2.py3-none-any.whl" | ||
| 80 | (%local-url #:path "") | ||
| 81 | (or name-in-url name))) | ||
| 82 | (packagetype . "bdist_wheel"))))))))) | ||
| 83 | |||
| 84 | (define test-specifications | ||
| 85 | '("Fizzy [foo, bar]" | ||
| 86 | "PickyThing<1.6,>1.9,!=1.9.6,<2.0a0,==2.4c1" | ||
| 87 | "SomethingWithMarker[foo]>1.0;python_version<\"2.7\"" | ||
| 88 | "requests [security,tests] >= 2.8.1, == 2.8.* ; python_version < \"2.7\"" | ||
| 89 | "pip @ https://github.com/pypa/pip/archive/1.3.1.zip#\ | ||
| 90 | sha1=da9234ee9982d4bbb3c72346a6de940a148ea686")) | ||
| 91 | |||
| 92 | (define test-requires.txt "\ | ||
| 93 | # A comment | ||
| 94 | # A comment after a space | ||
| 95 | foo ~= 3 | ||
| 96 | bar != 2 | ||
| 97 | |||
| 98 | [test] | ||
| 99 | pytest (>=2.5.0) | ||
| 100 | ") | ||
| 101 | |||
| 102 | ;; Beaker contains only optional dependencies. | ||
| 103 | (define test-requires.txt-beaker "\ | ||
| 104 | [crypto] | ||
| 105 | pycryptopp>=0.5.12 | ||
| 106 | |||
| 107 | [cryptography] | ||
| 108 | cryptography | ||
| 109 | |||
| 110 | [testsuite] | ||
| 111 | Mock | ||
| 112 | coverage | ||
| 113 | ") | ||
| 114 | |||
| 115 | (define test-pyproject.toml "\ | ||
| 116 | [build-system] | ||
| 117 | requires = [\"dummy-build-dep-a\", \"dummy-build-dep-b\"] | ||
| 118 | |||
| 119 | [project] | ||
| 120 | dependencies = [ | ||
| 121 | \"dummy-dep-a\", | ||
| 122 | \"dummy-dep-b\", | ||
| 123 | ] | ||
| 124 | |||
| 125 | [project.optional-dependencies] | ||
| 126 | test = [\"dummy-test-dep-a\", \"dummy-test-dep-b\"] | ||
| 127 | ") | ||
| 128 | |||
| 129 | (define test-metadata "\ | ||
| 130 | Classifier: Programming Language :: Python :: 3.7 | ||
| 131 | Requires-Dist: baz ~= 3 | ||
| 132 | Requires-Dist: bar != 2 | ||
| 133 | Provides-Extra: test | ||
| 134 | Requires-Dist: pytest (>=2.5.0) ; extra == 'test' | ||
| 135 | ") | ||
| 136 | |||
| 137 | (define test-metadata-with-extras " | ||
| 138 | Classifier: Programming Language :: Python :: 3.7 | ||
| 139 | Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.* | ||
| 140 | Requires-Dist: wrapt (<2,>=1) | ||
| 141 | Requires-Dist: bar | ||
| 142 | |||
| 143 | Provides-Extra: dev | ||
| 144 | Requires-Dist: tox ; extra == 'dev' | ||
| 145 | Requires-Dist: bumpversion (<1) ; extra == 'dev' | ||
| 146 | ") | ||
| 147 | |||
| 148 | ;;; Provides-Extra can appear before Requires-Dist. | ||
| 149 | (define test-metadata-with-extras-jedi "\ | ||
| 150 | Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.* | ||
| 151 | Provides-Extra: testing | ||
| 152 | Requires-Dist: parso (>=0.3.0) | ||
| 153 | Provides-Extra: testing | ||
| 154 | Requires-Dist: pytest (>=3.1.0); extra == 'testing' | ||
| 155 | ") | ||
| 156 | |||
| 157 | (define sample-directory | ||
| 158 | ;; Directory containing tarballs and .whl files for this test. | ||
| 159 | (let ((template (string-append (or (getenv "TMPDIR") "/tmp") | ||
| 160 | "/guix-pypi-test-XXXXXX"))) | ||
| 161 | (mkdtemp! template))) | ||
| 162 | |||
| 163 | (define (pypi-tarball name specs) | ||
| 164 | "Return a PyPI tarball called NAME suffixed with '.tar.gz' and containing | ||
| 165 | the files specified in SPECS. Return its file name." | ||
| 166 | (let ((directory (in-vicinity sample-directory name)) | ||
| 167 | (tarball (in-vicinity sample-directory (string-append name ".tar.gz")))) | ||
| 168 | (false-if-exception (delete-file tarball)) | ||
| 169 | (mkdir-p directory) | ||
| 170 | (for-each (match-lambda | ||
| 171 | ((file content) | ||
| 172 | (mkdir-p (in-vicinity directory (dirname file))) | ||
| 173 | (call-with-output-file (in-vicinity directory file) | ||
| 174 | (lambda (port) | ||
| 175 | (display content port))))) | ||
| 176 | specs) | ||
| 177 | (parameterize ((current-output-port (%make-void-port "w0"))) | ||
| 178 | (system* "tar" "-C" sample-directory "-czvf" tarball | ||
| 179 | (basename directory))) | ||
| 180 | (delete-file-recursively directory) | ||
| 181 | tarball)) | ||
| 182 | |||
| 183 | (define (wheel-file name specs) | ||
| 184 | "Return a Wheel file called NAME suffixed with '.whl' and containing the | ||
| 185 | files specified by SPECS. Return its file name." | ||
| 186 | (let* ((directory (in-vicinity sample-directory | ||
| 187 | (string-append name ".dist-info"))) | ||
| 188 | (zip-file (in-vicinity sample-directory | ||
| 189 | (string-append name ".zip"))) | ||
| 190 | (whl-file (in-vicinity sample-directory | ||
| 191 | (string-append name ".whl")))) | ||
| 192 | (false-if-exception (delete-file whl-file)) | ||
| 193 | (mkdir-p directory) | ||
| 194 | (for-each (match-lambda | ||
| 195 | ((file content) | ||
| 196 | (mkdir-p (in-vicinity directory (dirname file))) | ||
| 197 | (call-with-output-file (in-vicinity directory file) | ||
| 198 | (lambda (port) | ||
| 199 | (display content port))))) | ||
| 200 | specs) | ||
| 201 | ;; zip always adds a "zip" extension to the file it creates, | ||
| 202 | ;; so we need to rename it. | ||
| 203 | (with-directory-excursion (dirname directory) | ||
| 204 | (system* "zip" "-qr" zip-file (basename directory))) | ||
| 205 | (rename-file zip-file whl-file) | ||
| 206 | (delete-file-recursively directory) | ||
| 207 | whl-file)) | ||
| 208 | |||
| 209 | (define (file-dump file) | ||
| 210 | "Return a procedure that dumps FILE to the given port." | ||
| 211 | (lambda (output) | ||
| 212 | (call-with-input-file file | ||
| 213 | (lambda (input) | ||
| 214 | (dump-port input output))))) | ||
| 215 | |||
| 216 | (define-syntax-rule (with-pypi responses body ...) | ||
| 217 | (with-http-server responses | ||
| 218 | (parameterize ((%pypi-base-url (%local-url #:path "/"))) | ||
| 219 | body ...))) | ||
| 220 | |||
| 221 | |||
| 222 | (test-begin "pypi") | ||
| 223 | |||
| 224 | (test-equal "guix-package->pypi-name, old URL style" | ||
| 225 | "psutil" | ||
| 226 | (guix-package->pypi-name | ||
| 227 | (dummy-package "foo" | ||
| 228 | (source (dummy-origin | ||
| 229 | (uri | ||
| 230 | "https://pypi.org/packages/source/p/psutil/psutil-4.3.0.tar.gz")))))) | ||
| 231 | |||
| 232 | (test-equal "guix-package->pypi-name, new URL style" | ||
| 233 | "certbot" | ||
| 234 | (guix-package->pypi-name | ||
| 235 | (dummy-package "foo" | ||
| 236 | (source (dummy-origin | ||
| 237 | (uri | ||
| 238 | "https://pypi.org/packages/a2/3b/4756e6a0ceb14e084042a2a65c615d68d25621c6fd446d0fc10d14c4ce7d/certbot-0.8.1.tar.gz")))))) | ||
| 239 | |||
| 240 | (test-equal "guix-package->pypi-name, several URLs" | ||
| 241 | "cram" | ||
| 242 | (guix-package->pypi-name | ||
| 243 | (dummy-package "foo" | ||
| 244 | (source | ||
| 245 | (dummy-origin | ||
| 246 | (uri (list "https://bitheap.org/cram/cram-0.7.tar.gz" | ||
| 247 | (pypi-uri "cram" "0.7")))))))) | ||
| 248 | |||
| 249 | (test-equal "guix-package->pypi-name, honor 'upstream-name'" | ||
| 250 | "bar-3" | ||
| 251 | (guix-package->pypi-name | ||
| 252 | (dummy-package "foo" | ||
| 253 | (properties | ||
| 254 | '((upstream-name . "bar-3")))))) | ||
| 255 | |||
| 256 | (test-equal "specification->requirement-name" | ||
| 257 | '("Fizzy" "PickyThing" "SomethingWithMarker" "requests" "pip") | ||
| 258 | (map specification->requirement-name test-specifications)) | ||
| 259 | |||
| 260 | (test-equal "parse-requires.txt" | ||
| 261 | (list '("foo" "bar") '("pytest")) | ||
| 262 | (mock ((ice-9 ports) call-with-input-file | ||
| 263 | call-with-input-string) | ||
| 264 | (parse-requires.txt test-requires.txt))) | ||
| 265 | |||
| 266 | (test-equal "parse-requires.txt - Beaker" | ||
| 267 | (list '() '("Mock" "coverage")) | ||
| 268 | (mock ((ice-9 ports) call-with-input-file | ||
| 269 | call-with-input-string) | ||
| 270 | (parse-requires.txt test-requires.txt-beaker))) | ||
| 271 | |||
| 272 | (test-equal "parse-wheel-metadata, with extras" | ||
| 273 | (list '("wrapt" "bar") '("tox" "bumpversion")) | ||
| 274 | (mock ((ice-9 ports) call-with-input-file | ||
| 275 | call-with-input-string) | ||
| 276 | (parse-wheel-metadata test-metadata-with-extras))) | ||
| 277 | |||
| 278 | (test-equal "parse-wheel-metadata, with extras - Jedi" | ||
| 279 | (list '("parso") '("pytest")) | ||
| 280 | (mock ((ice-9 ports) call-with-input-file | ||
| 281 | call-with-input-string) | ||
| 282 | (parse-wheel-metadata test-metadata-with-extras-jedi))) | ||
| 283 | |||
| 284 | (test-equal "find-project-url, with numpy" | ||
| 285 | "numpy" | ||
| 286 | (find-project-url | ||
| 287 | "numpy" | ||
| 288 | "https://files.pythonhosted.org/packages/0a/c8/a62767a6b374a0dfb02d2a0456e5f56a372cdd1689dbc6ffb6bf1ddedbc0/numpy-1.22.1.zip")) | ||
| 289 | |||
| 290 | (test-equal "find-project-url, uWSGI" | ||
| 291 | "uwsgi" | ||
| 292 | (find-project-url | ||
| 293 | "uWSGI" | ||
| 294 | "https://files.pythonhosted.org/packages/24/fd/93851e4a076719199868d4c918cc93a52742e68370188c1c570a6e42a54f/uwsgi-2.0.20.tar.gz")) | ||
| 295 | |||
| 296 | (test-equal "find-project-url, flake8-array-spacing" | ||
| 297 | "flake8_array_spacing" | ||
| 298 | (find-project-url | ||
| 299 | "flake8-array-spacing" | ||
| 300 | "https://files.pythonhosted.org/packages/a4/21/ff29b901128b681b7de7a2787b3aeb3e1f3cba4a8c0cffa9712cbff016bc/flake8_array_spacing-0.2.0.tar.gz")) | ||
| 301 | |||
| 302 | (test-equal "find-project-url, foo/goo" | ||
| 303 | "foo" | ||
| 304 | (find-project-url | ||
| 305 | "foo" | ||
| 306 | "https://files.pythonhosted.org/packages/f0/f00/goo-0.0.0.tar.gz")) | ||
| 307 | |||
| 308 | (test-assert "pypi->guix-package, no wheel" | ||
| 309 | (let ((tarball (pypi-tarball | ||
| 310 | "foo-1.0.0" | ||
| 311 | `(("src/bizarre.egg-info/requires.txt" | ||
| 312 | ,test-requires.txt)))) | ||
| 313 | (twice (lambda (lst) (append lst lst)))) | ||
| 314 | (with-pypi (twice `(("/foo-1.0.0.tar.gz" 200 ,(file-dump tarball)) | ||
| 315 | ("/foo-1.0.0-py2.py3-none-any.whl" 404 "") | ||
| 316 | ("/foo/json" 200 ,(lambda (port) | ||
| 317 | (display (foo-json) port))))) | ||
| 318 | (match (pypi->guix-package "foo") | ||
| 319 | (`(package | ||
| 320 | (name "python-foo") | ||
| 321 | (version "1.0.0") | ||
| 322 | (source (origin | ||
| 323 | (method url-fetch) | ||
| 324 | (uri (pypi-uri "foo" version)) | ||
| 325 | (sha256 | ||
| 326 | (base32 ,(? string? hash))))) | ||
| 327 | (build-system pyproject-build-system) | ||
| 328 | (propagated-inputs (list python-bar python-foo)) | ||
| 329 | (native-inputs (list python-pytest | ||
| 330 | python-setuptools | ||
| 331 | python-wheel)) | ||
| 332 | (home-page "http://example.com") | ||
| 333 | (synopsis "summary") | ||
| 334 | (description "summary.") | ||
| 335 | (license license:lgpl2.0)) | ||
| 336 | (and (string=? default-sha256/base32 hash) | ||
| 337 | (equal? (pypi->guix-package "foo" #:version "1.0.0") | ||
| 338 | (pypi->guix-package "foo")) | ||
| 339 | (guard (c ((error? c) #t)) | ||
| 340 | (pypi->guix-package "foo" #:version "42")))) | ||
| 341 | (x | ||
| 342 | (pk 'fail x #f)))))) | ||
| 343 | |||
| 344 | (test-assert "pypi->guix-package, no wheel, no requires.txt, but pyproject.toml" | ||
| 345 | (let ((tarball (pypi-tarball | ||
| 346 | "foo-1.0.0" | ||
| 347 | `(("pyproject.toml" ,test-pyproject.toml)))) | ||
| 348 | (twice (lambda (lst) (append lst lst)))) | ||
| 349 | (with-pypi (twice `(("/foo-1.0.0.tar.gz" 200 ,(file-dump tarball)) | ||
| 350 | ("/foo-1.0.0-py2.py3-none-any.whl" 404 "") | ||
| 351 | ("/foo/json" 200 ,(lambda (port) | ||
| 352 | (display (foo-json) port))))) | ||
| 353 | ;; Not clearing the memoization cache here would mean returning the value | ||
| 354 | ;; computed in the previous test. | ||
| 355 | (invalidate-memoization! pypi->guix-package) | ||
| 356 | (match (pypi->guix-package "foo") | ||
| 357 | (`(package | ||
| 358 | (name "python-foo") | ||
| 359 | (version "1.0.0") | ||
| 360 | (source (origin | ||
| 361 | (method url-fetch) | ||
| 362 | (uri (pypi-uri "foo" version)) | ||
| 363 | (sha256 | ||
| 364 | (base32 ,(? string? hash))))) | ||
| 365 | (build-system pyproject-build-system) | ||
| 366 | (propagated-inputs (list python-dummy-dep-a python-dummy-dep-b)) | ||
| 367 | (native-inputs (list python-dummy-build-dep-a python-dummy-build-dep-b | ||
| 368 | python-dummy-test-dep-a python-dummy-test-dep-b)) | ||
| 369 | (home-page "http://example.com") | ||
| 370 | (synopsis "summary") | ||
| 371 | (description "summary.") | ||
| 372 | (license license:lgpl2.0)) | ||
| 373 | (and (string=? default-sha256/base32 hash) | ||
| 374 | (equal? (pypi->guix-package "foo" #:version "1.0.0") | ||
| 375 | (pypi->guix-package "foo")) | ||
| 376 | (guard (c ((error? c) #t)) | ||
| 377 | (pypi->guix-package "foo" #:version "42")))) | ||
| 378 | (x | ||
| 379 | (pk 'fail x #f)))))) | ||
| 380 | |||
| 381 | (test-assert "pypi->guix-package, no wheel, but requires.txt and pyproject.toml" | ||
| 382 | (let ((tarball (pypi-tarball | ||
| 383 | "foo-1.0.0" | ||
| 384 | `(("foo-1.0.0/pyproject.toml" ,test-pyproject.toml) | ||
| 385 | ("foo-1.0.0/bizarre.egg-info/requires.txt" | ||
| 386 | ,test-requires.txt)))) | ||
| 387 | (twice (lambda (lst) (append lst lst)))) | ||
| 388 | (with-pypi (twice `(("/foo-1.0.0.tar.gz" 200 ,(file-dump tarball)) | ||
| 389 | ("/foo-1.0.0-py2.py3-none-any.whl" 404 "") | ||
| 390 | ("/foo/json" 200 ,(lambda (port) | ||
| 391 | (display (foo-json) port))))) | ||
| 392 | ;; Not clearing the memoization cache here would mean returning the value | ||
| 393 | ;; computed in the previous test. | ||
| 394 | (invalidate-memoization! pypi->guix-package) | ||
| 395 | (match (pypi->guix-package "foo") | ||
| 396 | (`(package | ||
| 397 | (name "python-foo") | ||
| 398 | (version "1.0.0") | ||
| 399 | (source (origin | ||
| 400 | (method url-fetch) | ||
| 401 | (uri (pypi-uri "foo" version)) | ||
| 402 | (sha256 | ||
| 403 | (base32 ,(? string? hash))))) | ||
| 404 | (build-system pyproject-build-system) | ||
| 405 | ;; Information from requires.txt and pyproject.toml is combined. | ||
| 406 | (propagated-inputs (list python-bar python-dummy-dep-a python-dummy-dep-b | ||
| 407 | python-foo)) | ||
| 408 | (native-inputs (list python-dummy-build-dep-a python-dummy-build-dep-b | ||
| 409 | python-dummy-test-dep-a python-dummy-test-dep-b | ||
| 410 | python-pytest)) | ||
| 411 | (home-page "http://example.com") | ||
| 412 | (synopsis "summary") | ||
| 413 | (description "summary.") | ||
| 414 | (license license:lgpl2.0)) | ||
| 415 | (and (string=? default-sha256/base32 hash) | ||
| 416 | (equal? (pypi->guix-package "foo" #:version "1.0.0") | ||
| 417 | (pypi->guix-package "foo")) | ||
| 418 | (guard (c ((error? c) #t)) | ||
| 419 | (pypi->guix-package "foo" #:version "42")))) | ||
| 420 | (x | ||
| 421 | (pk 'fail x #f)))))) | ||
| 422 | |||
| 423 | (test-skip (if (which "zip") 0 1)) | ||
| 424 | (test-assert "pypi->guix-package, no requires.txt, but wheel." | ||
| 425 | (let ((tarball (pypi-tarball | ||
| 426 | "foo-1.0.0" | ||
| 427 | '(("foo-1.0.0/foo.egg-info/.empty" "")))) | ||
| 428 | (wheel (wheel-file "foo-1.0.0" | ||
| 429 | `(("METADATA" ,test-metadata))))) | ||
| 430 | (with-pypi `(("/foo-1.0.0.tar.gz" 200 ,(file-dump tarball)) | ||
| 431 | ("/foo-1.0.0-py2.py3-none-any.whl" | ||
| 432 | 200 ,(file-dump wheel)) | ||
| 433 | ("/foo/json" 200 ,(lambda (port) | ||
| 434 | (display (foo-json) port)))) | ||
| 435 | ;; Not clearing the memoization cache here would mean returning the value | ||
| 436 | ;; computed in the previous test. | ||
| 437 | (invalidate-memoization! pypi->guix-package) | ||
| 438 | (match (pypi->guix-package "foo") | ||
| 439 | (`(package | ||
| 440 | (name "python-foo") | ||
| 441 | (version "1.0.0") | ||
| 442 | (source (origin | ||
| 443 | (method url-fetch) | ||
| 444 | (uri (pypi-uri "foo" version)) | ||
| 445 | (sha256 | ||
| 446 | (base32 ,(? string? hash))))) | ||
| 447 | (build-system pyproject-build-system) | ||
| 448 | (propagated-inputs (list python-bar python-baz)) | ||
| 449 | (native-inputs (list python-pytest | ||
| 450 | python-setuptools | ||
| 451 | python-wheel)) | ||
| 452 | (home-page "http://example.com") | ||
| 453 | (synopsis "summary") | ||
| 454 | (description "summary.") | ||
| 455 | (license license:lgpl2.0)) | ||
| 456 | (string=? default-sha256/base32 hash)) | ||
| 457 | (x | ||
| 458 | (pk 'fail x #f)))))) | ||
| 459 | |||
| 460 | (test-assert "pypi->guix-package, no usable requirement file, no wheel." | ||
| 461 | (let ((tarball (pypi-tarball "foo-1.0.0" | ||
| 462 | '(("foo.egg-info/.empty" ""))))) | ||
| 463 | (with-pypi `(("/foo-1.0.0.tar.gz" 200 ,(file-dump tarball)) | ||
| 464 | ("/foo-1.0.0-py2.py3-none-any.whl" 404 "") | ||
| 465 | ("/foo/json" 200 ,(lambda (port) | ||
| 466 | (display (foo-json) port)))) | ||
| 467 | ;; Not clearing the memoization cache here would mean returning the | ||
| 468 | ;; value computed in the previous test. | ||
| 469 | (invalidate-memoization! pypi->guix-package) | ||
| 470 | (match (pypi->guix-package "foo") | ||
| 471 | (`(package | ||
| 472 | (name "python-foo") | ||
| 473 | (version "1.0.0") | ||
| 474 | (source (origin | ||
| 475 | (method url-fetch) | ||
| 476 | (uri (pypi-uri "foo" version)) | ||
| 477 | (sha256 | ||
| 478 | (base32 ,(? string? hash))))) | ||
| 479 | (build-system pyproject-build-system) | ||
| 480 | (native-inputs (list python-setuptools python-wheel)) | ||
| 481 | (home-page "http://example.com") | ||
| 482 | (synopsis "summary") | ||
| 483 | (description "summary.") | ||
| 484 | (license license:lgpl2.0)) | ||
| 485 | (string=? default-sha256/base32 hash)) | ||
| 486 | (x | ||
| 487 | (pk 'fail x #f)))))) | ||
| 488 | |||
| 489 | (test-assert "pypi->guix-package, package name contains \"-\" followed by digits" | ||
| 490 | (let ((tarball (pypi-tarball "foo-99-1.0.0" | ||
| 491 | `(("src/bizarre.egg-info/requires.txt" | ||
| 492 | ,test-requires.txt))))) | ||
| 493 | (with-pypi `(("/foo-99-1.0.0.tar.gz" 200 ,(file-dump tarball)) | ||
| 494 | ("/foo-99-1.0.0-py2.py3-none-any.whl" 404 "") | ||
| 495 | ("/foo-99/json" 200 ,(lambda (port) | ||
| 496 | (display (foo-json #:name "foo-99") | ||
| 497 | port)))) | ||
| 498 | (match (pypi->guix-package "foo-99") | ||
| 499 | (`(package | ||
| 500 | (name "python-foo-99") | ||
| 501 | (version "1.0.0") | ||
| 502 | (source (origin | ||
| 503 | (method url-fetch) | ||
| 504 | (uri (pypi-uri "foo-99" version)) | ||
| 505 | (sha256 | ||
| 506 | (base32 ,(? string? hash))))) | ||
| 507 | (properties (quote (("upstream-name" . "foo-99")))) | ||
| 508 | (build-system pyproject-build-system) | ||
| 509 | (propagated-inputs (list python-bar python-foo)) | ||
| 510 | (native-inputs (list python-pytest | ||
| 511 | python-setuptools | ||
| 512 | python-wheel)) | ||
| 513 | (home-page "http://example.com") | ||
| 514 | (synopsis "summary") | ||
| 515 | (description "summary.") | ||
| 516 | (license license:lgpl2.0)) | ||
| 517 | (string=? default-sha256/base32 hash)) | ||
| 518 | (x | ||
| 519 | (pk 'fail x #f)))))) | ||
| 520 | |||
| 521 | (test-equal "package-latest-release" | ||
| 522 | (list '("foo-1.0.0.tar.gz") | ||
| 523 | '("foo-1.0.0.tar.gz.asc") | ||
| 524 | (list (upstream-input | ||
| 525 | (name "bar") | ||
| 526 | (downstream-name "python-bar") | ||
| 527 | (type 'propagated)) | ||
| 528 | (upstream-input | ||
| 529 | (name "foo") | ||
| 530 | (downstream-name "python-foo") | ||
| 531 | (type 'propagated)) | ||
| 532 | (upstream-input | ||
| 533 | (name "pytest") | ||
| 534 | (downstream-name "python-pytest") | ||
| 535 | (type 'native)) | ||
| 536 | (upstream-input | ||
| 537 | (name "setuptools") | ||
| 538 | (downstream-name "python-setuptools") | ||
| 539 | (type 'native)) | ||
| 540 | (upstream-input | ||
| 541 | (name "wheel") | ||
| 542 | (downstream-name "python-wheel") | ||
| 543 | (type 'native)))) | ||
| 544 | (let ((tarball (pypi-tarball | ||
| 545 | "foo-1.0.0" | ||
| 546 | `(("src/bizarre.egg-info/requires.txt" | ||
| 547 | ,test-requires.txt))))) | ||
| 548 | (with-pypi `(("/foo-1.0.0.tar.gz" 200 ,(file-dump tarball)) | ||
| 549 | ("/foo-1.0.0-py2.py3-none-any.whl" 404 "") | ||
| 550 | ("/foo/json" 200 ,(lambda (port) | ||
| 551 | (display (foo-json) port)))) | ||
| 552 | (define source | ||
| 553 | (package-latest-release | ||
| 554 | (dummy-package "python-foo" | ||
| 555 | (version "0.1.2") | ||
| 556 | (source (dummy-origin | ||
| 557 | (method url-fetch) | ||
| 558 | (uri (pypi-uri "foo" version)))) | ||
| 559 | (build-system python-build-system)) | ||
| 560 | (list %pypi-updater))) | ||
| 561 | |||
| 562 | (list (map basename (upstream-source-urls source)) | ||
| 563 | (map basename (upstream-source-signature-urls source)) | ||
| 564 | (upstream-source-inputs source))))) | ||
| 565 | |||
| 566 | (test-end "pypi") | ||
| 567 | (delete-file-recursively sample-directory) | ||
| 568 | |||
| 569 | ;; Local Variables: | ||
| 570 | ;; eval: (put 'with-pypi 'scheme-indent-function 1) | ||
| 571 | ;; End: | ||
