55import pathlib
66import subprocess
77import sys
8- from typing import List
8+ from contextlib import contextmanager , suppress
9+ from typing import Generator , List
910
1011script_dir = pathlib .Path (__file__ ).parent
1112sys .path .append (os .fspath (script_dir ))
1617)
1718
1819
20+ @contextmanager
21+ def override_argv (argv : List [str ]) -> Generator :
22+ """Context manager to temporarily override sys.argv with the provided arguments."""
23+ original_argv = sys .argv
24+ sys .argv = argv
25+ try :
26+ yield
27+ finally :
28+ sys .argv = original_argv
29+
30+
1931def django_discovery_runner (manage_py_path : str , args : List [str ]) -> None :
2032 # Attempt a small amount of validation on the manage.py path.
2133 if not pathlib .Path (manage_py_path ).exists ():
@@ -58,8 +70,9 @@ def django_discovery_runner(manage_py_path: str, args: List[str]) -> None:
5870
5971
6072def django_execution_runner (manage_py_path : str , test_ids : List [str ], args : List [str ]) -> None :
73+ manage_path : pathlib .Path = pathlib .Path (manage_py_path )
6174 # Attempt a small amount of validation on the manage.py path.
62- if not pathlib . Path ( manage_py_path ) .exists ():
75+ if not manage_path .exists ():
6376 raise VSCodeUnittestError ("Error running Django, manage.py path does not exist." )
6477
6578 try :
@@ -72,31 +85,27 @@ def django_execution_runner(manage_py_path: str, test_ids: List[str], args: List
7285 else :
7386 env ["PYTHONPATH" ] = os .fspath (custom_test_runner_dir )
7487
75- # Build command to run 'python manage.py test'.
76- command : List [str ] = [
77- sys .executable ,
78- manage_py_path ,
88+ django_project_dir : pathlib .Path = manage_path .parent
89+ sys .path .insert (0 , os .fspath (django_project_dir ))
90+ print (f"Django project directory: { django_project_dir } " )
91+
92+ manage_argv : List [str ] = [
93+ str (manage_path ),
7994 "test" ,
8095 "--testrunner=django_test_runner.CustomExecutionTestRunner" ,
96+ * args ,
97+ * test_ids ,
8198 ]
82- # Add any additional arguments to the command provided by the user.
83- command .extend (args )
84- # Add the test_ids to the command.
85- print ("Test IDs: " , test_ids )
86- print ("args: " , args )
87- command .extend (test_ids )
88- print ("Running Django run tests with command: " , command )
89- subprocess_execution = subprocess .run (
90- command ,
91- capture_output = True ,
92- text = True ,
93- env = env ,
94- )
95- print (subprocess_execution .stderr , file = sys .stderr )
96- print (subprocess_execution .stdout , file = sys .stdout )
97- # Zero return code indicates success, 1 indicates test failures, so both are considered successful.
98- if subprocess_execution .returncode not in (0 , 1 ):
99- error_msg = "Django test execution process exited with non-zero error code See stderr above for more details."
100- print (error_msg , file = sys .stderr )
99+ print (f"Django manage.py arguments: { manage_argv } " )
100+
101+ try :
102+ argv_context = override_argv (manage_argv )
103+ suppress_context = suppress (SystemExit )
104+ manage_file = manage_path .open ()
105+ with argv_context , suppress_context , manage_file :
106+ manage_code = manage_file .read ()
107+ exec (manage_code , {"__name__" : "__main__" })
108+ except OSError as e :
109+ raise VSCodeUnittestError ("Error running Django, unable to read manage.py" ) from e
101110 except Exception as e :
102111 print (f"Error during Django test execution: { e } " , file = sys .stderr )
0 commit comments