Source code for extra_platforms.pytest

# Copyright Kevin Deldycke <kevin@deldycke.com> and contributors.
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
"""Pytest decorators to skip tests depending on the platform they're run on.

Generates a pair of ready-to-use ``@skip_<id>`` and ``@unless_<id>`` decorators for
each platform and group.
"""

from __future__ import annotations

try:
    import pytest  # noqa: F401
except ImportError:
    raise ImportError(
        "You need to install extra_platforms[pytest] extra dependencies to use this "
        "module."
    )

from itertools import chain

import extra_platforms

from .group import Group
from .group_data import ALL_GROUPS, ALL_TRAITS
from .trait import Trait

TYPE_CHECKING = False
if TYPE_CHECKING:
    from collections.abc import Callable

    from _pytest.mark.structures import MarkDecorator


[docs] class DeferredCondition: """Defer the evaluation of a condition. This allow a callable returning a boolean to be evaluated only when the boolean value is requested. Pytest's marks can have a condition attached to them. Which is practical for implementing our own ready-to-use ``@skip`` and ``@unless`` decorators. The problem is: this condition is evaluated at import time. Which leads to all our platform detection heuristics to be called when we generates our custom decorators below. This issue is being discussed upstream at: - https://github.com/pytest-dev/pytest/issues/7395 - https://github.com/pytest-dev/pytest/issues/9650 """ def __init__(self, condition: Callable[[], bool], invert: bool = False) -> None: self.condition = condition self.invert = invert def __bool__(self) -> bool: """Call the deferred condition and return its result.""" result = self.condition() return not result if self.invert else result
# Generate a pair of skip/unless decorators for each platform and group. for _obj in chain(ALL_TRAITS, ALL_GROUPS): # Sanity check to please the type checker. assert isinstance(_obj, (Trait, Group)) # Get the detection function for the current object. _func = getattr(extra_platforms, f"is_{_obj.id}") # Generate @skip decorator. globals()[f"skip_{_obj.id}"] = pytest.mark.skipif( DeferredCondition(_func), # type: ignore[arg-type] reason=f"Skip {_obj.short_desc}", ) # Generate @unless decorator. globals()[f"unless_{_obj.id}"] = pytest.mark.skipif( DeferredCondition(_func, invert=True), # type: ignore[arg-type] reason=f"Requires {_obj.short_desc}", ) # XXX Mypy doesn't understand dynamic type annotation, so we need to explicitly declare # all generated decorators after their generation. # These annotations are checked and enforced in unittests. if TYPE_CHECKING: skip_aarch64: MarkDecorator skip_aix: MarkDecorator skip_all_architectures: MarkDecorator skip_all_ci: MarkDecorator skip_all_platforms: MarkDecorator skip_all_traits: MarkDecorator skip_altlinux: MarkDecorator skip_amzn: MarkDecorator skip_android: MarkDecorator skip_any_arm: MarkDecorator skip_any_mips: MarkDecorator skip_any_sparc: MarkDecorator skip_any_windows: MarkDecorator skip_arch: MarkDecorator skip_arm: MarkDecorator skip_armv6l: MarkDecorator skip_armv7l: MarkDecorator skip_armv8l: MarkDecorator skip_azure_pipelines: MarkDecorator skip_bamboo: MarkDecorator skip_bsd: MarkDecorator skip_bsd_without_macos: MarkDecorator skip_buildkite: MarkDecorator skip_buildroot: MarkDecorator skip_cachyos: MarkDecorator skip_centos: MarkDecorator skip_circle_ci: MarkDecorator skip_cirrus_ci: MarkDecorator skip_cloudlinux: MarkDecorator skip_codebuild: MarkDecorator skip_cygwin: MarkDecorator skip_debian: MarkDecorator skip_exherbo: MarkDecorator skip_fedora: MarkDecorator skip_freebsd: MarkDecorator skip_gentoo: MarkDecorator skip_github_ci: MarkDecorator skip_gitlab_ci: MarkDecorator skip_guix: MarkDecorator skip_heroku_ci: MarkDecorator skip_hurd: MarkDecorator skip_i386: MarkDecorator skip_i586: MarkDecorator skip_i686: MarkDecorator skip_ibm_mainframe: MarkDecorator skip_ibm_powerkvm: MarkDecorator skip_kvmibm: MarkDecorator skip_linux: MarkDecorator skip_linux_layers: MarkDecorator skip_linux_like: MarkDecorator skip_linuxmint: MarkDecorator skip_loongarch: MarkDecorator skip_loongarch64: MarkDecorator skip_macos: MarkDecorator skip_mageia: MarkDecorator skip_mandriva: MarkDecorator skip_midnightbsd: MarkDecorator skip_mips: MarkDecorator skip_mips64: MarkDecorator skip_mips64el: MarkDecorator skip_mipsel: MarkDecorator skip_netbsd: MarkDecorator skip_nobara: MarkDecorator skip_openbsd: MarkDecorator skip_opensuse: MarkDecorator skip_oracle: MarkDecorator skip_other_unix: MarkDecorator skip_parallels: MarkDecorator skip_pidora: MarkDecorator skip_powerpc: MarkDecorator skip_ppc: MarkDecorator skip_ppc64: MarkDecorator skip_ppc64le: MarkDecorator skip_raspbian: MarkDecorator skip_rhel: MarkDecorator skip_riscv: MarkDecorator skip_riscv32: MarkDecorator skip_riscv64: MarkDecorator skip_rocky: MarkDecorator skip_s390x: MarkDecorator skip_scientific: MarkDecorator skip_slackware: MarkDecorator skip_sles: MarkDecorator skip_solaris: MarkDecorator skip_sparc: MarkDecorator skip_sparc64: MarkDecorator skip_sunos: MarkDecorator skip_system_v: MarkDecorator skip_teamcity: MarkDecorator skip_travis_ci: MarkDecorator skip_tumbleweed: MarkDecorator skip_tuxedo: MarkDecorator skip_ubuntu: MarkDecorator skip_ultramarine: MarkDecorator skip_unix: MarkDecorator skip_unix_layers: MarkDecorator skip_unix_without_macos: MarkDecorator skip_unknown: MarkDecorator skip_wasm32: MarkDecorator skip_wasm64: MarkDecorator skip_webassembly: MarkDecorator skip_windows: MarkDecorator skip_wsl1: MarkDecorator skip_wsl2: MarkDecorator skip_x86: MarkDecorator skip_x86_64: MarkDecorator skip_xenserver: MarkDecorator unless_aarch64: MarkDecorator unless_aix: MarkDecorator unless_all_architectures: MarkDecorator unless_all_ci: MarkDecorator unless_all_platforms: MarkDecorator unless_all_traits: MarkDecorator unless_altlinux: MarkDecorator unless_amzn: MarkDecorator unless_android: MarkDecorator unless_any_arm: MarkDecorator unless_any_mips: MarkDecorator unless_any_sparc: MarkDecorator unless_any_windows: MarkDecorator unless_arch: MarkDecorator unless_arm: MarkDecorator unless_armv6l: MarkDecorator unless_armv7l: MarkDecorator unless_armv8l: MarkDecorator unless_azure_pipelines: MarkDecorator unless_bamboo: MarkDecorator unless_bsd: MarkDecorator unless_bsd_without_macos: MarkDecorator unless_buildkite: MarkDecorator unless_buildroot: MarkDecorator unless_cachyos: MarkDecorator unless_centos: MarkDecorator unless_circle_ci: MarkDecorator unless_cirrus_ci: MarkDecorator unless_cloudlinux: MarkDecorator unless_codebuild: MarkDecorator unless_cygwin: MarkDecorator unless_debian: MarkDecorator unless_exherbo: MarkDecorator unless_fedora: MarkDecorator unless_freebsd: MarkDecorator unless_gentoo: MarkDecorator unless_github_ci: MarkDecorator unless_gitlab_ci: MarkDecorator unless_guix: MarkDecorator unless_heroku_ci: MarkDecorator unless_hurd: MarkDecorator unless_i386: MarkDecorator unless_i586: MarkDecorator unless_i686: MarkDecorator unless_ibm_mainframe: MarkDecorator unless_ibm_powerkvm: MarkDecorator unless_kvmibm: MarkDecorator unless_linux: MarkDecorator unless_linux_layers: MarkDecorator unless_linux_like: MarkDecorator unless_linuxmint: MarkDecorator unless_loongarch: MarkDecorator unless_loongarch64: MarkDecorator unless_macos: MarkDecorator unless_mageia: MarkDecorator unless_mandriva: MarkDecorator unless_midnightbsd: MarkDecorator unless_mips: MarkDecorator unless_mips64: MarkDecorator unless_mips64el: MarkDecorator unless_mipsel: MarkDecorator unless_netbsd: MarkDecorator unless_nobara: MarkDecorator unless_openbsd: MarkDecorator unless_opensuse: MarkDecorator unless_oracle: MarkDecorator unless_other_unix: MarkDecorator unless_parallels: MarkDecorator unless_pidora: MarkDecorator unless_powerpc: MarkDecorator unless_ppc: MarkDecorator unless_ppc64: MarkDecorator unless_ppc64le: MarkDecorator unless_raspbian: MarkDecorator unless_rhel: MarkDecorator unless_riscv: MarkDecorator unless_riscv32: MarkDecorator unless_riscv64: MarkDecorator unless_rocky: MarkDecorator unless_s390x: MarkDecorator unless_scientific: MarkDecorator unless_slackware: MarkDecorator unless_sles: MarkDecorator unless_solaris: MarkDecorator unless_sparc: MarkDecorator unless_sparc64: MarkDecorator unless_sunos: MarkDecorator unless_system_v: MarkDecorator unless_teamcity: MarkDecorator unless_travis_ci: MarkDecorator unless_tumbleweed: MarkDecorator unless_tuxedo: MarkDecorator unless_ubuntu: MarkDecorator unless_ultramarine: MarkDecorator unless_unix: MarkDecorator unless_unix_layers: MarkDecorator unless_unix_without_macos: MarkDecorator unless_unknown: MarkDecorator unless_wasm32: MarkDecorator unless_wasm64: MarkDecorator unless_webassembly: MarkDecorator unless_windows: MarkDecorator unless_wsl1: MarkDecorator unless_wsl2: MarkDecorator unless_x86: MarkDecorator unless_x86_64: MarkDecorator unless_xenserver: MarkDecorator