bootstrap.exec_in_env()   B
last analyzed

Complexity

Conditions 6

Size

Total Lines 24
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 22
dl 0
loc 24
rs 8.4186
c 0
b 0
f 0
cc 6
nop 0
1
#!/usr/bin/env python
2
import os
3
import pathlib
4
import subprocess
5
import sys
6
7
base_path: pathlib.Path = pathlib.Path(__file__).resolve().parent.parent
8
templates_path = base_path / "ci" / "templates"
9
10
11
def check_call(args):
12
    print("+", *args)
13
    subprocess.check_call(args)
14
15
16
def exec_in_env():
17
    env_path = base_path / ".tox" / "bootstrap"
18
    if sys.platform == "win32":
19
        bin_path = env_path / "Scripts"
20
    else:
21
        bin_path = env_path / "bin"
22
    if not env_path.exists():
23
        print(f"Making bootstrap env in: {env_path} ...")
24
        try:
25
            check_call([sys.executable, "-m", "venv", env_path])
26
        except subprocess.CalledProcessError:
27
            try:
28
                check_call([sys.executable, "-m", "virtualenv", env_path])
29
            except subprocess.CalledProcessError:
30
                check_call(["virtualenv", env_path])
31
        print("Installing `jinja2` into bootstrap environment...")
32
        check_call([bin_path / "pip", "install", "jinja2", "tox"])
33
    python_executable = bin_path / "python"
34
    if not python_executable.exists():
35
        python_executable = python_executable.with_suffix(".exe")
36
37
    print(f"Re-executing with: {python_executable}")
38
    print("+ exec", python_executable, __file__, "--no-env")
39
    os.execv(python_executable, [python_executable, __file__, "--no-env"])
40
41
42
def main():
43
    import jinja2  # noqa: PLC0415
44
45
    print(f"Project path: {base_path}")
46
47
    jinja = jinja2.Environment(
48
        loader=jinja2.FileSystemLoader(str(templates_path)),
49
        trim_blocks=True,
50
        lstrip_blocks=True,
51
        keep_trailing_newline=True,
52
    )
53
    tox_environments = [
54
        line.strip()
55
        # 'tox' need not be installed globally, but must be importable
56
        # by the Python that is running this script.
57
        # This uses sys.executable the same way that the call in
58
        # cookiecutter-pylibrary/hooks/post_gen_project.py
59
        # invokes this bootstrap.py itself.
60
        for line in subprocess.check_output([sys.executable, "-m", "tox", "--listenvs"], universal_newlines=True).splitlines()
61
    ]
62
    tox_environments = [line for line in tox_environments if line.startswith("py")]
63
    for template in templates_path.rglob("*"):
64
        if template.is_file():
65
            template_path = template.relative_to(templates_path).as_posix()
66
            destination = base_path / template_path
67
            destination.parent.mkdir(parents=True, exist_ok=True)
68
            destination.write_text(jinja.get_template(template_path).render(tox_environments=tox_environments))
69
            print(f"Wrote {template_path}")
70
    print("DONE.")
71
72
73
if __name__ == "__main__":
74
    args = sys.argv[1:]
75
    if args == ["--no-env"]:
76
        main()
77
    elif not args:
78
        exec_in_env()
79
    else:
80
        print(f"Unexpected arguments: {args}", file=sys.stderr)
81
        sys.exit(1)
82