From ca7359cbb42202a46127dc7969be757e14830609 Mon Sep 17 00:00:00 2001 From: David Baumgold Date: Fri, 17 May 2024 14:01:17 +0200 Subject: [PATCH] Support pathlib.Path() objects --- rollbar/__init__.py | 8 +++++++- rollbar/lib/transform.py | 3 +++ rollbar/lib/transforms/__init__.py | 1 + rollbar/lib/traverse.py | 11 ++++++++++- rollbar/lib/type_info.py | 6 ++++++ rollbar/test/test_rollbar.py | 19 +++++++++++++++++++ 6 files changed, 46 insertions(+), 2 deletions(-) diff --git a/rollbar/__init__.py b/rollbar/__init__.py index 42b8d5ec..71b3a82e 100644 --- a/rollbar/__init__.py +++ b/rollbar/__init__.py @@ -1118,8 +1118,14 @@ def _check_add_locals(frame, frame_num, total_frames): """ # Include the last frames locals # Include any frame locals that came from a file in the project's root + root = SETTINGS.get('root') + if root: + # coerce to string, in case root is a Path object + root = str(root) + else: + root = '' return any(((frame_num == total_frames - 1), - ('root' in SETTINGS and (frame.get('filename') or '').lower().startswith((SETTINGS['root'] or '').lower())))) + ('root' in SETTINGS and (frame.get('filename') or '').lower().startswith(root.lower())))) def _get_actual_request(request): diff --git a/rollbar/lib/transform.py b/rollbar/lib/transform.py index 2ba7a030..49391ecd 100644 --- a/rollbar/lib/transform.py +++ b/rollbar/lib/transform.py @@ -32,5 +32,8 @@ def transform_unicode(self, o, key=None): def transform_boolean(self, o, key=None): return self.default(o, key=key) + def transform_path(self, o, key=None): + return self.default(str(o), key=key) + def transform_custom(self, o, key=None): return self.default(o, key=key) diff --git a/rollbar/lib/transforms/__init__.py b/rollbar/lib/transforms/__init__.py index 3f1b8802..6b4c59c0 100644 --- a/rollbar/lib/transforms/__init__.py +++ b/rollbar/lib/transforms/__init__.py @@ -79,6 +79,7 @@ def default_handler(o, key=None): "list_handler": lambda o, key=None: do_transform("list", o, key=key), "set_handler": lambda o, key=None: do_transform("set", o, key=key), "mapping_handler": lambda o, key=None: do_transform("dict", o, key=key), + "path_handler": lambda o, key=None: do_transform("path", o, key=key), "circular_reference_handler": lambda o, key=None, ref_key=None: do_transform( "circular_reference", o, key=key, ref_key=ref_key ), diff --git a/rollbar/lib/traverse.py b/rollbar/lib/traverse.py index 6a613dad..de00d5b7 100644 --- a/rollbar/lib/traverse.py +++ b/rollbar/lib/traverse.py @@ -1,5 +1,5 @@ import logging - +from pathlib import Path from rollbar.lib import binary_type, string_types, circular_reference_label @@ -16,6 +16,7 @@ LIST, SET, STRING, + PATH, ) @@ -49,6 +50,9 @@ def _noop_set(a, **_): def _noop_mapping(a, **_): return dict(a) +def _noop_path(a, **_): + return Path(a) + _default_handlers = { CIRCULAR: _noop_circular, @@ -58,6 +62,7 @@ def _noop_mapping(a, **_): NAMEDTUPLE: _noop_namedtuple, LIST: _noop_list, SET: _noop_set, + PATH: _noop_path, MAPPING: _noop_mapping, } @@ -71,6 +76,7 @@ def traverse( list_handler=_default_handlers[LIST], set_handler=_default_handlers[SET], mapping_handler=_default_handlers[MAPPING], + path_handler=_default_handlers[PATH], default_handler=_default_handlers[DEFAULT], circular_reference_handler=_default_handlers[CIRCULAR], allowed_circular_reference_types=None, @@ -97,6 +103,7 @@ def traverse( "list_handler": list_handler, "set_handler": set_handler, "mapping_handler": mapping_handler, + "path_handler": path_handler, "default_handler": default_handler, "circular_reference_handler": circular_reference_handler, "allowed_circular_reference_types": allowed_circular_reference_types, @@ -137,6 +144,8 @@ def traverse( {k: traverse(v, key=key + (k,), **kw) for k, v in obj.items()}, key=key, ) + elif obj_type is PATH: + return path_handler(obj, key=key) elif obj_type is DEFAULT: for handler_type, handler in custom_handlers.items(): if isinstance(obj, handler_type): diff --git a/rollbar/lib/type_info.py b/rollbar/lib/type_info.py index 7cf0af54..9d1bd239 100644 --- a/rollbar/lib/type_info.py +++ b/rollbar/lib/type_info.py @@ -2,6 +2,7 @@ from collections.abc import Mapping, Sequence, Set +from pathlib import Path CIRCULAR = -1 @@ -12,6 +13,7 @@ LIST = 4 SET = 5 STRING = 6 +PATH = 7 def get_type(obj): @@ -33,6 +35,9 @@ def get_type(obj): if isinstance(obj, Sequence): return LIST + if isinstance(obj, Path): + return PATH + return DEFAULT @@ -45,5 +50,6 @@ def get_type(obj): "LIST", "SET", "STRING", + "PATH", "get_type", ] diff --git a/rollbar/test/test_rollbar.py b/rollbar/test/test_rollbar.py index 3107e9e4..ba44885c 100644 --- a/rollbar/test/test_rollbar.py +++ b/rollbar/test/test_rollbar.py @@ -12,6 +12,8 @@ except ImportError: from io import StringIO +from pathlib import Path + from unittest import mock import unittest @@ -1866,6 +1868,23 @@ def test_starlette_extract_user_ip_from_headers(self): request = Request(scope) user_ip = rollbar._starlette_extract_user_ip(request) self.assertEqual(user_ip, ip_forwarded_for.decode()) + + @mock.patch('rollbar.send_payload') + def test_root_path(self, send_payload): + prev_root = rollbar.SETTINGS['root'] + rollbar.SETTINGS['root'] = Path("/tmp") + try: + called_with('original value') + except: + rollbar.report_exc_info() + finally: + rollbar.SETTINGS['root'] = prev_root + + self.assertEqual(send_payload.called, True) + + payload = send_payload.call_args[0][0] + self.assertEqual(payload['data']['server']['root'], "/tmp") + ### Helpers