(use-modules (guix packages)
(guix download)
(guix build-system)
(guix utils)
((guix licenses) #:prefix license:)
(guix transformations)
(gnu packages base)
(gnu packages check)
(gnu packages compression)
(gnu packages dbm)
(gnu packages libffi)
(gnu packages machine-learning)
(gnu packages python)
(gnu packages python-science)
(gnu packages python-xyz)
(gnu packages pkg-config)
(gnu packages readline)
(gnu packages sqlite)
(gnu packages tcl)
(gnu packages tls)
(gnu packages xml)
(guix build-system python)
(guix build-system pyproject)
(guix build-system gnu)
(srfi srfi-1))
(define-public python-3.8
(package
(name "python")
(version "3.8.5")
(source (origin
(method url-fetch)
(uri (string-append "https://www.python.org/ftp/python/"
version "/Python-" version ".tar.xz"))
(sha256
(base32
"1c43dbv9lvlp3ynqmgdi4rh8q94swanhqarqrdx62zmigpakw073"))
(modules '((guix build utils)))
(snippet
'(begin
(delete-file-recursively "Modules/expat")
(substitute* "Modules/Setup"
(("^#pyexpat.*") "pyexpat pyexpat.c -lexpat\n"))))))
(outputs '("out"
"tk")) (build-system gnu-build-system)
(arguments
`(#:test-target "test"
#:tests? #false #:configure-flags
(list "--enable-shared" "--with-system-expat" "--with-system-ffi" "--with-ensurepip=install" "--enable-unicode=ucs4"
"INSTALL=install -c"
"MKDIR_P=mkdir -p"
,@(if (%current-target-system)
'("ac_cv_buggy_getaddrinfo=no"
"ac_cv_file__dev_ptmx=no"
"ac_cv_file__dev_ptc=no")
'())
(string-append "LDFLAGS=-Wl,-rpath="
(assoc-ref %outputs "out") "/lib"))
#:make-flags
(list (string-append
(format #f "TESTOPTS=-j~d" (parallel-job-count))
" --exclude test_mmap"
" test_socket"
,@(if (target-hurd?)
'(" test_posix" " test_time"
" test_pty"
" test_shutil"
" test_tempfile" " test_asyncio" " test_os" " test_openpty" " test_selectors" " test_compileall" " test_poll" " test_subprocess" " test_asyncore" " test_threadsignals"
" test_eintr" " test_io" " test_logging"
" test_signal"
" test_threading" " test_flags" " test_bidirectional_pty"
" test_create_unix_connection"
" test_unix_sock_client_ops"
" test_open_unix_connection"
" test_open_unix_connection_error"
" test_read_pty_output"
" test_write_pty")
'())))
#:modules ((ice-9 ftw) (ice-9 match)
(guix build utils) (guix build gnu-build-system))
#:phases
(modify-phases %standard-phases
(add-before 'configure 'patch-lib-shells
(lambda _
,@(if (%current-target-system)
'((setenv "_PYTHON_HOST_PLATFORM" ""))
'())
(substitute* (filter file-exists?
'("Lib/subprocess.py"
"Lib/popen2.py"
"Lib/distutils/tests/test_spawn.py"
"Lib/test/support/__init__.py"
"Lib/test/test_subprocess.py"))
(("/bin/sh") (which "sh")))))
(add-before 'configure 'do-not-record-configure-flags
(lambda* (#:key configure-flags #:allow-other-keys)
(substitute* "configure"
(("^CONFIG_ARGS=.*$")
(format #f "CONFIG_ARGS='~a'\n"
(if (member "--with-system-ffi" configure-flags)
"--with-system-ffi"
""))))))
(add-before 'check 'pre-check
(lambda _
(setenv "HOME" (getcwd))))
(add-after 'unpack 'set-source-file-times-to-1980
(lambda _
(let ((circa-1980 (* 10 366 24 60 60)))
(ftw "." (lambda (file stat flag)
(utime file circa-1980 circa-1980)
#t)))))
(add-after 'install 'remove-tests
(lambda* (#:key outputs #:allow-other-keys)
(let ((out (assoc-ref outputs "out")))
(match (scandir (string-append out "/lib")
(lambda (name)
(string-prefix? "python" name)))
((pythonX.Y)
(let ((testdir (string-append out "/lib/" pythonX.Y
"/test")))
(with-directory-excursion testdir
(for-each delete-file-recursively
(scandir testdir
(match-lambda
((or "." "..") #f)
("support" #f)
(file
(not
(string-prefix? "test_support."
file))))))
(call-with-output-file "__init__.py" (const #t)))))))))
(add-before 'check 'set-TZDIR
(lambda* (#:key inputs native-inputs #:allow-other-keys)
(setenv "TZDIR"
(string-append (assoc-ref
(or native-inputs inputs) "tzdata")
"/share/zoneinfo"))))
(add-before 'check 'unset-SOURCE_DATE_EPOCH
(lambda _ (unsetenv "SOURCE_DATE_EPOCH")))
(add-after 'check 'reset-SOURCE_DATE_EPOCH
(lambda _ (setenv "SOURCE_DATE_EPOCH" "1")))
(add-after 'remove-tests 'rebuild-bytecode
(lambda* (#:key outputs #:allow-other-keys)
(let ((out (assoc-ref outputs "out")))
(setenv "PYTHONHASHSEED" "0")
(for-each
(lambda (opt)
(format #t "Compiling with optimization level: ~a\n"
(if (null? opt) "none" (car opt)))
(for-each (lambda (file)
(apply invoke
`(,,(if (%current-target-system)
"python3"
'(string-append out
"/bin/python3"))
,@opt
"-m" "compileall"
"-f" "-x" "lib2to3/.*"
,file)))
(find-files out "\\.py$")))
(list '() '("-O") '("-OO"))))))
(add-after 'install 'move-tk-inter
(lambda* (#:key outputs #:allow-other-keys)
(let ((out (assoc-ref outputs "out"))
(tk (assoc-ref outputs "tk")))
(when tk
(match (find-files out "tkinter.*\\.so")
((tkinter.so)
(let* ((len (string-length out))
(target (string-append
tk "/"
(string-drop
(dirname (dirname tkinter.so))
len)
"/site-packages")))
(install-file tkinter.so target)
(delete-file tkinter.so))))))))
(add-after 'install 'install-sitecustomize.py
,(customize-site version)))))
(inputs
(list bzip2
expat
gdbm
libffi sqlite openssl
readline
zlib
tcl
tk))
(native-inputs
`(("tzdata" ,tzdata-for-tests)
("pkg-config" ,pkg-config)
("sitecustomize.py" ,(local-file (search-auxiliary-file
"python/sitecustomize.py")))
,@(if (%current-target-system)
`(("python3" ,this-package)
("which" ,which))
'())))
(native-search-paths
(list (search-path-specification
(variable "GUIX_PYTHONPATH")
(files (list (string-append "lib/python"
(version-major+minor version)
"/site-packages"))))))
(home-page "https://www.python.org")
(synopsis "High-level, dynamically-typed programming language")
(description
"Python is a remarkably powerful dynamic programming language that
is used in a wide variety of application domains. Some of its key
distinguishing features include: clear, readable syntax; strong
introspection capabilities; intuitive object orientation; natural
expression of procedural code; full modularity, supporting hierarchical
packages; exception-based error handling; and very high level dynamic
data types.")
(properties '((cpe-name . "python")))
(license license:psfl)))
(define transform
(options->transformation
`((with-source . ,(string-append "python-coloredlogs=" (pypi-uri "coloredlogs" "14.0")))
(with-source . ,(string-append "python-coverage=" (pypi-uri "coverage" "5.3.1")))
(with-source . "python-numpy=https://github.com/numpy/numpy/releases/download/v1.19.0/numpy-1.19.0.tar.gz")
(with-source . ,(string-append "python-pandas=" (pypi-uri "pandas" "1.0.5")))
(with-source . ,(string-append "python-pdoc3=" (pypi-uri "pdoc3" "0.9.1")))
(with-source . ,(string-append "python-scikit-learn=" (pypi-uri "scikit-learn" "0.23.1")))
(with-source . ,(string-append "python-pytest=" (pypi-uri "pytest" "5.4.3")))
(with-source . ,(string-append "python-pytest-cov=" (pypi-uri "pytest-cov" "2.10.1")))
(with-source . ,(string-append "python-pytest-asyncio=" (pypi-uri "pytest-asyncio" "0.14.0")))
(without-tests . "python-coloredlogs")
(without-tests . "python-coverage")
(without-tests . "python-numpy")
(without-tests . "python-pandas")
(without-tests . "python-pdoc3")
(without-tests . "python-scikit-learn")
(without-tests . "python-pytest")
(without-tests . "python-pytest-cov")
(without-tests . "python-pytest-asyncio")
)))
(define* (package-with-explicit-python python old-prefix new-prefix)
"Return a procedure of one argument, P. The procedure creates a package with
the same fields as P, which is assumed to use PYTHON-BUILD-SYSTEM, such that
it is compiled with PYTHON instead. The inputs are changed recursively
accordingly. If the name of P starts with OLD-PREFIX, this is replaced by
NEW-PREFIX; otherwise, NEW-PREFIX is prepended to the name."
(define (transform p)
(cond
((or (eq? (package-build-system p) python-build-system)
(eq? (package-build-system p) pyproject-build-system))
(package/inherit p
(location (package-location p))
(name (let ((name (package-name p)))
(if (string-prefix? old-prefix name)
(string-append new-prefix
(substring name (string-length old-prefix)))
name)))
(arguments
(let ((python (if (promise? python)
(force python)
python)))
(ensure-keyword-arguments (package-arguments p)
`(#:python ,python))))))
(else p)))
(define (cut? p)
(let ((stop?
(or (not (member (build-system-name (package-build-system p))
'(python pyproject)))
(member (package-name p)
(list "python" "inkscape")
string=?))))
(unless stop?
(pk 'will-build (package-name p) (package-build-system p)))
stop?))
(package-mapping transform cut?))
(define python38-package
(package-with-explicit-python python-3.8 "python-" "python38-"))
(packages->manifest
(map (compose transform python38-package)
(list
python-coloredlogs
python-coverage
python-numpy
python-pandas
python-pdoc3
python-scikit-learn
python-pytest
python-pytest-cov)))