|
1 | 1 | # Copyright (c) Microsoft Corporation. All rights reserved. |
2 | 2 | # Licensed under the MIT License. |
3 | 3 |
|
| 4 | +import importlib.util |
4 | 5 | import os |
5 | 6 | import pathlib |
6 | 7 | import subprocess |
7 | 8 | import sys |
8 | | -from typing import List |
| 9 | +from contextlib import contextmanager, suppress |
| 10 | +from typing import Generator, List |
9 | 11 |
|
10 | 12 | script_dir = pathlib.Path(__file__).parent |
11 | 13 | sys.path.append(os.fspath(script_dir)) |
|
16 | 18 | ) |
17 | 19 |
|
18 | 20 |
|
| 21 | +@contextmanager |
| 22 | +def override_argv(argv: List[str]) -> Generator: |
| 23 | + """Context manager to temporarily override sys.argv with the provided arguments.""" |
| 24 | + original_argv = sys.argv |
| 25 | + sys.argv = argv |
| 26 | + try: |
| 27 | + yield |
| 28 | + finally: |
| 29 | + sys.argv = original_argv |
| 30 | + |
| 31 | + |
19 | 32 | def django_discovery_runner(manage_py_path: str, args: List[str]) -> None: |
20 | 33 | # Attempt a small amount of validation on the manage.py path. |
21 | 34 | if not pathlib.Path(manage_py_path).exists(): |
@@ -72,31 +85,24 @@ def django_execution_runner(manage_py_path: str, test_ids: List[str], args: List |
72 | 85 | else: |
73 | 86 | env["PYTHONPATH"] = os.fspath(custom_test_runner_dir) |
74 | 87 |
|
75 | | - # Build command to run 'python manage.py test'. |
76 | | - command: List[str] = [ |
77 | | - sys.executable, |
| 88 | + django_project_dir: pathlib.Path = pathlib.Path(manage_py_path).parent |
| 89 | + sys.path.insert(0, os.fspath(django_project_dir)) |
| 90 | + print(f"Django project directory: {django_project_dir}") |
| 91 | + |
| 92 | + manage_spec = importlib.util.spec_from_file_location("manage", manage_py_path) |
| 93 | + manage_module = importlib.util.module_from_spec(manage_spec) |
| 94 | + manage_spec.loader.exec_module(manage_module) |
| 95 | + |
| 96 | + manage_argv: List[str] = [ |
78 | 97 | manage_py_path, |
79 | 98 | "test", |
80 | 99 | "--testrunner=django_test_runner.CustomExecutionTestRunner", |
| 100 | + *args, |
| 101 | + *test_ids, |
81 | 102 | ] |
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) |
| 103 | + print(f"Django manage.py arguments: {manage_argv}") |
| 104 | + |
| 105 | + with override_argv(manage_argv), suppress(SystemExit): |
| 106 | + manage_module.main() |
101 | 107 | except Exception as e: |
102 | 108 | print(f"Error during Django test execution: {e}", file=sys.stderr) |
0 commit comments