diff --git a/devel/Makefile b/devel/Makefile
index 46771a400..6dbebf7f5 100644
--- a/devel/Makefile
+++ b/devel/Makefile
@@ -4745,6 +4745,7 @@
     SUBDIR += py-cloudpickle
     SUBDIR += py-cloup
     SUBDIR += py-cluster
+    SUBDIR += py-cmake
     SUBDIR += py-cmd2
     SUBDIR += py-cmdtest
     SUBDIR += py-cobble
diff --git a/devel/py-cmake/Makefile b/devel/py-cmake/Makefile
new file mode 100644
index 000000000..6b4279504
--- /dev/null
+++ b/devel/py-cmake/Makefile
@@ -0,0 +1,71 @@
+PORTNAME=	cmake
+PORTVERSION=	${_CMAKE_VERSION}
+CATEGORIES=	devel python
+MASTER_SITES=	PYPI
+PKGNAMEPREFIX=	${PYTHON_PKGNAMEPREFIX}
+DIST_SUBDIR=	python
+
+MAINTAINER=	hiroo.ono+freebsd@gmail.com
+COMMENT=	A python module for cmake
+WWW=		https://pypi.org/project/cmake
+
+LICENSE=	APACHE20 BSD3CLAUSE
+LICENSE_COMB=	multi
+LICENSE_FILE_APACHE20=	${WRKSRC}/LICENSE_Apache_20
+LICENSE_FILE_BSD3CLAUSE=	${WRKSRC}/LICENSE_BSD_3
+
+OPTIONS_DEFINE=	DOCS
+
+BUILD_DEPENDS=	${PYTHON_PKGNAMEPREFIX}scikit-build-core>=0.10:devel/py-scikit-build-core@${PY_FLAVOR}
+LIB_DEPENDS=	libexpat.so:textproc/expat2 \
+		libidn2.so:dns/libidn2 \
+		libjsoncpp.so:devel/jsoncpp \
+		libpkg.so:${PKG_ORIGIN} \
+		librhash.so:security/rhash \
+		libuv.so:devel/libuv
+TEST_DEPENDS=	${PYTHON_PKGNAMEPREFIX}coverage>=4.2:devel/py-coverage@${PY_FLAVOR} \
+		${PYTHON_PKGNAMEPREFIX}pytest-cov>=2.4.0:devel/py-pytest-cov@${PY_FLAVOR}
+DOCS_BUILD_DEPENDS=	\
+		${PYTHON_PKGNAMEPREFIX}docutils>0:textproc/py-docutils@${PY_FLAVOR} \
+		${PYTHON_PKGNAMEPREFIX}funcparserlib>=1.0.0:devel/py-funcparserlib@${PY_FLAVOR} \
+		${PYTHON_PKGNAMEPREFIX}furo>0:textproc/py-furo@${PY_FLAVOR} \
+		${PYTHON_PKGNAMEPREFIX}pygments>0:textproc/py-pygments@${PY_FLAVOR} \
+		${PYTHON_PKGNAMEPREFIX}sphinx>0:textproc/py-sphinx@${PY_FLAVOR} \
+		${PYTHON_PKGNAMEPREFIX}sphinxcontrib-mermaid>0:textproc/py-sphinxcontrib-mermaid@${PY_FLAVOR}
+
+USES=		cmake:indirect python ssl
+USE_PYTHON=	autoplist pep517 pytest
+
+PEP517_BUILD_CONFIG_SETTING=	\
+		-Ccmake.define.BUILD_CMAKE_FROM_SOURCE=OFF \
+		-Ccmake.define.CMakePythonDistributions_SUPERBUILD=OFF \
+		-Ccmake.define.CMakeProject_BINARY_DISTRIBUTION_DIR=${WRKDIR}/cmake-tree/${LOCALBASE}
+
+pre-build:
+	@${MKDIR} ${WRKDIR}/cmake-tree
+	pkg info -l cmake-core | ${GREP} -v '^[0-9A-Za-z].*:$$' \
+		| ${SED} -E -e 's/^[ \t]*//' \
+		> ${WRKDIR}/cmake-tree/cmake-core.list
+	cat ${WRKDIR}/cmake-tree/cmake-core.list | ${TR} '\n' '\0' \
+		| ${XARGS} -0 ${TAR} -rf ${WRKDIR}/cmake-tree/cmake-core.tar
+	${TAR} -C ${WRKDIR}/cmake-tree -xf ${WRKDIR}/cmake-tree/cmake-core.tar
+
+do-build-DOCS-on:
+	cd ${WRKSRC} && \
+		${LOCALBASE}/bin/sphinx-build-${PYTHON_VER} -b html docs build/html
+
+do-install-DOCS-on:
+	@${MKDIR} ${STAGEDIR}${DOCSDIR}
+	cd ${WRKSRC}/build/html && ${COPYTREE_SHARE} . ${STAGEDIR}${DOCSDIR}
+
+post-install:
+.for file in ccmake cmake cpack ctest
+	${RM} ${STAGEDIR}${PREFIX}/bin/${file}
+.endfor
+.for plist_file in .PLIST.pymodtmp
+	${REINPLACE_CMD} -E \
+		-e '/^bin\/(ccmake|cmake|cpack|ctest)/d' \
+		${WRKDIR}/${plist_file}
+.endfor
+
+.include <bsd.port.mk>
diff --git a/devel/py-cmake/distinfo b/devel/py-cmake/distinfo
new file mode 100644
index 000000000..0bea230e8
--- /dev/null
+++ b/devel/py-cmake/distinfo
@@ -0,0 +1,3 @@
+TIMESTAMP = 1776428767
+SHA256 (python/cmake-3.31.10.tar.gz) = ec3d14a0e72e401b3665034dc37901df17f0b4e9c5b163be6cfedfb93470ac0f
+SIZE (python/cmake-3.31.10.tar.gz) = 34499
diff --git a/devel/py-cmake/pkg-descr b/devel/py-cmake/pkg-descr
new file mode 100644
index 000000000..913bbf5c5
--- /dev/null
+++ b/devel/py-cmake/pkg-descr
@@ -0,0 +1,9 @@
+CMake is used to control the software compilation process using simple platform
+and compiler independent configuration files, and generate native makefiles and
+workspaces that can be used in the compiler environment of your choice.
+
+The suite of CMake tools were created by Kitware in response to the need for
+a powerful, cross-platform build environment for open-source projects such as
+ITK and VTK.
+
+This is the CMake python wheels corresponding to Ports' default cmake version.
diff --git a/devel/py-cmake/pkg-plist b/devel/py-cmake/pkg-plist
new file mode 100644
index 000000000..39359474d
--- /dev/null
+++ b/devel/py-cmake/pkg-plist
@@ -0,0 +1,61 @@
+%%PORTDOCS%%%%DOCSDIR%%/.buildinfo
+%%PORTDOCS%%%%DOCSDIR%%/.doctrees/authors.doctree
+%%PORTDOCS%%%%DOCSDIR%%/.doctrees/build_system.doctree
+%%PORTDOCS%%%%DOCSDIR%%/.doctrees/building.doctree
+%%PORTDOCS%%%%DOCSDIR%%/.doctrees/contributing.doctree
+%%PORTDOCS%%%%DOCSDIR%%/.doctrees/environment.pickle
+%%PORTDOCS%%%%DOCSDIR%%/.doctrees/history.doctree
+%%PORTDOCS%%%%DOCSDIR%%/.doctrees/index.doctree
+%%PORTDOCS%%%%DOCSDIR%%/.doctrees/installation.doctree
+%%PORTDOCS%%%%DOCSDIR%%/.doctrees/make_a_release.doctree
+%%PORTDOCS%%%%DOCSDIR%%/.doctrees/update_cmake_version.doctree
+%%PORTDOCS%%%%DOCSDIR%%/.doctrees/usage.doctree
+%%PORTDOCS%%%%DOCSDIR%%/_sources/authors.rst.txt
+%%PORTDOCS%%%%DOCSDIR%%/_sources/build_system.rst.txt
+%%PORTDOCS%%%%DOCSDIR%%/_sources/building.rst.txt
+%%PORTDOCS%%%%DOCSDIR%%/_sources/contributing.rst.txt
+%%PORTDOCS%%%%DOCSDIR%%/_sources/history.rst.txt
+%%PORTDOCS%%%%DOCSDIR%%/_sources/index.rst.txt
+%%PORTDOCS%%%%DOCSDIR%%/_sources/installation.rst.txt
+%%PORTDOCS%%%%DOCSDIR%%/_sources/make_a_release.rst.txt
+%%PORTDOCS%%%%DOCSDIR%%/_sources/update_cmake_version.rst.txt
+%%PORTDOCS%%%%DOCSDIR%%/_sources/usage.rst.txt
+%%PORTDOCS%%%%DOCSDIR%%/_static/_sphinx_javascript_frameworks_compat.js
+%%PORTDOCS%%%%DOCSDIR%%/_static/basic.css
+%%PORTDOCS%%%%DOCSDIR%%/_static/debug.css
+%%PORTDOCS%%%%DOCSDIR%%/_static/doctools.js
+%%PORTDOCS%%%%DOCSDIR%%/_static/documentation_options.js
+%%PORTDOCS%%%%DOCSDIR%%/_static/file.png
+%%PORTDOCS%%%%DOCSDIR%%/_static/jquery-3.6.0.js
+%%PORTDOCS%%%%DOCSDIR%%/_static/jquery.js
+%%PORTDOCS%%%%DOCSDIR%%/_static/language_data.js
+%%PORTDOCS%%%%DOCSDIR%%/_static/minus.png
+%%PORTDOCS%%%%DOCSDIR%%/_static/plus.png
+%%PORTDOCS%%%%DOCSDIR%%/_static/pygments.css
+%%PORTDOCS%%%%DOCSDIR%%/_static/scripts/furo-extensions.js
+%%PORTDOCS%%%%DOCSDIR%%/_static/scripts/furo.js
+%%PORTDOCS%%%%DOCSDIR%%/_static/scripts/furo.js.LICENSE.txt
+%%PORTDOCS%%%%DOCSDIR%%/_static/scripts/furo.js.map
+%%PORTDOCS%%%%DOCSDIR%%/_static/searchtools.js
+%%PORTDOCS%%%%DOCSDIR%%/_static/skeleton.css
+%%PORTDOCS%%%%DOCSDIR%%/_static/sphinx_highlight.js
+%%PORTDOCS%%%%DOCSDIR%%/_static/styles/furo-extensions.css
+%%PORTDOCS%%%%DOCSDIR%%/_static/styles/furo-extensions.css.map
+%%PORTDOCS%%%%DOCSDIR%%/_static/styles/furo.css
+%%PORTDOCS%%%%DOCSDIR%%/_static/styles/furo.css.map
+%%PORTDOCS%%%%DOCSDIR%%/_static/underscore-1.13.1.js
+%%PORTDOCS%%%%DOCSDIR%%/_static/underscore.js
+%%PORTDOCS%%%%DOCSDIR%%/authors.html
+%%PORTDOCS%%%%DOCSDIR%%/build_system.html
+%%PORTDOCS%%%%DOCSDIR%%/building.html
+%%PORTDOCS%%%%DOCSDIR%%/contributing.html
+%%PORTDOCS%%%%DOCSDIR%%/genindex.html
+%%PORTDOCS%%%%DOCSDIR%%/history.html
+%%PORTDOCS%%%%DOCSDIR%%/index.html
+%%PORTDOCS%%%%DOCSDIR%%/installation.html
+%%PORTDOCS%%%%DOCSDIR%%/make_a_release.html
+%%PORTDOCS%%%%DOCSDIR%%/objects.inv
+%%PORTDOCS%%%%DOCSDIR%%/search.html
+%%PORTDOCS%%%%DOCSDIR%%/searchindex.js
+%%PORTDOCS%%%%DOCSDIR%%/update_cmake_version.html
+%%PORTDOCS%%%%DOCSDIR%%/usage.html
diff --git a/devel/py-game_sdl2/Makefile b/devel/py-game_sdl2/Makefile
index 0f2f09b94..4f0a0e542 100644
--- a/devel/py-game_sdl2/Makefile
+++ b/devel/py-game_sdl2/Makefile
@@ -1,6 +1,6 @@
 PORTNAME=	game_sdl2
 PORTVERSION=	7.4.11
