1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
|
# SPDX-FileCopyrightText: Peter Pentchev <roam@ringlet.net>
# SPDX-License-Identifier: BSD-2-Clause
"""Parse command-line arguments, run a command in a temporary directory."""
from __future__ import annotations
import os
import pathlib
import shutil
import subprocess # noqa: S404
import sys
import tempfile
import typing
import click
from . import defs
from . import util
if typing.TYPE_CHECKING:
from typing import Final
def arg_features(_ctx: click.Context, _self: click.Parameter, value: bool) -> bool: # noqa: FBT001
"""Display program features information and exit."""
if not value:
return value
print( # noqa: T201
"Features: " + " ".join(f"{name}={value}" for name, value in defs.FEATURES.items()),
)
sys.exit(0)
def run(cfg: defs.Config) -> None:
"""Create a temporary directory, copy the test file there, run the test."""
testf: Final = cfg.srcdir / "regex_3" / "test_regex.py"
if not testf.is_file():
sys.exit(f"Not a regular file: {testf}")
with tempfile.TemporaryDirectory(prefix="regex-temp-test.") as tempd_obj:
tempd: Final = pathlib.Path(tempd_obj)
cfg.log.debug("Using %(tempd)s as a temporary directory", {"tempd": tempd})
destf: Final = tempd / testf.name
cfg.log.debug("Copying %(src)s to %(dst)s", {"src": testf, "dst": destf})
shutil.copy2(testf, destf)
pyenv: Final = dict(os.environ)
def add_pypath(path: pathlib.Path) -> None:
"""Add the specified path to PYTHONPATH or set it if it isn't set at all."""
current: Final = pyenv.get("PYTHONPATH")
if current is None:
pyenv["PYTHONPATH"] = str(path)
else:
pyenv["PYTHONPATH"] = f"{path}:{current}"
if cfg.pybuild is not None:
pypath: Final = (
cfg.pybuild / f"cpython3_{sys.version_info[0]}.{sys.version_info[1]}" / "build"
)
if not pypath.is_dir():
sys.exit(f"Not a directory: {pypath}")
add_pypath(pypath)
if cfg.pypath is not None:
add_pypath(cfg.pypath)
subprocess.check_call( # noqa: S603
[sys.executable, "-B", "-u", "--", destf],
cwd=tempd,
env=pyenv,
)
@click.command(name="temptest")
@click.option(
"--features",
is_flag=True,
is_eager=True,
callback=arg_features,
help="display program features information and exit",
)
@click.option(
"--pybuild",
type=click.Path(
exists=True,
file_okay=False,
dir_okay=True,
path_type=pathlib.Path,
resolve_path=True,
),
help="the .pybuild directory to look for the built Python module in",
)
@click.option(
"--pypath",
type=click.Path(
exists=True,
file_okay=False,
dir_okay=True,
path_type=pathlib.Path,
resolve_path=True,
),
help="the built Python module parent directory to add to PYTHONPATH",
)
@click.option(
"--quiet",
"-q",
is_flag=True,
help="quiet operation; only display warning and error messages",
)
@click.option(
"--srcdir",
type=click.Path(
exists=True,
file_okay=False,
dir_okay=True,
path_type=pathlib.Path,
resolve_path=True,
),
required=True,
help="the directory to look for the regex module source code",
)
@click.option("--verbose", "-v", is_flag=True, help="verbose operation; display diagnostic output")
def main( # noqa: PLR0913 # yep, we like command-line arguments
*,
features: bool,
pybuild: pathlib.Path | None,
pypath: pathlib.Path | None,
quiet: bool,
srcdir: pathlib.Path,
verbose: bool,
) -> None:
"""Parse command-line arguments, copy test-regex to a temporary directory, run it."""
if features:
sys.exit("Internal error: how did we get to main() with features=True?")
cfg: Final = defs.Config(
log=util.build_logger(quiet=quiet, verbose=verbose),
pybuild=pybuild,
pypath=pypath,
srcdir=srcdir,
verbose=verbose,
)
run(cfg)
if __name__ == "__main__":
main()
|