• [gentoo-dev] [PATCH 3/5] python-utils-r1.eclass: Introduce EPYTEST_PLUG

    From =?UTF-8?q?Micha=C5=82=20G=C3=B3rny?@21:1/5 to All on Mon Jun 23 20:50:01 2025
    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 <mgorny@gentoo.org>
    ---
    eclass/python-utils-r1.eclass | 139 +++++++++++++++++++++++++++++++++-
    1 file changed, 138 insertions(+), 1 deletion(-)

    diff --git a/eclass/python-utils-r1.eclass b/eclass/python-utils-r1.eclass index 83727468b603..44746c4d296d 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
  • From Anna Vyalkova@21:1/5 to All on Wed Jun 25 11:10:02 2025
    On 2025-06-23, Michał Górny wrote:
    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.

    Is hardcoding plugin names the only way to match them with package
    names? Couldn't it be also done by parsing entry_points.txt?

    Signed-off-by: Michał Górny <mgorny@gentoo.org>
    ---
    eclass/python-utils-r1.eclass | 139 +++++++++++++++++++++++++++++++++-
    1 file changed, 138 insertions(+), 1 deletion(-)

    diff --git a/eclass/python-utils-r1.eclass b/eclass/python-utils-r1.eclass index 83727468b603..44746c4d296d 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,72 @@ 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-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



    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Micha=C5=82_G=C3=B3rny?=@21:1/5 to All on Wed Jun 25 12:50:01 2025
    Dnia 25 czerwca 2025 11:04:45 CEST, Anna Vyalkova <cyber+gentoo@sysrq.in> napisał/a:
    On 2025-06-23, Michał Górny wrote:
    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.

    Is hardcoding plugin names the only way to match them with package
    names? Couldn't it be also done by parsing entry_points.txt?

    Yes, I suppose that could work — at least as far as PN match (post normalization) upstream distribution names.


    Signed-off-by: Michał Górny <mgorny@gentoo.org>
    ---
    eclass/python-utils-r1.eclass | 139 +++++++++++++++++++++++++++++++++-
    1 file changed, 138 insertions(+), 1 deletion(-)

    diff --git a/eclass/python-utils-r1.eclass b/eclass/python-utils-r1.eclass >> index 83727468b603..44746c4d296d 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,72 @@ 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-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




    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Micha=C5=82_G=C3=B3rny?=@21:1/5 to Anna Vyalkova on Wed Jun 25 16:40:01 2025
    On Wed, 2025-06-25 at 14:04 +0500, Anna Vyalkova wrote:
    On 2025-06-23, Michał Górny wrote:
    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.

    Is hardcoding plugin names the only way to match them with package
    names? Couldn't it be also done by parsing entry_points.txt?


    Pushed for review as: https://github.com/gentoo/gentoo/pull/42738

    --
    Best regards,
    Michał Górny

    -----BEGIN PGP SIGNATURE-----

    iQFGBAABCgAwFiEEx2qEUJQJjSjMiybFY5ra4jKeJA4FAmhcCfQSHG1nb3JueUBn ZW50b28ub3JnAAoJEGOa2uIyniQOgggIAIYP+vQ3uQosZwXmMgb1vJTr1UXkcSQO eua/eoeVkmdnpIVMH22x3gq3Wto6W834WOeO1D/XPFC6M9mqWz03Vsr4sHw1bKg4 nq5uHlcLvBWlRd0EJ0+gzCjyWTwkSyHswB6fRXUq58B1QC7RNBoZL3QQiOXpyHNt jYCqfF7dnerC3VkM3QL87+Cu4dY4D5iYkzfPdqAyy9nALlKRgPRrEYIoEMO2uqau 5bY/jfE0WFs5tu5MysdkP/pj1fjg7Vme1steDx7qN7lXbRZ/U2lMeB0jhoXGi3sb Nd/tDN591SmRGRiKqu7WD234sU73iRTAfz8HdEiIQ3Js4LxT6OUuQBc=
    =ZN2r
    -----END PGP SIGNATURE-----

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)