-PORTREVISION=	6
+PORTREVISION=	7
 CATEGORIES=	devel python
 MASTER_SITES=	http://www.renpy.org/dl/${PORTVERSION}/
 PKGNAMEPREFIX=	${PYTHON_PKGNAMEPREFIX}
diff --git a/devel/py-game_sdl2/files/patch-setup.cfg b/devel/py-game_sdl2/files/patch-setup.cfg
new file mode 100644
index 000000000..1396a4426
--- /dev/null
+++ b/devel/py-game_sdl2/files/patch-setup.cfg
@@ -0,0 +1,8 @@
+--- setup.cfg.orig	2026-04-11 01:34:18 UTC
++++ setup.cfg
+@@ -1,4 +1,4 @@
+ [egg_info]
+-tag_build = -for-renpy-7.4.11
++tag_build = +for-renpy-7.4.11
+ tag_date = 0
+ 
diff --git a/devel/py-opendht/Makefile b/devel/py-opendht/Makefile
index bec17cd8e..3d4fe7eb8 100644
--- a/devel/py-opendht/Makefile
+++ b/devel/py-opendht/Makefile
@@ -1,6 +1,7 @@
 PORTNAME=	opendht
 DISTVERSIONPREFIX=	v
 DISTVERSION=	3.3.1
+PORTREVISION=	1
 CATEGORIES=	devel net
 PKGNAMEPREFIX=	${PYTHON_PKGNAMEPREFIX}
 
