summaryrefslogtreecommitdiff
path: root/dev-python/wxpython
diff options
context:
space:
mode:
Diffstat (limited to 'dev-python/wxpython')
-rw-r--r--dev-python/wxpython/Manifest4
-rw-r--r--dev-python/wxpython/files/wxpython-4.2.0-flags.patch16
-rw-r--r--dev-python/wxpython/files/wxpython-4.2.0-no-webkit.patch27
-rw-r--r--dev-python/wxpython/files/wxpython-4.2.1-x86-time.patch34
-rw-r--r--dev-python/wxpython/files/wxpython-4.2.2-no-stacktrace.patch16
-rw-r--r--dev-python/wxpython/files/wxpython-4.2.2-setuppy.patch38
-rw-r--r--dev-python/wxpython/files/wxpython-4.2.4-setuptools.patch78
-rw-r--r--dev-python/wxpython/metadata.xml16
-rw-r--r--dev-python/wxpython/wxpython-4.2.3-r2.ebuild141
-rw-r--r--dev-python/wxpython/wxpython-4.2.4.ebuild141
-rw-r--r--dev-python/wxpython/wxpython-4.2.5.ebuild139
11 files changed, 650 insertions, 0 deletions
diff --git a/dev-python/wxpython/Manifest b/dev-python/wxpython/Manifest
new file mode 100644
index 000000000000..2c3655c62f8b
--- /dev/null
+++ b/dev-python/wxpython/Manifest
@@ -0,0 +1,4 @@
+DIST wxPython-4.2.3.tar.gz 58861286 BLAKE2B 2c674227ff109564be1431f2a86a212250ffac809fed4ca8934f7473c93616603e252098511e443ffdf460ab546b5eb17b3f29ab275fb8b5433041a4d47e48cb SHA512 c7b9f0758b9d77dbeab436e8069c024796b6f252af5043615e14083b3f62fb44386c5f325a118f9e2d99c15eeb7687bb1cc1a13a00263114689b32e2126364a7
+DIST wxpython-4.2.4.tar.gz 58583054 BLAKE2B 03b236deb44a345beb989273af605228f5336eaa8b4a3a18b5654536007457b8a31b4a266e31ca8445a7b948c6d6af4040f9b005930ec5c653394e97af539a0f SHA512 4ae124bced8a0d357a34763c981ef370b7c0c978dfba0f941f37e83227816881fee2e65eb7eaa2a114bbaded14afd8e96ad17dba5a9886b38ac35bc75ec82737
+DIST wxpython-4.2.5.tar.gz 58732217 BLAKE2B 767238e3279c92c3a15fdcd8752ccab47325ca5e3fb3750f47e8d7a13882024dfc84470dfefb885c7aff121a385feb205db211a4c66d850230953e6ddbfd7e47 SHA512 a094faab4f901e46c6a771168160b0e3fec336e937507fedab97a0645df55671af046e673344a37d3d6997fadcb83c5490a673c2475c200841ef9eb12bc19763
+DIST wxpython-4.2.5.tar.gz.provenance 9350 BLAKE2B 98ce7cd4cad7ac0a0c937d91ef2b680b60cb35f94a079d6f042acd2b80dfd875aa02eddbba40c9414dd97c925b5b5fe7d09b8a66f7baa99f43b7eaa5ed03ac11 SHA512 1cf3d1f4b9b2c7c29d4126c81cf657d5777568630b49828304cf659c37e0a6c252cd7644fcb0990dbff88cb8f62193c8940b125ed6626f52ce1e9b1a3575a388
diff --git a/dev-python/wxpython/files/wxpython-4.2.0-flags.patch b/dev-python/wxpython/files/wxpython-4.2.0-flags.patch
new file mode 100644
index 000000000000..12af1e211b4a
--- /dev/null
+++ b/dev-python/wxpython/files/wxpython-4.2.0-flags.patch
@@ -0,0 +1,16 @@
+--- a/buildtools/config.py
++++ b/buildtools/config.py
+@@ -236,9 +236,12 @@ class Configuration(object):
+ for lst in [self.cflags, self.cxxflags]:
+ lst.append('-O3')
+
++ self.cflags += os.environ.get('CFLAGS', '').split()
++ self.cxxflags += os.environ.get('CXXFLAGS', '').split()
++
+ lflags = self.getWxConfigValue('--libs')
+ self.MONOLITHIC = (lflags.find("_xrc") == -1)
+- self.lflags = lflags.split()
++ self.lflags = lflags.split() + os.environ.get('LDFLAGS', '').split()
+
+ self.WXBASENAME = self.getWxConfigValue('--basename')
+ self.WXRELEASE = self.getWxConfigValue('--release')
diff --git a/dev-python/wxpython/files/wxpython-4.2.0-no-webkit.patch b/dev-python/wxpython/files/wxpython-4.2.0-no-webkit.patch
new file mode 100644
index 000000000000..5ab48cef727d
--- /dev/null
+++ b/dev-python/wxpython/files/wxpython-4.2.0-no-webkit.patch
@@ -0,0 +1,27 @@
+--- a/wscript
++++ b/wscript
+@@ -244,15 +244,6 @@
+ uselib_store='WXGL', mandatory=True,
+ msg='Finding libs for WXGL')
+
+- if cfg.checkSetup(wxConfigDir, 'wxUSE_WEBVIEW'):
+- wv_libs = '--libs webview,core,net'
+- else:
+- wv_libs = '--libs core,net'
+- conf.check_cfg(path=conf.options.wx_config, package='',
+- args='--cxxflags ' + wv_libs + rpath,
+- uselib_store='WXWEBVIEW', mandatory=True,
+- msg='Finding libs for WXWEBVIEW')
+-
+ conf.check_cfg(path=conf.options.wx_config, package='',
+ args='--cxxflags --libs xml,core,net' + rpath,
+ uselib_store='WXXML', mandatory=True,
+@@ -600,7 +591,6 @@
+ makeETGRule(bld, 'etg/_stc.py', '_stc', 'WXSTC')
+ makeETGRule(bld, 'etg/_html.py', '_html', 'WXHTML')
+ makeETGRule(bld, 'etg/_glcanvas.py', '_glcanvas', 'WXGL')
+- makeETGRule(bld, 'etg/_html2.py', '_html2', 'WXWEBVIEW')
+ makeETGRule(bld, 'etg/_xml.py', '_xml', 'WXXML')
+ makeETGRule(bld, 'etg/_xrc.py', '_xrc', 'WXXRC')
+ makeETGRule(bld, 'etg/_richtext.py', '_richtext', 'WXHTML WXRICHTEXT')
+
diff --git a/dev-python/wxpython/files/wxpython-4.2.1-x86-time.patch b/dev-python/wxpython/files/wxpython-4.2.1-x86-time.patch
new file mode 100644
index 000000000000..ea144419833e
--- /dev/null
+++ b/dev-python/wxpython/files/wxpython-4.2.1-x86-time.patch
@@ -0,0 +1,34 @@
+https://bugs.gentoo.org/922328
+https://github.com/wxWidgets/Phoenix/issues/1910
+https://github.com/wxWidgets/Phoenix/issues/2197 (specifically https://github.com/wxWidgets/Phoenix/issues/2197#issuecomment-1169378156)
+https://github.com/StefanBruens/Phoenix/commit/8b743981d557d0465ba53e938784be94f4679145 but w/ s/SIP_SSIZE_T/long
+i.e. a revert of https://github.com/wxWidgets/Phoenix/commit/c78823549bac1b28d99a1ad6dc1008485a2afb33.
+
+From 8b743981d557d0465ba53e938784be94f4679145 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Stefan=20Br=C3=BCns?= <stefan.bruens@rwth-aachen.de>
+Date: Tue, 28 Jun 2022 18:32:32 +0200
+Subject: [PATCH] Fix time_t ETG typedef, extend DateTime.FromTimeT tests
+
+Before c78823549bac ("Ensure time_t is treated as a 64-bit value by SIP")
+the typedef used "long" instead of wxInt64, which caused issues on Win64,
+as long is 32bit there (LLP64). On the other hand, wxInt64 is wrong on
+32 bit Linux (e.g. armv7, i586), and thus the code crashes.
+
+As SIP_SSIZE_T is 64 bit for both LLP64 (Windows) and LP64 (Linux), but
+32 bit on 32bit archs, it matches time_t better (though, according to the
+C standard, it could even be a double).
+
+Fixes #2197.
+ etg/defs.py | 2 +-
+
+--- a/etg/defs.py
++++ b/etg/defs.py
+@@ -73,7 +73,7 @@ def run():
+ td = module.find('wxUIntPtr')
+ module.insertItemAfter(td, etgtools.TypedefDef(type='wchar_t', name='wxUChar'))
+ module.insertItemAfter(td, etgtools.TypedefDef(type='wchar_t', name='wxChar'))
+- module.insertItemAfter(td, etgtools.TypedefDef(type='wxInt64', name='time_t'))
++ module.insertItemAfter(td, etgtools.TypedefDef(type='long', name='time_t'))
+ module.insertItemAfter(td, etgtools.TypedefDef(type='long long', name='wxFileOffset'))
+ module.insertItemAfter(td, etgtools.TypedefDef(type='SIP_SSIZE_T', name='ssize_t'))
+ module.insertItemAfter(td, etgtools.TypedefDef(type='unsigned char', name='byte', pyInt=True))
diff --git a/dev-python/wxpython/files/wxpython-4.2.2-no-stacktrace.patch b/dev-python/wxpython/files/wxpython-4.2.2-no-stacktrace.patch
new file mode 100644
index 000000000000..f387612522bd
--- /dev/null
+++ b/dev-python/wxpython/files/wxpython-4.2.2-no-stacktrace.patch
@@ -0,0 +1,16 @@
+https://bugs.gentoo.org/924057
+
+--- a/sip/cpp/sip_corewxAppTraits.cpp
++++ b/sip/cpp/sip_corewxAppTraits.cpp
+@@ -471,7 +471,11 @@
+ PyErr_Clear();
+
+ Py_BEGIN_ALLOW_THREADS
++ #ifdef __GLIBC__
+ sipRes = new ::wxString((sipSelfWasArg ? sipCpp->::wxAppTraits::GetAssertStackTrace() : sipCpp->GetAssertStackTrace()));
++ #else
++ sipRes = new ::wxString("");
++ #endif
+ Py_END_ALLOW_THREADS
+
+ if (PyErr_Occurred())
diff --git a/dev-python/wxpython/files/wxpython-4.2.2-setuppy.patch b/dev-python/wxpython/files/wxpython-4.2.2-setuppy.patch
new file mode 100644
index 000000000000..229d372aa5af
--- /dev/null
+++ b/dev-python/wxpython/files/wxpython-4.2.2-setuppy.patch
@@ -0,0 +1,38 @@
+Created by Quincy Fleming
+https://bugs.gentoo.org/909973
+
+--- a/setup.py
++++ b/setup.py
+@@ -113,6 +113,7 @@
+ """
+ user_options = [
+ ('skip-build', None, 'skip building the C/C++ code (assumes it has already been done)'),
++ ('buildpy-options=', None, 'string of commands and options passed to build.py'),
+ ]
+ boolean_options = ['skip-build']
+
+@@ -120,6 +121,7 @@
+ def initialize_options(self):
+ orig_build.initialize_options(self)
+ self.skip_build = '--skip-build' in sys.argv
++ self.buildpy_options = 'build'
+
+ def finalize_options(self):
+ orig_build.finalize_options(self)
+@@ -135,7 +137,7 @@
+ 'message and the wxWidgets and Phoenix build steps in the future.\n')
+
+ # Use the same Python that is running this script.
+- cmd = ['"{}"'.format(sys.executable), '-u', 'build.py', 'build']
++ cmd = ['"{}"'.format(sys.executable), '-u', 'build.py',self.buildpy_options]
+ cmd = ' '.join(cmd)
+ runcmd(cmd)
+
+@@ -143,7 +145,6 @@
+ # build/lib folder like normal.
+ orig_build.run(self)
+
+-
+ def _cleanup_symlinks(cmd):
+ # Clean out any libwx* symlinks in the build_lib folder, as they will
+ # turn into copies in the egg since zip files can't handle symlinks.
diff --git a/dev-python/wxpython/files/wxpython-4.2.4-setuptools.patch b/dev-python/wxpython/files/wxpython-4.2.4-setuptools.patch
new file mode 100644
index 000000000000..06e8bfd2e90e
--- /dev/null
+++ b/dev-python/wxpython/files/wxpython-4.2.4-setuptools.patch
@@ -0,0 +1,78 @@
+https://github.com/wxWidgets/Phoenix/commit/b91db9a2eff6460dd7189e24020bff1573c63211
+
+From b91db9a2eff6460dd7189e24020bff1573c63211 Mon Sep 17 00:00:00 2001
+From: Scott Talbert <swt@techie.net>
+Date: Fri, 6 Feb 2026 20:31:33 -0500
+Subject: [PATCH] Fix build with setuptools 81+
+
+Unfortunately distutils changed the API of copy_file and
+copy_tree, so we need to replace our monkey patched versions.
+
+(cherry picked from commit 1dec4c8fc560795b01bb54ca5f62a598fda2d8dd)
+---
+ setup.py | 33 +++++++++++++++++++++++++++++++--
+ 1 file changed, 31 insertions(+), 2 deletions(-)
+
+diff --git a/setup.py b/setup.py
+index 71d57d699..9bcef61c5 100644
+--- a/setup.py
++++ b/setup.py
+@@ -9,6 +9,7 @@
+ # License: wxWindows License
+ #----------------------------------------------------------------------
+
++import inspect
+ import sys, os
+ import glob
+ import stat
+@@ -260,9 +261,29 @@ def wx_copy_file(src, dst, preserve_mode=1, preserve_times=1, update=0,
+ os.symlink(linkdst, dst)
+ return (dst, 1)
+
++def wx_copy_file_new(src, dst, preserve_mode=True, preserve_times=True,
++ update=False, link=None, verbose=True):
++ if not os.path.islink(src):
++ return orig_copy_file(
++ src, dst, preserve_mode, preserve_times, update, link, verbose)
++ else:
++ # make a new, matching symlink in dst
++ if os.path.isdir(dst):
++ dst = os.path.join(dst, os.path.basename(src))
++ linkdst = os.readlink(src)
++ if verbose:
++ from distutils import log
++ log.info("%s %s -> %s", 'copying symlink', src, dst)
++ if not os.path.exists(dst):
++ os.symlink(linkdst, dst)
++ return (dst, True)
++
+ import distutils.file_util
+ orig_copy_file = distutils.file_util.copy_file
+-distutils.file_util.copy_file = wx_copy_file
++if 'dry_run' not in inspect.signature(orig_copy_file).parameters.keys():
++ distutils.file_util.copy_file = wx_copy_file_new
++else:
++ distutils.file_util.copy_file = wx_copy_file
+
+
+
+@@ -271,9 +292,17 @@ def wx_copy_tree(src, dst, preserve_mode=1, preserve_times=1,
+ return orig_copy_tree(
+ src, dst, preserve_mode, preserve_times, 1, update, verbose, dry_run)
+
++def wx_copy_tree_new(src, dst, preserve_mode=True, preserve_times=True,
++ preserve_symlinks=False, update=False, verbose=True):
++ return orig_copy_tree(
++ src, dst, preserve_mode, preserve_times, True, update, verbose)
++
+ import distutils.dir_util
+ orig_copy_tree = distutils.dir_util.copy_tree
+-distutils.dir_util.copy_tree = wx_copy_tree
++if 'dry_run' not in inspect.signature(orig_copy_tree).parameters.keys():
++ distutils.dir_util.copy_tree = wx_copy_tree_new
++else:
++ distutils.dir_util.copy_tree = wx_copy_tree
+
+
+ # Monkey-patch make_writeable too. Sometimes the link is copied before the
+
diff --git a/dev-python/wxpython/metadata.xml b/dev-python/wxpython/metadata.xml
new file mode 100644
index 000000000000..2ae11d018276
--- /dev/null
+++ b/dev-python/wxpython/metadata.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE pkgmetadata SYSTEM "https://www.gentoo.org/dtd/metadata.dtd">
+<pkgmetadata>
+ <maintainer type="project">
+ <email>wxwidgets@gentoo.org</email>
+ <name>Gentoo wxWidgets Project</name>
+ </maintainer>
+ <maintainer type="project">
+ <email>python@gentoo.org</email>
+ <name>Python</name>
+ </maintainer>
+ <upstream>
+ <remote-id type="github">wxWidgets/Phoenix</remote-id>
+ <remote-id type="pypi">wxPython</remote-id>
+ </upstream>
+</pkgmetadata>
diff --git a/dev-python/wxpython/wxpython-4.2.3-r2.ebuild b/dev-python/wxpython/wxpython-4.2.3-r2.ebuild
new file mode 100644
index 000000000000..53d9c5c76988
--- /dev/null
+++ b/dev-python/wxpython/wxpython-4.2.3-r2.ebuild
@@ -0,0 +1,141 @@
+# Copyright 1999-2025 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI=8
+DISTUTILS_EXT=1
+DISTUTILS_USE_PEP517=setuptools
+PYTHON_COMPAT=( python3_{11..13} )
+PYPI_NO_NORMALIZE=1
+PYPI_PN="wxPython"
+WX_GTK_VER="3.2-gtk3"
+
+inherit distutils-r1 multilib multiprocessing virtualx wxwidgets pypi
+
+DESCRIPTION="A blending of the wxWindows C++ class library with Python"
+HOMEPAGE="
+ https://www.wxpython.org/
+ https://github.com/wxWidgets/Phoenix/
+ https://pypi.org/project/wxPython/
+"
+
+LICENSE="wxWinLL-3"
+SLOT="4.0"
+KEYWORDS="~alpha amd64 arm arm64 ~loong ppc ppc64 ~riscv ~sparc x86"
+IUSE="test webkit"
+RESTRICT="!test? ( test )"
+
+# wxPython doesn't seem to be able to optionally disable features. webkit is
+# optionally patched out because it's so huge, but other elements are not,
+# which makes us have to require all features from wxGTK
+DEPEND="
+ >=x11-libs/wxGTK-3.2.7:${WX_GTK_VER}=[gstreamer,libnotify,opengl,sdl,tiff,webkit?,X]
+ media-libs/libpng:=
+ media-libs/tiff:=
+ media-libs/libjpeg-turbo:=
+"
+RDEPEND="
+ ${DEPEND}
+"
+BDEPEND="
+ app-text/doxygen
+ dev-python/cython[${PYTHON_USEDEP}]
+ >=dev-python/sip-6.11.1-r1[${PYTHON_USEDEP}]
+ test? (
+ ${VIRTUALX_DEPEND}
+ dev-python/appdirs[${PYTHON_USEDEP}]
+ dev-python/numpy[${PYTHON_USEDEP}]
+ dev-python/pillow[${PYTHON_USEDEP}]
+ dev-python/pytest-forked[${PYTHON_USEDEP}]
+ )
+"
+
+EPYTEST_XDIST=1
+distutils_enable_tests pytest
+
+PATCHES=(
+ "${FILESDIR}/${PN}-4.2.0-flags.patch"
+ "${FILESDIR}/${PN}-4.2.1-x86-time.patch"
+ "${FILESDIR}/${PN}-4.2.2-setuppy.patch"
+)
+
+python_prepare_all() {
+ if ! use webkit; then
+ eapply "${FILESDIR}/${PN}-4.2.0-no-webkit.patch"
+ fi
+
+ local build_options="build_py --use_syswx --no_magic --jobs=$(makeopts_jobs) --verbose --release"
+
+ DISTUTILS_ARGS=(
+ --verbose
+ build
+ --buildpy-options="${build_options}"
+ )
+
+ distutils-r1_python_prepare_all
+
+ # sigh
+ sed -i -e '/from buildtools/i\
+sys.path.insert(0, ".")' setup.py || die
+
+ # sigh, used only when fetching things implicitly which we definitely
+ # don't want; https://bugs.gentoo.org/955593
+ sed -i -e '/requests/d' build.py || die
+}
+
+src_configure() {
+ setup-wxwidgets
+}
+
+python_compile() {
+ # Patch will fail if copy of refreshed sip file is not restored
+ # if using multiple Python implementations
+ DOXYGEN="$(type -P doxygen)" ${PYTHON} build.py dox etg sip --nodoc || die
+ cp "${S}/sip/cpp/sip_corewxAppTraits.cpp" "${S}" || die
+
+ eapply "${FILESDIR}/${PN}-4.2.2-no-stacktrace.patch" || die
+
+ distutils-r1_python_compile
+
+ # This package's built system relies on copying extensions back
+ # to source directory for setuptools to pick them up. This is
+ # hopeless.
+ find -name "*$(get_modname)" -delete || die
+
+ cp "${S}/sip_corewxAppTraits.cpp" "${S}/sip/cpp/" || die
+}
+
+python_test() {
+ local EPYTEST_DESELECT=(
+ # virtx probably
+ unittests/test_display.py::display_Tests::test_display
+ unittests/test_frame.py::frame_Tests::test_frameRestore
+ unittests/test_mousemanager.py::mousemanager_Tests::test_mousemanager1
+ unittests/test_uiaction.py::uiaction_KeyboardTests::test_uiactionKeyboardChar
+ unittests/test_uiaction.py::uiaction_KeyboardTests::test_uiactionKeyboardKeyDownUp
+ unittests/test_uiaction.py::uiaction_MouseTests
+
+ # assertion (TODO)
+ unittests/test_aboutdlg.py::aboutdlg_Tests::test_aboutdlgGeneric
+ unittests/test_lib_agw_piectrl.py::lib_agw_piectrl_Tests::test_lib_agw_piectrlCtor
+
+ # seems to rely on state from a previous test (sigh)
+ unittests/test_lib_agw_persist_persistencemanager.py::lib_agw_persist_persistencemanager_Tests::test_persistencemanagerRestore
+
+ # requires Spanish localization
+ unittests/test_intl.py::intl_Tests::test_intlGetString
+
+ # TODO
+ unittests/test_tipwin.py::tipwin_Tests::test_tipwinCtor
+ unittests/test_lib_pubsub_provider.py::lib_pubsub_Except::test1
+ unittests/test_windowid.py::IdManagerTest::test_newIdRef03
+ )
+ local EPYTEST_IGNORE=()
+ if ! use webkit; then
+ EPYTEST_IGNORE+=( unittests/test_webview.py )
+ fi
+
+ rm -rf wx || die
+ # We use pytest-forked as opensuse does to avoid tests corrupting each
+ # other.
+ virtx epytest --forked unittests
+}
diff --git a/dev-python/wxpython/wxpython-4.2.4.ebuild b/dev-python/wxpython/wxpython-4.2.4.ebuild
new file mode 100644
index 000000000000..cfedabd6bf02
--- /dev/null
+++ b/dev-python/wxpython/wxpython-4.2.4.ebuild
@@ -0,0 +1,141 @@
+# Copyright 1999-2026 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI=8
+DISTUTILS_EXT=1
+DISTUTILS_USE_PEP517=setuptools
+PYTHON_COMPAT=( python3_{11..14} )
+PYPI_NO_NORMALIZE=1
+PYPI_PN="wxPython"
+WX_GTK_VER="3.2-gtk3"
+
+inherit distutils-r1 multilib multiprocessing virtualx wxwidgets pypi
+
+DESCRIPTION="A blending of the wxWindows C++ class library with Python"
+HOMEPAGE="
+ https://www.wxpython.org/
+ https://github.com/wxWidgets/Phoenix/
+ https://pypi.org/project/wxPython/
+"
+# >=4.2.4 has all lowercase sdist
+SRC_URI="$(pypi_sdist_url ${PN} ${PV})"
+
+LICENSE="wxWinLL-3"
+SLOT="4.0"
+KEYWORDS="~alpha amd64 ~arm arm64 ~loong ~ppc ~ppc64 ~riscv ~sparc ~x86"
+IUSE="test webkit"
+RESTRICT="!test? ( test )"
+
+# wxPython doesn't seem to be able to optionally disable features. webkit is
+# optionally patched out because it's so huge, but other elements are not,
+# which makes us have to require all features from wxGTK
+DEPEND="
+ >=x11-libs/wxGTK-3.2.7:${WX_GTK_VER}=[gstreamer,libnotify,opengl,sdl,tiff,webkit?,X]
+ media-libs/libpng:=
+ media-libs/tiff:=
+ media-libs/libjpeg-turbo:=
+"
+RDEPEND="
+ ${DEPEND}
+"
+BDEPEND="
+ app-text/doxygen
+ dev-python/cython[${PYTHON_USEDEP}]
+ >=dev-python/sip-6.11.1-r1[${PYTHON_USEDEP}]
+ test? (
+ ${VIRTUALX_DEPEND}
+ dev-python/appdirs[${PYTHON_USEDEP}]
+ dev-python/numpy[${PYTHON_USEDEP}]
+ dev-python/pillow[${PYTHON_USEDEP}]
+ dev-python/pytest-forked[${PYTHON_USEDEP}]
+ )
+"
+
+EPYTEST_XDIST=1
+distutils_enable_tests pytest
+
+PATCHES=(
+ "${FILESDIR}/${PN}-4.2.0-flags.patch"
+ "${FILESDIR}/${PN}-4.2.1-x86-time.patch"
+ "${FILESDIR}/${PN}-4.2.2-setuppy.patch"
+ "${FILESDIR}/${PN}-4.2.4-setuptools.patch"
+)
+
+python_prepare_all() {
+ if ! use webkit; then
+ eapply "${FILESDIR}/${PN}-4.2.0-no-webkit.patch"
+ fi
+
+ local build_options="build_py --use_syswx --no_magic --jobs=$(makeopts_jobs) --verbose --release"
+
+ DISTUTILS_ARGS=(
+ --verbose
+ build
+ --buildpy-options="${build_options}"
+ )
+
+ distutils-r1_python_prepare_all
+}
+
+src_configure() {
+ setup-wxwidgets
+}
+
+python_compile() {
+ # Patch will fail if copy of refreshed sip file is not restored
+ # if using multiple Python implementations.
+ # TODO: Could we do this in python_compile_all() instead? It would
+ # save a lot of time.
+ DOXYGEN="$(type -P doxygen)" ${PYTHON} build.py dox touch etg sip --nodoc || die
+
+ cp "${S}/sip/cpp/sip_corewxAppTraits.cpp" "${S}" || die
+
+ eapply "${FILESDIR}/${PN}-4.2.2-no-stacktrace.patch"
+
+ distutils-r1_python_compile
+
+ # This package's built system relies on copying extensions back
+ # to source directory for setuptools to pick them up. This is
+ # hopeless.
+ find -name "*$(get_modname)" -delete || die
+
+ cp "${S}/sip_corewxAppTraits.cpp" "${S}/sip/cpp/" || die
+}
+
+python_test() {
+ local EPYTEST_DESELECT=(
+ # virtx probably
+ unittests/test_display.py::display_Tests::test_display
+ unittests/test_frame.py::frame_Tests::test_frameRestore
+ unittests/test_mousemanager.py::mousemanager_Tests::test_mousemanager1
+ unittests/test_uiaction.py::uiaction_KeyboardTests::test_uiactionKeyboardChar
+ unittests/test_uiaction.py::uiaction_KeyboardTests::test_uiactionKeyboardKeyDownUp
+ unittests/test_uiaction.py::uiaction_KeyboardTests::test_uiactionKeyboardText
+ unittests/test_uiaction.py::uiaction_MouseTests
+
+ # assertion (TODO)
+ unittests/test_aboutdlg.py::aboutdlg_Tests::test_aboutdlgGeneric
+ unittests/test_lib_agw_piectrl.py::lib_agw_piectrl_Tests::test_lib_agw_piectrlCtor
+
+ # seems to rely on state from a previous test (sigh)
+ unittests/test_lib_agw_persist_persistencemanager.py::lib_agw_persist_persistencemanager_Tests::test_persistencemanagerRestore
+ unittests/test_lib_agw_persist_persistencemanager.py::lib_agw_persist_persistencemanager_Tests::test_persistencemanagerPersistValue
+
+ # requires Spanish localization
+ unittests/test_intl.py::intl_Tests::test_intlGetString
+
+ # TODO
+ unittests/test_tipwin.py::tipwin_Tests::test_tipwinCtor
+ unittests/test_lib_pubsub_provider.py::lib_pubsub_Except::test1
+ unittests/test_windowid.py::IdManagerTest::test_newIdRef03
+ )
+ local EPYTEST_IGNORE=()
+ if ! use webkit; then
+ EPYTEST_IGNORE+=( unittests/test_webview.py )
+ fi
+
+ rm -rf wx || die
+ # We use pytest-forked as opensuse does to avoid tests corrupting each
+ # other.
+ virtx epytest --forked unittests
+}
diff --git a/dev-python/wxpython/wxpython-4.2.5.ebuild b/dev-python/wxpython/wxpython-4.2.5.ebuild
new file mode 100644
index 000000000000..7c9af36db7a5
--- /dev/null
+++ b/dev-python/wxpython/wxpython-4.2.5.ebuild
@@ -0,0 +1,139 @@
+# Copyright 1999-2026 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI=8
+
+DISTUTILS_EXT=1
+DISTUTILS_USE_PEP517=setuptools
+PYTHON_COMPAT=( python3_{11..14} )
+PYPI_PN="wxPython"
+PYPI_VERIFY_REPO=https://github.com/wxWidgets/Phoenix
+WX_GTK_VER="3.2-gtk3"
+
+inherit distutils-r1 multilib multiprocessing virtualx wxwidgets pypi
+
+DESCRIPTION="A blending of the wxWindows C++ class library with Python"
+HOMEPAGE="
+ https://www.wxpython.org/
+ https://github.com/wxWidgets/Phoenix/
+ https://pypi.org/project/wxPython/
+"
+
+LICENSE="wxWinLL-3"
+SLOT="4.0"
+KEYWORDS="~alpha amd64 arm arm64 ~loong ~ppc ppc64 ~riscv ~sparc x86"
+IUSE="test webkit"
+RESTRICT="!test? ( test )"
+
+# wxPython doesn't seem to be able to optionally disable features. webkit is
+# optionally patched out because it's so huge, but other elements are not,
+# which makes us have to require all features from wxGTK
+DEPEND="
+ >=x11-libs/wxGTK-3.2.7:${WX_GTK_VER}=[gstreamer,libnotify,opengl,sdl,tiff,webkit?,X]
+ media-libs/libpng:=
+ media-libs/tiff:=
+ media-libs/libjpeg-turbo:=
+"
+RDEPEND="
+ ${DEPEND}
+"
+BDEPEND="
+ app-text/doxygen
+ dev-python/cython[${PYTHON_USEDEP}]
+ >=dev-python/sip-6.11.1-r1[${PYTHON_USEDEP}]
+ test? (
+ ${VIRTUALX_DEPEND}
+ dev-python/appdirs[${PYTHON_USEDEP}]
+ dev-python/numpy[${PYTHON_USEDEP}]
+ dev-python/pillow[${PYTHON_USEDEP}]
+ )
+"
+
+EPYTEST_PLUGINS=( pytest-forked )
+EPYTEST_XDIST=1
+distutils_enable_tests pytest
+
+PATCHES=(
+ "${FILESDIR}/${PN}-4.2.0-flags.patch"
+ "${FILESDIR}/${PN}-4.2.1-x86-time.patch"
+ "${FILESDIR}/${PN}-4.2.2-setuppy.patch"
+)
+
+python_prepare_all() {
+ if ! use webkit; then
+ eapply "${FILESDIR}/${PN}-4.2.0-no-webkit.patch"
+ fi
+
+ local build_options="build_py --use_syswx --no_magic --jobs=$(makeopts_jobs) --verbose --release"
+
+ DISTUTILS_ARGS=(
+ --verbose
+ build
+ --buildpy-options="${build_options}"
+ )
+
+ distutils-r1_python_prepare_all
+}
+
+src_configure() {
+ setup-wxwidgets
+}
+
+python_compile() {
+ # Patch will fail if copy of refreshed sip file is not restored
+ # if using multiple Python implementations.
+ # TODO: Could we do this in python_compile_all() instead? It would
+ # save a lot of time.
+ DOXYGEN="$(type -P doxygen)" ${PYTHON} build.py dox touch etg sip --nodoc || die
+
+ cp "${S}/sip/cpp/sip_corewxAppTraits.cpp" "${S}" || die
+
+ eapply "${FILESDIR}/${PN}-4.2.2-no-stacktrace.patch"
+
+ distutils-r1_python_compile
+
+ # This package's built system relies on copying extensions back
+ # to source directory for setuptools to pick them up. This is
+ # hopeless.
+ find -name "*$(get_modname)" -delete || die
+
+ cp "${S}/sip_corewxAppTraits.cpp" "${S}/sip/cpp/" || die
+}
+
+python_test() {
+ local EPYTEST_DESELECT=(
+ # virtx probably
+ unittests/test_display.py::display_Tests::test_display
+ unittests/test_frame.py::frame_Tests::test_frameRestore
+ unittests/test_mousemanager.py::mousemanager_Tests::test_mousemanager1
+ unittests/test_uiaction.py::uiaction_KeyboardTests::test_uiactionKeyboardChar
+ unittests/test_uiaction.py::uiaction_KeyboardTests::test_uiactionKeyboardKeyDownUp
+ unittests/test_uiaction.py::uiaction_KeyboardTests::test_uiactionKeyboardText
+ unittests/test_uiaction.py::uiaction_MouseTests
+
+ # assertion (TODO)
+ unittests/test_aboutdlg.py::aboutdlg_Tests::test_aboutdlgGeneric
+ unittests/test_lib_agw_piectrl.py::lib_agw_piectrl_Tests::test_lib_agw_piectrlCtor
+
+ # seems to rely on state from a previous test (sigh)
+ unittests/test_lib_agw_persist_persistencemanager.py::lib_agw_persist_persistencemanager_Tests::test_persistencemanagerRestore
+ unittests/test_lib_agw_persist_persistencemanager.py::lib_agw_persist_persistencemanager_Tests::test_persistencemanagerPersistValue
+
+ # requires Spanish localization
+ unittests/test_intl.py::intl_Tests::test_intlGetString
+
+ # TODO
+ unittests/test_tipwin.py::tipwin_Tests::test_tipwinCtor
+ unittests/test_lib_pubsub_provider.py::lib_pubsub_Except::test1
+ unittests/test_windowid.py::IdManagerTest::test_newIdRef03
+ )
+ local EPYTEST_IGNORE=()
+ if ! use webkit; then
+ EPYTEST_IGNORE+=( unittests/test_webview.py )
+ fi
+
+ rm -rf wx || die
+ # We use pytest-forked as opensuse does to avoid tests corrupting each
+ # other.
+ virtx epytest --forked unittests
+}