From 94f044767b77d2e5436b85dd6c06e3f053ad9908 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 e2bac3b..0d8b825 100644 --- a/Include/pyport.h +++ b/Include/pyport.h @@ -691,7 +691,7 @@ extern char * _getpty(int *, int, mode_t, int); # 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/Lib/plat-haiku1/regen b/Lib/plat-haiku1/regen new file mode 100644 index 0000000..4372ee2 --- /dev/null +++ b/Lib/plat-haiku1/regen @@ -0,0 +1,4 @@ +#! /bin/sh +HEADERS=/boot/develop/headers +set -v +eval $PYTHON_FOR_BUILD ../../Tools/scripts/h2py.py -i "'(u_long)'" $HEADERS/posix/netinet/in.h diff --git a/Makefile.pre.in b/Makefile.pre.in index 0e64ccc..f3032c3 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -147,7 +147,7 @@ BINDIR= @bindir@ LIBDIR= @libdir@ MANDIR= @mandir@ INCLUDEDIR= @includedir@ -CONFINCLUDEDIR= $(exec_prefix)/include +CONFINCLUDEDIR= $(INCLUDEDIR) PLATLIBDIR= @PLATLIBDIR@ SCRIPTDIR= $(prefix)/$(PLATLIBDIR) ABIFLAGS= @ABIFLAGS@ diff --git a/Modules/resource.c b/Modules/resource.c index 3c89468..3ea22bf 100644 --- a/Modules/resource.c +++ b/Modules/resource.c @@ -124,6 +124,7 @@ resource_getrusage_impl(PyObject *module, int who) PyFloat_FromDouble(doubletime(ru.ru_utime))); PyStructSequence_SET_ITEM(result, 1, PyFloat_FromDouble(doubletime(ru.ru_stime))); +#ifndef __HAIKU__ PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong(ru.ru_maxrss)); PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong(ru.ru_ixrss)); PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong(ru.ru_idrss)); @@ -138,7 +139,22 @@ resource_getrusage_impl(PyObject *module, int who) PyStructSequence_SET_ITEM(result, 13, PyLong_FromLong(ru.ru_nsignals)); PyStructSequence_SET_ITEM(result, 14, PyLong_FromLong(ru.ru_nvcsw)); PyStructSequence_SET_ITEM(result, 15, PyLong_FromLong(ru.ru_nivcsw)); - +#else + PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong(0)); + PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong(0)); + PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong(0)); + PyStructSequence_SET_ITEM(result, 5, PyLong_FromLong(0)); + PyStructSequence_SET_ITEM(result, 6, PyLong_FromLong(0)); + PyStructSequence_SET_ITEM(result, 7, PyLong_FromLong(0)); + PyStructSequence_SET_ITEM(result, 8, PyLong_FromLong(0)); + PyStructSequence_SET_ITEM(result, 9, PyLong_FromLong(0)); + PyStructSequence_SET_ITEM(result, 10, PyLong_FromLong(0)); + PyStructSequence_SET_ITEM(result, 11, PyLong_FromLong(0)); + PyStructSequence_SET_ITEM(result, 12, PyLong_FromLong(0)); + PyStructSequence_SET_ITEM(result, 13, PyLong_FromLong(0)); + PyStructSequence_SET_ITEM(result, 14, PyLong_FromLong(0)); + PyStructSequence_SET_ITEM(result, 15, PyLong_FromLong(0)); +#endif if (PyErr_Occurred()) { Py_DECREF(result); return NULL; @@ -387,19 +403,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 +427,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 f5ca004..1ed1819 100644 --- a/Modules/socketmodule.h +++ b/Modules/socketmodule.h @@ -111,6 +111,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/Modules/spwdmodule.c b/Modules/spwdmodule.c index 13f1115..45f477c 100644 --- a/Modules/spwdmodule.c +++ b/Modules/spwdmodule.c @@ -9,6 +9,7 @@ #ifdef HAVE_SHADOW_H #include #endif +#include #include "clinic/spwdmodule.c.h" @@ -148,7 +149,12 @@ spwd_getspnam_impl(PyObject *module, PyObject *arg) if (PyBytes_AsStringAndSize(bytes, &name, NULL) == -1) goto out; if ((p = getspnam(name)) == NULL) { +// Haiku sets ENOENT if invalid user is specified. Ignore it to make KeyError is set. +#ifdef __HAIKU__ + if (errno != 0 && errno != ENOENT) +#else if (errno != 0) +#endif PyErr_SetFromErrno(PyExc_OSError); else PyErr_SetString(PyExc_KeyError, "getspnam(): name not found"); diff --git a/configure.ac b/configure.ac index 0d6df8e..a85e431 100644 --- a/configure.ac +++ b/configure.ac @@ -1524,6 +1524,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) @@ -1669,6 +1679,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 @@ -3441,7 +3452,7 @@ then else CCSHARED="+z"; fi;; Linux-android*) ;; - Linux*|GNU*) CCSHARED="-fPIC";; + Linux*|GNU*|Haiku*) CCSHARED="-fPIC";; Emscripten*|WASI*) AS_VAR_IF([enable_wasm_dynamic_linking], [yes], [ CCSHARED="-fPIC" @@ -3474,7 +3485,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/*) LINKFORSHARED="$extra_undefs -framework CoreFoundation" @@ -5622,6 +5633,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.45.2 From ad34f4d68d338d042490c7b455b689ac357c2d5d 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 1d17ae3..4461393 100644 --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -1940,6 +1940,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 35ea2ac..ccc25ed 100644 --- a/Modules/_posixsubprocess.c +++ b/Modules/_posixsubprocess.c @@ -756,6 +756,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.45.2 From 9e5fadd7fc838286ac17b319dd42d6ed66b5f2ea 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 c550883..6b23423 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 @@ -268,6 +269,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): @@ -370,6 +425,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.45.2 From 49dd426f78da08ed6bceb39d706cf59155d65ec7 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 13b9e85..7d81178 100755 --- a/Lib/webbrowser.py +++ b/Lib/webbrowser.py @@ -480,6 +480,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.45.2 From 188f515c46a4a0f581c24dc93ae890a323643a9d 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 22d3198..f369a88 100644 --- a/Lib/logging/__init__.py +++ b/Lib/logging/__init__.py @@ -250,7 +250,7 @@ def _releaseLock(): # 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.45.2 From 40dd67671bc97d1d7c1204e2a46ce11e01cdd968 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 9724879..f714ed8 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -3489,7 +3489,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; @@ -3520,7 +3520,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.45.2 From 1ca2d28caa2ecaefd88a19afc6155a89dcdeea21 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 2277cae..365ce3f 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -3249,11 +3249,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.45.2 From 84387b230b47b9f2fce0e395d3eeea43ad51fd14 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 8b68653..5aede8c 100644 --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -634,7 +634,7 @@ class IOTest(unittest.TestCase): # On Windows and Mac OSX 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 sys.platform == 'darwin': + if sys.platform[:3] == 'win' or sys.platform == 'darwin' 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 282400c..6448a8d 100644 --- a/Lib/test/test_largefile.py +++ b/Lib/test/test_largefile.py @@ -274,7 +274,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 1867e8c..e4fab02 100644 --- a/Lib/test/test_mmap.py +++ b/Lib/test/test_mmap.py @@ -1009,7 +1009,7 @@ class LargeMmapTests(unittest.TestCase): unlink(TESTFN) def _make_test_file(self, num_zeroes, tail): - 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(0x180000000)) f = open(TESTFN, 'w+b') -- 2.45.2 From 6156deb2f3bc6b43cde398b9a6d10a3d49d6e357 Mon Sep 17 00:00:00 2001 From: Oscar Lesta Date: Fri, 26 Jul 2024 19:18:56 -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 924cfbe..3863055 100644 --- a/Lib/site.py +++ b/Lib/site.py @@ -302,6 +302,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") @@ -382,7 +390,31 @@ def getsitepackages(prefixes=None): continue seen.add(prefix) - if os.sep == '/': + if sys.platform.startswith('haiku'): + # Locations under /system/ + sitepackages.append(os.path.join(prefix, "non-packaged", "lib", + "python%d.%d" % sys.version_info[:2], + "site-packages")) + sitepackages.append(os.path.join(prefix, "lib", + "python%d.%d" % sys.version_info[:2], + "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", + "python%d.%d" % sys.version_info[:2], + "vendor-packages")) + elif os.sep == '/': libdirs = [sys.platlibdir] if sys.platlibdir != "lib": libdirs.append("lib") diff --git a/Lib/sysconfig.py b/Lib/sysconfig.py index 122d441..55e13c4 100644 --- a/Lib/sysconfig.py +++ b/Lib/sysconfig.py @@ -47,6 +47,36 @@ _INSTALL_SCHEMES = { 'scripts': '{base}/bin', 'data': '{base}', }, + 'haiku': { + 'stdlib': '{installed_base}/lib/python{py_version_short}', + 'platstdlib': '{platbase}/lib/python{py_version_short}', + 'purelib': '{base}/non-packaged/lib/python{py_version_short}/site-packages', + 'platlib': '{platbase}/non-packaged/lib/python{py_version_short}/site-packages', + 'include': '{installed_base}/non-packaged/develop/headers/python{py_version_short}', + 'platinclude': '{installed_platbase}/develop/headers/python{py_version_short}', + 'scripts': '{base}/non-packaged/bin', + 'data' : '{base}/non-packaged', + }, + 'haiku_vendor': { + 'stdlib': '{installed_base}/lib/python{py_version_short}', + 'platstdlib': '{platbase}/lib/python{py_version_short}', + 'purelib': '{base}/lib/python{py_version_short}/vendor-packages', + 'platlib': '{platbase}/lib/python{py_version_short}/vendor-packages', + 'include': '{installed_base}/develop/headers/python{py_version_short}', + 'platinclude': '{installed_platbase}/develop/headers/python{py_version_short}', + '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', @@ -86,6 +116,16 @@ _INSTALL_SCHEMES = { 'scripts': '{base}/bin', 'data': '{base}', }, + 'haiku_venv': { + 'stdlib': '{installed_base}/lib/python{py_version_short}', + 'platstdlib': '{platbase}/lib/python{py_version_short}', + 'purelib': '{base}/non-packaged/lib/python{py_version_short}/site-packages', + 'platlib': '{platbase}/non-packaged/lib/python{py_version_short}/site-packages', + 'include': '{installed_base}/non-packaged/develop/headers/python{py_version_short}', + 'platinclude': '{installed_platbase}/develop/headers/python{py_version_short}', + 'scripts': '{base}/non-packaged/bin', + 'data' : '{base}/non-packaged', + }, 'nt_venv': { 'stdlib': '{installed_base}/Lib', 'platstdlib': '{base}/Lib', @@ -101,6 +141,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'] @@ -127,6 +169,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) @@ -152,6 +202,15 @@ if _HAS_USER_BASE: 'scripts': '{userbase}/bin', 'data': '{userbase}', }, + 'haiku_user': { + 'stdlib': '{userbase}/lib/python{py_version_short}', + 'platstdlib': '{userbase}/lib/python{py_version_short}', + 'purelib': '{userbase}/lib/python{py_version_short}/site-packages', + 'platlib': '{userbase}/lib/python{py_version_short}/site-packages', + 'include': '{userbase}/develop/headers/python{py_version_short}', + 'scripts': '{userbase}/bin', + 'data': '{userbase}', + }, 'osx_framework_user': { 'stdlib': '{userbase}/lib/python', 'platstdlib': '{userbase}/lib/python', @@ -282,6 +341,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 1137c20..575e4e5 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -344,9 +344,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.45.2 From d90396e18308b22a1a47a91296731a8ea1bacac1 Mon Sep 17 00:00:00 2001 From: Oscar Lesta Date: Fri, 26 Jul 2024 19:01:05 -0300 Subject: Fix location of REPL's history file. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From "initial Haiku patch" by Jérôme Duval. diff --git a/Lib/site.py b/Lib/site.py index 3863055..da608bd 100644 --- a/Lib/site.py +++ b/Lib/site.py @@ -518,8 +518,16 @@ def enablerlcompleter(): # each interpreter exit when readline was already configured # through a PYTHONSTARTUP hook, see: # http://bugs.python.org/issue5845#msg198636 - history = 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') try: readline.read_history_file(history) except OSError: -- 2.45.2 From 38533600230ef9bec7d8a99f0760665a2f690ff2 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 de8a264..02a301e 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.45.2 From e1b37fe32fcf2b17dafec1efd5dfe860c46d373b 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 0528e07..0885bc6 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -5926,6 +5926,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 ebfcffd..0517b87 100644 --- a/Lib/test/test_fileio.py +++ b/Lib/test/test_fileio.py @@ -391,6 +391,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.45.2 From c1134b6f49f4a0c53be2a0334ca24b8db5c5e6bd Mon Sep 17 00:00:00 2001 From: Oscar Lesta Date: Sat, 10 Feb 2024 06:01:25 -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 50788e5..82fd9d9 100644 --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -2722,13 +2722,20 @@ _select_exec(PyObject *m) #ifdef EVFILT_SIGNAL PyModule_AddIntConstant(m, "KQ_FILTER_SIGNAL", EVFILT_SIGNAL); #endif +#ifdef EVFILT_TIMER PyModule_AddIntConstant(m, "KQ_FILTER_TIMER", EVFILT_TIMER); - +#endif /* event flags */ PyModule_AddIntConstant(m, "KQ_EV_ADD", EV_ADD); PyModule_AddIntConstant(m, "KQ_EV_DELETE", EV_DELETE); +#ifdef EV_ENABLE PyModule_AddIntConstant(m, "KQ_EV_ENABLE", EV_ENABLE); +#else + PyModule_AddIntConstant(m, "KQ_EV_ENABLE", 0); // "test_kqueue.py" assumes KQ_EV_ENABLE exists +#endif +#ifdef EV_DISABLE PyModule_AddIntConstant(m, "KQ_EV_DISABLE", EV_DISABLE); +#endif PyModule_AddIntConstant(m, "KQ_EV_ONESHOT", EV_ONESHOT); PyModule_AddIntConstant(m, "KQ_EV_CLEAR", EV_CLEAR); @@ -2761,14 +2768,28 @@ _select_exec(PyObject *m) /* PROC filter flags */ #ifdef EVFILT_PROC PyModule_AddIntConstant(m, "KQ_NOTE_EXIT", NOTE_EXIT); +#ifdef NOTE_FORK PyModule_AddIntConstant(m, "KQ_NOTE_FORK", NOTE_FORK); +#endif +#ifdef NOTE_EXEC PyModule_AddIntConstant(m, "KQ_NOTE_EXEC", NOTE_EXEC); +#endif +#ifdef NOTE_PCTRLMASK PyModule_AddIntConstant(m, "KQ_NOTE_PCTRLMASK", NOTE_PCTRLMASK); +#endif +#ifdef NOTE_PDATAMASK PyModule_AddIntConstant(m, "KQ_NOTE_PDATAMASK", NOTE_PDATAMASK); +#endif +#ifdef NOTE_TRACK PyModule_AddIntConstant(m, "KQ_NOTE_TRACK", NOTE_TRACK); +#endif +#ifdef NOTE_CHILD PyModule_AddIntConstant(m, "KQ_NOTE_CHILD", NOTE_CHILD); +#endif +#ifdef NOTE_TRACKERR PyModule_AddIntConstant(m, "KQ_NOTE_TRACKERR", NOTE_TRACKERR); +#endif #endif /* NETDEV filter flags */ -- 2.45.2 From 76dd51e3429bdb55f0daeccb9a9945903aa4d0a2 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.45.2 From 0fdc0ab08ce964d27122139a9621dd5441fdb074 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.45.2 From a928a72ce3a70d3c0babd0f922809bdeb821fbd0 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. diff --git a/Lib/site.py b/Lib/site.py index da608bd..d11f972 100644 --- a/Lib/site.py +++ b/Lib/site.py @@ -303,12 +303,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") @@ -402,16 +398,8 @@ 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", + _home_prefix = os.path.expanduser(os.path.join("~", "config")) + sitepackages.append(os.path.join(_home_prefix, "lib", "python%d.%d" % sys.version_info[:2], "vendor-packages")) elif os.sep == '/': diff --git a/Lib/test/test_site.py b/Lib/test/test_site.py index 1a9c81d..09e612f 100644 --- a/Lib/test/test_site.py +++ b/Lib/test/test_site.py @@ -322,7 +322,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.45.2 From 10db21f1709a4155d9737f7dac526e542e4537be 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 575e4e5..18f73b3 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -201,6 +201,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'), @@ -345,7 +358,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.45.2 From 9a3687667dd0e5ffd65a072b7652356b8a112bf2 Mon Sep 17 00:00:00 2001 From: Oscar Lesta Date: Fri, 9 Aug 2024 15:45:45 -0300 Subject: Fix test_compileall by skipping tests that need hardlink support. Just a quick fix. Python 3.13 has "@os_helper.skip_unless_hardlink" which reads better (albeit we need to patch a bit too). diff --git a/Lib/test/test_compileall.py b/Lib/test/test_compileall.py index 5832f84..2e736db 100644 --- a/Lib/test/test_compileall.py +++ b/Lib/test/test_compileall.py @@ -921,6 +921,7 @@ class CommandLineTestsBase: # only for more than one optimization level self.assertRunNotOK(self.directory, "-o 1", "--hardlink-dupes") + @unittest.skipUnless(sys.platform[:5] != 'haiku', 'requires hardlink support') 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). @@ -958,7 +959,7 @@ class CommandLineTestsNoSourceEpoch(CommandLineTestsBase, -@unittest.skipUnless(hasattr(os, 'link'), 'requires os.link') +@unittest.skipUnless(hasattr(os, 'link') and sys.platform[:5] != 'haiku', 'requires os.link') class HardlinkDedupTestsBase: # Test hardlink_dupes parameter of compileall.compile_dir() -- 2.45.2