1- #!/usr/bin/env python
21from __future__ import annotations
32
3+ import os
4+ import pathlib
45import shlex
56import subprocess
67import sys
8+ import venv
79from pathlib import Path
810
911ERROR_MSG = "Error occured while running command"
1012PRETTY_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
1327def 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
2544def 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
4867def 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 } \n Installing 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 } \n Installing 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