summary refs log tree commit diff
diff options
context:
space:
mode:
-rwxr-xr-xetc/guix-install.sh2
-rw-r--r--gnu/local.mk1
-rw-r--r--gnu/packages/algebra.scm4
-rw-r--r--gnu/packages/audio.scm4
-rw-r--r--gnu/packages/check.scm3
-rw-r--r--gnu/packages/chromium.scm6
-rw-r--r--gnu/packages/emacs-xyz.scm36
-rw-r--r--gnu/packages/finance.scm8
-rw-r--r--gnu/packages/gtk.scm2
-rw-r--r--gnu/packages/guile-xyz.scm119
-rw-r--r--gnu/packages/guile.scm6
-rw-r--r--gnu/packages/haskell-check.scm44
-rw-r--r--gnu/packages/haskell.scm140
-rw-r--r--gnu/packages/icu4c.scm18
-rw-r--r--gnu/packages/image-viewers.scm26
-rw-r--r--gnu/packages/linux.scm4
-rw-r--r--gnu/packages/lisp.scm39
-rw-r--r--gnu/packages/maths.scm30
-rw-r--r--gnu/packages/package-management.scm21
-rw-r--r--gnu/packages/patches/webkitgtk-sans-gstreamer-gl.patch24
-rw-r--r--gnu/packages/regex.scm4
-rw-r--r--gnu/packages/tls.scm4
-rw-r--r--gnu/packages/upnp.scm4
-rw-r--r--gnu/packages/webkit.scm5
-rw-r--r--gnu/services/databases.scm7
-rw-r--r--guix/build-system/python.scm2
-rw-r--r--guix/derivations.scm4
-rw-r--r--guix/grafts.scm24
-rw-r--r--guix/import/crate.scm4
-rw-r--r--guix/import/pypi.scm397
-rw-r--r--tests/crate.scm2
-rw-r--r--tests/pypi.scm214
32 files changed, 849 insertions, 359 deletions
diff --git a/etc/guix-install.sh b/etc/guix-install.sh
index 604c683202..aa95cb4e20 100755
--- a/etc/guix-install.sh
+++ b/etc/guix-install.sh
@@ -104,7 +104,7 @@ chk_require()
 
     gpg --list-keys ${OPENPGP_SIGNING_KEY_ID} >/dev/null 2>&1 || (
         _err "${ERR}Missing OpenPGP public key.  Fetch it with this command:"
-        echo "  gpg --keyserver pool.sks-keyservers.net --recv-keys ${OPENPGP_SIGNING_KEY_ID}"
+        echo "  wget https://sv.gnu.org/people/viewgpg.php?user_id=15145 -qO - | gpg --import -"
         exit 1
     )
 }
diff --git a/gnu/local.mk b/gnu/local.mk
index 0f4cb2a6e4..6e90d88689 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -1370,7 +1370,6 @@ dist_patch_DATA =						\
   %D%/packages/patches/wavpack-CVE-2018-6767.patch		\
   %D%/packages/patches/wavpack-CVE-2018-7253.patch		\
   %D%/packages/patches/wavpack-CVE-2018-7254.patch		\
-  %D%/packages/patches/webkitgtk-sans-gstreamer-gl.patch	\
   %D%/packages/patches/weechat-python.patch			\
   %D%/packages/patches/wicd-bitrate-none-fix.patch		\
   %D%/packages/patches/wicd-get-selected-profile-fix.patch	\
