This commit is contained in:
nose
2025-12-20 23:57:44 -08:00
parent b75faa49a2
commit 8ca5783970
39 changed files with 4294 additions and 1722 deletions

View File

@@ -5,6 +5,8 @@ import inspect
import threading
from pathlib import Path
from rich_display import console_for
_DEBUG_ENABLED = False
_thread_local = threading.local()
@@ -56,6 +58,80 @@ def debug(*args, **kwargs) -> None:
# Use the same logic as log()
log(*args, **kwargs)
def debug_inspect(
obj,
*,
title: str | None = None,
file=None,
methods: bool = False,
docs: bool = False,
private: bool = False,
dunder: bool = False,
sort: bool = True,
all: bool = False,
value: bool = True,
) -> None:
"""Rich-inspect an object when debug logging is enabled.
Uses the same stream / quiet-mode behavior as `debug()` and prepends a
`[file.function]` prefix when debug is enabled.
"""
if not _DEBUG_ENABLED:
return
# Mirror debug() quiet-mode guard.
try:
stderr_name = getattr(sys.stderr, "name", "")
if "nul" in str(stderr_name).lower() or "/dev/null" in str(stderr_name):
return
except Exception:
pass
# Resolve destination stream.
stream = get_thread_stream()
if stream is not None:
file = stream
elif file is None:
file = sys.stderr
# Compute caller prefix (same as log()).
prefix = None
frame = inspect.currentframe()
if frame is not None and frame.f_back is not None:
caller_frame = frame.f_back
try:
file_name = Path(caller_frame.f_code.co_filename).stem
func_name = caller_frame.f_code.co_name
prefix = f"[{file_name}.{func_name}]"
finally:
del caller_frame
if frame is not None:
del frame
# Render.
from rich import inspect as rich_inspect
console = console_for(file)
# If the caller provides a title, treat it as authoritative.
# Only fall back to the automatic [file.func] prefix when no title is supplied.
effective_title = title
if not effective_title and prefix:
effective_title = prefix
rich_inspect(
obj,
console=console,
title=effective_title,
methods=methods,
docs=docs,
private=private,
dunder=dunder,
sort=sort,
all=all,
value=value,
)
def log(*args, **kwargs) -> None:
"""Print with automatic file.function prefix.
@@ -71,12 +147,18 @@ def log(*args, **kwargs) -> None:
# Get the calling frame
frame = inspect.currentframe()
if frame is None:
print(*args, **kwargs)
file = kwargs.pop("file", sys.stdout)
sep = kwargs.pop("sep", " ")
end = kwargs.pop("end", "\n")
console_for(file).print(*args, sep=sep, end=end)
return
caller_frame = frame.f_back
if caller_frame is None:
print(*args, **kwargs)
file = kwargs.pop("file", sys.stdout)
sep = kwargs.pop("sep", " ")
end = kwargs.pop("end", "\n")
console_for(file).print(*args, sep=sep, end=end)
return
try:
@@ -93,12 +175,15 @@ def log(*args, **kwargs) -> None:
# Set default to stdout if not specified
elif 'file' not in kwargs:
kwargs['file'] = sys.stdout
file = kwargs.pop("file", sys.stdout)
sep = kwargs.pop("sep", " ")
end = kwargs.pop("end", "\n")
if add_prefix:
prefix = f"[{file_name}.{func_name}]"
print(prefix, *args, **kwargs)
console_for(file).print(prefix, *args, sep=sep, end=end)
else:
print(*args, **kwargs)
console_for(file).print(*args, sep=sep, end=end)
finally:
del frame
del caller_frame