Suppress stdout/stderr writes that originate from package.
Replaces sys.stdout and sys.stderr with a proxy that walks the call stack
on every write; output whose innermost package-level frame matches
package is dropped, everything else passes through unchanged.
More reliable than patching builtins.print because it also catches tqdm
progress bars and any code that calls sys.stdout.write() directly.
Source code in src/spyglass/position/utils_dlc.py
| @contextlib.contextmanager
def suppress_print_from_package(package: str = "deeplabcut"):
"""Suppress stdout/stderr writes that originate from *package*.
Replaces sys.stdout and sys.stderr with a proxy that walks the call stack
on every write; output whose innermost package-level frame matches
``package`` is dropped, everything else passes through unchanged.
More reliable than patching builtins.print because it also catches tqdm
progress bars and any code that calls sys.stdout.write() directly.
"""
class _PackageFilter:
"""Proxy stream: suppress writes from *package*, pass others through."""
def __init__(self, stream: object) -> None:
self._stream = stream
def write(self, text: str) -> int:
for frame_info in inspect.stack():
# Real FrameInfo objects store the frame in .frame;
# test mocks may expose f_globals directly on the object.
fg = getattr(frame_info, "f_globals", None)
if fg is None:
raw = getattr(frame_info, "frame", None)
fg = getattr(raw, "f_globals", {}) if raw else {}
if fg.get("__name__", "").startswith(package):
return len(text) # drop — came from target package
return self._stream.write(text)
def flush(self) -> None:
return self._stream.flush()
def __getattr__(self, name: str):
return getattr(self._stream, name)
old_stdout, old_stderr = sys.stdout, sys.stderr
sys.stdout = _PackageFilter(old_stdout)
sys.stderr = _PackageFilter(old_stderr)
try:
yield
finally:
sys.stdout = old_stdout
sys.stderr = old_stderr
|