diff --git a/gnu/packages/algebra.scm b/gnu/packages/algebra.scm
index 95189401f7..7e66e42f0a 100644
--- a/gnu/packages/algebra.scm
+++ b/gnu/packages/algebra.scm
@@ -331,7 +331,7 @@ precision.")
 (define-public giac
   (package
     (name "giac")
-    (version "1.5.0-57")
+    (version "1.5.0-61")
     (source (origin
               (method url-fetch)
               ;; "~parisse/giac" is not used because the maintainer regularly
@@ -343,7 +343,7 @@ precision.")
                                   "source/giac_" version ".tar.gz"))
               (sha256
                (base32
-                "08c93knsisbk9dkyyrignw0wvqbr1sa5czlvk5l307ahxbbmqncf"))))
+                "050vzpqq77fhky32sbisc0ysimgp60xjv39q7y45jkaabdkmclwh"))))
     (build-system gnu-build-system)
     (arguments
      `(#:modules ((ice-9 ftw)
diff --git a/gnu/packages/audio.scm b/gnu/packages/audio.scm
index b8dbc2f00a..eff4edeb59 100644
--- a/gnu/packages/audio.scm
+++ b/gnu/packages/audio.scm
@@ -3701,7 +3701,7 @@ library.")
 (define-public faudio
   (package
     (name "faudio")
-    (version "19.06.07")
+    (version "19.07")
     (source
      (origin
        (method git-fetch)
@@ -3710,7 +3710,7 @@ library.")
              (commit version)))
        (file-name (string-append name "-" version "-checkout"))
        (sha256
-        (base32 "1w37qp279lgpyvslwz3wlb4fp0i68ncd411rqdlk5s71b1zz466n"))))
+        (base32 "1wf6skc5agaikc9qgwk8bx56sad31fafs53lqqn4jmx8i76pl0lw"))))
     (arguments
      '(#:tests? #f                      ; No tests.
        #:configure-flags '("-DFFMPEG=ON")))
diff --git a/gnu/packages/check.scm b/gnu/packages/check.scm
index 36ecad03e2..085538b2de 100644
--- a/gnu/packages/check.scm
+++ b/gnu/packages/check.scm
@@ -1924,7 +1924,8 @@ backported from Python 2.7 for Python 2.4+.")
        ("python-pyhamcrest" ,python-pyhamcrest)
        ("python-pytest" ,python-pytest)))
     (propagated-inputs
-     `(("python-six" ,python-six)
+     `(("python-importlib-metadata" ,python-importlib-metadata)
+       ("python-six" ,python-six)
        ("python-parse" ,python-parse)
        ("python-parse-type" ,python-parse-type)))
     (arguments
diff --git a/gnu/packages/chromium.scm b/gnu/packages/chromium.scm
index e357556956..79828ef589 100644
--- a/gnu/packages/chromium.scm
+++ b/gnu/packages/chromium.scm
@@ -714,7 +714,11 @@ from forcing GEXP-PROMISE."
        ("glib" ,glib)
        ("gtk+" ,gtk+)
        ("harfbuzz" ,harfbuzz)
-       ("icu4c" ,icu4c)
+
+       ;; Build against ICU 64 to prevent a localization problem in version 75
+       ;; and later: <https://github.com/Eloston/ungoogled-chromium/issues/778>.
+       ("icu4c" ,icu4c-64)
+
        ("jsoncpp" ,jsoncpp)
        ("lcms" ,lcms)
        ("libevent" ,libevent)
diff --git a/gnu/packages/emacs-xyz.scm b/gnu/packages/emacs-xyz.scm
index 2a59ae522e..d337700914 100644
--- a/gnu/packages/emacs-xyz.scm
+++ b/gnu/packages/emacs-xyz.scm
@@ -550,7 +550,7 @@ for editing Racket's Scribble documentation syntax in Emacs.")
 (define-public emacs-shroud
   (package
     (name "emacs-shroud")
-    (version "1.15.1")
+    (version "1.83.4")
     (source
      (origin
        (method git-fetch)
@@ -559,7 +559,7 @@ for editing Racket's Scribble documentation syntax in Emacs.")
              (commit version)))
        (file-name (git-file-name name version))
        (sha256
-        (base32 "0wvm4lxqcc1p8v7rpqal3bnqgnpk1gs7v18i83f6cvi5d88jkgdg"))))
+        (base32 "1yvdjx0kp4y8w5yz2cbqq9n6xl5splvmsyyx8ld1xv0q1c9872nf"))))
     (build-system emacs-build-system)
     (propagated-inputs
      `(("emacs-bui" ,emacs-bui)
@@ -16340,3 +16340,35 @@ themselves live in an Org-mode file.  As such, this leverages the power of
 Org-mode (the notes may have outlines, latex fragments, babel, etc...) while
 acting like notes that are made @emph{in} the document.")
     (license license:gpl3+)))
+
+(define-public emacs-multi-term
+  (let ((commit "0804b11e52b960c80f5cd0712ee1e53ae70d83a4"))
+    (package
+      (name "emacs-multi-term")
+      (version "1.2")
+      (source (origin
+                (method git-fetch)
+                (uri (git-reference
+                      (url "https://github.com/manateelazycat/multi-term.git")
+                      (commit commit)))
+                (file-name (git-file-name name version))
+                (sha256
+                 (base32
+                  "0apvidmvb7rv05qjnjhax42ma8wrimik5vxx620dlbv17svz7iyf"))))
+      (build-system emacs-build-system)
+      (inputs `(("zsh" ,zsh)))
+      (home-page "https://github.com/manateelazycat/multi-term")
+      (synopsis "Manage multiple terminal buffers in Emacs")
+      (description
+       "This package enhances @code{term.el} with the following features:
+
+@enumerate
+@item Functions to switch between multiple terminal buffers
+@item List of keys to be intercepted by @code{emacs-multi-term} instead of by
+the underlying terminal
+@item Kills the unused buffer left after exiting the terminal
+@item Kills the running sub-processes along with the terminal when killing the
+it forcibly
+@item Dedicated window for debugging program.
+@end enumerate")
+      (license license:gpl3+))))
diff --git a/gnu/packages/finance.scm b/gnu/packages/finance.scm
index cd5d3b7d9a..03a8285fc1 100644
--- a/gnu/packages/finance.scm
+++ b/gnu/packages/finance.scm
@@ -935,7 +935,7 @@ Luhn and family of ISO/IEC 7064 check digit algorithms. ")
 (define-public python-duniterpy
   (package
     (name "python-duniterpy")
-    (version "0.54.1")
+    (version "0.54.3")
     (source
      (origin
        (method git-fetch)
@@ -946,7 +946,7 @@ Luhn and family of ISO/IEC 7064 check digit algorithms. ")
        (file-name (git-file-name name version))
        (sha256
         (base32
-         "15z5wc3ahvv8axyiqmf7hd4y91ahh1x4bfmgsqxwygyhswl1yjq8"))))
+         "1k3rpfc9zxj9z50cr4zjfyzdla9ap5mj1v1rlcriqmflgb5cmiba"))))
     (build-system python-build-system)
     (arguments
      ;; Tests fail with "AttributeError: module 'attr' has no attribute 's'".
@@ -993,7 +993,7 @@ main features are:
 (define-public silkaj
   (package
     (name "silkaj")
-    (version "0.7.0")
+    (version "0.7.2")
     (source
      (origin
        (method git-fetch)
@@ -1003,7 +1003,7 @@ main features are:
        (file-name (git-file-name name version))
        (sha256
         (base32
-         "0pnd5v15sgxxm114sbs0z24a4dars5hy1nabc9v9ask7kxzrxs9y"))))
+         "059k2kil2l8jcm4wp86w1z7y8p26rww7d3l5fzds0qq2dzvkvzgs"))))
     (build-system python-build-system)
     (arguments
      `(#:tests? #f))                    ;no test
diff --git a/gnu/packages/gtk.scm b/gnu/packages/gtk.scm
index e63e84a7c3..6f37e5e8ca 100644
--- a/gnu/packages/gtk.scm
+++ b/gnu/packages/gtk.scm
@@ -1182,7 +1182,7 @@ extensive documentation, including API reference and a tutorial.")
      ;; In 'Requires' of gtksourceviewmm-3.0.pc.
      `(("glibmm" ,glibmm)
        ("gtkmm" ,gtkmm)
-       ("gtksourceview" ,gtksourceview)))
+       ("gtksourceview" ,gtksourceview-3)))
     (synopsis "C++ interface to the GTK+ 'GtkTextView' widget")
     (description
      "gtksourceviewmm is a portable C++ library that extends the standard GTK+
diff --git a/gnu/packages/guile-xyz.scm b/gnu/packages/guile-xyz.scm
index a8352380f7..f652a94d2e 100644
--- a/gnu/packages/guile-xyz.scm
+++ b/gnu/packages/guile-xyz.scm
@@ -2326,82 +2326,55 @@ more expressive and flexible than the traditional @code{format} procedure.")
       (license license:bsd-3))))
 
 (define-public emacsy
-  (let ((commit "7d49cc1425d5d209bdb82cac0d8ea0694b8b3784")
-        (revision "4"))
-    (package
-      (name "emacsy")
-      (version (string-append "0.1.2-" revision "." (string-take commit 7)))
-      (source (origin
-                (method git-fetch)
-                (uri (git-reference
-                      (url "https://gitlab.com/janneke/emacsy.git")
-                      (commit commit)))
-                (file-name (string-append name "-" version))
-                (sha256
-                 (base32
-                  "0k9yns1v8zn135w60sx96nqs2bm2p2dvcvlm987hkw4lbff9ii6i"))))
-      (build-system gnu-build-system)
-      (native-inputs
-       `(("emacsy-webkit-gtk"
-          ,(origin
-             (method git-fetch)
-             (uri (git-reference
-                   (url "https://gitlab.com/janneke/emacsy-webkit-gtk.git")
-                   (commit "35ded1b3e997fd779a17e0c4a2c73741718562d9")))
-             (file-name (string-append "emacsy-webkit-gtk" "-" version))
-             (sha256
-              (base32
-               "1gp0li2rbp6in926r3hrww6cnh864pp46v1din2pgmd7vzzl7kg0"))))
-         ("hello-emacsy"
-          ,(origin
-             (method git-fetch)
-             (uri (git-reference
-                   (url "https://gitlab.com/janneke/hello-emacsy.git")
-                   (commit "2c117e5286a261be4ff24938f3ae1d348396c538")))
-             (file-name (string-append "hello-emacsy" "-" version))
-             (sha256
-              (base32
-               "15ykd7s8axcy8ym4v71fgal4x28fxnim0pv0jmpi3dnhizr63zqn"))))
-         ("autoconf" ,autoconf)
-         ("automake" ,automake)
-         ("bzip2" ,bzip2)
-         ("guile" ,guile-2.2)
-         ("gettext" ,gnu-gettext)
-         ("libtool" ,libtool)
-         ("noweb" ,noweb)
-         ("perl" ,perl)
-         ("pkg-config" ,pkg-config)
-         ("texinfo" ,texinfo)
-         ("texlive" ,texlive)))
-      (propagated-inputs
-       `(("guile-lib" ,guile-lib)
-         ("guile-readline" ,guile-readline)
-         ("freeglut" ,freeglut)
-         ("gssettings-desktop-schemas" ,gsettings-desktop-schemas)
-         ("webkitgtk" ,webkitgtk)))
-      (inputs `(("guile" ,guile-2.2)))
-      (arguments
-       `(#:phases
-         (modify-phases %standard-phases
-           (add-after 'unpack 'unpack-examples
-             (lambda _
-               (copy-recursively (assoc-ref %build-inputs "emacsy-webkit-gtk")
-                                 "example/emacsy-webkit-gtk")
-               (copy-recursively (assoc-ref %build-inputs "hello-emacsy")
-                                 "example/hello-emacsy")))
-           (add-before 'configure 'setenv
-             (lambda _
-               (setenv "GUILE_AUTO_COMPILE" "0"))))))
-      (home-page "https://github.com/shanecelis/emacsy/")
-      (synopsis "Embeddable GNU Emacs-like library using Guile")
-      (description
-       "Emacsy is an embeddable GNU Emacs-like library that uses GNU Guile
+  (package
+    (name "emacsy")
+    (version "0.4.1")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append
+                    "https://download.savannah.nongnu.org/releases/"
+                    name "/" name "-" version ".tar.gz"))
+              (sha256
+               (base32
+                "1cpb85dl1nibd34c2x2h7vfmjpkgh353p5b1w20v6cs6gmvgg4np"))))
+    (build-system gnu-build-system)
+    (native-inputs
+     `(("autoconf" ,autoconf)
+       ("automake" ,automake)
+       ("bzip2" ,bzip2)
+       ("guile" ,guile-2.2)
+       ("gettext" ,gnu-gettext)
+       ("libtool" ,libtool)
+       ("perl" ,perl)
+       ("pkg-config" ,pkg-config)
+       ("texinfo" ,texinfo)
+       ("texlive" ,texlive)))
+    (propagated-inputs
+     `(("dbus-glib" ,dbus-glib)
+       ("guile" ,guile-2.2)
+       ("guile-lib" ,guile-lib)
+       ("guile-readline" ,guile-readline)
+       ("glib-networking" ,glib-networking)
+       ("freeglut" ,freeglut)
+       ("gssettings-desktop-schemas" ,gsettings-desktop-schemas)
+       ("webkitgtk" ,webkitgtk)))
+    (arguments
+     `(#:phases
+       (modify-phases %standard-phases
+         (add-before 'configure 'setenv
+           (lambda _
+             (setenv "GUILE_AUTO_COMPILE" "0")
+             #t)))))
+    (home-page "https://savannah.nongnu.org/projects/emacsy")
+    (synopsis "Embeddable GNU Emacs-like library using Guile")
+    (description
+     "Emacsy is an embeddable Emacs-like library that uses GNU Guile
 as extension language.  Emacsy can give a C program an Emacsy feel with
 keymaps, minibuffer, recordable macros, history, tab completion, major
 and minor modes, etc., and can also be used as a pure Guile library.  It
-comes with a simple counter example using GLUT and browser examples in C
-using gtk+-3 and webkitgtk.")
-      (license license:gpl3+))))
+comes with a simple counter example using FreeGLUT and browser examples
+in C using Gtk+-3 and WebKitGtk.")
+    (license license:gpl3+)))
 
 (define-public guile-jpeg
   (let ((commit "6a1673578b297c2c1b28e44a76bd5c49e76a5046")
diff --git a/gnu/packages/guile.scm b/gnu/packages/guile.scm
index f0a53e7c39..6e11a13c56 100644
--- a/gnu/packages/guile.scm
+++ b/gnu/packages/guile.scm
@@ -286,17 +286,17 @@ without requiring the source code to be rewritten.")
                   (max-silent-time . 36000))))) ;10 hours (needed on ARM
                                                 ;  when heavily loaded)
 
-(define-public guile-2.2.5
+(define-public guile-2.2.6
   (package
     (inherit guile-2.2)
-    (version "2.2.5")
+    (version "2.2.6")
     (source (origin
               (inherit (package-source guile-2.2))
               (uri (string-append "mirror://gnu/guile/guile-" version
                                   ".tar.xz"))
               (sha256
                (base32
-                "19w5ws1jvs01dpv756qv2cgs37rsnwq1f4f07mj0wra35pqp6c7w"))))))
+                "1269ymxm56j1z1lvq1y42rm961f2n7rinm3k6l00p9k52hrpcddk"))))))
 
 (define-public guile-next
   ;; This is the upcoming Guile 3.0, with JIT support.
diff --git a/gnu/packages/haskell-check.scm b/gnu/packages/haskell-check.scm
index 550bb13a65..9b010fd5eb 100644
--- a/gnu/packages/haskell-check.scm
+++ b/gnu/packages/haskell-check.scm
@@ -822,3 +822,47 @@ minimal dependencies.")
 cryptographic ciphers, and is used by the test runners of various Haskell
 implementations of cryptographic ciphers.")
     (license license:bsd-3)))
