diff --git a/backend/app/modules/code/code_projects_api.py b/backend/app/modules/code/code_projects_api.py index ae8b4707..8cb130ea 100644 --- a/backend/app/modules/code/code_projects_api.py +++ b/backend/app/modules/code/code_projects_api.py @@ -1296,7 +1296,8 @@ async def get_pipeline_results( results_path = os.path.join(repo_dir, "pipeline_results.json") if os.path.exists(results_path): try: - data = json.loads(open(results_path, encoding="utf-8").read()) + with open(results_path, encoding="utf-8") as _f: + data = json.loads(_f.read()) return PipelineRunResponse(**data) except (json.JSONDecodeError, TypeError): pass @@ -1370,7 +1371,8 @@ async def auto_fix_pipeline( results_path = os.path.join(repo_dir, "pipeline_results.json") if os.path.exists(results_path): try: - prev = json.loads(open(results_path, encoding="utf-8").read()) + with open(results_path, encoding="utf-8") as _f: + prev = json.loads(_f.read()) failed_steps = [s for s in prev.get("steps", []) if s.get("status") == "failed"] except (json.JSONDecodeError, TypeError): pass diff --git a/backend/tests/test_pr_06_code_projects_files.py b/backend/tests/test_pr_06_code_projects_files.py new file mode 100644 index 00000000..bde7bacf --- /dev/null +++ b/backend/tests/test_pr_06_code_projects_files.py @@ -0,0 +1,44 @@ +"""Test that code_projects_api.py uses context managers for file reads. + +Verifies no open().read() patterns remain that would leave file handles unclosed. +""" +import re +import os + + +def test_no_unclosed_file_reads(): + """Verify no open(...).read() patterns remain in code_projects_api.py.""" + module_path = os.path.join( + os.path.dirname(__file__), + "..", + "app", + "modules", + "code", + "code_projects_api.py", + ) + with open(module_path, "r", encoding="utf-8") as f: + source = f.read() + + unclosed = re.findall(r"open\([^)]+\)\.read\(\)", source) + assert len(unclosed) == 0, ( + f"Found {len(unclosed)} unclosed file read(s) in code_projects_api.py" + ) + + +def test_results_path_uses_context_manager(): + """Verify that results_path file reads use context managers.""" + module_path = os.path.join( + os.path.dirname(__file__), + "..", + "app", + "modules", + "code", + "code_projects_api.py", + ) + with open(module_path, "r", encoding="utf-8") as f: + source = f.read() + + context_reads = len(re.findall(r"with open\(results_path", source)) + assert context_reads >= 3, ( + f"Expected at least 3 context-managed opens of results_path, found {context_reads}" + )