Module meerschaum.utils.warnings
Handle all things warnings and errors here
Expand source code
#! /usr/bin/env python
# -*- coding: utf-8 -*-
# vim:fenc=utf-8
"""
Handle all things warnings and errors here
"""
from __future__ import annotations
from meerschaum.utils.typing import Any, Union
import sys
import warnings
warnings.filterwarnings(
"always",
category = UserWarning
)
warnings.filterwarnings(
"ignore",
category = DeprecationWarning
)
warnings.filterwarnings(
"always",
category = ImportWarning
)
warnings.filterwarnings(
"ignore",
category = RuntimeWarning
)
def enable_depreciation_warnings(name) -> None:
"""Enable depreciation warnings in the warnings module."""
import meerschaum.actions
warnings.filterwarnings(
"always",
category = DeprecationWarning,
module = name
)
def warn(*args, stacklevel=2, stack=True, color: bool = True, **kw) -> None:
"""
Print a stylized warning message.
May be captured by `warnings.filterwarnings()`.
"""
if stacklevel is None:
stacklevel = 1
stack = False
_old_sw = warnings.showwarning
get_config = None
if color:
try:
from meerschaum.utils.formatting import (
CHARSET, ANSI, colored, fill_ansi, highlight_pipes, _init
)
except ImportError:
CHARSET = 'ascii'
ANSI = False
try:
from meerschaum.config import get_config as _get_config
from meerschaum.config import _config
cf = _config()
get_config = _get_config
except ImportError:
get_config = None
if get_config is None and color:
try:
warn_config = cf['formatting']['warnings']
except KeyError:
warn_config = {
'ansi' : {'color' : []},
'unicode' : {'icon' : ''},
'ascii' : {'icon' : ''},
}
elif color:
warn_config = get_config('formatting', 'warnings', patch=True)
a = list(args)
a[0] = ' ' + (warn_config[CHARSET]['icon'] if color else '') + ' ' + str(a[0])
if color:
if ANSI:
_init()
a[0] = fill_ansi(highlight_pipes(a[0]), **warn_config['ansi']['rich'])
### Optionally omit the warning location.
def _no_stack_sw(message, category, filename, lineno, file=None, line=None):
sys.stderr.write(str(message) + '\n')
if not stack:
warnings.showwarning = _no_stack_sw
warnings.warn(*a, stacklevel=stacklevel, **kw)
if not stack:
warnings.showwarning = _old_sw
def exception_with_traceback(
message: str,
exception_class = Exception,
stacklevel = 1,
tb_type = 'single'
):
"""Traceback construction help found here:
https://stackoverflow.com/questions/27138440/how-to-create-a-traceback-object
"""
import types
tb, depth = None, 0
while True:
try:
frame = sys._getframe(depth)
depth += 1
except ValueError as e:
break
tb = types.TracebackType(tb, frame, frame.f_lasti, frame.f_lineno)
tbs, _tb = [], tb
while True:
if _tb is None:
break
tbs.append(_tb)
_tb = _tb.tb_next
found_main, main_i = False, 0
first_mrsm_after_main = None
last_mrsm_i = None
tbs[(-1 * stacklevel)].tb_next = None
for i, _tb in enumerate([_tb for _tb in tbs]):
if 'meerschaum' in str(_tb.tb_frame) and '__main__.py' in str(_tb.tb_frame):
found_main = True
main_i = i
continue
if i >= (len(tbs) - (stacklevel - 1)):
tbs[i] = None
elif (
found_main and 'meerschaum' in str(_tb.tb_frame)
and first_mrsm_after_main is None
and 'Shell' not in str(_tb.tb_frame)
):
first_mrsm_after_main = i
elif 'meerschaum' in str(_tb.tb_frame):
last_mrsm_i = i
tbs = [_tb for _tb in tbs if tb is not None]
if tb_type == 'single':
return exception_class(message).with_traceback(tbs[-3])
return exception_class(message).with_traceback(tbs[first_mrsm_after_main])
def error(
message: str,
exception_class = Exception,
nopretty: bool = False,
silent: bool = True,
stack: bool = True,
raise_: bool = True,
):
"""
Raise an exception with supressed traceback.
"""
from meerschaum.utils.formatting import (
CHARSET, ANSI, get_console, fill_ansi, highlight_pipes, _init
)
from meerschaum.utils.packages import import_rich, attempt_import
from meerschaum.config import get_config
import types, inspect
rich = import_rich()
rich_traceback = attempt_import('rich.traceback')
error_config = get_config('formatting', 'errors', patch=True)
message = ' ' + error_config[CHARSET]['icon'] + ' ' + str(message)
exception = exception_with_traceback(message, exception_class, stacklevel=3)
color_message = str(message)
color_exception = exception_with_traceback(color_message, exception_class, stacklevel=3)
if ANSI and not nopretty:
_init()
color_message = '\n' + fill_ansi(highlight_pipes(message), **error_config['ansi']['rich'])
color_exception = exception_with_traceback(color_message, exception_class, stacklevel=3)
try:
trace = rich_traceback.Traceback.extract(
exception_class, exception, exception.__traceback__
)
rtb = rich_traceback.Traceback(trace)
except Exception as e:
trace, rtb = None, None
if trace is None or rtb is None:
nopretty = True
if not nopretty and stack:
if get_console() is not None:
get_console().print(rtb)
frame = sys._getframe(len(inspect.stack()) - 1)
if raise_:
raise color_exception
def info(message: str, icon: bool = True, **kw):
"""Print an informative message."""
from meerschaum.utils.packages import import_rich, attempt_import
from meerschaum.utils.formatting import (
CHARSET, ANSI, highlight_pipes, fill_ansi, _init
)
from meerschaum.config import get_config
info_config = get_config('formatting', 'info', patch=True)
if icon:
message = ' ' + info_config[CHARSET]['icon'] + ' ' + message
if ANSI:
_init()
message = highlight_pipes(message)
lines = message.split('\n')
message = fill_ansi(lines[0], **info_config['ansi']['rich']) + (
'\n' + '\n'.join(lines[1:]) if len(lines) > 1 else ''
)
print(message)
Functions
def enable_depreciation_warnings(name) ‑> None
-
Enable depreciation warnings in the warnings module.
Expand source code
def enable_depreciation_warnings(name) -> None: """Enable depreciation warnings in the warnings module.""" import meerschaum.actions warnings.filterwarnings( "always", category = DeprecationWarning, module = name )
def error(message: str, exception_class=builtins.Exception, nopretty: bool = False, silent: bool = True, stack: bool = True, raise_: bool = True)
-
Raise an exception with supressed traceback.
Expand source code
def error( message: str, exception_class = Exception, nopretty: bool = False, silent: bool = True, stack: bool = True, raise_: bool = True, ): """ Raise an exception with supressed traceback. """ from meerschaum.utils.formatting import ( CHARSET, ANSI, get_console, fill_ansi, highlight_pipes, _init ) from meerschaum.utils.packages import import_rich, attempt_import from meerschaum.config import get_config import types, inspect rich = import_rich() rich_traceback = attempt_import('rich.traceback') error_config = get_config('formatting', 'errors', patch=True) message = ' ' + error_config[CHARSET]['icon'] + ' ' + str(message) exception = exception_with_traceback(message, exception_class, stacklevel=3) color_message = str(message) color_exception = exception_with_traceback(color_message, exception_class, stacklevel=3) if ANSI and not nopretty: _init() color_message = '\n' + fill_ansi(highlight_pipes(message), **error_config['ansi']['rich']) color_exception = exception_with_traceback(color_message, exception_class, stacklevel=3) try: trace = rich_traceback.Traceback.extract( exception_class, exception, exception.__traceback__ ) rtb = rich_traceback.Traceback(trace) except Exception as e: trace, rtb = None, None if trace is None or rtb is None: nopretty = True if not nopretty and stack: if get_console() is not None: get_console().print(rtb) frame = sys._getframe(len(inspect.stack()) - 1) if raise_: raise color_exception
def exception_with_traceback(message: str, exception_class=builtins.Exception, stacklevel=1, tb_type='single')
-
Traceback construction help found here: https://stackoverflow.com/questions/27138440/how-to-create-a-traceback-object
Expand source code
def exception_with_traceback( message: str, exception_class = Exception, stacklevel = 1, tb_type = 'single' ): """Traceback construction help found here: https://stackoverflow.com/questions/27138440/how-to-create-a-traceback-object """ import types tb, depth = None, 0 while True: try: frame = sys._getframe(depth) depth += 1 except ValueError as e: break tb = types.TracebackType(tb, frame, frame.f_lasti, frame.f_lineno) tbs, _tb = [], tb while True: if _tb is None: break tbs.append(_tb) _tb = _tb.tb_next found_main, main_i = False, 0 first_mrsm_after_main = None last_mrsm_i = None tbs[(-1 * stacklevel)].tb_next = None for i, _tb in enumerate([_tb for _tb in tbs]): if 'meerschaum' in str(_tb.tb_frame) and '__main__.py' in str(_tb.tb_frame): found_main = True main_i = i continue if i >= (len(tbs) - (stacklevel - 1)): tbs[i] = None elif ( found_main and 'meerschaum' in str(_tb.tb_frame) and first_mrsm_after_main is None and 'Shell' not in str(_tb.tb_frame) ): first_mrsm_after_main = i elif 'meerschaum' in str(_tb.tb_frame): last_mrsm_i = i tbs = [_tb for _tb in tbs if tb is not None] if tb_type == 'single': return exception_class(message).with_traceback(tbs[-3]) return exception_class(message).with_traceback(tbs[first_mrsm_after_main])
def info(message: str, icon: bool = True, **kw)
-
Print an informative message.
Expand source code
def info(message: str, icon: bool = True, **kw): """Print an informative message.""" from meerschaum.utils.packages import import_rich, attempt_import from meerschaum.utils.formatting import ( CHARSET, ANSI, highlight_pipes, fill_ansi, _init ) from meerschaum.config import get_config info_config = get_config('formatting', 'info', patch=True) if icon: message = ' ' + info_config[CHARSET]['icon'] + ' ' + message if ANSI: _init() message = highlight_pipes(message) lines = message.split('\n') message = fill_ansi(lines[0], **info_config['ansi']['rich']) + ( '\n' + '\n'.join(lines[1:]) if len(lines) > 1 else '' ) print(message)
def warn(*args, stacklevel=2, stack=True, color: bool = True, **kw) ‑> None
-
Print a stylized warning message. May be captured by
warnings.filterwarnings()
.Expand source code
def warn(*args, stacklevel=2, stack=True, color: bool = True, **kw) -> None: """ Print a stylized warning message. May be captured by `warnings.filterwarnings()`. """ if stacklevel is None: stacklevel = 1 stack = False _old_sw = warnings.showwarning get_config = None if color: try: from meerschaum.utils.formatting import ( CHARSET, ANSI, colored, fill_ansi, highlight_pipes, _init ) except ImportError: CHARSET = 'ascii' ANSI = False try: from meerschaum.config import get_config as _get_config from meerschaum.config import _config cf = _config() get_config = _get_config except ImportError: get_config = None if get_config is None and color: try: warn_config = cf['formatting']['warnings'] except KeyError: warn_config = { 'ansi' : {'color' : []}, 'unicode' : {'icon' : ''}, 'ascii' : {'icon' : ''}, } elif color: warn_config = get_config('formatting', 'warnings', patch=True) a = list(args) a[0] = ' ' + (warn_config[CHARSET]['icon'] if color else '') + ' ' + str(a[0]) if color: if ANSI: _init() a[0] = fill_ansi(highlight_pipes(a[0]), **warn_config['ansi']['rich']) ### Optionally omit the warning location. def _no_stack_sw(message, category, filename, lineno, file=None, line=None): sys.stderr.write(str(message) + '\n') if not stack: warnings.showwarning = _no_stack_sw warnings.warn(*a, stacklevel=stacklevel, **kw) if not stack: warnings.showwarning = _old_sw