diff --git a/devel/py-opendht/files/patch-CMakeLists.txt b/devel/py-opendht/files/patch-CMakeLists.txt
new file mode 100644
index 000000000..1aec5a8eb
--- /dev/null
+++ b/devel/py-opendht/files/patch-CMakeLists.txt
@@ -0,0 +1,17 @@
+--- CMakeLists.txt.orig	2026-04-12 07:42:08 UTC
++++ CMakeLists.txt
+@@ -1,6 +1,7 @@ set(CURRENT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
+ 
+ set(CURRENT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
+ set(CURRENT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
++set(PACKAGE_VERSION "3.3.1")
+ 
+ configure_file(setup.py.in setup.py)
+ configure_file(pyproject.toml pyproject.toml COPYONLY)
+@@ -16,4 +17,4 @@ if (OPENDHT_TOOLS)
+ install(CODE "execute_process(COMMAND python3 setup.py install --root=\$ENV{DESTDIR}/ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})")
+ if (OPENDHT_TOOLS)
+ 	install(PROGRAMS tools/dhtcluster.py DESTINATION ${CMAKE_INSTALL_BINDIR} RENAME dhtcluster)
+-endif()
+\ No newline at end of file
++endif()
diff --git a/devel/py-persistent/Makefile b/devel/py-persistent/Makefile
index e3c8884de..21791319a 100644
--- a/devel/py-persistent/Makefile
+++ b/devel/py-persistent/Makefile
@@ -1,6 +1,6 @@
 PORTNAME=	persistent
 DISTVERSION=	4.9.3
-PORTREVISION=	1
+PORTREVISION=	2
 CATEGORIES=	devel python
 MASTER_SITES=	PYPI
 PKGNAMEPREFIX=	${PYTHON_PKGNAMEPREFIX}
diff --git a/devel/py-persistent/files/patch-src_persistent_cPickleCache.c b/devel/py-persistent/files/patch-src_persistent_cPickleCache.c
new file mode 100644
index 000000000..d010e40ed
--- /dev/null
+++ b/devel/py-persistent/files/patch-src_persistent_cPickleCache.c
@@ -0,0 +1,29 @@
+--- src/persistent/cPickleCache.c.orig	2026-04-19 11:48:14 UTC
++++ src/persistent/cPickleCache.c
+@@ -623,7 +623,7 @@ cc_oid_unreferenced(ccobject *self, PyObject *oid)
+ 
+     dead_pers_obj = (cPersistentObject*)PyDict_GetItem(self->data, oid);
+     assert(dead_pers_obj);
+-    assert(dead_pers_obj->ob_refcnt == 0);
++    assert(Py_REFCNT(dead_pers_obj) == 0);
+ 
+     dead_pers_obj_ref_to_self = (ccobject*)dead_pers_obj->cache;
+     assert(dead_pers_obj_ref_to_self == self);
+@@ -633,7 +633,7 @@ cc_oid_unreferenced(ccobject *self, PyObject *oid)
+     */
+ 
+     Py_INCREF(dead_pers_obj);
+-    assert(dead_pers_obj->ob_refcnt == 1);
++    assert(Py_REFCNT(dead_pers_obj) == 1);
+     /* Incremement the refcount again, because delitem is going to
+         DECREF it.  If its refcount reached zero again, we'd call back to
+         the dealloc function that called us.
+@@ -662,7 +662,7 @@ cc_oid_unreferenced(ccobject *self, PyObject *oid)
+     Py_DECREF(dead_pers_obj_ref_to_self);
+     dead_pers_obj->cache = NULL;
+ 
+-    assert(dead_pers_obj->ob_refcnt == 1);
++    assert(Py_REFCNT(dead_pers_obj) == 1);
+ 
+     /* Don't DECREF the object, because this function is called from
+         the object's dealloc function. If the refcnt reaches zero (again), it
diff --git a/devel/py-tree-sitter/Makefile b/devel/py-tree-sitter/Makefile
index 89a8e8f72..4e3fe8b2a 100644
--- a/devel/py-tree-sitter/Makefile
+++ b/devel/py-tree-sitter/Makefile
@@ -1,6 +1,6 @@
 PORTNAME=	tree-sitter
 PORTVERSION=	0.20.4
-PORTREVISION=	1
+PORTREVISION=	2
 CATEGORIES=	devel python
 MASTER_SITES=	PYPI
 PKGNAMEPREFIX=	${PYTHON_PKGNAMEPREFIX}
diff --git a/devel/py-tree-sitter/files/patch-tree__sitter_____init____.py b/devel/py-tree-sitter/files/patch-tree__sitter_____init____.py
new file mode 100644
index 000000000..4f6d9204f
--- /dev/null
+++ b/devel/py-tree-sitter/files/patch-tree__sitter_____init____.py
@@ -0,0 +1,15 @@
+--- tree_sitter/__init__.py.orig	2023-11-13 05:21:18 UTC
++++ tree_sitter/__init__.py
+@@ -115,10 +115,12 @@ class Language:
+                         extra_preargs=flags,
+                     )[0]
+                 )
++            flags =["-shared", "-fPIC"]
+             compiler.link_shared_object(
+                 object_paths,
+                 output_path,
+                 target_lang="c++" if cpp else "c",
++                extra_preargs=flags,
+             )
+         return True
+ 
diff --git a/devel/py-virtualenvwrapper/Makefile b/devel/py-virtualenvwrapper/Makefile
index 2fc8cc8cb..6610e72d7 100644
--- a/devel/py-virtualenvwrapper/Makefile
+++ b/devel/py-virtualenvwrapper/Makefile
@@ -1,6 +1,5 @@
 PORTNAME=	virtualenvwrapper
-PORTVERSION=	4.8.4
-PORTREVISION=	2
+PORTVERSION=	6.1.1
 CATEGORIES=	devel python
 MASTER_SITES=	PYPI
 PKGNAMEPREFIX=	${PYTHON_PKGNAMEPREFIX}
@@ -12,45 +11,57 @@ WWW=		https://virtualenvwrapper.readthedocs.io/
 LICENSE=	MIT
 LICENSE_FILE=	${WRKSRC}/LICENSE
 
-BUILD_DEPENDS=	${PYTHON_PKGNAMEPREFIX}pbr>0:devel/py-pbr@${PY_FLAVOR}
+BUILD_DEPENDS=	${PYTHON_PKGNAMEPREFIX}setuptools>0:devel/py-setuptools@${PY_FLAVOR} \
+		${PYTHON_PKGNAMEPREFIX}setuptools-scm>=6.2:devel/py-setuptools-scm@${PY_FLAVOR} \
+		${PYTHON_PKGNAMEPREFIX}sphinx>=0,1:textproc/py-sphinx@${PY_FLAVOR} \
+		${PYTHON_PKGNAMEPREFIX}wheel>0:devel/py-wheel@${PY_FLAVOR}
 RUN_DEPENDS=	${PYTHON_PKGNAMEPREFIX}stevedore>0:devel/py-stevedore@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}virtualenv>0:devel/py-virtualenv@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}virtualenv-clone>0:devel/py-virtualenv-clone@${PY_FLAVOR}
 
-# Actually 2.6-2.7,3.3-3.6
+# Actually 3.8-3.12
 USES=		python
-USE_PYTHON=	autoplist concurrent distutils
+USE_PYTHON=	autoplist concurrent pep517
 
 OPTIONS_DEFINE=	DOCS
 
-DOCS_BUILD_DEPENDS=	${PYTHON_PKGNAMEPREFIX}sphinx>=0,1:textproc/py-sphinx@${PY_FLAVOR} \
-			${PYTHON_PKGNAMEPREFIX}sphinxcontrib-bitbucket>=1.0:textproc/py-sphinxcontrib-bitbucket@${PY_FLAVOR}
-DOCS_VARS=		PYDISTUTILS_BUILD_TARGET+=build_sphinx \
-			PYDISTUTILS_BUILDARGS="-a -E"
 
+DOCS_MAKE_ENV=	PYTHONPATH=${WRKSRC}
+PLIST_FILES=	share/man/man1/virtualenvwrapper.1.gz
 PORTDOCS=	*
 
 NO_ARCH=	yes
 
 post-patch:
-	${REINPLACE_CMD} \
-		-e 's|$$(command \\which python)|${PYTHON_CMD}|1' \
+	${REINPLACE_CMD} -E \
+		-e 's|which virtualenvwrapper.sh|which ${PORTNAME}.sh${UNIQUE_SUFFIX}|' \
+		-e 's|(_virtualenvwrapper_python_executable)=".*"|\1=${PYTHON_CMD}|1' \
 		-e 's|="virtualenv"|="virtualenv${UNIQUE_SUFFIX}"|1' \
 		-e 's|="virtualenv-clone"|="virtualenv-clone${UNIQUE_SUFFIX}"|1' \
-		${WRKSRC}/${PORTNAME}.sh
-	${REINPLACE_CMD} \
-		-e 's|which virtualenvwrapper.sh|which ${PORTNAME}.sh${UNIQUE_SUFFIX}|' \
+		-e 's|\$$\{\.sh\.file\}|$$0|1' \
+		-e 's|function (.*) \{|\1 ( ) {|' \
+		-e 's/(COMPREPLY|reply|in_args|out_args|args)=\((.*)\)/\1=\2/' \
+		-e 's|typeset ([^=]*)|\1=|' \
+		-e 's|typeset ||' \
+		-e 's|source |. |' \
+		${WRKSRC}/${PORTNAME}.sh \
 		${WRKSRC}/${PORTNAME}_lazy.sh
 
-post-patch-DOCS-on:
-	@${REINPLACE_CMD} -e 's|python setup.py|${PYTHON_CMD} setup.py|' \
-		${WRKSRC}/docs/source/conf.py
+post-build:
+	cd ${WRKSRC}/docs && ${SETENVI} ${MAKE_ENV} \
+		${BSDMAKE} SPHINX_BUILD=${LOCALBASE}/bin/sphinx-build${UNIQUE_SUFFIX} man
 
 post-build-DOCS-on:
-	@${RM} ${WRKSRC}/docs/build/html/.buildinfo
+	cd ${WRKSRC}/docs && ${SETENVI} ${MAKE_ENV} \
+		${BSDMAKE} SPHINX_BUILD=${LOCALBASE}/bin/sphinx-build${UNIQUE_SUFFIX} html
+
+post-install:
+	${INSTALL_MAN} ${WRKSRC}/docs/build/man/virtualenvwrapper.1 \
+		${STAGEDIR}${PREFIX}/share/man/man1
 
 post-install-DOCS-on:
 	${MKDIR} ${STAGEDIR}${DOCSDIR}
-	@cd ${WRKSRC}/docs/build/html && ${COPYTREE_SHARE} . ${STAGEDIR}${DOCSDIR}
+	@cd ${WRKSRC}/docs/build/html && \
+		${COPYTREE_SHARE} . ${STAGEDIR}${DOCSDIR} "-not ( -name .buildinfo )"
 
 .include <bsd.port.mk>
diff --git a/devel/py-virtualenvwrapper/distinfo b/devel/py-virtualenvwrapper/distinfo
index cd0c95445..5e92d4012 100644
--- a/devel/py-virtualenvwrapper/distinfo
+++ b/devel/py-virtualenvwrapper/distinfo
@@ -1,3 +1,3 @@
-TIMESTAMP = 1584492404
-SHA256 (virtualenvwrapper-4.8.4.tar.gz) = 51a1a934e7ed0ff221bdd91bf9d3b604d875afbb3aa2367133503fee168f5bfa
-SIZE (virtualenvwrapper-4.8.4.tar.gz) = 334920
+TIMESTAMP = 1777103810
+SHA256 (virtualenvwrapper-6.1.1.tar.gz) = 112e7ea34a9a3ce90aaea54182f0d3afef4d1a913eeb75e98a263b4978cd73c6
+SIZE (virtualenvwrapper-6.1.1.tar.gz) = 95964
diff --git a/devel/py-virtualenvwrapper/files/patch-virtualenvwrapper_user__scripts.py b/devel/py-virtualenvwrapper/files/patch-virtualenvwrapper_user__scripts.py
new file mode 100644
index 000000000..c5e3dc1b0
--- /dev/null
+++ b/devel/py-virtualenvwrapper/files/patch-virtualenvwrapper_user__scripts.py
@@ -0,0 +1,65 @@
+--- virtualenvwrapper/user_scripts.py.orig	2026-04-25 10:17:06 UTC
++++ virtualenvwrapper/user_scripts.py
+@@ -202,7 +202,7 @@ def initialize_source(args):
+ # Run user-provided scripts
+ #
+ [ -f "$VIRTUALENVWRAPPER_HOOK_DIR/initialize" ] && \
+-    source "$VIRTUALENVWRAPPER_HOOK_DIR/initialize"
++    . "$VIRTUALENVWRAPPER_HOOK_DIR/initialize"
+ """
+ 
+ 
+@@ -223,7 +223,7 @@ def post_mkvirtualenv_source(args):
+ # Run user-provided scripts
+ #
+ [ -f "$VIRTUALENVWRAPPER_HOOK_DIR/postmkvirtualenv" ] && \
+-    source "$VIRTUALENVWRAPPER_HOOK_DIR/postmkvirtualenv"
++    . "$VIRTUALENVWRAPPER_HOOK_DIR/postmkvirtualenv"
+ """
+ 
+ 
+@@ -244,7 +244,7 @@ def post_cpvirtualenv_source(args):
+ # Run user-provided scripts
+ #
+ [ -f "$VIRTUALENVWRAPPER_HOOK_DIR/postcpvirtualenv" ] && \
+-    source "$VIRTUALENVWRAPPER_HOOK_DIR/postcpvirtualenv"
++    . "$VIRTUALENVWRAPPER_HOOK_DIR/postcpvirtualenv"
+ """
+ 
+ 
+@@ -276,9 +276,9 @@ def post_activate_source(args):
+ # Run user-provided scripts
+ #
+ [ -f "$VIRTUALENVWRAPPER_HOOK_DIR/postactivate" ] && \
+-    source "$VIRTUALENVWRAPPER_HOOK_DIR/postactivate"
++    . "$VIRTUALENVWRAPPER_HOOK_DIR/postactivate"
+ [ -f "$VIRTUAL_ENV/$VIRTUALENVWRAPPER_ENV_BIN_DIR/postactivate" ] && \
+-    source "$VIRTUAL_ENV/$VIRTUALENVWRAPPER_ENV_BIN_DIR/postactivate"
++    . "$VIRTUAL_ENV/$VIRTUALENVWRAPPER_ENV_BIN_DIR/postactivate"
+ """
+ 
+ 
+@@ -289,9 +289,9 @@ def pre_deactivate_source(args):
+ # Run user-provided scripts
+ #
+ [ -f "$VIRTUAL_ENV/$VIRTUALENVWRAPPER_ENV_BIN_DIR/predeactivate" ] && \
+-    source "$VIRTUAL_ENV/$VIRTUALENVWRAPPER_ENV_BIN_DIR/predeactivate"
++    . "$VIRTUAL_ENV/$VIRTUALENVWRAPPER_ENV_BIN_DIR/predeactivate"
+ [ -f "$VIRTUALENVWRAPPER_HOOK_DIR/predeactivate" ] && \
+-    source "$VIRTUALENVWRAPPER_HOOK_DIR/predeactivate"
++    . "$VIRTUALENVWRAPPER_HOOK_DIR/predeactivate"
+ """
+ 
+ 
+@@ -303,9 +303,9 @@ VIRTUALENVWRAPPER_LAST_VIRTUAL_ENV="$WORKON_HOME/%(env
+ #
+ VIRTUALENVWRAPPER_LAST_VIRTUAL_ENV="$WORKON_HOME/%(env_name)s"
+ [ -f "$WORKON_HOME/%(env_name)s/bin/postdeactivate" ] && \
+-    source "$WORKON_HOME/%(env_name)s/bin/postdeactivate"
++    . "$WORKON_HOME/%(env_name)s/bin/postdeactivate"
+ [ -f "$VIRTUALENVWRAPPER_HOOK_DIR/postdeactivate" ] && \
+-    source "$VIRTUALENVWRAPPER_HOOK_DIR/postdeactivate"
++    . "$VIRTUALENVWRAPPER_HOOK_DIR/postdeactivate"
+ unset VIRTUALENVWRAPPER_LAST_VIRTUAL_ENV
+ """ % {'env_name': args[0]}
+ 
diff --git a/devel/py-zconfig/Makefile b/devel/py-zconfig/Makefile
index 943e1fbd5..46da4c1df 100644
--- a/devel/py-zconfig/Makefile
+++ b/devel/py-zconfig/Makefile
@@ -1,5 +1,5 @@
 PORTNAME=	ZConfig
-DISTVERSION=	4.2
+DISTVERSION=	4.3
 CATEGORIES=	devel python
 MASTER_SITES=	PYPI
 PKGNAMEPREFIX=	${PYTHON_PKGNAMEPREFIX}
@@ -13,7 +13,7 @@ WWW=		https://pypi.org/project/ZConfig/
 LICENSE=	ZPL21
 LICENSE_FILE=	${WRKSRC}/LICENSE.txt
 
-BUILD_DEPENDS=	${PYTHON_PKGNAMEPREFIX}setuptools>=0:devel/py-setuptools@${PY_FLAVOR} \
+BUILD_DEPENDS=	${PYTHON_PKGNAMEPREFIX}setuptools>=78.1.1:devel/py-setuptools@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}wheel>=0:devel/py-wheel@${PY_FLAVOR}
 
 NO_ARCH=	yes
diff --git a/devel/py-zconfig/distinfo b/devel/py-zconfig/distinfo
index 19e107543..46499925d 100644
--- a/devel/py-zconfig/distinfo
+++ b/devel/py-zconfig/distinfo
@@ -1,3 +1,3 @@
-TIMESTAMP = 1738155884
-SHA256 (zope/zconfig-4.2.tar.gz) = a0e4b5277c4cee8060ce335a578ac458f82c240ae96b16659200dbc4d98bfcce
-SIZE (zope/zconfig-4.2.tar.gz) = 127198
+TIMESTAMP = 1776734539
+SHA256 (zope/zconfig-4.3.tar.gz) = 472233e515fa29be6c873e78b8a2b450c2cd25d0133cb45960837f33f1ab4fe3
+SIZE (zope/zconfig-4.3.tar.gz) = 128126
diff --git a/devel/py-zconfig/files/patch-pyproject.toml b/devel/py-zconfig/files/patch-pyproject.toml
new file mode 100644
index 000000000..fe9115fd7
--- /dev/null
+++ b/devel/py-zconfig/files/patch-pyproject.toml
@@ -0,0 +1,11 @@
+--- pyproject.toml.orig	2026-04-21 01:23:28 UTC
++++ pyproject.toml
+@@ -4,7 +4,7 @@ requires = [
+ 
+ [build-system]
+ requires = [
+-    "setuptools >= 78.1.1,< 81",
++    "setuptools >= 78.1.1",
+     "wheel",
+ ]
+ build-backend = "setuptools.build_meta"
diff --git a/finance/py-bitcoin/Makefile b/finance/py-bitcoin/Makefile
index 1592c4cb7..22e120305 100644
--- a/finance/py-bitcoin/Makefile
+++ b/finance/py-bitcoin/Makefile
@@ -20,7 +20,7 @@ NO_ARCH=	yes
 POST_PLIST=	fix-plist
 
 fix-plist:
-	@${REINPLACE_CMD} -e "s|^LICENSE$$||" ${TMPPLIST}
+	@${REINPLACE_CMD} -E -e "s|^(\./)?LICENSE$$||" ${TMPPLIST}
 
 post-install:
 	${RM} ${STAGEDIR}${PREFIX}/LICENSE
diff --git a/graphics/py-pyvista/Makefile b/graphics/py-pyvista/Makefile
index c7d4bbb8a..f979d1dea 100644
--- a/graphics/py-pyvista/Makefile
+++ b/graphics/py-pyvista/Makefile
@@ -1,6 +1,6 @@
 PORTNAME=	pyvista
 DISTVERSION=	0.34.2
-PORTREVISION=	9
+PORTREVISION=	10
 CATEGORIES=	graphics python
 MASTER_SITES=	PYPI
 PKGNAMEPREFIX=	${PYTHON_PKGNAMEPREFIX}
diff --git a/graphics/py-pyvista/files/patch-setup.py b/graphics/py-pyvista/files/patch-setup.py
new file mode 100644
index 000000000..f64db2b3e
--- /dev/null
+++ b/graphics/py-pyvista/files/patch-setup.py
@@ -0,0 +1,11 @@
+--- setup.py.orig	2026-04-13 05:09:30 UTC
++++ setup.py
+@@ -71,7 +71,7 @@ setup(
+             '2k_earth_daymap.jpg',
+         ],
+     },
+-    python_requires='>=3.7.*',
++    python_requires='>=3.7',
+     install_requires=install_requires,
+     extras_require={
+         'all': ['matplotlib', 'colorcet', 'cmocean', 'meshio'],
diff --git a/graphics/rapid-photo-downloader/Makefile b/graphics/rapid-photo-downloader/Makefile
index 8228ffa13..4f9a63a39 100644
--- a/graphics/rapid-photo-downloader/Makefile
+++ b/graphics/rapid-photo-downloader/Makefile
@@ -1,6 +1,6 @@
 PORTNAME=	rapid-photo-downloader
 DISTVERSION=	0.9.26
-PORTREVISION=	14
+PORTREVISION=	15
 CATEGORIES=	graphics
 MASTER_SITES=	https://launchpad.net/rapid/pyqt/${PORTVERSION}/+download/
 
diff --git a/graphics/rapid-photo-downloader/files/patch-raphodo_rapid.py b/graphics/rapid-photo-downloader/files/patch-raphodo_rapid.py
index 86b085ca3..9890b6b32 100644
--- a/graphics/rapid-photo-downloader/files/patch-raphodo_rapid.py
+++ b/graphics/rapid-photo-downloader/files/patch-raphodo_rapid.py
@@ -1,6 +1,6 @@
---- raphodo/rapid.py.orig	2020-05-03 17:31:45 UTC
+--- raphodo/rapid.py.orig	2020-12-24 23:41:26 UTC
 +++ raphodo/rapid.py
-@@ -97,7 +97,7 @@ from PyQt5.QtNetwork import QLocalSocket, QLocalServer
+@@ -101,7 +101,7 @@ from raphodo.storage import (
  import sip
  
  from raphodo.storage import (
@@ -9,7 +9,7 @@
      has_one_or_more_folders, mountPaths, get_desktop_environment, get_desktop,
      gvfs_controls_mounts, get_default_file_manager, validate_download_folder,
      validate_source_folder, get_fdo_cache_thumb_base_directory, WatchDownloadDirs, get_media_dir,
-@@ -945,18 +945,6 @@ class RapidWindow(QMainWindow):
+@@ -949,18 +949,6 @@ class RapidWindow(QMainWindow):
              logging.debug("Starting camera hotplug monitor...")
              QTimer.singleShot(0, self.cameraHotplugThread.start)
  
@@ -28,7 +28,7 @@
          if self.gvfsControlsMounts:
              # Gio.VolumeMonitor must be in the main thread, according to
              # Gnome documentation
-@@ -4748,8 +4736,6 @@ Do you want to proceed with the download?
+@@ -4752,8 +4740,6 @@ Do you want to proceed with the download?
              self.sendTerminateToThread(self.backup_controller)
  
          if not self.gvfsControlsMounts:
diff --git a/graphics/rapid-photo-downloader/files/patch-raphodo_utilities.py b/graphics/rapid-photo-downloader/files/patch-raphodo_utilities.py
index dbc96fdd6..2fbab62d8 100644
--- a/graphics/rapid-photo-downloader/files/patch-raphodo_utilities.py
+++ b/graphics/rapid-photo-downloader/files/patch-raphodo_utilities.py
@@ -1,6 +1,6 @@
---- raphodo/utilities.py.orig	2020-05-03 17:31:45 UTC
+--- raphodo/utilities.py.orig	2020-12-24 23:41:26 UTC
 +++ raphodo/utilities.py
-@@ -83,10 +83,11 @@ if arrow_version >= parse_version('0.14.3') and arrow_
+@@ -84,10 +84,11 @@ if arrow_version >= parse_version('0.14.3') and arrow_
  # Linux specific code to ensure child processes exit when parent dies
  # See http://stackoverflow.com/questions/19447603/
  # how-to-kill-a-python-child-process-created-with-subprocess-check-output-when-t/
diff --git a/graphics/rapid-photo-downloader/files/patch-setup.py b/graphics/rapid-photo-downloader/files/patch-setup.py
index 3e788e0da..3eb819766 100644
--- a/graphics/rapid-photo-downloader/files/patch-setup.py
+++ b/graphics/rapid-photo-downloader/files/patch-setup.py
@@ -1,4 +1,4 @@
---- setup.py.orig	2020-05-03 17:31:45 UTC
+--- setup.py.orig	2020-12-24 23:41:26 UTC
 +++ setup.py
 @@ -271,7 +271,6 @@ setup(
          'scandir;python_version<"3.5"',
@@ -8,3 +8,12 @@
          'babel',
      ],
      extras_require={
+@@ -302,7 +301,7 @@ setup(
+         )
+     ],
+     packages=['raphodo'],
+-    python_requires='>=3.4.*, <4',
++    python_requires='>=3.4, <4',
+     entry_points={
+         'gui_scripts': ['rapid-photo-downloader=raphodo.rapid:main'],
+         'console_scripts': ['analyze-pv-structure=raphodo.analyzephotos:main']
diff --git a/irc/py-limnoria/Makefile b/irc/py-limnoria/Makefile
index feb80a443..3df876ac7 100644
--- a/irc/py-limnoria/Makefile
+++ b/irc/py-limnoria/Makefile
@@ -1,6 +1,6 @@
 PORTNAME=	limnoria
 PORTVERSION=	2021.11.18
-PORTREVISION=	3
+PORTREVISION=	4
 CATEGORIES=	irc python
 PKGNAMEPREFIX=	${PYTHON_PKGNAMEPREFIX}
 
@@ -56,6 +56,12 @@ SQLITE_RUN_DEPENDS=	${PYTHON_PKGNAMEPREFIX}sqlite3>0:databases/py-sqlite3@${PY_F
 TIME_RUN_DEPENDS=	${PYTHON_PKGNAMEPREFIX}python-dateutil>=0:devel/py-python-dateutil@${PY_FLAVOR} \
 			${PYTHON_PKGNAMEPREFIX}pytz>=0:devel/py-pytz@${PY_FLAVOR}
 
+SUB_FILES=	version.py
+SUB_LIST=	VERSION=${PORTVERSION}
+
+pre-configure:
+	${CP} ${WRKDIR}/version.py ${WRKSRC}/src
+
 # Needs to be installed first to work.
 do-test:
 	@cd ${WRKSRC} && ${PYTHON_CMD} ${LOCALBASE}/bin/supybot-test \
diff --git a/irc/py-limnoria/files/version.py.in b/irc/py-limnoria/files/version.py.in
new file mode 100644
index 000000000..7ad5ec074
--- /dev/null
+++ b/irc/py-limnoria/files/version.py.in
@@ -0,0 +1 @@
+version = "%%VERSION%%"
diff --git a/math/py-mathics-scanner/Makefile b/math/py-mathics-scanner/Makefile
index 723040838..da95d726a 100644
--- a/math/py-mathics-scanner/Makefile
+++ b/math/py-mathics-scanner/Makefile
@@ -1,6 +1,6 @@
 PORTNAME=	Mathics_Scanner
 PORTVERSION=	2.0.0
-PORTREVISION=	1
+PORTREVISION=	2
 CATEGORIES=	math python
 MASTER_SITES=	PYPI
 PKGNAMEPREFIX=	${PYTHON_PKGNAMEPREFIX}
diff --git a/math/py-mathics-scanner/pkg-plist b/math/py-mathics-scanner/pkg-plist
index fa400f8a4..5fd366044 100644
--- a/math/py-mathics-scanner/pkg-plist
+++ b/math/py-mathics-scanner/pkg-plist
@@ -1,12 +1,13 @@
 bin/mathics3-generate-json-table
 bin/mathics3-generate-operator-json-table
 bin/mathics3-tokens
-%%PYTHON_SITELIBDIR%%/Mathics_Scanner-%%VER%%.dist-info/AUTHORS.txt
-%%PYTHON_SITELIBDIR%%/Mathics_Scanner-%%VER%%.dist-info/METADATA
-%%PYTHON_SITELIBDIR%%/Mathics_Scanner-%%VER%%.dist-info/RECORD
-%%PYTHON_SITELIBDIR%%/Mathics_Scanner-%%VER%%.dist-info/WHEEL
-%%PYTHON_SITELIBDIR%%/Mathics_Scanner-%%VER%%.dist-info/entry_points.txt
-%%PYTHON_SITELIBDIR%%/Mathics_Scanner-%%VER%%.dist-info/top_level.txt
+%%PYTHON_SITELIBDIR%%/mathics_scanner-%%VER%%.dist-info/METADATA
+%%PYTHON_SITELIBDIR%%/mathics_scanner-%%VER%%.dist-info/RECORD
+%%PYTHON_SITELIBDIR%%/mathics_scanner-%%VER%%.dist-info/WHEEL
+%%PYTHON_SITELIBDIR%%/mathics_scanner-%%VER%%.dist-info/entry_points.txt
+%%PYTHON_SITELIBDIR%%/mathics_scanner-%%VER%%.dist-info/licenses/AUTHORS.txt
+%%PYTHON_SITELIBDIR%%/mathics_scanner-%%VER%%.dist-info/licenses/COPYING.txt
+%%PYTHON_SITELIBDIR%%/mathics_scanner-%%VER%%.dist-info/top_level.txt
 %%PYTHON_SITELIBDIR%%/mathics_scanner/__init__.py
 %%PYTHON_SITELIBDIR%%/mathics_scanner/__pycache__/__init__%%PYTHON_TAG%%.opt-1.pyc
 %%PYTHON_SITELIBDIR%%/mathics_scanner/__pycache__/__init__%%PYTHON_TAG%%.pyc
diff --git a/math/py-petsc4py/Makefile b/math/py-petsc4py/Makefile
index e6e7c1aa1..7063e9ca4 100644
--- a/math/py-petsc4py/Makefile
+++ b/math/py-petsc4py/Makefile
@@ -1,6 +1,6 @@
 PORTNAME=	petsc4py
 DISTVERSION=	3.22.4
-PORTREVISION=	2
+PORTREVISION=	3
 CATEGORIES=	math python
 MASTER_SITES=	PYPI
 PKGNAMEPREFIX=	${PYTHON_PKGNAMEPREFIX}
diff --git a/math/py-petsc4py/files/patch-conf_confpetsc.py b/math/py-petsc4py/files/patch-conf_confpetsc.py
new file mode 100644
index 000000000..b99139929
--- /dev/null
+++ b/math/py-petsc4py/files/patch-conf_confpetsc.py
@@ -0,0 +1,10 @@
+--- conf/confpetsc.py.orig	2026-04-12 03:48:08 UTC
++++ conf/confpetsc.py
+@@ -694,7 +694,6 @@ class build_ext(_build_ext):
+             (config_file, config_data),
+             msg='writing %s' % config_file,
+             verbose=self.verbose,
+-            dry_run=self.dry_run,
+         )
+ 
+     def get_config_data(self, arch_list):
diff --git a/misc/thefuck/Makefile b/misc/thefuck/Makefile
index b5bf1f2b6..58d78e517 100644
--- a/misc/thefuck/Makefile
+++ b/misc/thefuck/Makefile
@@ -1,6 +1,6 @@
 PORTNAME=	thefuck
 DISTVERSION=	3.32
-PORTREVISION=	1
+PORTREVISION=	2
 CATEGORIES=	misc python
 MASTER_SITES=	PYPI
 
diff --git a/misc/thefuck/files/patch-fastentrypoints.py b/misc/thefuck/files/patch-fastentrypoints.py
new file mode 100644
index 000000000..2bf0116ab
--- /dev/null
+++ b/misc/thefuck/files/patch-fastentrypoints.py
@@ -0,0 +1,34 @@
+--- fastentrypoints.py.orig	2021-12-19 20:26:39 UTC
++++ fastentrypoints.py
+@@ -35,6 +35,7 @@ http://github.com/ninjaaron/fast-entry_points
+ (c) 2016, Aaron Christianson
+ http://github.com/ninjaaron/fast-entry_points
+ '''
++from importlib.metadata import entry_points
+ from setuptools.command import easy_install
+ import re
+ TEMPLATE = r'''\
+@@ -59,17 +60,17 @@ def get_args(cls, dist, header=None):
+     """
+     if header is None:
+         header = cls.get_header()
+-    spec = str(dist.as_requirement())
++    spec = f'{dist.name}=={dist.version}'
+     for type_ in 'console', 'gui':
+         group = type_ + '_scripts'
+-        for name, ep in dist.get_entry_map(group).items():
++        for ep in entry_points(group=group, name='thefuck'):
+             # ensure_safe_name
+-            if re.search(r'[\\/]', name):
++            if re.search(r'[\\/]', ep.name):
+                 raise ValueError("Path separators not allowed in script names")
+             script_text = TEMPLATE.format(
+-                          ep.module_name, ep.attrs[0], '.'.join(ep.attrs),
+-                          spec, group, name)
+-            args = cls._get_script_args(type_, name, header, script_text)
++                          ep.module, ep.attr, ep.attr,
++                          spec, group, ep.name)
++            args = cls._get_script_args(type_, ep.name, header, script_text)
+             for res in args:
+                 yield res
+ 
diff --git a/net/ryu/Makefile b/net/ryu/Makefile
index 83c65e5b8..254ba2a8c 100644
--- a/net/ryu/Makefile
+++ b/net/ryu/Makefile
@@ -1,7 +1,7 @@
 PORTNAME=	ryu
 PORTVERSION=	4.26
 DISTVERSIONPREFIX=	v
-PORTREVISION=	7
+PORTREVISION=	8
 CATEGORIES=	net python
 PKGNAMEPREFIX=	${PYTHON_PKGNAMEPREFIX}
 
diff --git a/net/ryu/files/patch-ryu_hooks.py b/net/ryu/files/patch-ryu_hooks.py
new file mode 100644
index 000000000..7a68402e4
--- /dev/null
+++ b/net/ryu/files/patch-ryu_hooks.py
@@ -0,0 +1,20 @@
+--- ryu/hooks.py.orig	2026-04-15 06:02:21 UTC
++++ ryu/hooks.py
+@@ -33,7 +33,7 @@ def save_orig():
+     """Save original easy_install.get_script_args.
+     This is necessary because pbr's setup_hook is sometimes called
+     before ours."""
+-    _main_module()._orig_get_script_args = easy_install.get_script_args
++    _main_module()._orig_get_script_args = easy_install.ScriptWriter._get_script_args
+ 
+ 
+ def setup_hook(config):
+@@ -57,7 +57,7 @@ def setup_hook(config):
+         return _main_module()._orig_get_script_args(*args, **kwargs)
+ 
+     packaging.override_get_script_args = my_get_script_args
+-    easy_install.get_script_args = my_get_script_args
++    easy_install.ScriptWriter._get_script_args = my_get_script_args
+ 
+     # another hack to allow setup from tarball.
+     orig_get_version = packaging.get_version
diff --git a/science/py-meshio/Makefile b/science/py-meshio/Makefile
index e58f25326..80cadd2ed 100644
--- a/science/py-meshio/Makefile
+++ b/science/py-meshio/Makefile
@@ -1,6 +1,6 @@
 PORTNAME=	meshio
 PORTVERSION=	5.3.5
-PORTREVISION=	1
+PORTREVISION=	2
 CATEGORIES=	science cad python
 MASTER_SITES=	PYPI
 PKGNAMEPREFIX=	${PYTHON_PKGNAMEPREFIX}
diff --git a/science/py-meshio/pkg-plist b/science/py-meshio/pkg-plist
index f3a0677c6..a9cf45994 100644
--- a/science/py-meshio/pkg-plist
+++ b/science/py-meshio/pkg-plist
@@ -1,5 +1,5 @@
 bin/meshio
-%%PYTHON_SITELIBDIR%%/meshio-%%VER%%.dist-info/LICENSE.txt
+%%PYTHON_SITELIBDIR%%/meshio-%%VER%%.dist-info/licenses/LICENSE.txt
 %%PYTHON_SITELIBDIR%%/meshio-%%VER%%.dist-info/METADATA
 %%PYTHON_SITELIBDIR%%/meshio-%%VER%%.dist-info/RECORD
 %%PYTHON_SITELIBDIR%%/meshio-%%VER%%.dist-info/WHEEL
diff --git a/science/py-paida/Makefile b/science/py-paida/Makefile
index 3a5aed612..18bb85c77 100644
--- a/science/py-paida/Makefile
+++ b/science/py-paida/Makefile
@@ -1,6 +1,6 @@
 PORTNAME=	paida
 PORTVERSION=	3.2.1.2.10
-PORTREVISION=	2
+PORTREVISION=	3
 CATEGORIES=	science python
 MASTER_SITES=	SF/${PORTNAME}/${PORTNAME}/${PORTNAME}-3.2.1_2.10.1
 PKGNAMEPREFIX=	${PYTHON_PKGNAMEPREFIX}
diff --git a/science/py-paida/files/patch-setup.py b/science/py-paida/files/patch-setup.py
new file mode 100644
index 000000000..72580770e
--- /dev/null
+++ b/science/py-paida/files/patch-setup.py
@@ -0,0 +1,11 @@
+--- setup.py.orig	2026-04-16 08:12:40 UTC
++++ setup.py
+@@ -49,7 +49,7 @@ setup (name = "paida",
+ 	'paida.tools']
+ 
+ setup (name = "paida",
+-       version = "3.2.1_2.10.1",
++       version = "3.2.1+2.10.1",
+        author = "Koji Kishimoto",
+        author_email = "korry@users.sourceforge.net",
+        url = "http://paida.sourceforge.net/",
diff --git a/science/py-tweedledum/Makefile b/science/py-tweedledum/Makefile
index 7490d0c61..163dfb595 100644
--- a/science/py-tweedledum/Makefile
+++ b/science/py-tweedledum/Makefile
@@ -1,7 +1,7 @@
 PORTNAME=	tweedledum
 DISTVERSIONPREFIX=	v
 DISTVERSION=	1.1.1-20221123
-PORTREVISION=	1
+PORTREVISION=	2
 CATEGORIES=	science python # quantum-computing
 PKGNAMEPREFIX=	${PYTHON_PKGNAMEPREFIX}
 
@@ -14,11 +14,14 @@ LICENSE_FILE=	${WRKSRC}/LICENSE
 
 #BROKEN_FreeBSD_14=	clang crashes, see https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=265751
 
-BUILD_DEPENDS=	${PYTHON_PKGNAMEPREFIX}scikit-build>0:devel/py-scikit-build@${PY_FLAVOR} \
-		cmake:devel/cmake-core
+BUILD_DEPENDS=	${PYTHON_PKGNAMEPREFIX}cmake>=3.18:devel/py-cmake@${PY_FLAVOR} \
+		${PYTHON_PKGNAMEPREFIX}ninja>0:devel/py-ninja@${PY_FLAVOR} \
+		${PYTHON_PKGNAMEPREFIX}scikit-build>0:devel/py-scikit-build@${PY_FLAVOR} \
+		${PYTHON_PKGNAMEPREFIX}setuptools>=42:devel/py-setuptools@${PY_FLAVOR} \
+		${PYTHON_PKGNAMEPREFIX}wheel>0:devel/py-wheel@${PY_FLAVOR}
 
-USES=		compiler:c++17-lang python
-USE_PYTHON=	distutils autoplist pytest # tests fail to run, see https://github.com/boschmitt/tweedledum/issues/176
+USES=		compiler:c++17-lang ninja:build python
+USE_PYTHON=	autoplist pytest pep517
 
 USE_GITHUB=	yes
 GH_ACCOUNT=	boschmitt
@@ -28,9 +31,31 @@ GH_TUPLE=	pybind:pybind11:v2.12.0:pybind11
 #MAKE_ENV=	CMAKE_ARGS=-DTWEEDLEDUM_USE_EXTERNAL_PYBIND11=ON # external pybind11 should work but it fails to configure
 TEST_ENV=	${MAKE_ENV} PYTHONPATH=${STAGEDIR}${PYTHONPREFIX_SITELIBDIR}
 TEST_WRKSRC=	${WRKSRC}/python/test
+PEP517_INSTALL_CMD=	${PYTHON_CMD} -m installer --destdir ${STAGEDIR} --prefix ${PREFIX} \
+			${BUILD_WRKSRC}/dist/${PORTNAME}-${DISTVERSION:C|-|+|}*.whl
 
 post-extract:
 	@${RM} -r ${WRKSRC}/external/pybind11
 	@${CP} -r ${WRKSRC_pybind11} ${WRKSRC}/external/pybind11
 
+do-install:
+	@${MKDIR} ${STAGEDIR}${PYTHONPREFIX_SITELIBDIR}
+	@cd ${INSTALL_WRKSRC} && ${SETENVI} ${WRK_ENV} ${MAKE_ENV} ${PEP517_INSTALL_CMD}
+	@${PYTHON_CMD} -B ${PORTSDIR}/Mk/Scripts/strip_RECORD.py \
+		${STAGEDIR}${PYTHONPREFIX_SITELIBDIR}/${PORTNAME:tl:C|[-_.]+|_|g}-${DISTVERSION:C|-|+|}*.dist-info/RECORD >> ${_PYTHONPKGLIST}
+	@${REINPLACE_CMD} \
+		-e '/\.pyc$$/d' \
+		-e 's|^|${PYTHONPREFIX_SITELIBDIR}/|' \
+		-e 's|^${PYTHONPREFIX_SITELIBDIR}/../../../etc/|etc/|' \
+		-e 's|^${PYTHONPREFIX_SITELIBDIR}/../../../bin/|bin/|' \
+		-e 's|^${PYTHONPREFIX_SITELIBDIR}/../../../include/|include/|' \
+		-e 's|^${PYTHONPREFIX_SITELIBDIR}/../../../lib/|lib/|' \
+		-e 's|^${PYTHONPREFIX_SITELIBDIR}/../../../libdata/|libdata/|' \
+		-e 's|^${PYTHONPREFIX_SITELIBDIR}/../../../libexec/|libexec/|' \
+		-e 's|^${PYTHONPREFIX_SITELIBDIR}/../../../man/|man/|' \
+		-e 's|^${PYTHONPREFIX_SITELIBDIR}/../../../sbin/|sbin/|' \
+		-e 's|^${PYTHONPREFIX_SITELIBDIR}/../../../share/|share/|' \
+		${_PYTHONPKGLIST}
+	@cd ${STAGEDIR}${PREFIX} && ${FIND} lib -name '*.pyc' >> ${_PYTHONPKGLIST}
+
 .include <bsd.port.mk>
diff --git a/science/py-tweedledum/files/patch-pyproject.toml b/science/py-tweedledum/files/patch-pyproject.toml
new file mode 100644
index 000000000..e558dfdad
--- /dev/null
+++ b/science/py-tweedledum/files/patch-pyproject.toml
@@ -0,0 +1,17 @@
+--- pyproject.toml.orig	2022-11-24 00:42:05 UTC
++++ pyproject.toml
+@@ -1,5 +1,14 @@
+ [project]
++name = "tweedledum"
++version = "1.1.1+20221123"
+ requires-python = ">=3.6"
++dynamic = [
++    "authors",
++    "classifiers",
++    "description",
++    "license",
++    "readme",
++]
+ 
+ [build-system]
+ requires = [
diff --git a/security/py-btchip-python/files/patch-setup.py b/security/py-btchip-python/files/patch-setup.py
new file mode 100644
index 000000000..33332de15
--- /dev/null
+++ b/security/py-btchip-python/files/patch-setup.py
@@ -0,0 +1,11 @@
+--- setup.py.orig	2026-04-13 11:39:38 UTC
++++ setup.py
+@@ -17,7 +17,7 @@ setup(
+     packages=find_packages(),
+     install_requires=['hidapi>=0.7.99', 'ecdsa>=0.9'],
+     extras_require = {
+-	'smartcard': [ 'python-pyscard>=1.6.12-4build1' ]
++	'smartcard': [ 'python-pyscard>=1.6.12' ]
+     },
+     include_package_data=True,
+     zip_safe=False,
diff --git a/security/py-gnupg/Makefile b/security/py-gnupg/Makefile
index adfeb1c58..856184540 100644
--- a/security/py-gnupg/Makefile
+++ b/security/py-gnupg/Makefile
@@ -1,6 +1,6 @@
 PORTNAME=	gnupg
 PORTVERSION=	3.1.1
-PORTREVISION=	1
+PORTREVISION=	2
 CATEGORIES=	security python
 PKGNAMEPREFIX=	${PYTHON_PKGNAMEPREFIX}
 
@@ -19,4 +19,12 @@ USE_PYTHON=	distutils autoplist
 GH_ACCOUNT=	isislovecruft
 GH_PROJECT=	python-gnupg
 
+NO_ARCH=	yes
+
+post-patch:
+	${REINPLACE_CMD} \
+		-e 's|\(git_refnames =\).*$$|\1 "${PORTVERSION}"|' \
+		-e 's|\(git_full =\).*$$|\1 "${PORTVERSION}"|' \
+		${WRKSRC}/pretty_bad_protocol/_version.py
+
 .include <bsd.port.mk>
diff --git a/security/py-iris-client/Makefile b/security/py-iris-client/Makefile
index acbff98e5..918536e5d 100644
--- a/security/py-iris-client/Makefile
+++ b/security/py-iris-client/Makefile
@@ -1,6 +1,6 @@
-PORTNAME=	iris-client
+PORTNAME=	dfir-iris-client
 DISTVERSION=	2.0.1
-PORTREVISION=	1
+PORTREVISION=	2
 DISTVERSIONPREFIX=	v
 CATEGORIES=	security python
 PKGNAMEPREFIX=	${PYTHON_PKGNAMEPREFIX}
@@ -12,16 +12,17 @@ WWW=		https://github.com/dfir-iris/iris-client
 LICENSE=	LGPL3
 LICENSE_FILE=	${WRKSRC}/LICENSE.txt
 
+BUILD_DEPENDS=	${PYTHON_PKGNAMEPREFIX}flit-core>=3.2<4:devel/py-flit-core@${PY_FLAVOR}
 RUN_DEPENDS=	${PYTHON_PKGNAMEPREFIX}packaging>0:devel/py-packaging@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}requests>0:www/py-requests@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}deprecated>=0:devel/py-deprecated@${PY_FLAVOR}
 
 USE_GITHUB=	yes
 GH_ACCOUNT=	dfir-iris
-GH_PROJECT=	${PORTNAME}
+GH_PROJECT=	iris-client
 
 USES=		python
-USE_PYTHON=	autoplist distutils
+USE_PYTHON=	autoplist concurrent pep517
 
 NO_ARCH=	yes
 
diff --git a/security/py-iris-client/files/patch-dfir__iris__client_____init____.py b/security/py-iris-client/files/patch-dfir__iris__client_____init____.py
new file mode 100644
index 000000000..dee6172b5
--- /dev/null
+++ b/security/py-iris-client/files/patch-dfir__iris__client_____init____.py
@@ -0,0 +1,22 @@
+--- dfir_iris_client/__init__.py.orig	2023-05-15 14:17:25 UTC
++++ dfir_iris_client/__init__.py
+@@ -1 +1,19 @@
++"""
++iris Client API Source Code
++contact@dfir-iris.org
+ 
++This program is free software; you can redistribute it and/or
++modify it under the terms of the GNU Lesser General Public
++License as published by the Free Software Foundation; either
++version 3 of the License, or (at your option) any later version.
++
++This program is distributed in the hope that it will be useful,
++but WITHOUT ANY WARRANTY; without even the implied warranty of
++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++Lesser General Public License for more details.
++
++You should have received a copy of the GNU Lesser General Public License
++along with this program; if not, write to the Free Software Foundation,
++Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
++"""
++__version__ = "2.0.1"
diff --git a/security/theonionbox/files/patch-setup.py b/security/theonionbox/files/patch-setup.py
index 3b045a2a5..b9a03b416 100644
--- a/security/theonionbox/files/patch-setup.py
+++ b/security/theonionbox/files/patch-setup.py
@@ -1,6 +1,6 @@
 --- setup.py.orig	2019-05-10 21:59:01 UTC
 +++ setup.py
-@@ -295,19 +295,9 @@ package_data_exclude = {
+@@ -295,19 +295,9 @@ data_files = [
  }
  
  data_files = [
@@ -23,7 +23,13 @@
  ]
  # print(generate_data_files(data_files))
  
-@@ -381,10 +371,10 @@ setup(
+@@ -376,15 +366,15 @@ setup(
+     },
+     install_requires=[
+         'psutil>=5.4.0',
+-        'apscheduler>=2.1.2, <3.*; python_version<"3.0"',
++        'apscheduler>=2.1.2, <3; python_version<"3.0"',
+         'apscheduler>=3.4; python_version>="3.0"',
          'requests>=2.21',
          'PySocks>=1.6.7',
          'bottle>=0.12.13',
diff --git a/sysutils/iocage-devel/Makefile b/sysutils/iocage-devel/Makefile
index 1965e5caa..2fbfc7069 100644
--- a/sysutils/iocage-devel/Makefile
+++ b/sysutils/iocage-devel/Makefile
@@ -1,5 +1,6 @@
 PORTNAME=	iocage-devel
 PORTVERSION=	1.11.20250711
+PORTREVISION=	1
 PORTEPOCH=	1
 CATEGORIES=	sysutils python
 PKGNAMEPREFIX=	${PYTHON_PKGNAMEPREFIX}
diff --git a/sysutils/iocage-devel/files/patch-fastentrypoints.py b/sysutils/iocage-devel/files/patch-fastentrypoints.py
new file mode 100644
index 000000000..b0ee351f3
--- /dev/null
+++ b/sysutils/iocage-devel/files/patch-fastentrypoints.py
@@ -0,0 +1,28 @@
+--- fastentrypoints.py.orig	2025-12-12 22:04:57 UTC
++++ fastentrypoints.py
+@@ -35,6 +35,7 @@ http://github.com/ninjaaron/fast-entry_points
+ (c) 2016, Aaron Christianson
+ http://github.com/ninjaaron/fast-entry_points
+ '''
++from importlib import metadata
+ from setuptools.command import easy_install
+ import re
+ TEMPLATE = '''\
+@@ -59,13 +60,13 @@ def get_args(cls, dist, header=None):
+         header = cls.get_header()
+     for type_ in 'console', 'gui':
+         group = type_ + '_scripts'
+-        for name, ep in dist.get_entry_map(group).items():
++        for ep in metadata.entry_points(group=group, module="iocage_cli"):
+             # ensure_safe_name
+-            if re.search(r'[\\/]', name):
++            if re.search(r'[\\/]', ep.name):
+                 raise ValueError("Path separators not allowed in script names")
+             script_text = TEMPLATE.format(
+-                          ep.module_name, ep.attrs[0], '.'.join(ep.attrs))
+-            args = cls._get_script_args(type_, name, header, script_text)
++                          ep.module, ep.attr, ep.attr)
++            args = cls._get_script_args(type_, ep.name, header, script_text)
+             for res in args:
+                 yield res
+ 
diff --git a/sysutils/iocage/Makefile b/sysutils/iocage/Makefile
index 563b34888..f24edf8d2 100644
--- a/sysutils/iocage/Makefile
+++ b/sysutils/iocage/Makefile
@@ -1,5 +1,6 @@
 PORTNAME=	iocage
 PORTVERSION=	1.12
+PORTREVISION=	1
 CATEGORIES=	sysutils python
 PKGNAMEPREFIX=	${PYTHON_PKGNAMEPREFIX}
 
diff --git a/sysutils/iocage/files/patch-fastentrypoints.py b/sysutils/iocage/files/patch-fastentrypoints.py
new file mode 100644
index 000000000..b0ee351f3
--- /dev/null
+++ b/sysutils/iocage/files/patch-fastentrypoints.py
@@ -0,0 +1,28 @@
+--- fastentrypoints.py.orig	2025-12-12 22:04:57 UTC
++++ fastentrypoints.py
+@@ -35,6 +35,7 @@ http://github.com/ninjaaron/fast-entry_points
+ (c) 2016, Aaron Christianson
+ http://github.com/ninjaaron/fast-entry_points
+ '''
++from importlib import metadata
+ from setuptools.command import easy_install
+ import re
+ TEMPLATE = '''\
+@@ -59,13 +60,13 @@ def get_args(cls, dist, header=None):
+         header = cls.get_header()
+     for type_ in 'console', 'gui':
+         group = type_ + '_scripts'
+-        for name, ep in dist.get_entry_map(group).items():
++        for ep in metadata.entry_points(group=group, module="iocage_cli"):
+             # ensure_safe_name
+-            if re.search(r'[\\/]', name):
++            if re.search(r'[\\/]', ep.name):
+                 raise ValueError("Path separators not allowed in script names")
+             script_text = TEMPLATE.format(
+-                          ep.module_name, ep.attrs[0], '.'.join(ep.attrs))
+-            args = cls._get_script_args(type_, name, header, script_text)
++                          ep.module, ep.attr, ep.attr)
++            args = cls._get_script_args(type_, ep.name, header, script_text)
+             for res in args:
+                 yield res
+ 
diff --git a/sysutils/py-howdoi/Makefile b/sysutils/py-howdoi/Makefile
index 8ab9e27ca..ec828df42 100644
--- a/sysutils/py-howdoi/Makefile
+++ b/sysutils/py-howdoi/Makefile
@@ -1,6 +1,6 @@
 PORTNAME=	howdoi
 PORTVERSION=	2.0.20
-PORTREVISION=	6
+PORTREVISION=	7
 CATEGORIES=	sysutils python
 MASTER_SITES=	PYPI
 PKGNAMEPREFIX=	${PYTHON_PKGNAMEPREFIX}
@@ -26,4 +26,6 @@ RUN_DEPENDS=	${PYTHON_PKGNAMEPREFIX}appdirs>0:devel/py-appdirs@${PY_FLAVOR} \
 USES=		python
 USE_PYTHON=	autoplist distutils
 
+NO_ARCH=	yes
+
 .include <bsd.port.mk>
diff --git a/sysutils/py-howdoi/files/patch-fastentrypoints.py b/sysutils/py-howdoi/files/patch-fastentrypoints.py
new file mode 100644
index 000000000..7984c8687
--- /dev/null
+++ b/sysutils/py-howdoi/files/patch-fastentrypoints.py
@@ -0,0 +1,35 @@
+--- fastentrypoints.py.orig	2021-07-30 16:10:51 UTC
++++ fastentrypoints.py
+@@ -38,6 +38,7 @@ http://github.com/ninjaaron/fast-entry_points
+ (c) 2016, Aaron Christianson
+ http://github.com/ninjaaron/fast-entry_points
+ '''
++from importlib import metadata
+ from setuptools.command import easy_install
+ import re
+ TEMPLATE = r'''
+@@ -63,18 +64,18 @@ def get_args(cls, dist, header=None):  # noqa: D205,D4
+     if header is None:
+         # pylint: disable=E1101
+         header = cls.get_header()
+-    spec = str(dist.as_requirement())
++    spec = f'{dist.name}=={dist.version}'
+     for type_ in 'console', 'gui':
+         group = type_ + '_scripts'
+-        for name, ep in dist.get_entry_map(group).items():
++        for ep in metadata.entry_points(group=group, name="howdoi"):
+             # ensure_safe_name
+-            if re.search(r'[\\/]', name):
++            if re.search(r'[\\/]', ep.name):
+                 raise ValueError("Path separators not allowed in script names")
+             script_text = TEMPLATE.format(
+-                ep.module_name, ep.attrs[0], '.'.join(ep.attrs),
+-                spec, group, name)
++                ep.module, ep.attr, ep.attr,
++                spec, group, ep.name)
+             # pylint: disable=E1101
+-            args = cls._get_script_args(type_, name, header, script_text)
++            args = cls._get_script_args(type_, ep.name, header, script_text)
+             for res in args:
+                 yield res
+ 
diff --git a/www/py-webob/Makefile b/www/py-webob/Makefile
index 985591c91..02351b533 100644
--- a/www/py-webob/Makefile
+++ b/www/py-webob/Makefile
@@ -1,5 +1,6 @@
 PORTNAME=	webob
 PORTVERSION=	1.8.9
+PORTREVISION=	1
 CATEGORIES=	www python
 MASTER_SITES=	PYPI
 PKGNAMEPREFIX=	${PYTHON_PKGNAMEPREFIX}
diff --git a/www/py-webob/files/pyproject.toml.in b/www/py-webob/files/pyproject.toml.in
index bd54f55da..54e25fca4 100644
--- a/www/py-webob/files/pyproject.toml.in
+++ b/www/py-webob/files/pyproject.toml.in
@@ -5,3 +5,15 @@ build-backend = "setuptools.build_meta"
 [project]
 name = "webob"
 version = "%%PORTVERSION%%"
+dynamic = [
+    "description",
+    "readme",
+    "requires-python",
+    "license",
+    "authors",
+    "maintainers",
+    "keywords",
+    "classifiers",
+    "dependencies",
+    "optional-dependencies",
+]
diff --git a/www/twms/Makefile b/www/twms/Makefile
index e33afdafa..531b88333 100644
--- a/www/twms/Makefile
+++ b/www/twms/Makefile
@@ -1,6 +1,6 @@
 PORTNAME=	twms
 PORTVERSION=	0.06y
-PORTREVISION=	4
+PORTREVISION=	5
 CATEGORIES=	www astro
 
 MAINTAINER=	ports@FreeBSD.org
diff --git a/www/twms/files/patch-setup.py b/www/twms/files/patch-setup.py
index 43470433b..c1f551816 100644
--- a/www/twms/files/patch-setup.py
+++ b/www/twms/files/patch-setup.py
@@ -1,6 +1,6 @@
 --- setup.py.orig	2018-05-08 12:10:19 UTC
 +++ setup.py
-@@ -11,7 +11,7 @@ is_windows = __platform__ in ['Windows']
+@@ -11,7 +11,7 @@ def read(fname):
  __name__ = "twms"
  
  def read(fname):
@@ -9,7 +9,7 @@
  
  def glob(fname):
      return abs_glob(os.path.join(os.path.dirname(__file__), fname))
-@@ -25,7 +25,7 @@ def man_files(pattern):
+@@ -25,7 +25,7 @@ def config_files():
  
  def config_files():
      if not is_windows:
@@ -18,3 +18,12 @@
      else:
          return []
  
+@@ -40,7 +40,7 @@ setup(
+ 
+ setup(
+     name = __name__,
+-    version = "0.06y",
++    version = "0.06+y",
+     author = 'Darafei Praliaskoiski',
+     author_email = 'me@komzpa.net',
+     url = 'https://github.com/komzpa/twms',
diff --git a/www/twms/pkg-plist b/www/twms/pkg-plist
index 58e1a33f9..532422e56 100644
--- a/www/twms/pkg-plist
+++ b/www/twms/pkg-plist
@@ -1,5 +1,11 @@
 bin/twms
 @sample %%ETCDIR%%/twms.conf.sample
+%%PYTHON_SITELIBDIR%%/twms-0.6+y-py%%PYTHON_VER%%.egg-info/PKG-INFO
+%%PYTHON_SITELIBDIR%%/twms-0.6+y-py%%PYTHON_VER%%.egg-info/SOURCES.txt
+%%PYTHON_SITELIBDIR%%/twms-0.6+y-py%%PYTHON_VER%%.egg-info/dependency_links.txt
+%%PYTHON_SITELIBDIR%%/twms-0.6+y-py%%PYTHON_VER%%.egg-info/entry_points.txt
+%%PYTHON_SITELIBDIR%%/twms-0.6+y-py%%PYTHON_VER%%.egg-info/requires.txt
+%%PYTHON_SITELIBDIR%%/twms-0.6+y-py%%PYTHON_VER%%.egg-info/top_level.txt
 %%PYTHON_SITELIBDIR%%/twms/__init__.py
 %%PYTHON_SITELIBDIR%%/twms/__init__.pyc
 %%PYTHON_SITELIBDIR%%/twms/__init__.pyo
diff --git a/x11/arandr/Makefile b/x11/arandr/Makefile
index 152c78379..7c2bf978f 100644
--- a/x11/arandr/Makefile
+++ b/x11/arandr/Makefile
@@ -1,6 +1,6 @@
 PORTNAME=	arandr
 PORTVERSION=	0.1.11
-PORTREVISION=	2
+PORTREVISION=	3
 CATEGORIES=	x11 deskutils
 
 MAINTAINER=	sbz@FreeBSD.org
diff --git a/x11/arandr/files/patch-setup.py b/x11/arandr/files/patch-setup.py
new file mode 100644
index 000000000..eca381920
--- /dev/null
+++ b/x11/arandr/files/patch-setup.py
@@ -0,0 +1,19 @@
+--- setup.py.orig	2026-04-10 07:38:01 UTC
++++ setup.py
+@@ -29,13 +29,15 @@ from distutils.log import info, warn
+ from distutils.core import setup
+ from distutils.dep_util import newer
+ from distutils.log import info, warn
+-from distutils.cmd import Command
++# from distutils.cmd import Command
+ from distutils.command.build import build as _build
+ from distutils.command.install_data import install_data as _install_data
+ from distutils.command.install import install as _install
+ from distutils.command.sdist import sdist as _sdist
+ from distutils.dir_util import remove_tree
+ from distutils.command.clean import clean as _clean
++
++from setuptools import Command
+ 
+ 
+ PO_DIR = 'data/po'
