Skip to content

Commit 2a2e33e

Browse files
Update default template
1 parent 7198d5d commit 2a2e33e

File tree

13 files changed

+182
-600
lines changed

13 files changed

+182
-600
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
__pycache__/
33
*.py[cod]
44
*$py.class
5+
.ruff_cache/
56

67
# Distribution / packaging
78
.Python

.pre-commit-config.yaml

Lines changed: 0 additions & 49 deletions
This file was deleted.

cookiecutter.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"project_name": "Boilerplate Template",
66
"github_repo_name": "{{ cookiecutter.project_name.lower().replace(' ', '-') }}",
77
"project_slug": "{{ cookiecutter.project_name.lower().replace(' ', '_').replace('-', '_') }}",
8-
"project_short_description": "Minimal python cookiecutter template with Poetry as the dependency manager and Black, Isort, Flake8, Flake8-bugbear as the linters.",
8+
"project_short_description": "Minimal python cookiecutter template with pip as the package manager and Ruff as the linting tool.",
99
"version": "1.0.0",
10-
"pytest": ["y", "n"]
10+
"pytest": ["n", "y"]
1111
}

hooks/post_gen_project.py

Lines changed: 103 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,27 @@
1-
#!/usr/bin/env python
21
from __future__ import annotations
32

3+
import os
4+
import pathlib
45
import shlex
56
import subprocess
67
import sys
8+
import venv
79
from pathlib import Path
810

911
ERROR_MSG = "Error occured while running command"
1012
PRETTY_LINES = "*" * 80
13+
PROJECT_NAME = "{{ cookiecutter.project_slug }}"
14+
# TODO: Can allow user to pass it in through cookiecutter.json
15+
VENV_NAME = ".venv"
16+
VIRTUAL_ENV = "VIRTUAL_ENV"
17+
18+
19+
# Setting up environment
20+
SUBPROCESS_PARAMS = {
21+
"stdout": subprocess.PIPE,
22+
"stderr": subprocess.PIPE,
23+
"check": True,
24+
}
1125

1226

1327
def main() -> int:
@@ -19,7 +33,12 @@ def main() -> int:
1933

2034
if return_code_one == 0:
2135
return_code_two = setup_environment()
22-
return 0 or return_code_one or return_code_two
36+
37+
if return_code_two == 0:
38+
return_code_three = _rename_pyproject_toml_file()
39+
print(f"New project {PROJECT_NAME!r} is setup.")
40+
41+
return 0 or return_code_one or return_code_two or return_code_three
2342

2443

2544
def initialize_git() -> int:
@@ -30,14 +49,14 @@ def initialize_git() -> int:
3049
),
3150
"init_git": (
3251
shlex.split("git init"),
33-
"Initializing an empty git repository locally. You will have to create a repo "
52+
"Initializing an empty git repository locally. You will have to create a repository "
3453
"on remote.\n",
3554
),
3655
}
3756
for cmds, message in COMMANDS_AND_MESSAGE.values():
3857
print(message)
3958
try:
40-
subprocess.run(cmds, check=True)
59+
subprocess.run(cmds, **SUBPROCESS_PARAMS)
4160
except subprocess.CalledProcessError as e:
4261
print(ERROR_MSG, e)
4362
return e.returncode
@@ -46,26 +65,87 @@ def initialize_git() -> int:
4665

4766

4867
def setup_environment() -> int:
68+
return_code = 0
69+
try:
70+
# Always create a new environment in the project dir
71+
python_venv_path = _create_new_environment()
72+
system_type, python_executable_path, python_activate_script_path = _get_python_paths(venv_path=python_venv_path)
73+
_activate_environment(system_type, python_activate_script_path)
74+
except Exception:
75+
return_code = -1
76+
return_code = _install_requirements(python_executable_path)
77+
return 0 or return_code
4978

50-
COMMANDS_AND_MESSAGE = {
51-
"install_poetry": (
52-
shlex.split("poetry install"),
53-
f"\n{PRETTY_LINES}\nInstalling poetry virtual environment",
54-
),
55-
"install_pre_commit": (
56-
shlex.split(
57-
"poetry run pre-commit install --hook-type pre-commit --hook-type pre-push"
58-
),
59-
f"\n{PRETTY_LINES}\nInstalling pre-commit hooks",
60-
),
61-
}
62-
for cmds, message in COMMANDS_AND_MESSAGE.values():
63-
print(message)
64-
try:
65-
subprocess.run(cmds, check=True)
66-
except subprocess.CalledProcessError as e:
67-
print(ERROR_MSG, e)
68-
return e.returncode
79+
80+
def _create_new_environment() -> str:
81+
parent_dir = pathlib.Path(os.getcwd()).parent.resolve()
82+
project_name = PROJECT_NAME.strip()
83+
python_venv_path = str(parent_dir / project_name / VENV_NAME)
84+
85+
print(PRETTY_LINES)
86+
print(f"Attempting to create a new virtual env at {python_venv_path}")
87+
try:
88+
venv.create(env_dir=python_venv_path, with_pip=True)
89+
except Exception:
90+
print("An unexpected error has occured")
91+
raise
92+
93+
print(f"Successfully created virtualenv at: {python_venv_path!r}")
94+
return python_venv_path
95+
96+
97+
def _get_python_paths(venv_path: str) -> tuple[str, str, str]:
98+
sys_type = sys.platform
99+
if sys_type == "win32":
100+
python_executable_path = pathlib.Path(venv_path, "Scripts", "python.exe")
101+
activate_script_path = pathlib.Path(venv_path, "Scripts", "activate")
102+
elif sys_type in ("darwin", "linux", "linux2"):
103+
python_executable_path = pathlib.Path(venv_path, "bin", "python")
104+
activate_script_path = pathlib.Path(venv_path, "bin", "activate")
105+
else:
106+
raise OSError(f"Unsupported platform: {sys_type!r}")
107+
return sys_type, str(python_executable_path), str(activate_script_path)
108+
109+
110+
def _activate_environment(system_type: str, activate_script_path: str) -> None:
111+
if system_type == "win32":
112+
subprocess.call(["cmd.exe", "c", activate_script_path])
113+
elif system_type in ("darwin", "linux", "linux2"):
114+
subprocess.call(f"source {activate_script_path}", shell=True)
115+
116+
print("Successfully activated virtualenv.")
117+
print(f"\n{PRETTY_LINES}")
118+
119+
120+
def _install_requirements(python_executable_path: str) -> int:
121+
print("Installing all dependencies from the requirements.txt file.\n")
122+
try:
123+
subprocess.run(
124+
[python_executable_path, "-m", "pip", "install", "-r", "requirements.txt"],
125+
**SUBPROCESS_PARAMS,
126+
)
127+
if "{{ cookiecutter.project_slug }}":
128+
subprocess.run(
129+
[python_executable_path, "-m", "pip", "install", "-r", "dev-requirements.txt"],
130+
**SUBPROCESS_PARAMS,
131+
)
132+
except subprocess.CalledProcessError as e:
133+
print(ERROR_MSG, e)
134+
return e.returncode
135+
136+
print(PRETTY_LINES)
137+
return 0
138+
139+
140+
def _rename_pyproject_toml_file() -> int:
141+
try:
142+
os.rename(
143+
"template-pyproject.toml",
144+
"pyproject.toml",
145+
)
146+
except subprocess.CalledProcessError as e:
147+
print(ERROR_MSG, e)
148+
return e.returncode
69149

70150
return 0
71151

0 commit comments

Comments
 (0)