projects/guix·blob wip-postfix · refs

790 lines · 37.5 KiB

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