mirror of
				https://github.com/fedora-python/tox-current-env.git
				synced 2025-11-04 01:58:56 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			136 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			136 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
import configparser
 | 
						|
import contextlib
 | 
						|
import functools
 | 
						|
import os
 | 
						|
import pathlib
 | 
						|
import re
 | 
						|
import subprocess
 | 
						|
import sys
 | 
						|
from configparser import ConfigParser
 | 
						|
 | 
						|
import pytest
 | 
						|
from packaging.version import parse as ver
 | 
						|
 | 
						|
PYTHON_VERSION_DOT = f"{sys.version_info[0]}.{sys.version_info[1]}"
 | 
						|
PYTHON_VERSION_NODOT = f"{sys.version_info[0]}{sys.version_info[1]}"
 | 
						|
NATIVE_TOXENV = f"py{PYTHON_VERSION_NODOT}"
 | 
						|
NATIVE_SITE_PACKAGES = f"lib/python{PYTHON_VERSION_DOT}/site-packages"
 | 
						|
NATIVE_EXECUTABLE = str(pathlib.Path(sys.executable).resolve())
 | 
						|
FIXTURES_DIR = pathlib.Path(__file__).parent / "fixtures"
 | 
						|
DOT_TOX = pathlib.Path("./.tox")
 | 
						|
 | 
						|
 | 
						|
def _exec_prefix(executable):
 | 
						|
    """Returns sys.exec_prefix for the given executable"""
 | 
						|
    cmd = (executable, "-c", "import sys; print(sys.exec_prefix)")
 | 
						|
    return subprocess.check_output(cmd, encoding="utf-8").strip()
 | 
						|
 | 
						|
 | 
						|
NATIVE_EXEC_PREFIX = _exec_prefix(NATIVE_EXECUTABLE)
 | 
						|
NATIVE_EXEC_PREFIX_MSG = f"{NATIVE_EXEC_PREFIX} is the exec_prefix"
 | 
						|
 | 
						|
 | 
						|
def tox(*args, quiet=True, **kwargs):
 | 
						|
    kwargs.setdefault("encoding", "utf-8")
 | 
						|
    kwargs.setdefault("stdout", subprocess.PIPE)
 | 
						|
    kwargs.setdefault("stderr", subprocess.PIPE)
 | 
						|
    kwargs.setdefault("check", True)
 | 
						|
    kwargs.setdefault("cwd", os.getcwd())
 | 
						|
    q = ("-q",) if quiet else ()
 | 
						|
    env = dict(os.environ)
 | 
						|
    env.pop("TOX_WORK_DIR", None)
 | 
						|
    kwargs["env"] = {**env, **kwargs.get("env", {})}
 | 
						|
    try:
 | 
						|
        print("current", os.getcwd(), "running in", kwargs["cwd"])
 | 
						|
        cp = subprocess.run((sys.executable, "-m", "tox") + q + args, **kwargs)
 | 
						|
    except subprocess.CalledProcessError as e:
 | 
						|
        print(e.stdout, file=sys.stdout)
 | 
						|
        print(e.stderr, file=sys.stderr)
 | 
						|
        raise
 | 
						|
    print(cp.stdout, file=sys.stdout)
 | 
						|
    print(cp.stderr, file=sys.stderr)
 | 
						|
    return cp
 | 
						|
 | 
						|
 | 
						|
TOX_VERSION = ver(tox("--version").stdout.split(" ")[0].split("+")[0])
 | 
						|
TOX4 = TOX_VERSION.major == 4
 | 
						|
 | 
						|
 | 
						|
@contextlib.contextmanager
 | 
						|
def modify_config(tox_ini_path):
 | 
						|
    """Context manager that allows modifying the given Tox config file
 | 
						|
 | 
						|
    A statement like::
 | 
						|
 | 
						|
        with prepare_config(projdir) as config:
 | 
						|
 | 
						|
    will make `config` a ConfigParser instance that is saved at the end
 | 
						|
    of the `with` block.
 | 
						|
    """
 | 
						|
    config = configparser.ConfigParser()
 | 
						|
    config.read(tox_ini_path)
 | 
						|
    yield config
 | 
						|
    with open(tox_ini_path, "w") as tox_ini_file:
 | 
						|
        config.write(tox_ini_file)
 | 
						|
 | 
						|
 | 
						|
@functools.lru_cache(maxsize=8)
 | 
						|
def is_available(python):
 | 
						|
    try:
 | 
						|
        subprocess.run((python, "--version"))
 | 
						|
    except FileNotFoundError:
 | 
						|
        return False
 | 
						|
    return True
 | 
						|
 | 
						|
 | 
						|
@functools.lru_cache()
 | 
						|
def drop_unsupported_pythons(envlist):
 | 
						|
    return envlist[len("py36,py37,"):] if TOX4 else envlist
 | 
						|
 | 
						|
 | 
						|
@functools.lru_cache()
 | 
						|
def envs_from_tox_ini():
 | 
						|
    cp = ConfigParser()
 | 
						|
    cp.read(FIXTURES_DIR / "tox.ini")
 | 
						|
    envlist = drop_unsupported_pythons(cp["tox"]["envlist"])
 | 
						|
    return envlist.split(",")
 | 
						|
 | 
						|
 | 
						|
def tox_footer(envs=None, spaces=8):
 | 
						|
    if envs is None:
 | 
						|
        envs = envs_from_tox_ini()
 | 
						|
    elif isinstance(envs, str):
 | 
						|
        envs = [envs]
 | 
						|
 | 
						|
    default_indent = " " * spaces
 | 
						|
 | 
						|
    if TOX4:
 | 
						|
        result = ""
 | 
						|
    else:
 | 
						|
        result = "___________________________________ summary ____________________________________\n"
 | 
						|
 | 
						|
    for i, env in enumerate(envs):
 | 
						|
        if TOX4:
 | 
						|
            # Skip indentation for the first line
 | 
						|
            indent = default_indent if i > 0 else ""
 | 
						|
            result += f"{indent}  {env}: OK\n"
 | 
						|
        else:
 | 
						|
            result += f"{default_indent}  {env}: commands succeeded\n"
 | 
						|
 | 
						|
    result += f"{default_indent}  congratulations :)"
 | 
						|
 | 
						|
    return result
 | 
						|
 | 
						|
 | 
						|
def prep_tox_output(output):
 | 
						|
    """Remove time info from tox output"""
 | 
						|
    result = re.sub(r" \((\d+\.\d+|\d+) seconds\)", "", output)
 | 
						|
    result = re.sub(r" ✔ in (\d+\.\d+|\d+) seconds", "", result)
 | 
						|
    return result
 | 
						|
 | 
						|
 | 
						|
needs_all_pythons = pytest.mark.skipif(
 | 
						|
    not all((is_available(f"python3.{x}") for x in range(6, 12))),
 | 
						|
    reason="This test needs all pythons from 3.6 to 3.11 available in $PATH",
 | 
						|
)
 |