Issues (17)

hooks/post_gen_project.py (2 issues)

1
#!/bin/env python3
2
"""
3
Cookiecutter post generation hook script that handles operations after the
4
template project is used to generate a target project.
5
"""
6
7
import os
8
import shlex
9
import shutil
10
import subprocess
11
import sys
12
from collections import OrderedDict
13
14
PROJECT_DIRECTORY = os.path.realpath(os.path.curdir)
15
16
17
def initialize_git_repo():
18
    """
19
    Initialize the Git repository in the generated project.
20
    """
21
    subprocess.check_output(
22
        "git init", stderr=subprocess.STDOUT, shell=True, cwd=PROJECT_DIRECTORY
23
    )
24
25
26
def git_add():
27
    """
28
    Do a Git add operation on the generated project.
29
    """
30
    subprocess.check_output(
31
        "git add --all", stderr=subprocess.STDOUT, shell=True, cwd=PROJECT_DIRECTORY
32
    )
33
34
35
def git_commit():
36
    """
37
    Commit the staged changes in the generated project.
38
    """
39
    cookiecutter_config = (
40
        OrderedDict()
41
    )  # We init the variable to the same type that will be set in the next line.
42
    cookiecutter_config = {{cookiecutter}}  # noqa pylint: disable=undefined-variable
43
44
    cookiecutter_config_str = ""
45
    for key, val in cookiecutter_config.items():  # noqa pylint: disable=no-member
46
        cookiecutter_config_str += f"  {key}: {val}\n"
47
48
    commit_message = (
49
        "Template applied from"
50
        " https://github.com/Digimach/cookiecutter-python-"
51
        "package\n\n"
52
        "Template configuration:\n"
53
        f"{cookiecutter_config_str}"
54
    )
55
56
    author_info = "{{ cookiecutter.project_author_name }}"
57
    author_info += " <{{cookiecutter.project_author_email }}>"
58
59
    env = os.environ.copy()
60
    env["GIT_COMMITTER_NAME"] = "{{ cookiecutter.project_author_name }}"
61
    env["GIT_COMMITTER_EMAIL"] = "{{ cookiecutter.project_author_email }}"
62
63
    try:
64
        subprocess.check_output(
65
            (f'git commit --author "{author_info}"' f' --message "{commit_message}"'),
66
            shell=True,
67
            cwd=PROJECT_DIRECTORY,
68
            env=env,
69
        )
70
71
    except subprocess.CalledProcessError as exc_info:
72
        if exc_info.returncode != 0:
73
            print(exc_info.output)
74
        raise
75
76
77
def is_git_repo_clean():
78
    """
79
    Check to confirm if the Git repository is clean and has no uncommitted
80
    changes. If its clean return True otherwise False.
81
    """
82
    try:
83
        if sys.version_info.minor >= 7:
84
            git_status = subprocess.run(
85
                shlex.split("git status --porcelain"),
86
                capture_output=True,
87
                cwd=PROJECT_DIRECTORY,
88
                check=True,
89
            )
90
        elif sys.version_info.minor < 7:
91
            git_status = subprocess.run(
92
                shlex.split("git status --porcelain"),
93
                stdout=subprocess.PIPE,
94
                stderr=subprocess.PIPE,
95
                cwd=PROJECT_DIRECTORY,
96
                check=True,
97
            )
98
    except subprocess.CalledProcessError:
99
        print(f"** Git repository in {PROJECT_DIRECTORY} cannot get status")
100
        sys.exit(1)
101
102
    if git_status.stdout == b"" and git_status.stderr == b"":
0 ignored issues
show
The variable git_status does not seem to be defined for all execution paths.
Loading history...
103
        return True
104
105
    return False
106
107
108
def set_license():
109
    """
110
    The template project generates the LICENSES folder that contains multiple
111
    licenses. This function will clear that folder up and move the chosen
112
    license to the generated project as the "LICENSE" file.
113
    """
114
    project_directory = PROJECT_DIRECTORY
115
    license_file = os.path.join(
116
        project_directory, "LICENSES", "{{ cookiecutter.project_license }}.rst"
117
    )
118
119
    if not os.path.exists(license_file):
120
        raise IOError("No known license for {{ cookiecutter.project_license }}")
121
122
    shutil.move(license_file, os.path.join(project_directory, "LICENSE.rst"))
123
    shutil.rmtree(os.path.join(project_directory, "LICENSES"))
124
125
    # Add the title to the LICENSE.rst file
126
    with open(
127
        os.path.join(project_directory, "LICENSE.rst"), "r+", encoding="utf8"
0 ignored issues
show
Wrong hanging indentation before block (add 4 spaces).
Loading history...
128
    ) as license_fp:
129
        content = license_fp.read()
130
        license_fp.seek(0, 0)
131
        license_fp.write("LICENSE\n#######" + "\n" + content)
132
133
134
if __name__ == "__main__":
135
    set_license()
136
137
    if "{{ cookiecutter.initialize_git_repo|lower }}" == "yes":
138
        initialize_git_repo()
139
        if not is_git_repo_clean():
140
            git_add()
141
            git_commit()
142
143
    sys.exit(0)
144