mirror of
https://github.com/bugsink/bugsink.git
synced 2026-01-01 10:50:47 -06:00
96 lines
2.7 KiB
Python
96 lines
2.7 KiB
Python
import collections
|
|
import json
|
|
|
|
from django.utils.encoding import force_str
|
|
from django.template.defaultfilters import truncatechars
|
|
|
|
|
|
SENTRY_MAX_VARIABLE_SIZE = 512
|
|
|
|
|
|
def get_path(data, *path, **kwargs):
|
|
"""
|
|
Safely resolves data from a recursive data structure. A value is only
|
|
returned if the full path exists, otherwise ``None`` is returned.
|
|
If the ``default`` argument is specified, it is returned instead of ``None``.
|
|
If the ``filter`` argument is specified and the value is a list, it is
|
|
filtered with the given callback. Alternatively, pass ``True`` as filter to
|
|
only filter ``None`` values.
|
|
"""
|
|
default = kwargs.pop("default", None)
|
|
f = kwargs.pop("filter", None)
|
|
for k in kwargs:
|
|
raise TypeError("set_path() got an undefined keyword argument '%s'" % k)
|
|
|
|
for p in path:
|
|
if isinstance(data, collections.abc.Mapping) and p in data:
|
|
data = data[p]
|
|
elif isinstance(data, (list, tuple)) and -len(data) <= p < len(data):
|
|
data = data[p]
|
|
else:
|
|
return default
|
|
|
|
if f and data and isinstance(data, (list, tuple)):
|
|
data = list(filter((lambda x: x is not None) if f is True else f, data))
|
|
|
|
return data if data is not None else default
|
|
|
|
|
|
def trim(
|
|
value,
|
|
max_size=SENTRY_MAX_VARIABLE_SIZE,
|
|
max_depth=6,
|
|
object_hook=None,
|
|
_depth=0,
|
|
_size=0,
|
|
**kwargs
|
|
):
|
|
"""
|
|
Truncates a value to ```MAX_VARIABLE_SIZE```.
|
|
The method of truncation depends on the type of value.
|
|
"""
|
|
options = {
|
|
"max_depth": max_depth,
|
|
"max_size": max_size,
|
|
"object_hook": object_hook,
|
|
"_depth": _depth + 1,
|
|
}
|
|
|
|
if _depth > max_depth:
|
|
if not isinstance(value, str):
|
|
value = json.dumps(value)
|
|
return trim(value, _size=_size, max_size=max_size)
|
|
|
|
elif isinstance(value, dict):
|
|
result = {}
|
|
_size += 2
|
|
for k in sorted(value.keys()):
|
|
v = value[k]
|
|
trim_v = trim(v, _size=_size, **options)
|
|
result[k] = trim_v
|
|
_size += len(force_str(trim_v)) + 1
|
|
if _size >= max_size:
|
|
break
|
|
|
|
elif isinstance(value, (list, tuple)):
|
|
result = []
|
|
_size += 2
|
|
for v in value:
|
|
trim_v = trim(v, _size=_size, **options)
|
|
result.append(trim_v)
|
|
_size += len(force_str(trim_v))
|
|
if _size >= max_size:
|
|
break
|
|
if isinstance(value, tuple):
|
|
result = tuple(result)
|
|
|
|
elif isinstance(value, str):
|
|
result = truncatechars(value, max_size - _size)
|
|
|
|
else:
|
|
result = value
|
|
|
|
if object_hook is None:
|
|
return result
|
|
return object_hook(result)
|