From d1bc7b8a8d02fd7644744a4f4d94d780a7b6b69b 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 72a157e..67141ae 100644 --- a/Include/pyport.h +++ b/Include/pyport.h @@ -506,7 +506,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 ecf77bd..49823d6 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -149,7 +149,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 d34795d..acf87df 100644 --- a/Modules/resource.c +++ b/Modules/resource.c @@ -125,6 +125,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)); @@ -139,6 +140,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); @@ -411,19 +428,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 @@ -435,31 +452,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 8480590..ac7b78c 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 9477654..67dcd2d 100644 --- a/configure.ac +++ b/configure.ac @@ -1573,6 +1573,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) @@ -1720,6 +1730,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 @@ -3608,7 +3619,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" @@ -5942,6 +5953,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.52.0 From bec628a1db881d55b2e1d0b4b5a5b5c6e61b4584 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 3a8c743..f9778a6 100644 --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -1976,6 +1976,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 0a7ef74..c505f6c 100644 --- a/Modules/_posixsubprocess.c +++ b/Modules/_posixsubprocess.c @@ -847,6 +847,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.52.0 From 56d897564e32c6f847a7c804850571eb5b7baf6a 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 117bf06..6301aa2 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 @@ -277,6 +278,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): @@ -379,6 +434,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.52.0 From 7c3a4a1a24c7f3dfb2da63199d8a46f49bf72144 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 2f9555a..90bea57 100755 --- a/Lib/webbrowser.py +++ b/Lib/webbrowser.py @@ -496,6 +496,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.52.0 From 047294deb568792ece3f3435693c1fd3005e1a3b 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 9005f1e..28708e2 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.52.0 From d14e90b43c9d2106c2c2ed951afe6cd4afc593fd 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 6df7401..3307388 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -3541,7 +3541,7 @@ sock_connect(PySocketSockObject *s, PyObject *addro) } res = internal_connect(s, SAS2SA(&addrbuf), addrlen, 1); - if (res < 0) + if (res == -1) return NULL; Py_RETURN_NONE; @@ -3572,7 +3572,7 @@ sock_connect_ex(PySocketSockObject *s, PyObject *addro) } res = internal_connect(s, SAS2SA(&addrbuf), addrlen, 0); - if (res < 0) + if (res == -1) return NULL; return PyLong_FromLong((long) res); -- 2.52.0 From 87057a56802f2f2efcd0695cf2224b6cb71134c9 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 b2beda4..d43693b 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -3307,11 +3307,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.52.0 From 402583f46f519480499bd65e6da10d1a597eaf9e 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 77b9b70..addf661 100644 --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -628,7 +628,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 7f33db5..13a1481 100644 --- a/Lib/test/test_mmap.py +++ b/Lib/test/test_mmap.py @@ -1178,7 +1178,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.52.0 From 510d1ae5c276ea525fe411c1f19ffd0c5da626c9 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 041dca1..ff27efc 100644 --- a/Lib/site.py +++ b/Lib/site.py @@ -307,6 +307,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") @@ -399,7 +407,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 f7bd675..e3699d0 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'] @@ -131,6 +173,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) @@ -156,6 +206,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}', @@ -285,6 +344,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 9723300..435a4c1 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -393,9 +393,10 @@ class TestSysConfig(unittest.TestCase): 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.52.0 From 0502bcbc58696708c0617f71e3a1d3a35c5a47f5 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 ff27efc..753420a 100644 --- a/Lib/site.py +++ b/Lib/site.py @@ -506,8 +506,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.52.0 From c261b97ec20f1ee49689fe37bdf0509986ba5601 Mon Sep 17 00:00:00 2001 From: Oscar Lesta Date: Sun, 8 Oct 2023 17:02:19 -0300 Subject: Use spawn instead of fork for multiprocessing. Without this change, we get: ``` Fatal Python error: PyOS_AfterFork_Child: the function must be called with the GIL held, after Python initialization and before Python finalization, but the GIL is released (the current Python thread state is NULL) ``` when running "test_re.py" (as part of the "--with-optimizations" build) without using spawn instead of fork in multiprocessing/context.py. and also: ``` Traceback (most recent call last): File "", line 1, in File "/sources/Python-3.12.0/Lib/multiprocessing/forkserver.py", line 202, in main signal.set_wakeup_fd(sig_w) ValueError: the fd 6 must be in non-blocking mode ``` when running the "compileall" step of "make install". From: https://docs.python.org/3.12/library/multiprocessing.html#contexts-and-start-methods "The default start method will change away from fork in Python 3.14." So, we might be in the clear switching to "spawn" now. diff --git a/Lib/multiprocessing/context.py b/Lib/multiprocessing/context.py index f395e8b..c286964 100644 --- a/Lib/multiprocessing/context.py +++ b/Lib/multiprocessing/context.py @@ -320,7 +320,7 @@ if sys.platform != 'win32': 'spawn': SpawnContext(), 'forkserver': ForkServerContext(), } - if sys.platform == 'darwin': + if sys.platform == 'darwin' or sys.platform[:5] == 'haiku': # bpo-33725: running arbitrary code after fork() is no longer reliable # on macOS since macOS 10.14 (Mojave). Use spawn by default instead. _default_context = DefaultContext(_concrete_contexts['spawn']) -- 2.52.0 From b4c31ccbbafd4348c9e043e0a60e2d4e9c00996e 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 22ab655..a2d3d12 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -6089,6 +6089,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 fdb36ed..5411a96 100644 --- a/Lib/test/test_fileio.py +++ b/Lib/test/test_fileio.py @@ -404,6 +404,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.52.0 From ebeb117857122351b504d9a27c2392356075ceb4 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 5bd9b77..88e29a4 100644 --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -2769,13 +2769,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); @@ -2808,14 +2816,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.52.0 From a7465561a265aedf42c6b4d6ea888d664e0dba2c Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Thu, 14 Mar 2024 12:54:33 -0500 Subject: config.guess: Update to universal haiku arch guessing * Matches upstream config.guess as of 2022, python just ships a really old one diff --git a/config.guess b/config.guess index e81d3ae..366429c 100755 --- a/config.guess +++ b/config.guess @@ -1364,8 +1364,11 @@ EOF BePC:Haiku:*:*) # Haiku running on Intel PC compatible. GUESS=i586-pc-haiku ;; - x86_64:Haiku:*:*) - GUESS=x86_64-unknown-haiku + ppc:Haiku:*:*) + GUESS=powerpc-apple-haiku + ;; + *:Haiku:*:*) + GUESS=$UNAME_MACHINE-unknown-haiku ;; SX-4:SUPER-UX:*:*) GUESS=sx4-nec-superux$UNAME_RELEASE -- 2.52.0 From a675ede1119510075f7a5f89ab5f4057f4e178ee 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.52.0 From 097f830c9a6d6206bb96870c898d3e9b9e601b01 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 753420a..2eecc18 100644 --- a/Lib/site.py +++ b/Lib/site.py @@ -308,12 +308,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") @@ -419,18 +415,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 a128ab3..0b5cb08 100644 --- a/Lib/test/test_site.py +++ b/Lib/test/test_site.py @@ -325,7 +325,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.52.0 From ae0782877dddc6819895f219b4fdea0e1bd7a796 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 435a4c1..b5445e4 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -221,6 +221,19 @@ class TestSysConfig(unittest.TestCase): 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'), @@ -394,7 +407,7 @@ class TestSysConfig(unittest.TestCase): 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.52.0 From d7e3a80392dc5b0dd4f04d15b83c31d14fa83359 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 26c467a..4969750 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 21ecebc..632fc1c 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.52.0 From 025ac1f30e003512343f6b5a05624f884190b521 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 49823d6..3b7ba0a 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -752,7 +752,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 @@ -2035,7 +2035,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 4d3fb65..be95e7d 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.52.0 From 58a91c0600bf987dfbc56df4ff0194183ab6e331 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 67dcd2d..fe40172 100644 --- a/configure.ac +++ b/configure.ac @@ -2069,7 +2069,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.52.0 From e7502c3c77f9e149fedf53a1ce95f963038f5f69 Mon Sep 17 00:00:00 2001 From: Oscar Lesta Date: Wed, 8 Apr 2026 00:21:53 -0300 Subject: configure.ac: add Haiku to the MACHDEP cases. diff --git a/configure.ac b/configure.ac index fe40172..d25025b 100644 --- a/configure.ac +++ b/configure.ac @@ -330,6 +330,9 @@ then *-apple-ios*) ac_sys_system=iOS ;; + *-*-haiku*) + ac_sys_system=Haiku + ;; *-*-vxworks*) ac_sys_system=VxWorks ;; @@ -366,6 +369,7 @@ then linux*) MACHDEP="linux";; cygwin*) MACHDEP="cygwin";; darwin*) MACHDEP="darwin";; + haiku*) MACHDEP="haiku";; '') MACHDEP="unknown";; esac -- 2.52.0