def test_everything(self, cr): """ Put all cases together. """ exc = "Traceback:\nFake traceback...\nFakeError: yolo" stack = "fake stack trace" rv = cr(None, None, { "event": "test", "exception": exc, "key": "value", "foo": "bar", "timestamp": "13:13", "logger": "some_module", "level": "error", "stack": stack, }) assert ( dev.DIM + "13:13" + dev.RESET_ALL + " [" + dev.RED + dev.BRIGHT + dev._pad("error", cr._longest_level) + dev.RESET_ALL + "] " + PADDED_TEST + "[" + dev.BLUE + dev.BRIGHT + "some_module" + dev.RESET_ALL + "] " + dev.CYAN + "foo" + dev.RESET_ALL + "=" + dev.MAGENTA + "'bar'" + dev.RESET_ALL + " " + dev.CYAN + "key" + dev.RESET_ALL + "=" + dev.MAGENTA + "'value'" + dev.RESET_ALL + "\n" + stack + "\n\n" + "=" * 79 + "\n" + "\n" + exc ) == rv
def test_init_accepts_overriding_levels(self, styles, padded): """ Stdlib levels are rendered aligned, in brackets, and color coded. """ my_styles = dev.ConsoleRenderer.get_default_level_styles( colors=dev._has_colorama ) my_styles["MY_OH_MY"] = my_styles["critical"] cr = dev.ConsoleRenderer( colors=dev._has_colorama, level_styles=my_styles ) # this would blow up if the level_styles override failed rv = cr( None, None, {"event": "test", "level": "MY_OH_MY", "foo": "bar"} ) # fmt: off assert ( "[" + dev.RED + styles.bright + dev._pad("MY_OH_MY", cr._longest_level) + styles.reset + "] " + padded + styles.kv_key + "foo" + styles.reset + "=" + styles.kv_value + "bar" + styles.reset ) == rv
def test_pad_event_param(self): """ `pad_event` parameter works. """ rv = dev.ConsoleRenderer(42)(None, None, {"event": "test"}) assert (dev.BRIGHT + dev._pad("test", 42) + dev.RESET_ALL + " ") == rv
def test_everything(self, cr): """ Put all cases together. """ exc = "Traceback:\nFake traceback...\nFakeError: yolo" stack = "fake stack trace" rv = cr( None, None, { "event": "test", "exception": exc, "key": "value", "foo": "bar", "timestamp": "13:13", "logger": "some_module", "level": "error", "stack": stack, }) assert (dev.DIM + "13:13" + dev.RESET_ALL + " [" + dev.RED + dev.BRIGHT + dev._pad("error", cr._longest_level) + dev.RESET_ALL + "] " + PADDED_TEST + "[" + dev.BLUE + dev.BRIGHT + "some_module" + dev.RESET_ALL + "] " + dev.CYAN + "foo" + dev.RESET_ALL + "=" + dev.MAGENTA + "'bar'" + dev.RESET_ALL + " " + dev.CYAN + "key" + dev.RESET_ALL + "=" + dev.MAGENTA + "'value'" + dev.RESET_ALL + "\n" + stack + "\n\n" + "=" * 79 + "\n" + "\n" + exc) == rv
def test_everything(self, cr, styles, padded): """ Put all cases together. """ exc = "Traceback:\nFake traceback...\nFakeError: yolo" stack = "fake stack trace" rv = cr( None, None, { "event": "test", "exception": exc, "key": "value", "foo": "bar", "timestamp": "13:13", "logger": "some_module", "level": "error", "stack": stack, }, ) # fmt: off assert (styles.timestamp + "13:13" + styles.reset + " [" + styles.level_error + styles.bright + dev._pad("error", cr._longest_level) + styles.reset + "] " + padded + "[" + dev.BLUE + styles.bright + "some_module" + styles.reset + "] " + styles.kv_key + "foo" + styles.reset + "=" + styles.kv_value + "bar" + styles.reset + " " + styles.kv_key + "key" + styles.reset + "=" + styles.kv_value + "value" + styles.reset + "\n" + stack + "\n\n" + "=" * 79 + "\n" + "\n" + exc) == rv
def __call__(self, _, __, event_dict): from io import StringIO from structlog.dev import _pad sio = StringIO() ts = event_dict.pop('timestamp', None) if ts is not None: sio.write( # can be a number if timestamp is UNIXy self._styles.timestamp + str(ts) + self._styles.reset + ' ') level = event_dict.pop('level', None) if level is not None: sio.write('[' + self._level_to_color[level] + _pad(level, self._longest_level) + self._styles.reset + '] ') logger_name = event_dict.pop('logger', None) if logger_name is not None: sio.write('[' + self._styles.logger_name + self._styles.bright + logger_name + self._styles.reset + '] ') event = str(event_dict.pop('event')) if event_dict: event = _pad(event, self._pad_event) + self._styles.reset + ' ' else: event += self._styles.reset sio.write(self._styles.bright + event) stack = event_dict.pop('stack', None) exc = event_dict.pop('exception', None) sio.write(' '.join(self._styles.kv_key + key + self._styles.reset + '=' + self._styles.kv_value + self._repr(event_dict[key]) + self._styles.reset for key in sorted(event_dict.keys()))) if stack is not None: sio.write('\n' + stack) if exc is not None: sio.write('\n\n' + '=' * 79 + '\n') if exc is not None: sio.write('\n' + exc) return sio.getvalue()
def test_level(self, cr): """ Levels are rendered aligned, in square brackets, and color coded. """ rv = cr(None, None, {"event": "test", "level": "critical"}) assert ("[" + dev.RED + dev.BRIGHT + dev._pad("critical", cr._longest_level) + dev.RESET_ALL + "] " + PADDED_TEST) == rv
def test_pad_event_param(self): """ `pad_event` parameter works. """ rv = dev.ConsoleRenderer(42)(None, None, {"event": "test"}) assert ( dev.BRIGHT + dev._pad("test", 42) + dev.RESET_ALL + " " ) == rv
def test_level(self, cr): """ Levels are rendered aligned, in square brackets, and color coded. """ rv = cr(None, None, {"event": "test", "level": "critical"}) assert ( "[" + dev.RED + dev.BRIGHT + dev._pad("critical", cr._longest_level) + dev.RESET_ALL + "] " + PADDED_TEST ) == rv
def test_pad_event_param(self, styles): """ `pad_event` parameter works. """ rv = dev.ConsoleRenderer(42, dev._has_colorama)(None, None, { "event": "test", "foo": "bar" }) assert (styles.bright + dev._pad("test", 42) + styles.reset + " " + styles.kv_key + "foo" + styles.reset + "=" + styles.kv_value + "'bar'" + styles.reset) == rv
def test_level(self, cr, styles, padded): """ Levels are rendered aligned, in square brackets, and color coded. """ rv = cr(None, None, { "event": "test", "level": "critical", "foo": "bar" }) assert ("[" + dev.RED + styles.bright + dev._pad("critical", cr._longest_level) + styles.reset + "] " + padded + styles.kv_key + "foo" + styles.reset + "=" + styles.kv_value + "'bar'" + styles.reset) == rv
def test_level(self, cr, styles, padded): """ Levels are rendered aligned, in square brackets, and color coded. """ rv = cr(None, None, { "event": "test", "level": "critical", "foo": "bar" }) assert ( "[" + dev.RED + styles.bright + dev._pad("critical", cr._longest_level) + styles.reset + "] " + padded + styles.kv_key + "foo" + styles.reset + "=" + styles.kv_value + "bar" + styles.reset ) == rv
def test_pad_event_param(self, styles): """ `pad_event` parameter works. """ rv = dev.ConsoleRenderer(42, dev._has_colorama)(None, None, { "event": "test", "foo": "bar" }) assert ( styles.bright + dev._pad("test", 42) + styles.reset + " " + styles.kv_key + "foo" + styles.reset + "=" + styles.kv_value + "bar" + styles.reset ) == rv
def test_colorama_force_colors(self, styles, padded): """ If force_colors is True, use colors even if the destination is non-tty. """ cr = dev.ConsoleRenderer(colors=dev._has_colorama, force_colors=dev._has_colorama) rv = cr(None, None, { "event": "test", "level": "critical", "foo": "bar" }) assert ("[" + dev.RED + styles.bright + dev._pad("critical", cr._longest_level) + styles.reset + "] " + padded + styles.kv_key + "foo" + styles.reset + "=" + styles.kv_value + "bar" + styles.reset) == rv assert not dev._has_colorama or dev._ColorfulStyles is cr._styles
def test_everything(self, cr, styles, padded): """ Put all cases together. """ exc = "Traceback:\nFake traceback...\nFakeError: yolo" stack = "fake stack trace" rv = cr(None, None, { "event": "test", "exception": exc, "key": "value", "foo": "bar", "timestamp": "13:13", "logger": "some_module", "level": "error", "stack": stack, }) assert ( styles.timestamp + "13:13" + styles.reset + " [" + styles.level_error + styles.bright + dev._pad("error", cr._longest_level) + styles.reset + "] " + padded + "[" + dev.BLUE + styles.bright + "some_module" + styles.reset + "] " + styles.kv_key + "foo" + styles.reset + "=" + styles.kv_value + "bar" + styles.reset + " " + styles.kv_key + "key" + styles.reset + "=" + styles.kv_value + "value" + styles.reset + "\n" + stack + "\n\n" + "=" * 79 + "\n" + "\n" + exc ) == rv
def test_negative(self): """ If string is already too long, don't do anything. """ assert len("test") == len(dev._pad("test", 2))
def padded(styles): return ( styles.bright + dev._pad("test", dev._EVENT_WIDTH) + styles.reset + " " )
def test_normal(self): """ If chars are missing, adequate number of " " are added. """ assert 100 == len(dev._pad("test", 100))
level. """ with pytest.raises(SystemError) as e: dev.ConsoleRenderer() assert ("ConsoleRenderer requires the colorama package installed." ) in e.value.args[0] @pytest.fixture def cr(): return dev.ConsoleRenderer() if dev.colorama is not None: PADDED_TEST = (dev.BRIGHT + dev._pad("test", dev._EVENT_WIDTH) + dev.RESET_ALL + " ") @pytest.mark.skipif(dev.colorama is None, reason="Requires colorama.") class TestConsoleRenderer(object): def test_plain(self, cr): """ Works with a plain event_dict with only the event. """ rv = cr(None, None, {"event": "test"}) assert PADDED_TEST == rv def test_timestamp(self, cr): """
def __call__(self, logger, name, event_dict): sio = StringIO() # ``readthedocs`` as programname is required because it's used by # syslog to filter messages and send them to different files. # https://www.rsyslog.com/doc/master/configuration/properties.html#message-properties sio.write("readthedocs") process_id = event_dict.pop("process_id", None) if process_id is not None: sio.write( "[" + str(process_id) + "]" ) # syslog tag delimiter sio.write(": ") ts = event_dict.pop("timestamp", None) if ts is not None: sio.write( # can be a number if timestamp is UNIXy self._styles.timestamp + str(ts) + self._styles.reset + " " ) level = event_dict.pop("level", None) if level is not None: sio.write( "[" + self._level_to_color.get(level, "") + _pad(level, self._longest_level) + self._styles.reset + "] " ) # force event to str for compatibility with standard library event = event_dict.pop("event", None) if not isinstance(event, str): event = str(event) if event_dict: event = _pad(event, self._pad_event) + self._styles.reset + " " else: event += self._styles.reset sio.write(self._styles.bright + event) logger_name = event_dict.pop("logger", None) if logger_name is None: logger_name = event_dict.pop("logger_name", None) line_number = event_dict.pop("line_number", None) if logger_name is not None: sio.write( "[" + self._styles.logger_name + self._styles.bright + logger_name + self._styles.reset + ":" + str(line_number) + "] " ) stack = event_dict.pop("stack", None) exc = event_dict.pop("exception", None) exc_info = event_dict.pop("exc_info", None) event_dict_keys = event_dict.keys() if self._sort_keys: event_dict_keys = sorted(event_dict_keys) sio.write( " ".join( self._styles.kv_key + key + self._styles.reset + "=" + self._styles.kv_value + self._repr(event_dict[key]) + self._styles.reset for key in event_dict_keys ) ) if stack is not None: sio.write("\n" + stack) if exc_info or exc is not None: sio.write("\n\n" + "=" * 79 + "\n") if exc_info: if not isinstance(exc_info, tuple): exc_info = sys.exc_info() self._exception_formatter(sio, exc_info) elif exc is not None: if self._exception_formatter is not plain_traceback: warnings.warn( "Remove `format_exc_info` from your processor chain " "if you want pretty exceptions." ) sio.write("\n" + exc) return sio.getvalue()
dev.ConsoleRenderer() assert ( "ConsoleRenderer requires the colorama package installed." ) in e.value.args[0] @pytest.fixture def cr(): return dev.ConsoleRenderer() if dev.colorama is not None: PADDED_TEST = ( dev.BRIGHT + dev._pad("test", dev._EVENT_WIDTH) + dev.RESET_ALL + " " ) @pytest.mark.skipif(dev.colorama is None, reason="Requires colorama.") class TestConsoleRenderer(object): def test_plain(self, cr): """ Works with a plain event_dict with only the event. """ rv = cr(None, None, {"event": "test"}) assert PADDED_TEST == rv def test_timestamp(self, cr):