11#!/usr/bin/env python
2- # -*- coding: utf-8 -*-
32
43"""
54Helper functions
65"""
6+
77import contextlib
88import logging
99import os
1010import sys
1111from pathlib import Path
12+ from typing import TextIO
13+
1214import requests
1315from tqdm import tqdm
14- from pywhispercpp .constants import MODELS_BASE_URL , MODELS_PREFIX_URL , AVAILABLE_MODELS , MODELS_DIR
1516
17+ from pywhispercpp .constants import (
18+ AVAILABLE_MODELS ,
19+ MODELS_BASE_URL ,
20+ MODELS_DIR ,
21+ MODELS_PREFIX_URL ,
22+ )
1623
1724logger = logging .getLogger (__name__ )
1825
@@ -185,7 +192,7 @@ def output_csv(segments: list, output_file_path: str) -> str:
185192
186193
187194@contextlib .contextmanager
188- def redirect_stderr (to = False ) -> None :
195+ def redirect_stderr (to : bool | TextIO | str | None = False ) -> None :
189196 """
190197 Redirect stderr to the specified target.
191198
@@ -201,45 +208,45 @@ def redirect_stderr(to=False) -> None:
201208 yield
202209 return
203210
211+ def _resolve_target (target ):
212+ opened_stream = None
213+ if target is None :
214+ opened_stream = open (os .devnull , "w" )
215+ return opened_stream , True
216+ if isinstance (target , str ):
217+ opened_stream = open (target , "w" )
218+ return opened_stream , True
219+ if hasattr (target , "write" ):
220+ return target , False
221+ raise ValueError (
222+ "Invalid `to` parameter; expected None, a filepath string, or a file-like object."
223+ )
224+
204225 sys .stderr .flush ()
205226 try :
206- original_stderr_fd = sys .stderr .fileno ()
207- has_fileno = True
227+ original_fd = sys .stderr .fileno ()
208228 except (AttributeError , OSError ):
209229 # Jupyter or non-standard stderr implementations
210- has_fileno = False
211-
212- if has_fileno :
213- if to is None :
214- target_fd = os .open (os .devnull , os .O_WRONLY )
215- elif isinstance (to , str ):
216- file = open (to , 'w' )
217- target_fd = file .fileno ()
218- elif hasattr (to , 'fileno' ):
219- target_fd = to .fileno ()
220- else :
221- raise ValueError ("Invalid `to` parameter; must be None, a filepath string, or sys.stdout/sys.stderr." )
222- os .dup2 (target_fd , original_stderr_fd )
230+ original_fd = None
231+
232+ stream , should_close = _resolve_target (to )
233+
234+ if original_fd is not None and hasattr (stream , "fileno" ):
235+ saved_fd = os .dup (original_fd )
223236 try :
237+ os .dup2 (stream .fileno (), original_fd )
224238 yield
225239 finally :
226- os .dup2 (original_stderr_fd , original_stderr_fd )
227- if isinstance (to , str ):
228- file .close ()
229- elif to is None :
230- os .close (target_fd )
231- else :
232- # Replace sys.stderr directly
233- original_stderr = sys .stderr
234- if to is None :
235- sys .stderr = open (os .devnull , 'w' )
236- elif isinstance (to , str ):
237- sys .stderr = open (to , 'w' )
238- elif hasattr (to , 'write' ):
239- sys .stderr = to
240- try :
240+ os .dup2 (saved_fd , original_fd )
241+ os .close (saved_fd )
242+ if should_close :
243+ stream .close ()
244+ return
245+
246+ # Fallback: Python-level redirect
247+ try :
248+ with contextlib .redirect_stderr (stream ):
241249 yield
242- finally :
243- sys .stderr = original_stderr
244- if isinstance (to , str ) or to is None :
245- sys .stderr .close ()
250+ finally :
251+ if should_close :
252+ stream .close ()
0 commit comments