From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from smtp.gentoo.org (woodpecker.gentoo.org [140.211.166.183]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by finch.gentoo.org (Postfix) with ESMTPS id 17E57158074 for ; Wed, 25 Jun 2025 04:36:08 +0000 (UTC) Received: from lists.gentoo.org (bobolink.gentoo.org [140.211.166.189]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519) (No client certificate requested) (Authenticated sender: relay-lists.gentoo.org@gentoo.org) by smtp.gentoo.org (Postfix) with ESMTPSA id 04F0B3410ED for ; Wed, 25 Jun 2025 04:36:08 +0000 (UTC) Received: from bobolink.gentoo.org (localhost [127.0.0.1]) by bobolink.gentoo.org (Postfix) with ESMTP id DC44C11055E; Wed, 25 Jun 2025 04:35:59 +0000 (UTC) Received: from smtp.gentoo.org (mail.gentoo.org [IPv6:2001:470:ea4a:1:5054:ff:fec7:86e4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519) (No client certificate requested) by bobolink.gentoo.org (Postfix) with ESMTPS id C249611055C for ; Wed, 25 Jun 2025 04:35:59 +0000 (UTC) Received: from oystercatcher.gentoo.org (oystercatcher.gentoo.org [148.251.78.52]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id 57219341071 for ; Wed, 25 Jun 2025 04:35:59 +0000 (UTC) Received: from localhost.localdomain (localhost [IPv6:::1]) by oystercatcher.gentoo.org (Postfix) with ESMTP id EFB502A76 for ; Wed, 25 Jun 2025 04:35:57 +0000 (UTC) From: "Michał Górny" To: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: 8bit Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Michał Górny" Message-ID: <1750826138.d566ed631d80b9a4d53d3df1d9ff154b056a0878.mgorny@gentoo> Subject: [gentoo-commits] repo/gentoo:master commit in: eclass/ X-VCS-Repository: repo/gentoo X-VCS-Files: eclass/python-utils-r1.eclass X-VCS-Directories: eclass/ X-VCS-Committer: mgorny X-VCS-Committer-Name: Michał Górny X-VCS-Revision: d566ed631d80b9a4d53d3df1d9ff154b056a0878 X-VCS-Branch: master Date: Wed, 25 Jun 2025 04:35:57 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply X-Archives-Salt: 1c4afe83-840f-4be6-831d-c32acf082402 X-Archives-Hash: 90978a63b6e29596eeb0be179ad8d50f commit: d566ed631d80b9a4d53d3df1d9ff154b056a0878 Author: Michał Górny gentoo org> AuthorDate: Sat Jun 21 10:16:20 2025 +0000 Commit: Michał Górny gentoo org> CommitDate: Wed Jun 25 04:35:38 2025 +0000 URL: https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=d566ed63 python-utils-r1.eclass: Introduce EPYTEST_PLUGINS Introduce a new EPYTEST_PLUGINS variable that can be used to control which plugins are used by epytest. It provides a convenient method to disable plugin autoloading, as well as specify which plugins to load. It accepts package names, and includes a mapping from package names to `-p` argumetns for a number of plugins currently in ::gentoo. Signed-off-by: Michał Górny gentoo.org> eclass/python-utils-r1.eclass | 131 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 130 insertions(+), 1 deletion(-) diff --git a/eclass/python-utils-r1.eclass b/eclass/python-utils-r1.eclass index 6c887626cbd1..4ce75b962957 100644 --- a/eclass/python-utils-r1.eclass +++ b/eclass/python-utils-r1.eclass @@ -1273,6 +1273,78 @@ _python_check_occluded_packages() { # parameter, when calling epytest. The listed files will be entirely # skipped from test collection. +# @ECLASS_VARIABLE: EPYTEST_PLUGINS +# @DEFAULT_UNSET +# @DESCRIPTION: +# An array of pytest plugin package names (without categories) to use +# for the package. It has a twofold purpose: +# +# 1. When set prior to calling distutils_enable_tests, it causes +# dependencies on the specified pytest plugins to be added. +# +# 2. When plugin autoloading is disabled, it causes "-p" arguments +# loading specified plugins to be added. +# +# Defaults to an empty list. +# +# The eclasses explicitly handle a number of pytest plugins, and assume +# the default of "dev-python/${package}" and "-p ${package}" for others. +# If this is incorrect for some plugin package, please report a bug +# to have it added. +# +# This is not a perfect solution, and may not be sufficient for some +# packages. In these cases, either plugin autoloading should be used +# or PYTEST_PLUGINS environment variable may be used directly (see +# pytest documentation). +# +# For pytest-timeout and pytest-xdist plugins, it is generally +# preferable to use EPYTEST_TIMEOUT and EPYTEST_XDIST options +# that handle passing all needed options. + +# @ECLASS_VARIABLE: EPYTEST_PLUGIN_AUTOLOAD +# @DEFAULT_UNSET +# @DESCRIPTION: +# If set to a non-empty value, permits pytest plugin autoloading. +# Otherwise, PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 is set to disable it. +# +# If EPYTEST_PLUGINS is set explicitly or EAPI is 9 or later, +# defaults to disabled. Otherwise, defaults to enabled. +# The recommended way to disable it in EAPI 8 or earlier is to set +# EPYTEST_PLUGINS (possibly to an empty array). + +# @FUNCTION: _set_epytest_plugins +# @INTERNAL +# @DESCRIPTION: +# Check if EPYTEST_PLUGINS is set correctly, and set the default +# if it is not. +_set_epytest_plugins() { + debug-print-function ${FUNCNAME} "$@" + + # TODO: drop BASH_VERSINFO check when we require EAPI 8 + if [[ ${BASH_VERSINFO[0]} -ge 5 ]]; then + [[ ${EPYTEST_PLUGINS@a} == *a* ]] + else + [[ $(declare -p EPYTEST_PLUGINS) == "declare -a"* ]] + fi + if [[ ${?} -eq 0 ]]; then + # EPYTEST_PLUGINS set explicitly -- disable autoloading + : "${EPYTEST_PLUGIN_AUTOLOAD:=}" + else + if ! declare -p EPYTEST_PLUGINS &>/dev/null; then + # EPYTEST_PLUGINS unset -- default to empty. + # EPYTEST_PLUGIN_AUTOLOAD default depends on EAPI. + EPYTEST_PLUGINS=() + if [[ ${EAPI} != [78] ]]; then + : "${EPYTEST_PLUGIN_AUTOLOAD:=}" + else + : "${EPYTEST_PLUGIN_AUTOLOAD:=1}" + fi + else + die 'EPYTEST_PLUGINS must be an array.' + fi + fi +} + # @ECLASS_VARIABLE: EPYTEST_TIMEOUT # @DEFAULT_UNSET # @DESCRIPTION: @@ -1363,7 +1435,64 @@ epytest() { ) fi - if [[ ! ${PYTEST_DISABLE_PLUGIN_AUTOLOAD} ]]; then + _set_epytest_plugins + if [[ ! ${EPYTEST_PLUGIN_AUTOLOAD} ]]; then + local -x PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 + fi + + if [[ ${PYTEST_DISABLE_PLUGIN_AUTOLOAD} ]]; then + local plugin + for plugin in "${EPYTEST_PLUGINS[@]}"; do + case ${plugin} in + # special cases + hypothesis) + plugin=hypothesispytest + ;; + noseofyeti) + plugin=nose_of_yeti + ;; + pytest-helpers-namespace) + plugin=helpers_namespace + ;; + pytest-lazy-fixtures) + plugin=pytest_lazyfixture + ;; + pytest-testinfra) + plugin=pytest11.testinfra + ;; + # "generic" cases + betamax) + plugin=pytest-${plugin} + ;; + pyfakefs) + plugin=pytest_${plugin} + ;; + # pytest-x-y-z -> x-y-z + pytest-aiohttp | pytest-asyncio | pytest-check | \ + pytest-console-scripts | pytest-django | pytest-env | \ + pytest-freezer | pytest-home | pytest-httpbin | \ + pytest-import-check | pytest-localftpserver | \ + pytest-localserver | pytest-plus | pytest-recording | \ + pytest-regressions | pytest-repeat | pytest-reraise | \ + pytest-rerunfailures | pytest-reserial | \ + pytest-shell-utilities | pytest-skip-markers | \ + pytest-subtests | pytest-timeout | pytest-tornasync | \ + pytest-trio | pytext-xdist | pytest-xprocess | \ + pytest-xvfb ) + plugin=${plugin#pytest-} + ;; + # foo-bar-baz unchanged + pytest-datadir | pytest-qt | pytest-subprocess) + ;; + # foo-bar-baz -> foo_bar_baz + *) + plugin=${plugin//-/_} + ;; + esac + + args+=( -p "${plugin}" ) + done + else args+=( # disable the undesirable-dependency plugins by default to # trigger missing argument strips. strip options that require