11# --------------------------------------------------------------------------
2- # The Module inspect FastAPI template is appropriate
3- #
4- # This module will be read by Github Action when contributor
2+ # The Module defines FastAPI template inspector for template validation.
3+ # This module will be used by maintainers of FastAPI-fastkit when anyone
54# makes a PR of adding new FastAPI template.
65#
76# First, check a FastAPI template is formed a valid template form with .py-tpl extension
3332 install_dependencies ,
3433)
3534from fastapi_fastkit .backend .transducer import copy_and_convert_template
35+ from fastapi_fastkit .core .settings import settings
36+ from fastapi_fastkit .utils .logging import get_logger
3637from fastapi_fastkit .utils .main import print_error , print_success , print_warning
3738
3839
@@ -50,7 +51,14 @@ def __init__(self, template_path: str):
5051 def __del__ (self ) -> None :
5152 """Cleanup temp directory when inspector is destroyed."""
5253 if os .path .exists (self .temp_dir ):
53- shutil .rmtree (self .temp_dir )
54+ try :
55+ shutil .rmtree (self .temp_dir )
56+ except OSError as e :
57+ if settings .DEBUG_MODE :
58+ logger = get_logger (__name__ )
59+ logger .warning (
60+ f"Failed to cleanup temp directory { self .temp_dir } : { e } "
61+ )
5462
5563 def inspect_template (self ) -> bool :
5664 """Inspect the template is valid FastAPI application."""
@@ -102,29 +110,37 @@ def _check_dependencies(self) -> bool:
102110 self .errors .append ("setup.py-tpl not found" )
103111 return False
104112
105- with open (req_path ) as f :
106- deps = f .read ().splitlines ()
107- package_names = [dep .split ("==" )[0 ] for dep in deps if dep ]
108- if "fastapi" not in package_names :
109- self .errors .append (
110- "FastAPI dependency not found in requirements.txt-tpl"
111- )
112- return False
113+ try :
114+ with open (req_path , encoding = "utf-8" ) as f :
115+ deps = f .read ().splitlines ()
116+ package_names = [dep .split ("==" )[0 ] for dep in deps if dep ]
117+ if "fastapi" not in package_names :
118+ self .errors .append (
119+ "FastAPI dependency not found in requirements.txt-tpl"
120+ )
121+ return False
122+ except (OSError , UnicodeDecodeError ) as e :
123+ self .errors .append (f"Error reading requirements.txt-tpl: { e } " )
124+ return False
113125 return True
114126
115127 def _check_fastapi_implementation (self ) -> bool :
116128 """Check if the template has a proper FastAPI server implementation."""
117- core_modules = find_template_core_modules (self .temp_dir )
118-
119- if not core_modules ["main" ]:
120- self .errors .append ("main.py not found in template" )
121- return False
129+ try :
130+ core_modules = find_template_core_modules (self .temp_dir )
122131
123- with open (core_modules ["main" ]) as f :
124- content = f .read ()
125- if "FastAPI" not in content or "app" not in content :
126- self .errors .append ("FastAPI app creation not found in main.py" )
132+ if not core_modules ["main" ]:
133+ self .errors .append ("main.py not found in template" )
127134 return False
135+
136+ with open (core_modules ["main" ], encoding = "utf-8" ) as f :
137+ content = f .read ()
138+ if "FastAPI" not in content or "app" not in content :
139+ self .errors .append ("FastAPI app creation not found in main.py" )
140+ return False
141+ except (OSError , UnicodeDecodeError ) as e :
142+ self .errors .append (f"Error checking FastAPI implementation: { e } " )
143+ return False
128144 return True
129145
130146 def _test_template (self ) -> bool :
@@ -152,13 +168,17 @@ def _test_template(self) -> bool:
152168 capture_output = True ,
153169 text = True ,
154170 cwd = self .temp_dir ,
171+ timeout = 300 , # 5 minute timeout
155172 )
156173
157174 if result .returncode != 0 :
158175 self .errors .append (f"Tests failed: { result .stderr } " )
159176 return False
160177
161- except Exception as e :
178+ except subprocess .TimeoutExpired :
179+ self .errors .append ("Tests timed out after 5 minutes" )
180+ return False
181+ except (OSError , subprocess .SubprocessError ) as e :
162182 self .errors .append (f"Error running tests: { e } " )
163183 return False
164184
@@ -169,7 +189,7 @@ def inspect_template(template_path: str) -> Dict[str, Any]:
169189 """Run the template inspection and return the result."""
170190 inspector = TemplateInspector (template_path )
171191 is_valid = inspector .inspect_template ()
172- result : dict [str , Any ] = {
192+ result : Dict [str , Any ] = {
173193 "valid" : is_valid ,
174194 "errors" : inspector .errors ,
175195 "warnings" : inspector .warnings ,
@@ -196,7 +216,7 @@ def inspect_template(template_path: str) -> Dict[str, Any]:
196216
197217if __name__ == "__main__" :
198218 if len (sys .argv ) != 2 :
199- print ("Usage: python inspector.py <template_dir>" )
219+ print_error ("Usage: python inspector.py <template_dir>" )
200220 sys .exit (1 )
201221
202222 template_dir = sys .argv [1 ]
0 commit comments