From ea0fafb7c714f537f8d2d8a8b5bcb793b9af8bee Mon Sep 17 00:00:00 2001 From: OscarL Date: Thu, 8 May 2025 07:40:26 +0000 Subject: [PATCH] python3.14: new recipe. (#11298) * python3.14: new recipe. First alpha release. Final 3.14.0 version expected next year. Only tested unoptimized 64 bits builds so far. * python3.14: update to alpha2. Works on 32 bits now! * python3.14: update to alpha3. * python3.14: update to alpha4. Removed patch for `config.guess`, as it is now not needed. * python3.14: update to alpha5. * python3.14: make sure 'spawn' is used and not 'forkserver'. * python3.14: update to alpha6. * python3.14: update to alpha7. * python3.14: update to 3.14.0 beta1. --- .../patches/python3.14-3.14.0~b1.patchset | 1142 +++++++++++++++++ dev-lang/python/python3.14-3.14.0~b1.recipe | 469 +++++++ 2 files changed, 1611 insertions(+) create mode 100644 dev-lang/python/patches/python3.14-3.14.0~b1.patchset create mode 100644 dev-lang/python/python3.14-3.14.0~b1.recipe diff --git a/dev-lang/python/patches/python3.14-3.14.0~b1.patchset b/dev-lang/python/patches/python3.14-3.14.0~b1.patchset new file mode 100644 index 000000000..e37bf10d9 --- /dev/null +++ b/dev-lang/python/patches/python3.14-3.14.0~b1.patchset @@ -0,0 +1,1142 @@ +From 842faa1e37d23baf52de92c44c67268d7fe10102 Mon Sep 17 00:00:00 2001 +From: Oscar Lesta +Date: Sun, 8 Oct 2023 01:02:25 -0300 +Subject: initial Haiku patch + +Based on the patch from Jerome Duval, modified to make it apply cleanly +over 3.12's sources. + +Parts of that original patch were split into specific commit/patches. + +diff --git a/Include/pyport.h b/Include/pyport.h +index 3eac119..1e5df7e 100644 +--- a/Include/pyport.h ++++ b/Include/pyport.h +@@ -535,7 +535,7 @@ extern "C" { + # define _Py_FORCE_UTF8_LOCALE + #endif + +-#if defined(_Py_FORCE_UTF8_LOCALE) || defined(__APPLE__) ++#if defined(_Py_FORCE_UTF8_LOCALE) || defined(__APPLE__) || defined(__HAIKU__) + // Use UTF-8 as the filesystem encoding. + // See PyUnicode_DecodeFSDefaultAndSize(), PyUnicode_EncodeFSDefault(), + // Py_DecodeLocale() and Py_EncodeLocale(). +diff --git a/Makefile.pre.in b/Makefile.pre.in +index 17e0c99..87b9c15 100644 +--- a/Makefile.pre.in ++++ b/Makefile.pre.in +@@ -156,7 +156,7 @@ BINDIR= @bindir@ + LIBDIR= @libdir@ + MANDIR= @mandir@ + INCLUDEDIR= @includedir@ +-CONFINCLUDEDIR= $(exec_prefix)/include ++CONFINCLUDEDIR= $(INCLUDEDIR) + PLATLIBDIR= @PLATLIBDIR@ + SCRIPTDIR= $(prefix)/$(PLATLIBDIR) + # executable name for shebangs +diff --git a/Modules/resource.c b/Modules/resource.c +index 3fe18e7..d0e1872 100644 +--- a/Modules/resource.c ++++ b/Modules/resource.c +@@ -126,6 +126,7 @@ resource_getrusage_impl(PyObject *module, int who) + PyFloat_FromDouble(doubletime(ru.ru_utime))); + PyStructSequence_SetItem(result, 1, + PyFloat_FromDouble(doubletime(ru.ru_stime))); ++#ifndef __HAIKU__ + PyStructSequence_SetItem(result, 2, PyLong_FromLong(ru.ru_maxrss)); + PyStructSequence_SetItem(result, 3, PyLong_FromLong(ru.ru_ixrss)); + PyStructSequence_SetItem(result, 4, PyLong_FromLong(ru.ru_idrss)); +@@ -140,6 +141,22 @@ resource_getrusage_impl(PyObject *module, int who) + PyStructSequence_SetItem(result, 13, PyLong_FromLong(ru.ru_nsignals)); + PyStructSequence_SetItem(result, 14, PyLong_FromLong(ru.ru_nvcsw)); + PyStructSequence_SetItem(result, 15, PyLong_FromLong(ru.ru_nivcsw)); ++#else ++ PyStructSequence_SetItem(result, 2, PyLong_FromLong(0)); ++ PyStructSequence_SetItem(result, 3, PyLong_FromLong(0)); ++ PyStructSequence_SetItem(result, 4, PyLong_FromLong(0)); ++ PyStructSequence_SetItem(result, 5, PyLong_FromLong(0)); ++ PyStructSequence_SetItem(result, 6, PyLong_FromLong(0)); ++ PyStructSequence_SetItem(result, 7, PyLong_FromLong(0)); ++ PyStructSequence_SetItem(result, 8, PyLong_FromLong(0)); ++ PyStructSequence_SetItem(result, 9, PyLong_FromLong(0)); ++ PyStructSequence_SetItem(result, 10, PyLong_FromLong(0)); ++ PyStructSequence_SetItem(result, 11, PyLong_FromLong(0)); ++ PyStructSequence_SetItem(result, 12, PyLong_FromLong(0)); ++ PyStructSequence_SetItem(result, 13, PyLong_FromLong(0)); ++ PyStructSequence_SetItem(result, 14, PyLong_FromLong(0)); ++ PyStructSequence_SetItem(result, 15, PyLong_FromLong(0)); ++#endif + + if (PyErr_Occurred()) { + Py_DECREF(result); +@@ -387,19 +404,19 @@ resource_exec(PyObject *module) + } + + /* insert constants */ +-#ifdef RLIMIT_CPU ++#if !defined(__HAIKU__) && defined(RLIMIT_CPU) + ADD_INT(module, RLIMIT_CPU); + #endif + +-#ifdef RLIMIT_FSIZE ++#if !defined(__HAIKU__) && defined(RLIMIT_FSIZE) + ADD_INT(module, RLIMIT_FSIZE); + #endif + +-#ifdef RLIMIT_DATA ++#if !defined(__HAIKU__) && defined(RLIMIT_DATA) + ADD_INT(module, RLIMIT_DATA); + #endif + +-#ifdef RLIMIT_STACK ++#if !defined(__HAIKU__) && defined(RLIMIT_STACK) + ADD_INT(module, RLIMIT_STACK); + #endif + +@@ -411,31 +428,31 @@ resource_exec(PyObject *module) + ADD_INT(module, RLIMIT_NOFILE); + #endif + +-#ifdef RLIMIT_OFILE ++#if !defined(__HAIKU__) && defined(RLIMIT_OFILE) + ADD_INT(module, RLIMIT_OFILE); + #endif + +-#ifdef RLIMIT_VMEM ++#if !defined(__HAIKU__) && defined(RLIMIT_VMEM) + ADD_INT(module, RLIMIT_VMEM); + #endif + +-#ifdef RLIMIT_AS ++#if !defined(__HAIKU__) && defined(RLIMIT_AS) + ADD_INT(module, RLIMIT_AS); + #endif + +-#ifdef RLIMIT_RSS ++#if !defined(__HAIKU__) && defined(RLIMIT_RSS) + ADD_INT(module, RLIMIT_RSS); + #endif + +-#ifdef RLIMIT_NPROC ++#if !defined(__HAIKU__) && defined(RLIMIT_NPROC) + ADD_INT(module, RLIMIT_NPROC); + #endif + +-#ifdef RLIMIT_MEMLOCK ++#if !defined(__HAIKU__) && defined(RLIMIT_MEMLOCK) + ADD_INT(module, RLIMIT_MEMLOCK); + #endif + +-#ifdef RLIMIT_SBSIZE ++#if !defined(__HAIKU__) && defined(RLIMIT_SBSIZE) + ADD_INT(module, RLIMIT_SBSIZE); + #endif + +diff --git a/Modules/socketmodule.h b/Modules/socketmodule.h +index 63624d5..3692640 100644 +--- a/Modules/socketmodule.h ++++ b/Modules/socketmodule.h +@@ -113,6 +113,10 @@ typedef int socklen_t; + # undef AF_QIPCRTR + #endif + ++#if defined(__HAIKU__) ++#undef HAVE_BLUETOOTH_BLUETOOTH_H ++#endif ++ + #ifdef HAVE_BLUETOOTH_BLUETOOTH_H + #include + #include +diff --git a/configure.ac b/configure.ac +index a7b2f62..2579824 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1584,6 +1584,16 @@ if test $enable_shared = "yes"; then + PY3LIBRARY=libpython3.so + fi + ;; ++ Haiku*) ++ LDLIBRARY='libpython$(LDVERSION).so' ++ BLDLIBRARY='-L. -lpython$(LDVERSION)' ++ RUNSHARED=LIBRARY_PATH=`pwd`${LIBRARY_PATH:+:${LIBRARY_PATH}} ++ INSTSONAME="$LDLIBRARY".$SOVERSION ++ if test "$with_pydebug" != yes ++ then ++ PY3LIBRARY=libpython3.so ++ fi ++ ;; + hp*|HP*) + case `uname -m` in + ia64) +@@ -1701,6 +1711,7 @@ AC_PROG_MKDIR_P + AC_SUBST([LN]) + if test -z "$LN" ; then + case $ac_sys_system in ++ Haiku*) LN="ln -s";; + CYGWIN*) LN="ln -s";; + *) LN=ln;; + esac +@@ -3592,7 +3603,7 @@ then + LINKFORSHARED="-Wl,-E -Wl,+s";; + # LINKFORSHARED="-Wl,-E -Wl,+s -Wl,+b\$(BINLIBDEST)/lib-dynload";; + Linux-android*) LINKFORSHARED="-pie -Xlinker -export-dynamic";; +- Linux*|GNU*) LINKFORSHARED="-Xlinker -export-dynamic";; ++ Linux*|GNU*|Haiku*) LINKFORSHARED="-Xlinker -export-dynamic";; + # -u libsys_s pulls in all symbols in libsys + Darwin/*|iOS/*) + LINKFORSHARED="$extra_undefs -framework CoreFoundation" +@@ -5856,6 +5867,7 @@ AC_CHECK_FUNC([__fpu_control], + AC_SUBST([LIBM]) + case $ac_sys_system in + Darwin) ;; ++Haiku) ;; + *) LIBM=-lm + esac + AC_MSG_CHECKING([for --with-libm=STRING]) +-- +2.48.1 + + +From 345d40b40d53beff9c406ce45a7058b9a8d82180 Mon Sep 17 00:00:00 2001 +From: Jerome Duval +Date: Sun, 16 Apr 2017 10:05:42 +0200 +Subject: fix for negative errnos + + +diff --git a/Lib/subprocess.py b/Lib/subprocess.py +index 54c2eb5..1fa840e 100644 +--- a/Lib/subprocess.py ++++ b/Lib/subprocess.py +@@ -1955,6 +1955,8 @@ class Popen: + SubprocessError) + if issubclass(child_exception_type, OSError) and hex_errno: + errno_num = int(hex_errno, 16) ++ if sys.platform.startswith('haiku'): ++ errno_num = -errno_num; + if err_msg == "noexec:chdir": + err_msg = "" + # The error must be from chdir(cwd). +diff --git a/Modules/_posixsubprocess.c b/Modules/_posixsubprocess.c +index b542f86..a996ebf 100644 +--- a/Modules/_posixsubprocess.c ++++ b/Modules/_posixsubprocess.c +@@ -843,6 +843,10 @@ error: + char *cur; + _Py_write_noraise(errpipe_write, "OSError:", 8); + cur = hex_errno + sizeof(hex_errno); ++#ifdef __HAIKU__ ++ if (saved_errno < 0) ++ saved_errno = -saved_errno; ++#endif + while (saved_errno != 0 && cur != hex_errno) { + *--cur = Py_hexdigits[saved_errno % 16]; + saved_errno /= 16; +-- +2.48.1 + + +From c8f81ae70b94579c266b27c69a227ec6149edf1a Mon Sep 17 00:00:00 2001 +From: Oscar Lesta +Date: Sun, 8 Oct 2023 20:06:31 -0300 +Subject: Implement CTypes's find_library for Haiku + +This combines: + - the original patch by Philippe Houdoin + - A slight variation of Adrien Destugues' fix for x86_gcc2. + +diff --git a/Lib/ctypes/util.py b/Lib/ctypes/util.py +index 9950491..fefae29 100644 +--- a/Lib/ctypes/util.py ++++ b/Lib/ctypes/util.py +@@ -1,4 +1,5 @@ + import os ++import platform + import shutil + import subprocess + import sys +@@ -352,6 +353,60 @@ elif os.name == "posix": + def find_library(name, is64 = False): + return _get_soname(_findLib_crle(name, is64) or _findLib_gcc(name)) + ++ elif sys.platform.startswith("haiku"): ++ ++ def _num_version(libname): ++ # "libxyz.so.MAJOR.MINOR" => [ MAJOR, MINOR ] ++ parts = libname.split('.') ++ nums = [] ++ try: ++ while parts: ++ nums.insert(0, int(parts.pop())) ++ except ValueError: ++ pass ++ return nums or [sys.maxint] ++ ++ def find_library(name): ++ if name in ('c', 'm'): ++ return find_library('root') ++ for directory in os.environ['LIBRARY_PATH'].split(os.pathsep): ++ if directory.startswith("%A/"): ++ directory = directory.replace('%A', ++ os.path.dirname(os.path.abspath(sys.argv[0] or os.getcwd()))) ++ ++ # Are we on x86 32 bits?: ++ if platform.machine() == 'BePC': ++ directory = os.path.join(directory, "x86") ++ ++ if not os.path.isdir(directory): ++ continue ++ ++ # try direct match ++ fname = os.path.join(directory, name) ++ if os.path.isfile(fname): ++ return fname ++ ++ fname = os.path.join(directory, 'lib%s.so' % name) ++ if os.path.isfile(fname): ++ return fname ++ ++ # no exact matching in this directroy ++ # collect versioned candidates, if any ++ candidates = [] ++ pattern = re.compile(r'lib%s\.so\.\S+' % re.escape(name)) ++ for entry in os.listdir(directory): ++ if not os.path.isfile(os.path.join(directory, entry)): ++ continue ++ ++ if re.match(pattern, entry): ++ candidates.append(os.path.join(directory, entry)) ++ ++ if candidates: ++ # return latest version found ++ candidates.sort(key=_num_version) ++ return candidates[-1] ++ ++ return None + else: + + def _findSoname_ldconfig(name): +@@ -503,6 +558,12 @@ def test(): + print(f"crypt\t:: {cdll.LoadLibrary(find_library('crypt'))}") + print(f"crypto\t:: {find_library('crypto')}") + print(f"crypto\t:: {cdll.LoadLibrary(find_library('crypto'))}") ++ elif sys.platform.startswith("haiku"): ++ print(find_library("libbz2.so.1.0")) ++ print(find_library("tracker")) ++ print(find_library("media")) ++ print(cdll.LoadLibrary(find_library("tracker"))) ++ print(cdll.LoadLibrary("libmedia.so")) + else: + print(cdll.LoadLibrary("libm.so")) + print(cdll.LoadLibrary("libcrypt.so")) +-- +2.48.1 + + +From 1b9110b05fad43f085c2af75669365d5c509663b Mon Sep 17 00:00:00 2001 +From: Philipp Wolfer +Date: Mon, 23 Sep 2019 09:14:58 +0200 +Subject: webbrowser: Support for default browsers on Haiku + + +diff --git a/Lib/webbrowser.py b/Lib/webbrowser.py +index f2e2394..b937321 100644 +--- a/Lib/webbrowser.py ++++ b/Lib/webbrowser.py +@@ -495,6 +495,12 @@ def register_standard_browsers(): + # SerenityOS webbrowser, simply called "Browser". + register("Browser", None, BackgroundBrowser("Browser")) + ++ if sys.platform[:5] == "haiku": ++ # First try to use the default configured browser ++ register("haiku-default", None, GenericBrowser("open")) ++ # Fall back to WebPositive as the standard browser of Haiku ++ register("webpositive", None, BackgroundBrowser("WebPositive")) ++ + if sys.platform[:3] == "win": + # First try to use the default Windows browser + register("windows-default", WindowsDefault) +-- +2.48.1 + + +From 2e81cbfefa905692e6cae8ecedfe54c5ea50ff9b Mon Sep 17 00:00:00 2001 +From: Jerome Duval +Date: Fri, 4 Oct 2019 22:02:35 +0200 +Subject: since 3.8, don't reinit locks on fork. + + +diff --git a/Lib/logging/__init__.py b/Lib/logging/__init__.py +index aa9b79d..b99e1e0 100644 +--- a/Lib/logging/__init__.py ++++ b/Lib/logging/__init__.py +@@ -253,7 +253,7 @@ def _afterFork(): + + # Prevent a held logging lock from blocking a child from logging. + +-if not hasattr(os, 'register_at_fork'): # Windows and friends. ++if sys.platform.startswith('haiku') or not hasattr(os, 'register_at_fork'): # Windows and friends. + def _register_at_fork_reinit_lock(instance): + pass # no-op when os.register_at_fork does not exist. + else: +-- +2.48.1 + + +From ef1e9f0006c624d6b6bbf4613c8a9d86e53d35ff Mon Sep 17 00:00:00 2001 +From: Jerome Duval +Date: Fri, 15 May 2020 15:20:57 +0200 +Subject: handle errors returned by internal_connect() + +upstream bug #40628 by Ryan C. Gordon + +diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c +index 4795837..5483752 100644 +--- a/Modules/socketmodule.c ++++ b/Modules/socketmodule.c +@@ -3741,7 +3741,7 @@ sock_connect(PyObject *self, PyObject *addro) + } + + res = internal_connect(s, SAS2SA(&addrbuf), addrlen, 1); +- if (res < 0) { ++ if (res == -1) { + assert(PyErr_Occurred()); + return NULL; + } +-- +2.48.1 + + +From 90979d230221e131a9d799a9075796f96c8050bb Mon Sep 17 00:00:00 2001 +From: Jerome Duval +Date: Mon, 19 Oct 2020 18:03:09 +0200 +Subject: ttyname_r can use MAXPATHLEN + + +diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c +index 922694f..93a2658 100644 +--- a/Modules/posixmodule.c ++++ b/Modules/posixmodule.c +@@ -3420,11 +3420,14 @@ static PyObject * + os_ttyname_impl(PyObject *module, int fd) + /*[clinic end generated code: output=c424d2e9d1cd636a input=9ff5a58b08115c55]*/ + { +- ++#ifndef __HAIKU__ + long size = sysconf(_SC_TTY_NAME_MAX); + if (size == -1) { + return posix_error(); + } ++#else ++ long size = MAXPATHLEN; ++#endif + char *buffer = (char *)PyMem_RawMalloc(size); + if (buffer == NULL) { + return PyErr_NoMemory(); +-- +2.48.1 + + +From ad0a0f5693982d150ebe05e3132c7021c191a41b Mon Sep 17 00:00:00 2001 +From: Oscar Lesta +Date: Mon, 24 Oct 2022 20:04:10 -0300 +Subject: Lib/test: require the "largefile" usage flag for I/O heavy tests. + +The same is done for Windows and macOS already. + +This avoids needing several GBs of storage to run the tests +(unless the "largefile" resource usage flag is enabled). + +diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py +index 5a8f194..5452192 100644 +--- a/Lib/test/test_io.py ++++ b/Lib/test/test_io.py +@@ -652,7 +652,7 @@ class IOTest(unittest.TestCase): + # On Windows and Apple platforms this test consumes large resources; It + # takes a long time to build the >2 GiB file and takes >2 GiB of disk + # space therefore the resource must be enabled to run this test. +- if sys.platform[:3] == 'win' or is_apple: ++ if sys.platform[:3] == 'win' or is_apple or sys.platform[:5] == 'haiku': + support.requires( + 'largefile', + 'test requires %s bytes and a long time to run' % self.LARGE) +diff --git a/Lib/test/test_largefile.py b/Lib/test/test_largefile.py +index 41f7b70..e4830de 100644 +--- a/Lib/test/test_largefile.py ++++ b/Lib/test/test_largefile.py +@@ -273,7 +273,7 @@ def setUpModule(): + # takes a long time to build the >2 GiB file and takes >2 GiB of disk + # space therefore the resource must be enabled to run this test. + # If not, nothing after this line stanza will be executed. +- if sys.platform[:3] == 'win' or sys.platform == 'darwin': ++ if sys.platform[:3] == 'win' or sys.platform == 'darwin' or sys.platform[:5] == 'haiku': + requires('largefile', + 'test requires %s bytes and a long time to run' % str(size)) + else: +diff --git a/Lib/test/test_mmap.py b/Lib/test/test_mmap.py +index fd4197b..662954d 100644 +--- a/Lib/test/test_mmap.py ++++ b/Lib/test/test_mmap.py +@@ -1146,7 +1146,7 @@ class LargeMmapTests(unittest.TestCase): + unlink(TESTFN) + + def _make_test_file(self, num_zeroes, tail): +- if sys.platform[:3] == 'win' or is_apple: ++ if sys.platform[:3] == 'win' or is_apple or sys.platform[:5] == 'haiku': + requires('largefile', + 'test requires %s bytes and a long time to run' % str(0x180000000)) + f = open(TESTFN, 'w+b') +-- +2.48.1 + + +From 15f9a4b465dd6b872d71297a34bda0769cb21ee2 Mon Sep 17 00:00:00 2001 +From: Oscar Lesta +Date: Sat, 27 Jul 2024 04:51:52 -0300 +Subject: _getuserbase(), getsitepackages(), and INSTALL_SCHEMES for Haiku. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This combines (at least parts of) previous "commits" on older ".patchset"s: + +* Initial Haiku patch. +* default schemes for Haiku + +from Jérôme Duval + +* syncronize both _getuserbase() copies on site.py and sysconfig.py. +* Add missing 'platinclude' to sysconfig's _INSTALL_SCHEMES. +* Adjust test_sysconfig.test_get_scheme_names for Haiku. + +by me, plus: + +* new changes to allow Python to find modules installed via 'pkgman -H'. +* Attempt to support the "venv" install scheme (untested). + +The idea was to have all _getuserbase()/INSTALL_SCHEMES related changes in "one place". + +diff --git a/Lib/site.py b/Lib/site.py +index 5c38b1b..f0f5ba5 100644 +--- a/Lib/site.py ++++ b/Lib/site.py +@@ -312,6 +312,14 @@ def _getuserbase(): + return joinuser("~", "Library", sys._framework, + "%d.%d" % sys.version_info[:2]) + ++ if sys.platform.startswith('haiku'): ++ try: ++ import subprocess ++ return subprocess.check_output( ++ ['finddir', 'B_USER_NONPACKAGED_DIRECTORY']).rstrip().decode('utf-8') ++ except: ++ pass ++ + return joinuser("~", ".local") + + +@@ -404,7 +412,31 @@ def getsitepackages(prefixes=None): + abi_thread = 't' + else: + abi_thread = '' +- if os.sep == '/': ++ if sys.platform.startswith('haiku'): ++ # Locations under /system/ ++ sitepackages.append(os.path.join(prefix, "non-packaged", "lib", ++ f"{implementation}{ver[0]}.{ver[1]}{abi_thread}", ++ "site-packages")) ++ sitepackages.append(os.path.join(prefix, "lib", ++ f"{implementation}{ver[0]}.{ver[1]}{abi_thread}", ++ "vendor-packages")) ++ ++ # For .hpkg installed under ~/config/ (pkgman install -H) ++ # ("pip install --user" uses ~/config/non-packaged/, and gets ++ # handled by the "haiku_user" install scheme. ++ try: ++ import subprocess ++ _home_prefix = subprocess.check_output( ++ ['finddir', 'B_USER_CONFIG_DIRECTORY']).rstrip().decode('utf-8') ++ except: ++ # print("'finddir B_USER_CONFIG_DIRECTORY' failed.") ++ _home_prefix = None ++ ++ if _home_prefix is not None: ++ sitepackages.append(os.path.join(_home_prefix, "lib", ++ f"{implementation}{ver[0]}.{ver[1]}{abi_thread}", ++ "vendor-packages")) ++ elif os.sep == '/': + libdirs = [sys.platlibdir] + if sys.platlibdir != "lib": + libdirs.append("lib") +diff --git a/Lib/sysconfig/__init__.py b/Lib/sysconfig/__init__.py +index dad715e..c573614 100644 +--- a/Lib/sysconfig/__init__.py ++++ b/Lib/sysconfig/__init__.py +@@ -48,6 +48,36 @@ _INSTALL_SCHEMES = { + 'scripts': '{base}/bin', + 'data': '{base}', + }, ++ 'haiku': { ++ 'stdlib': '{installed_base}/lib/python{py_version_short}{abi_thread}', ++ 'platstdlib': '{platbase}/lib/python{py_version_short}{abi_thread}', ++ 'purelib': '{base}/non-packaged/lib/python{py_version_short}{abi_thread}/site-packages', ++ 'platlib': '{platbase}/non-packaged/lib/python{py_version_short}{abi_thread}/site-packages', ++ 'include': '{installed_base}/non-packaged/develop/headers/python{py_version_short}{abiflags}', ++ 'platinclude': '{installed_platbase}/develop/headers/python{py_version_short}{abiflags}', ++ 'scripts': '{base}/non-packaged/bin', ++ 'data' : '{base}/non-packaged', ++ }, ++ 'haiku_vendor': { ++ 'stdlib': '{installed_base}/lib/python{py_version_short}{abi_thread}', ++ 'platstdlib': '{platbase}/lib/python{py_version_short}{abi_thread}', ++ 'purelib': '{base}/lib/python{py_version_short}{abi_thread}/vendor-packages', ++ 'platlib': '{platbase}/lib/python{py_version_short}{abi_thread}/vendor-packages', ++ 'include': '{installed_base}/develop/headers/python{py_version_short}{abiflags}', ++ 'platinclude': '{installed_platbase}/develop/headers/python{py_version_short}{abiflags}', ++ 'scripts': '{base}/bin', ++ 'data' : '{base}', ++ }, ++ 'haiku_home': { ++ 'stdlib': '{installed_base}/lib/python{py_version_short}', ++ 'platstdlib': '{base}/lib/python{py_version_short}', ++ 'purelib': '{base}/lib/python{py_version_short}', ++ 'platlib': '{base}/lib/python{py_version_short}', ++ 'include': '{installed_base}/develop/headers/python{py_version_short}', ++ 'platinclude': '{installed_base}/develop/headers/python{py_version_short}', ++ 'scripts': '{base}/bin', ++ 'data': '{base}', ++ }, + 'nt': { + 'stdlib': '{installed_base}/Lib', + 'platstdlib': '{base}/Lib', +@@ -88,6 +118,16 @@ _INSTALL_SCHEMES = { + 'scripts': '{base}/bin', + 'data': '{base}', + }, ++ 'haiku_venv': { ++ 'stdlib': '{installed_base}/lib/python{py_version_short}{abi_thread}', ++ 'platstdlib': '{platbase}/lib/python{py_version_short}{abi_thread}', ++ 'purelib': '{base}/non-packaged/lib/python{py_version_short}{abi_thread}/site-packages', ++ 'platlib': '{platbase}/non-packaged/lib/python{py_version_short}{abi_thread}/site-packages', ++ 'include': '{installed_base}/non-packaged/develop/headers/python{py_version_short}{abiflags}', ++ 'platinclude': '{installed_platbase}/develop/headers/python{py_version_short}{abiflags}', ++ 'scripts': '{base}/non-packaged/bin', ++ 'data' : '{base}/non-packaged', ++ }, + 'nt_venv': { + 'stdlib': '{installed_base}/Lib', + 'platstdlib': '{base}/Lib', +@@ -103,6 +143,8 @@ _INSTALL_SCHEMES = { + # For the OS-native venv scheme, we essentially provide an alias: + if os.name == 'nt': + _INSTALL_SCHEMES['venv'] = _INSTALL_SCHEMES['nt_venv'] ++elif sys.platform.startswith('haiku'): ++ _INSTALL_SCHEMES['venv'] = _INSTALL_SCHEMES['haiku_venv'] + else: + _INSTALL_SCHEMES['venv'] = _INSTALL_SCHEMES['posix_venv'] + +@@ -133,6 +175,14 @@ def _getuserbase(): + return joinuser("~", "Library", sys._framework, + f"{sys.version_info[0]}.{sys.version_info[1]}") + ++ if sys.platform.startswith('haiku'): ++ try: ++ import subprocess ++ return subprocess.check_output( ++ ['finddir', 'B_USER_NONPACKAGED_DIRECTORY']).rstrip().decode('utf-8') ++ except: ++ pass ++ + return joinuser("~", ".local") + + _HAS_USER_BASE = (_getuserbase() is not None) +@@ -158,6 +208,15 @@ if _HAS_USER_BASE: + 'scripts': '{userbase}/bin', + 'data': '{userbase}', + }, ++ 'haiku_user': { ++ 'stdlib': '{userbase}/lib/python{py_version_short}{abi_thread}', ++ 'platstdlib': '{userbase}/lib/python{py_version_short}{abi_thread}', ++ 'purelib': '{userbase}/lib/python{py_version_short}{abi_thread}/site-packages', ++ 'platlib': '{userbase}/lib/python{py_version_short}{abi_thread}/site-packages', ++ 'include': '{userbase}/develop/headers/python{py_version_short}{abi_thread}', ++ 'scripts': '{userbase}/bin', ++ 'data': '{userbase}', ++ }, + 'osx_framework_user': { + 'stdlib': '{userbase}/lib/{implementation_lower}', + 'platstdlib': '{userbase}/lib/{implementation_lower}', +@@ -287,6 +346,18 @@ def _expand_vars(scheme, vars): + + + def _get_preferred_schemes(): ++ if sys.platform.startswith('haiku'): ++ if os.environ.get('HAIKU_USE_VENDOR_DIRECTORIES') == '1': ++ return { ++ 'prefix': 'haiku_vendor', ++ 'home': 'haiku_home', ++ 'user': 'haiku_user', ++ } ++ return { ++ 'prefix': 'haiku', ++ 'home': 'haiku_home', ++ 'user': 'haiku_user', ++ } + if os.name == 'nt': + return { + 'prefix': 'nt', +diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py +index 53e5538..36c9cfb 100644 +--- a/Lib/test/test_sysconfig.py ++++ b/Lib/test/test_sysconfig.py +@@ -388,9 +388,10 @@ class TestSysConfig(unittest.TestCase, VirtualEnvironmentMixin): + self.assertTrue(os.path.isfile(config_h), config_h) + + def test_get_scheme_names(self): +- wanted = ['nt', 'posix_home', 'posix_prefix', 'posix_venv', 'nt_venv', 'venv'] ++ wanted = ['nt', 'posix_home', 'posix_prefix', 'posix_venv', 'nt_venv', 'venv', 'haiku', ++ 'haiku_home', 'haiku_vendor'] + if HAS_USER_BASE: +- wanted.extend(['nt_user', 'osx_framework_user', 'posix_user']) ++ wanted.extend(['nt_user', 'osx_framework_user', 'posix_user', 'haiku_user']) + self.assertEqual(get_scheme_names(), tuple(sorted(wanted))) + + @skip_unless_symlink +-- +2.48.1 + + +From 3b782c4a49c7c3338f726ad8eee0425f673e8ef7 Mon Sep 17 00:00:00 2001 +From: Oscar Lesta +Date: Mon, 12 Feb 2024 08:39:38 -0300 +Subject: Fix location of REPL's history file. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Adapted from previous patches by Jérôme Duval. + +diff --git a/Lib/site.py b/Lib/site.py +index f0f5ba5..eeb34ea 100644 +--- a/Lib/site.py ++++ b/Lib/site.py +@@ -511,8 +511,18 @@ def gethistoryfile(): + history = os.environ.get("PYTHON_HISTORY") + if history: + return history +- return os.path.join(os.path.expanduser('~'), +- '.python_history') ++ ++ import subprocess ++ try: ++ history = os.path.join(subprocess.check_output( ++ ['finddir', 'B_USER_VAR_DIRECTORY']).rstrip().decode('utf-8'), ++ 'python', 'history') ++ if not os.path.exists(os.path.dirname(history)): ++ os.makedirs(os.path.dirname(history)) ++ except subprocess.CalledProcessError: ++ history = os.path.join(os.path.expanduser('~'), '.python_history') ++ ++ return history + + + def enablerlcompleter(): +-- +2.48.1 + + +From 5a3089a0bcb8a2ed6b3989408cec4e873768bd24 Mon Sep 17 00:00:00 2001 +From: Oscar Lesta +Date: Sun, 10 Dec 2023 19:50:22 -0300 +Subject: Miscellaneous "Lib/test/" fixes for Haiku. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +test_fileio.py fix from "initial Haiku patch" by Jérôme Duval. + +diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py +index 55844ec..61aeb3f 100644 +--- a/Lib/test/datetimetester.py ++++ b/Lib/test/datetimetester.py +@@ -6403,6 +6403,9 @@ def pairs(iterable): + + class ZoneInfo(tzinfo): + zoneroot = '/usr/share/zoneinfo' ++ if sys.platform.startswith('haiku'): ++ zoneroot = '/system/data/zoneinfo' ++ + def __init__(self, ut, ti): + """ + +diff --git a/Lib/test/test_fileio.py b/Lib/test/test_fileio.py +index 5a0f033..8e85ed4 100644 +--- a/Lib/test/test_fileio.py ++++ b/Lib/test/test_fileio.py +@@ -544,6 +544,7 @@ class OtherFileTests: + self.assertEqual(f.writable(), True) + if sys.platform != "darwin" and \ + 'bsd' not in sys.platform and \ ++ 'haiku' not in sys.platform and \ + not sys.platform.startswith(('sunos', 'aix')): + # Somehow /dev/tty appears seekable on some BSDs + self.assertEqual(f.seekable(), False) +-- +2.48.1 + + +From 5caefb7d87991d2bed2634d40e0290761c05ec84 Mon Sep 17 00:00:00 2001 +From: Oscar Lesta +Date: Mon, 12 Feb 2024 10:50:34 -0300 +Subject: Fix build on nightlies, following the addition of kqueue. + +See HaikuPorts issue #10001. + +diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c +index d234d50..6e16247 100644 +--- a/Modules/selectmodule.c ++++ b/Modules/selectmodule.c +@@ -2806,13 +2806,21 @@ _select_exec(PyObject *m) + #ifdef EVFILT_SIGNAL + ADD_INT_CONST("KQ_FILTER_SIGNAL", EVFILT_SIGNAL); + #endif ++#ifdef EVFILT_TIMER + ADD_INT_CONST("KQ_FILTER_TIMER", EVFILT_TIMER); ++#endif + + /* event flags */ + ADD_INT_CONST("KQ_EV_ADD", EV_ADD); + ADD_INT_CONST("KQ_EV_DELETE", EV_DELETE); ++#ifdef EV_ENABLE + ADD_INT_CONST("KQ_EV_ENABLE", EV_ENABLE); ++#else ++ ADD_INT_CONST("KQ_EV_ENABLE", 0); // "test_kqueue.py" assumes KQ_EV_ENABLE exists ++#endif ++#ifdef EV_DISABLE + ADD_INT_CONST("KQ_EV_DISABLE", EV_DISABLE); ++#endif + ADD_INT_CONST("KQ_EV_ONESHOT", EV_ONESHOT); + ADD_INT_CONST("KQ_EV_CLEAR", EV_CLEAR); + +@@ -2845,14 +2853,28 @@ _select_exec(PyObject *m) + /* PROC filter flags */ + #ifdef EVFILT_PROC + ADD_INT_CONST("KQ_NOTE_EXIT", NOTE_EXIT); ++#ifdef NOTE_FORK + ADD_INT_CONST("KQ_NOTE_FORK", NOTE_FORK); ++#endif ++#ifdef NOTE_EXEC + ADD_INT_CONST("KQ_NOTE_EXEC", NOTE_EXEC); ++#endif ++#ifdef NOTE_PCTRLMASK + ADD_INT_CONST("KQ_NOTE_PCTRLMASK", NOTE_PCTRLMASK); ++#endif ++#ifdef NOTE_PDATAMASK + ADD_INT_CONST("KQ_NOTE_PDATAMASK", NOTE_PDATAMASK); ++#endif + ++#ifdef NOTE_TRACK + ADD_INT_CONST("KQ_NOTE_TRACK", NOTE_TRACK); ++#endif ++#ifdef NOTE_CHILD + ADD_INT_CONST("KQ_NOTE_CHILD", NOTE_CHILD); ++#endif ++#ifdef NOTE_TRACKERR + ADD_INT_CONST("KQ_NOTE_TRACKERR", NOTE_TRACKERR); ++#endif + #endif + + /* NETDEV filter flags */ +-- +2.48.1 + + +From b9850a06fd2082ac4b4212cc2131adb06994e791 Mon Sep 17 00:00:00 2001 +From: Oscar Lesta +Date: Fri, 9 Aug 2024 13:38:28 -0300 +Subject: fix test_utf8_mode. + + +diff --git a/Lib/test/test_utf8_mode.py b/Lib/test/test_utf8_mode.py +index f668810..a55a8e4 100644 +--- a/Lib/test/test_utf8_mode.py ++++ b/Lib/test/test_utf8_mode.py +@@ -226,7 +226,7 @@ class UTF8ModeTests(unittest.TestCase): + with self.subTest(LC_ALL=loc): + check('utf8', [arg_utf8], LC_ALL=loc) + +- if sys.platform == 'darwin' or support.is_android or VXWORKS: ++ if sys.platform == 'darwin' or support.is_android or VXWORKS or sys.platform[:5] == 'haiku': + c_arg = arg_utf8 + elif sys.platform.startswith("aix"): + c_arg = arg.decode('iso-8859-1') +-- +2.48.1 + + +From 7740a4ede72b77dfb3cf9876afc8f95f822269a3 Mon Sep 17 00:00:00 2001 +From: Oscar Lesta +Date: Fri, 9 Aug 2024 14:35:04 -0300 +Subject: Fix test_site. + +test_site expects a specific set of modules to be imported. +By importing "subprocess" (for calling `finddir`) we end up breaking +that assumption. + +Also, site.py should avoid costly imports to help startup times. + +Hardcoding a few paths avoids having to import subprocess, that +causes many other subsequent imports. + +Lib/site.py changes should eventually be merged with previous commits. +Leaving the changes here now for easier review. + +diff --git a/Lib/site.py b/Lib/site.py +index eeb34ea..435a4ac 100644 +--- a/Lib/site.py ++++ b/Lib/site.py +@@ -313,12 +313,8 @@ def _getuserbase(): + "%d.%d" % sys.version_info[:2]) + + if sys.platform.startswith('haiku'): +- try: +- import subprocess +- return subprocess.check_output( +- ['finddir', 'B_USER_NONPACKAGED_DIRECTORY']).rstrip().decode('utf-8') +- except: +- pass ++ # 'B_USER_NONPACKAGED_DIRECTORY' ++ return joinuser("~", "config", "non-packaged") + + return joinuser("~", ".local") + +@@ -424,18 +420,10 @@ def getsitepackages(prefixes=None): + # For .hpkg installed under ~/config/ (pkgman install -H) + # ("pip install --user" uses ~/config/non-packaged/, and gets + # handled by the "haiku_user" install scheme. +- try: +- import subprocess +- _home_prefix = subprocess.check_output( +- ['finddir', 'B_USER_CONFIG_DIRECTORY']).rstrip().decode('utf-8') +- except: +- # print("'finddir B_USER_CONFIG_DIRECTORY' failed.") +- _home_prefix = None +- +- if _home_prefix is not None: +- sitepackages.append(os.path.join(_home_prefix, "lib", +- f"{implementation}{ver[0]}.{ver[1]}{abi_thread}", +- "vendor-packages")) ++ _home_prefix = os.path.expanduser(os.path.join("~", "config")) ++ sitepackages.append(os.path.join(_home_prefix, "lib", ++ f"{implementation}{ver[0]}.{ver[1]}{abi_thread}", ++ "vendor-packages")) + elif os.sep == '/': + libdirs = [sys.platlibdir] + if sys.platlibdir != "lib": +diff --git a/Lib/test/test_site.py b/Lib/test/test_site.py +index a7e9241..03a6bd9 100644 +--- a/Lib/test/test_site.py ++++ b/Lib/test/test_site.py +@@ -324,7 +324,21 @@ class HelperFunctionsTests(unittest.TestCase): + def test_getsitepackages(self): + site.PREFIXES = ['xoxo'] + dirs = site.getsitepackages() +- if os.sep == '/': ++ if sys.platform[:5] == 'haiku': ++ self.assertEqual(len(dirs), 3) # site-packages + sys/user vendor-packages ++ wanted = os.path.join('xoxo', 'non-packaged', 'lib', ++ 'python%d.%d' % sys.version_info[:2], ++ 'site-packages') ++ self.assertEqual(dirs[0], wanted) ++ wanted = os.path.join('xoxo', sys.platlibdir, ++ 'python%d.%d' % sys.version_info[:2], ++ 'vendor-packages') ++ self.assertEqual(dirs[1], wanted) ++ wanted = os.path.join('xoxo', os.path.expanduser('~/config'), 'lib', ++ 'python%d.%d' % sys.version_info[:2], ++ 'vendor-packages') ++ self.assertEqual(dirs[2], wanted) ++ elif os.sep == '/': + # OS X, Linux, FreeBSD, etc + if sys.platlibdir != "lib": + self.assertEqual(len(dirs), 2) +-- +2.48.1 + + +From c7afe1a34fe5ca23d50e9591d55d4fade1f66f0d Mon Sep 17 00:00:00 2001 +From: Oscar Lesta +Date: Fri, 9 Aug 2024 15:37:13 -0300 +Subject: Fix test_sysconfig. + + +diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py +index 36c9cfb..25dccd0 100644 +--- a/Lib/test/test_sysconfig.py ++++ b/Lib/test/test_sysconfig.py +@@ -223,6 +223,19 @@ class TestSysConfig(unittest.TestCase, VirtualEnvironmentMixin): + sysconfig.get_path('purelib', scheme='venv'), + sysconfig.get_path('purelib', scheme='nt_venv') + ) ++ elif sys.platform[:5] == 'haiku': ++ self.assertEqual( ++ sysconfig.get_path('scripts', scheme='venv'), ++ sysconfig.get_path('scripts', scheme='haiku_venv') ++ ) ++ self.assertEqual( ++ sysconfig.get_path('include', scheme='venv'), ++ sysconfig.get_path('include', scheme='haiku_venv') ++ ) ++ self.assertEqual( ++ sysconfig.get_path('purelib', scheme='venv'), ++ sysconfig.get_path('purelib', scheme='haiku_venv') ++ ) + else: + self.assertEqual( + sysconfig.get_path('scripts', scheme='venv'), +@@ -389,7 +402,7 @@ class TestSysConfig(unittest.TestCase, VirtualEnvironmentMixin): + + def test_get_scheme_names(self): + wanted = ['nt', 'posix_home', 'posix_prefix', 'posix_venv', 'nt_venv', 'venv', 'haiku', +- 'haiku_home', 'haiku_vendor'] ++ 'haiku_home', 'haiku_vendor', 'haiku_venv'] + if HAS_USER_BASE: + wanted.extend(['nt_user', 'osx_framework_user', 'posix_user', 'haiku_user']) + self.assertEqual(get_scheme_names(), tuple(sorted(wanted))) +-- +2.48.1 + + +From f63dede5e9a8f49a7e2f79b5958014869ce421f5 Mon Sep 17 00:00:00 2001 +From: Oscar Lesta +Date: Sun, 29 Sep 2024 03:01:27 -0300 +Subject: Partially fix test_compileall by skipping tests that need hardlink + support. + + +diff --git a/Lib/test/support/os_helper.py b/Lib/test/support/os_helper.py +index 2c45fe2..b63467b 100644 +--- a/Lib/test/support/os_helper.py ++++ b/Lib/test/support/os_helper.py +@@ -207,6 +207,8 @@ def can_hardlink(): + # Android blocks hard links using SELinux + # (https://stackoverflow.com/q/32365690). + _can_hardlink = hasattr(os, "link") and not support.is_android ++ if sys.platform[:5] == 'haiku': ++ _can_hardlink = False + return _can_hardlink + + +diff --git a/Lib/test/test_compileall.py b/Lib/test/test_compileall.py +index a580a24..d2e7ad1 100644 +--- a/Lib/test/test_compileall.py ++++ b/Lib/test/test_compileall.py +@@ -947,6 +947,7 @@ class CommandLineTestsBase: + # only for more than one optimization level + self.assertRunNotOK(self.directory, "-o 1", "--hardlink-dupes") + ++ @os_helper.skip_unless_hardlink + def test_hardlink(self): + # 'a = 0' code produces the same bytecode for the 3 optimization + # levels. All three .pyc files must have the same inode (hardlinks). +-- +2.48.1 + + +From b238dc5f2ccd0daafefc9c14a689eca2b9b7caa6 Mon Sep 17 00:00:00 2001 +From: Oscar Lesta +Date: Thu, 9 May 2024 15:16:26 -0300 +Subject: Fix 3.13.0 build. + +The change in Makefile.pre.in is to stop failing tests on the PGO stage +breaking the `--with-optimizations` builds (and to restore a sane timeout). + +Previous Python versions had both the time out and the "|| true". + +Some of the test run in that PGO stage sadly still fail on Haiku. + +diff --git a/Makefile.pre.in b/Makefile.pre.in +index 87b9c15..18581fb 100644 +--- a/Makefile.pre.in ++++ b/Makefile.pre.in +@@ -856,7 +856,7 @@ profile-run-stamp: + $(MAKE) profile-gen-stamp + # Next, run the profile task to generate the profile information. + @ # FIXME: can't run for a cross build +- $(LLVM_PROF_FILE) $(RUNSHARED) ./$(BUILDPYTHON) $(PROFILE_TASK) ++ $(LLVM_PROF_FILE) $(RUNSHARED) ./$(BUILDPYTHON) $(PROFILE_TASK) || true + $(LLVM_PROF_MERGER) + # Remove profile generation binary since we are done with it. + $(MAKE) clean-retain-profile +@@ -2221,7 +2221,7 @@ $(LIBRARY_OBJS) $(MODOBJS) Programs/python.o: $(PYTHON_HEADERS) + TESTOPTS= $(EXTRATESTOPTS) + TESTPYTHON= $(RUNSHARED) $(PYTHON_FOR_BUILD) $(TESTPYTHONOPTS) + TESTRUNNER= $(TESTPYTHON) -m test +-TESTTIMEOUT= ++TESTTIMEOUT= 1200 + + # Remove "test_python_*" directories of previous failed test jobs. + # Pass TESTOPTS options because it can contain --tempdir option. +diff --git a/Objects/mimalloc/prim/unix/prim.c b/Objects/mimalloc/prim/unix/prim.c +index 1598eba..88b94b6 100644 +--- a/Objects/mimalloc/prim/unix/prim.c ++++ b/Objects/mimalloc/prim/unix/prim.c +@@ -49,6 +49,8 @@ terms of the MIT license. A copy of the license can be found in the file + #include + #endif + #include ++#elif defined(__HAIKU__) ++ #include + #endif + + #if !defined(__HAIKU__) && !defined(__APPLE__) && !defined(__CYGWIN__) && !defined(_AIX) && !defined(__OpenBSD__) && !defined(__FreeBSD__) && !defined(__sun) && !defined(__NetBSD__) +-- +2.48.1 + + +From 466f056fe263ac8d5e23e6cf7f0155b52526d810 Mon Sep 17 00:00:00 2001 +From: Oscar Lesta +Date: Sat, 5 Oct 2024 07:32:17 -0300 +Subject: Avoid forcing "-g" on LTO builds, unless Py_DEBUG is defined. + + +diff --git a/configure.ac b/configure.ac +index 2579824..971ab7d 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -2017,7 +2017,9 @@ if test "$Py_LTO" = 'true' ; then + then + # bpo-30345: Add -g to LDFLAGS when compiling with LTO + # to get debug symbols. +- LTOFLAGS="$LTOFLAGS -g" ++ if test "$Py_DEBUG" = 'true' ; then ++ LTOFLAGS="$LTOFLAGS -g" ++ fi + fi + + CFLAGS_NODIST="$CFLAGS_NODIST ${LTOCFLAGS-$LTOFLAGS}" +-- +2.48.1 + + +From 26fc298d259487f52d11ead852ecf635afd15883 Mon Sep 17 00:00:00 2001 +From: Oscar Lesta +Date: Thu, 13 Feb 2025 13:30:03 -0300 +Subject: Make sure we use 'spawn' on Haiku and not 'forkserver'. + + +diff --git a/Lib/multiprocessing/context.py b/Lib/multiprocessing/context.py +index d0a3ad0..5c69f5f 100644 +--- a/Lib/multiprocessing/context.py ++++ b/Lib/multiprocessing/context.py +@@ -322,7 +322,7 @@ if sys.platform != 'win32': + # bpo-33725: running arbitrary code after fork() is no longer reliable + # on macOS since macOS 10.14 (Mojave). Use spawn by default instead. + # gh-84559: We changed everyones default to a thread safeish one in 3.14. +- if reduction.HAVE_SEND_HANDLE and sys.platform != 'darwin': ++ if reduction.HAVE_SEND_HANDLE and sys.platform != 'darwin' and sys.platform[:5] != 'haiku': + _default_context = DefaultContext(_concrete_contexts['forkserver']) + else: + _default_context = DefaultContext(_concrete_contexts['spawn']) +-- +2.48.1 + diff --git a/dev-lang/python/python3.14-3.14.0~b1.recipe b/dev-lang/python/python3.14-3.14.0~b1.recipe new file mode 100644 index 000000000..4a67eb2ec --- /dev/null +++ b/dev-lang/python/python3.14-3.14.0~b1.recipe @@ -0,0 +1,469 @@ +SUMMARY="An interpreted, interactive, object-oriented programming language" +DESCRIPTION="Python is a programming language that lets you work more quickly \ +and integrate your systems more effectively. You can learn to use Python and \ +see almost immediate gains in productivity and lower maintenance costs. + +Python runs on Windows, Linux/Unix, Mac OS X, and has been ported to the Java \ +and .NET virtual machines. + +Python is free to use, even for commercial products, because of its \ +OSI-approved open source license. + +Note: to install \"pip\" for this Python version, use the following commands: + +> python3.14 -m ensurepip --altinstall +> python3.14 -m pip install --upgrade pip + +And then you should be able to use \"pip3.14\" normally." +HOMEPAGE="https://www.python.org" +LICENSE="Python" +COPYRIGHT="1990-2025 Python Software Foundation" +REVISION="1" +SOURCE_URI="https://www.python.org/ftp/python/${portVersion%~b1}/Python-${portVersion/'~'/}.tar.xz" +CHECKSUM_SHA256="2ddd30a77c9f62e065ce648664a254b9b0c011bcdaa8c1c2787087e644cbeb39" +SOURCE_DIR="Python-${portVersion/'~'/}" + +pyShortVer="${portVersion%~b1}" +pyShortVer="${pyShortVer%.*}" +pyVersionCompat="${portVersion%~b1} compat >= $pyShortVer" + +PATCHES="python$pyShortVer-$portVersion.patchset" + +ARCHITECTURES="all !x86_gcc2" +SECONDARY_ARCHITECTURES="x86" + +# On x86_gcc2 we don't want to install the commands in bin//, but in bin/. +commandSuffix=$secondaryArchSuffix +commandBinDir=$binDir +if [ "$targetArchitecture" = x86_gcc2 ]; then + commandSuffix= + commandBinDir=$prefix/bin +fi + +GLOBAL_WRITABLE_FILES=" + non-packaged/lib/python$pyShortVer/site-packages directory keep-old + " + +# [RECIPE OPTIONS]>>> + +# If this is not intended to be the "default" Python version, set to "false", so "make altinstall" +# is used, and only version-suffixed commands are used in PROVIDES. +installAsDefaultPython=false + +# Set to "true" if we should build the "tkinter" module. +# Disabled for now, as tkinter deadlocks on Haiku. Try again when tk drops undroidwish for xlibe. +enableTkinter=false + +# Set to "true" to package all the tests into a separate "_tests" package (around 30 MB in size). +# Tests are discarded if set to "false". +packageTests=false + +# Set to "false" for faster local/test builds. Around 4 to 5 times faster that way. +optimizedBuild=true + +# Generally, we disable parallel builds if "optimizedBuild == true" as they can fail. +forceParallelBuild=true + +# Run all tests by default. Set to "true" to make "hp --test" only run then known failing tests. +runOnlyKnownFailingTests=false + +# Run only the tests that are generally excluded. Expect LOTS of hangs/crashes/etc. +runOnlyExcludedTests=false + +# <<<[RECIPE OPTIONS] + +PROVIDES=" + python$pyShortVer$secondaryArchSuffix = $pyVersionCompat + cmd:pydoc$pyShortVer = $pyVersionCompat + cmd:python$pyShortVer = $pyVersionCompat + cmd:python${pyShortVer}_config = $pyVersionCompat + devel:libpython$pyShortVer$secondaryArchSuffix = 1.0 + lib:libpython$pyShortVer$secondaryArchSuffix = 1.0 + " +REQUIRES=" + haiku$secondaryArchSuffix + cmd:file + lib:libbz2$secondaryArchSuffix + lib:libedit$secondaryArchSuffix + lib:libexpat$secondaryArchSuffix + lib:libffi$secondaryArchSuffix + lib:libintl$secondaryArchSuffix + lib:liblzma$secondaryArchSuffix +# lib:libmpdec$secondaryArchSuffix # bundled libmpdecimal scheduled for removal on 3.15 + lib:libncursesw$secondaryArchSuffix + lib:libsqlite3$secondaryArchSuffix # >= 3.15.2 + lib:libssl$secondaryArchSuffix + lib:libz$secondaryArchSuffix + " +BUILD_REQUIRES=" + haiku${secondaryArchSuffix}_devel + devel:libbz2$secondaryArchSuffix + devel:libedit$secondaryArchSuffix + devel:libexpat$secondaryArchSuffix + devel:libffi$secondaryArchSuffix + devel:liblzma$secondaryArchSuffix +# devel:libmpdec$secondaryArchSuffix # bundled libmpdecimal scheduled for removal on 3.15 + devel:libncursesw$secondaryArchSuffix + devel:libsqlite3$secondaryArchSuffix + devel:libssl$secondaryArchSuffix + devel:libz$secondaryArchSuffix + " +BUILD_PREREQUIRES=" + autoconf_archive + cmd:aclocal # >= 1.16.4 + cmd:autoconf # >= 2.71 + cmd:find + cmd:gcc$secondaryArchSuffix + cmd:ld$secondaryArchSuffix + cmd:libtoolize$secondaryArchSuffix + cmd:make + cmd:pkg_config$secondaryArchSuffix + " + +if $installAsDefaultPython; then + PROVIDES+=" + cmd:python3 = $pyVersionCompat + cmd:pydoc3 = $pyVersionCompat + cmd:python3_config = $pyVersionCompat + " +fi + +if $enableTkinter; then + PROVIDES+=" + cmd:idle$pyShortVer = $pyVersionCompat + " + if $installAsDefaultPython; then + PROVIDES+=" + cmd:idle3 = $portVersion compat >= $pyShortVer + " + fi + BUILD_REQUIRES+=" + devel:libtclstub8.6$secondaryArchSuffix + devel:libtk8.6$secondaryArchSuffix + " +fi + +if $packageTests; then + PROVIDES_tests=" + python$pyShortVer${secondaryArchSuffix}_tests = $portVersion + " + REQUIRES_tests=" + python$pyShortVer$secondaryArchSuffix == $portVersion base + " +fi + +BUILD() +{ + autoreconf -fi + + # From ./configure: + # "compiler flags are generated in two sets, BASECFLAGS and OPT. OPT is just + # for debug/optimization stuff. BASECFLAGS is for flags that are required + # just to get things to compile and link." + + # If not provided, the Makefile ends up with: + # BASECFLAGS= -fno-strict-overflow -Wsign-compare + # OPT= -DNDEBUG -g -O3 -Wall + # -NDEBUG gets added by ./configure unless "--with-assertions" is used. + + export BASECFLAGS="-pipe -D_BSD_SOURCE" + export OPT="-Wall" # remove "-g" until we use "defineDebugInfoPackage". + + if $optimizedBuild; then + export OPT+=" -O3" + maybeEnableOptimizations="--enable-optimizations --with-lto" + else + export OPT+=" -O0" + maybeEnableOptimizations= + fi + + runConfigure --omit-dirs binDir,includeDir ./configure \ + --bindir=$commandBinDir \ + --includedir=$developDir/headers \ + $maybeEnableOptimizations \ + --enable-shared \ + --with-ensurepip=no \ + --with-readline=editline \ + --with-system-expat \ + --with-system-libmpdec=no \ + --with-tzpath=$(findpaths -c : B_FIND_PATH_DATA_DIRECTORY zoneinfo) \ + --without-static-libpython + + # use --enable-safety/--enable-slower-safety? (the first should have no performance impact) + + # --disable-test-modules # can speed up the build a bit. + # + # --with-lto # Issues with enabling this flag: + # - Is too CPU intensive (at least 2.5x slower build times). + # - 30% final package size increase, unless "-g" is removed from 'LTOFLAGS="$LTOFLAGS -g"' + # on "configure.ac". + # but resulting Python is about 5% faster, at least on the "pystone.py" syntetic benchmark. + # + # --enable-experimental-jit=yes-off # PYTHON_JIT=1 to enable it at runtime. Requires: + # - cmd:python3.11 or newer. + # - cmd:clang >= 18 + # - patching Tools/jit/_target.py so it recognizes Haiku's triplet. + + # Uncomment when doing repeated builds (for testing different flags/options). + # echo "[.recipe] Cleaning before rebuild:" && make clean && rm -f python + + # NOTE: When using "--enable-optimizations" above, using "make $jobArgs" might be unreliable. + # Can see several instances of, for example: + # + # libgcov profiling error:/sources/Python-3.xx.x/Objects/.gcda:Merge mismatch for function + # + # Build might end OK (with only some "missing profile" warnings later on), or it can fail + # with something like: + # + # "Parser/parser.c:38718:1: error: corrupted profile info: invalid time profile" + # + # Not using multiple jobs for make solves both the warnings and the possible error. + + if $optimizedBuild && ! $forceParallelBuild; then + echo "Running make with: -j 1" + make -j 1 + else + echo "Running make with: $jobArgs" + make $jobArgs + fi +} + +INSTALL() +{ + if $installAsDefaultPython; then + make install + else + # altinstall avoids clobbering $prefix/bin/{idle3,pydoc3,python3,python3-config} + make altinstall + fi + + rm $libDir/libpython3.so + + # No point in having this if we don't have a working tkinter. + if ! $enableTkinter; then + rm $prefix/bin/idle$pyShortVer + if $installAsDefaultPython; then + rm -f $prefix/bin/idle3 + fi + fi + + if [ "$targetArchitecture" = x86_gcc2 ]; then + # On x86_gcc2, move lib-dynload to lib/python3.x/ + mv $libDir/python$pyShortVer/lib-dynload $prefix/lib/python$pyShortVer/ + fi + prepareInstalledDevelLib libpython$pyShortVer + fixPkgconfig + if [ "$targetArchitecture" = x86_gcc2 ]; then + # fix pkgconfig to match configure flags + sed -i -e 's,headers/x86,headers,' $developLibDir/pkgconfig/python*.pc + fi + + mkdir -p $prefix/lib/python$pyShortVer/vendor-packages + echo 'This directory contains packaged python modules.' \ + >$prefix/lib/python$pyShortVer/vendor-packages/README + + mkdir -p $prefix/non-packaged/lib/python$pyShortVer + mv $prefix/lib/python$pyShortVer/site-packages $prefix/non-packaged/lib/python$pyShortVer/ + + if $packageTests; then + packageEntries tests \ + $prefix/lib/python$pyShortVer/idlelib/idle_test \ + $prefix/lib/python$pyShortVer/test + else + # drop testsuite altogether + cd $prefix/lib/python$pyShortVer + rm -rf idlelib/idle_test test + fi +} + +# Some of the test will crash, invoking the crash dialog, and will hang waiting for +# user's interaction. To avoid that, make sure to configure your system by adding +# the following lines in the file "~/config/settings/system/debug_server/settings": +##--- +# executable_actions { +# /sources/Python-3.*/python kill +# } +##--- + +# For some tests that purposefully crash, it would make sense to add support for +# crash-report suppression (as done for other platforms) on "tests/support/__init__,py"'s +# SuppressCrashReport class. +# But that needs support from Haiku's debug_server, as we can't change settings from +# the recipe's building environment at the moment (https://dev.haiku-os.org/ticket/10301) + +# To see the available test-runs options: +# > hp -E python3.nn +# > LIBRARY_PATH=%A:/boot/system/lib python -m test --help +# or: +# > LD_PRELOAD=./libpython3.nn.so.1.0 python -m test --help +# +# To only execute a particular test (from the $sourceDir): +# +# > LD_PRELOAD=./libpython3.nn.so.1.0 python -m test test_datetime -W +# +# Beware that running tests that way can cause some tests to fail, while they work fine under +# "hp --test"'s chroot. (test_sysconfig.MakefileTests.test_parse_makefile, for example). +# Problem is "os.getcwd()" will return wrong data, causing some file operations to fail. + +# For reference, results for 3.14.0b1 on hrev57937+129 (64 bits VMware): +# Total duration: 12 min 33 sec +# Total tests: run=41,364 failures=673 skipped=1,941 +# Total test files: run=478/454 failed=29 skipped=33 resource_denied=7 rerun=31 +TEST() +{ + # Remove tests data left-overs, if any: + # rm -f -r /boot/system/cache/tmp/ + # rm -f -d -r build/test_python* + make $jobArgs test EXTRATESTOPTS="--cleanup" + + local test_options=( + # Use this to get same test order on different runs (actual value not important). + -r + --randseed 7858065 + + # Print the names of the 10 slowest tests. + --slowest + + # Possibly useful? + # --tempdir=/another_drive/tmp + + # Enable/disable certain tests by "resource" type: + # -uall,-audio,-cpu,-curses,-decimal,-gui,-largefile,-network,-subprocess,-urlfetch + # make test --help says that "-unone" is the default, but the build is doing this: + # "resources: all,-audio,-gui,-largefile" instead. + # + # Let's be explicit to avoid surprises: + -unone,curses,tzdata + ) + + local tests_to_exclude=( + # Many of the tests hang/stall. We have two options: + # + # 1- Manually remove the problematic test-cases. + # 2- Set a TIMEOUT (eg: --timeout=300). + # + # Option 1: Works, but requires manual identification/mainteinance. + # + # Option 2: Doesn't requires maintaining a list of stalling tests, but: + # at the end of the test run it causes: + # - "unmounting failed: Device/File/Resource Busy" errors, as there are + # dangling threads running when the tests timeout (requiring `killall python`) + # - The time it takes to run the full suite largely increases. + # + # Let's use Option 1, for now at least. + + # These hang reliably. + -x test_interpreters + -x test_multiprocessing_spawn + -x test_threaded_import # test_importlib.test_threaded_import + -x test_threading # tends to hang (or at least run for more than 5 minutes). + + # The following are all under test_asyncio/ + -x test_base_events + -x test_buffered_proto # Exception on Exception handler. + -x test_events + -x test_sendfile + -x test_server # Exception on Exception handler. + -x test_sock_lowlevel + -x test_sslproto # Exception on Exception handler. + -x test_streams + -x test_unix_events + + # These not always hang/stall, but they do it enough to warrant skipping for now. + -x test_multiprocessing_fork #? resource_tracker: process died unexpectedly + -x test_multiprocessing_forkserver #? + -x test_socket + -x test_ssl # pegs one core to 100$ + + # 3.11.8 / 3.12.2 (hang on nightlies, at least) + -x test_httplib + -x test_logging + + # Fails while outputing "ResourceWarning: unclosed 5 minutes. + ) + + local tests_that_fail=( + test.test_concurrent_futures.test_process_pool + test__locale + test_c_locale_coercion + test_cmd + test_ctypes # stupid test compares wording of error message. + test_datetime # on rare ocassions, it passes. + test_fcntl # "Permission denied" in test_lockf_exclusive + test_genericpath # os.path.getatime() should return an int. + test_importlib + test_ioctl + test_json # "AssertionError: 13 != -2147459059" (errno.EPIPE) +# test_mailbox # fails to clean a temp file? (os.utime() related?). Sometimes it takes >5 minutes. + test_math # test expects to get -0.0, gets 0.0 + test_ntpath + test_os # named pipes related errors. set_get_priority, ttyname, and utime fails. + test_popen # sign error numbers in waitstatus_to_exitcode()... "AssertionError: -42 != 42" + test_posix # test_posix_fallocate and test_link_dir_fd. Operation not supported. + test_posixpath + test_pyrepl # several: "module 'termios' has no attribute 'VREPRINT'". Adding hasattr(termios, 'VREPRINT') still results in error. + test_re # locale related failures. + test_shutil # "Operation not supported" calling "os.scandir(topfd)". + test_signal # stupid test compares wording of strsignal(signal.SIGTERM). + test_strptime # locale related failures. + test_subprocess # "Device/File/Resource busy" calling setrlimit() + test_sysconfig # venv related failures. + test_tarfile # os.path.getmtime() should return an int. Also, path.stat().st_mtime and pathlib.Path(TEMPDIR).stat().st_mtime seems to be using different scales: 1723.215266 vs 1723215266.0319815 + test_termios # tcdrain/tcflow/tcflush/tcsendbreak related failures. + test_time # ctime/mktime related failures. + test_tools # _strptime / "%z" related. + test_venv + ) + + # besides the above ones, the following only fail when the workdir is in RAMFS: + local tests_that_fail_only_on_ramfs=( + test.test_concurrent_futures.test_as_completed + test.test_concurrent_futures.test_deadlock + test.test_concurrent_futures.test_init + test.test_concurrent_futures.test_interpreter_pool + test.test_concurrent_futures.test_shutdown + test.test_concurrent_futures.test_wait + ) + + # test_freeze_simple_script is auto-skipped on PGO builds. + if ! $optimizedBuild; then + # This skips tests_tools.test_freeze, copied from Gentoo's ebuild. + local -x LOGNAME=buildbot + fi + + if $runOnlyExcludedTests; then + make $jobArgs test EXTRATESTOPTS="${test_options[*]} ${tests_to_exclude[*]}" + elif $runOnlyKnownFailingTests; then + make $jobArgs test EXTRATESTOPTS="${test_options[*]} ${tests_that_fail[*]}" + else + # Runs the full test suite (minus the tests that we explicitly exclude). + make $jobArgs test EXTRATESTOPTS="${test_options[*]} ${tests_to_exclude[*]}" + fi + + # Occasionally, some test fails seemingly due to the racy nature of tempfile.mktemp(). + # Even the help for that function says to NOT use it, but some tests still do. + # + # If you find some strange "æ" suffix on temp dirnames, ej: + # "cwd: /sources/Python-3.nn.nn/build/test_python_10324æ" + # That's due to usages of os_helper.FS_NONASCII. +}