Skip to content

Commit

Permalink
call original showwarning, add exc count
Browse files Browse the repository at this point in the history
  • Loading branch information
isabelizimm committed Apr 19, 2024
1 parent 59989a3 commit e9d2919
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,9 @@ def connection_show(self, line: str) -> None:

_traceback_file_link_re = re.compile(r"^(File \x1b\[\d+;\d+m)(.+):(\d+)")

# keep reference to original showwarning
original_showwarning = warnings.showwarning


class PositronShell(ZMQInteractiveShell):
kernel: PositronIPyKernel
Expand Down Expand Up @@ -420,8 +423,8 @@ def __init__(self, **kwargs) -> None:
# Register display publisher hooks
self.shell.display_pub.register_hook(self.widget_hook)

warnings.showwarning = _showwarning
warnings.formatwarning = _formatwarning
warnings.showwarning = self._showwarning

# Ignore warnings that the user can't do anything about
warnings.filterwarnings(
"ignore",
Expand Down Expand Up @@ -471,6 +474,29 @@ async def do_shutdown(self, restart: bool) -> JsonRecord: # type: ignore Report
# points to the same underlying asyncio loop).
return dict(status="ok", restart=restart)

# monkey patching warning.showwarning is recommended by the official documentation
# https://docs.python.org/3/library/warnings.html#warnings.showwarning
def _showwarning(self, message, category, filename, lineno, file=None, line=None):
# if coming from one of our files, log and don't send to user
positron_files_path = Path(__file__).parent

if str(positron_files_path) in str(filename):
msg = f"{filename}-{lineno}: {category}: {message}"
logger.warning(msg)
return

# Check if the filename refers to a cell in the Positron Console.
# We use the fact that ipykernel sets the filename to a path starting in the root temporary
# directory. We can't determine the full filename since it depends on the cell's code which
# is unknown at this point. See ipykernel.compiler.XCachingCompiler.get_code_name.
console_dir = get_tmp_directory()
if console_dir in str(filename):
filename = f"<positron-console-cell-{self.execution_count}>"

msg = warnings.WarningMessage(message, category, filename, lineno, file, line)

return original_showwarning(message, category, filename, lineno, file, line) # type: ignore reportAttributeAccessIssue


class PositronIPKernelApp(IPKernelApp):
kernel: PositronIPyKernel
Expand Down Expand Up @@ -526,50 +552,3 @@ def _link(uri: str, label: str, params: Dict[str, str] = {}) -> str:
Create a hyperlink with the given label, URI, and params.
"""
return _start_hyperlink(uri, params) + label + _end_hyperlink()


# monkey patching warning.showwarning is recommended by the official documentation
# https://docs.python.org/3/library/warnings.html#warnings.showwarning
def _showwarning(message, category, filename, lineno, file=None, line=None):
# if coming from one of our files, log and don't send to user
positron_files_path = Path("python_files", "positron", "positron_ipykernel")

if str(positron_files_path) in str(filename):
msg = f"{category}: {message}"
logger.warning(msg)
return

# Check if the filename refers to a cell in the Positron Console.
# We use the fact that ipykernel sets the filename to a path starting in the root temporary
# directory. We can't determine the full filename since it depends on the cell's code which
# is unknown at this point. See ipykernel.compiler.XCachingCompiler.get_code_name.
console_dir = get_tmp_directory()
if console_dir in str(filename):
filename = "POSITRON_CONSOLE"

msg = warnings.WarningMessage(message, category, filename, lineno, file, line)

return warnings._showwarnmsg_impl(msg) # type: ignore reportAttributeAccessIssue


# vendored as-is from warnings
def _formatwarning(message, category, filename, lineno, line=None):
# --- Start Positron ---
if filename == "POSITRON_CONSOLE":
s = f"{category.__name__}: {message}\n"
# --- End Positron ---
else:
s = "%s:%s: %s: %s\n" % (filename, lineno, category.__name__, message)
if line is None:
try:
import linecache

line = linecache.getline(filename, lineno)
except Exception:
# When a warning is logged during Python shutdown, linecache
# and the import machinery don't work anymore
line = None
if line:
line = line.strip()
s += " %s\n" % line
return s
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
from IPython.utils.syspathcontext import prepended_to_syspath
from ipykernel.compiler import get_tmp_directory

from positron_ipykernel.positron_ipkernel import _showwarning
from positron_ipykernel.help import help
from positron_ipykernel.session_mode import SessionMode
from positron_ipykernel.utils import alias_home
Expand Down Expand Up @@ -328,18 +327,18 @@ def test_console_warning(shell: PositronShell, warning_kwargs):
filename = get_tmp_directory() + os.sep + "12345678.py"

with pytest.warns() as record:
_showwarning(filename=filename, **warning_kwargs)
shell.kernel._showwarning(filename=filename, **warning_kwargs)

assert len(record) == 1
assert record[0].filename == "POSITRON_CONSOLE"
assert record[0].filename == "<positron-console-cell-1>"
assert record[0].message == "this is a warning"


def test_console_warning_logger(caplog, warning_kwargs):
def test_console_warning_logger(shell: PositronShell, caplog, warning_kwargs):
"""
Check that Positron files are sent to logs
"""

with caplog.at_level(logging.WARNING):
_showwarning(filename=Path(__file__), **warning_kwargs)
shell.kernel._showwarning(filename=Path(__file__), **warning_kwargs)
assert "this is a warning" in caplog.text

0 comments on commit e9d2919

Please sign in to comment.