|
24 | 24 | PY2 = sys.version_info[0] == 2
|
25 | 25 |
|
26 | 26 |
|
27 |
| -def run_before_script( |
| 27 | +def run_before_script2( |
28 | 28 | script_file: str | pathlib.Path,
|
29 | 29 | cwd: pathlib.Path | None = None,
|
30 | 30 | ) -> int:
|
@@ -96,6 +96,73 @@ def run_before_script(
|
96 | 96 | return return_code
|
97 | 97 |
|
98 | 98 |
|
| 99 | +def run_before_script( |
| 100 | + script_file: str | pathlib.Path, |
| 101 | + cwd: pathlib.Path | None = None, |
| 102 | +) -> int: |
| 103 | + script_cmd = shlex.split(str(script_file)) |
| 104 | + |
| 105 | + try: |
| 106 | + proc = subprocess.Popen( |
| 107 | + script_cmd, |
| 108 | + cwd=cwd, |
| 109 | + stdout=subprocess.PIPE, |
| 110 | + stderr=subprocess.PIPE, |
| 111 | + text=True, # still decode to str |
| 112 | + errors="backslashreplace", |
| 113 | + bufsize=0, # unbuffered in Python, best effort |
| 114 | + ) |
| 115 | + except FileNotFoundError as e: |
| 116 | + raise exc.BeforeLoadScriptNotExists( |
| 117 | + e, |
| 118 | + os.path.abspath(script_file), # NOQA: PTH100 |
| 119 | + ) from e |
| 120 | + |
| 121 | + out_buffer = [] |
| 122 | + err_buffer = [] |
| 123 | + is_out_tty = sys.stdout.isatty() |
| 124 | + is_err_tty = sys.stderr.isatty() |
| 125 | + |
| 126 | + # We'll read in chunks from both stdout and stderr in a loop. |
| 127 | + # This example uses a single loop that tries to read both streams |
| 128 | + # repeatedly. For large outputs, consider threading or select(). |
| 129 | + |
| 130 | + while True: |
| 131 | + return_code = proc.poll() |
| 132 | + |
| 133 | + # Read some data from stdout (if available) |
| 134 | + chunk_out = proc.stdout.read(1024) if proc.stdout else "" |
| 135 | + if chunk_out: |
| 136 | + out_buffer.append(chunk_out) |
| 137 | + if is_out_tty: |
| 138 | + sys.stdout.write(chunk_out) |
| 139 | + sys.stdout.flush() |
| 140 | + |
| 141 | + # Read some data from stderr (if available) |
| 142 | + chunk_err = proc.stderr.read(1024) if proc.stderr else "" |
| 143 | + if chunk_err: |
| 144 | + err_buffer.append(chunk_err) |
| 145 | + if is_err_tty: |
| 146 | + sys.stderr.write(chunk_err) |
| 147 | + sys.stderr.flush() |
| 148 | + |
| 149 | + if return_code is not None and not chunk_out and not chunk_err: |
| 150 | + # No more data from pipes, process ended |
| 151 | + break |
| 152 | + |
| 153 | + return_code = proc.wait() |
| 154 | + |
| 155 | + if return_code != 0: |
| 156 | + stderr_str = "".join(err_buffer).strip() |
| 157 | + raise exc.BeforeLoadScriptError( |
| 158 | + return_code, |
| 159 | + os.path.abspath(script_file), # NOQA: PTH100 |
| 160 | + stderr_str, |
| 161 | + ) |
| 162 | + |
| 163 | + return return_code |
| 164 | + |
| 165 | + |
99 | 166 | def oh_my_zsh_auto_title() -> None:
|
100 | 167 | """Give warning and offer to fix ``DISABLE_AUTO_TITLE``.
|
101 | 168 |
|
|
0 commit comments