1 ;;; GNU Guix --- Functional package management for GNU
2 ;;; Copyright © 2014 David Thompson <davet@gnu.org>
3 ;;; Copyright © 2016 Ricardo Wurmus <rekado@elephly.net>
5 ;;; This file is part of GNU Guix.
7 ;;; GNU Guix is free software; you can redistribute it and/or modify it
8 ;;; under the terms of the GNU General Public License as published by
9 ;;; the Free Software Foundation; either version 3 of the License, or (at
10 ;;; your option) any later version.
12 ;;; GNU Guix is distributed in the hope that it will be useful, but
13 ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ;;; GNU General Public License for more details.
17 ;;; You should have received a copy of the GNU General Public License
18 ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
20 (define-module (test-pypi)
21 #:use-module (guix import pypi)
22 #:use-module (guix base32)
23 #:use-module (gcrypt hash)
24 #:use-module (guix tests)
25 #:use-module (guix build-system python)
26 #:use-module ((guix build utils) #:select (delete-file-recursively which mkdir-p))
27 #:use-module (srfi srfi-64)
28 #:use-module (ice-9 match))
33 \"version\": \"1.0.0\",
35 \"license\": \"GNU LGPL\",
36 \"summary\": \"summary\",
37 \"home_page\": \"http://example.com\",
42 \"url\": \"https://example.com/foo-1.0.0.egg\",
43 \"packagetype\": \"bdist_egg\",
45 \"url\": \"https://example.com/foo-1.0.0.tar.gz\",
46 \"packagetype\": \"sdist\",
48 \"url\": \"https://example.com/foo-1.0.0-py2.py3-none-any.whl\",
49 \"packagetype\": \"bdist_wheel\",
55 (define test-source-hash
58 (define test-specifications
60 "PickyThing<1.6,>1.9,!=1.9.6,<2.0a0,==2.4c1"
61 "SomethingWithMarker[foo]>1.0;python_version<\"2.7\""
62 "requests [security,tests] >= 2.8.1, == 2.8.* ; python_version < \"2.7\""
63 "pip @ https://github.com/pypa/pip/archive/1.3.1.zip#\
64 sha1=da9234ee9982d4bbb3c72346a6de940a148ea686"))
66 (define test-requires.txt "\
68 # A comment after a space
73 (define test-requires-with-sections "\
95 (test-equal "guix-package->pypi-name, old URL style"
97 (guix-package->pypi-name
101 "https://pypi.org/packages/source/p/psutil/psutil-4.3.0.tar.gz"))))))
103 (test-equal "guix-package->pypi-name, new URL style"
105 (guix-package->pypi-name
107 (source (dummy-origin
109 "https://pypi.org/packages/a2/3b/4756e6a0ceb14e084042a2a65c615d68d25621c6fd446d0fc10d14c4ce7d/certbot-0.8.1.tar.gz"))))))
111 (test-equal "guix-package->pypi-name, several URLs"
113 (guix-package->pypi-name
117 (uri (list "https://bitheap.org/cram/cram-0.7.tar.gz"
118 (pypi-uri "cram" "0.7"))))))))
120 (test-equal "specification->requirement-name"
121 '("Fizzy" "PickyThing" "SomethingWithMarker" "requests" "pip")
122 (map specification->requirement-name test-specifications))
124 (test-equal "parse-requires.txt, with sections"
126 (mock ((ice-9 ports) call-with-input-file
127 call-with-input-string)
128 (parse-requires.txt test-requires-with-sections)))
130 (test-assert "pypi->guix-package"
131 ;; Replace network resources with sample data.
132 (mock ((guix import utils) url-fetch
133 (lambda (url file-name)
135 ("https://example.com/foo-1.0.0.tar.gz"
137 (mkdir-p "foo-1.0.0/foo.egg-info/")
138 (with-output-to-file "foo-1.0.0/foo.egg-info/requires.txt"
140 (display test-requires.txt)))
141 (parameterize ((current-output-port (%make-void-port "rw+")))
142 (system* "tar" "czvf" file-name "foo-1.0.0/"))
143 (delete-file-recursively "foo-1.0.0")
144 (set! test-source-hash
145 (call-with-input-file file-name port-sha256))))
146 ("https://example.com/foo-1.0.0-py2.py3-none-any.whl" #f)
147 (_ (error "Unexpected URL: " url)))))
148 (mock ((guix http-client) http-fetch
151 ("https://pypi.org/pypi/foo/json"
152 (values (open-input-string test-json)
153 (string-length test-json)))
154 ("https://example.com/foo-1.0.0-py2.py3-none-any.whl" #f)
155 (_ (error "Unexpected URL: " url)))))
156 (match (pypi->guix-package "foo")
162 ('uri ('pypi-uri "foo" 'version))
166 ('build-system 'python-build-system)
169 (("python-bar" ('unquote 'python-bar))
170 ("python-baz" ('unquote 'python-baz)))))
171 ('home-page "http://example.com")
172 ('synopsis "summary")
173 ('description "summary")
174 ('license 'license:lgpl2.0))
175 (string=? (bytevector->nix-base32-string
181 (test-skip (if (which "zip") 0 1))
182 (test-assert "pypi->guix-package, wheels"
183 ;; Replace network resources with sample data.
184 (mock ((guix import utils) url-fetch
185 (lambda (url file-name)
187 ("https://example.com/foo-1.0.0.tar.gz"
189 (mkdir-p "foo-1.0.0/foo.egg-info/")
190 (with-output-to-file "foo-1.0.0/foo.egg-info/requires.txt"
192 (display test-requires.txt)))
193 (parameterize ((current-output-port (%make-void-port "rw+")))
194 (system* "tar" "czvf" file-name "foo-1.0.0/"))
195 (delete-file-recursively "foo-1.0.0")
196 (set! test-source-hash
197 (call-with-input-file file-name port-sha256))))
198 ("https://example.com/foo-1.0.0-py2.py3-none-any.whl"
200 (mkdir "foo-1.0.0.dist-info")
201 (with-output-to-file "foo-1.0.0.dist-info/metadata.json"
203 (display test-metadata)))
204 (let ((zip-file (string-append file-name ".zip")))
205 ;; zip always adds a "zip" extension to the file it creates,
206 ;; so we need to rename it.
207 (system* "zip" zip-file "foo-1.0.0.dist-info/metadata.json")
208 (rename-file zip-file file-name))
209 (delete-file-recursively "foo-1.0.0.dist-info")))
210 (_ (error "Unexpected URL: " url)))))
211 (mock ((guix http-client) http-fetch
214 ("https://pypi.org/pypi/foo/json"
215 (values (open-input-string test-json)
216 (string-length test-json)))
217 ("https://example.com/foo-1.0.0-py2.py3-none-any.whl" #f)
218 (_ (error "Unexpected URL: " url)))))
219 (match (pypi->guix-package "foo")
225 ('uri ('pypi-uri "foo" 'version))
229 ('build-system 'python-build-system)
232 (("python-bar" ('unquote 'python-bar))
233 ("python-baz" ('unquote 'python-baz)))))
234 ('home-page "http://example.com")
235 ('synopsis "summary")
236 ('description "summary")
237 ('license 'license:lgpl2.0))
238 (string=? (bytevector->nix-base32-string