bootstrap   A
last analyzed

Complexity

Total Complexity 10

Size/Duplication

Total Lines 84
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 10
eloc 61
dl 0
loc 84
rs 10
c 0
b 0
f 0

3 Functions

Rating   Name   Duplication   Size   Complexity  
B exec_in_env() 0 26 6
A check_call() 0 3 1
A main() 0 29 3
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
        import subprocess
24
25
        print(f"Making bootstrap env in: {env_path} ...")
26
        try:
27
            check_call([sys.executable, "-m", "venv", env_path])
28
        except subprocess.CalledProcessError:
29
            try:
30
                check_call([sys.executable, "-m", "virtualenv", env_path])
31
            except subprocess.CalledProcessError:
32
                check_call(["virtualenv", env_path])
33
        print("Installing `jinja2` into bootstrap environment...")
34
        check_call([bin_path / "pip", "install", "jinja2", "tox"])
35
    python_executable = bin_path / "python"
36
    if not python_executable.exists():
37
        python_executable = python_executable.with_suffix(".exe")
38
39
    print(f"Re-executing with: {python_executable}")
40
    print("+ exec", python_executable, __file__, "--no-env")
41
    os.execv(python_executable, [python_executable, __file__, "--no-env"])
42
43
44
def main():
45
    import jinja2
46
47
    print(f"Project path: {base_path}")
48
49
    jinja = jinja2.Environment(
50
        loader=jinja2.FileSystemLoader(str(templates_path)),
51
        trim_blocks=True,
52
        lstrip_blocks=True,
53
        keep_trailing_newline=True,
54
    )
55
    tox_environments = [
56
        line.strip()
57
        # 'tox' need not be installed globally, but must be importable
58
        # by the Python that is running this script.
59
        # This uses sys.executable the same way that the call in
60
        # cookiecutter-pylibrary/hooks/post_gen_project.py
61
        # invokes this bootstrap.py itself.
62
        for line in subprocess.check_output([sys.executable, "-m", "tox", "--listenvs"], universal_newlines=True).splitlines()
63
    ]
64
    tox_environments = [line for line in tox_environments if line.startswith("py")]
65
    for template in templates_path.rglob("*"):
66
        if template.is_file():
67
            template_path = template.relative_to(templates_path).as_posix()
68
            destination = base_path / template_path
69
            destination.parent.mkdir(parents=True, exist_ok=True)
70
            destination.write_text(jinja.get_template(template_path).render(tox_environments=tox_environments))
71
            print(f"Wrote {template_path}")
72
    print("DONE.")
73
74
75
if __name__ == "__main__":
76
    args = sys.argv[1:]
77
    if args == ["--no-env"]:
78
        main()
79
    elif not args:
80
        exec_in_env()
81
    else:
82
        print(f"Unexpected arguments: {args}", file=sys.stderr)
83
        sys.exit(1)
84