1+ """Post-generation project setup and cleanup script.
2+
3+ This script runs after cookiecutter generates the project template.
4+ It removes unnecessary files based on user choices and initializes the project.
5+ """
6+
17import os
28import shutil
39import subprocess
10+ import sys
11+ from pathlib import Path
12+ from typing import List , Union
13+
14+
15+ class ProjectCleaner :
16+ """Handles removal of unnecessary files and directories based on cookiecutter choices."""
17+
18+ def __init__ (self ):
19+ self .project_slug = "{{cookiecutter.project_slug}}"
20+ self .use_cli = "{{cookiecutter.include_cli}}" == "yes"
21+ self .use_github_actions = "{{cookiecutter.use_github_actions}}" == "yes"
22+ self .use_podman = "{{cookiecutter.use_podman}}" == "yes"
23+
24+ def _safe_remove (self , path : Union [str , Path ]) -> bool :
25+ """Safely remove a file or directory.
26+
27+ Args:
28+ path: Path to remove
29+
30+ Returns:
31+ bool: True if removed successfully, False otherwise
32+ """
33+ try :
34+ path = Path (path )
35+ if not path .exists ():
36+ return False
37+
38+ if path .is_file ():
39+ path .unlink ()
40+ print (f"Removed file: { path } " )
41+ elif path .is_dir ():
42+ shutil .rmtree (path )
43+ print (f"Removed directory: { path } " )
44+ return True
45+ except Exception as e :
46+ print (f"Warning: Failed to remove { path } : { e } " )
47+ return False
48+
49+ def _remove_files (self , files : List [Union [str , Path ]]) -> None :
50+ """Remove multiple files or directories.
51+
52+ Args:
53+ files: List of file/directory paths to remove
54+ """
55+ for file_path in files :
56+ self ._safe_remove (file_path )
57+
58+ def clean_cli_files (self ) -> None :
59+ """Remove CLI related files if CLI is not needed."""
60+ if self .use_cli :
61+ return
62+
63+ cli_files = [
64+ Path (self .project_slug ) / "cli.py"
65+ ]
66+ print ("Removing CLI files..." )
67+ self ._remove_files (cli_files )
68+
69+ def clean_container_files (self ) -> None :
70+ """Remove container related files if Podman is not used."""
71+ if self .use_podman :
72+ return
73+
74+ container_files = [
75+ ".dockerignore" ,
76+ "container" ,
77+ Path (".github" ) / "workflows" / "container-release.yaml"
78+ ]
79+ print ("Removing container files..." )
80+ self ._remove_files (container_files )
81+
82+ def clean_github_actions_files (self ) -> None :
83+ """Remove GitHub Actions and documentation files if not needed."""
84+ if self .use_github_actions :
85+ return
86+
87+ github_files = [
88+ ".github" ,
89+ "mkdocs.yml" ,
90+ "docs"
91+ ]
92+ print ("Removing GitHub Actions and documentation files..." )
93+ self ._remove_files (github_files )
94+
95+
96+ class ProjectInitializer :
97+ """Handles project initialization tasks."""
98+
99+ def __init__ (self ):
100+ self .project_slug = "{{cookiecutter.project_slug}}"
101+
102+ def setup_environment (self ) -> None :
103+ """Initialize project dependencies and environment."""
104+ project_dir = Path (self .project_slug ).resolve ()
105+
106+ if not project_dir .exists ():
107+ print (f"Error: Project directory { project_dir } does not exist" )
108+ sys .exit (1 )
109+
110+ print (f"Changing to project directory: { project_dir } " )
111+ os .chdir (project_dir )
112+
113+ try :
114+ print ("Installing project dependencies..." )
115+ subprocess .run (["task" , "init" ], check = True )
116+ print ("✅ Dependencies installed successfully" )
117+ except subprocess .CalledProcessError as e :
118+ print (f"❌ Failed to install dependencies: { e } " )
119+ sys .exit (1 )
120+ except FileNotFoundError :
121+ print ("❌ uv not found. Please install uv first: https://docs.astral.sh/uv/" )
122+ sys .exit (1 )
123+
124+
125+ def main () -> None :
126+ """Main execution function."""
127+ print ("🚀 Starting post-generation project setup..." )
128+
129+ # Initialize cleaner and perform cleanup
130+ cleaner = ProjectCleaner ()
131+
132+ print ("\n 📁 Cleaning up unnecessary files..." )
133+ cleaner .clean_cli_files ()
134+ cleaner .clean_container_files ()
135+ cleaner .clean_github_actions_files ()
4136
137+ # Initialize project
138+ print ("\n 🔧 Initializing project..." )
139+ initializer = ProjectInitializer ()
140+ initializer .setup_environment ()
5141
6- def remove_cli ():
7- """Remove CLI related files if not needed."""
8- cli_file = os .path .join ("{{cookiecutter.project_slug}}" , "cli.py" )
9- if os .path .exists (cli_file ):
10- os .remove (cli_file )
11-
12- def remove_docker ():
13- """Remove GitHub Actions configuration if not needed."""
14- file_name = [".dockerignore" , "docker" , ".github/workflows/docker_release.yaml" ]
15- if "{{cookiecutter.use_github_actions}}" == "no" :
16- for item in file_name :
17- if os .path .exists (item ):
18- if os .path .isfile (item ):
19- os .remove (item )
20- elif os .path .isdir (item ):
21- shutil .rmtree (item )
22-
23-
24- def remove_github_actions ():
25- """Remove GitHub Actions configuration if not needed."""
26- if "{{cookiecutter.use_github_actions}}" == "no" :
27- github_dir = os .path .join (".github" )
28- if os .path .exists (github_dir ):
29- shutil .rmtree (github_dir )
30-
31-
32- def remove_docs ():
33- """Remove documentation related files if GitHub Actions is not used."""
34- if "{{cookiecutter.use_github_actions}}" == "no" :
35- # 删除 mkdocs.yml
36- if os .path .exists ("mkdocs.yml" ):
37- os .remove ("mkdocs.yml" )
38- # 删除 docs 目录
39- docs_dir = "docs"
40- if os .path .exists (docs_dir ):
41- shutil .rmtree (docs_dir )
42-
43-
44- def init_project_depends ():
45- """Initialize project dependencies using uv."""
46- project_dir = os .path .abspath ("{{cookiecutter.project_slug}}" )
47- os .chdir (project_dir )
48-
49- # 安装基础开发依赖
50- subprocess .run (["uv" , "sync" ], check = True )
142+ print ("\n ✨ Project setup completed successfully!" )
143+ print (f"📂 Your project is ready at: {{cookiecutter.project_slug}}" )
51144
52145
53146if __name__ == "__main__" :
54- if "{{cookiecutter.include_cli}}" == "no" :
55- remove_cli ()
56-
57- if "{{cookiecutter.use_github_actions}}" == "no" :
58- remove_github_actions ()
59- remove_docs ()
60-
61- if "{{cookiecutter.use_docker}}" == "no" :
62- remove_docker ()
63-
64- init_project_depends ()
147+ main ()
0 commit comments