00c3eb7774e5458f979eaafa6143e5390c134e5b
[jackhill/guix/guix.git] / gnu / packages / python.scm
1 ;;; GNU Guix --- Functional package management for GNU
2 ;;; Copyright © 2013 Nikita Karetnikov <nikita@karetnikov.org>
3 ;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2018, 2021 Ludovic Courtès <ludo@gnu.org>
4 ;;; Copyright © 2013, 2014, 2015, 2016 Andreas Enge <andreas@enge.fr>
5 ;;; Copyright © 2014, 2015 Mark H Weaver <mhw@netris.org>
6 ;;; Copyright © 2014, 2017, 2019 Eric Bavier <bavier@member.fsf.org>
7 ;;; Copyright © 2014, 2015 Federico Beffa <beffa@fbengineering.ch>
8 ;;; Copyright © 2015 Omar Radwan <toxemicsquire4@gmail.com>
9 ;;; Copyright © 2015 Pierre-Antoine Rault <par@rigelk.eu>
10 ;;; Copyright © 2015, 2016, 2017, 2018, 2019 Ricardo Wurmus <rekado@elephly.net>
11 ;;; Copyright © 2015, 2016 Christine Lemmer-Webber <cwebber@dustycloud.org>
12 ;;; Copyright © 2015 Eric Dvorsak <eric@dvorsak.fr>
13 ;;; Copyright © 2015, 2016 David Thompson <davet@gnu.org>
14 ;;; Copyright © 2015, 2016, 2017, 2021 Leo Famulari <leo@famulari.name>
15 ;;; Copyright © 2015, 2017 Ben Woodcroft <donttrustben@gmail.com>
16 ;;; Copyright © 2015, 2016 Erik Edrosa <erik.edrosa@gmail.com>
17 ;;; Copyright © 2015, 2016, 2017, 2018, 2019, 2020 Efraim Flashner <efraim@flashner.co.il>
18 ;;; Copyright © 2015, 2017 Kyle Meyer <kyle@kyleam.com>
19 ;;; Copyright © 2015, 2016 Chris Marusich <cmmarusich@gmail.com>
20 ;;; Copyright © 2016 Danny Milosavljevic <dannym+a@scratchpost.org>
21 ;;; Copyright © 2016 Lukas Gradl <lgradl@openmailbox.org>
22 ;;; Copyright © 2016, 2018 Hartmut Goebel <h.goebel@crazy-compilers.com>
23 ;;; Copyright © 2016 Daniel Pimentel <d4n1@d4n1.org>
24 ;;; Copyright © 2016 Sou Bunnbu <iyzsong@gmail.com>
25 ;;; Copyright © 2016, 2017 Troy Sankey <sankeytms@gmail.com>
26 ;;; Copyright © 2016, 2017 Nikita <nikita@n0.is>
27 ;;; Copyright © 2016 Dylan Jeffers <sapientech@sapientech@openmailbox.org>
28 ;;; Copyright © 2016 David Craven <david@craven.ch>
29 ;;; Copyright © 2016, 2017, 2018, 2019, 2020, 2021 Marius Bakke <marius@gnu.org>
30 ;;; Copyright © 2016, 2017 Stefan Reichör <stefan@xsteve.at>
31 ;;; Copyright © 2016, 2017 Alex Vong <alexvong1995@gmail.com>
32 ;;; Copyright © 2016, 2017, 2018 Arun Isaac <arunisaac@systemreboot.net>
33 ;;; Copyright © 2016–2018, 2021, 2022 Tobias Geerinckx-Rice <me@tobias.gr>
34 ;;; Copyright © 2016, 2017, 2018, 2021 Julien Lepiller <julien@lepiller.eu>
35 ;;; Copyright © 2016, 2017 Thomas Danckaert <post@thomasdanckaert.be>
36 ;;; Copyright © 2017 Carlo Zancanaro <carlo@zancanaro.id.au>
37 ;;; Copyright © 2017 Frederick M. Muriithi <fredmanglis@gmail.com>
38 ;;; Copyright © 2017, 2018 Adriano Peluso <catonano@gmail.com>
39 ;;; Copyright © 2017 Ben Sturmfels <ben@sturm.com.au>
40 ;;; Copyright © 2017, 2018, 2019 Mathieu Othacehe <m.othacehe@gmail.com>
41 ;;; Copyright © 2017 José Miguel Sánchez García <jmi2k@openmailbox.org>
42 ;;; Copyright © 2017 Roel Janssen <roel@gnu.org>
43 ;;; Copyright © 2017, 2018 Kei Kebreau <kkebreau@posteo.net>
44 ;;; Copyright © 2017 Rutger Helling <rhelling@mykolab.com>
45 ;;; Copyright © 2017 Brendan Tildesley <mail@brendan.scot>
46 ;;; Copyright © 2018 Ethan R. Jones <ethanrjones97@gmail.com
47 ;;; Copyright © 2018 Fis Trivial <ybbs.daans@hotmail.com>
48 ;;; Copyright © 2018 Vijayalakshmi Vedantham <vijimay12@gmail.com>
49 ;;; Copyright © 2018 Mathieu Lirzin <mthl@gnu.org>
50 ;;; Copyright © 2018 Adam Massmann <massmannak@gmail.com>
51 ;;; Copyright © 2016, 2018 Tomáš Čech <sleep_walker@gnu.org>
52 ;;; Copyright © 2018 Nicolas Goaziou <mail@nicolasgoaziou.fr>
53 ;;; Copyright © 2018 Oleg Pykhalov <go.wigust@gmail.com>
54 ;;; Copyright © 2018 Clément Lassieur <clement@lassieur.org>
55 ;;; Copyright © 2018, 2019, 2020, 2021 Maxim Cournoyer <maxim.cournoyer@gmail.com>
56 ;;; Copyright © 2018 Luther Thompson <lutheroto@gmail.com>
57 ;;; Copyright © 2018 Vagrant Cascadian <vagrant@debian.org>
58 ;;; Copyright © 2019 Tanguy Le Carrour <tanguy@bioneland.org>
59 ;;; Copyright © 2020 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
60 ;;; Copyright © 2020, 2021 Greg Hogan <code@greghogan.com>
61 ;;; Copyright © 2022 Philip McGrath <philip@philipmcgrath.com>
62 ;;; Copyright © 2022 jgart <jgart@dismail.de>
63 ;;;
64 ;;; This file is part of GNU Guix.
65 ;;;
66 ;;; GNU Guix is free software; you can redistribute it and/or modify it
67 ;;; under the terms of the GNU General Public License as published by
68 ;;; the Free Software Foundation; either version 3 of the License, or (at
69 ;;; your option) any later version.
70 ;;;
71 ;;; GNU Guix is distributed in the hope that it will be useful, but
72 ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
73 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
74 ;;; GNU General Public License for more details.
75 ;;;
76 ;;; You should have received a copy of the GNU General Public License
77 ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
78
79 (define-module (gnu packages python)
80 #:use-module ((guix licenses) #:prefix license:)
81 #:use-module (gnu packages)
82 #:use-module (gnu packages base)
83 #:use-module (gnu packages bash)
84 #:use-module (gnu packages check)
85 #:use-module (gnu packages compression)
86 #:use-module (gnu packages dbm)
87 #:use-module (gnu packages hurd)
88 #:use-module (gnu packages libffi)
89 #:use-module (gnu packages pkg-config)
90 #:use-module (gnu packages readline)
91 #:use-module (gnu packages sqlite)
92 #:use-module (gnu packages tcl)
93 #:use-module (gnu packages tls)
94 #:use-module (gnu packages xml)
95 #:use-module (guix gexp)
96 #:use-module (guix packages)
97 #:use-module (guix download)
98 #:use-module (guix utils)
99 #:use-module (guix build-system gnu)
100 #:use-module (guix build-system trivial)
101 #:use-module (srfi srfi-1)
102 #:use-module (srfi srfi-26)
103
104 #:export (customize-site
105 guix-pythonpath-search-path))
106
107 (define* (customize-site version)
108 "Generate a install-sitecustomize.py phase, using VERSION."
109 `(lambda* (#:key native-inputs inputs outputs #:allow-other-keys)
110 (let* ((out (assoc-ref outputs "out"))
111 (site-packages (string-append
112 out "/lib/python"
113 ,(version-major+minor version)
114 "/site-packages"))
115 (sitecustomize.py (assoc-ref (or native-inputs inputs)
116 "sitecustomize.py"))
117 (dest (string-append site-packages "/sitecustomize.py")))
118 (mkdir-p site-packages)
119 (copy-file sitecustomize.py dest)
120 ;; Set the correct permissions on the installed file, else the byte
121 ;; compilation phase fails with a permission denied error.
122 (chmod dest #o644))))
123
124 (define (guix-pythonpath-search-path version)
125 "Generate a GUIX_PYTHONPATH search path specification, using VERSION."
126 (search-path-specification (variable "GUIX_PYTHONPATH")
127 (files (list (string-append
128 "lib/python"
129 (version-major+minor version)
130 "/site-packages")))))
131
132 (define-public python-2.7
133 (package
134 (name "python2")
135 (version "2.7.18")
136 (source
137 (origin
138 (method url-fetch)
139 (uri (string-append "https://www.python.org/ftp/python/"
140 version "/Python-" version ".tar.xz"))
141 (sha256
142 (base32
143 "0hzgxl94hnflis0d6m4szjx0b52gah7wpmcg5g00q7am6xwhwb5n"))
144 (patches (search-patches "python-2.7-search-paths.patch"
145 "python-2-deterministic-build-info.patch"
146 "python-2.7-site-prefixes.patch"
147 "python-2.7-source-date-epoch.patch"
148 "python-2.7-adjust-tests.patch"
149 "python-cross-compile.patch"
150 "python-2.7-CVE-2021-3177.patch"
151 "python-2.7-no-static-lib.patch"))
152 (modules '((guix build utils)))
153 (snippet
154 '(begin
155 ;; Ensure the bundled copies of these libraries are not used.
156 (for-each delete-file-recursively
157 '("Modules/_ctypes/libffi" "Modules/expat" "Modules/zlib"))
158
159 (substitute* "Modules/Setup.dist"
160 ;; Link Expat instead of embedding the bundled one.
161 (("^#pyexpat.*") "pyexpat pyexpat.c -lexpat\n"))
162
163 ;; Suboptimal to delete failing tests here, but if we delete them in
164 ;; the arguments then we need to make sure to strip out that phase
165 ;; when it gets inherited by python and python-minimal.
166 (for-each delete-file
167 '("Lib/test/test_compileall.py"
168 "Lib/test/test_ctypes.py" ; fails on mips64el
169 "Lib/test/test_distutils.py"
170 "Lib/test/test_import.py"
171 "Lib/test/test_shutil.py"
172 "Lib/test/test_socket.py"
173 "Lib/test/test_subprocess.py"))))))
174 (outputs '("out"
175 "tk" ;tkinter; adds 50 MiB to the closure
176 "idle")) ;programming environment; weighs 5MB
177 (build-system gnu-build-system)
178 (arguments
179 `(#:test-target "test"
180 #:configure-flags
181 (list "--enable-shared" ;allow embedding
182 "--with-system-expat" ;for XML support
183 "--with-system-ffi" ;build ctypes
184 "--with-ensurepip=install" ;install pip and setuptools
185 "--with-computed-gotos" ;main interpreter loop optimization
186 "--enable-unicode=ucs4"
187
188 ;; FIXME: These flags makes Python significantly faster, but
189 ;; leads to non-reproducible binaries.
190 ;; "--with-lto" ;increase size by 20MB, but 15% speedup
191 ;; "--enable-optimizations"
192
193 ;; Prevent the installed _sysconfigdata.py from retaining a reference
194 ;; to coreutils.
195 "INSTALL=install -c"
196 "MKDIR_P=mkdir -p"
197
198 ;; Disable runtime check failing if cross-compiling, see:
199 ;; https://lists.yoctoproject.org/pipermail/poky/2013-June/008997.html
200 ,@(if (%current-target-system)
201 '("ac_cv_buggy_getaddrinfo=no"
202 "ac_cv_file__dev_ptmx=no"
203 "ac_cv_file__dev_ptc=no")
204 '())
205 ;; -fno-semantic-interposition reinstates some optimizations by gcc
206 ;; leading to around 15% speedup. This is the default starting from
207 ;; python 3.10.
208 "CFLAGS=-fno-semantic-interposition"
209 (string-append "LDFLAGS=-Wl,-rpath="
210 (assoc-ref %outputs "out") "/lib"
211 " -fno-semantic-interposition"))
212 ;; With no -j argument tests use all available cpus, so provide one.
213 #:make-flags
214 (list (string-append
215 (format #f "TESTOPTS=-j~d" (parallel-job-count))
216 ;; Exclude the following tests as they fail
217 ;; non-deterministically with "error: [Errno 104] Connection
218 ;; reset by peer." Python 3 seems unaffected. A potential fix,
219 ;; yet to be backported to Python 2, is available at:
220 ;; https://github.com/python/cpython/commit/529525fb5a8fd9b96ab4021311a598c77588b918.
221 " --exclude test_urllib2_localnet test_httplib"))
222
223 #:modules ((ice-9 ftw) (ice-9 match)
224 (guix build utils) (guix build gnu-build-system))
225 #:phases
226 (modify-phases %standard-phases
227 (add-before
228 'configure 'patch-lib-shells
229 (lambda _
230 ;; This variable is used in setup.py to enable cross compilation
231 ;; specific switches. As it is not set properly by configure
232 ;; script, set it manually.
233 ,@(if (%current-target-system)
234 '((setenv "_PYTHON_HOST_PLATFORM" ""))
235 '())
236 ;; Filter for existing files, since some may not exist in all
237 ;; versions of python that are built with this recipe.
238 (substitute* (filter file-exists?
239 '("Lib/subprocess.py"
240 "Lib/popen2.py"
241 "Lib/distutils/tests/test_spawn.py"
242 "Lib/test/support/__init__.py"
243 "Lib/test/test_subprocess.py"))
244 (("/bin/sh") (which "sh")))))
245 ,@(if (hurd-system?)
246 `((add-before 'build 'patch-regen-for-hurd
247 (lambda* (#:key inputs #:allow-other-keys)
248 (let ((libc (assoc-ref inputs "libc")))
249 (substitute* "Lib/plat-generic/regen"
250 (("/usr/include/") (string-append libc "/include/")))))))
251 '())
252 (add-before 'configure 'do-not-record-configure-flags
253 (lambda* (#:key configure-flags #:allow-other-keys)
254 ;; Remove configure flags from the installed '_sysconfigdata.py'
255 ;; and 'Makefile' so we don't end up keeping references to the
256 ;; build tools.
257 ;;
258 ;; Preserve at least '--with-system-ffi' since otherwise the
259 ;; thing tries to build libffi, fails, and we end up with a
260 ;; Python that lacks ctypes.
261 (substitute* "configure"
262 (("^CONFIG_ARGS=.*$")
263 (format #f "CONFIG_ARGS='~a'\n"
264 (if (member "--with-system-ffi" configure-flags)
265 "--with-system-ffi"
266 ""))))))
267 (add-before 'check 'pre-check
268 (lambda _
269 ;; 'Lib/test/test_site.py' needs a valid $HOME
270 (setenv "HOME" (getcwd))))
271 (add-after 'unpack 'set-source-file-times-to-1980
272 ;; XXX One of the tests uses a ZIP library to pack up some of the
273 ;; source tree, and fails with "ZIP does not support timestamps
274 ;; before 1980". Work around this by setting the file times in the
275 ;; source tree to sometime in early 1980.
276 (lambda _
277 (let ((circa-1980 (* 10 366 24 60 60)))
278 (ftw "." (lambda (file stat flag)
279 (utime file circa-1980 circa-1980)
280 #t)))))
281 (add-after 'install 'remove-tests
282 ;; Remove 25 MiB of unneeded unit tests. Keep test_support.*
283 ;; because these files are used by some libraries out there.
284 (lambda* (#:key outputs #:allow-other-keys)
285 (let ((out (assoc-ref outputs "out")))
286 (match (scandir (string-append out "/lib")
287 (lambda (name)
288 (string-prefix? "python" name)))
289 ((pythonX.Y)
290 (let ((testdir (string-append out "/lib/" pythonX.Y
291 "/test")))
292 (with-directory-excursion testdir
293 (for-each delete-file-recursively
294 (scandir testdir
295 (match-lambda
296 ((or "." "..") #f)
297 ("support" #f)
298 (file
299 (not
300 (string-prefix? "test_support."
301 file))))))
302 (call-with-output-file "__init__.py" (const #t))))
303 (let ((libdir (string-append out "/lib/" pythonX.Y)))
304 (for-each
305 (lambda (directory)
306 (let ((dir (string-append libdir "/" directory)))
307 (when (file-exists? dir)
308 (delete-file-recursively dir))))
309 '("email/test" "ctypes/test" "unittest/test" "tkinter/test"
310 "sqlite3/test" "bsddb/test" "lib-tk/test" "json/tests"
311 "distutils/tests"))))))))
312 (add-after 'remove-tests 'move-tk-inter
313 (lambda* (#:key outputs #:allow-other-keys)
314 ;; When Tkinter support is built move it to a separate output so
315 ;; that the main output doesn't contain a reference to Tcl/Tk.
316 (let ((out (assoc-ref outputs "out"))
317 (tk (assoc-ref outputs "tk")))
318 (when tk
319 (match (find-files out "tkinter.*\\.so")
320 ((tkinter.so)
321 ;; The .so is in OUT/lib/pythonX.Y/lib-dynload, but we
322 ;; want it under TK/lib/pythonX.Y/site-packages.
323 (let* ((len (string-length out))
324 (target (string-append
325 tk "/"
326 (string-drop
327 (dirname (dirname tkinter.so))
328 len)
329 "/site-packages")))
330 (install-file tkinter.so target)
331 (delete-file tkinter.so))))))))
332 (add-after 'move-tk-inter 'move-idle
333 (lambda* (#:key outputs #:allow-other-keys)
334 ;; when idle is built, move it to a separate output to save some
335 ;; space (5MB)
336 (let ((out (assoc-ref outputs "out"))
337 (idle (assoc-ref outputs "idle")))
338 (when idle
339 (for-each
340 (lambda (file)
341 (let ((target (string-append idle "/bin/" (basename file))))
342 (install-file file (dirname target))
343 (delete-file file)))
344 (find-files (string-append out "/bin") "^idle"))
345 (match (find-files out "^idlelib$" #:directories? #t)
346 ((idlelib)
347 (let* ((len (string-length out))
348 (target (string-append idle "/"
349 (string-drop idlelib len)
350 "/site-packages")))
351 (mkdir-p (dirname target))
352 (rename-file idlelib target))))))))
353 (add-after 'move-idle 'rebuild-bytecode
354 (lambda* (#:key outputs #:allow-other-keys)
355 (let ((out (assoc-ref outputs "out")))
356 ;; Disable hash randomization to ensure the generated .pycs
357 ;; are reproducible.
358 (setenv "PYTHONHASHSEED" "0")
359 (for-each
360 (lambda (output)
361 (for-each (lambda (opt)
362 (format #t "Compiling with optimization level: ~a\n"
363 (if (null? opt) "none" (car opt)))
364 (apply invoke
365 `(,,(if (%current-target-system)
366 "python2"
367 '(string-append out "/bin/python"))
368 ,@opt
369 "-m" "compileall"
370 "-f" ; force rebuild
371 ;; Don't build lib2to3, because it contains
372 ;; Python 3 code.
373 "-x" "lib2to3/.*"
374 ,output)))
375 ;; Python 2 has a single file extension (.pyo) for the
376 ;; chosen level of optimization, so it doesn't make
377 ;; sense to byte compile with more than one level.
378 (list '() '("-OO"))))
379 (map cdr outputs)))))
380 (add-after 'install 'install-sitecustomize.py
381 ,(customize-site version)))))
382 (inputs
383 (list bzip2
384 expat
385 gdbm
386 libffi ; for ctypes
387 sqlite ; for sqlite extension
388 openssl-1.1
389 readline
390 zlib
391 tcl
392 tk)) ; for tkinter
393 (native-inputs
394 `(("pkg-config" ,pkg-config)
395 ("sitecustomize.py" ,(local-file (search-auxiliary-file
396 "python/sitecustomize.py")))
397 ;; When cross-compiling, a native version of Python itself is needed.
398 ,@(if (%current-target-system)
399 `(("python2" ,this-package)
400 ("which" ,which))
401 '())))
402 (native-search-paths
403 (list (guix-pythonpath-search-path version)))
404 (home-page "https://www.python.org")
405 (synopsis "High-level, dynamically-typed programming language")
406 (description
407 "Python is a remarkably powerful dynamic programming language that
408 is used in a wide variety of application domains. Some of its key
409 distinguishing features include: clear, readable syntax; strong
410 introspection capabilities; intuitive object orientation; natural
411 expression of procedural code; full modularity, supporting hierarchical
412 packages; exception-based error handling; and very high level dynamic
413 data types.")
414 (properties '((cpe-name . "python")))
415 (license license:psfl)))
416
417 ;; Current 2.x version.
418 (define-public python-2 python-2.7)
419
420 (define-public python-3.9
421 (package
422 (inherit python-2)
423 (name "python")
424 (version "3.9.9")
425 (source (origin
426 (method url-fetch)
427 (uri (string-append "https://www.python.org/ftp/python/"
428 version "/Python-" version ".tar.xz"))
429 (patches (search-patches
430 "python-3-arm-alignment.patch"
431 "python-3-deterministic-build-info.patch"
432 "python-3-fix-tests.patch"
433 "python-3-hurd-configure.patch"
434 "python-3-search-paths.patch"
435 "python-3-no-static-lib.patch"))
436 (sha256
437 (base32
438 "09vd7g71i11iz5ydqghwc8kaxr0vgji94hhwwnj77h3kll28r0h6"))
439 (modules '((guix build utils)))
440 (snippet
441 '(begin
442 ;; Delete the bundled copy of libexpat.
443 (delete-file-recursively "Modules/expat")
444 (substitute* "Modules/Setup"
445 ;; Link Expat instead of embedding the bundled one.
446 (("^#pyexpat.*") "pyexpat pyexpat.c -lexpat\n"))
447 ;; Delete windows binaries
448 (for-each delete-file
449 (find-files "Lib/distutils/command" "\\.exe$"))))))
450 (arguments
451 (substitute-keyword-arguments (package-arguments python-2)
452 ((#:make-flags _)
453 `(list (string-append
454 (format #f "TESTOPTS=-j~d" (parallel-job-count))
455 ;; test_mmap fails on low-memory systems
456 " --exclude test_mmap test_socket"
457 ,@(if (hurd-target?)
458 '(" test_posix" ;multiple errors
459 " test_time"
460 " test_pty"
461 " test_shutil"
462 " test_tempfile" ;chflags: invalid argument:
463 ; tbv14c9t/dir0/dir0/dir0/test0.txt
464 " test_asyncio" ;runs over 10min
465 " test_os" ;stty: 'standard input':
466 ; Inappropriate ioctl for device
467 " test_openpty" ;No such file or directory
468 " test_selectors" ;assertEqual(NUM_FDS // 2, len(fds))
469 ; 32752 != 4
470 " test_compileall" ;multiple errors
471 " test_poll" ;list index out of range
472 " test_subprocess" ;runs over 10min
473 " test_asyncore" ;multiple errors
474 " test_threadsignals"
475 " test_eintr" ;Process return code is -14
476 " test_io" ;multiple errors
477 " test_logging"
478 " test_signal"
479 " test_threading" ;runs over 10min
480 " test_flags" ;ERROR
481 " test_bidirectional_pty"
482 " test_create_unix_connection"
483 " test_unix_sock_client_ops"
484 " test_open_unix_connection"
485 " test_open_unix_connection_error"
486 " test_read_pty_output"
487 " test_write_pty")
488 '()))))
489 ((#:phases phases)
490 `(modify-phases ,phases
491 ,@(if (hurd-system?)
492 `((delete 'patch-regen-for-hurd)) ;regen was removed after 3.5.9
493 '())
494 (add-after 'unpack 'remove-windows-binaries
495 (lambda _
496 ;; Delete .exe from embedded .whl (zip) files
497 (for-each
498 (lambda (whl)
499 (let ((dir "whl-content")
500 (circa-1980 (* 10 366 24 60 60)))
501 (mkdir-p dir)
502 (with-directory-excursion dir
503 (let ((whl (string-append "../" whl)))
504 (invoke "unzip" whl)
505 (for-each delete-file
506 (find-files "." "\\.exe$"))
507 (delete-file whl)
508 ;; Reset timestamps to prevent them from ending
509 ;; up in the Zip archive.
510 (ftw "." (lambda (file stat flag)
511 (utime file circa-1980 circa-1980)
512 #t))
513 (apply invoke "zip" "-X" whl
514 (find-files "." #:directories? #t))))
515 (delete-file-recursively dir)))
516 (find-files "Lib/ensurepip" "\\.whl$"))))
517 (add-before 'check 'set-TZDIR
518 (lambda* (#:key inputs native-inputs #:allow-other-keys)
519 ;; test_email requires the Olson time zone database.
520 (setenv "TZDIR"
521 (string-append (assoc-ref
522 (or native-inputs inputs) "tzdata")
523 "/share/zoneinfo"))))
524 (replace 'rebuild-bytecode
525 (lambda* (#:key outputs #:allow-other-keys)
526 (let ((out (assoc-ref outputs "out")))
527 ;; Disable hash randomization to ensure the generated .pycs
528 ;; are reproducible.
529 (setenv "PYTHONHASHSEED" "0")
530
531 (for-each (lambda (output)
532 ;; XXX: Delete existing pycs generated by the build
533 ;; system beforehand because the -f argument does
534 ;; not necessarily overwrite all files, leading to
535 ;; indeterministic results.
536 (for-each (lambda (pyc)
537 (delete-file pyc))
538 (find-files output "\\.pyc$"))
539
540 (apply invoke
541 `(,,(if (%current-target-system)
542 "python3"
543 '(string-append out
544 "/bin/python3"))
545 "-m" "compileall"
546 "-o" "0" "-o" "1" "-o" "2"
547 "-f" ; force rebuild
548 "--invalidation-mode=unchecked-hash"
549 ;; Don't build lib2to3, because it's
550 ;; Python 2 code.
551 "-x" "lib2to3/.*"
552 ,output)))
553 (map cdr outputs)))))
554 (replace 'install-sitecustomize.py
555 ,(customize-site version))))))
556 (inputs
557 (modify-inputs (package-inputs python-2.7)
558 (replace "openssl" openssl)))
559 (native-inputs
560 `(("tzdata" ,tzdata-for-tests)
561 ("unzip" ,unzip)
562 ("zip" ,(@ (gnu packages compression) zip))
563 ,@(if (%current-target-system)
564 `(("python3" ,this-package))
565 '())
566 ,@(package-native-inputs python-2)))
567 (native-search-paths
568 (list (guix-pythonpath-search-path version)
569 ;; Used to locate tzdata by the zoneinfo module introduced in
570 ;; Python 3.9.
571 (search-path-specification
572 (variable "PYTHONTZPATH")
573 (files (list "share/zoneinfo")))))))
574
575 ;; Current 3.x version.
576 (define-public python-3 python-3.9)
577
578 ;; Current major version.
579 (define-public python python-3)
580
581 ;; Minimal variants of Python, mostly used to break the cycle between Tk and
582 ;; Python (Tk -> libxcb -> Python.)
583
584 (define-public python2-minimal
585 (package/inherit python-2
586 (name "python2-minimal")
587 (outputs '("out"))
588
589 ;; Keep zlib, which is used by 'pip' (via the 'zipimport' module), which
590 ;; is invoked upon 'make install'. 'pip' also expects 'ctypes' and thus
591 ;; libffi. Expat is needed for XML support which is expected by a lot
592 ;; of libraries out there.
593 (inputs `(("expat" ,expat)
594 ("libffi" ,libffi)
595 ("zlib" ,zlib)))))
596
597 (define-public python-minimal
598 (package/inherit python
599 (name "python-minimal")
600 (outputs '("out"))
601
602 ;; Build fails due to missing ctypes without libffi.
603 ;; OpenSSL is a mandatory dependency of Python 3.x, for urllib;
604 ;; zlib is required by 'zipimport', used by pip. Expat is needed
605 ;; for XML support, which is generally expected to be available.
606 (inputs `(("expat" ,expat)
607 ("libffi" ,libffi)
608 ("openssl" ,openssl)
609 ("zlib" ,zlib)))))
610
611 (define-public python-debug
612 (package/inherit python
613 (name "python-debug")
614 (outputs '("out" "debug"))
615 (build-system gnu-build-system)
616 (arguments
617 (substitute-keyword-arguments (package-arguments python)
618 ((#:configure-flags flags '())
619 `(cons "--with-pydebug" ,flags))))
620 (synopsis
621 "Python with the debug hooks enabled")
622 (description
623 "This variant of Python provides an interpreter built with
624 @code{--with-pydebug} to help develop and debug extensions. See
625 @url{https://pythonextensionpatterns.readthedocs.io/en/latest/debugging/debug.html},
626 for more information.")))
627
628 (define* (wrap-python3 python
629 #:optional
630 (name (string-append (package-name python) "-wrapper")))
631 (package/inherit python
632 (name name)
633 (source #f)
634 (build-system trivial-build-system)
635 (outputs '("out"))
636 (inputs `(("bash" ,bash)))
637 (propagated-inputs `(("python" ,python)))
638 (arguments
639 `(#:modules ((guix build utils))
640 #:builder
641 (begin
642 (use-modules (guix build utils))
643 (let ((bin (string-append (assoc-ref %outputs "out") "/bin"))
644 (python (string-append (assoc-ref %build-inputs "python") "/bin/")))
645 (mkdir-p bin)
646 (for-each
647 (lambda (old new)
648 (symlink (string-append python old)
649 (string-append bin "/" new)))
650 `("python3" ,"pydoc3" ,"pip3")
651 `("python" ,"pydoc" ,"pip"))
652 ;; python-config outputs search paths based upon its location,
653 ;; use a bash wrapper to avoid changing its outputs.
654 (let ((bash (string-append (assoc-ref %build-inputs "bash")
655 "/bin/bash"))
656 (old (string-append python "python3-config"))
657 (new (string-append bin "/python-config")))
658 (with-output-to-file new
659 (lambda ()
660 (format #t "#!~a~%" bash)
661 (format #t "exec \"~a\" \"$@\"~%" old)
662 (chmod new #o755))))))))
663 (synopsis "Wrapper for the Python 3 commands")
664 (description
665 "This package provides wrappers for the commands of Python@tie{}3.x such
666 that they can also be invoked under their usual names---e.g., @command{python}
667 instead of @command{python3} or @command{pip} instead of @command{pip3}.
668
669 To function properly, this package should not be installed together with the
670 @code{python} package: this package uses the @code{python} package as a
671 propagated input, so installing this package already makes both the versioned
672 and the unversioned commands available.")))
673
674 (define-public python-wrapper (wrap-python3 python))
675 (define-public python-minimal-wrapper (wrap-python3 python-minimal))
676
677 (define-public micropython
678 (package
679 (name "micropython")
680 (version "1.19")
681 (source
682 (origin
683 (method url-fetch)
684 (uri (string-append "https://github.com/micropython/micropython/"
685 "releases/download/v" version
686 "/micropython-" version ".tar.xz"))
687 (sha256
688 (base32 "090bbls5vnicynjyjqqd5zqwx8d6zxp7wlnrxgh0b4s8cyf5i8zj"))
689 (modules '((guix build utils)))
690 (snippet
691 '(begin
692 (delete-file-recursively "ports/cc3200/FreeRTOS")
693 (with-directory-excursion "lib"
694 ;; TODO: Unbundle axtls and berkley-db-1.xx
695 (for-each delete-file-recursively
696 '("libffi" "lwip" "stm32lib" "nrfx")))))))
697 (build-system gnu-build-system)
698 (arguments
699 (list #:phases
700 #~(modify-phases %standard-phases
701 (add-before 'build 'build-mpy-cross
702 (lambda* (#:key make-flags #:allow-other-keys)
703 (with-directory-excursion "mpy-cross"
704 (apply invoke "make" make-flags))))
705 (add-after 'build-mpy-cross 'prepare-build
706 (lambda _
707 (chdir "ports/unix")
708 ;; see: https://github.com/micropython/micropython/pull/4246
709 (substitute* "Makefile"
710 (("-Os") "-Os -ffp-contract=off"))))
711 (add-before 'install-license-files 'chdir-back
712 ;; We don't build in the root directory so the file isn't found.
713 (lambda _
714 (chdir "../..")))
715 (delete 'configure)) ; no configure
716 #:make-flags
717 #~(list (string-append "PREFIX=" #$output)
718 "V=1")
719 #:test-target "test"))
720 (native-inputs (list pkg-config python-wrapper))
721 (inputs
722 (list libffi))
723 (home-page "https://micropython.org/")
724 (synopsis "Python implementation for microcontrollers and constrained systems")
725 (description "MicroPython is a lean and efficient implementation of the
726 Python 3 programming language that includes a small subset of the Python
727 standard library and is optimised to run on microcontrollers and in constrained
728 environments. MicroPython is packed full of advanced features such as an
729 interactive prompt, arbitrary precision integers, closures, list comprehension,
730 generators, exception handling and more. Still it is compact enough to fit and
731 run within just 256k of code space and 16k of RAM. MicroPython aims to be as
732 compatible with normal Python as possible to allow you to transfer code with
733 ease from the desktop to a microcontroller or embedded system.")
734 (license license:expat)))