+
+(define-public ghc-hedgehog
+  (package
+    (name "ghc-hedgehog")
+    (version "0.6.1")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (string-append
+             "mirror://hackage/package/hedgehog/hedgehog-"
+             version
+             ".tar.gz"))
+       (sha256
+        (base32
+         "0xz10ycdm5vk9nrcym1fi83k19frfwqz18bz8bnpzwvaj0j41yfj"))))
+    (build-system haskell-build-system)
+    (inputs
+     `(("ghc-ansi-terminal" ,ghc-ansi-terminal-0.8)
+       ("ghc-async" ,ghc-async)
+       ("ghc-concurrent-output" ,ghc-concurrent-output)
+       ("ghc-exceptions" ,ghc-exceptions)
+       ("ghc-lifted-async" ,ghc-lifted-async)
+       ("ghc-mmorph" ,ghc-mmorph)
+       ("ghc-monad-control" ,ghc-monad-control)
+       ("ghc-pretty-show" ,ghc-pretty-show)
+       ("ghc-primitive" ,ghc-primitive)
+       ("ghc-random" ,ghc-random)
+       ("ghc-resourcet" ,ghc-resourcet)
+       ("ghc-semigroups" ,ghc-semigroups)
+       ("ghc-stm" ,ghc-stm)
+       ("ghc-th-lift" ,ghc-th-lift)
+       ("ghc-transformers-base" ,ghc-transformers-base)
+       ("ghc-wl-pprint-annotated"
+        ,ghc-wl-pprint-annotated)))
+    (home-page "https://hedgehog.qa")
+    (synopsis "Property-based testing in the spirt of QuickCheck")
+    (description
+     "Hedgehog is a property-based testing system, in the spirit of
+QuickCheck.  Hedgehog uses integrated shrinking, so shrinks obey the invariants
+of generated values by construction.
+
+To get started quickly, see the examples:
+@uref{https://github.com/hedgehogqa/haskell-hedgehog/tree/master/hedgehog-example}")
+    (license license:bsd-3)))
diff --git a/gnu/packages/haskell.scm b/gnu/packages/haskell.scm
index 52f688a283..17fddc1965 100644
--- a/gnu/packages/haskell.scm
+++ b/gnu/packages/haskell.scm
@@ -18,6 +18,7 @@
 ;;; Copyright © 2018 Arun Isaac <arunisaac@systemreboot.net>
 ;;; Copyright © 2018, 2019 Gabriel Hondet <gabrielhondet@gmail.com>
 ;;; Copyright © 2019 Robert Vollmert <rob@vllmrt.net>
+;;; Copyright © 2019 Jacob MacDonald <jaccarmac@gmail.com>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -4085,7 +4086,7 @@ instances of the @code{Pretty} class.")
          "0gnb4mkqryv08vncxnj0bzwcnd749613yw3cxfzw6y3nsldp4c56"))))
     (build-system haskell-build-system)
     (inputs
-     `(("ghc-ansi-terminal" ,ghc-ansi-terminal)))
+     `(("ghc-ansi-terminal" ,ghc-ansi-terminal-0.8)))
     (home-page "https://github.com/ekmett/ansi-wl-pprint")
     (synopsis "Wadler/Leijen Pretty Printer for colored ANSI terminal output")
     (description "This is a pretty printing library based on Wadler's paper
@@ -4362,7 +4363,7 @@ interface.")
 (define-public ghc-ansi-terminal
   (package
     (name "ghc-ansi-terminal")
-    (version "0.8.0.4")
+    (version "0.9.1")
     (source
      (origin
        (method url-fetch)
@@ -4372,7 +4373,7 @@ interface.")
              ".tar.gz"))
        (sha256
         (base32
-         "0428gq8m3fdnb7ldcsyk97qcch76hcxbgh2666p6f76fs2qbhg7b"))))
+         "1yr0ld0kqns3w3j9gl62bdwshvyazidx4dv1qkvq19ivnf08w23l"))))
     (build-system haskell-build-system)
     (inputs
      `(("ghc-colour" ,ghc-colour)))
@@ -4383,6 +4384,21 @@ allows cursor movement, screen clearing, color output showing or hiding the
 cursor, and changing the title.")
     (license license:bsd-3)))
 
+(define-public ghc-ansi-terminal-0.8
+  (package (inherit ghc-ansi-terminal)
+           (name "ghc-ansi-terminal")
+           (version "0.8.0.4")
+           (source
+            (origin
+              (method url-fetch)
+              (uri (string-append
+                    "https://hackage.haskell.org/package/ansi-terminal/ansi-terminal-"
+                    version
+                    ".tar.gz"))
+              (sha256
+               (base32
+                "0428gq8m3fdnb7ldcsyk97qcch76hcxbgh2666p6f76fs2qbhg7b"))))))
+
 (define-public ghc-vault
   (package
     (name "ghc-vault")
@@ -11591,4 +11607,122 @@ Replace some ASCII sequences by their Unicode equivalent (turned off by
 default)
 @end itemize")
     (license license:bsd-3)))
+
+(define-public ghc-validation
+  (package
+    (name "ghc-validation")
+    (version "1.1")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (string-append
+             "mirror://hackage/package/validation/validation-"
+             version
+             ".tar.gz"))
+       (sha256
+        (base32
+         "1acj7mh3581ks405xswxw6667z7y1y0slisg6jvp6chc191ji9l5"))))
+    (build-system haskell-build-system)
+    (arguments
+     `(#:phases
+       (modify-phases %standard-phases
+         (add-after 'unpack 'add-setup-script
+           (lambda _
+             ;; The usual "Setup.hs" script is missing from the source.
+             (with-output-to-file "Setup.hs"
+               (lambda ()
+                 (format #t "import Distribution.Simple~%")
+                 (format #t "main = defaultMain~%"))))))))
+    (inputs
+     `(("ghc-semigroups" ,ghc-semigroups)
+       ("ghc-semigroupoids" ,ghc-semigroupoids)
+       ("ghc-bifunctors" ,ghc-bifunctors)
+       ("ghc-lens" ,ghc-lens)))
+    (native-inputs
+     `(("ghc-hedgehog" ,ghc-hedgehog)
+       ("ghc-hunit" ,ghc-hunit)))
+    (home-page "https://github.com/qfpl/validation")
+    (synopsis
+     "Data-type like Either but with an accumulating Applicative")
+    (description
+     "A data-type like Either but with differing properties and type-class
+instances.
+
+Library support is provided for this different representation, including
+@code{lens}-related functions for converting between each and abstracting over
+their similarities.
+
+The @code{Validation} data type is isomorphic to @code{Either}, but has an
+instance of @code{Applicative} that accumulates on the error side.  That is to
+say, if two (or more) errors are encountered, they are appended using a
+@{Semigroup} operation.
+
+As a consequence of this @code{Applicative} instance, there is no
+corresponding @code{Bind} or @code{Monad} instance.  @code{Validation} is an
+example of, \"An applicative functor that is not a monad.\"")
+    (license license:bsd-3)))
+
+(define-public ghc-concurrent-output
+  (package
+    (name "ghc-concurrent-output")
+    (version "1.10.10")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (string-append
+             "mirror://hackage/package/concurrent-output/concurrent-output-"
+             version
+             ".tar.gz"))
+       (sha256
+        (base32
+         "1wnjxnwbc3l853kiiijagzjyb6fmhz3lmkwls24plbximl1qrr22"))))
+    (build-system haskell-build-system)
+    (inputs
+     `(("ghc-async" ,ghc-async)
+       ("ghc-stm" ,ghc-stm)
+       ("ghc-exceptions" ,ghc-exceptions)
+       ("ghc-ansi-terminal" ,ghc-ansi-terminal)
+       ("ghc-terminal-size" ,ghc-terminal-size)))
+    (home-page
+     "https://hackage.haskell.org/package/concurrent-output")
+    (synopsis
+     "Ungarble output from several threads or commands")
+    (description
+     "Lets multiple threads and external processes concurrently output to the
+console, without it getting all garbled up.
+
+Built on top of that is a way of defining multiple output regions, which are
+automatically laid out on the screen and can be individually updated by
+concurrent threads.  Can be used for progress displays etc.")
+    (license license:bsd-2)))
+
+(define-public ghc-wl-pprint-annotated
+  (package
+    (name "ghc-wl-pprint-annotated")
+    (version "0.1.0.1")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (string-append
+             "mirror://hackage/package/wl-pprint-annotated/wl-pprint-annotated-"
+             version
+             ".tar.gz"))
+       (sha256
+        (base32
+         "1br7qyf27iza213inwhf9bm2k6in0zbmfw6w4clqlc9f9cj2nrkb"))))
+    (build-system haskell-build-system)
+    (native-inputs
+     `(("ghc-tasty" ,ghc-tasty)
+       ("ghc-tasty-hunit" ,ghc-tasty-hunit)))
+    (home-page
+     "https://github.com/minad/wl-pprint-annotated#readme")
+    (synopsis
+     "Wadler/Leijen pretty printer with annotation support")
+    (description
+     "Annotations are useful for coloring.  This is a limited version of
+@code{wl-pprint-extras} without support for point effects and without the free
+monad.  Like in @code{annotated-wl-pprint}, only annotations are supported.
+Compared to @code{annotated-wl-pprint} this library provides a slightly
+modernized interface.")
+    (license license:bsd-3)))
 ;;; haskell.scm ends here
diff --git a/gnu/packages/icu4c.scm b/gnu/packages/icu4c.scm
index 6e93d6aed9..512967a305 100644
--- a/gnu/packages/icu4c.scm
+++ b/gnu/packages/icu4c.scm
@@ -4,6 +4,7 @@
 ;;; Copyright © 2016, 2017 Efraim Flashner <efraim@flashner.co.il>
 ;;; Copyright © 2017 Clément Lassieur <clement@lassieur.org>
 ;;; Copyright © 2017 Ricardo Wurmus <rekado@elephly.net>
+;;; Copyright © 2019 Marius Bakke <mbakke@fastmail.com>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -23,6 +24,7 @@
 (define-module (gnu packages icu4c)
   #:use-module (gnu packages)
   #:use-module (gnu packages perl)
+  #:use-module (gnu packages python)
   #:use-module (guix licenses)
   #:use-module (guix packages)
   #:use-module (guix download)
@@ -81,6 +83,22 @@ C/C++ part.")
    (license x11)
    (home-page "http://site.icu-project.org/")))
 
+(define-public icu4c-64
+  (package
+    (inherit icu4c)
+    (version "64.2")
+    (source (origin
+              (inherit (package-source icu4c))
+              (uri (string-append
+                    "http://download.icu-project.org/files/icu4c/" version "/icu4c-"
+                    (string-map (lambda (x) (if (char=? x #\.) #\_ x)) version)
+                    "-src.tgz"))
+              (sha256
+               (base32 "0v0xsf14xwlj125y9fd8lrhsaych4d8liv8gr746zng6g225szb2"))))
+    (native-inputs
+     `(;; For tests.
+       ("python" ,python)))))
+
 (define-public java-icu4j
   (package
     (name "java-icu4j")
diff --git a/gnu/packages/image-viewers.scm b/gnu/packages/image-viewers.scm
index a5bfb28a88..7d2ff9a677 100644
--- a/gnu/packages/image-viewers.scm
+++ b/gnu/packages/image-viewers.scm
@@ -10,6 +10,7 @@
 ;;; Copyright © 2018, 2019 Tobias Geerinckx-Rice <me@tobias.gr>
 ;;; Copyright © 2018, 2019 Ricardo Wurmus <rekado@elephly.net>
 ;;; Copyright © 2019 Nicolas Goaziou <mail@nicolasgoaziou.fr>
+;;; Copyright © 2019 Guy Fleury Iteriteka <hoonandon@gmail.com>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -477,3 +478,28 @@ minimalism and usability in mind.  Its features include animated GIF
 controls, file history, rotation/mirroring, and multithreaded
 preloading.")
     (license license:gpl3+)))
