import: pypi: Updater silently ignores packages without source.

Reported by Andreas Enge <andreas@enge.fr>
at <https://lists.gnu.org/archive/html/guix-devel/2015-11/msg00764.html>.

* guix/import/pypi.scm (&missing-source-error): New error type.
(latest-source-release): Raise it instead of using 'error'.
(pypi->guix-package): Guard against it and use 'leave' to report the
error.
(latest-release): Guard against it and return #f when caught.
master
Ludovic Courtès 2015-12-01 23:15:19 +01:00
parent b6ab89efb2
commit 85dce718cb
1 changed files with 34 additions and 21 deletions

View File

@ -1,6 +1,7 @@
;;; GNU Guix --- Functional package management for GNU ;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2014 David Thompson <davet@gnu.org> ;;; Copyright © 2014 David Thompson <davet@gnu.org>
;;; Copyright © 2015 Cyril Roelandt <tipecaml@gmail.com> ;;; Copyright © 2015 Cyril Roelandt <tipecaml@gmail.com>
;;; Copyright © 2015 Ludovic Courtès <ludo@gnu.org>
;;; ;;;
;;; This file is part of GNU Guix. ;;; This file is part of GNU Guix.
;;; ;;;
@ -25,6 +26,8 @@
#:use-module ((ice-9 rdelim) #:select (read-line)) #:use-module ((ice-9 rdelim) #:select (read-line))
#:use-module (srfi srfi-1) #:use-module (srfi srfi-1)
#:use-module (srfi srfi-26) #:use-module (srfi srfi-26)
#:use-module (srfi srfi-34)
#:use-module (srfi srfi-35)
#:use-module (rnrs bytevectors) #:use-module (rnrs bytevectors)
#:use-module (json) #:use-module (json)
#:use-module (web uri) #:use-module (web uri)
@ -54,6 +57,11 @@ or #f on failure."
(json-fetch (string-append "https://pypi.python.org/pypi/" (json-fetch (string-append "https://pypi.python.org/pypi/"
name "/json"))))))) name "/json")))))))
;; For packages found on PyPI that lack a source distribution.
(define-condition-type &missing-source-error &error
missing-source-error?
(package missing-source-error-package))
(define (latest-source-release pypi-package) (define (latest-source-release pypi-package)
"Return the latest source release for PYPI-PACKAGE." "Return the latest source release for PYPI-PACKAGE."
(let ((releases (assoc-ref* pypi-package "releases" (let ((releases (assoc-ref* pypi-package "releases"
@ -61,9 +69,8 @@ or #f on failure."
(or (find (lambda (release) (or (find (lambda (release)
(string=? "sdist" (assoc-ref release "packagetype"))) (string=? "sdist" (assoc-ref release "packagetype")))
releases) releases)
(error "No source release found for pypi package: " (raise (condition (&missing-source-error
(assoc-ref* pypi-package "info" "name") (package pypi-package)))))))
(assoc-ref* pypi-package "info" "version")))))
(define (python->package-name name) (define (python->package-name name)
"Given the NAME of a package on PyPI, return a Guix-compliant name for the "Given the NAME of a package on PyPI, return a Guix-compliant name for the
@ -203,15 +210,20 @@ VERSION, SOURCE-URL, HOME-PAGE, SYNOPSIS, DESCRIPTION, and LICENSE."
`package' s-expression corresponding to that package, or #f on failure." `package' s-expression corresponding to that package, or #f on failure."
(let ((package (pypi-fetch package-name))) (let ((package (pypi-fetch package-name)))
(and package (and package
(let ((name (assoc-ref* package "info" "name")) (guard (c ((missing-source-error? c)
(version (assoc-ref* package "info" "version")) (let ((package (missing-source-error-package c)))
(release (assoc-ref (latest-source-release package) "url")) (leave (_ "no source release for pypi package ~a ~a~%")
(synopsis (assoc-ref* package "info" "summary")) (assoc-ref* package "info" "name")
(description (assoc-ref* package "info" "summary")) (assoc-ref* package "info" "version")))))
(home-page (assoc-ref* package "info" "home_page")) (let ((name (assoc-ref* package "info" "name"))
(license (string->license (assoc-ref* package "info" "license")))) (version (assoc-ref* package "info" "version"))
(make-pypi-sexp name version release home-page synopsis (release (assoc-ref (latest-source-release package) "url"))
description license))))) (synopsis (assoc-ref* package "info" "summary"))
(description (assoc-ref* package "info" "summary"))
(home-page (assoc-ref* package "info" "home_page"))
(license (string->license (assoc-ref* package "info" "license"))))
(make-pypi-sexp name version release home-page synopsis
description license))))))
(define (pypi-package? package) (define (pypi-package? package)
"Return true if PACKAGE is a Python package from PyPI." "Return true if PACKAGE is a Python package from PyPI."
@ -230,15 +242,16 @@ VERSION, SOURCE-URL, HOME-PAGE, SYNOPSIS, DESCRIPTION, and LICENSE."
(define (latest-release guix-package) (define (latest-release guix-package)
"Return an <upstream-source> for the latest release of GUIX-PACKAGE." "Return an <upstream-source> for the latest release of GUIX-PACKAGE."
(let* ((pypi-name (guix-package->pypi-name (guard (c ((missing-source-error? c) #f))
(specification->package guix-package))) (let* ((pypi-name (guix-package->pypi-name
(metadata (pypi-fetch pypi-name)) (specification->package guix-package)))
(version (assoc-ref* metadata "info" "version")) (metadata (pypi-fetch pypi-name))
(url (assoc-ref (latest-source-release metadata) "url"))) (version (assoc-ref* metadata "info" "version"))
(upstream-source (url (assoc-ref (latest-source-release metadata) "url")))
(package guix-package) (upstream-source
(version version) (package guix-package)
(urls (list url))))) (version version)
(urls (list url))))))
(define %pypi-updater (define %pypi-updater
(upstream-updater (upstream-updater