summaryrefslogtreecommitdiff
path: root/gnu/packages/python.scm
diff options
context:
space:
mode:
authorNicolas Graves <ngraves@ngraves.fr>2026-01-17 14:27:18 +0100
committerSharlatan Hellseher <sharlatanus@gmail.com>2026-05-24 10:14:18 +0100
commit356f58222035d1199418f47ff0b4e5ca36502c07 (patch)
tree3a526ba8018e45e0932a7544cd808cf8d8883c82 /gnu/packages/python.scm
parent18a3715a185c0dbac6d69d868c39c4bc79ae2254 (diff)
gnu: python: Refactor module.
* gnu/packages/python.scm (common-python-phases): New variable, encompassing phases used both in all python packages. Add a warning comment. (common-python3-phases): New variable, encompassing phases used in all python@3 packages. Add a warning comment. (python-2.7)[arguments]<#:phases>: Modify them from (common-python-phases) base. (python-3.10)[arguments]: Avoid substituting python-2.7 arguments. <#:configure-flags>: ...except here, which is fine since it's not further inherited. <#:phases>: Modify them from (common-python3-phases) base. (python-3.11)[arguments]<#:phases>: Modify them from (common-python3-phases) base. (python-2.7)[arguments]<#:phases>: Modify them from (common-python3-phases) base.
Diffstat (limited to 'gnu/packages/python.scm')
-rw-r--r--gnu/packages/python.scm1030
1 files changed, 325 insertions, 705 deletions
diff --git a/gnu/packages/python.scm b/gnu/packages/python.scm
index 04b42331748..21f1a169eba 100644
--- a/gnu/packages/python.scm
+++ b/gnu/packages/python.scm
@@ -63,6 +63,7 @@
63;;; Copyright © 2021 Lars-Dominik Braun <lars@6xq.net> 63;;; Copyright © 2021 Lars-Dominik Braun <lars@6xq.net>
64;;; Copyright © 2025 Hugo Buddelmeijer <hugo@buddelmeijer.nl> 64;;; Copyright © 2025 Hugo Buddelmeijer <hugo@buddelmeijer.nl>
65;;; Copyright © 2025 Sharlatan Hellseher <sharlatanus@gmail.com> 65;;; Copyright © 2025 Sharlatan Hellseher <sharlatanus@gmail.com>
66;;; Copyright © 2025-2026 Nicolas Graves <ngraves@ngraves.fr>
66;;; 67;;;
67;;; This file is part of GNU Guix. 68;;; This file is part of GNU Guix.
68;;; 69;;;
@@ -105,6 +106,7 @@
105 #:use-module (guix build-system copy) 106 #:use-module (guix build-system copy)
106 #:use-module (guix build-system gnu) 107 #:use-module (guix build-system gnu)
107 #:use-module (guix build-system trivial) 108 #:use-module (guix build-system trivial)
109 #:use-module (ice-9 optargs)
108 #:use-module (srfi srfi-1) 110 #:use-module (srfi srfi-1)
109 #:use-module (srfi srfi-26) 111 #:use-module (srfi srfi-26)
110 112
@@ -136,6 +138,225 @@
136 (version-major+minor version) 138 (version-major+minor version)
137 "/site-packages"))))) 139 "/site-packages")))))
138 140
141;; Modifying this is a world-rebuild! If possible, modify phases in python
142;; packages themselves.
143(define (common-python-phases-edits)
144 #~((add-before 'configure 'patch-lib-shells
145 (lambda _
146 ;; This variable is used in setup.py to enable cross compilation
147 ;; specific switches. As it is not set properly by configure
148 ;; script, set it manually.
149 #$@(if (%current-target-system)
150 #~((setenv "_PYTHON_HOST_PLATFORM" ""))
151 #~())
152 ;; Filter for existing files, since some may not exist in all
153 ;; versions of python that are built with this recipe.
154 (substitute* (filter file-exists?
155 '("Lib/subprocess.py"
156 "Lib/popen2.py"
157 "Lib/distutils/tests/test_spawn.py"
158 "Lib/test/support/__init__.py"
159 "Lib/test/test_subprocess.py"))
160 (("/bin/sh") (which "sh")))))
161 (add-before 'configure 'do-not-record-configure-flags
162 (lambda* (#:key configure-flags #:allow-other-keys)
163 ;; Remove configure flags from the installed '_sysconfigdata.py'
164 ;; and 'Makefile' so we don't end up keeping references to the
165 ;; build tools.
166 ;;
167 ;; Preserve at least '--with-system-ffi' since otherwise the
168 ;; thing tries to build libffi, fails, and we end up with a
169 ;; Python that lacks ctypes.
170 (substitute* "configure"
171 (("^CONFIG_ARGS=.*$")
172 (format #f "CONFIG_ARGS='~a'\n"
173 (if (member "--with-system-ffi" configure-flags)
174 "--with-system-ffi"
175 ""))))))
176 (add-before 'check 'pre-check
177 (lambda _
178 ;; 'Lib/test/test_site.py' needs a valid $HOME
179 (setenv "HOME" (getcwd))))
180 (add-after 'unpack 'set-source-file-times-to-1980
181 ;; XXX One of the tests uses a ZIP library to pack up some of the
182 ;; source tree, and fails with "ZIP does not support timestamps
183 ;; before 1980". Work around this by setting the file times in the
184 ;; source tree to sometime in early 1980.
185 (lambda _
186 (let ((circa-1980 (* 10 366 24 60 60)))
187 (ftw "." (lambda (file stat flag)
188 (utime file circa-1980 circa-1980)
189 #t)))))
190 (add-after 'install 'add-libxcrypt-reference-pkgconfig
191 (lambda* (#:key inputs outputs #:allow-other-keys)
192 (define out (assoc-ref outputs "out"))
193 (define libxcrypt
194 (false-if-exception
195 (dirname (search-input-file inputs "lib/libcrypt.so.1"))))
196 (when libxcrypt
197 (substitute*
198 (find-files (string-append out "/lib/pkgconfig")
199 ".*\\.pc")
200 (("-lcrypt")
201 (string-append "-L" libxcrypt " -lcrypt"))))))
202 (add-after 'install 'remove-tests
203 ;; Remove 25 MiB of unneeded unit tests. Keep test_support.*
204 ;; because these files are used by some libraries out there.
205 (lambda* (#:key outputs #:allow-other-keys)
206 (let ((out (assoc-ref outputs "out")))
207 (match (scandir (string-append out "/lib")
208 (lambda (name)
209 (string-prefix? "python" name)))
210 ((pythonX.Y)
211 (let ((testdir (string-append out "/lib/" pythonX.Y
212 "/test")))
213 (with-directory-excursion testdir
214 (for-each delete-file-recursively
215 (scandir testdir
216 (match-lambda
217 ((or "." "..") #f)
218 ("support" #f)
219 (file
220 (not
221 (string-prefix? "test_support."
222 file))))))
223 (call-with-output-file "__init__.py" (const #t))))
224 (let ((libdir (string-append out "/lib/" pythonX.Y)))
225 (for-each
226 (lambda (directory)
227 (let ((dir (string-append libdir "/" directory)))
228 (when (file-exists? dir)
229 (delete-file-recursively dir))))
230 '("email/test" "ctypes/test" "unittest/test" "tkinter/test"
231 "sqlite3/test" "bsddb/test" "lib-tk/test" "json/tests"
232 "distutils/tests"))))))))
233 (add-after 'remove-tests 'move-tk-inter
234 (lambda* (#:key outputs #:allow-other-keys)
235 ;; When Tkinter support is built move it to a separate output so
236 ;; that the main output doesn't contain a reference to Tcl/Tk.
237 (let ((out (assoc-ref outputs "out"))
238 (tk (assoc-ref outputs "tk")))
239 (when tk
240 (match (find-files out "tkinter.*\\.so")
241 ((tkinter.so)
242 ;; The .so is in OUT/lib/pythonX.Y/lib-dynload, but we
243 ;; want it under TK/lib/pythonX.Y/site-packages.
244 (let* ((len (string-length out))
245 (target (string-append
246 tk "/"
247 (string-drop
248 (dirname (dirname tkinter.so))
249 len)
250 "/site-packages")))
251 (install-file tkinter.so target)
252 (delete-file tkinter.so))))))))
253 (add-after 'move-tk-inter 'move-idle
254 (lambda* (#:key outputs #:allow-other-keys)
255 ;; when idle is built, move it to a separate output to save some
256 ;; space (5MB)
257 (let ((out (assoc-ref outputs "out"))
258 (idle (assoc-ref outputs "idle")))
259 (when idle
260 (for-each
261 (lambda (file)
262 (let ((target (string-append idle "/bin/" (basename file))))
263 (install-file file (dirname target))
264 (delete-file file)))
265 (find-files (string-append out "/bin") "^idle"))
266 (match (find-files out "^idlelib$" #:directories? #t)
267 ((idlelib)
268 (let* ((len (string-length out))
269 (target (string-append idle "/"
270 (string-drop idlelib len)
271 "/site-packages")))
272 (mkdir-p (dirname target))
273 (rename-file idlelib target))))))))))
274
275;; Modifying this is a world-rebuild! If possible, modify phases in python
276;; packages themselves.
277(define (common-python3-phases-edits)
278 #~(#$@(common-python-phases-edits)
279 #$@(if (system-hurd?)
280 #~((add-after 'unpack 'disable-multi-processing
281 (lambda _
282 (substitute* "Makefile.pre.in"
283 (("-j0") "-j1")))))
284 #~())
285 (add-after 'unpack 'remove-windows-binaries
286 (lambda _
287 ;; Delete .exe from embedded .whl (zip) files
288 (for-each
289 (lambda (whl)
290 (let ((dir "whl-content")
291 (circa-1980 (* 10 366 24 60 60)))
292 (mkdir-p dir)
293 (with-directory-excursion dir
294 (let ((whl (string-append "../" whl)))
295 (invoke "unzip" whl)
296 (for-each delete-file (find-files "." "\\.exe$"))
297 (delete-file whl)
298 ;; Reset timestamps to prevent them from ending
299 ;; up in the Zip archive.
300 (ftw "." (lambda (file stat flag)
301 (utime file circa-1980 circa-1980)))
302 (apply invoke "zip" "-X" whl
303 (find-files "." #:directories? #t))))
304 (delete-file-recursively dir)))
305 (find-files "Lib/ensurepip" "\\.whl$"))))
306 (add-after 'move-tk-inter 'move-tk-inter:remove-explicit-store-path
307 (lambda* (#:key outputs inputs #:allow-other-keys)
308 ;; When Tkinter support is built move it to a separate output so
309 ;; that the main output doesn't contain a reference to Tcl/Tk.
310 (let ((out (assoc-ref outputs "out"))
311 (tk (assoc-ref outputs "tk")))
312 (when tk
313 ;; Remove explicit store path references.
314 (let ((tcl (assoc-ref inputs "tcl"))
315 (tk (assoc-ref inputs "tk")))
316 (substitute* (find-files (string-append out "/lib")
317 "^(_sysconfigdata_.*\\.py|Makefile)$")
318 (((string-append "-L" tk "/lib"))
319 "")
320 (((string-append "-L" tcl "/lib"))
321 "")))))))
322 (add-before 'check 'set-TZDIR
323 (lambda* (#:key inputs native-inputs #:allow-other-keys)
324 ;; test_email requires the Olson time zone database.
325 (setenv "TZDIR"
326 (string-append (assoc-ref (or native-inputs
327 inputs) "tzdata")
328 "/share/zoneinfo"))))
329 (add-after 'move-idle 'rebuild-bytecode
330 (lambda* (#:key outputs #:allow-other-keys)
331 ;; Disable hash randomization to ensure the generated .pycs
332 ;; are reproducible.
333 (setenv "PYTHONHASHSEED" "0")
334
335 (for-each (lambda (output)
336 ;; XXX: Delete existing pycs generated by the build
337 ;; system beforehand because the -f argument does
338 ;; not necessarily overwrite all files, leading to
339 ;; indeterministic results.
340 (for-each (lambda (pyc)
341 (delete-file pyc))
342 (find-files output "\\.pyc$"))
343
344 (apply invoke
345 #$(if (%current-target-system)
346 "python3"
347 #~(string-append #$output "/bin/python3"))
348 `("-m" "compileall"
349 "-o" "0"
350 "-o" "1"
351 "-o" "2"
352 "-f" ;force rebuild
353 "--invalidation-mode=unchecked-hash"
354 ;; Don't build lib2to3, because it's Python
355 ;; 2 code.
356 "-x" "lib2to3/.*"
357 ,output)))
358 (map cdr outputs))))))
359
139(define-public python-2.7 360(define-public python-2.7
140 (package 361 (package
141 (name "python2") 362 (name "python2")
@@ -251,24 +472,7 @@
251 (guix build gnu-build-system)) 472 (guix build gnu-build-system))
252 #:phases 473 #:phases
253 #~(modify-phases %standard-phases 474 #~(modify-phases %standard-phases
254 (add-before 475 #$@(common-python-phases-edits)
255 'configure 'patch-lib-shells
256 (lambda _
257 ;; This variable is used in setup.py to enable cross compilation
258 ;; specific switches. As it is not set properly by configure
259 ;; script, set it manually.
260 #$@(if (%current-target-system)
261 #~((setenv "_PYTHON_HOST_PLATFORM" ""))
262 #~())
263 ;; Filter for existing files, since some may not exist in all
264 ;; versions of python that are built with this recipe.
265 (substitute* (filter file-exists?
266 '("Lib/subprocess.py"
267 "Lib/popen2.py"
268 "Lib/distutils/tests/test_spawn.py"
269 "Lib/test/support/__init__.py"
270 "Lib/test/test_subprocess.py"))
271 (("/bin/sh") (which "sh")))))
272 #$@(if (system-hurd?) 476 #$@(if (system-hurd?)
273 #~((add-before 'build 'patch-regen-for-hurd 477 #~((add-before 'build 'patch-regen-for-hurd
274 (lambda* (#:key inputs #:allow-other-keys) 478 (lambda* (#:key inputs #:allow-other-keys)
@@ -276,119 +480,6 @@
276 (substitute* "Lib/plat-generic/regen" 480 (substitute* "Lib/plat-generic/regen"
277 (("/usr/include/") (string-append libc "/include/"))))))) 481 (("/usr/include/") (string-append libc "/include/")))))))
278 #~()) 482 #~())
279 (add-before 'configure 'do-not-record-configure-flags
280 (lambda* (#:key configure-flags #:allow-other-keys)
281 ;; Remove configure flags from the installed '_sysconfigdata.py'
282 ;; and 'Makefile' so we don't end up keeping references to the
283 ;; build tools.
284 ;;
285 ;; Preserve at least '--with-system-ffi' since otherwise the
286 ;; thing tries to build libffi, fails, and we end up with a
287 ;; Python that lacks ctypes.
288 (substitute* "configure"
289 (("^CONFIG_ARGS=.*$")
290 (format #f "CONFIG_ARGS='~a'\n"
291 (if (member "--with-system-ffi" configure-flags)
292 "--with-system-ffi"
293 ""))))))
294 (add-before 'check 'pre-check
295 (lambda _
296 ;; 'Lib/test/test_site.py' needs a valid $HOME
297 (setenv "HOME" (getcwd))))
298 (add-after 'unpack 'set-source-file-times-to-1980
299 ;; XXX One of the tests uses a ZIP library to pack up some of the
300 ;; source tree, and fails with "ZIP does not support timestamps
301 ;; before 1980". Work around this by setting the file times in the
302 ;; source tree to sometime in early 1980.
303 (lambda _
304 (let ((circa-1980 (* 10 366 24 60 60)))
305 (ftw "." (lambda (file stat flag)
306 (utime file circa-1980 circa-1980)
307 #t)))))
308 (add-after 'install 'remove-tests
309 ;; Remove 25 MiB of unneeded unit tests. Keep test_support.*
310 ;; because these files are used by some libraries out there.
311 (lambda* (#:key outputs #:allow-other-keys)
312 (let ((out (assoc-ref outputs "out")))
313 (match (scandir (string-append out "/lib")
314 (lambda (name)
315 (string-prefix? "python" name)))
316 ((pythonX.Y)
317 (let ((testdir (string-append out "/lib/" pythonX.Y
318 "/test")))
319 (with-directory-excursion testdir
320 (for-each delete-file-recursively
321 (scandir testdir
322 (match-lambda
323 ((or "." "..") #f)
324 ("support" #f)
325 (file
326 (not
327 (string-prefix? "test_support."
328 file))))))
329 (call-with-output-file "__init__.py" (const #t))))
330 (let ((libdir (string-append out "/lib/" pythonX.Y)))
331 (for-each
332 (lambda (directory)
333 (let ((dir (string-append libdir "/" directory)))
334 (when (file-exists? dir)
335 (delete-file-recursively dir))))
336 '("email/test" "ctypes/test" "unittest/test" "tkinter/test"
337 "sqlite3/test" "bsddb/test" "lib-tk/test" "json/tests"
338 "distutils/tests"))))))))
339 (add-after 'install 'add-libxcrypt-reference-pkgconfig
340 (lambda* (#:key inputs outputs #:allow-other-keys)
341 (define out (assoc-ref outputs "out"))
342 (define libxcrypt
343 (false-if-exception
344 (dirname (search-input-file inputs "lib/libcrypt.so.1"))))
345 (when libxcrypt
346 (substitute*
347 (find-files (string-append out "/lib/pkgconfig")
348 ".*\\.pc")
349 (("-lcrypt")
350 (string-append "-L" libxcrypt " -lcrypt"))))))
351 (add-after 'remove-tests 'move-tk-inter
352 (lambda* (#:key outputs #:allow-other-keys)
353 ;; When Tkinter support is built move it to a separate output so
354 ;; that the main output doesn't contain a reference to Tcl/Tk.
355 (let ((out (assoc-ref outputs "out"))
356 (tk (assoc-ref outputs "tk")))
357 (when tk
358 (match (find-files out "tkinter.*\\.so")
359 ((tkinter.so)
360 ;; The .so is in OUT/lib/pythonX.Y/lib-dynload, but we
361 ;; want it under TK/lib/pythonX.Y/site-packages.
362 (let* ((len (string-length out))
363 (target (string-append
364 tk "/"
365 (string-drop
366 (dirname (dirname tkinter.so))
367 len)
368 "/site-packages")))
369 (install-file tkinter.so target)
370 (delete-file tkinter.so))))))))
371 (add-after 'move-tk-inter 'move-idle
372 (lambda* (#:key outputs #:allow-other-keys)
373 ;; when idle is built, move it to a separate output to save some
374 ;; space (5MB)
375 (let ((out (assoc-ref outputs "out"))
376 (idle (assoc-ref outputs "idle")))
377 (when idle
378 (for-each
379 (lambda (file)
380 (let ((target (string-append idle "/bin/" (basename file))))
381 (install-file file (dirname target))
382 (delete-file file)))
383 (find-files (string-append out "/bin") "^idle"))
384 (match (find-files out "^idlelib$" #:directories? #t)
385 ((idlelib)
386 (let* ((len (string-length out))
387 (target (string-append idle "/"
388 (string-drop idlelib len)
389 "/site-packages")))
390 (mkdir-p (dirname target))
391 (rename-file idlelib target))))))))
392 (add-after 'move-idle 'rebuild-bytecode 483 (add-after 'move-idle 'rebuild-bytecode
393 (lambda* (#:key outputs #:allow-other-keys) 484 (lambda* (#:key outputs #:allow-other-keys)
394 (let ((out (assoc-ref outputs "out"))) 485 (let ((out (assoc-ref outputs "out")))
@@ -492,100 +583,103 @@ data types.")
492 ;; Delete windows binaries 583 ;; Delete windows binaries
493 (for-each delete-file 584 (for-each delete-file
494 (find-files "Lib/distutils/command" "\\.exe$")))))) 585 (find-files "Lib/distutils/command" "\\.exe$"))))))
586 (build-system gnu-build-system)
495 (arguments 587 (arguments
496 (substitute-keyword-arguments arguments 588 (list
497 ((#:configure-flags flags) 589 #:configure-flags
498 #~(append #$flags 590 ;; Avoid inheriting phases, but configure-flags is fine, as
591 ;; it doesn't propagate to later python version.
592 (let-keywords (package-arguments python-2) #t
593 ((configure-flags #~(list)))
594 #~(append #$configure-flags
499 ;; XXX Use quote to avoid world rebuild at this time 595 ;; XXX Use quote to avoid world rebuild at this time
500 '("--without-static-libpython"))) 596 '("--without-static-libpython")))
501 ((#:make-flags _) 597 #:make-flags
502 #~(list (string-append 598 #~(list (string-append
503 (format #f "TESTOPTS=-j~d" (parallel-job-count)) 599 (format #f "TESTOPTS=-j~d" (parallel-job-count))
504 ;; test_mmap fails on low-memory systems 600 ;; test_mmap fails on low-memory systems
505 " --exclude test_mmap test_socket" 601 " --exclude test_mmap test_socket"
506 #$@(if (system-hurd?) 602 #$@(if (system-hurd?)
507 #~(" test_posix" ;multiple errors 603 #~(" test_posix" ;multiple errors
508 " test_time" 604 " test_time"
509 " test_pty" 605 " test_pty"
510 " test_shutil" 606 " test_shutil"
511 " test_tempfile" ;chflags: invalid argument: 607 " test_tempfile" ;chflags: invalid argument:
512 ; tbv14c9t/dir0/dir0/dir0/test0.txt 608 ; tbv14c9t/dir0/dir0/dir0/test0.txt
513 " test_asyncio" ;runs over 10min 609 " test_asyncio" ;runs over 10min
514 " test_os" ;stty: 'standard input': 610 " test_os" ;stty: 'standard input':
515 ; Inappropriate ioctl for device 611 ; Inappropriate ioctl for device
516 " test_openpty" ;No such file or directory 612 " test_openpty" ;No such file or directory
517 " test_selectors" ;assertEqual(NUM_FDS // 2, len(fds)) 613 " test_selectors" ;assertEqual(NUM_FDS // 2, len(fds))
518 ; 32752 != 4 614 ; 32752 != 4
519 " test_compileall" ;multiple errors 615 " test_compileall" ;multiple errors
520 " test_poll" ;list index out of range 616 " test_poll" ;list index out of range
521 " test_subprocess" ;runs over 10min 617 " test_subprocess" ;runs over 10min
522 " test_asyncore" ;multiple errors 618 " test_asyncore" ;multiple errors
523 " test_threadsignals" 619 " test_threadsignals"
524 " test_eintr" ;Process return code is -14 620 " test_eintr" ;Process return code is -14
525 " test_io" ;multiple errors 621 " test_io" ;multiple errors
526 " test_logging" 622 " test_logging"
527 " test_signal" 623 " test_signal"
528 " test_threading" ;runs over 10min 624 " test_threading" ;runs over 10min
529 " test_flags" ;ERROR 625 " test_flags" ;ERROR
530 " test_bidirectional_pty" 626 " test_bidirectional_pty"
531 " test_create_unix_connection" 627 " test_create_unix_connection"
532 " test_unix_sock_client_ops" 628 " test_unix_sock_client_ops"
533 " test_open_unix_connection" 629 " test_open_unix_connection"
534 " test_open_unix_connection_error" 630 " test_open_unix_connection_error"
535 " test_read_pty_output" 631 " test_read_pty_output"
536 " test_write_pty" 632 " test_write_pty"
537 " test_concurrent_futures" ;freeze 633 " test_concurrent_futures" ;freeze
538 " test_venv" ;freeze 634 " test_venv" ;freeze
539 " test_multiprocessing_forkserver" ;runs over 10min 635 " test_multiprocessing_forkserver" ;runs over 10min
540 " test_multiprocessing_spawn" ;runs over 10min 636 " test_multiprocessing_spawn" ;runs over 10min
541 " test_builtin" 637 " test_builtin"
542 " test_capi" 638 " test_capi"
543 " test_dbm_ndbm" 639 " test_dbm_ndbm"
544 " test_exceptions" 640 " test_exceptions"
545 " test_faulthandler" 641 " test_faulthandler"
546 " test_getopt" 642 " test_getopt"
547 " test_importlib" 643 " test_importlib"
548 " test_json" 644 " test_json"
549 " test_multiprocessing_fork" 645 " test_multiprocessing_fork"
550 " test_multiprocessing_main_handling" 646 " test_multiprocessing_main_handling"
551 " test_pdb " 647 " test_pdb "
552 " test_regrtest" 648 " test_regrtest"
553 " test_sqlite") 649 " test_sqlite")
554 #~())))) 650 #~())))
555 ((#:phases phases) 651 #:modules '((ice-9 ftw)
556 #~(modify-phases #$phases 652 (ice-9 match)
557 #$@(if (system-hurd?) 653 (guix build utils)
558 #~((delete 'patch-regen-for-hurd) ;regen was removed after 3.5.9 654 (guix build gnu-build-system))
559 (add-after 'unpack 'disable-multi-processing 655 #:phases
560 (lambda _ 656 #~(modify-phases %standard-phases
561 (substitute* "Makefile.pre.in" 657 #$@(common-python3-phases-edits)
562 (("-j0") "-j1"))))) 658 (replace 'remove-windows-binaries
563 #~()) 659 (lambda _
564 (add-after 'unpack 'remove-vendored-wheel-content 660 ;; Delete .exe from embedded .whl (zip) files
565 (lambda _ 661 (for-each
566 ;; Delete .exe from embedded .whl (zip) files 662 (lambda (whl)
567 (for-each 663 (let ((dir "whl-content")
568 (lambda (whl) 664 (circa-1980 (* 10 366 24 60 60)))
569 (let ((dir "whl-content") 665 (mkdir-p dir)
570 (circa-1980 (* 10 366 24 60 60))) 666 (with-directory-excursion dir
571 (mkdir-p dir) 667 (let ((whl (string-append "../" whl)))
572 (with-directory-excursion dir 668 (invoke "unzip" whl)
573 (let ((whl (string-append "../" whl))) 669 (for-each delete-file
574 (invoke "unzip" whl) 670 (find-files "." "\\.exe$"))
575 (for-each delete-file 671 (delete-file whl)
576 (find-files "." "\\.exe$"))
577 (delete-file whl)
578 672
579 ;; Search for cacert.pem, delete it, and rewrite the 673 ;; Search for cacert.pem, delete it, and rewrite the
580 ;; file which directs python to look for it. 674 ;; file which directs python to look for it.
581 (let ((cacert (find-files "." "cacert\\.pem"))) 675 (let ((cacert (find-files "." "cacert\\.pem")))
582 (unless (null? cacert) 676 (unless (null? cacert)
583 (let ((certifi (dirname (car cacert)))) 677 (let ((certifi (dirname (car cacert))))
584 (delete-file (string-append certifi "/cacert.pem")) 678 (delete-file (string-append certifi "/cacert.pem"))
585 (delete-file (string-append certifi "/core.py")) 679 (delete-file (string-append certifi "/core.py"))
586 (with-output-to-file (string-append certifi "/core.py") 680 (with-output-to-file (string-append certifi "/core.py")
587 (lambda _ 681 (lambda _
588 (display "\"\"\" 682 (display "\"\"\"
589certifi.py 683certifi.py
590~~~~~~~~~~ 684~~~~~~~~~~
591This file is a Guix-specific version of core.py. 685This file is a Guix-specific version of core.py.
@@ -609,54 +703,17 @@ def contents() -> str:
609 with open(where(), \"r\", encoding=\"ascii\") as data: 703 with open(where(), \"r\", encoding=\"ascii\") as data:
610 return data.read()")))))) 704 return data.read()"))))))
611 705
612 ;; Reset timestamps to prevent them from ending 706 ;; Reset timestamps to prevent them from ending
613 ;; up in the Zip archive. 707 ;; up in the Zip archive.
614 (ftw "." (lambda (file stat flag) 708 (ftw "." (lambda (file stat flag)
615 (utime file circa-1980 circa-1980) 709 (utime file circa-1980 circa-1980)
616 #t)) 710 #t))
617 (apply invoke "zip" "-X" whl 711 (apply invoke "zip" "-X" whl
618 (find-files "." #:directories? #t)))) 712 (find-files "." #:directories? #t))))
619 (delete-file-recursively dir))) 713 (delete-file-recursively dir)))
620 (find-files "Lib/ensurepip" "\\.whl$")))) 714 (find-files "Lib/ensurepip" "\\.whl$"))))
621 (add-before 'check 'set-TZDIR 715 (add-after 'install 'install-sitecustomize.py
622 (lambda* (#:key inputs native-inputs #:allow-other-keys) 716 #$(customize-site version)))))
623 ;; test_email requires the Olson time zone database.
624 (setenv "TZDIR"
625 (string-append (assoc-ref
626 (or native-inputs inputs) "tzdata")
627 "/share/zoneinfo"))))
628 (replace 'rebuild-bytecode
629 (lambda* (#:key outputs #:allow-other-keys)
630 (let ((out (assoc-ref outputs "out")))
631 ;; Disable hash randomization to ensure the generated .pycs
632 ;; are reproducible.
633 (setenv "PYTHONHASHSEED" "0")
634
635 (for-each (lambda (output)
636 ;; XXX: Delete existing pycs generated by the build
637 ;; system beforehand because the -f argument does
638 ;; not necessarily overwrite all files, leading to
639 ;; indeterministic results.
640 (for-each (lambda (pyc)
641 (delete-file pyc))
642 (find-files output "\\.pyc$"))
643
644 (apply invoke
645 `(,#$(if (%current-target-system)
646 "python3"
647 #~(string-append out
648 "/bin/python3"))
649 "-m" "compileall"
650 "-o" "0" "-o" "1" "-o" "2"
651 "-f" ; force rebuild
652 "--invalidation-mode=unchecked-hash"
653 ;; Don't build lib2to3, because it's
654 ;; Python 2 code.
655 "-x" "lib2to3/.*"
656 ,output)))
657 (map cdr outputs)))))
658 (replace 'install-sitecustomize.py
659 #$(customize-site version))))))
660 (inputs 717 (inputs
661 (modify-inputs (package-inputs python-2.7) 718 (modify-inputs (package-inputs python-2.7)
662 (replace "openssl" openssl))) 719 (replace "openssl" openssl)))
@@ -837,228 +894,7 @@ def contents() -> str:
837 894
838 #:phases 895 #:phases
839 #~(modify-phases %standard-phases 896 #~(modify-phases %standard-phases
840 #$@(if (system-hurd?) 897 #$@(common-python3-phases-edits)
841 `((add-after 'unpack
842 'disable-multi-processing
843 (lambda _
844 (substitute* "Makefile.pre.in"
845 (("-j0")
846 "-j1")))))
847 '())
848 (add-before 'configure 'patch-lib-shells
849 (lambda _
850 ;; This variable is used in setup.py to enable cross compilation
851 ;; specific switches. As it is not set properly by configure
852 ;; script, set it manually.
853 #$@(if (%current-target-system)
854 '((setenv "_PYTHON_HOST_PLATFORM" ""))
855 '())
856 ;; Filter for existing files, since some may not exist in all
857 ;; versions of python that are built with this recipe.
858 (substitute* (filter file-exists?
859 '("Lib/subprocess.py"
860 "Lib/popen2.py"
861 "Lib/distutils/tests/test_spawn.py"
862 "Lib/test/support/__init__.py"
863 "Lib/test/test_subprocess.py"))
864 (("/bin/sh")
865 (which "sh")))))
866 (add-before 'configure 'do-not-record-configure-flags
867 (lambda* (#:key configure-flags #:allow-other-keys)
868 ;; Remove configure flags from the installed '_sysconfigdata.py'
869 ;; and 'Makefile' so we don't end up keeping references to the
870 ;; build tools.
871 ;;
872 ;; Preserve at least '--with-system-ffi' since otherwise the
873 ;; thing tries to build libffi, fails, and we end up with a
874 ;; Python that lacks ctypes.
875 (substitute* "configure"
876 (("^CONFIG_ARGS=.*$")
877 (format #f "CONFIG_ARGS='~a'\n"
878 (if (member "--with-system-ffi"
879 configure-flags)
880 "--with-system-ffi" ""))))))
881 (add-before 'check 'pre-check
882 (lambda _
883 ;; 'Lib/test/test_site.py' needs a valid $HOME
884 (setenv "HOME"
885 (getcwd))))
886 (add-after 'unpack 'set-source-file-times-to-1980
887 ;; XXX One of the tests uses a ZIP library to pack up some of the
888 ;; source tree, and fails with "ZIP does not support timestamps
889 ;; before 1980". Work around this by setting the file times in the
890 ;; source tree to sometime in early 1980.
891 (lambda _
892 (let ((circa-1980 (* 10 366 24 60 60)))
893 (ftw "."
894 (lambda (file stat flag)
895 (utime file circa-1980 circa-1980) #t)))))
896 (add-after 'unpack 'remove-windows-binaries
897 (lambda _
898 ;; Delete .exe from embedded .whl (zip) files
899 (for-each (lambda (whl)
900 (let ((dir "whl-content")
901 (circa-1980 (* 10 366 24 60 60)))
902 (mkdir-p dir)
903 (with-directory-excursion dir
904 (let ((whl (string-append "../" whl)))
905 (invoke "unzip" whl)
906 (for-each delete-file
907 (find-files "." "\\.exe$"))
908 (delete-file whl)
909 ;; Reset timestamps to prevent them from ending
910 ;; up in the Zip archive.
911 (ftw "."
912 (lambda (file stat flag)
913 (utime file circa-1980
914 circa-1980) #t))
915 (apply invoke "zip" "-X" whl
916 (find-files "."
917 #:directories? #t))))
918 (delete-file-recursively dir)))
919 (find-files "Lib/ensurepip" "\\.whl$"))))
920 (add-after 'install 'remove-tests
921 ;; Remove 25 MiB of unneeded unit tests. Keep test_support.*
922 ;; because these files are used by some libraries out there.
923 (lambda* (#:key outputs #:allow-other-keys)
924 (let ((out (assoc-ref outputs "out")))
925 (match (scandir (string-append out "/lib")
926 (lambda (name)
927 (string-prefix? "python" name)))
928 ((pythonX.Y)
929 (let ((testdir (string-append out "/lib/" pythonX.Y
930 "/test")))
931 (with-directory-excursion testdir
932 (for-each delete-file-recursively
933 (scandir testdir
934 (match-lambda
935 ((or "." "..")
936 #f)
937 ("support" #f)
938 (file (not (string-prefix?
939 "test_support."
940 file))))))
941 (call-with-output-file "__init__.py"
942 (const #t))))
943 (let ((libdir (string-append out "/lib/" pythonX.Y)))
944 (for-each (lambda (directory)
945 (let ((dir (string-append libdir "/"
946 directory)))
947 (when (file-exists? dir)
948 (delete-file-recursively dir))))
949 '("email/test" "ctypes/test"
950 "unittest/test"
951 "tkinter/test"
952 "sqlite3/test"
953 "bsddb/test"
954 "lib-tk/test"
955 "json/tests"
956 "distutils/tests"))))))))
957 (add-after 'remove-tests 'move-tk-inter
958 (lambda* (#:key outputs inputs #:allow-other-keys)
959 ;; When Tkinter support is built move it to a separate output so
960 ;; that the main output doesn't contain a reference to Tcl/Tk.
961 (let ((out (assoc-ref outputs "out"))
962 (tk (assoc-ref outputs "tk")))
963 (when tk
964 (match (find-files out "tkinter.*\\.so")
965 ((tkinter.so)
966 ;; The .so is in OUT/lib/pythonX.Y/lib-dynload, but we
967 ;; want it under TK/lib/pythonX.Y/site-packages.
968 (let* ((len (string-length out))
969 (target (string-append tk "/"
970 (string-drop (dirname
971 (dirname
972 tkinter.so))
973 len)
974 "/site-packages")))
975 (install-file tkinter.so target)
976 (delete-file tkinter.so))))
977 ;; Remove explicit store path references.
978 (let ((tcl (assoc-ref inputs "tcl"))
979 (tk (assoc-ref inputs "tk")))
980 (substitute* (find-files (string-append out "/lib")
981 "^(_sysconfigdata_.*\\.py|Makefile)$")
982 (((string-append "-L" tk "/lib"))
983 "")
984 (((string-append "-L" tcl "/lib"))
985 "")))))))
986 (add-after 'move-tk-inter 'move-idle
987 (lambda* (#:key outputs #:allow-other-keys)
988 ;; when idle is built, move it to a separate output to save some
989 ;; space (5MB)
990 (let ((out (assoc-ref outputs "out"))
991 (idle (assoc-ref outputs "idle")))
992 (when idle
993 (for-each (lambda (file)
994 (let ((target (string-append idle
995 "/bin/"
996 (basename
997 file))))
998 (install-file file
999 (dirname target))
1000 (delete-file file)))
1001 (find-files (string-append out "/bin")
1002 "^idle"))
1003 (match (find-files out "^idlelib$"
1004 #:directories? #t)
1005 ((idlelib)
1006 (let* ((len (string-length out))
1007 (target (string-append idle "/"
1008 (string-drop
1009 idlelib len)
1010 "/site-packages")))
1011 (mkdir-p (dirname target))
1012 (rename-file idlelib target))))))))
1013 (add-after 'move-idle 'rebuild-bytecode
1014 (lambda* (#:key outputs #:allow-other-keys)
1015 ;; Disable hash randomization to ensure the generated .pycs
1016 ;; are reproducible.
1017 (setenv "PYTHONHASHSEED" "0")
1018
1019 (for-each (lambda (output)
1020 ;; XXX: Delete existing pycs generated by the build
1021 ;; system beforehand because the -f argument does
1022 ;; not necessarily overwrite all files, leading to
1023 ;; indeterministic results.
1024 (for-each (lambda (pyc)
1025 (delete-file pyc))
1026 (find-files output "\\.pyc$"))
1027
1028 (apply invoke
1029 #$(if (%current-target-system)
1030 "python3"
1031 #~(string-append #$output "/bin/python3"))
1032 `("-m" "compileall"
1033 "-o" "0"
1034 "-o" "1"
1035 "-o" "2"
1036 "-f" ;force rebuild
1037 "--invalidation-mode=unchecked-hash"
1038 ;; Don't build lib2to3, because it's Python
1039 ;; 2 code.
1040 "-x" "lib2to3/.*"
1041 ,output)))
1042 (map cdr outputs))))
1043 (add-before 'check 'set-TZDIR
1044 (lambda* (#:key inputs native-inputs #:allow-other-keys)
1045 ;; test_email requires the Olson time zone database.
1046 (setenv "TZDIR"
1047 (string-append (assoc-ref (or native-inputs
1048 inputs) "tzdata")
1049 "/share/zoneinfo"))))
1050 (add-after 'install 'add-libxcrypt-reference-pkgconfig
1051 (lambda* (#:key inputs #:allow-other-keys)
1052 (let ((libxcrypt
1053 (false-if-exception
1054 (dirname
1055 (search-input-file inputs "lib/libcrypt.so.1")))))
1056 (when libxcrypt
1057 (substitute*
1058 (find-files (string-append #$output "/lib/pkgconfig")
1059 ".*\\.pc")
1060 (("Libs:")
1061 (string-append "Libs: " "-L" libxcrypt " -lcrypt")))))))
1062 (add-after 'install 'install-sitecustomize.py 898 (add-after 'install 'install-sitecustomize.py
1063 #$(customize-site version))))) 899 #$(customize-site version)))))
1064 (inputs (list bzip2 900 (inputs (list bzip2
@@ -1223,223 +1059,7 @@ def contents() -> str:
1223 1059
1224 #:phases 1060 #:phases
1225 #~(modify-phases %standard-phases 1061 #~(modify-phases %standard-phases
1226 #$@(if (system-hurd?) 1062 #$@(common-python3-phases-edits)
1227 #~((add-after 'unpack
1228 'disable-multi-processing
1229 (lambda _
1230 (substitute* "Makefile.pre.in"
1231 (("-j0")
1232 "-j1")))))
1233 #~())
1234 (add-before 'configure 'patch-lib-shells
1235 (lambda _
1236 ;; This variable is used in setup.py to enable cross compilation
1237 ;; specific switches. As it is not set properly by configure
1238 ;; script, set it manually.
1239 #$@(if (%current-target-system)
1240 #~((setenv "_PYTHON_HOST_PLATFORM" ""))
1241 #~())
1242 ;; Filter for existing files, since some may not exist in all
1243 ;; versions of python that are built with this recipe.
1244 (substitute* (filter file-exists?
1245 '("Lib/subprocess.py"
1246 "Lib/popen2.py"
1247 "Lib/distutils/tests/test_spawn.py"
1248 "Lib/test/support/__init__.py"
1249 "Lib/test/test_subprocess.py"))
1250 (("/bin/sh")
1251 (which "sh")))))
1252 (add-before 'configure 'do-not-record-configure-flags
1253 (lambda* (#:key configure-flags #:allow-other-keys)
1254 ;; Remove configure flags from the installed '_sysconfigdata.py'
1255 ;; and 'Makefile' so we don't end up keeping references to the
1256 ;; build tools.
1257 ;;
1258 ;; Preserve at least '--with-system-ffi' since otherwise the
1259 ;; thing tries to build libffi, fails, and we end up with a
1260 ;; Python that lacks ctypes.
1261 (substitute* "configure"
1262 (("^CONFIG_ARGS=.*$")
1263 (format #f "CONFIG_ARGS='~a'\n"
1264 (if (member "--with-system-ffi"
1265 configure-flags)
1266 "--with-system-ffi" ""))))))
1267 (add-before 'check 'pre-check
1268 (lambda _
1269 ;; 'Lib/test/test_site.py' needs a valid $HOME
1270 (setenv "HOME"
1271 (getcwd))))
1272 (add-after 'unpack 'set-source-file-times-to-1980
1273 ;; XXX One of the tests uses a ZIP library to pack up some of the
1274 ;; source tree, and fails with "ZIP does not support timestamps
1275 ;; before 1980". Work around this by setting the file times in the
1276 ;; source tree to sometime in early 1980.
1277 (lambda _
1278 (let ((circa-1980 (* 10 366 24 60 60)))
1279 (ftw "."
1280 (lambda (file stat flag)
1281 (utime file circa-1980 circa-1980) #t)))))
1282 (add-after 'unpack 'remove-windows-binaries
1283 (lambda _
1284 ;; Delete .exe from embedded .whl (zip) files
1285 (for-each (lambda (whl)
1286 (let ((dir "whl-content")
1287 (circa-1980 (* 10 366 24 60 60)))
1288 (mkdir-p dir)
1289 (with-directory-excursion dir
1290 (let ((whl (string-append "../" whl)))
1291 (invoke "unzip" whl)
1292 (for-each delete-file
1293 (find-files "." "\\.exe$"))
1294 (delete-file whl)
1295 ;; Reset timestamps to prevent them from ending
1296 ;; up in the Zip archive.
1297 (ftw "."
1298 (lambda (file stat flag)
1299 (utime file circa-1980
1300 circa-1980) #t))
1301 (apply invoke "zip" "-X" whl
1302 (find-files "."
1303 #:directories? #t))))
1304 (delete-file-recursively dir)))
1305 (find-files "Lib/ensurepip" "\\.whl$"))))
1306 (add-after 'install 'remove-tests
1307 ;; Remove 25 MiB of unneeded unit tests. Keep test_support.*
1308 ;; because these files are used by some libraries out there.
1309 (lambda* (#:key outputs #:allow-other-keys)
1310 (let ((out (assoc-ref outputs "out")))
1311 (match (scandir (string-append out "/lib")
1312 (lambda (name)
1313 (string-prefix? "python" name)))
1314 ((pythonX.Y)
1315 (let ((testdir (string-append out "/lib/" pythonX.Y
1316 "/test")))
1317 (with-directory-excursion testdir
1318 (for-each delete-file-recursively
1319 (scandir testdir
1320 (match-lambda
1321 ((or "." "..")
1322 #f)
1323 ("support" #f)
1324 (file (not (string-prefix?
1325 "test_support."
1326 file))))))
1327 (call-with-output-file "__init__.py"
1328 (const #t))))
1329 (let ((libdir (string-append out "/lib/" pythonX.Y)))
1330 (for-each (lambda (directory)
1331 (let ((dir (string-append libdir "/"
1332 directory)))
1333 (when (file-exists? dir)
1334 (delete-file-recursively dir))))
1335 '("email/test" "ctypes/test"
1336 "unittest/test"
1337 "tkinter/test"
1338 "sqlite3/test"
1339 "bsddb/test"
1340 "lib-tk/test"
1341 "json/tests"
1342 "distutils/tests"))))))))
1343 (add-after 'remove-tests 'move-tk-inter
1344 (lambda* (#:key outputs inputs #:allow-other-keys)
1345 ;; When Tkinter support is built move it to a separate output so
1346 ;; that the main output doesn't contain a reference to Tcl/Tk.
1347 (let ((out (assoc-ref outputs "out"))
1348 (tk (assoc-ref outputs "tk")))
1349 (when tk
1350 (match (find-files out "tkinter.*\\.so")
1351 ((tkinter.so)
1352 ;; The .so is in OUT/lib/pythonX.Y/lib-dynload, but we
1353 ;; want it under TK/lib/pythonX.Y/site-packages.
1354 (let* ((len (string-length out))
1355 (target (string-append tk "/"
1356 (string-drop (dirname
1357 (dirname
1358 tkinter.so))
1359 len)
1360 "/site-packages")))
1361 (install-file tkinter.so target)
1362 (delete-file tkinter.so))))
1363 ;; Remove explicit store path references.
1364 (let ((tcl (assoc-ref inputs "tcl"))
1365 (tk (assoc-ref inputs "tk")))
1366 (substitute* (find-files (string-append out "/lib")
1367 "^(_sysconfigdata_.*\\.py|Makefile)$")
1368 (((string-append "-L" tk "/lib"))
1369 "")
1370 (((string-append "-L" tcl "/lib"))
1371 "")))))))
1372 (add-after 'move-tk-inter 'move-idle
1373 (lambda* (#:key outputs #:allow-other-keys)
1374 ;; when idle is built, move it to a separate output to save some
1375 ;; space (5MB)
1376 (let ((out (assoc-ref outputs "out"))
1377 (idle (assoc-ref outputs "idle")))
1378 (when idle
1379 (for-each (lambda (file)
1380 (let ((target (string-append idle
1381 "/bin/"
1382 (basename
1383 file))))
1384 (install-file file
1385 (dirname target))
1386 (delete-file file)))
1387 (find-files (string-append out "/bin")
1388 "^idle"))
1389 (match (find-files out "^idlelib$"
1390 #:directories? #t)
1391 ((idlelib)
1392 (let* ((len (string-length out))
1393 (target (string-append idle "/"
1394 (string-drop
1395 idlelib len)
1396 "/site-packages")))
1397 (mkdir-p (dirname target))
1398 (rename-file idlelib target))))))))
1399 (add-after 'move-idle 'rebuild-bytecode
1400 (lambda* (#:key outputs #:allow-other-keys)
1401 (let ((out (assoc-ref outputs "out")))
1402 ;; Disable hash randomization to ensure the generated .pycs
1403 ;; are reproducible.
1404 (setenv "PYTHONHASHSEED" "0")
1405
1406 (for-each (lambda (output)
1407 ;; XXX: Delete existing pycs generated by the build
1408 ;; system beforehand because the -f argument does
1409 ;; not necessarily overwrite all files, leading to
1410 ;; indeterministic results.
1411 (for-each (lambda (pyc)
1412 (delete-file pyc))
1413 (find-files output "\\.pyc$"))
1414
1415 (apply invoke
1416 `(,#$(if (%current-target-system)
1417 "python3"
1418 #~(string-append
1419 out
1420 "/bin/python3")) "-m"
1421 "compileall"
1422 "-o"
1423 "0"
1424 "-o"
1425 "1"
1426 "-o"
1427 "2"
1428 "-f" ;force rebuild
1429 "--invalidation-mode=unchecked-hash"
1430 ;; Don't build lib2to3, because it's
1431 ;; Python 2 code.
1432 "-x"
1433 "lib2to3/.*"
1434 ,output)))
1435 (map cdr outputs)))))
1436 (add-before 'check 'set-TZDIR
1437 (lambda* (#:key inputs native-inputs #:allow-other-keys)
1438 ;; test_email requires the Olson time zone database.
1439 (setenv "TZDIR"
1440 (string-append (assoc-ref (or native-inputs
1441 inputs) "tzdata")
1442 "/share/zoneinfo"))))
1443 (add-after 'install 'install-sitecustomize.py 1063 (add-after 'install 'install-sitecustomize.py
1444 #$(customize-site version))))) 1064 #$(customize-site version)))))
1445 (inputs (list bzip2 1065 (inputs (list bzip2