+
+(define-public chafa
+  (package
+    (name "chafa")
+    (version "1.0.1")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "https://hpjansson.org/chafa/releases/chafa-"
+                                  version ".tar.xz"))
+              (sha256
+               (base32
+                "00cf2z52az0z6bzc3hfm4l8infipy5ck410wqmbaybd2csjr3m29"))))
+    (build-system gnu-build-system)
+    (native-inputs
+     `(("pkg-config" ,pkg-config)))
+    (inputs
+     `(("glib" ,glib)
+       ("imagemagick" ,imagemagick)))
+    (synopsis "Convert images to ANSI/Unicode characters")
+    (description
+     "Chafa is a command-line utility that converts all kinds of images,
+including animated GIFs, into ANSI/Unicode character output that can be
+displayed in a terminal.")
+    (home-page "https://hpjansson.org/chafa/")
+    (license license:lgpl3+)))
diff --git a/gnu/packages/linux.scm b/gnu/packages/linux.scm
index 72b62faf42..b4407a5133 100644
--- a/gnu/packages/linux.scm
+++ b/gnu/packages/linux.scm
@@ -3544,7 +3544,7 @@ and copy/paste text in the console and in xterm.")
 (define-public btrfs-progs
   (package
     (name "btrfs-progs")
-    (version "5.1")
+    (version "5.1.1")
     (source (origin
               (method url-fetch)
               (uri (string-append "mirror://kernel.org/linux/kernel/"
@@ -3552,7 +3552,7 @@ and copy/paste text in the console and in xterm.")
                                   "btrfs-progs-v" version ".tar.xz"))
               (sha256
                (base32
-                "0dgh56pamav8wb9nmabjwdlpcazvqc9pgzwablxn77mqh0qrhkaq"))))
+                "06xybs7rglxjqkbzl2409acb3rgmnc5zc0xhyaxsc2p1x5yipfcw"))))
     (build-system gnu-build-system)
     (outputs '("out"
                "static"))      ; static versions of the binaries in "out"
diff --git a/gnu/packages/lisp.scm b/gnu/packages/lisp.scm
index 58813c2d84..37e375d356 100644
--- a/gnu/packages/lisp.scm
+++ b/gnu/packages/lisp.scm
@@ -5665,6 +5665,45 @@ basic everyday functions and macros.")
 (define-public ecl-fare-utils
   (sbcl-package->ecl-package sbcl-fare-utils))
 
