import: pypi: Allow imports of a specific version.
* guix/import/pypi.scm (latest-version): New procedure. (latest-source-release): Rename to... (source-release): ... this. Add 'version' parameter. (latest-wheel-release): Rename to... (wheel-release): ... this. Add 'version' parameter. (pypi->guix-package): Honor 'version' parameter. (pypi-recursive-import): Add 'version' parameter and honor it. * guix/scripts/import/pypi.scm (guix-import-pypi): Expect a spec. Pass it to 'package-name->name+version'. Pass the 'version' parameter. * tests/pypi.scm ("pypi->guix-package, no wheel"): Exercise the #:version parameter. * doc/guix.texi (Invoking guix import): Document it.master
parent
650dcc18e7
commit
b20cd80ff1
|
@ -11723,13 +11723,19 @@ information, including package dependencies. For maximum efficiency, it
|
||||||
is recommended to install the @command{unzip} utility, so that the
|
is recommended to install the @command{unzip} utility, so that the
|
||||||
importer can unzip Python wheels and gather data from them.
|
importer can unzip Python wheels and gather data from them.
|
||||||
|
|
||||||
The command below imports metadata for the @code{itsdangerous} Python
|
The command below imports metadata for the latest version of the
|
||||||
package:
|
@code{itsdangerous} Python package:
|
||||||
|
|
||||||
@example
|
@example
|
||||||
guix import pypi itsdangerous
|
guix import pypi itsdangerous
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
|
You can also ask for a specific version:
|
||||||
|
|
||||||
|
@example
|
||||||
|
guix import pypi itsdangerous@@1.1.0
|
||||||
|
@end example
|
||||||
|
|
||||||
@table @code
|
@table @code
|
||||||
@item --recursive
|
@item --recursive
|
||||||
@itemx -r
|
@itemx -r
|
||||||
|
|
|
@ -128,27 +128,30 @@
|
||||||
missing-source-error?
|
missing-source-error?
|
||||||
(package missing-source-error-package))
|
(package missing-source-error-package))
|
||||||
|
|
||||||
(define (latest-source-release pypi-package)
|
(define (latest-version project)
|
||||||
"Return the latest source release for PYPI-PACKAGE."
|
"Return the latest version of PROJECT, a <pypi-project> record."
|
||||||
(let ((releases (assoc-ref (pypi-project-releases pypi-package)
|
(project-info-version (pypi-project-info project)))
|
||||||
(project-info-version
|
|
||||||
(pypi-project-info pypi-package)))))
|
(define* (source-release pypi-package
|
||||||
|
#:optional (version (latest-version pypi-package)))
|
||||||
|
"Return the source release of VERSION for PYPI-PACKAGE, a <pypi-project>
|
||||||
|
record, by default the latest version."
|
||||||
|
(let ((releases (or (assoc-ref (pypi-project-releases pypi-package) version)
|
||||||
|
'())))
|
||||||
(or (find (lambda (release)
|
(or (find (lambda (release)
|
||||||
(string=? "sdist" (distribution-package-type release)))
|
(string=? "sdist" (distribution-package-type release)))
|
||||||
releases)
|
releases)
|
||||||
(raise (condition (&missing-source-error
|
(raise (condition (&missing-source-error
|
||||||
(package pypi-package)))))))
|
(package pypi-package)))))))
|
||||||
|
|
||||||
(define (latest-wheel-release pypi-package)
|
(define* (wheel-release pypi-package
|
||||||
|
#:optional (version (latest-version pypi-package)))
|
||||||
"Return the url of the wheel for the latest release of pypi-package,
|
"Return the url of the wheel for the latest release of pypi-package,
|
||||||
or #f if there isn't any."
|
or #f if there isn't any."
|
||||||
(let ((releases (assoc-ref (pypi-project-releases pypi-package)
|
(let ((releases (assoc-ref (pypi-project-releases pypi-package) version)))
|
||||||
(project-info-version
|
(find (lambda (release)
|
||||||
(pypi-project-info pypi-package)))))
|
(string=? "bdist_wheel" (distribution-package-type release)))
|
||||||
(or (find (lambda (release)
|
releases)))
|
||||||
(string=? "bdist_wheel" (distribution-package-type release)))
|
|
||||||
releases)
|
|
||||||
#f)))
|
|
||||||
|
|
||||||
(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
|
||||||
|
@ -484,18 +487,17 @@ VERSION, SOURCE-URL, HOME-PAGE, SYNOPSIS, DESCRIPTION, and LICENSE."
|
||||||
"Fetch the metadata for PACKAGE-NAME from pypi.org, and return the
|
"Fetch the metadata for PACKAGE-NAME from pypi.org, and return the
|
||||||
`package' s-expression corresponding to that package, or #f on failure."
|
`package' s-expression corresponding to that package, or #f on failure."
|
||||||
(let* ((project (pypi-fetch package-name))
|
(let* ((project (pypi-fetch package-name))
|
||||||
(info (and project (pypi-project-info project))))
|
(info (and=> project pypi-project-info))
|
||||||
|
(version (or version (and=> project latest-version))))
|
||||||
(and project
|
(and project
|
||||||
(guard (c ((missing-source-error? c)
|
(guard (c ((missing-source-error? c)
|
||||||
(let ((package (missing-source-error-package c)))
|
(let ((package (missing-source-error-package c)))
|
||||||
(leave (G_ "no source release for pypi package ~a ~a~%")
|
(leave (G_ "no source release for pypi package ~a ~a~%")
|
||||||
(project-info-name info)
|
(project-info-name info) version))))
|
||||||
(project-info-version info)))))
|
(make-pypi-sexp (project-info-name info) version
|
||||||
(make-pypi-sexp (project-info-name info)
|
(and=> (source-release project version)
|
||||||
(project-info-version info)
|
|
||||||
(and=> (latest-source-release project)
|
|
||||||
distribution-url)
|
distribution-url)
|
||||||
(and=> (latest-wheel-release project)
|
(and=> (wheel-release project version)
|
||||||
distribution-url)
|
distribution-url)
|
||||||
(project-info-home-page info)
|
(project-info-home-page info)
|
||||||
(project-info-summary info)
|
(project-info-summary info)
|
||||||
|
@ -503,8 +505,9 @@ VERSION, SOURCE-URL, HOME-PAGE, SYNOPSIS, DESCRIPTION, and LICENSE."
|
||||||
(string->license
|
(string->license
|
||||||
(project-info-license info)))))))))
|
(project-info-license info)))))))))
|
||||||
|
|
||||||
(define (pypi-recursive-import package-name)
|
(define* (pypi-recursive-import package-name #:optional version)
|
||||||
(recursive-import package-name
|
(recursive-import package-name
|
||||||
|
#:version version
|
||||||
#:repo->guix-package pypi->guix-package
|
#:repo->guix-package pypi->guix-package
|
||||||
#:guix-name python->package-name))
|
#:guix-name python->package-name))
|
||||||
|
|
||||||
|
@ -538,7 +541,7 @@ VERSION, SOURCE-URL, HOME-PAGE, SYNOPSIS, DESCRIPTION, and LICENSE."
|
||||||
(let* ((info (pypi-project-info pypi-package))
|
(let* ((info (pypi-project-info pypi-package))
|
||||||
(version (project-info-version info))
|
(version (project-info-version info))
|
||||||
(url (distribution-url
|
(url (distribution-url
|
||||||
(latest-source-release pypi-package))))
|
(source-release pypi-package))))
|
||||||
(upstream-source
|
(upstream-source
|
||||||
(urls (list url))
|
(urls (list url))
|
||||||
(input-changes
|
(input-changes
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#:use-module (srfi srfi-1)
|
#:use-module (srfi srfi-1)
|
||||||
#:use-module (srfi srfi-11)
|
#:use-module (srfi srfi-11)
|
||||||
#:use-module (srfi srfi-37)
|
#:use-module (srfi srfi-37)
|
||||||
|
#:use-module (srfi srfi-71)
|
||||||
#:use-module (ice-9 match)
|
#:use-module (ice-9 match)
|
||||||
#:use-module (ice-9 format)
|
#:use-module (ice-9 format)
|
||||||
#:export (guix-import-pypi))
|
#:export (guix-import-pypi))
|
||||||
|
@ -83,21 +84,22 @@ Import and convert the PyPI package for PACKAGE-NAME.\n"))
|
||||||
(_ #f))
|
(_ #f))
|
||||||
(reverse opts))))
|
(reverse opts))))
|
||||||
(match args
|
(match args
|
||||||
((package-name)
|
((spec)
|
||||||
(if (assoc-ref opts 'recursive)
|
(let ((name version (package-name->name+version spec)))
|
||||||
;; Recursive import
|
(if (assoc-ref opts 'recursive)
|
||||||
(map (match-lambda
|
;; Recursive import
|
||||||
((and ('package ('name name) . rest) pkg)
|
(map (match-lambda
|
||||||
`(define-public ,(string->symbol name)
|
((and ('package ('name name) . rest) pkg)
|
||||||
,pkg))
|
`(define-public ,(string->symbol name)
|
||||||
(_ #f))
|
,pkg))
|
||||||
(pypi-recursive-import package-name))
|
(_ #f))
|
||||||
;; Single import
|
(pypi-recursive-import name version))
|
||||||
(let ((sexp (pypi->guix-package package-name)))
|
;; Single import
|
||||||
(unless sexp
|
(let ((sexp (pypi->guix-package name #:version version)))
|
||||||
(leave (G_ "failed to download meta-data for package '~a'~%")
|
(unless sexp
|
||||||
package-name))
|
(leave (G_ "failed to download meta-data for package '~a'~%")
|
||||||
sexp)))
|
name))
|
||||||
|
sexp))))
|
||||||
(()
|
(()
|
||||||
(leave (G_ "too few arguments~%")))
|
(leave (G_ "too few arguments~%")))
|
||||||
((many ...)
|
((many ...)
|
||||||
|
|
|
@ -260,9 +260,15 @@ Requires-Dist: pytest (>=3.1.0); extra == 'testing'
|
||||||
('synopsis "summary")
|
('synopsis "summary")
|
||||||
('description "summary")
|
('description "summary")
|
||||||
('license 'license:lgpl2.0))
|
('license 'license:lgpl2.0))
|
||||||
(string=? (bytevector->nix-base32-string
|
(and (string=? (bytevector->nix-base32-string
|
||||||
test-source-hash)
|
test-source-hash)
|
||||||
hash))
|
hash)
|
||||||
|
(equal? (pypi->guix-package "foo" #:version "1.0.0")
|
||||||
|
(pypi->guix-package "foo"))
|
||||||
|
(catch 'quit
|
||||||
|
(lambda ()
|
||||||
|
(pypi->guix-package "foo" #:version "42"))
|
||||||
|
(const #t))))
|
||||||
(x
|
(x
|
||||||
(pk 'fail x #f))))))
|
(pk 'fail x #f))))))
|
||||||
|
|
||||||
|
|
Reference in New Issue