diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index 59df97c..2556f8b 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -94,25 +94,13 @@ jobs: max-parallel: 10 matrix: python-version: - - "3.5" - - "3.6" - "3.7" - "3.8" - "3.9" - "3.10" pytest-version: - - "~=6.0.0" - - "~=6.1.0" - - "~=6.2.0" - - "~=7.0.0" - "~=7.1.0" - exclude: - - {"python-version": "3.5", "pytest-version": "~=6.2.0"} - - {"python-version": "3.5", "pytest-version": "~=7.0.0"} - - {"python-version": "3.5", "pytest-version": "~=7.1.0"} - - {"python-version": "3.6", "pytest-version": "~=7.1.0"} - - {"python-version": "3.10", "pytest-version": "~=6.0.0"} - - {"python-version": "3.10", "pytest-version": "~=6.1.0"} + - "~=7.2.0" steps: - uses: actions/checkout@v2 @@ -277,19 +265,13 @@ jobs: max-parallel: 10 matrix: python-version: - - "3.6" - "3.7" - "3.8" - "3.9" - "3.10" pytest-version: - - "~=6.2.0" - - "~=7.0.0" - "~=7.1.0" - exclude: - - {"python-version": "3.6", "pytest-version": "~=7.1.0"} - - {"python-version": "3.10", "pytest-version": "~=6.0.0"} - - {"python-version": "3.10", "pytest-version": "~=6.1.0"} + - "~=7.2.0" steps: - uses: actions/checkout@v2 @@ -423,19 +405,13 @@ jobs: max-parallel: 10 matrix: python-version: - - "3.6" - "3.7" - "3.8" - "3.9" - "3.10" pytest-version: - - "~=6.2.0" - - "~=7.0.0" - "~=7.1.0" - exclude: - - {"python-version": "3.6", "pytest-version": "~=7.1.0"} - - {"python-version": "3.10", "pytest-version": "~=6.0.0"} - - {"python-version": "3.10", "pytest-version": "~=6.1.0"} + - "~=7.2.0" steps: - uses: actions/checkout@v2 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index fd60a26..0bdff74 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,7 +2,7 @@ minimum_pre_commit_version: 1.15.2 repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.2.0 + rev: v4.4.0 hooks: - id: check-merge-conflict # Check for files that contain merge conflict strings. - id: trailing-whitespace # Trims trailing whitespace. @@ -36,32 +36,16 @@ repos: language: system # <---- Local Hooks ------------------------------------------------------------------------------------------------ - # ----- Remove Typing - Py3.5 Support ----------------------------------------------------------------------------> - - repo: https://github.com/s0undt3ch/downgrade-source - rev: v2.1.0 - hooks: - - id: downgrade-source - name: Downgrade source code into a separate package to support Py3.5 - files: ^src/.*\.py$ - exclude: ^src/pytestskipmarkers/((__init__|version|utils/__init__)\.py|downgraded/.*\.py)$ - args: - - --target-version=3.5 - - --pkg-path=src/pytestskipmarkers - - --skip-checker=nounusableimports - - --skip-checker=nostarimports - # <---- Remove Typing - Py3.5 Support ----------------------------------------------------------------------------- - # ----- Formatting ------------------------------------------------------------------------------------------------> - repo: https://github.com/asottile/pyupgrade - rev: v2.32.0 + rev: v3.3.1 hooks: - id: pyupgrade - name: Rewrite Code to be Py3.5+ - args: [--py3-plus] - exclude: ^src/pytestskipmarkers/downgraded/.*\.py$ + name: Rewrite Code to be Py3.7+ + args: [--py37-plus] - repo: https://github.com/asottile/reorder_python_imports - rev: v3.0.1 + rev: v3.9.0 hooks: - id: reorder-python-imports args: [ @@ -71,7 +55,7 @@ repos: exclude: ^src/pytestskipmarkers/(version.py|downgraded/.*)$ - repo: https://github.com/psf/black - rev: 22.3.0 + rev: 22.12.0 hooks: - id: black args: [-l 100] @@ -111,7 +95,7 @@ repos: # ----- Code Analysis ---------------------------------------------------------------------------------------------> - repo: https://github.com/pycqa/flake8 - rev: '4.0.1' + rev: '6.0.0' hooks: - id: flake8 exclude: ^(src/pytestskipmarkers/(downgraded/.*|version\.py)|\.pre-commit-hooks/.*\.py)$ @@ -121,7 +105,7 @@ repos: - flake8-typing-imports - repo: https://github.com/pre-commit/mirrors-mypy - rev: v0.942 + rev: v0.991 hooks: - id: mypy name: Run mypy against source @@ -134,7 +118,7 @@ repos: - types-setuptools - repo: https://github.com/pre-commit/mirrors-mypy - rev: v0.942 + rev: v0.991 hooks: - id: mypy name: Run mypy against tests diff --git a/changelog/21.improvement.rst b/changelog/21.improvement.rst new file mode 100644 index 0000000..901f404 --- /dev/null +++ b/changelog/21.improvement.rst @@ -0,0 +1 @@ +Don't cache the functions in `pytestskipmarkers.utils.platform` diff --git a/changelog/22.breaking.rst b/changelog/22.breaking.rst new file mode 100644 index 0000000..4476761 --- /dev/null +++ b/changelog/22.breaking.rst @@ -0,0 +1 @@ +Drop support for python versions older than 3.7 diff --git a/changelog/23.trivial.rst b/changelog/23.trivial.rst new file mode 100644 index 0000000..dc7f12c --- /dev/null +++ b/changelog/23.trivial.rst @@ -0,0 +1 @@ +Updated pre-commit hook versions diff --git a/noxfile.py b/noxfile.py index c463365..799da30 100644 --- a/noxfile.py +++ b/noxfile.py @@ -134,7 +134,7 @@ def tests(session): # itself does not get upgraded pytest_requirements = [] if not pytest_version_requirement.startswith("pytest"): - pytest_version_requirement = "pytest{}".format(pytest_version_requirement) + pytest_version_requirement = f"pytest{pytest_version_requirement}" pytest_requirements.append(pytest_version_requirement) if pytest_version_requirement.startswith("pytest~=6"): pytest_requirements.append("pytest-subtests<0.7.0") @@ -172,10 +172,10 @@ def tests(session): args = [ "--rootdir", str(REPO_ROOT), - "--log-file={}".format(RUNTESTS_LOGFILE), + f"--log-file={RUNTESTS_LOGFILE}", "--log-file-level=debug", "--show-capture=no", - "--junitxml={}".format(JUNIT_REPORT), + f"--junitxml={JUNIT_REPORT}", "--showlocals", "--strict-markers", "-ra", @@ -222,7 +222,7 @@ def tests(session): "--include=src/pytestskipmarkers/*,tests/*", ] if pytest_version(session) >= (6, 2): - cmdline.append("--fail-under={}".format(COVERAGE_FAIL_UNDER_PERCENT)) + cmdline.append(f"--fail-under={COVERAGE_FAIL_UNDER_PERCENT}") session.run(*cmdline) finally: if COVERAGE_REPORT_DB.exists(): @@ -239,7 +239,7 @@ def _lint(session, rcfile, flags, paths): session.run("pylint", "--version") pylint_report_path = os.environ.get("PYLINT_REPORT") - cmd_args = ["pylint", "--rcfile={}".format(rcfile)] + list(flags) + list(paths) + cmd_args = ["pylint", f"--rcfile={rcfile}"] + list(flags) + list(paths) stdout = tempfile.TemporaryFile(mode="w+b") try: @@ -264,8 +264,8 @@ def lint(session): """ Run PyLint against Salt and it's test suite. Set PYLINT_REPORT to a path to capture output. """ - session.notify("lint-code-{}".format(session.python)) - session.notify("lint-tests-{}".format(session.python)) + session.notify(f"lint-code-{session.python}") + session.notify(f"lint-tests-{session.python}") @nox.session(python="3", name="lint-code") @@ -421,7 +421,7 @@ def changelog(session, draft): stderr=None, ).strip() - town_cmd = ["towncrier", "build", "--version={}".format(version)] + town_cmd = ["towncrier", "build", f"--version={version}"] if draft: town_cmd.append("--draft") session.run(*town_cmd) @@ -444,7 +444,7 @@ def release(session): version = session.posargs[0] try: session.log("Generating temporary %s tag", version) - session.run("git", "tag", "-as", version, "-m", "Release {}".format(version), external=True) + session.run("git", "tag", "-as", version, "-m", f"Release {version}", external=True) changelog(session, draft=False) except CommandFailed: session.error("Failed to generate the temporary tag") @@ -456,16 +456,14 @@ def release(session): "commit", "-a", "-m", - "Generate Changelog for version {}".format(version), + f"Generate Changelog for version {version}", external=True, ) except CommandFailed: session.error("Failed to generate the release changelog") try: session.log("Overwriting temporary %s tag", version) - session.run( - "git", "tag", "-fas", version, "-m", "Release {}".format(version), external=True - ) + session.run("git", "tag", "-fas", version, "-m", f"Release {version}", external=True) except CommandFailed: session.error("Failed to overwrite the temporary tag") session.warn("Don't forget to push the newly created tag") diff --git a/requirements/base.txt b/requirements/base.txt index beadc3d..46573e9 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -1,4 +1,4 @@ -pytest>=6.0.0 +pytest>=7.1.0 attrs>=19.2.0 pywin32; sys_platform == "win32" distro diff --git a/setup.cfg b/setup.cfg index 3b2c643..29b0a7e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -15,11 +15,12 @@ classifiers = Programming Language :: Cython Programming Language :: Python :: 3 Programming Language :: Python :: 3 :: Only - Programming Language :: Python :: 3.5 - Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 + Programming Language :: Python :: 3.10 + Programming Language :: Python :: 3.11 + Programming Language :: Python :: 3.12 Development Status :: 5 - Production/Stable Framework :: Pytest Typing :: Typed @@ -33,7 +34,7 @@ include_package_data = True package_dir = =src packages = find: -python_requires = >= 3.5.2 +python_requires = >= 3.7 setup_requires = setuptools>=50.3.2 setuptools_scm[toml]>=3.4 diff --git a/src/pytestskipmarkers/__init__.py b/src/pytestskipmarkers/__init__.py index 92af1ce..3cde139 100644 --- a/src/pytestskipmarkers/__init__.py +++ b/src/pytestskipmarkers/__init__.py @@ -2,47 +2,10 @@ # SPDX-License-Identifier: Apache-2.0 # # type: ignore -import importlib import pathlib import re import sys - -USE_DOWNGRADED_TRANSPILED_CODE = sys.version_info < (3, 6) - - -if USE_DOWNGRADED_TRANSPILED_CODE: - # We generated downgraded code just for Py3.5 - # Let's just import from those modules instead - - class NoTypingImporter: - """ - Meta importer to redirect imports on Py35. - """ - - NO_REDIRECT_NAMES = ( - "pytestskipmarkers.version", - "pytestskipmarkers.downgraded", - ) - - def find_module(self, module_name, package_path=None): # noqa: D102 - if module_name.startswith(self.NO_REDIRECT_NAMES): - return None - if not module_name.startswith("pytestskipmarkers"): - return None - return self - - def load_module(self, name): # noqa: D102 - if not name.startswith(self.NO_REDIRECT_NAMES): - mod = importlib.import_module("pytestskipmarkers.downgraded.{}".format(name[18:])) - else: - mod = importlib.import_module(name) - sys.modules[name] = mod - return mod - - # Try our importer first - sys.meta_path = [NoTypingImporter()] + sys.meta_path - try: from .version import __version__ except ImportError: # pragma: no cover diff --git a/src/pytestskipmarkers/downgraded/__init__.py b/src/pytestskipmarkers/downgraded/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/src/pytestskipmarkers/downgraded/plugin.py b/src/pytestskipmarkers/downgraded/plugin.py deleted file mode 100644 index 434f190..0000000 --- a/src/pytestskipmarkers/downgraded/plugin.py +++ /dev/null @@ -1,137 +0,0 @@ -# Copyright 2021-2022 VMware, Inc. -# SPDX-License-Identifier: Apache-2.0 -# -""" -Pytest plugin hooks. -""" -from __future__ import generator_stop -from typing import TYPE_CHECKING -import pytest -import pytestskipmarkers.utils.markers - -if TYPE_CHECKING: - from _pytest.config import Config - from _pytest.config.argparsing import Parser - from _pytest.nodes import Item - - -def pytest_addoption(parser: 'Parser') -> None: - """ - Register argparse-style options and ini-style config values. - """ - test_selection_group = parser.getgroup('Tests Selection') - test_selection_group.addoption( - '--run-destructive', - action='store_true', - default=False, - help='Run destructive tests. These tests can include adding or removing users from your system for example. Default: False', - ) - test_selection_group.addoption( - '--run-expensive', - action='store_true', - default=False, - help='Run expensive tests. These tests usually involve costs like for example bootstrapping a cloud VM. Default: False', - ) - - -@pytest.hookimpl(tryfirst=True) -def pytest_runtest_setup(item: 'Item') -> None: - """ - Fixtures injection based on markers or test skips based on CLI arguments. - """ - __tracebackhide__ = True - pytestskipmarkers.utils.markers.evaluate_markers(item) - - -@pytest.mark.trylast -def pytest_configure(config: 'Config') -> None: - """ - Configure the plugin. - - called after command line options have been parsed - and all plugins and initial conftest files been loaded. - """ - config.addinivalue_line( - 'markers', - 'destructive_test: Run destructive tests. These tests can include adding or removing users from your system for example.', - ) - config.addinivalue_line( - 'markers', - 'expensive_test: Run expensive tests. These tests can include starting resources which cost money, like VMs, for example.', - ) - config.addinivalue_line( - 'markers', - 'skip_if_not_root: Skip if the current user is not root on non windows platforms or not Administrator on windows platforms', - ) - config.addinivalue_line( - 'markers', 'skip_if_not_root: Skip if the current user is not `root`.' - ) - config.addinivalue_line( - 'markers', - "skip_if_binaries_missing(*binaries, check_all=True, message=None):If 'check_all' is True, all binaries must exist.If 'check_all' is False, then only one the passed binaries needs to be found. Usefull when, for example, passing a list of python interpreter names(python3.5, python3, python), where only one needs to exist.", - ) - config.addinivalue_line( - 'markers', - "requires_network(only_local_network=False): Skip if no networking is set up. If 'only_local_network' is 'True', only the local network is checked.", - ) - config.addinivalue_line('markers', 'skip_on_windows: Skip test on Windows') - config.addinivalue_line( - 'markers', 'skip_unless_on_windows: Skip test unless on Windows' - ) - config.addinivalue_line('markers', 'skip_on_linux: Skip test on Linux') - config.addinivalue_line( - 'markers', 'skip_unless_on_linux: Skip test unless on Linux' - ) - config.addinivalue_line('markers', 'skip_on_darwin: Skip test on Darwin') - config.addinivalue_line( - 'markers', 'skip_unless_on_darwin: Skip test unless on Darwin' - ) - config.addinivalue_line('markers', 'skip_on_sunos: Skip test on SunOS') - config.addinivalue_line( - 'markers', 'skip_unless_on_sunos: Skip test unless on SunOS' - ) - config.addinivalue_line('markers', 'skip_on_smartos: Skip test on SmartOS') - config.addinivalue_line( - 'markers', 'skip_unless_on_smartos: Skip test unless on SmartOS' - ) - config.addinivalue_line('markers', 'skip_on_freebsd: Skip test on FreeBSD') - config.addinivalue_line( - 'markers', 'skip_unless_on_freebsd: Skip test unless on FreeBSD' - ) - config.addinivalue_line('markers', 'skip_on_netbsd: Skip test on NetBSD') - config.addinivalue_line( - 'markers', 'skip_unless_on_netbsd: Skip test unless on NetBSD' - ) - config.addinivalue_line('markers', 'skip_on_openbsd: Skip test on OpenBSD') - config.addinivalue_line( - 'markers', 'skip_unless_on_openbsd: Skip test unless on OpenBSD' - ) - config.addinivalue_line('markers', 'skip_on_aix: Skip test on AIX') - config.addinivalue_line('markers', 'skip_unless_on_aix: Skip test unless on AIX') - config.addinivalue_line('markers', 'skip_on_aarch64: Skip test on AArch64') - config.addinivalue_line( - 'markers', 'skip_unless_on_aarch64: Skip test unless on AArch64' - ) - config.addinivalue_line('markers', 'skip_on_photonos: Skip test on PhotonOS') - config.addinivalue_line( - 'markers', 'skip_unless_on_photonos: Skip test unless on PhotonOS' - ) - config.addinivalue_line( - 'markers', 'skip_on_spawning_platform: Skip test on spawning platforms' - ) - config.addinivalue_line( - 'markers', - 'skip_unless_on_spawning_platform: Skip test unless on spawning platforms', - ) - config.addinivalue_line( - 'markers', - 'skip_on_platforms(windows=False, linux=False, darwin=False, sunos=False, smartos=False, freebsd=False, netbsd=False, openbsd=False, aix=False, aarch64=False, spawning=False, photonos=False): Pass True to one or more keywords to get the test skipped.', - ) - config.addinivalue_line( - 'markers', - 'skip_unless_on_platforms(windows=False, linux=False, darwin=False, sunos=False, smartos=False, freebsd=False, netbsd=False, openbsd=False, aix=False, aarch64=False, spawning=False, photonos=False): Pass True to one or more keywords to get the test skipped unless matched.', - ) - config.addinivalue_line( - 'markers', - 'skip_on_env(envvar, present=True, eq=None, ne=None): Skip test based on environment variables presence and contents.', - ) diff --git a/src/pytestskipmarkers/downgraded/utils/__init__.py b/src/pytestskipmarkers/downgraded/utils/__init__.py deleted file mode 100644 index 804183b..0000000 --- a/src/pytestskipmarkers/downgraded/utils/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright 2022 VMware, Inc. -# SPDX-License-Identifier: Apache-2.0 -# -from __future__ import generator_stop diff --git a/src/pytestskipmarkers/downgraded/utils/markers.py b/src/pytestskipmarkers/downgraded/utils/markers.py deleted file mode 100644 index 25c0425..0000000 --- a/src/pytestskipmarkers/downgraded/utils/markers.py +++ /dev/null @@ -1,784 +0,0 @@ -# Copyright 2021-2022 VMware, Inc. -# SPDX-License-Identifier: Apache-2.0 -# -""" -PyTest Markers related utilities. - -.. - PYTEST_DONT_REWRITE -""" -from __future__ import generator_stop -import contextlib -import logging -import os -import shutil -from typing import Any -from typing import cast -from typing import Dict -from typing import List -from typing import Optional -from typing import Tuple -from typing import TYPE_CHECKING -from typing import Union -import _pytest._version -import pytest -import pytestskipmarkers.utils.platform -import pytestskipmarkers.utils.ports as ports -import pytestskipmarkers.utils.socket as socket - -if TYPE_CHECKING: - from _pytest.nodes import Item -PYTEST_GE_7 = getattr(_pytest._version, 'version_tuple', (-1, -1)) >= (7, 0) -log = logging.getLogger(__name__) - - -def skip_if_not_root() -> Optional[str]: - """ - Helper function to check for root/Administrator privileges. - - Returns: - str: The reason of the skip - """ - if not pytestskipmarkers.utils.platform.is_windows(): - if os.getuid() != 0: - return 'You must be logged in as root to run this test' - else: - from pytestskipmarkers.utils import win_functions - - current_user = win_functions.get_current_user() - if TYPE_CHECKING: - assert current_user - if current_user != 'SYSTEM': - if not win_functions.is_admin(cast(str, current_user)): - return 'You must be logged in as an Administrator to run this test' - return None - - -def skip_if_binaries_missing( - binaries: Union[List[str], Tuple[str, ...]], - check_all: bool = True, - reason: Optional[str] = None, -) -> Optional[str]: - """ - Helper function to check for existing binaries. - - Args: - binaries (list or tuple): - Iterator of binaries to check - check_all (bool): - If ``check_all`` is ``True``, the default, all binaries must exist. - If ``check_all`` is ``False``, then only one the passed binaries needs to be found. - Useful when, for example, passing a list of python interpreter names(python3.5, - python3, python), where only one needs to exist. - reason (str): - The skip reason. - - Returns: - str: The reason for the skip. - None: Should not be skipped. - """ - if check_all is False: - for binary in binaries: - if shutil.which(binary) is not None: - break - else: - if reason is not None: - return reason - return 'None of the following binaries was found: {}'.format( - ', '.join(binaries) - ) - else: - for binary in binaries: - if shutil.which(binary) is None: - if reason is not None: - return reason - return "The '{}' binary was not found".format(binary) - log.debug('All binaries found. Searched for: %s', ', '.join(binaries)) - return None - - -def skip_if_no_local_network() -> Optional[str]: - """ - Helper function to check for existing local network. - - Returns: - str: The reason for the skip. - None: Should not be skipped. - """ - check_port = ports.get_unused_localhost_port() - has_local_network = False - try: - with contextlib.closing( - socket.socket(socket.AF_INET, socket.SOCK_STREAM) - ) as pubsock: - pubsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - pubsock.bind(('', check_port)) - has_local_network = True - except OSError: - try: - with contextlib.closing( - socket.socket(socket.AF_INET6, socket.SOCK_STREAM) - ) as pubsock: - pubsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - pubsock.bind(('', check_port)) - has_local_network = True - except OSError: - pass - if has_local_network is False: - return 'No local network was detected' - return None - - -def skip_if_no_remote_network() -> Optional[str]: - """ - Helper function to check for existing remote network(internet). - - Returns: - str: The reason for the skip. - None: Should not be skipped. - """ - if os.environ.get('NO_INTERNET'): - return 'Environment variable NO_INTERNET is set' - has_remote_network = False - for addr in ( - '172.217.17.14', - '172.217.16.238', - '173.194.41.198', - '173.194.41.199', - '173.194.41.200', - '173.194.41.201', - '173.194.41.206', - '173.194.41.192', - '173.194.41.193', - '173.194.41.194', - '173.194.41.195', - '173.194.41.196', - '173.194.41.197', - '216.58.201.174', - ): - try: - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.settimeout(0.25) - sock.connect((addr, 80)) - sock.close() - has_remote_network = True - break - except OSError: - continue - if has_remote_network is False: - return 'No internet network connection was detected' - return None - - -def skip_on_env( - varname: str, - present: bool = True, - eq: Optional[str] = None, - ne: Optional[str] = None, - reason: Optional[str] = None, -) -> Optional[str]: - """ - Helper function to check for environment variables. - - If any of the checks match, return the skip reason. - - Args: - varname(str): - The environment variable to check - present(bool): - When ``True``, skip if variable is present in the environment. - When ``False``, skip if variable is not present in the environment. - eq(str): - Skips when the variable is present in the environment and matches this value. - ne(str): - Skips when the variable is present in the environment and does not match this value. - reason(str): - The custom reason message to use. - - Returns: - str: The skip reason - None: Should not be skipped. - """ - if eq and ne: - raise pytest.UsageError('Cannot pass both `eq` and `ne`.') - if present is False and (eq or ne): - raise pytest.UsageError('Cannot pass `present=False` and either `eq` or `ne`.') - if present is False and varname not in os.environ: - if not reason: - reason = "The variable '{0}' is not present in the environ.".format(varname) - return reason - elif present is True and varname in os.environ: - varname_value = os.environ[varname] - if eq: - if varname_value == eq: - if not reason: - reason = "'{0}' present in environ and '{1}=={2}'".format( - varname, varname, eq - ) - elif ne: - if varname_value != ne: - if not reason: - reason = "'{0}' present in environ and '{1}!={2}'".format( - varname, varname, eq - ) - elif not reason: - reason = "The variable '{0}' is present in the environ.".format(varname) - return reason - return None - - -def evaluate_markers(item: 'Item') -> None: - """ - Fixtures injection based on markers or test skips based on CLI arguments. - """ - exc_kwargs = {} - if PYTEST_GE_7: - exc_kwargs['_use_item_location'] = True - destructive_tests_marker = item.get_closest_marker('destructive_test') - if destructive_tests_marker is not None: - if destructive_tests_marker.args or destructive_tests_marker.kwargs: - raise pytest.UsageError( - "The 'destructive_test' marker does not accept any arguments or keyword arguments" - ) - if item.config.getoption('--run-destructive') is False: - raise pytest.skip.Exception('Destructive tests are disabled', **exc_kwargs) - expensive_tests_marker = item.get_closest_marker('expensive_test') - if expensive_tests_marker is not None: - if expensive_tests_marker.args or expensive_tests_marker.kwargs: - raise pytest.UsageError( - "The 'expensive_test' marker does not accept any arguments or keyword arguments" - ) - if item.config.getoption('--run-expensive') is False: - raise pytest.skip.Exception('Expensive tests are disabled', **exc_kwargs) - skip_if_not_root_marker = item.get_closest_marker('skip_if_not_root') - if skip_if_not_root_marker is not None: - if skip_if_not_root_marker.args or skip_if_not_root_marker.kwargs: - raise pytest.UsageError( - "The 'skip_if_not_root' marker does not accept any arguments or keyword arguments" - ) - skip_reason = skip_if_not_root() - if skip_reason: - raise pytest.skip.Exception(skip_reason, **exc_kwargs) - skip_if_binaries_missing_marker = item.get_closest_marker( - 'skip_if_binaries_missing' - ) - if skip_if_binaries_missing_marker is not None: - binaries = skip_if_binaries_missing_marker.args - if not binaries: - raise pytest.UsageError( - "The 'skip_if_binaries_missing' marker needs at least one binary name to be passed" - ) - for arg in binaries: - if not isinstance(arg, str): - raise pytest.UsageError( - "The 'skip_if_binaries_missing' marker only accepts strings as arguments. If you are trying to pass multiple binaries, each binary should be an separate argument." - ) - message = cast(Dict[str, Any], skip_if_binaries_missing_marker.kwargs).pop( - 'message', None - ) - if message: - item.warn( - pytest.PytestWarning( - 'Please stop passing \'message="{0}"\' and instead pass \'reason="{0}"\''.format( - message - ) - ) - ) - cast(Dict[str, Any], skip_if_binaries_missing_marker.kwargs)[ - 'reason' - ] = message - skip_reason = skip_if_binaries_missing( - binaries, **skip_if_binaries_missing_marker.kwargs - ) - if skip_reason: - raise pytest.skip.Exception(skip_reason, **exc_kwargs) - requires_network_marker = item.get_closest_marker('requires_network') - if requires_network_marker is not None: - only_local_network = requires_network_marker.kwargs.get( - 'only_local_network', False - ) - local_skip_reason = skip_if_no_local_network() - if local_skip_reason: - raise pytest.skip.Exception(local_skip_reason, **exc_kwargs) - if only_local_network is False: - remote_skip_reason = skip_if_no_remote_network() - if remote_skip_reason: - raise pytest.skip.Exception(remote_skip_reason, **exc_kwargs) - skip_on_windows_marker = item.get_closest_marker('skip_on_windows') - if skip_on_windows_marker is not None: - if skip_on_windows_marker.args: - raise pytest.UsageError( - 'The skip_on_windows marker does not accept any arguments' - ) - reason = cast(Dict[str, Any], skip_on_windows_marker.kwargs).pop('reason', None) - if skip_on_windows_marker.kwargs: - raise pytest.UsageError( - "The skip_on_windows marker only accepts 'reason' as a keyword argument." - ) - if reason is None: - reason = 'Skipped on Windows' - if pytestskipmarkers.utils.platform.is_windows(): - raise pytest.skip.Exception(reason, **exc_kwargs) - skip_unless_on_windows_marker = item.get_closest_marker('skip_unless_on_windows') - if skip_unless_on_windows_marker is not None: - if skip_unless_on_windows_marker.args: - raise pytest.UsageError( - 'The skip_unless_on_windows marker does not accept any arguments' - ) - reason = cast(Dict[str, Any], skip_unless_on_windows_marker.kwargs).pop( - 'reason', None - ) - if skip_unless_on_windows_marker.kwargs: - raise pytest.UsageError( - "The skip_unless_on_windows marker only accepts 'reason' as a keyword argument." - ) - if reason is None: - reason = 'Platform is not Windows, skipped' - if not pytestskipmarkers.utils.platform.is_windows(): - raise pytest.skip.Exception(reason, **exc_kwargs) - skip_on_linux_marker = item.get_closest_marker('skip_on_linux') - if skip_on_linux_marker is not None: - if skip_on_linux_marker.args: - raise pytest.UsageError( - 'The skip_on_linux marker does not accept any arguments' - ) - reason = cast(Dict[str, Any], skip_on_linux_marker.kwargs).pop('reason', None) - if skip_on_linux_marker.kwargs: - raise pytest.UsageError( - "The skip_on_linux marker only accepts 'reason' as a keyword argument." - ) - if reason is None: - reason = 'Skipped on Linux' - if pytestskipmarkers.utils.platform.is_linux(): - raise pytest.skip.Exception(reason, **exc_kwargs) - skip_unless_on_linux_marker = item.get_closest_marker('skip_unless_on_linux') - if skip_unless_on_linux_marker is not None: - if skip_unless_on_linux_marker.args: - raise pytest.UsageError( - 'The skip_unless_on_linux marker does not accept any arguments' - ) - reason = cast(Dict[str, Any], skip_unless_on_linux_marker.kwargs).pop( - 'reason', None - ) - if skip_unless_on_linux_marker.kwargs: - raise pytest.UsageError( - "The skip_unless_on_linux marker only accepts 'reason' as a keyword argument." - ) - if reason is None: - reason = 'Platform is not Linux, skipped' - if not pytestskipmarkers.utils.platform.is_linux(): - raise pytest.skip.Exception(reason, **exc_kwargs) - skip_on_darwin_marker = item.get_closest_marker('skip_on_darwin') - if skip_on_darwin_marker is not None: - if skip_on_darwin_marker.args: - raise pytest.UsageError( - 'The skip_on_darwin marker does not accept any arguments' - ) - reason = cast(Dict[str, Any], skip_on_darwin_marker.kwargs).pop('reason', None) - if skip_on_darwin_marker.kwargs: - raise pytest.UsageError( - "The skip_on_darwin marker only accepts 'reason' as a keyword argument." - ) - if reason is None: - reason = 'Skipped on Darwin' - if pytestskipmarkers.utils.platform.is_darwin(): - raise pytest.skip.Exception(reason, **exc_kwargs) - skip_unless_on_darwin_marker = item.get_closest_marker('skip_unless_on_darwin') - if skip_unless_on_darwin_marker is not None: - if skip_unless_on_darwin_marker.args: - raise pytest.UsageError( - 'The skip_unless_on_darwin marker does not accept any arguments' - ) - reason = cast(Dict[str, Any], skip_unless_on_darwin_marker.kwargs).pop( - 'reason', None - ) - if skip_unless_on_darwin_marker.kwargs: - raise pytest.UsageError( - "The skip_unless_on_darwin marker only accepts 'reason' as a keyword argument." - ) - if reason is None: - reason = 'Platform is not Darwin, skipped' - if not pytestskipmarkers.utils.platform.is_darwin(): - raise pytest.skip.Exception(reason, **exc_kwargs) - skip_on_sunos_marker = item.get_closest_marker('skip_on_sunos') - if skip_on_sunos_marker is not None: - if skip_on_sunos_marker.args: - raise pytest.UsageError( - 'The skip_on_sunos marker does not accept any arguments' - ) - reason = cast(Dict[str, Any], skip_on_sunos_marker.kwargs).pop('reason', None) - if skip_on_sunos_marker.kwargs: - raise pytest.UsageError( - "The skip_on_sunos marker only accepts 'reason' as a keyword argument." - ) - if reason is None: - reason = 'Skipped on SunOS' - if pytestskipmarkers.utils.platform.is_sunos(): - raise pytest.skip.Exception(reason, **exc_kwargs) - skip_unless_on_sunos_marker = item.get_closest_marker('skip_unless_on_sunos') - if skip_unless_on_sunos_marker is not None: - if skip_unless_on_sunos_marker.args: - raise pytest.UsageError( - 'The skip_unless_on_sunos marker does not accept any arguments' - ) - reason = cast(Dict[str, Any], skip_unless_on_sunos_marker.kwargs).pop( - 'reason', None - ) - if skip_unless_on_sunos_marker.kwargs: - raise pytest.UsageError( - "The skip_unless_on_sunos marker only accepts 'reason' as a keyword argument." - ) - if reason is None: - reason = 'Platform is not SunOS, skipped' - if not pytestskipmarkers.utils.platform.is_sunos(): - raise pytest.skip.Exception(reason, **exc_kwargs) - skip_on_smartos_marker = item.get_closest_marker('skip_on_smartos') - if skip_on_smartos_marker is not None: - if skip_on_smartos_marker.args: - raise pytest.UsageError( - 'The skip_on_smartos marker does not accept any arguments' - ) - reason = cast(Dict[str, Any], skip_on_smartos_marker.kwargs).pop('reason', None) - if skip_on_smartos_marker.kwargs: - raise pytest.UsageError( - "The skip_on_smartos marker only accepts 'reason' as a keyword argument." - ) - if reason is None: - reason = 'Skipped on SmartOS' - if pytestskipmarkers.utils.platform.is_smartos(): - raise pytest.skip.Exception(reason, **exc_kwargs) - skip_unless_on_smartos_marker = item.get_closest_marker('skip_unless_on_smartos') - if skip_unless_on_smartos_marker is not None: - if skip_unless_on_smartos_marker.args: - raise pytest.UsageError( - 'The skip_unless_on_smartos marker does not accept any arguments' - ) - reason = cast(Dict[str, Any], skip_unless_on_smartos_marker.kwargs).pop( - 'reason', None - ) - if skip_unless_on_smartos_marker.kwargs: - raise pytest.UsageError( - "The skip_unless_on_smartos marker only accepts 'reason' as a keyword argument." - ) - if reason is None: - reason = 'Platform is not SmartOS, skipped' - if not pytestskipmarkers.utils.platform.is_smartos(): - raise pytest.skip.Exception(reason, **exc_kwargs) - skip_on_freebsd_marker = item.get_closest_marker('skip_on_freebsd') - if skip_on_freebsd_marker is not None: - if skip_on_freebsd_marker.args: - raise pytest.UsageError( - 'The skip_on_freebsd marker does not accept any arguments' - ) - reason = cast(Dict[str, Any], skip_on_freebsd_marker.kwargs).pop('reason', None) - if skip_on_freebsd_marker.kwargs: - raise pytest.UsageError( - "The skip_on_freebsd marker only accepts 'reason' as a keyword argument." - ) - if reason is None: - reason = 'Skipped on FreeBSD' - if pytestskipmarkers.utils.platform.is_freebsd(): - raise pytest.skip.Exception(reason, **exc_kwargs) - skip_unless_on_freebsd_marker = item.get_closest_marker('skip_unless_on_freebsd') - if skip_unless_on_freebsd_marker is not None: - if skip_unless_on_freebsd_marker.args: - raise pytest.UsageError( - 'The skip_unless_on_freebsd marker does not accept any arguments' - ) - reason = cast(Dict[str, Any], skip_unless_on_freebsd_marker.kwargs).pop( - 'reason', None - ) - if skip_unless_on_freebsd_marker.kwargs: - raise pytest.UsageError( - "The skip_unless_on_freebsd marker only accepts 'reason' as a keyword argument." - ) - if reason is None: - reason = 'Platform is not FreeBSD, skipped' - if not pytestskipmarkers.utils.platform.is_freebsd(): - raise pytest.skip.Exception(reason, **exc_kwargs) - skip_on_netbsd_marker = item.get_closest_marker('skip_on_netbsd') - if skip_on_netbsd_marker is not None: - if skip_on_netbsd_marker.args: - raise pytest.UsageError( - 'The skip_on_netbsd marker does not accept any arguments' - ) - reason = cast(Dict[str, Any], skip_on_netbsd_marker.kwargs).pop('reason', None) - if skip_on_netbsd_marker.kwargs: - raise pytest.UsageError( - "The skip_on_netbsd marker only accepts 'reason' as a keyword argument." - ) - if reason is None: - reason = 'Skipped on NetBSD' - if pytestskipmarkers.utils.platform.is_netbsd(): - raise pytest.skip.Exception(reason, **exc_kwargs) - skip_unless_on_netbsd_marker = item.get_closest_marker('skip_unless_on_netbsd') - if skip_unless_on_netbsd_marker is not None: - if skip_unless_on_netbsd_marker.args: - raise pytest.UsageError( - 'The skip_unless_on_netbsd marker does not accept any arguments' - ) - reason = cast(Dict[str, Any], skip_unless_on_netbsd_marker.kwargs).pop( - 'reason', None - ) - if skip_unless_on_netbsd_marker.kwargs: - raise pytest.UsageError( - "The skip_unless_on_netbsd marker only accepts 'reason' as a keyword argument." - ) - if reason is None: - reason = 'Platform is not NetBSD, skipped' - if not pytestskipmarkers.utils.platform.is_netbsd(): - raise pytest.skip.Exception(reason, **exc_kwargs) - skip_on_openbsd_marker = item.get_closest_marker('skip_on_openbsd') - if skip_on_openbsd_marker is not None: - if skip_on_openbsd_marker.args: - raise pytest.UsageError( - 'The skip_on_openbsd marker does not accept any arguments' - ) - reason = cast(Dict[str, Any], skip_on_openbsd_marker.kwargs).pop('reason', None) - if skip_on_openbsd_marker.kwargs: - raise pytest.UsageError( - "The skip_on_openbsd marker only accepts 'reason' as a keyword argument." - ) - if reason is None: - reason = 'Skipped on OpenBSD' - if pytestskipmarkers.utils.platform.is_openbsd(): - raise pytest.skip.Exception(reason, **exc_kwargs) - skip_unless_on_openbsd_marker = item.get_closest_marker('skip_unless_on_openbsd') - if skip_unless_on_openbsd_marker is not None: - if skip_unless_on_openbsd_marker.args: - raise pytest.UsageError( - 'The skip_unless_on_openbsd marker does not accept any arguments' - ) - reason = cast(Dict[str, Any], skip_unless_on_openbsd_marker.kwargs).pop( - 'reason', None - ) - if skip_unless_on_openbsd_marker.kwargs: - raise pytest.UsageError( - "The skip_unless_on_openbsd marker only accepts 'reason' as a keyword argument." - ) - if reason is None: - reason = 'Platform is not OpenBSD, skipped' - if not pytestskipmarkers.utils.platform.is_openbsd(): - raise pytest.skip.Exception(reason, **exc_kwargs) - skip_on_aix_marker = item.get_closest_marker('skip_on_aix') - if skip_on_aix_marker is not None: - if skip_on_aix_marker.args: - raise pytest.UsageError( - 'The skip_on_aix marker does not accept any arguments' - ) - reason = cast(Dict[str, Any], skip_on_aix_marker.kwargs).pop('reason', None) - if skip_on_aix_marker.kwargs: - raise pytest.UsageError( - "The skip_on_aix marker only accepts 'reason' as a keyword argument." - ) - if reason is None: - reason = 'Skipped on AIX' - if pytestskipmarkers.utils.platform.is_aix(): - raise pytest.skip.Exception(reason, **exc_kwargs) - skip_unless_on_aix_marker = item.get_closest_marker('skip_unless_on_aix') - if skip_unless_on_aix_marker is not None: - if skip_unless_on_aix_marker.args: - raise pytest.UsageError( - 'The skip_unless_on_aix marker does not accept any arguments' - ) - reason = cast(Dict[str, Any], skip_unless_on_aix_marker.kwargs).pop( - 'reason', None - ) - if skip_unless_on_aix_marker.kwargs: - raise pytest.UsageError( - "The skip_unless_on_aix marker only accepts 'reason' as a keyword argument." - ) - if reason is None: - reason = 'Platform is not AIX, skipped' - if not pytestskipmarkers.utils.platform.is_aix(): - raise pytest.skip.Exception(reason, **exc_kwargs) - skip_on_aarch64_marker = item.get_closest_marker('skip_on_aarch64') - if skip_on_aarch64_marker is not None: - if skip_on_aarch64_marker.args: - raise pytest.UsageError( - 'The skip_on_aarch64 marker does not accept any arguments' - ) - reason = cast(Dict[str, Any], skip_on_aarch64_marker.kwargs).pop('reason', None) - if skip_on_aarch64_marker.kwargs: - raise pytest.UsageError( - "The skip_on_aarch64 marker only accepts 'reason' as a keyword argument." - ) - if reason is None: - reason = 'Skipped on AArch64' - if pytestskipmarkers.utils.platform.is_aarch64(): - raise pytest.skip.Exception(reason, **exc_kwargs) - skip_unless_on_aarch64_marker = item.get_closest_marker('skip_unless_on_aarch64') - if skip_unless_on_aarch64_marker is not None: - if skip_unless_on_aarch64_marker.args: - raise pytest.UsageError( - 'The skip_unless_on_aarch64 marker does not accept any arguments' - ) - reason = cast(Dict[str, Any], skip_unless_on_aarch64_marker.kwargs).pop( - 'reason', None - ) - if skip_unless_on_aarch64_marker.kwargs: - raise pytest.UsageError( - "The skip_unless_on_aarch64 marker only accepts 'reason' as a keyword argument." - ) - if reason is None: - reason = 'Platform is not AArch64, skipped' - if not pytestskipmarkers.utils.platform.is_aarch64(): - raise pytest.skip.Exception(reason, **exc_kwargs) - skip_on_spawning_platform_marker = item.get_closest_marker( - 'skip_on_spawning_platform' - ) - if skip_on_spawning_platform_marker is not None: - if skip_on_spawning_platform_marker.args: - raise pytest.UsageError( - 'The skip_on_spawning_platform marker does not accept any arguments' - ) - reason = cast(Dict[str, Any], skip_on_spawning_platform_marker.kwargs).pop( - 'reason', None - ) - if skip_on_spawning_platform_marker.kwargs: - raise pytest.UsageError( - "The skip_on_spawning_platform marker only accepts 'reason' as a keyword argument." - ) - if reason is None: - reason = 'Skipped on spawning platforms' - if pytestskipmarkers.utils.platform.is_spawning_platform(): - raise pytest.skip.Exception(reason, **exc_kwargs) - skip_unless_on_spawning_platform_marker = item.get_closest_marker( - 'skip_unless_on_spawning_platform' - ) - if skip_unless_on_spawning_platform_marker is not None: - if skip_unless_on_spawning_platform_marker.args: - raise pytest.UsageError( - 'The skip_unless_on_spawning_platform marker does not accept any arguments' - ) - reason = cast( - Dict[str, Any], skip_unless_on_spawning_platform_marker.kwargs - ).pop('reason', None) - if skip_unless_on_spawning_platform_marker.kwargs: - raise pytest.UsageError( - "The skip_unless_on_spawning_platform marker only accepts 'reason' as a keyword argument." - ) - if reason is None: - reason = 'Platform does not default multiprocessing to spawn, skipped' - if not pytestskipmarkers.utils.platform.is_spawning_platform(): - raise pytest.skip.Exception(reason, **exc_kwargs) - skip_on_photonos_marker = item.get_closest_marker('skip_on_photonos') - if skip_on_photonos_marker is not None: - if skip_on_photonos_marker.args: - raise pytest.UsageError( - 'The skip_on_photonos marker does not accept any arguments' - ) - reason = cast(Dict[str, Any], skip_on_photonos_marker.kwargs).pop( - 'reason', None - ) - if skip_on_photonos_marker.kwargs: - raise pytest.UsageError( - "The skip_on_photonos marker only accepts 'reason' as a keyword argument." - ) - if reason is None: - reason = 'Skipped on PhotonOS' - if pytestskipmarkers.utils.platform.is_photonos(): - raise pytest.skip.Exception(reason, **exc_kwargs) - skip_unless_on_photonos_marker = item.get_closest_marker('skip_unless_on_photonos') - if skip_unless_on_photonos_marker is not None: - if skip_unless_on_photonos_marker.args: - raise pytest.UsageError( - 'The skip_unless_on_photonos marker does not accept any arguments' - ) - reason = cast(Dict[str, Any], skip_unless_on_photonos_marker.kwargs).pop( - 'reason', None - ) - if skip_unless_on_photonos_marker.kwargs: - raise pytest.UsageError( - "The skip_unless_on_photonos marker only accepts 'reason' as a keyword argument." - ) - if reason is None: - reason = 'Platform is not PhotonOS, skipped' - if not pytestskipmarkers.utils.platform.is_photonos(): - raise pytest.skip.Exception(reason, **exc_kwargs) - skip_on_platforms_marker = item.get_closest_marker('skip_on_platforms') - if skip_on_platforms_marker is not None: - if skip_on_platforms_marker.args: - raise pytest.UsageError( - 'The skip_on_platforms marker does not accept any arguments' - ) - reason = cast(Dict[str, Any], skip_on_platforms_marker.kwargs).pop( - 'reason', None - ) - if not skip_on_platforms_marker.kwargs: - raise pytest.UsageError( - 'Pass at least one platform to skip_on_platforms as a keyword argument' - ) - if not any(skip_on_platforms_marker.kwargs.values()): - raise pytest.UsageError( - 'Pass at least one platform with a True value to skip_on_platforms as a keyword argument' - ) - if reason is None: - reason = 'Skipped on platform match' - try: - if pytestskipmarkers.utils.platform.on_platforms( - **skip_on_platforms_marker.kwargs - ): - raise pytest.skip.Exception(reason, **exc_kwargs) - except TypeError as exc: - raise pytest.UsageError( - 'Passed an invalid platform to skip_on_platforms: {}'.format(exc) - ) - skip_unless_on_platforms_marker = item.get_closest_marker( - 'skip_unless_on_platforms' - ) - if skip_unless_on_platforms_marker is not None: - if skip_unless_on_platforms_marker.args: - raise pytest.UsageError( - 'The skip_unless_on_platforms marker does not accept any arguments' - ) - reason = cast(Dict[str, Any], skip_unless_on_platforms_marker.kwargs).pop( - 'reason', None - ) - if not skip_unless_on_platforms_marker.kwargs: - raise pytest.UsageError( - 'Pass at least one platform to skip_unless_on_platforms as a keyword argument' - ) - if not any(skip_unless_on_platforms_marker.kwargs.values()): - raise pytest.UsageError( - 'Pass at least one platform with a True value to skip_unless_on_platforms as a keyword argument' - ) - if reason is None: - reason = 'Platform(s) do not match, skipped' - try: - if not pytestskipmarkers.utils.platform.on_platforms( - **skip_unless_on_platforms_marker.kwargs - ): - raise pytest.skip.Exception(reason, **exc_kwargs) - except TypeError as exc: - raise pytest.UsageError( - 'Passed an invalid platform to skip_unless_on_platforms: {}'.format(exc) - ) - skip_on_env_marker = item.get_closest_marker('skip_on_env') - if skip_on_env_marker is not None: - args = list(skip_on_env_marker.args) - if not args: - raise pytest.UsageError( - "The 'skip_on_env' marker needs at least one argument to be passed, the environment variable name." - ) - envvar = args.pop(0) - if args: - raise pytest.UsageError( - "The 'skip_on_env' only accepts one argument, the environment variable name." - ) - if not isinstance(envvar, str): - raise pytest.UsageError( - 'The environment variable argument must be a string.' - ) - kwargs = cast(Dict[str, Any], skip_on_env_marker.kwargs).copy() - present = kwargs.pop('present', True) - eq = kwargs.pop('eq', None) - ne = kwargs.pop('ne', None) - reason = kwargs.pop('reason', None) - if kwargs: - raise pytest.UsageError( - "The 'skip_on_env' marker only accepts 'present', 'eq', 'ne' and 'reason' as keyword arguments." - ) - skip_reason = skip_on_env(envvar, present=present, eq=eq, ne=ne, reason=reason) - if skip_reason: - raise pytest.skip.Exception(skip_reason, **exc_kwargs) diff --git a/src/pytestskipmarkers/downgraded/utils/platform.py b/src/pytestskipmarkers/downgraded/utils/platform.py deleted file mode 100644 index 8e575aa..0000000 --- a/src/pytestskipmarkers/downgraded/utils/platform.py +++ /dev/null @@ -1,230 +0,0 @@ -# Copyright 2021-2022 VMware, Inc. -# SPDX-License-Identifier: Apache-2.0 -# -""" -Platform related utilities. - -.. - PYTEST_DONT_REWRITE -""" -from __future__ import generator_stop -import multiprocessing -import os -import pathlib -import platform -import shutil -import subprocess -import sys -from functools import lru_cache -from typing import cast -import distro - - -@lru_cache(maxsize=None) -def is_windows() -> bool: - """ - Simple function to return if a host is Windows or not. - - :return bool: Return true on Windows - """ - return sys.platform.startswith('win') - - -@lru_cache(maxsize=None) -def is_linux() -> bool: - """ - Simple function to return if a host is Linux or not. - - Note for a proxy minion, we need to return something else - :return bool: Return true on Linux - """ - return sys.platform.startswith('linux') - - -@lru_cache(maxsize=None) -def is_darwin() -> bool: - """ - Simple function to return if a host is Darwin (macOS) or not. - - :return bool: Return true on Darwin(macOS) - """ - return sys.platform.startswith('darwin') - - -@lru_cache(maxsize=None) -def is_sunos() -> bool: - """ - Simple function to return if host is SunOS or not. - - :return bool: Return true on SunOS - """ - return sys.platform.startswith('sunos') - - -@lru_cache(maxsize=None) -def is_smartos() -> bool: - """ - Simple function to return if host is SmartOS (Illumos) or not. - - :return bool: Return true on SmartOS (Illumos) - """ - if is_sunos(): - return os.uname()[3].startswith('joyent_') - return False - - -@lru_cache(maxsize=None) -def is_freebsd() -> bool: - """ - Simple function to return if host is FreeBSD or not. - - :return bool: Return true on FreeBSD - """ - return sys.platform.startswith('freebsd') - - -@lru_cache(maxsize=None) -def is_netbsd() -> bool: - """ - Simple function to return if host is NetBSD or not. - - :return bool: Return true on NetBSD - """ - return sys.platform.startswith('netbsd') - - -@lru_cache(maxsize=None) -def is_openbsd() -> bool: - """ - Simple function to return if host is OpenBSD or not. - - :return bool: Return true on OpenBSD - """ - return sys.platform.startswith('openbsd') - - -@lru_cache(maxsize=None) -def is_aix() -> bool: - """ - Simple function to return if host is AIX or not. - - :return bool: Return true on AIX - """ - return sys.platform.startswith('aix') - - -@lru_cache(maxsize=None) -def is_aarch64() -> bool: - """ - Simple function to return if host is AArch64 or not. - """ - return platform.machine().startswith('aarch64') - - -@lru_cache(maxsize=None) -def is_photonos() -> bool: - """ - Simple function to return if host is Photon OS or not. - """ - osname, _, _ = (x.strip('"').strip("'") for x in distro.linux_distribution()) - return cast(bool, osname == 'VMware Photon OS') - - -def is_spawning_platform() -> bool: - """ - Returns ``True`` if running on a platform which defaults multiprocessing to spawn. - """ - return multiprocessing.get_start_method(allow_none=False) == 'spawn' - - -def on_platforms( - windows: bool = False, - linux: bool = False, - darwin: bool = False, - sunos: bool = False, - smartos: bool = False, - freebsd: bool = False, - netbsd: bool = False, - openbsd: bool = False, - aix: bool = False, - aarch64: bool = False, - spawning: bool = False, - photonos: bool = False, -) -> bool: - """ - Check to see if we're on one of the provided platforms. - - :keyword bool windows: When :py:const:`True`, check if running on Windows. - :keyword bool linux: When :py:const:`True`, check if running on Linux. - :keyword bool darwin: When :py:const:`True`, check if running on Darwin. - :keyword bool sunos: When :py:const:`True`, check if running on SunOS. - :keyword bool smartos: When :py:const:`True`, check if running on SmartOS. - :keyword bool freebsd: When :py:const:`True`, check if running on FreeBSD. - :keyword bool netbsd: When :py:const:`True`, check if running on NetBSD. - :keyword bool openbsd: When :py:const:`True`, check if running on OpenBSD. - :keyword bool aix: When :py:const:`True`, check if running on AIX. - :keyword bool aarch64: When :py:const:`True`, check if running on AArch64. - :keyword bool spawning: - When :py:const:`True`, check if running on a platform which defaults - multiprocessing to spawn - """ - if windows and is_windows(): - return True - if linux and is_linux(): - return True - if darwin and is_darwin(): - return True - if sunos and is_sunos(): - return True - if smartos and is_smartos(): - return True - if freebsd and is_freebsd(): - return True - if netbsd and is_netbsd(): - return True - if openbsd and is_openbsd(): - return True - if aix and is_aix(): - return True - if aarch64 and is_aarch64(): - return True - if spawning and is_spawning_platform(): - return True - if photonos and is_photonos(): - return True - return False - - -def is_fips_enabled() -> bool: - """ - Check is FIPS is enabled. - - :return bool: Return true when enabled - """ - if pathlib.Path('/etc/system-fips').exists(): - return True - kernel_fips_enabled_path = pathlib.Path('/proc/sys/crypto/fips_enabled') - if ( - kernel_fips_enabled_path.exists() - and kernel_fips_enabled_path.read_text(encoding='utf-8').strip() == '1' - ): - return True - sysctl_path = shutil.which('sysctl') - if not sysctl_path: - return False - ret = subprocess.run( - [sysctl_path, 'crypto.fips_enabled'], - check=False, - shell=False, - stdout=subprocess.PIPE, - universal_newlines=True, - ) - if ret.returncode == 0: - stripped_output = ret.stdout.strip() - if not stripped_output: - return False - if '=' not in stripped_output: - return False - if stripped_output.split('=')[-1].strip() == '1': - return True - return False diff --git a/src/pytestskipmarkers/downgraded/utils/ports.py b/src/pytestskipmarkers/downgraded/utils/ports.py deleted file mode 100644 index 6f12ddc..0000000 --- a/src/pytestskipmarkers/downgraded/utils/ports.py +++ /dev/null @@ -1,68 +0,0 @@ -# Copyright 2021-2022 VMware, Inc. -# SPDX-License-Identifier: Apache-2.0 -# -""" -Ports related utility functions. -""" -from __future__ import generator_stop -import contextlib -import logging -from typing import Set -import pytest -from pytestskipmarkers.utils import socket - -log = logging.getLogger(__name__) - - -def get_unused_localhost_port(use_cache: bool = False) -> int: - """ - Return a random unused port on localhost. - - :keyword bool use_cache: - If ``use_cache`` is ``True``, consecutive calls to this function will never return the cached port. - """ - if not isinstance(use_cache, bool): - raise pytest.UsageError( - "The value of 'use_cache' needs to be an boolean, not {}".format( - type(use_cache) - ) - ) - with contextlib.closing( - socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM) - ) as usock: - usock.bind(('127.0.0.1', 0)) - port = usock.getsockname()[1] - if use_cache: - try: - cached_ports = get_unused_localhost_port.__cached_ports__ - except AttributeError: - cached_ports = get_unused_localhost_port.__cached_ports__ = set() - if port in cached_ports: - return get_unused_localhost_port(use_cache=use_cache) - cached_ports.add(port) - return port - - -def get_connectable_ports(ports: Set[int]) -> Set[int]: - """ - Returns a set of the ports where connection was successful. - - :param ~collections.abc.Iterable ports: An iterable of ports to try and connect to - :rtype: set - :return: Returns a set of the ports where connection was successful - """ - connectable_ports = set() - ports = set(ports) - for port in set(ports): - with contextlib.closing( - socket.socket(socket.AF_INET, socket.SOCK_STREAM) - ) as sock: - conn = sock.connect_ex(('localhost', port)) - try: - if conn == 0: - log.debug('Port %s is connectable!', port) - connectable_ports.add(port) - sock.shutdown(socket.SHUT_RDWR) - except OSError: - continue - return connectable_ports diff --git a/src/pytestskipmarkers/downgraded/utils/socket.py b/src/pytestskipmarkers/downgraded/utils/socket.py deleted file mode 100644 index 1f931ed..0000000 --- a/src/pytestskipmarkers/downgraded/utils/socket.py +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright 2021-2022 VMware, Inc. -# SPDX-License-Identifier: Apache-2.0 -# -""" -Namespaced ``socket`` module. - -This module's sole purpose is to have the standard library :py:mod:`socket` module -functions under a different namespace to be used in pytest-skip-markers so that -projects using it, which need to mock :py:mod:`socket` functions, don't influence -the pytest-skip-markers run time behavior. -""" -from __future__ import generator_stop -from socket import * diff --git a/src/pytestskipmarkers/downgraded/utils/win_functions.py b/src/pytestskipmarkers/downgraded/utils/win_functions.py deleted file mode 100644 index 057b87b..0000000 --- a/src/pytestskipmarkers/downgraded/utils/win_functions.py +++ /dev/null @@ -1,130 +0,0 @@ -# Copyright 2021-2022 VMware, Inc. -# SPDX-License-Identifier: Apache-2.0 -# -""" -Windows specific functions. - -.. - PYTEST_DONT_REWRITE -""" -from __future__ import generator_stop -from typing import List -from typing import Union - -try: - import pywintypes - import win32api - import win32net - import win32security -except ImportError: - pass - - -def is_admin(name: str) -> bool: - """ - Is the passed user a member of the Administrators group. - - Args: - name (str): The name to check - - Returns: - bool: True if user is a member of the Administrators group, False - otherwise - """ - groups = get_user_groups(name, True) - for group in groups: - if group in ('S-1-5-32-544', 'S-1-5-18'): - return True - return False - - -def get_user_groups(name: str, sid: bool = False) -> List[str]: - """ - Get the groups to which a user belongs. - - Args: - name (str): The user name to query - sid (bool): True will return a list of SIDs, False will return a list of - group names - - Returns: - list: A list of group names or sids - """ - groups = [] - if name.upper() == 'SYSTEM': - groups = ['SYSTEM'] - else: - try: - groups = win32net.NetUserGetLocalGroups(None, name) - except (win32net.error, pywintypes.error) as exc: - if exc.winerror in (5, 1722, 2453, 1927, 1355): - groups = win32net.NetUserGetLocalGroups(None, name, 0) - else: - try: - groups = win32net.NetUserGetGroups(None, name) - except win32net.error as exc: - if exc.winerror in (5, 1722, 2453, 1927, 1355): - groups = win32net.NetUserGetLocalGroups(None, name, 0) - except pywintypes.error as exc: - if exc.winerror in (5, 1722, 2453, 1927, 1355): - groups = win32net.NetUserGetLocalGroups(None, name, 1) - else: - raise - if not sid: - return groups - ret_groups = [] - for group in groups: - ret_groups.append(get_sid_from_name(group)) - return ret_groups - - -def get_sid_from_name(name: str) -> str: - """ - This is a tool for getting a sid from a name. The name can be any object. - - Usually a user or a group. - - Args: - name (str): The name of the user or group for which to get the sid - - Returns: - str: The corresponding SID - """ - if name is None: - name = 'NULL SID' - try: - sid = win32security.LookupAccountName(None, name)[0] - except pywintypes.error as exc: - raise Exception('User {} not found: {}'.format(name, exc)) from exc - sidstr = win32security.ConvertSidToStringSid(sid) - return sidstr - - -def get_current_user(with_domain: bool = True) -> Union[str, bool]: - """ - Gets the user executing the process. - - Args: - - with_domain (bool): - ``True`` will prepend the user name with the machine name or domain - separated by a backslash - - Returns: - str: The user name - """ - try: - user_name = win32api.GetUserNameEx(win32api.NameSamCompatible) - if user_name[-1] == '$': - test_user = win32api.GetUserName() - if test_user == 'SYSTEM': - user_name = 'SYSTEM' - elif get_sid_from_name(test_user) == 'S-1-5-18': - user_name = 'SYSTEM' - elif not with_domain: - user_name = win32api.GetUserName() - except pywintypes.error as exc: - raise Exception('Failed to get current user: {}'.format(exc)) from exc - if not user_name: - return False - return user_name diff --git a/src/pytestskipmarkers/utils/markers.py b/src/pytestskipmarkers/utils/markers.py index 45b02a3..7911b5a 100644 --- a/src/pytestskipmarkers/utils/markers.py +++ b/src/pytestskipmarkers/utils/markers.py @@ -94,7 +94,7 @@ def skip_if_binaries_missing( if shutil.which(binary) is None: if reason is not None: return reason - return "The '{}' binary was not found".format(binary) + return f"The '{binary}' binary was not found" log.debug("All binaries found. Searched for: %s", ", ".join(binaries)) return None @@ -685,9 +685,7 @@ def evaluate_markers(item: "Item") -> None: if pytestskipmarkers.utils.platform.on_platforms(**skip_on_platforms_marker.kwargs): raise pytest.skip.Exception(reason, **exc_kwargs) except TypeError as exc: - raise pytest.UsageError( - "Passed an invalid platform to skip_on_platforms: {}".format(exc) - ) + raise pytest.UsageError(f"Passed an invalid platform to skip_on_platforms: {exc}") skip_unless_on_platforms_marker = item.get_closest_marker("skip_unless_on_platforms") if skip_unless_on_platforms_marker is not None: @@ -713,7 +711,7 @@ def evaluate_markers(item: "Item") -> None: raise pytest.skip.Exception(reason, **exc_kwargs) except TypeError as exc: raise pytest.UsageError( - "Passed an invalid platform to skip_unless_on_platforms: {}".format(exc) + f"Passed an invalid platform to skip_unless_on_platforms: {exc}" ) skip_on_env_marker = item.get_closest_marker("skip_on_env") diff --git a/src/pytestskipmarkers/utils/platform.py b/src/pytestskipmarkers/utils/platform.py index 9bc3416..38ef0f2 100644 --- a/src/pytestskipmarkers/utils/platform.py +++ b/src/pytestskipmarkers/utils/platform.py @@ -14,13 +14,11 @@ import shutil import subprocess import sys -from functools import lru_cache from typing import cast import distro -@lru_cache(maxsize=None) def is_windows() -> bool: """ Simple function to return if a host is Windows or not. @@ -30,7 +28,6 @@ def is_windows() -> bool: return sys.platform.startswith("win") -@lru_cache(maxsize=None) def is_linux() -> bool: """ Simple function to return if a host is Linux or not. @@ -41,7 +38,6 @@ def is_linux() -> bool: return sys.platform.startswith("linux") -@lru_cache(maxsize=None) def is_darwin() -> bool: """ Simple function to return if a host is Darwin (macOS) or not. @@ -51,7 +47,6 @@ def is_darwin() -> bool: return sys.platform.startswith("darwin") -@lru_cache(maxsize=None) def is_sunos() -> bool: """ Simple function to return if host is SunOS or not. @@ -61,7 +56,6 @@ def is_sunos() -> bool: return sys.platform.startswith("sunos") -@lru_cache(maxsize=None) def is_smartos() -> bool: """ Simple function to return if host is SmartOS (Illumos) or not. @@ -73,7 +67,6 @@ def is_smartos() -> bool: return False -@lru_cache(maxsize=None) def is_freebsd() -> bool: """ Simple function to return if host is FreeBSD or not. @@ -83,7 +76,6 @@ def is_freebsd() -> bool: return sys.platform.startswith("freebsd") -@lru_cache(maxsize=None) def is_netbsd() -> bool: """ Simple function to return if host is NetBSD or not. @@ -93,7 +85,6 @@ def is_netbsd() -> bool: return sys.platform.startswith("netbsd") -@lru_cache(maxsize=None) def is_openbsd() -> bool: """ Simple function to return if host is OpenBSD or not. @@ -103,7 +94,6 @@ def is_openbsd() -> bool: return sys.platform.startswith("openbsd") -@lru_cache(maxsize=None) def is_aix() -> bool: """ Simple function to return if host is AIX or not. @@ -113,7 +103,6 @@ def is_aix() -> bool: return sys.platform.startswith("aix") -@lru_cache(maxsize=None) def is_aarch64() -> bool: """ Simple function to return if host is AArch64 or not. @@ -121,7 +110,6 @@ def is_aarch64() -> bool: return platform.machine().startswith("aarch64") -@lru_cache(maxsize=None) def is_photonos() -> bool: """ Simple function to return if host is Photon OS or not. @@ -229,7 +217,7 @@ def is_fips_enabled() -> bool: check=False, shell=False, stdout=subprocess.PIPE, - universal_newlines=True, + text=True, ) if ret.returncode == 0: stripped_output = ret.stdout.strip() diff --git a/src/pytestskipmarkers/utils/ports.py b/src/pytestskipmarkers/utils/ports.py index 407c09c..e3a87a1 100644 --- a/src/pytestskipmarkers/utils/ports.py +++ b/src/pytestskipmarkers/utils/ports.py @@ -24,7 +24,7 @@ def get_unused_localhost_port(use_cache: bool = False) -> int: """ if not isinstance(use_cache, bool): raise pytest.UsageError( - "The value of 'use_cache' needs to be an boolean, not {}".format(type(use_cache)) + f"The value of 'use_cache' needs to be an boolean, not {type(use_cache)}" ) with contextlib.closing(socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)) as usock: diff --git a/src/pytestskipmarkers/utils/win_functions.py b/src/pytestskipmarkers/utils/win_functions.py index 101f038..563f999 100644 --- a/src/pytestskipmarkers/utils/win_functions.py +++ b/src/pytestskipmarkers/utils/win_functions.py @@ -112,7 +112,7 @@ def get_sid_from_name(name: str) -> str: try: sid = win32security.LookupAccountName(None, name)[0] except pywintypes.error as exc: - raise Exception("User {} not found: {}".format(name, exc)) from exc + raise Exception(f"User {name} not found: {exc}") from exc sidstr: str = win32security.ConvertSidToStringSid(sid) return sidstr @@ -144,7 +144,7 @@ def get_current_user(with_domain: bool = True) -> Union[str, bool]: elif not with_domain: user_name = win32api.GetUserName() except pywintypes.error as exc: - raise Exception("Failed to get current user: {}".format(exc)) from exc + raise Exception(f"Failed to get current user: {exc}") from exc if not user_name: return False diff --git a/tests/functional/test_skip_on_platforms.py b/tests/functional/test_skip_on_platforms.py index d631906..f28a94e 100644 --- a/tests/functional/test_skip_on_platforms.py +++ b/tests/functional/test_skip_on_platforms.py @@ -47,9 +47,7 @@ def test_one(): ) ) return_value = True - with mock.patch( - "pytestskipmarkers.utils.platform.is_{}".format(platform), return_value=return_value - ): + with mock.patch(f"pytestskipmarkers.utils.platform.is_{platform}", return_value=return_value): res = pytester.runpytest_inprocess() res.assert_outcomes(skipped=1) res.stdout.no_fnmatch_line("*PytestUnknownMarkWarning*") @@ -83,9 +81,7 @@ def test_one(): ) ) return_value = False - with mock.patch( - "pytestskipmarkers.utils.platform.is_{}".format(platform), return_value=return_value - ): + with mock.patch(f"pytestskipmarkers.utils.platform.is_{platform}", return_value=return_value): res = pytester.runpytest_inprocess() res.assert_outcomes(passed=1) res.stdout.no_fnmatch_line("*PytestUnknownMarkWarning*") diff --git a/tests/functional/test_skip_unless_on_platforms.py b/tests/functional/test_skip_unless_on_platforms.py index 15f2517..87efe30 100644 --- a/tests/functional/test_skip_unless_on_platforms.py +++ b/tests/functional/test_skip_unless_on_platforms.py @@ -49,9 +49,9 @@ def test_one(): ) return_value = False if platform == "spawning": - patch_target = "pytestskipmarkers.utils.platform.is_{}_platform".format(platform) + patch_target = f"pytestskipmarkers.utils.platform.is_{platform}_platform" else: - patch_target = "pytestskipmarkers.utils.platform.is_{}".format(platform) + patch_target = f"pytestskipmarkers.utils.platform.is_{platform}" with mock.patch(patch_target, return_value=return_value): res = pytester.runpytest_inprocess() res.assert_outcomes(skipped=1) @@ -88,9 +88,9 @@ def test_one(): ) return_value = True if platform == "spawning": - patch_target = "pytestskipmarkers.utils.platform.is_{}_platform".format(platform) + patch_target = f"pytestskipmarkers.utils.platform.is_{platform}_platform" else: - patch_target = "pytestskipmarkers.utils.platform.is_{}".format(platform) + patch_target = f"pytestskipmarkers.utils.platform.is_{platform}" with mock.patch(patch_target, return_value=return_value): res = pytester.runpytest_inprocess() res.assert_outcomes(passed=1) diff --git a/tests/unit/utils/test_platform.py b/tests/unit/utils/test_platform.py index a1af429..f515edb 100644 --- a/tests/unit/utils/test_platform.py +++ b/tests/unit/utils/test_platform.py @@ -100,7 +100,7 @@ def test_is_smartos(): def is_sunos_ids(value): - return "is_sunos={}".format(value) + return f"is_sunos={value}" @pytest.mark.skip_on_windows(reason="Windows does not have `os.uname()`")