+(define-public sbcl-trivial-utf-8
+  (let ((commit "4d427cfbb1c452436a0efb71c3205c9da67f718f")
+        (revision "1"))
+    (package
+      (name "sbcl-trivial-utf-8")
+      (version (git-version "0.0.0" revision commit))
+      (source
+       (origin
+         (method git-fetch)
+         (uri
+          (git-reference
+           (url (string-append "https://gitlab.common-lisp.net/"
+                               "trivial-utf-8/trivial-utf-8.git"))
+           (commit commit)))
+         (file-name (git-file-name name version))
+         (sha256
+          (base32
+           "1jz27gz8gvqdmvp3k9bxschs6d5b3qgk94qp2bj6nv1d0jc3m1l1"))))
+      (arguments
+       ;; Guix incorrectly assumes the "8" is part of the version
+       ;; number and lobs it off.
+       `(#:asd-file "trivial-utf-8.asd"
+         #:asd-system-name "trivial-utf-8"))
+      (build-system asdf-build-system/sbcl)
+      (synopsis "UTF-8 input/output library")
+      (description
+       "The Babel library solves a similar problem while understanding more
+encodings.  Trivial UTF-8 was written before Babel existed, but for new
+projects you might be better off going with Babel.  The one plus that Trivial
+UTF-8 has is that it doesn't depend on any other libraries.")
+      (home-page "https://common-lisp.net/project/trivial-utf-8/")
+      (license license:bsd-3))))
+
+(define-public cl-trivial-utf-8
+  (sbcl-package->cl-source-package sbcl-trivial-utf-8))
+
+(define-public ecl-trivial-utf-8
+  (sbcl-package->ecl-package sbcl-trivial-utf-8))
+
 (define-public sbcl-idna
   (package
     (name "sbcl-idna")
diff --git a/gnu/packages/maths.scm b/gnu/packages/maths.scm
index 5b31596041..7d2c4797f1 100644
--- a/gnu/packages/maths.scm
+++ b/gnu/packages/maths.scm
@@ -1463,30 +1463,30 @@ can solve two kinds of problems:
         "11wwxpy2q1bhxs2v41bqn05i2sb0905cj1xil6mg8l4k2kka4cq6"))))
     (build-system gnu-build-system)
     (inputs
-     `(("lapack" ,lapack)
-       ("qhull" ,qhull)
-       ("readline" ,readline)
-       ("gl2ps" ,gl2ps)
-       ("glpk" ,glpk)
+     `(("alsa-lib" ,alsa-lib)
+       ("arpack" ,arpack-ng)
+       ("curl" ,curl)
        ("fftw" ,fftw)
        ("fftwf" ,fftwf)
-       ("arpack" ,arpack-ng)
-       ("pcre" ,pcre)
        ("fltk" ,fltk)
        ("fontconfig" ,fontconfig)
        ("freetype" ,freetype)
-       ("hdf5" ,hdf5)
-       ("libxft" ,libxft)
-       ("mesa" ,mesa)
+       ("gl2ps" ,gl2ps)
+       ("glpk" ,glpk)
        ("glu" ,glu)
-       ("zlib" ,zlib)
-       ("curl" ,curl)
-       ("texinfo" ,texinfo)
        ("graphicsmagick" ,graphicsmagick)
-       ("suitesparse" ,suitesparse)
+       ("hdf5" ,hdf5)
+       ("lapack" ,lapack)
        ("libsndfile" ,libsndfile)
+       ("libxft" ,libxft)
+       ("mesa" ,mesa)
+       ("pcre" ,pcre)
        ("portaudio" ,portaudio)
-       ("alsa-lib" ,alsa-lib)))
+       ("qhull" ,qhull)
+       ("readline" ,readline)
+       ("suitesparse" ,suitesparse)
+       ("texinfo" ,texinfo)
+       ("zlib" ,zlib)))
     (native-inputs
      `(("lzip" ,lzip)
        ("gfortran" ,gfortran)
diff --git a/gnu/packages/package-management.scm b/gnu/packages/package-management.scm
index ca360b3884..d0388e5d43 100644
--- a/gnu/packages/package-management.scm
+++ b/gnu/packages/package-management.scm
@@ -475,17 +475,28 @@ sub-directory.")
                (base32
                 "0h8qr2rxsrkg6d8jxjk68r23jgn1dxdxyp4bnzzinpa8sjhfl905"))))
     (build-system gnu-build-system)
+    (arguments
+     '(#:phases
+       (modify-phases %standard-phases
+         (add-after 'install 'wrap-stow
+           (lambda* (#:key inputs outputs #:allow-other-keys)
+             (let ((out (assoc-ref outputs "out")))
+               (wrap-program (string-append out "/bin/stow")
+                 `("PERL5LIB" ":" prefix
+                   ,(map (lambda (i) (string-append (assoc-ref inputs i)
+                                                    "/lib/perl5/site_perl"))
+                         '("perl-clone-choose" "perl-clone" "perl-hash-merge"))))
+               #t))))))
     (inputs
-     `(("perl" ,perl)))
+     `(("perl" ,perl)
+       ("perl-clone" ,perl-clone)
+       ("perl-clone-choose" ,perl-clone-choose)
+       ("perl-hash-merge" ,perl-hash-merge)))
     (native-inputs
      `(("perl-test-simple" ,perl-test-simple)
        ("perl-test-output" ,perl-test-output)
        ("perl-capture-tiny" ,perl-capture-tiny)
        ("perl-io-stringy" ,perl-io-stringy)))
-    (propagated-inputs
-     `(("perl-clone-choose" ,perl-clone-choose)
-       ("perl-clone" ,perl-clone)
-       ("perl-hash-merge" ,perl-hash-merge)))
     (home-page "https://www.gnu.org/software/stow/")
     (synopsis "Managing installed software packages")
     (description
diff --git a/gnu/packages/patches/webkitgtk-sans-gstreamer-gl.patch b/gnu/packages/patches/webkitgtk-sans-gstreamer-gl.patch
deleted file mode 100644
index 4577c81edb..0000000000
--- a/gnu/packages/patches/webkitgtk-sans-gstreamer-gl.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-Fix build failure when USE_GSTREAMER_GL=off.  See
-<https://bugs.webkit.org/show_bug.cgi?id=196440>.
-
-This patch is taken from the upstream source repository:
-<https://git.webkit.org/?p=WebKit.git;a=commitdiff;h=e2dd6decbe25ea9498f1ba213808f34b232740c7>.
-
-diff --git a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp
-index 00a2af6489e..5cb5f7536ac 100644
---- a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp
-+++ b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp
-@@ -1000,11 +1000,13 @@ void MediaPlayerPrivateGStreamerBase::updateTextureMapperFlags()
-         break;
-     }
- 
-+#if USE(GSTREAMER_GL)
-     // When the imxvpudecoder is used, the texture sampling of the
-     // directviv-uploaded texture returns an RGB value, so there's no need to
-     // convert it.
-     if (m_videoDecoderPlatform != WebKitGstVideoDecoderPlatform::ImxVPU)
-         m_textureMapperFlags |= TEXTURE_MAPPER_COLOR_CONVERT_FLAG;
-+#endif
- }
- #endif
- 
diff --git a/gnu/packages/regex.scm b/gnu/packages/regex.scm
index a64944080b..71dac09737 100644
--- a/gnu/packages/regex.scm
+++ b/gnu/packages/regex.scm
@@ -30,7 +30,7 @@
 (define-public re2
    (package
      (name "re2")
-     (version "2019-06-01")
+     (version "2019-07-01")
      (home-page "https://github.com/google/re2")
      (source (origin
                (method git-fetch)
@@ -38,7 +38,7 @@
                (file-name (git-file-name name version))
                (sha256
                 (base32
-                 "01613z66wgiffdngbq3031rwd92jf87j93h7y5mn8hlx19gg5k4j"))))
+                 "1ric6gdnf5mqj5iy5f81al49mr3mmjqj3nqi3mw2hjdbbgwkdn71"))))
      (build-system gnu-build-system)
      (arguments
       `(#:modules ((guix build gnu-build-system)
diff --git a/gnu/packages/tls.scm b/gnu/packages/tls.scm
index 53f5ccb26f..da2bfd5cad 100644
--- a/gnu/packages/tls.scm
+++ b/gnu/packages/tls.scm
@@ -834,7 +834,7 @@ then ported to the GNU / Linux environment.")
 (define-public mbedtls-apache
   (package
     (name "mbedtls-apache")
-    (version "2.16.1")
+    (version "2.16.2")
     (source
      (origin
        (method url-fetch)
@@ -844,7 +844,7 @@ then ported to the GNU / Linux environment.")
                            version "-apache.tgz"))
        (sha256
         (base32
-         "08zz88gcb2jmpfsgy5b6qc3li6l39yw1dbimd18aziyd889nvl7b"))))
+         "1906hbwlkq32075hca4vjad03dcc36aycvmaz8yvhr3ygg6lz0x6"))))
     (build-system cmake-build-system)
     (arguments
      `(#:configure-flags
diff --git a/gnu/packages/upnp.scm b/gnu/packages/upnp.scm
index 3f3d80f576..a085fe9747 100644
--- a/gnu/packages/upnp.scm
+++ b/gnu/packages/upnp.scm
@@ -32,14 +32,14 @@
 (define-public miniupnpc
   (package
     (name "miniupnpc")
-    (version "2.1.20190408")
+    (version "2.1.20190625")
     (source
      (origin
        (method url-fetch)
        (uri (string-append "https://miniupnp.tuxfamily.org/files/"
                            name "-" version ".tar.gz"))
        (sha256
-        (base32 "1v0l2m8j7r6jiy871d6v11ls243xqn6s3856iwd3bmk5c37npi50"))))
+        (base32 "1yqp0d8x5ldjfma5x2vhpg1aaafdg0470ismccixww3rzpbza8w7"))))
     (build-system gnu-build-system)
     (native-inputs
      `(("python" ,python-2)))
diff --git a/gnu/packages/webkit.scm b/gnu/packages/webkit.scm
index e9b7ab74a7..6b38998772 100644
--- a/gnu/packages/webkit.scm
+++ b/gnu/packages/webkit.scm
@@ -168,15 +168,14 @@ HTML/CSS applications to full-fledged web browsers.")
 (define-public webkitgtk-2.24
   (package/inherit webkitgtk
     (name "webkitgtk")
-    (version "2.24.2")
+    (version "2.24.3")
     (source (origin
               (method url-fetch)
               (uri (string-append "https://www.webkitgtk.org/releases/"
                                   name "-" version ".tar.xz"))
               (sha256
                (base32
-                "071jnjvjq6wsxx1jh4ql3j53h1nhphs5ga67fa5i9xjvs3qb3701"))
-              (patches (search-patches "webkitgtk-sans-gstreamer-gl.patch"))))
+                "0lbcrw5axwrbrajxq7fqywfyh0djqi23ynzb5wi5ghw2grnp83cl"))))
     (native-inputs
      `(("gcc" ,gcc-7)  ; webkitgtk-2.22 requires gcc-6 or newer
        ,@(package-native-inputs webkitgtk)))
diff --git a/gnu/services/databases.scm b/gnu/services/databases.scm
index 7113f1f2a1..ec31489d48 100644
--- a/gnu/services/databases.scm
+++ b/gnu/services/databases.scm
@@ -5,6 +5,7 @@
 ;;; Copyright © 2017 Christopher Baines <mail@cbaines.net>
 ;;; Copyright © 2018 Clément Lassieur <clement@lassieur.org>
 ;;; Copyright © 2018 Julien Lepiller <julien@lepiller.eu>
+;;; Copyright © 2019 Robert Vollmert <rob@vllmrt.net>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -91,9 +92,9 @@
 (define %default-postgres-hba
   (plain-file "pg_hba.conf"
               "
-local	all	all			trust
-host	all	all	127.0.0.1/32 	trust
-host	all	all	::1/128 	trust"))
+local	all	all			peer
+host	all	all	127.0.0.1/32 	md5
+host	all	all	::1/128 	md5"))
 
 (define %default-postgres-ident
   (plain-file "pg_ident.conf"
diff --git a/guix/build-system/python.scm b/guix/build-system/python.scm
index b753940bad..e39c06528e 100644
--- a/guix/build-system/python.scm
+++ b/guix/build-system/python.scm
@@ -50,7 +50,7 @@
   "Return a URI string for the Python package hosted on the Python Package
 Index (PyPI) corresponding to NAME and VERSION.  EXTENSION is the file name
 extension, such as '.tar.gz'."
-  (string-append "https://pypi.org/packages/source/"
+  (string-append "https://files.pythonhosted.org/packages/source/"
                  (string-take name 1) "/" name "/"
                  name "-" version extension))
 
diff --git a/guix/derivations.scm b/guix/derivations.scm
index 433b4551a5..ebeac31877 100644
--- a/guix/derivations.scm
+++ b/guix/derivations.scm
@@ -1011,8 +1011,8 @@ recursively."
 
 (define* (build-derivations store derivations
                             #:optional (mode (build-mode normal)))
-  "Build DERIVATIONS, a list of <derivation> objects, .drv file names, or
-derivation/output pairs, using the specified MODE."
+  "Build DERIVATIONS, a list of <derivation> or <derivation-input> objects,
+.drv file names, or derivation/output pairs, using the specified MODE."
   (build-things store (map (match-lambda
                             ((? derivation? drv)
                              (derivation-file-name drv))
diff --git a/guix/grafts.scm b/guix/grafts.scm
index 3b43e11425..adc7bfafae 100644
--- a/guix/grafts.scm
+++ b/guix/grafts.scm
@@ -163,16 +163,11 @@ references.  Call REFERENCES to get the list of references."
                  items))))
     (remove (cut member <> self) refs)))
 
-(define (references-oracle store drv)
-  "Return a one-argument procedure that, when passed the file name of DRV's
-outputs or their dependencies, returns the list of references of that item.
-Use either local info or substitute info; build DRV if no information is
-available."
-  (define (output-paths drv)
-    (match (derivation->output-paths drv)
-      (((names . items) ...)
-       items)))
-
+(define (references-oracle store input)
+  "Return a one-argument procedure that, when passed the output file names of
+INPUT, a derivation input, or their dependencies, returns the list of
+references of that item.  Use either local info or substitute info; build
+INPUT if no information is available."
   (define (references* items)
     (guard (c ((store-protocol-error? c)
                ;; As a last resort, build DRV and query the references of the
@@ -181,13 +176,14 @@ available."
                ;; Warm up the narinfo cache, otherwise each derivation build
                ;; will result in one HTTP request to get one narinfo, which is
                ;; much less efficient than fetching them all upfront.
-               (substitution-oracle store (list drv))
+               (substitution-oracle store
+                                    (list (derivation-input-derivation input)))
 
-               (and (build-derivations store (list drv))
+               (and (build-derivations store (list input))
                     (map (cut references store <>) items))))
       (references/substitutes store items)))
 
-  (let loop ((items (output-paths drv))
+  (let loop ((items (derivation-input-output-paths input))
              (result vlist-null))
     (match items
       (()
@@ -324,7 +320,7 @@ DRV, and graft DRV itself to refer to those grafted dependencies."
   ;; upfront to have as much parallelism as possible when querying substitute
   ;; info or when building DRV.
   (define references
-    (references-oracle store drv))
+    (references-oracle store (derivation-input drv outputs)))
 
   (match (run-with-state
              (cumulative-grafts store drv grafts references
diff --git a/guix/import/crate.scm b/guix/import/crate.scm
index 9a73d9fe16..29318aac0e 100644
--- a/guix/import/crate.scm
+++ b/guix/import/crate.scm
@@ -85,14 +85,14 @@
     (()
      '())
     ((package-inputs ...)
-     `((#:cargo-inputs ,package-inputs)))))
+     `(#:cargo-inputs ,package-inputs))))
 
 (define (maybe-cargo-development-inputs package-names)
   (match (package-names->package-inputs package-names)
     (()
      '())
     ((package-inputs ...)
-     `((#:cargo-development-inputs ,package-inputs)))))
+     `(#:cargo-development-inputs ,package-inputs))))
 
 (define (maybe-arguments arguments)
   (match arguments
diff --git a/guix/import/pypi.scm b/guix/import/pypi.scm
index 3a20fc4b9b..ab7a024ee0 100644
--- a/guix/import/pypi.scm
+++ b/guix/import/pypi.scm
@@ -4,6 +4,7 @@
 ;;; Copyright © 2015, 2016, 2017 Ludovic Courtès <ludo@gnu.org>
 ;;; Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com>
 ;;; Copyright © 2018 Ricardo Wurmus <rekado@elephly.net>
+;;; Copyright © 2019 Maxim Cournoyer <maxim.cournoyer@gmail.com>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -21,25 +22,22 @@
 ;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.
 
 (define-module (guix import pypi)
-  #:use-module (ice-9 binary-ports)
   #:use-module (ice-9 match)
-  #:use-module (ice-9 pretty-print)
   #:use-module (ice-9 regex)
   #:use-module (ice-9 receive)
   #:use-module ((ice-9 rdelim) #:select (read-line))
   #:use-module (srfi srfi-1)
+  #:use-module (srfi srfi-11)
   #:use-module (srfi srfi-26)
   #:use-module (srfi srfi-34)
   #:use-module (srfi srfi-35)
-  #:use-module (rnrs bytevectors)
-  #:use-module (json)
-  #:use-module (web uri)
   #:use-module (guix ui)
   #:use-module (guix utils)
   #:use-module ((guix build utils)
                 #:select ((package-name->name+version
                            . hyphen-package-name->name+version)
-                          find-files))
+                          find-files
+                          invoke))
   #:use-module (guix import utils)
   #:use-module ((guix download) #:prefix download:)
   #:use-module (guix import json)
@@ -47,7 +45,10 @@
   #:use-module (guix upstream)
   #:use-module ((guix licenses) #:prefix license:)
   #:use-module (guix build-system python)
-  #:export (guix-package->pypi-name
+  #:export (parse-requires.txt
+            parse-wheel-metadata
+            specification->requirement-name
+            guix-package->pypi-name
             pypi-recursive-import
             pypi->guix-package
             %pypi-updater))
@@ -108,86 +109,180 @@ package on PyPI."
     ((name version _ ...)
      (string-append name "-" version ".dist-info"))))
 
-(define (maybe-inputs package-inputs)
+(define (maybe-inputs package-inputs input-type)
   "Given a list of PACKAGE-INPUTS, tries to generate the 'inputs' field of a
-package definition."
+package definition.  INPUT-TYPE, a symbol, is used to populate the name of
+the input field."
   (match package-inputs
     (()
      '())
     ((package-inputs ...)
-     `((propagated-inputs (,'quasiquote ,package-inputs))))))
+     `((,input-type (,'quasiquote ,package-inputs))))))
 
-(define (guess-requirements source-url wheel-url tarball)
-  "Given SOURCE-URL, WHEEL-URL and a TARBALL of the package, return a list
-of the required packages specified in the requirements.txt file.  TARBALL will
-be extracted in a temporary directory."
+(define %requirement-name-regexp
+  ;; Regexp to match the requirement name in a requirement specification.
 
-  (define (tarball-directory url)
-    ;; Given the URL of the package's tarball, return the name of the directory
-    ;; that will be created upon decompressing it. If the filetype is not
-    ;; supported, return #f.
-    ;; TODO: Support more archive formats.
-    (let ((basename (substring url (+ 1 (string-rindex url #\/)))))
-      (cond
-       ((string-suffix? ".tar.gz" basename)
-        (string-drop-right basename 7))
-       ((string-suffix? ".tar.bz2" basename)
-        (string-drop-right basename 8))
-       (else
-        (begin
-          (warning (G_ "Unsupported archive format: \
-cannot determine package dependencies"))
-          #f)))))
-
-  (define (clean-requirement s)
-    ;; Given a requirement LINE, as can be found in a Python requirements.txt
-    ;; file, remove everything other than the actual name of the required
-    ;; package, and return it.
-    (string-take s
-      (or (string-index s (lambda (chr) (member chr '(#\space #\> #\= #\<))))
-          (string-length s))))
+  ;; Some grammar, taken from PEP-0508 (see:
+  ;; https://www.python.org/dev/peps/pep-0508/).
+
+  ;; Using this grammar makes the PEP-0508 regexp easier to understand for
+  ;; humans.  The use of a regexp is preferred to more primitive string
+  ;; manipulations because we can more directly match what upstream uses
+  ;; (again, per PEP-0508).  The regexp approach is also easier to extend,
+  ;; should we want to implement more completely the grammar of PEP-0508.
+
+  ;; The unified rule can be expressed as:
+  ;; specification = wsp* ( url_req | name_req ) wsp*
+
+  ;; where url_req is:
+  ;; url_req = name wsp* extras? wsp* urlspec wsp+ quoted_marker?
+
+  ;; and where name_req is:
+  ;; name_req = name wsp* extras? wsp* versionspec? wsp* quoted_marker?
+
+  ;; Thus, we need only matching NAME, which is expressed as:
+  ;; identifer_end = letterOrDigit | (('-' | '_' | '.' )* letterOrDigit)
+  ;; identifier    = letterOrDigit identifier_end*
+  ;; name          = identifier
+  (let* ((letter-or-digit "[A-Za-z0-9]")
+         (identifier-end (string-append "(" letter-or-digit "|"
+                                        "[-_.]*" letter-or-digit ")"))
+         (identifier (string-append "^" letter-or-digit identifier-end "*"))
+         (name identifier))
+    (make-regexp name)))
+
+(define (specification->requirement-name spec)
+  "Given a specification SPEC, return the requirement name."
+  (match:substring
+   (or (regexp-exec %requirement-name-regexp spec)
+       (error (G_ "Could not extract requirement name in spec:") spec))))
+
+(define (test-section? name)
+  "Return #t if the section name contains 'test' or 'dev'."
+  (any (cut string-contains-ci name <>)
+       '("test" "dev")))
+
+(define (parse-requires.txt requires.txt)
+  "Given REQUIRES.TXT, a Setuptools requires.txt file, return a list of lists
+of requirements.
+
+The first list contains the required dependencies while the second the
+optional test dependencies.  Note that currently, optional, non-test
+dependencies are omitted since these can be difficult or expensive to
+satisfy."
 
   (define (comment? line)
     ;; Return #t if the given LINE is a comment, #f otherwise.
-    (eq? (string-ref (string-trim line) 0) #\#))
-
-  (define (read-requirements requirements-file)
-    ;; Given REQUIREMENTS-FILE, a Python requirements.txt file, return a list
-    ;; of name/variable pairs describing the requirements.
-    (call-with-input-file requirements-file
-      (lambda (port)
-        (let loop ((result '()))
-          (let ((line (read-line port)))
-            (if (eof-object? line)
-                result
-                (cond
-                 ((or (string-null? line) (comment? line))
-                  (loop result))
-                 (else
-                  (loop (cons (clean-requirement line)
-                              result))))))))))
+    (string-prefix? "#" (string-trim line)))
+
+  (define (section-header? line)
+    ;; Return #t if the given LINE is a section header, #f otherwise.
+    (string-prefix? "[" (string-trim line)))
+
+  (call-with-input-file requires.txt
+    (lambda (port)
+      (let loop ((required-deps '())
+                 (test-deps '())
+                 (inside-test-section? #f)
+                 (optional? #f))
+        (let ((line (read-line port)))
+          (cond
+           ((eof-object? line)
+            ;; Duplicates can occur, since the same requirement can be
+            ;; listed multiple times with different conditional markers, e.g.
+            ;; pytest >= 3 ; python_version >= "3.3"
+            ;; pytest < 3 ; python_version < "3.3"
+            (map (compose reverse delete-duplicates)
+                 (list required-deps test-deps)))
+           ((or (string-null? line) (comment? line))
+            (loop required-deps test-deps inside-test-section? optional?))
+           ((section-header? line)
+            ;; Encountering a section means that all the requirements
+            ;; listed below are optional. Since we want to pick only the
+            ;; test dependencies from the optional dependencies, we must
+            ;; track those separately.
+            (loop required-deps test-deps (test-section? line) #t))
+           (inside-test-section?
+            (loop required-deps
+                  (cons (specification->requirement-name line)
+                        test-deps)
+                  inside-test-section? optional?))
+           ((not optional?)
+            (loop (cons (specification->requirement-name line)
+                        required-deps)
+                  test-deps inside-test-section? optional?))
+           (optional?
+            ;; Skip optional items.
+            (loop required-deps test-deps inside-test-section? optional?))
+           (else
+            (warning (G_ "parse-requires.txt reached an unexpected \
+condition on line ~a~%") line))))))))
+
+(define (parse-wheel-metadata metadata)
+  "Given METADATA, a Wheel metadata file, return a list of lists of
+requirements.
+
+Refer to the documentation of PARSE-REQUIRES.TXT for a description of the
+returned value."
+  ;; METADATA is a RFC-2822-like, header based file.
+
+  (define (requires-dist-header? line)
+    ;; Return #t if the given LINE is a Requires-Dist header.
+    (string-match "^Requires-Dist: " line))
+
+  (define (requires-dist-value line)
+    (string-drop line (string-length "Requires-Dist: ")))
+
+  (define (extra? line)
+    ;; Return #t if the given LINE is an "extra" requirement.
+    (string-match "extra == '(.*)'" line))
+
+  (define (test-requirement? line)
+    (and=> (match:substring (extra? line) 1) test-section?))
+
+  (call-with-input-file metadata
+    (lambda (port)
+      (let loop ((required-deps '())
+                 (test-deps '()))
+        (let ((line (read-line port)))
+          (cond
+           ((eof-object? line)
+            (map (compose reverse delete-duplicates)
+                 (list required-deps test-deps)))
+           ((and (requires-dist-header? line) (not (extra? line)))
+            (loop (cons (specification->requirement-name
+                         (requires-dist-value line))
+                        required-deps)
+                  test-deps))
+           ((and (requires-dist-header? line) (test-requirement? line))
+            (loop required-deps
+                  (cons (specification->requirement-name (requires-dist-value line))
+                        test-deps)))
+           (else
+            (loop required-deps test-deps)))))))) ;skip line
+
+(define (guess-requirements source-url wheel-url archive)
+  "Given SOURCE-URL, WHEEL-URL and an ARCHIVE of the package, return a list
+of the required packages specified in the requirements.txt file.  ARCHIVE will
+be extracted in a temporary directory."
 
   (define (read-wheel-metadata wheel-archive)
     ;; Given WHEEL-ARCHIVE, a ZIP Python wheel archive, return the package's
-    ;; requirements.
+    ;; requirements, or #f if the metadata file contained therein couldn't be
+    ;; extracted.
     (let* ((dirname (wheel-url->extracted-directory wheel-url))
-           (json-file (string-append dirname "/metadata.json")))
-      (and (zero? (system* "unzip" "-q" wheel-archive json-file))
-           (dynamic-wind
-             (const #t)
-             (lambda ()
-               (call-with-input-file json-file
-                 (lambda (port)
-                   (let* ((metadata (json->scm port))
-                          (run_requires (hash-ref metadata "run_requires"))
-                          (requirements (if run_requires
-                                            (hash-ref (list-ref run_requires 0)
-                                                       "requires")
-                                            '())))
-                     (map clean-requirement requirements)))))
-             (lambda ()
-               (delete-file json-file)
-               (rmdir dirname))))))
+           (metadata (string-append dirname "/METADATA")))
+      (call-with-temporary-directory
+       (lambda (dir)
+         (if (zero?
+              (parameterize ((current-error-port (%make-void-port "rw+"))
+                             (current-output-port (%make-void-port "rw+")))
+                (system* "unzip" wheel-archive "-d" dir metadata)))
+             (parse-wheel-metadata (string-append dir "/" metadata))
+             (begin
+               (warning
+                (G_ "Failed to extract file: ~a from wheel.~%") metadata)
+               #f))))))
 
   (define (guess-requirements-from-wheel)
     ;; Return the package's requirements using the wheel, or #f if an error
@@ -195,63 +290,68 @@ cannot determine package dependencies"))
     (call-with-temporary-output-file
      (lambda (temp port)
        (if wheel-url
-         (and (url-fetch wheel-url temp)
-              (read-wheel-metadata temp))
-         #f))))
+           (and (url-fetch wheel-url temp)
+                (read-wheel-metadata temp))
+           #f))))
 
   (define (guess-requirements-from-source)
     ;; Return the package's requirements by guessing them from the source.
-    (let ((dirname (tarball-directory source-url)))
-      (if (string? dirname)
-          (call-with-temporary-directory
-           (lambda (dir)
-             (let* ((pypi-name (string-take dirname (string-rindex dirname #\-)))
-                    (req-files (list (string-append dirname "/requirements.txt")
-                                     (string-append dirname "/" pypi-name ".egg-info"
-                                                    "/requires.txt")))
-                    (exit-codes (map (lambda (file-name)
-                                       (parameterize ((current-error-port (%make-void-port "rw+"))
-                                                      (current-output-port (%make-void-port "rw+")))
-                                         (system* "tar" "xf" tarball "-C" dir file-name)))
-                                     req-files)))
-               ;; Only one of these files needs to exist.
-               (if (any zero? exit-codes)
-                   (match (find-files dir)
-                     ((file . _)
-                      (read-requirements file))
-                     (()
-                      (warning (G_ "No requirements file found.\n"))))
-                   (begin
-                     (warning (G_ "Failed to extract requirements files\n"))
-                     '())))))
-          '())))
-
-  ;; First, try to compute the requirements using the wheel, since that is the
-  ;; most reliable option. If a wheel is not provided for this package, try
-  ;; getting them by reading either the "requirements.txt" file or the
-  ;; "requires.txt" from the egg-info directory from the source tarball. Note
-  ;; that "requirements.txt" is not mandatory, so this is likely to fail.
+    (if (compressed-file? source-url)
+        (call-with-temporary-directory
+         (lambda (dir)
+           (parameterize ((current-error-port (%make-void-port "rw+"))
+                          (current-output-port (%make-void-port "rw+")))
+             (if (string=? "zip" (file-extension source-url))
+                 (invoke "unzip" archive "-d" dir)
+                 (invoke "tar" "xf" archive "-C" dir)))
+           (let ((requires.txt-files
+                  (find-files dir (lambda (abs-file-name _)
+		                    (string-match "\\.egg-info/requires.txt$"
+                                                  abs-file-name)))))
+             (match requires.txt-files
+               (()
+                (warning (G_ "Cannot guess requirements from source archive:\
+ no requires.txt file found.~%"))
+                (list '() '()))
+               (else (parse-requires.txt (first requires.txt-files)))))))
+        (begin
+          (warning (G_ "Unsupported archive format; \
+cannot determine package dependencies from source archive: ~a~%")
+                   (basename source-url))
+          (list '() '()))))
+
+  ;; First, try to compute the requirements using the wheel, else, fallback to
+  ;; reading the "requires.txt" from the egg-info directory from the source
+  ;; archive.
   (or (guess-requirements-from-wheel)
       (guess-requirements-from-source)))
 
-
-(define (compute-inputs source-url wheel-url tarball)
-  "Given the SOURCE-URL of an already downloaded TARBALL, return a list of
-name/variable pairs describing the required inputs of this package.  Also
+(define (compute-inputs source-url wheel-url archive)
+  "Given the SOURCE-URL and WHEEL-URL of an already downloaded ARCHIVE, return
+a pair of lists, each consisting of a list of name/variable pairs, for the
+propagated inputs and the native inputs, respectively.  Also
 return the unaltered list of upstream dependency names."
-  (let ((dependencies
-         (remove (cut string=? "argparse" <>)
-                 (guess-requirements source-url wheel-url tarball))))
-    (values (sort
-             (map (lambda (input)
-                    (let ((guix-name (python->package-name input)))
-                      (list guix-name (list 'unquote (string->symbol guix-name)))))
-                  dependencies)
-             (lambda args
-               (match args
-                 (((a _ ...) (b _ ...))
-                  (string-ci<? a b)))))
-            dependencies)))
+
+  (define (strip-argparse deps)
+    (remove (cut string=? "argparse" <>) deps))
+
+  (define (requirement->package-name/sort deps)
+    (sort
+     (map (lambda (input)
+            (let ((guix-name (python->package-name input)))
+              (list guix-name (list 'unquote (string->symbol guix-name)))))
+          deps)
+     (lambda args
+       (match args
+         (((a _ ...) (b _ ...))
+          (string-ci<? a b))))))
+
+  (define process-requirements
+    (compose requirement->package-name/sort strip-argparse))
+
+  (let ((dependencies (guess-requirements source-url wheel-url archive)))
+    (values (map process-requirements dependencies)
+            (concatenate dependencies))))
 
 (define (make-pypi-sexp name version source-url wheel-url home-page synopsis
                         description license)
@@ -260,29 +360,36 @@ VERSION, SOURCE-URL, HOME-PAGE, SYNOPSIS, DESCRIPTION, and LICENSE."
   (call-with-temporary-output-file
    (lambda (temp port)
      (and (url-fetch source-url temp)
-          (receive (input-package-names upstream-dependency-names)
+          (receive (guix-dependencies upstream-dependencies)
               (compute-inputs source-url wheel-url temp)
-            (values
-             `(package
-                (name ,(python->package-name name))
-                (version ,version)
-                (source (origin
-                          (method url-fetch)
-
-                          ;; Sometimes 'pypi-uri' doesn't quite work due to mixed
-                          ;; cases in NAME, for instance, as is the case with
-                          ;; "uwsgi".  In that case, fall back to a full URL.
-                          (uri (pypi-uri ,(string-downcase name) version))
-                          (sha256
-                           (base32
-                            ,(guix-hash-url temp)))))
-                (build-system python-build-system)
-                ,@(maybe-inputs input-package-names)
-                (home-page ,home-page)
-                (synopsis ,synopsis)
-                (description ,description)
-                (license ,(license->symbol license)))
-             upstream-dependency-names))))))
+            (match guix-dependencies
+              ((required-inputs test-inputs)
+               (values
+                `(package
+                   (name ,(python->package-name name))
+                   (version ,version)
+                   (source
+                    (origin
+                      (method url-fetch)
+                      ;; PyPI URL are case sensitive, but sometimes a project
+                      ;; named using mixed case has a URL using lower case, so
+                      ;; we must work around this inconsistency.  For actual
+                      ;; examples, compare the URLs of the "Deprecated" and
+                      ;; "uWSGI" PyPI packages.
+                      (uri ,(if (string-contains source-url name)
+                                `(pypi-uri ,name version)
+                                `(pypi-uri ,(string-downcase name) version)))
+                      (sha256
+                       (base32
+                        ,(guix-hash-url temp)))))
+                   (build-system python-build-system)
+                   ,@(maybe-inputs required-inputs 'propagated-inputs)
+                   ,@(maybe-inputs test-inputs 'native-inputs)
+                   (home-page ,home-page)
+                   (synopsis ,synopsis)
+                   (description ,description)
+                   (license ,(license->symbol license)))
+                upstream-dependencies))))))))
 
 (define pypi->guix-package
   (memoize
diff --git a/tests/crate.scm b/tests/crate.scm
index a4a328d507..72c3a13350 100644
--- a/tests/crate.scm
+++ b/tests/crate.scm
@@ -91,7 +91,7 @@
          ('build-system 'cargo-build-system)
          ('arguments
           ('quasiquote
-           (('#:cargo-inputs (("rust-bar" ('unquote rust-bar)))))))
+           ('#:cargo-inputs (("rust-bar" ('unquote rust-bar))))))
          ('home-page "http://example.com")
          ('synopsis "summary")
          ('description "summary")
diff --git a/tests/pypi.scm b/tests/pypi.scm
index 6daa44a6e7..43d45f1dd8 100644
--- a/tests/pypi.scm
+++ b/tests/pypi.scm
@@ -1,6 +1,7 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2014 David Thompson <davet@gnu.org>
 ;;; Copyright © 2016 Ricardo Wurmus <rekado@elephly.net>
+;;; Copyright © 2019 Maxim Cournoyer <maxim.cournoyer@gmail.com>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -20,10 +21,12 @@
 (define-module (test-pypi)
   #:use-module (guix import pypi)
   #:use-module (guix base32)
+  #:use-module (guix memoization)
   #:use-module (gcrypt hash)
+  #:use-module (guix memoization)
   #:use-module (guix tests)
   #:use-module (guix build-system python)
-  #:use-module ((guix build utils) #:select (delete-file-recursively which))
+  #:use-module ((guix build utils) #:select (delete-file-recursively which mkdir-p))
   #:use-module (srfi srfi-64)
   #:use-module (ice-9 match))
 
@@ -55,23 +58,64 @@
 (define test-source-hash
   "")
 
-(define test-requirements
-"# A comment
+(define test-specifications
+  '("Fizzy [foo, bar]"
+    "PickyThing<1.6,>1.9,!=1.9.6,<2.0a0,==2.4c1"
+    "SomethingWithMarker[foo]>1.0;python_version<\"2.7\""
+    "requests [security,tests] >= 2.8.1, == 2.8.* ; python_version < \"2.7\""
+    "pip @ https://github.com/pypa/pip/archive/1.3.1.zip#\
+sha1=da9234ee9982d4bbb3c72346a6de940a148ea686"))
+
+(define test-requires.txt "\
+# A comment
  # A comment after a space
-bar
-baz > 13.37")
+foo ~= 3
+bar != 2
 
-(define test-metadata
-  "{
-  \"run_requires\": [
-    {
-      \"requires\": [
-        \"bar\",
-        \"baz (>13.37)\"
-      ]
-    }
-  ]
-}")
+[test]
+pytest (>=2.5.0)
+")
+
+;; Beaker contains only optional dependencies.
+(define test-requires.txt-beaker "\
+[crypto]
+pycryptopp>=0.5.12
+
+[cryptography]
+cryptography
+
+[testsuite]
+Mock
+coverage
+")
+
+(define test-metadata "\
+Classifier: Programming Language :: Python :: 3.7
+Requires-Dist: baz ~= 3
+Requires-Dist: bar != 2
+Provides-Extra: test
+Requires-Dist: pytest (>=2.5.0) ; extra == 'test'
+")
+
+(define test-metadata-with-extras "
+Classifier: Programming Language :: Python :: 3.7
+Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*
+Requires-Dist: wrapt (<2,>=1)
+Requires-Dist: bar
+
+Provides-Extra: dev
+Requires-Dist: tox ; extra == 'dev'
+Requires-Dist: bumpversion (<1) ; extra == 'dev'
+")
+
+;;; Provides-Extra can appear before Requires-Dist.
+(define test-metadata-with-extras-jedi "\
+Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*
+Provides-Extra: testing
+Requires-Dist: parso (>=0.3.0)
+Provides-Extra: testing
+Requires-Dist: pytest (>=3.1.0); extra == 'testing'
+")
 
 (test-begin "pypi")
 
@@ -100,18 +144,48 @@ baz > 13.37")
                     (uri (list "https://bitheap.org/cram/cram-0.7.tar.gz"
                                (pypi-uri "cram" "0.7"))))))))
 
-(test-assert "pypi->guix-package"
+(test-equal "specification->requirement-name"
+  '("Fizzy" "PickyThing" "SomethingWithMarker" "requests" "pip")
+  (map specification->requirement-name test-specifications))
+
+(test-equal "parse-requires.txt"
+  (list '("foo" "bar") '("pytest"))
+  (mock ((ice-9 ports) call-with-input-file
+         call-with-input-string)
+        (parse-requires.txt test-requires.txt)))
+
+(test-equal "parse-requires.txt - Beaker"
+  (list '() '("Mock" "coverage"))
+  (mock ((ice-9 ports) call-with-input-file
+         call-with-input-string)
+        (parse-requires.txt test-requires.txt-beaker)))
+
+(test-equal "parse-wheel-metadata, with extras"
+  (list '("wrapt" "bar") '("tox" "bumpversion"))
+  (mock ((ice-9 ports) call-with-input-file
+         call-with-input-string)
+        (parse-wheel-metadata test-metadata-with-extras)))
+
+(test-equal "parse-wheel-metadata, with extras - Jedi"
+  (list '("parso") '("pytest"))
+  (mock ((ice-9 ports) call-with-input-file
+         call-with-input-string)
+        (parse-wheel-metadata test-metadata-with-extras-jedi)))
+
+(test-assert "pypi->guix-package, no wheel"
   ;; Replace network resources with sample data.
     (mock ((guix import utils) url-fetch
            (lambda (url file-name)
              (match url
                ("https://example.com/foo-1.0.0.tar.gz"
                 (begin
-                  (mkdir "foo-1.0.0")
-                  (with-output-to-file "foo-1.0.0/requirements.txt"
+                  ;; Unusual requires.txt location should still be found.
+                  (mkdir-p "foo-1.0.0/src/bizarre.egg-info")
+                  (with-output-to-file "foo-1.0.0/src/bizarre.egg-info/requires.txt"
                     (lambda ()
-                      (display test-requirements)))
-                  (system* "tar" "czvf" file-name "foo-1.0.0/")
+                      (display test-requires.txt)))
+                  (parameterize ((current-output-port (%make-void-port "rw+")))
+                    (system* "tar" "czvf" file-name "foo-1.0.0/"))
                   (delete-file-recursively "foo-1.0.0")
                   (set! test-source-hash
                     (call-with-input-file file-name port-sha256))))
@@ -139,7 +213,10 @@ baz > 13.37")
                      ('propagated-inputs
                       ('quasiquote
                        (("python-bar" ('unquote 'python-bar))
-                        ("python-baz" ('unquote 'python-baz)))))
+                        ("python-foo" ('unquote 'python-foo)))))
+                     ('native-inputs
+                      ('quasiquote
+                       (("python-pytest" ('unquote 'python-pytest)))))
                      ('home-page "http://example.com")
                      ('synopsis "summary")
                      ('description "summary")
@@ -157,27 +234,28 @@ baz > 13.37")
          (lambda (url file-name)
            (match url
              ("https://example.com/foo-1.0.0.tar.gz"
-               (begin
-                 (mkdir "foo-1.0.0")
-                 (with-output-to-file "foo-1.0.0/requirements.txt"
-                   (lambda ()
-                     (display test-requirements)))
-                 (system* "tar" "czvf" file-name "foo-1.0.0/")
-                 (delete-file-recursively "foo-1.0.0")
-                 (set! test-source-hash
-                       (call-with-input-file file-name port-sha256))))
+              (begin
+                (mkdir-p "foo-1.0.0/foo.egg-info/")
+                (with-output-to-file "foo-1.0.0/foo.egg-info/requires.txt"
+                  (lambda ()
+                    (display "wrong data to make sure we're testing wheels ")))
+                (parameterize ((current-output-port (%make-void-port "rw+")))
+                  (system* "tar" "czvf" file-name "foo-1.0.0/"))
+                (delete-file-recursively "foo-1.0.0")
+                (set! test-source-hash
+                  (call-with-input-file file-name port-sha256))))
              ("https://example.com/foo-1.0.0-py2.py3-none-any.whl"
-               (begin
-                 (mkdir "foo-1.0.0.dist-info")
-                 (with-output-to-file "foo-1.0.0.dist-info/metadata.json"
-                   (lambda ()
-                     (display test-metadata)))
-                 (let ((zip-file (string-append file-name ".zip")))
-                   ;; zip always adds a "zip" extension to the file it creates,
-                   ;; so we need to rename it.
-                   (system* "zip" zip-file "foo-1.0.0.dist-info/metadata.json")
-                   (rename-file zip-file file-name))
-                 (delete-file-recursively "foo-1.0.0.dist-info")))
+              (begin
+                (mkdir "foo-1.0.0.dist-info")
+                (with-output-to-file "foo-1.0.0.dist-info/METADATA"
+                  (lambda ()
+                    (display test-metadata)))
+                (let ((zip-file (string-append file-name ".zip")))
+                  ;; zip always adds a "zip" extension to the file it creates,
+                  ;; so we need to rename it.
+                  (system* "zip" "-q" zip-file "foo-1.0.0.dist-info/METADATA")
+                  (rename-file zip-file file-name))
+                (delete-file-recursively "foo-1.0.0.dist-info")))
              (_ (error "Unexpected URL: " url)))))
         (mock ((guix http-client) http-fetch
                (lambda (url . rest)
@@ -187,6 +265,9 @@ baz > 13.37")
                             (string-length test-json)))
                    ("https://example.com/foo-1.0.0-py2.py3-none-any.whl" #f)
                    (_ (error "Unexpected URL: " url)))))
+              ;; Not clearing the memoization cache here would mean returning the value
+              ;; computed in the previous test.
+              (invalidate-memoization! pypi->guix-package)
               (match (pypi->guix-package "foo")
                 (('package
                    ('name "python-foo")
@@ -202,6 +283,55 @@ baz > 13.37")
                     ('quasiquote
                      (("python-bar" ('unquote 'python-bar))
                       ("python-baz" ('unquote 'python-baz)))))
+                   ('native-inputs
+                    ('quasiquote
+                     (("python-pytest" ('unquote 'python-pytest)))))
+                   ('home-page "http://example.com")
+                   ('synopsis "summary")
+                   ('description "summary")
+                   ('license 'license:lgpl2.0))
+                 (string=? (bytevector->nix-base32-string
+                            test-source-hash)
+                           hash))
+                (x
+                 (pk 'fail x #f))))))
+
+(test-assert "pypi->guix-package, no usable requirement file."
+  ;; Replace network resources with sample data.
+  (mock ((guix import utils) url-fetch
+         (lambda (url file-name)
+           (match url
+             ("https://example.com/foo-1.0.0.tar.gz"
+              (mkdir-p "foo-1.0.0/foo.egg-info/")
+              (parameterize ((current-output-port (%make-void-port "rw+")))
+                (system* "tar" "czvf" file-name "foo-1.0.0/"))
+              (delete-file-recursively "foo-1.0.0")
+              (set! test-source-hash
+                (call-with-input-file file-name port-sha256)))
+             ("https://example.com/foo-1.0.0-py2.py3-none-any.whl" #f)
+             (_ (error "Unexpected URL: " url)))))
+        (mock ((guix http-client) http-fetch
+               (lambda (url . rest)
+                 (match url
+                   ("https://pypi.org/pypi/foo/json"
+                    (values (open-input-string test-json)
+                            (string-length test-json)))
+                   ("https://example.com/foo-1.0.0-py2.py3-none-any.whl" #f)
+                   (_ (error "Unexpected URL: " url)))))
+              ;; Not clearing the memoization cache here would mean returning the value
+              ;; computed in the previous test.
+              (invalidate-memoization! pypi->guix-package)
+              (match (pypi->guix-package "foo")
+                (('package
+                   ('name "python-foo")
+                   ('version "1.0.0")
+                   ('source ('origin
+                              ('method 'url-fetch)
+                              ('uri ('pypi-uri "foo" 'version))
+                              ('sha256
+                               ('base32
+                                (? string? hash)))))
+                   ('build-system 'python-build-system)
                    ('home-page "http://example.com")
                    ('synopsis "summary")
                    ('description "summary")