Strip six module and rename to raven._compat
We're seeing some odd issues with our six module interacting badly with the six module from other libraries for some users. The suspicion is that our six module in some cases gets unvendored. We thus rename it to `raven._compat` (which is also what some other Python modules do). We still use six normally for the tests.
This commit is contained in:
parent
f2eedb742c
commit
97e93ea7ba
|
@ -20,13 +20,17 @@ def main():
|
||||||
from flake8.main import DEFAULT_CONFIG
|
from flake8.main import DEFAULT_CONFIG
|
||||||
from flake8.engine import get_style_guide
|
from flake8.engine import get_style_guide
|
||||||
from flake8.hooks import run
|
from flake8.hooks import run
|
||||||
from raven.utils import six
|
|
||||||
|
|
||||||
gitcmd = "git diff-index --cached --name-only HEAD"
|
gitcmd = "git diff-index --cached --name-only HEAD"
|
||||||
|
|
||||||
_, files_modified, _ = run(gitcmd)
|
_, files_modified, _ = run(gitcmd)
|
||||||
|
|
||||||
files_modified = [six.text_type(x) for x in files_modified]
|
try:
|
||||||
|
text_type = unicode
|
||||||
|
except NameError:
|
||||||
|
text_type = str
|
||||||
|
|
||||||
|
files_modified = [text_type(x) for x in files_modified]
|
||||||
|
|
||||||
# remove non-py files and files which no longer exist
|
# remove non-py files and files which no longer exist
|
||||||
files_modified = filter(
|
files_modified = filter(
|
||||||
|
|
|
@ -0,0 +1,177 @@
|
||||||
|
"""Utilities for writing code that runs on Python 2 and 3"""
|
||||||
|
# flake8: noqa
|
||||||
|
|
||||||
|
# Copyright (c) 2010-2013 Benjamin Peterson
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
# this software and associated documentation files (the "Software"), to deal in
|
||||||
|
# the Software without restriction, including without limitation the rights to
|
||||||
|
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
# the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
# subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in all
|
||||||
|
# copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
import operator
|
||||||
|
import sys
|
||||||
|
import types
|
||||||
|
|
||||||
|
__author__ = "Benjamin Peterson <benjamin@python.org>"
|
||||||
|
__version__ = "1.3.0"
|
||||||
|
|
||||||
|
|
||||||
|
PY2 = sys.version_info[0] == 2
|
||||||
|
|
||||||
|
if not PY2:
|
||||||
|
string_types = str,
|
||||||
|
integer_types = int,
|
||||||
|
class_types = type,
|
||||||
|
text_type = str
|
||||||
|
binary_type = bytes
|
||||||
|
|
||||||
|
MAXSIZE = sys.maxsize
|
||||||
|
else:
|
||||||
|
string_types = basestring,
|
||||||
|
integer_types = (int, long)
|
||||||
|
class_types = (type, types.ClassType)
|
||||||
|
text_type = unicode
|
||||||
|
binary_type = str
|
||||||
|
|
||||||
|
if sys.platform.startswith("java"):
|
||||||
|
# Jython always uses 32 bits.
|
||||||
|
MAXSIZE = int((1 << 31) - 1)
|
||||||
|
else:
|
||||||
|
# It's possible to have sizeof(long) != sizeof(Py_ssize_t).
|
||||||
|
class X(object):
|
||||||
|
def __len__(self):
|
||||||
|
return 1 << 31
|
||||||
|
try:
|
||||||
|
len(X())
|
||||||
|
except OverflowError:
|
||||||
|
# 32-bit
|
||||||
|
MAXSIZE = int((1 << 31) - 1)
|
||||||
|
else:
|
||||||
|
# 64-bit
|
||||||
|
MAXSIZE = int((1 << 63) - 1)
|
||||||
|
del X
|
||||||
|
|
||||||
|
|
||||||
|
def _import_module(name):
|
||||||
|
"""Import module, returning the module after the last dot."""
|
||||||
|
__import__(name)
|
||||||
|
return sys.modules[name]
|
||||||
|
|
||||||
|
|
||||||
|
if not PY2:
|
||||||
|
_iterkeys = "keys"
|
||||||
|
_itervalues = "values"
|
||||||
|
_iteritems = "items"
|
||||||
|
_iterlists = "lists"
|
||||||
|
else:
|
||||||
|
_iterkeys = "iterkeys"
|
||||||
|
_itervalues = "itervalues"
|
||||||
|
_iteritems = "iteritems"
|
||||||
|
_iterlists = "iterlists"
|
||||||
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
advance_iterator = next
|
||||||
|
except NameError:
|
||||||
|
def advance_iterator(it):
|
||||||
|
return it.next()
|
||||||
|
next = advance_iterator
|
||||||
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
callable = callable
|
||||||
|
except NameError:
|
||||||
|
def callable(obj):
|
||||||
|
return any("__call__" in klass.__dict__ for klass in type(obj).__mro__)
|
||||||
|
|
||||||
|
|
||||||
|
def iterkeys(d, **kw):
|
||||||
|
"""Return an iterator over the keys of a dictionary."""
|
||||||
|
return iter(getattr(d, _iterkeys)(**kw))
|
||||||
|
|
||||||
|
|
||||||
|
def itervalues(d, **kw):
|
||||||
|
"""Return an iterator over the values of a dictionary."""
|
||||||
|
return iter(getattr(d, _itervalues)(**kw))
|
||||||
|
|
||||||
|
|
||||||
|
def iteritems(d, **kw):
|
||||||
|
"""Return an iterator over the (key, value) pairs of a dictionary."""
|
||||||
|
return iter(getattr(d, _iteritems)(**kw))
|
||||||
|
|
||||||
|
|
||||||
|
def iterlists(d, **kw):
|
||||||
|
"""Return an iterator over the (key, [values]) pairs of a dictionary."""
|
||||||
|
return iter(getattr(d, _iterlists)(**kw))
|
||||||
|
|
||||||
|
|
||||||
|
if not PY2:
|
||||||
|
def b(s):
|
||||||
|
return s.encode("latin-1")
|
||||||
|
|
||||||
|
def u(s):
|
||||||
|
return s
|
||||||
|
if sys.version_info[1] <= 1:
|
||||||
|
def int2byte(i):
|
||||||
|
return bytes((i,))
|
||||||
|
else:
|
||||||
|
# This is about 2x faster than the implementation above on 3.2+
|
||||||
|
int2byte = operator.methodcaller("to_bytes", 1, "big")
|
||||||
|
import io
|
||||||
|
StringIO = io.StringIO
|
||||||
|
BytesIO = io.BytesIO
|
||||||
|
else:
|
||||||
|
def b(s): # NOQA
|
||||||
|
return s
|
||||||
|
|
||||||
|
def u(s): # NOQA
|
||||||
|
return unicode(s, "unicode_escape")
|
||||||
|
int2byte = chr
|
||||||
|
import StringIO
|
||||||
|
StringIO = BytesIO = StringIO.StringIO
|
||||||
|
|
||||||
|
|
||||||
|
if not PY2:
|
||||||
|
import builtins
|
||||||
|
exec_ = getattr(builtins, "exec")
|
||||||
|
|
||||||
|
def reraise(tp, value, tb=None):
|
||||||
|
if value.__traceback__ is not tb:
|
||||||
|
raise value.with_traceback(tb)
|
||||||
|
raise value
|
||||||
|
|
||||||
|
del builtins
|
||||||
|
|
||||||
|
else:
|
||||||
|
def exec_(_code_, _globs_=None, _locs_=None):
|
||||||
|
"""Execute code in a namespace."""
|
||||||
|
if _globs_ is None:
|
||||||
|
frame = sys._getframe(1)
|
||||||
|
_globs_ = frame.f_globals
|
||||||
|
if _locs_ is None:
|
||||||
|
_locs_ = frame.f_locals
|
||||||
|
del frame
|
||||||
|
elif _locs_ is None:
|
||||||
|
_locs_ = _globs_
|
||||||
|
exec("""exec _code_ in _globs_, _locs_""")
|
||||||
|
|
||||||
|
exec_("""def reraise(tp, value, tb=None):
|
||||||
|
raise tp, value, tb
|
||||||
|
""")
|
||||||
|
|
||||||
|
def with_metaclass(meta, base=object):
|
||||||
|
"""Create a base class with a metaclass."""
|
||||||
|
return meta("NewBase", (base,), {})
|
|
@ -30,7 +30,8 @@ from raven.conf import defaults
|
||||||
from raven.conf.remote import RemoteConfig
|
from raven.conf.remote import RemoteConfig
|
||||||
from raven.context import Context
|
from raven.context import Context
|
||||||
from raven.exceptions import APIError, RateLimited
|
from raven.exceptions import APIError, RateLimited
|
||||||
from raven.utils import six, json, get_versions, get_auth_header, merge_dicts
|
from raven.utils import json, get_versions, get_auth_header, merge_dicts
|
||||||
|
from raven._compat import text_type, iteritems
|
||||||
from raven.utils.encoding import to_unicode
|
from raven.utils.encoding import to_unicode
|
||||||
from raven.utils.serializer import transform
|
from raven.utils.serializer import transform
|
||||||
from raven.utils.stacks import get_stack_info, iter_stack_frames, get_culprit
|
from raven.utils.stacks import get_stack_info, iter_stack_frames, get_culprit
|
||||||
|
@ -145,7 +146,7 @@ class Client(object):
|
||||||
|
|
||||||
self.include_paths = set(o.get('include_paths') or [])
|
self.include_paths = set(o.get('include_paths') or [])
|
||||||
self.exclude_paths = set(o.get('exclude_paths') or [])
|
self.exclude_paths = set(o.get('exclude_paths') or [])
|
||||||
self.name = six.text_type(o.get('name') or o.get('machine') or defaults.NAME)
|
self.name = text_type(o.get('name') or o.get('machine') or defaults.NAME)
|
||||||
self.auto_log_stacks = bool(
|
self.auto_log_stacks = bool(
|
||||||
o.get('auto_log_stacks') or defaults.AUTO_LOG_STACKS)
|
o.get('auto_log_stacks') or defaults.AUTO_LOG_STACKS)
|
||||||
self.capture_locals = bool(
|
self.capture_locals = bool(
|
||||||
|
@ -252,7 +253,8 @@ class Client(object):
|
||||||
>>> result = client.capture(**kwargs)
|
>>> result = client.capture(**kwargs)
|
||||||
>>> ident = client.get_ident(result)
|
>>> ident = client.get_ident(result)
|
||||||
"""
|
"""
|
||||||
warnings.warn('Client.get_ident is deprecated. The event ID is now returned as the result of capture.',
|
warnings.warn('Client.get_ident is deprecated. The event ID is now '
|
||||||
|
'returned as the result of capture.',
|
||||||
DeprecationWarning)
|
DeprecationWarning)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
@ -306,7 +308,7 @@ class Client(object):
|
||||||
if data.get('culprit'):
|
if data.get('culprit'):
|
||||||
culprit = data['culprit']
|
culprit = data['culprit']
|
||||||
|
|
||||||
for k, v in six.iteritems(result):
|
for k, v in iteritems(result):
|
||||||
if k not in data:
|
if k not in data:
|
||||||
data[k] = v
|
data[k] = v
|
||||||
|
|
||||||
|
@ -394,11 +396,11 @@ class Client(object):
|
||||||
data['message'] = kwargs.get('message', handler.to_string(data))
|
data['message'] = kwargs.get('message', handler.to_string(data))
|
||||||
|
|
||||||
# tags should only be key=>u'value'
|
# tags should only be key=>u'value'
|
||||||
for key, value in six.iteritems(data['tags']):
|
for key, value in iteritems(data['tags']):
|
||||||
data['tags'][key] = to_unicode(value)
|
data['tags'][key] = to_unicode(value)
|
||||||
|
|
||||||
# extra data can be any arbitrary value
|
# extra data can be any arbitrary value
|
||||||
for k, v in six.iteritems(data['extra']):
|
for k, v in iteritems(data['extra']):
|
||||||
data['extra'][k] = self.transform(v)
|
data['extra'][k] = self.transform(v)
|
||||||
|
|
||||||
# It's important date is added **after** we serialize
|
# It's important date is added **after** we serialize
|
||||||
|
@ -556,7 +558,8 @@ class Client(object):
|
||||||
if isinstance(exc, RateLimited):
|
if isinstance(exc, RateLimited):
|
||||||
retry_after = exc.retry_after
|
retry_after = exc.retry_after
|
||||||
self.error_logger.error(
|
self.error_logger.error(
|
||||||
'Sentry responded with an API error: %s(%s)', type(exc).__name__, exc.message)
|
'Sentry responded with an API error: %s(%s)',
|
||||||
|
type(exc).__name__, exc.message)
|
||||||
else:
|
else:
|
||||||
self.error_logger.error(
|
self.error_logger.error(
|
||||||
'Sentry responded with an error: %s (url: %s)\n%s',
|
'Sentry responded with an error: %s (url: %s)\n%s',
|
||||||
|
@ -577,10 +580,10 @@ class Client(object):
|
||||||
if 'exception' in data and 'stacktrace' in data['exception']['values'][0]:
|
if 'exception' in data and 'stacktrace' in data['exception']['values'][0]:
|
||||||
# try to reconstruct a reasonable version of the exception
|
# try to reconstruct a reasonable version of the exception
|
||||||
for frame in data['exception']['values'][0]['stacktrace']['frames']:
|
for frame in data['exception']['values'][0]['stacktrace']['frames']:
|
||||||
output.append(' File "%(filename)s", line %(lineno)s, in %(function)s' % {
|
output.append(' File "%(fn)s", line %(lineno)s, in %(func)s' % {
|
||||||
'filename': frame['filename'],
|
'fn': frame['filename'],
|
||||||
'lineno': frame['lineno'],
|
'lineno': frame['lineno'],
|
||||||
'function': frame['function'],
|
'func': frame['function'],
|
||||||
})
|
})
|
||||||
|
|
||||||
self.uncaught_logger.error(output)
|
self.uncaught_logger.error(output)
|
||||||
|
|
|
@ -2,9 +2,9 @@ from __future__ import absolute_import
|
||||||
|
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
|
from raven._compat import PY2, text_type
|
||||||
from raven.exceptions import InvalidDsn
|
from raven.exceptions import InvalidDsn
|
||||||
from raven.transport.threaded import ThreadedHTTPTransport
|
from raven.transport.threaded import ThreadedHTTPTransport
|
||||||
from raven.utils import six
|
|
||||||
from raven.utils.encoding import to_string
|
from raven.utils.encoding import to_string
|
||||||
from raven.utils.urlparse import parse_qsl, urlparse
|
from raven.utils.urlparse import parse_qsl, urlparse
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ class RemoteConfig(object):
|
||||||
self._transport_cls = transport or DEFAULT_TRANSPORT
|
self._transport_cls = transport or DEFAULT_TRANSPORT
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return six.text_type(self.base_url)
|
return text_type(self.base_url)
|
||||||
|
|
||||||
def is_active(self):
|
def is_active(self):
|
||||||
return all([self.base_url, self.project, self.public_key, self.secret_key])
|
return all([self.base_url, self.project, self.public_key, self.secret_key])
|
||||||
|
@ -58,7 +58,7 @@ class RemoteConfig(object):
|
||||||
def from_string(cls, value, transport=None, transport_registry=None):
|
def from_string(cls, value, transport=None, transport_registry=None):
|
||||||
# in Python 2.x sending the DSN as a unicode value will eventually
|
# in Python 2.x sending the DSN as a unicode value will eventually
|
||||||
# cause issues in httplib
|
# cause issues in httplib
|
||||||
if not six.PY3:
|
if PY2:
|
||||||
value = to_string(value)
|
value = to_string(value)
|
||||||
|
|
||||||
url = urlparse(value)
|
url = urlparse(value)
|
||||||
|
|
|
@ -10,7 +10,7 @@ from __future__ import absolute_import
|
||||||
from collections import Mapping, Iterable
|
from collections import Mapping, Iterable
|
||||||
from threading import local
|
from threading import local
|
||||||
|
|
||||||
from raven.utils import six
|
from raven._compat import iteritems
|
||||||
|
|
||||||
|
|
||||||
class Context(local, Mapping, Iterable):
|
class Context(local, Mapping, Iterable):
|
||||||
|
@ -42,10 +42,10 @@ class Context(local, Mapping, Iterable):
|
||||||
|
|
||||||
def merge(self, data):
|
def merge(self, data):
|
||||||
d = self.data
|
d = self.data
|
||||||
for key, value in six.iteritems(data):
|
for key, value in iteritems(data):
|
||||||
if key in ('tags', 'extra'):
|
if key in ('tags', 'extra'):
|
||||||
d.setdefault(key, {})
|
d.setdefault(key, {})
|
||||||
for t_key, t_value in six.iteritems(value):
|
for t_key, t_value in iteritems(value):
|
||||||
d[key][t_key] = t_value
|
d[key][t_key] = t_value
|
||||||
else:
|
else:
|
||||||
d[key] = value
|
d[key] = value
|
||||||
|
|
|
@ -19,7 +19,7 @@ import warnings
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from hashlib import md5
|
from hashlib import md5
|
||||||
|
|
||||||
from raven.utils import six
|
from raven._compat import PY2, binary_type, text_type
|
||||||
from raven.utils.imports import import_string
|
from raven.utils.imports import import_string
|
||||||
from raven.contrib.django.management import patch_cli_runner
|
from raven.contrib.django.management import patch_cli_runner
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ class ProxyClient(object):
|
||||||
__ne__ = lambda x, o: get_client() != o
|
__ne__ = lambda x, o: get_client() != o
|
||||||
__gt__ = lambda x, o: get_client() > o
|
__gt__ = lambda x, o: get_client() > o
|
||||||
__ge__ = lambda x, o: get_client() >= o
|
__ge__ = lambda x, o: get_client() >= o
|
||||||
if not six.PY3:
|
if PY2:
|
||||||
__cmp__ = lambda x, o: cmp(get_client(), o) # NOQA
|
__cmp__ = lambda x, o: cmp(get_client(), o) # NOQA
|
||||||
__hash__ = lambda x: hash(get_client())
|
__hash__ = lambda x: hash(get_client())
|
||||||
# attributes are currently not callable
|
# attributes are currently not callable
|
||||||
|
@ -92,11 +92,11 @@ class ProxyClient(object):
|
||||||
__invert__ = lambda x: ~(get_client())
|
__invert__ = lambda x: ~(get_client())
|
||||||
__complex__ = lambda x: complex(get_client())
|
__complex__ = lambda x: complex(get_client())
|
||||||
__int__ = lambda x: int(get_client())
|
__int__ = lambda x: int(get_client())
|
||||||
if not six.PY3:
|
if PY2:
|
||||||
__long__ = lambda x: long(get_client()) # NOQA
|
__long__ = lambda x: long(get_client()) # NOQA
|
||||||
__float__ = lambda x: float(get_client())
|
__float__ = lambda x: float(get_client())
|
||||||
__str__ = lambda x: six.binary_type(get_client())
|
__str__ = lambda x: binary_type(get_client())
|
||||||
__unicode__ = lambda x: six.text_type(get_client())
|
__unicode__ = lambda x: text_type(get_client())
|
||||||
__oct__ = lambda x: oct(get_client())
|
__oct__ = lambda x: oct(get_client())
|
||||||
__hex__ = lambda x: hex(get_client())
|
__hex__ = lambda x: hex(get_client())
|
||||||
__index__ = lambda x: get_client().__index__()
|
__index__ = lambda x: get_client().__index__()
|
||||||
|
@ -139,7 +139,7 @@ def get_client(client=None, reset=False):
|
||||||
options.setdefault('release', ga('RELEASE'))
|
options.setdefault('release', ga('RELEASE'))
|
||||||
|
|
||||||
transport = ga('TRANSPORT') or options.get('transport')
|
transport = ga('TRANSPORT') or options.get('transport')
|
||||||
if isinstance(transport, six.string_types):
|
if isinstance(transport, string_types):
|
||||||
transport = import_string(transport)
|
transport = import_string(transport)
|
||||||
options['transport'] = transport
|
options['transport'] = transport
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ from django.conf import settings
|
||||||
from django.http import HttpRequest
|
from django.http import HttpRequest
|
||||||
from django.utils.functional import Promise
|
from django.utils.functional import Promise
|
||||||
from raven.utils.serializer import Serializer, register
|
from raven.utils.serializer import Serializer, register
|
||||||
from raven.utils import six
|
from raven._compat import text_type
|
||||||
|
|
||||||
__all__ = ('PromiseSerializer',)
|
__all__ = ('PromiseSerializer',)
|
||||||
|
|
||||||
|
@ -34,12 +34,15 @@ class PromiseSerializer(Serializer):
|
||||||
|
|
||||||
def serialize(self, value, **kwargs):
|
def serialize(self, value, **kwargs):
|
||||||
# EPIC HACK
|
# EPIC HACK
|
||||||
# handles lazy model instances (which are proxy values that don't easily give you the actual function)
|
# handles lazy model instances (which are proxy values that don't
|
||||||
|
# easily give you the actual function)
|
||||||
pre = value.__class__.__name__[1:]
|
pre = value.__class__.__name__[1:]
|
||||||
if hasattr(value, '%s__func' % pre):
|
if hasattr(value, '%s__func' % pre):
|
||||||
value = getattr(value, '%s__func' % pre)(*getattr(value, '%s__args' % pre), **getattr(value, '%s__kw' % pre))
|
value = getattr(value, '%s__func' % pre)(
|
||||||
|
*getattr(value, '%s__args' % pre),
|
||||||
|
**getattr(value, '%s__kw' % pre))
|
||||||
else:
|
else:
|
||||||
return self.recurse(six.text_type(value))
|
return self.recurse(text_type(value))
|
||||||
return self.recurse(value, **kwargs)
|
return self.recurse(value, **kwargs)
|
||||||
|
|
||||||
register(PromiseSerializer)
|
register(PromiseSerializer)
|
||||||
|
|
|
@ -15,9 +15,9 @@ from django.views.decorators.cache import never_cache
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
from django.views.decorators.http import require_http_methods
|
from django.views.decorators.http import require_http_methods
|
||||||
|
|
||||||
|
from raven._compat import string_types
|
||||||
from raven.contrib.django.models import client
|
from raven.contrib.django.models import client
|
||||||
from raven.utils import json
|
from raven.utils import json
|
||||||
from raven.utils import six
|
|
||||||
|
|
||||||
|
|
||||||
def is_valid_origin(origin):
|
def is_valid_origin(origin):
|
||||||
|
@ -32,7 +32,7 @@ def is_valid_origin(origin):
|
||||||
|
|
||||||
origin = origin.lower()
|
origin = origin.lower()
|
||||||
for value in settings.SENTRY_ALLOW_ORIGIN:
|
for value in settings.SENTRY_ALLOW_ORIGIN:
|
||||||
if isinstance(value, six.string_types):
|
if isinstance(value, string_types):
|
||||||
if value.lower() == origin:
|
if value.lower() == origin:
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -23,11 +23,11 @@ from flask import request, current_app, g
|
||||||
from flask.signals import got_request_exception, request_finished
|
from flask.signals import got_request_exception, request_finished
|
||||||
from werkzeug.exceptions import ClientDisconnected
|
from werkzeug.exceptions import ClientDisconnected
|
||||||
|
|
||||||
|
from raven._compat import string_types
|
||||||
from raven.conf import setup_logging
|
from raven.conf import setup_logging
|
||||||
from raven.base import Client
|
from raven.base import Client
|
||||||
from raven.middleware import Sentry as SentryMiddleware
|
from raven.middleware import Sentry as SentryMiddleware
|
||||||
from raven.handlers.logging import SentryHandler
|
from raven.handlers.logging import SentryHandler
|
||||||
from raven.utils import six
|
|
||||||
from raven.utils.compat import _urlparse
|
from raven.utils.compat import _urlparse
|
||||||
from raven.utils.encoding import to_unicode
|
from raven.utils.encoding import to_unicode
|
||||||
from raven.utils.imports import import_string
|
from raven.utils.imports import import_string
|
||||||
|
@ -38,13 +38,14 @@ def make_client(client_cls, app, dsn=None):
|
||||||
# TODO(dcramer): django and Flask share very similar concepts here, and
|
# TODO(dcramer): django and Flask share very similar concepts here, and
|
||||||
# should be refactored
|
# should be refactored
|
||||||
transport = app.config.get('SENTRY_TRANSPORT')
|
transport = app.config.get('SENTRY_TRANSPORT')
|
||||||
if isinstance(transport, six.string_types):
|
if isinstance(transport, string_types):
|
||||||
transport = import_string(transport)
|
transport = import_string(transport)
|
||||||
|
|
||||||
return client_cls(
|
return client_cls(
|
||||||
dsn=dsn or app.config.get('SENTRY_DSN') or os.environ.get('SENTRY_DSN'),
|
dsn=dsn or app.config.get('SENTRY_DSN') or os.environ.get('SENTRY_DSN'),
|
||||||
transport=transport,
|
transport=transport,
|
||||||
include_paths=set(app.config.get('SENTRY_INCLUDE_PATHS', [])) | set([app.import_name]),
|
include_paths=set(app.config.get(
|
||||||
|
'SENTRY_INCLUDE_PATHS', [])) | set([app.import_name]),
|
||||||
exclude_paths=app.config.get('SENTRY_EXCLUDE_PATHS'),
|
exclude_paths=app.config.get('SENTRY_EXCLUDE_PATHS'),
|
||||||
name=app.config.get('SENTRY_NAME'),
|
name=app.config.get('SENTRY_NAME'),
|
||||||
site=app.config.get('SENTRY_SITE_NAME'),
|
site=app.config.get('SENTRY_SITE_NAME'),
|
||||||
|
@ -131,17 +132,20 @@ class Sentry(object):
|
||||||
if not self.client:
|
if not self.client:
|
||||||
return
|
return
|
||||||
|
|
||||||
ignored_exc_type_list = current_app.config.get('RAVEN_IGNORE_EXCEPTIONS', [])
|
ignored_exc_type_list = current_app.config.get(
|
||||||
|
'RAVEN_IGNORE_EXCEPTIONS', [])
|
||||||
exc = sys.exc_info()[1]
|
exc = sys.exc_info()[1]
|
||||||
|
|
||||||
if any((isinstance(exc, ignored_exc_type) for ignored_exc_type in ignored_exc_type_list)):
|
if any((isinstance(exc, ignored_exc_type)
|
||||||
|
for ignored_exc_type in ignored_exc_type_list)):
|
||||||
return
|
return
|
||||||
|
|
||||||
self.captureException(exc_info=kwargs.get('exc_info'))
|
self.captureException(exc_info=kwargs.get('exc_info'))
|
||||||
|
|
||||||
def get_user_info(self, request):
|
def get_user_info(self, request):
|
||||||
"""
|
"""
|
||||||
Requires Flask-Login (https://pypi.python.org/pypi/Flask-Login/) to be installed
|
Requires Flask-Login (https://pypi.python.org/pypi/Flask-Login/)
|
||||||
|
to be installed
|
||||||
and setup
|
and setup
|
||||||
"""
|
"""
|
||||||
if not has_flask_login:
|
if not has_flask_login:
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
from raven.utils import six
|
from raven._compat import text_type
|
||||||
|
|
||||||
|
|
||||||
class APIError(Exception):
|
class APIError(Exception):
|
||||||
|
@ -9,7 +9,7 @@ class APIError(Exception):
|
||||||
self.message = message
|
self.message = message
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return six.text_type("%s: %s" % (self.message, self.code))
|
return text_type("%s: %s" % (self.message, self.code))
|
||||||
|
|
||||||
|
|
||||||
class RateLimited(APIError):
|
class RateLimited(APIError):
|
||||||
|
|
|
@ -13,16 +13,16 @@ import logbook
|
||||||
import sys
|
import sys
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
|
from raven._compat import string_types
|
||||||
from raven.base import Client
|
from raven.base import Client
|
||||||
from raven.utils.encoding import to_string
|
from raven.utils.encoding import to_string
|
||||||
from raven.utils import six
|
|
||||||
|
|
||||||
|
|
||||||
class SentryHandler(logbook.Handler):
|
class SentryHandler(logbook.Handler):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
if len(args) == 1:
|
if len(args) == 1:
|
||||||
arg = args[0]
|
arg = args[0]
|
||||||
if isinstance(arg, six.string_types):
|
if isinstance(arg, string_types):
|
||||||
self.client = kwargs.pop('client_cls', Client)(dsn=arg, **kwargs)
|
self.client = kwargs.pop('client_cls', Client)(dsn=arg, **kwargs)
|
||||||
elif isinstance(arg, Client):
|
elif isinstance(arg, Client):
|
||||||
self.client = arg
|
self.client = arg
|
||||||
|
|
|
@ -14,8 +14,8 @@ import logging
|
||||||
import sys
|
import sys
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
|
from raven._compat import string_types, iteritems, text_type
|
||||||
from raven.base import Client
|
from raven.base import Client
|
||||||
from raven.utils import six
|
|
||||||
from raven.utils.encoding import to_string
|
from raven.utils.encoding import to_string
|
||||||
from raven.utils.stacks import iter_stack_frames, label_from_frame
|
from raven.utils.stacks import iter_stack_frames, label_from_frame
|
||||||
|
|
||||||
|
@ -31,15 +31,14 @@ class SentryHandler(logging.Handler, object):
|
||||||
client = kwargs.get('client_cls', Client)
|
client = kwargs.get('client_cls', Client)
|
||||||
if len(args) == 1:
|
if len(args) == 1:
|
||||||
arg = args[0]
|
arg = args[0]
|
||||||
if isinstance(arg, six.string_types):
|
if isinstance(arg, string_types):
|
||||||
self.client = client(dsn=arg, **kwargs)
|
self.client = client(dsn=arg, **kwargs)
|
||||||
elif isinstance(arg, Client):
|
elif isinstance(arg, Client):
|
||||||
self.client = arg
|
self.client = arg
|
||||||
else:
|
else:
|
||||||
raise ValueError('The first argument to %s must be either a Client instance or a DSN, got %r instead.' % (
|
raise ValueError('The first argument to %s must be either a '
|
||||||
self.__class__.__name__,
|
'Client instance or a DSN, got %r instead.' %
|
||||||
arg,
|
(self.__class__.__name__, arg,))
|
||||||
))
|
|
||||||
elif 'client' in kwargs:
|
elif 'client' in kwargs:
|
||||||
self.client = kwargs['client']
|
self.client = kwargs['client']
|
||||||
else:
|
else:
|
||||||
|
@ -68,7 +67,8 @@ class SentryHandler(logging.Handler, object):
|
||||||
except Exception:
|
except Exception:
|
||||||
if self.client.raise_send_errors:
|
if self.client.raise_send_errors:
|
||||||
raise
|
raise
|
||||||
print("Top level Sentry exception caught - failed creating log record", file=sys.stderr)
|
print("Top level Sentry exception caught - failed "
|
||||||
|
"creating log record", file=sys.stderr)
|
||||||
print(to_string(record.msg), file=sys.stderr)
|
print(to_string(record.msg), file=sys.stderr)
|
||||||
print(to_string(traceback.format_exc()), file=sys.stderr)
|
print(to_string(traceback.format_exc()), file=sys.stderr)
|
||||||
|
|
||||||
|
@ -113,7 +113,7 @@ class SentryHandler(logging.Handler, object):
|
||||||
else:
|
else:
|
||||||
extra = {}
|
extra = {}
|
||||||
|
|
||||||
for k, v in six.iteritems(vars(record)):
|
for k, v in iteritems(vars(record)):
|
||||||
if k in RESERVED:
|
if k in RESERVED:
|
||||||
continue
|
continue
|
||||||
if k.startswith('_'):
|
if k.startswith('_'):
|
||||||
|
@ -136,13 +136,13 @@ class SentryHandler(logging.Handler, object):
|
||||||
'params': record.args,
|
'params': record.args,
|
||||||
}
|
}
|
||||||
try:
|
try:
|
||||||
handler_kwargs['message'] = six.text_type(record.msg)
|
handler_kwargs['message'] = text_type(record.msg)
|
||||||
except UnicodeDecodeError:
|
except UnicodeDecodeError:
|
||||||
# Handle binary strings where it should be unicode...
|
# Handle binary strings where it should be unicode...
|
||||||
handler_kwargs['message'] = repr(record.msg)[1:-1]
|
handler_kwargs['message'] = repr(record.msg)[1:-1]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
handler_kwargs['formatted'] = six.text_type(record.message)
|
handler_kwargs['formatted'] = text_type(record.message)
|
||||||
except UnicodeDecodeError:
|
except UnicodeDecodeError:
|
||||||
# Handle binary strings where it should be unicode...
|
# Handle binary strings where it should be unicode...
|
||||||
handler_kwargs['formatted'] = repr(record.message)[1:-1]
|
handler_kwargs['formatted'] = repr(record.message)[1:-1]
|
||||||
|
@ -160,8 +160,12 @@ class SentryHandler(logging.Handler, object):
|
||||||
handler_kwargs = {'exc_info': record.exc_info}
|
handler_kwargs = {'exc_info': record.exc_info}
|
||||||
|
|
||||||
# HACK: discover a culprit when we normally couldn't
|
# HACK: discover a culprit when we normally couldn't
|
||||||
elif not (data.get('stacktrace') or data.get('culprit')) and (record.name or record.funcName):
|
elif not (data.get('stacktrace') or data.get('culprit')) \
|
||||||
culprit = label_from_frame({'module': record.name, 'function': record.funcName})
|
and (record.name or record.funcName):
|
||||||
|
culprit = label_from_frame({
|
||||||
|
'module': record.name,
|
||||||
|
'function': record.funcName
|
||||||
|
})
|
||||||
if culprit:
|
if culprit:
|
||||||
data['culprit'] = culprit
|
data['culprit'] = culprit
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,8 @@ from __future__ import absolute_import
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
from raven._compat import string_types, text_type
|
||||||
from raven.utils import varmap
|
from raven.utils import varmap
|
||||||
from raven.utils import six
|
|
||||||
|
|
||||||
|
|
||||||
class Processor(object):
|
class Processor(object):
|
||||||
|
@ -88,13 +88,13 @@ class SanitizePasswordsProcessor(Processor):
|
||||||
if value is None:
|
if value is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
if isinstance(value, six.string_types) and self.VALUES_RE.match(value):
|
if isinstance(value, string_types) and self.VALUES_RE.match(value):
|
||||||
return self.MASK
|
return self.MASK
|
||||||
|
|
||||||
if not key: # key can be a NoneType
|
if not key: # key can be a NoneType
|
||||||
return value
|
return value
|
||||||
|
|
||||||
key = six.text_type(key).lower()
|
key = text_type(key).lower()
|
||||||
for field in self.FIELDS:
|
for field in self.FIELDS:
|
||||||
if field in key:
|
if field in key:
|
||||||
# store mask as a fixed length for security
|
# store mask as a fixed length for security
|
||||||
|
@ -112,7 +112,7 @@ class SanitizePasswordsProcessor(Processor):
|
||||||
if n not in data:
|
if n not in data:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if isinstance(data[n], six.string_types) and '=' in data[n]:
|
if isinstance(data[n], string_types) and '=' in data[n]:
|
||||||
# at this point we've assumed it's a standard HTTP query
|
# at this point we've assumed it's a standard HTTP query
|
||||||
# or cookie
|
# or cookie
|
||||||
if n == 'cookies':
|
if n == 'cookies':
|
||||||
|
|
|
@ -7,10 +7,10 @@ raven.transport.http
|
||||||
"""
|
"""
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
from raven._compat import string_types
|
||||||
from raven.conf import defaults
|
from raven.conf import defaults
|
||||||
from raven.exceptions import APIError, RateLimited
|
from raven.exceptions import APIError, RateLimited
|
||||||
from raven.transport.base import Transport
|
from raven.transport.base import Transport
|
||||||
from raven.utils import six
|
|
||||||
from raven.utils.http import urlopen
|
from raven.utils.http import urlopen
|
||||||
from raven.utils.compat import urllib2
|
from raven.utils.compat import urllib2
|
||||||
|
|
||||||
|
@ -23,9 +23,9 @@ class HTTPTransport(Transport):
|
||||||
self._parsed_url = parsed_url
|
self._parsed_url = parsed_url
|
||||||
self._url = parsed_url.geturl().rsplit('+', 1)[-1]
|
self._url = parsed_url.geturl().rsplit('+', 1)[-1]
|
||||||
|
|
||||||
if isinstance(timeout, six.string_types):
|
if isinstance(timeout, string_types):
|
||||||
timeout = int(timeout)
|
timeout = int(timeout)
|
||||||
if isinstance(verify_ssl, six.string_types):
|
if isinstance(verify_ssl, string_types):
|
||||||
verify_ssl = bool(int(verify_ssl))
|
verify_ssl = bool(int(verify_ssl))
|
||||||
|
|
||||||
self.timeout = timeout
|
self.timeout = timeout
|
||||||
|
|
|
@ -7,7 +7,7 @@ raven.utils
|
||||||
"""
|
"""
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
from raven.utils import six
|
from raven._compat import iteritems, string_types
|
||||||
import logging
|
import logging
|
||||||
try:
|
try:
|
||||||
import pkg_resources
|
import pkg_resources
|
||||||
|
@ -24,7 +24,7 @@ def merge_dicts(*dicts):
|
||||||
if not d:
|
if not d:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for k, v in six.iteritems(d):
|
for k, v in iteritems(d):
|
||||||
out[k] = v
|
out[k] = v
|
||||||
return out
|
return out
|
||||||
|
|
||||||
|
@ -42,7 +42,8 @@ def varmap(func, var, context=None, name=None):
|
||||||
return func(name, '<...>')
|
return func(name, '<...>')
|
||||||
context[objid] = 1
|
context[objid] = 1
|
||||||
if isinstance(var, dict):
|
if isinstance(var, dict):
|
||||||
ret = dict((k, varmap(func, v, context, k)) for k, v in six.iteritems(var))
|
ret = dict((k, varmap(func, v, context, k))
|
||||||
|
for k, v in iteritems(var))
|
||||||
elif isinstance(var, (list, tuple)):
|
elif isinstance(var, (list, tuple)):
|
||||||
ret = [varmap(func, f, context, name) for f in var]
|
ret = [varmap(func, f, context, name) for f in var]
|
||||||
else:
|
else:
|
||||||
|
@ -79,7 +80,7 @@ def get_version_from_app(module_name, app):
|
||||||
if callable(version):
|
if callable(version):
|
||||||
version = version()
|
version = version()
|
||||||
|
|
||||||
if not isinstance(version, (six.string_types, list, tuple)):
|
if not isinstance(version, (string_types, list, tuple)):
|
||||||
version = None
|
version = None
|
||||||
|
|
||||||
if version is None:
|
if version is None:
|
||||||
|
@ -98,7 +99,8 @@ def get_versions(module_list=None):
|
||||||
ext_module_list = set()
|
ext_module_list = set()
|
||||||
for m in module_list:
|
for m in module_list:
|
||||||
parts = m.split('.')
|
parts = m.split('.')
|
||||||
ext_module_list.update('.'.join(parts[:idx]) for idx in range(1, len(parts) + 1))
|
ext_module_list.update('.'.join(parts[:idx])
|
||||||
|
for idx in range(1, len(parts) + 1))
|
||||||
|
|
||||||
versions = {}
|
versions = {}
|
||||||
for module_name in ext_module_list:
|
for module_name in ext_module_list:
|
||||||
|
@ -128,7 +130,8 @@ def get_versions(module_list=None):
|
||||||
return versions
|
return versions
|
||||||
|
|
||||||
|
|
||||||
def get_auth_header(protocol, timestamp, client, api_key, api_secret=None, **kwargs):
|
def get_auth_header(protocol, timestamp, client, api_key,
|
||||||
|
api_secret=None, **kwargs):
|
||||||
header = [
|
header = [
|
||||||
('sentry_timestamp', timestamp),
|
('sentry_timestamp', timestamp),
|
||||||
('sentry_client', client),
|
('sentry_client', client),
|
||||||
|
|
|
@ -8,7 +8,9 @@ raven.utils.encoding
|
||||||
from __future__ import absolute_import, unicode_literals
|
from __future__ import absolute_import, unicode_literals
|
||||||
|
|
||||||
import warnings
|
import warnings
|
||||||
from raven.utils import six
|
|
||||||
|
from raven._compat import integer_types, text_type, binary_type, \
|
||||||
|
string_types, PY2
|
||||||
|
|
||||||
|
|
||||||
def is_protected_type(obj):
|
def is_protected_type(obj):
|
||||||
|
@ -19,7 +21,7 @@ def is_protected_type(obj):
|
||||||
"""
|
"""
|
||||||
import Decimal
|
import Decimal
|
||||||
import datetime
|
import datetime
|
||||||
return isinstance(obj, six.integer_types + (type(None), float, Decimal,
|
return isinstance(obj, integer_types + (type(None), float, Decimal,
|
||||||
datetime.datetime, datetime.date, datetime.time))
|
datetime.datetime, datetime.date, datetime.time))
|
||||||
|
|
||||||
|
|
||||||
|
@ -31,25 +33,25 @@ def force_text(s, encoding='utf-8', strings_only=False, errors='strict'):
|
||||||
If strings_only is True, don't convert (some) non-string-like objects.
|
If strings_only is True, don't convert (some) non-string-like objects.
|
||||||
"""
|
"""
|
||||||
# Handle the common case first, saves 30-40% when s is an instance of
|
# Handle the common case first, saves 30-40% when s is an instance of
|
||||||
# six.text_type. This function gets called often in that setting.
|
# text_type. This function gets called often in that setting.
|
||||||
if isinstance(s, six.text_type):
|
if isinstance(s, text_type):
|
||||||
return s
|
return s
|
||||||
if strings_only and is_protected_type(s):
|
if strings_only and is_protected_type(s):
|
||||||
return s
|
return s
|
||||||
try:
|
try:
|
||||||
if not isinstance(s, six.string_types):
|
if not isinstance(s, string_types):
|
||||||
if hasattr(s, '__unicode__'):
|
if hasattr(s, '__unicode__'):
|
||||||
s = s.__unicode__()
|
s = s.__unicode__()
|
||||||
else:
|
else:
|
||||||
if six.PY3:
|
if not PY2:
|
||||||
if isinstance(s, bytes):
|
if isinstance(s, bytes):
|
||||||
s = six.text_type(s, encoding, errors)
|
s = text_type(s, encoding, errors)
|
||||||
else:
|
else:
|
||||||
s = six.text_type(s)
|
s = text_type(s)
|
||||||
else:
|
else:
|
||||||
s = six.text_type(bytes(s), encoding, errors)
|
s = text_type(bytes(s), encoding, errors)
|
||||||
else:
|
else:
|
||||||
# Note: We use .decode() here, instead of six.text_type(s, encoding,
|
# Note: We use .decode() here, instead of text_type(s, encoding,
|
||||||
# errors), so that if s is a SafeBytes, it ends up being a
|
# errors), so that if s is a SafeBytes, it ends up being a
|
||||||
# SafeText at the end.
|
# SafeText at the end.
|
||||||
s = s.decode(encoding, errors)
|
s = s.decode(encoding, errors)
|
||||||
|
@ -69,19 +71,20 @@ def force_text(s, encoding='utf-8', strings_only=False, errors='strict'):
|
||||||
|
|
||||||
def transform(value):
|
def transform(value):
|
||||||
from raven.utils.serializer import transform
|
from raven.utils.serializer import transform
|
||||||
warnings.warn('You should switch to raven.utils.serializer.transform', DeprecationWarning)
|
warnings.warn('You should switch to raven.utils.serializer.'
|
||||||
|
'transform', DeprecationWarning)
|
||||||
|
|
||||||
return transform(value)
|
return transform(value)
|
||||||
|
|
||||||
|
|
||||||
def to_unicode(value):
|
def to_unicode(value):
|
||||||
try:
|
try:
|
||||||
value = six.text_type(force_text(value))
|
value = text_type(force_text(value))
|
||||||
except (UnicodeEncodeError, UnicodeDecodeError):
|
except (UnicodeEncodeError, UnicodeDecodeError):
|
||||||
value = '(Error decoding value)'
|
value = '(Error decoding value)'
|
||||||
except Exception: # in some cases we get a different exception
|
except Exception: # in some cases we get a different exception
|
||||||
try:
|
try:
|
||||||
value = six.binary_type(repr(type(value)))
|
value = binary_type(repr(type(value)))
|
||||||
except Exception:
|
except Exception:
|
||||||
value = '(Error decoding value)'
|
value = '(Error decoding value)'
|
||||||
return value
|
return value
|
||||||
|
@ -89,6 +92,6 @@ def to_unicode(value):
|
||||||
|
|
||||||
def to_string(value):
|
def to_string(value):
|
||||||
try:
|
try:
|
||||||
return six.binary_type(value.decode('utf-8').encode('utf-8'))
|
return binary_type(value.decode('utf-8').encode('utf-8'))
|
||||||
except:
|
except:
|
||||||
return to_unicode(value).encode('utf-8')
|
return to_unicode(value).encode('utf-8')
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
from . import six
|
from raven._compat import PY2
|
||||||
|
|
||||||
|
|
||||||
def import_string(key):
|
def import_string(key):
|
||||||
# HACK(dcramer): Ensure a unicode key is still importable
|
# HACK(dcramer): Ensure a unicode key is still importable
|
||||||
if not six.PY3:
|
if PY2:
|
||||||
key = str(key)
|
key = str(key)
|
||||||
|
|
||||||
if '.' not in key:
|
if '.' not in key:
|
||||||
|
|
|
@ -11,7 +11,8 @@ from __future__ import absolute_import
|
||||||
import itertools
|
import itertools
|
||||||
import types
|
import types
|
||||||
|
|
||||||
from raven.utils import six
|
from raven._compat import text_type, binary_type, string_types, iteritems, \
|
||||||
|
class_types, PY2
|
||||||
from raven.utils.encoding import to_unicode
|
from raven.utils.encoding import to_unicode
|
||||||
from .manager import manager as serialization_manager
|
from .manager import manager as serialization_manager
|
||||||
|
|
||||||
|
@ -54,13 +55,14 @@ class Serializer(object):
|
||||||
_depth += 1
|
_depth += 1
|
||||||
if _depth >= max_depth:
|
if _depth >= max_depth:
|
||||||
try:
|
try:
|
||||||
value = six.text_type(repr(value))[:string_max_length]
|
value = text_type(repr(value))[:string_max_length]
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
import traceback
|
import traceback
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
self.manager.logger.exception(e)
|
self.manager.logger.exception(e)
|
||||||
return six.text_type(type(value))
|
return text_type(type(value))
|
||||||
return self.manager.transform(value, max_depth=max_depth, _depth=_depth, **kwargs)
|
return self.manager.transform(value, max_depth=max_depth,
|
||||||
|
_depth=_depth, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class IterableSerializer(Serializer):
|
class IterableSerializer(Serializer):
|
||||||
|
@ -71,7 +73,8 @@ class IterableSerializer(Serializer):
|
||||||
return tuple(
|
return tuple(
|
||||||
self.recurse(o, **kwargs)
|
self.recurse(o, **kwargs)
|
||||||
for n, o
|
for n, o
|
||||||
in itertools.takewhile(lambda x: x[0] < list_max_length, enumerate(value))
|
in itertools.takewhile(lambda x: x[0] < list_max_length,
|
||||||
|
enumerate(value))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -79,7 +82,7 @@ class DictSerializer(Serializer):
|
||||||
types = (dict,)
|
types = (dict,)
|
||||||
|
|
||||||
def make_key(self, key):
|
def make_key(self, key):
|
||||||
if not isinstance(key, six.string_types):
|
if not isinstance(key, string_types):
|
||||||
return to_unicode(key)
|
return to_unicode(key)
|
||||||
return key
|
return key
|
||||||
|
|
||||||
|
@ -88,12 +91,13 @@ class DictSerializer(Serializer):
|
||||||
return dict(
|
return dict(
|
||||||
(self.make_key(self.recurse(k, **kwargs)), self.recurse(v, **kwargs))
|
(self.make_key(self.recurse(k, **kwargs)), self.recurse(v, **kwargs))
|
||||||
for n, (k, v)
|
for n, (k, v)
|
||||||
in itertools.takewhile(lambda x: x[0] < list_max_length, enumerate(six.iteritems(value)))
|
in itertools.takewhile(lambda x: x[0] < list_max_length, enumerate(
|
||||||
|
iteritems(value)))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class UnicodeSerializer(Serializer):
|
class UnicodeSerializer(Serializer):
|
||||||
types = (six.text_type,)
|
types = (text_type,)
|
||||||
|
|
||||||
def serialize(self, value, **kwargs):
|
def serialize(self, value, **kwargs):
|
||||||
# try to return a reasonable string that can be decoded
|
# try to return a reasonable string that can be decoded
|
||||||
|
@ -101,21 +105,22 @@ class UnicodeSerializer(Serializer):
|
||||||
# unicode character
|
# unicode character
|
||||||
# e.g. we want the output to be like: "u'רונית מגן'"
|
# e.g. we want the output to be like: "u'רונית מגן'"
|
||||||
string_max_length = kwargs.get('string_max_length', None)
|
string_max_length = kwargs.get('string_max_length', None)
|
||||||
return repr(six.text_type('%s')) % (value[:string_max_length],)
|
return repr(text_type('%s')) % (value[:string_max_length],)
|
||||||
|
|
||||||
|
|
||||||
class StringSerializer(Serializer):
|
class StringSerializer(Serializer):
|
||||||
types = (six.binary_type,)
|
types = (binary_type,)
|
||||||
|
|
||||||
def serialize(self, value, **kwargs):
|
def serialize(self, value, **kwargs):
|
||||||
string_max_length = kwargs.get('string_max_length', None)
|
string_max_length = kwargs.get('string_max_length', None)
|
||||||
if six.PY3:
|
if not PY2:
|
||||||
return repr(value[:string_max_length])
|
return repr(value[:string_max_length])
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Python2 madness: let's try to recover from developer's issues
|
# Python2 madness: let's try to recover from developer's issues
|
||||||
# Try to process the string as if it was a unicode.
|
# Try to process the string as if it was a unicode.
|
||||||
return "'" + value.decode('utf8')[:string_max_length].encode('utf8') + "'"
|
return "'" + value.decode('utf8')[:string_max_length] \
|
||||||
|
.encode('utf8') + "'"
|
||||||
except UnicodeDecodeError:
|
except UnicodeDecodeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -123,10 +128,11 @@ class StringSerializer(Serializer):
|
||||||
|
|
||||||
|
|
||||||
class TypeSerializer(Serializer):
|
class TypeSerializer(Serializer):
|
||||||
types = six.class_types
|
types = class_types
|
||||||
|
|
||||||
def can(self, value):
|
def can(self, value):
|
||||||
return not super(TypeSerializer, self).can(value) and has_sentry_metadata(value)
|
return not super(TypeSerializer, self).can(value) \
|
||||||
|
and has_sentry_metadata(value)
|
||||||
|
|
||||||
def serialize(self, value, **kwargs):
|
def serialize(self, value, **kwargs):
|
||||||
return self.recurse(value.__sentry__(), **kwargs)
|
return self.recurse(value.__sentry__(), **kwargs)
|
||||||
|
@ -157,10 +163,11 @@ class FunctionSerializer(Serializer):
|
||||||
types = (types.FunctionType,)
|
types = (types.FunctionType,)
|
||||||
|
|
||||||
def serialize(self, value, **kwargs):
|
def serialize(self, value, **kwargs):
|
||||||
return '<function %s from %s at 0x%x>' % (value.__name__, value.__module__, id(value))
|
return '<function %s from %s at 0x%x>' % (
|
||||||
|
value.__name__, value.__module__, id(value))
|
||||||
|
|
||||||
|
|
||||||
if not six.PY3:
|
if PY2:
|
||||||
class LongSerializer(Serializer):
|
class LongSerializer(Serializer):
|
||||||
types = (long,) # noqa
|
types = (long,) # noqa
|
||||||
|
|
||||||
|
@ -178,5 +185,5 @@ serialization_manager.register(BooleanSerializer)
|
||||||
serialization_manager.register(FloatSerializer)
|
serialization_manager.register(FloatSerializer)
|
||||||
serialization_manager.register(IntegerSerializer)
|
serialization_manager.register(IntegerSerializer)
|
||||||
serialization_manager.register(FunctionSerializer)
|
serialization_manager.register(FunctionSerializer)
|
||||||
if not six.PY3:
|
if PY2:
|
||||||
serialization_manager.register(LongSerializer)
|
serialization_manager.register(LongSerializer)
|
||||||
|
|
|
@ -9,7 +9,7 @@ from __future__ import absolute_import
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from contextlib import closing
|
from contextlib import closing
|
||||||
from raven.utils import six
|
from raven._compat import text_type
|
||||||
|
|
||||||
__all__ = ('register', 'transform')
|
__all__ = ('register', 'transform')
|
||||||
|
|
||||||
|
@ -69,16 +69,18 @@ class Serializer(object):
|
||||||
return serializer.serialize(value, **kwargs)
|
return serializer.serialize(value, **kwargs)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception(e)
|
logger.exception(e)
|
||||||
return six.text_type(type(value))
|
return text_type(type(value))
|
||||||
|
|
||||||
# if all else fails, lets use the repr of the object
|
# if all else fails, lets use the repr of the object
|
||||||
try:
|
try:
|
||||||
return repr(value)
|
return repr(value)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception(e)
|
logger.exception(e)
|
||||||
# It's common case that a model's __unicode__ definition may try to query the database
|
# It's common case that a model's __unicode__ definition
|
||||||
# which if it was not cleaned up correctly, would hit a transaction aborted exception
|
# may try to query the database which if it was not
|
||||||
return six.text_type(type(value))
|
# cleaned up correctly, would hit a transaction aborted
|
||||||
|
# exception
|
||||||
|
return text_type(type(value))
|
||||||
finally:
|
finally:
|
||||||
self.context.remove(objid)
|
self.context.remove(objid)
|
||||||
|
|
||||||
|
|
|
@ -1,406 +0,0 @@
|
||||||
"""Utilities for writing code that runs on Python 2 and 3"""
|
|
||||||
# flake8: noqa
|
|
||||||
|
|
||||||
# Copyright (c) 2010-2013 Benjamin Peterson
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
||||||
# this software and associated documentation files (the "Software"), to deal in
|
|
||||||
# the Software without restriction, including without limitation the rights to
|
|
||||||
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
||||||
# the Software, and to permit persons to whom the Software is furnished to do so,
|
|
||||||
# subject to the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included in all
|
|
||||||
# copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
||||||
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
||||||
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
||||||
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
||||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
from __future__ import absolute_import
|
|
||||||
|
|
||||||
import operator
|
|
||||||
import sys
|
|
||||||
import types
|
|
||||||
|
|
||||||
__author__ = "Benjamin Peterson <benjamin@python.org>"
|
|
||||||
__version__ = "1.3.0"
|
|
||||||
|
|
||||||
|
|
||||||
# True if we are running on Python 3.
|
|
||||||
PY3 = sys.version_info[0] == 3
|
|
||||||
|
|
||||||
if PY3:
|
|
||||||
string_types = str,
|
|
||||||
integer_types = int,
|
|
||||||
class_types = type,
|
|
||||||
text_type = str
|
|
||||||
binary_type = bytes
|
|
||||||
|
|
||||||
MAXSIZE = sys.maxsize
|
|
||||||
else:
|
|
||||||
string_types = basestring,
|
|
||||||
integer_types = (int, long)
|
|
||||||
class_types = (type, types.ClassType)
|
|
||||||
text_type = unicode
|
|
||||||
binary_type = str
|
|
||||||
|
|
||||||
if sys.platform.startswith("java"):
|
|
||||||
# Jython always uses 32 bits.
|
|
||||||
MAXSIZE = int((1 << 31) - 1)
|
|
||||||
else:
|
|
||||||
# It's possible to have sizeof(long) != sizeof(Py_ssize_t).
|
|
||||||
class X(object):
|
|
||||||
def __len__(self):
|
|
||||||
return 1 << 31
|
|
||||||
try:
|
|
||||||
len(X())
|
|
||||||
except OverflowError:
|
|
||||||
# 32-bit
|
|
||||||
MAXSIZE = int((1 << 31) - 1)
|
|
||||||
else:
|
|
||||||
# 64-bit
|
|
||||||
MAXSIZE = int((1 << 63) - 1)
|
|
||||||
del X
|
|
||||||
|
|
||||||
|
|
||||||
def _add_doc(func, doc):
|
|
||||||
"""Add documentation to a function."""
|
|
||||||
func.__doc__ = doc
|
|
||||||
|
|
||||||
|
|
||||||
def _import_module(name):
|
|
||||||
"""Import module, returning the module after the last dot."""
|
|
||||||
__import__(name)
|
|
||||||
return sys.modules[name]
|
|
||||||
|
|
||||||
|
|
||||||
class _LazyDescr(object):
|
|
||||||
|
|
||||||
def __init__(self, name):
|
|
||||||
self.name = name
|
|
||||||
|
|
||||||
def __get__(self, obj, tp):
|
|
||||||
result = self._resolve()
|
|
||||||
setattr(obj, self.name, result)
|
|
||||||
# This is a bit ugly, but it avoids running this again.
|
|
||||||
delattr(tp, self.name)
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
class MovedModule(_LazyDescr):
|
|
||||||
|
|
||||||
def __init__(self, name, old, new=None):
|
|
||||||
super(MovedModule, self).__init__(name)
|
|
||||||
if PY3:
|
|
||||||
if new is None:
|
|
||||||
new = name
|
|
||||||
self.mod = new
|
|
||||||
else:
|
|
||||||
self.mod = old
|
|
||||||
|
|
||||||
def _resolve(self):
|
|
||||||
return _import_module(self.mod)
|
|
||||||
|
|
||||||
|
|
||||||
class MovedAttribute(_LazyDescr):
|
|
||||||
|
|
||||||
def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None):
|
|
||||||
super(MovedAttribute, self).__init__(name)
|
|
||||||
if PY3:
|
|
||||||
if new_mod is None:
|
|
||||||
new_mod = name
|
|
||||||
self.mod = new_mod
|
|
||||||
if new_attr is None:
|
|
||||||
if old_attr is None:
|
|
||||||
new_attr = name
|
|
||||||
else:
|
|
||||||
new_attr = old_attr
|
|
||||||
self.attr = new_attr
|
|
||||||
else:
|
|
||||||
self.mod = old_mod
|
|
||||||
if old_attr is None:
|
|
||||||
old_attr = name
|
|
||||||
self.attr = old_attr
|
|
||||||
|
|
||||||
def _resolve(self):
|
|
||||||
module = _import_module(self.mod)
|
|
||||||
return getattr(module, self.attr)
|
|
||||||
|
|
||||||
|
|
||||||
class _MovedItems(types.ModuleType):
|
|
||||||
"""Lazy loading of moved objects"""
|
|
||||||
|
|
||||||
|
|
||||||
_moved_attributes = [
|
|
||||||
MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"),
|
|
||||||
MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"),
|
|
||||||
MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"),
|
|
||||||
MovedAttribute("map", "itertools", "builtins", "imap", "map"),
|
|
||||||
MovedAttribute("reload_module", "__builtin__", "imp", "reload"),
|
|
||||||
MovedAttribute("reduce", "__builtin__", "functools"),
|
|
||||||
MovedAttribute("StringIO", "StringIO", "io"),
|
|
||||||
MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"),
|
|
||||||
MovedAttribute("zip", "itertools", "builtins", "izip", "zip"),
|
|
||||||
|
|
||||||
MovedModule("builtins", "__builtin__"),
|
|
||||||
MovedModule("configparser", "ConfigParser"),
|
|
||||||
MovedModule("copyreg", "copy_reg"),
|
|
||||||
MovedModule("http_cookiejar", "cookielib", "http.cookiejar"),
|
|
||||||
MovedModule("http_cookies", "Cookie", "http.cookies"),
|
|
||||||
MovedModule("html_entities", "htmlentitydefs", "html.entities"),
|
|
||||||
MovedModule("html_parser", "HTMLParser", "html.parser"),
|
|
||||||
MovedModule("http_client", "httplib", "http.client"),
|
|
||||||
MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"),
|
|
||||||
MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"),
|
|
||||||
MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"),
|
|
||||||
MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"),
|
|
||||||
MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"),
|
|
||||||
MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"),
|
|
||||||
MovedModule("cPickle", "cPickle", "pickle"),
|
|
||||||
MovedModule("queue", "Queue"),
|
|
||||||
MovedModule("reprlib", "repr"),
|
|
||||||
MovedModule("socketserver", "SocketServer"),
|
|
||||||
MovedModule("tkinter", "Tkinter"),
|
|
||||||
MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"),
|
|
||||||
MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"),
|
|
||||||
MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"),
|
|
||||||
MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"),
|
|
||||||
MovedModule("tkinter_tix", "Tix", "tkinter.tix"),
|
|
||||||
MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"),
|
|
||||||
MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"),
|
|
||||||
MovedModule("tkinter_colorchooser", "tkColorChooser",
|
|
||||||
"tkinter.colorchooser"),
|
|
||||||
MovedModule("tkinter_commondialog", "tkCommonDialog",
|
|
||||||
"tkinter.commondialog"),
|
|
||||||
MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"),
|
|
||||||
MovedModule("tkinter_font", "tkFont", "tkinter.font"),
|
|
||||||
MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"),
|
|
||||||
MovedModule("tkinter_tksimpledialog", "tkSimpleDialog",
|
|
||||||
"tkinter.simpledialog"),
|
|
||||||
MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"),
|
|
||||||
MovedModule("winreg", "_winreg"),
|
|
||||||
]
|
|
||||||
for attr in _moved_attributes:
|
|
||||||
setattr(_MovedItems, attr.name, attr)
|
|
||||||
del attr
|
|
||||||
|
|
||||||
moves = sys.modules[__name__ + ".moves"] = _MovedItems("moves")
|
|
||||||
|
|
||||||
|
|
||||||
def add_move(move):
|
|
||||||
"""Add an item to six.moves."""
|
|
||||||
setattr(_MovedItems, move.name, move)
|
|
||||||
|
|
||||||
|
|
||||||
def remove_move(name):
|
|
||||||
"""Remove item from six.moves."""
|
|
||||||
try:
|
|
||||||
delattr(_MovedItems, name)
|
|
||||||
except AttributeError:
|
|
||||||
try:
|
|
||||||
del moves.__dict__[name]
|
|
||||||
except KeyError:
|
|
||||||
raise AttributeError("no such move, %r" % (name,))
|
|
||||||
|
|
||||||
|
|
||||||
if PY3:
|
|
||||||
_meth_func = "__func__"
|
|
||||||
_meth_self = "__self__"
|
|
||||||
|
|
||||||
_func_closure = "__closure__"
|
|
||||||
_func_code = "__code__"
|
|
||||||
_func_defaults = "__defaults__"
|
|
||||||
_func_globals = "__globals__"
|
|
||||||
|
|
||||||
_iterkeys = "keys"
|
|
||||||
_itervalues = "values"
|
|
||||||
_iteritems = "items"
|
|
||||||
_iterlists = "lists"
|
|
||||||
else:
|
|
||||||
_meth_func = "im_func"
|
|
||||||
_meth_self = "im_self"
|
|
||||||
|
|
||||||
_func_closure = "func_closure"
|
|
||||||
_func_code = "func_code"
|
|
||||||
_func_defaults = "func_defaults"
|
|
||||||
_func_globals = "func_globals"
|
|
||||||
|
|
||||||
_iterkeys = "iterkeys"
|
|
||||||
_itervalues = "itervalues"
|
|
||||||
_iteritems = "iteritems"
|
|
||||||
_iterlists = "iterlists"
|
|
||||||
|
|
||||||
|
|
||||||
try:
|
|
||||||
advance_iterator = next
|
|
||||||
except NameError:
|
|
||||||
def advance_iterator(it):
|
|
||||||
return it.next()
|
|
||||||
next = advance_iterator
|
|
||||||
|
|
||||||
|
|
||||||
try:
|
|
||||||
callable = callable
|
|
||||||
except NameError:
|
|
||||||
def callable(obj):
|
|
||||||
return any("__call__" in klass.__dict__ for klass in type(obj).__mro__)
|
|
||||||
|
|
||||||
if PY3:
|
|
||||||
def get_unbound_function(unbound):
|
|
||||||
return unbound
|
|
||||||
|
|
||||||
Iterator = object
|
|
||||||
else:
|
|
||||||
def get_unbound_function(unbound): # NOQA
|
|
||||||
return unbound.im_func
|
|
||||||
|
|
||||||
class Iterator(object):
|
|
||||||
|
|
||||||
def next(self):
|
|
||||||
return type(self).__next__(self)
|
|
||||||
|
|
||||||
callable = callable
|
|
||||||
_add_doc(get_unbound_function,
|
|
||||||
"""Get the function out of a possibly unbound function""")
|
|
||||||
|
|
||||||
|
|
||||||
get_method_function = operator.attrgetter(_meth_func)
|
|
||||||
get_method_self = operator.attrgetter(_meth_self)
|
|
||||||
get_function_closure = operator.attrgetter(_func_closure)
|
|
||||||
get_function_code = operator.attrgetter(_func_code)
|
|
||||||
get_function_defaults = operator.attrgetter(_func_defaults)
|
|
||||||
get_function_globals = operator.attrgetter(_func_globals)
|
|
||||||
|
|
||||||
|
|
||||||
def iterkeys(d, **kw):
|
|
||||||
"""Return an iterator over the keys of a dictionary."""
|
|
||||||
return iter(getattr(d, _iterkeys)(**kw))
|
|
||||||
|
|
||||||
|
|
||||||
def itervalues(d, **kw):
|
|
||||||
"""Return an iterator over the values of a dictionary."""
|
|
||||||
return iter(getattr(d, _itervalues)(**kw))
|
|
||||||
|
|
||||||
|
|
||||||
def iteritems(d, **kw):
|
|
||||||
"""Return an iterator over the (key, value) pairs of a dictionary."""
|
|
||||||
return iter(getattr(d, _iteritems)(**kw))
|
|
||||||
|
|
||||||
|
|
||||||
def iterlists(d, **kw):
|
|
||||||
"""Return an iterator over the (key, [values]) pairs of a dictionary."""
|
|
||||||
return iter(getattr(d, _iterlists)(**kw))
|
|
||||||
|
|
||||||
|
|
||||||
if PY3:
|
|
||||||
def b(s):
|
|
||||||
return s.encode("latin-1")
|
|
||||||
|
|
||||||
def u(s):
|
|
||||||
return s
|
|
||||||
if sys.version_info[1] <= 1:
|
|
||||||
def int2byte(i):
|
|
||||||
return bytes((i,))
|
|
||||||
else:
|
|
||||||
# This is about 2x faster than the implementation above on 3.2+
|
|
||||||
int2byte = operator.methodcaller("to_bytes", 1, "big")
|
|
||||||
import io
|
|
||||||
StringIO = io.StringIO
|
|
||||||
BytesIO = io.BytesIO
|
|
||||||
else:
|
|
||||||
def b(s): # NOQA
|
|
||||||
return s
|
|
||||||
|
|
||||||
def u(s): # NOQA
|
|
||||||
return unicode(s, "unicode_escape")
|
|
||||||
int2byte = chr
|
|
||||||
import StringIO
|
|
||||||
StringIO = BytesIO = StringIO.StringIO
|
|
||||||
_add_doc(b, """Byte literal""")
|
|
||||||
_add_doc(u, """Text literal""")
|
|
||||||
|
|
||||||
|
|
||||||
if PY3:
|
|
||||||
import builtins
|
|
||||||
exec_ = getattr(builtins, "exec")
|
|
||||||
|
|
||||||
def reraise(tp, value, tb=None):
|
|
||||||
if value.__traceback__ is not tb:
|
|
||||||
raise value.with_traceback(tb)
|
|
||||||
raise value
|
|
||||||
|
|
||||||
print_ = getattr(builtins, "print")
|
|
||||||
del builtins
|
|
||||||
|
|
||||||
else:
|
|
||||||
def exec_(_code_, _globs_=None, _locs_=None):
|
|
||||||
"""Execute code in a namespace."""
|
|
||||||
if _globs_ is None:
|
|
||||||
frame = sys._getframe(1)
|
|
||||||
_globs_ = frame.f_globals
|
|
||||||
if _locs_ is None:
|
|
||||||
_locs_ = frame.f_locals
|
|
||||||
del frame
|
|
||||||
elif _locs_ is None:
|
|
||||||
_locs_ = _globs_
|
|
||||||
exec("""exec _code_ in _globs_, _locs_""")
|
|
||||||
|
|
||||||
exec_("""def reraise(tp, value, tb=None):
|
|
||||||
raise tp, value, tb
|
|
||||||
""")
|
|
||||||
|
|
||||||
def print_(*args, **kwargs):
|
|
||||||
"""The new-style print function."""
|
|
||||||
fp = kwargs.pop("file", sys.stdout)
|
|
||||||
if fp is None:
|
|
||||||
return
|
|
||||||
|
|
||||||
def write(data):
|
|
||||||
if not isinstance(data, basestring):
|
|
||||||
data = str(data)
|
|
||||||
fp.write(data)
|
|
||||||
want_unicode = False
|
|
||||||
sep = kwargs.pop("sep", None)
|
|
||||||
if sep is not None:
|
|
||||||
if isinstance(sep, unicode):
|
|
||||||
want_unicode = True
|
|
||||||
elif not isinstance(sep, str):
|
|
||||||
raise TypeError("sep must be None or a string")
|
|
||||||
end = kwargs.pop("end", None)
|
|
||||||
if end is not None:
|
|
||||||
if isinstance(end, unicode):
|
|
||||||
want_unicode = True
|
|
||||||
elif not isinstance(end, str):
|
|
||||||
raise TypeError("end must be None or a string")
|
|
||||||
if kwargs:
|
|
||||||
raise TypeError("invalid keyword arguments to print()")
|
|
||||||
if not want_unicode:
|
|
||||||
for arg in args:
|
|
||||||
if isinstance(arg, unicode):
|
|
||||||
want_unicode = True
|
|
||||||
break
|
|
||||||
if want_unicode:
|
|
||||||
newline = unicode("\n")
|
|
||||||
space = unicode(" ")
|
|
||||||
else:
|
|
||||||
newline = "\n"
|
|
||||||
space = " "
|
|
||||||
if sep is None:
|
|
||||||
sep = space
|
|
||||||
if end is None:
|
|
||||||
end = newline
|
|
||||||
for i, arg in enumerate(args):
|
|
||||||
if i:
|
|
||||||
write(sep)
|
|
||||||
write(arg)
|
|
||||||
write(end)
|
|
||||||
|
|
||||||
_add_doc(reraise, """Reraise an exception.""")
|
|
||||||
|
|
||||||
|
|
||||||
def with_metaclass(meta, base=object):
|
|
||||||
"""Create a base class with a metaclass."""
|
|
||||||
return meta("NewBase", (base,), {})
|
|
|
@ -14,13 +14,14 @@ import sys
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
from raven.utils.serializer import transform
|
from raven.utils.serializer import transform
|
||||||
from raven.utils import six
|
from raven._compat import iteritems
|
||||||
|
|
||||||
|
|
||||||
_coding_re = re.compile(r'coding[:=]\s*([-\w.]+)')
|
_coding_re = re.compile(r'coding[:=]\s*([-\w.]+)')
|
||||||
|
|
||||||
|
|
||||||
def get_lines_from_file(filename, lineno, context_lines, loader=None, module_name=None):
|
def get_lines_from_file(filename, lineno, context_lines,
|
||||||
|
loader=None, module_name=None):
|
||||||
"""
|
"""
|
||||||
Returns context_lines before and after lineno from file.
|
Returns context_lines before and after lineno from file.
|
||||||
Returns (pre_context_lineno, pre_context, context_line, post_context).
|
Returns (pre_context_lineno, pre_context, context_line, post_context).
|
||||||
|
@ -63,7 +64,8 @@ def get_lines_from_file(filename, lineno, context_lines, loader=None, module_nam
|
||||||
try:
|
try:
|
||||||
pre_context = [line.strip('\r\n') for line in source[lower_bound:lineno]]
|
pre_context = [line.strip('\r\n') for line in source[lower_bound:lineno]]
|
||||||
context_line = source[lineno].strip('\r\n')
|
context_line = source[lineno].strip('\r\n')
|
||||||
post_context = [line.strip('\r\n') for line in source[(lineno + 1):upper_bound]]
|
post_context = [line.strip('\r\n') for line in
|
||||||
|
source[(lineno + 1):upper_bound]]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
# the file may have changed since it was loaded into memory
|
# the file may have changed since it was loaded into memory
|
||||||
return None, None, None
|
return None, None, None
|
||||||
|
@ -178,7 +180,7 @@ def get_frame_locals(frame, transformer=transform, max_var_size=4096):
|
||||||
|
|
||||||
f_vars = {}
|
f_vars = {}
|
||||||
f_size = 0
|
f_size = 0
|
||||||
for k, v in six.iteritems(f_locals):
|
for k, v in iteritems(f_locals):
|
||||||
v = transformer(v)
|
v = transformer(v)
|
||||||
v_size = len(repr(v))
|
v_size = len(repr(v))
|
||||||
if v_size + f_size < 4096:
|
if v_size + f_size < 4096:
|
||||||
|
@ -253,7 +255,8 @@ def get_stack_info(frames, transformer=transform, capture_locals=True,
|
||||||
lineno -= 1
|
lineno -= 1
|
||||||
|
|
||||||
if lineno is not None and abs_path:
|
if lineno is not None and abs_path:
|
||||||
pre_context, context_line, post_context = get_lines_from_file(abs_path, lineno, 5, loader, module_name)
|
pre_context, context_line, post_context = \
|
||||||
|
get_lines_from_file(abs_path, lineno, 5, loader, module_name)
|
||||||
else:
|
else:
|
||||||
pre_context, context_line, post_context = None, None, None
|
pre_context, context_line, post_context = None, None, None
|
||||||
|
|
||||||
|
@ -261,7 +264,8 @@ def get_stack_info(frames, transformer=transform, capture_locals=True,
|
||||||
# This changes /foo/site-packages/baz/bar.py into baz/bar.py
|
# This changes /foo/site-packages/baz/bar.py into baz/bar.py
|
||||||
try:
|
try:
|
||||||
base_filename = sys.modules[module_name.split('.', 1)[0]].__file__
|
base_filename = sys.modules[module_name.split('.', 1)[0]].__file__
|
||||||
filename = abs_path.split(base_filename.rsplit('/', 2)[0], 1)[-1].lstrip("/")
|
filename = abs_path.split(
|
||||||
|
base_filename.rsplit('/', 2)[0], 1)[-1].lstrip("/")
|
||||||
except:
|
except:
|
||||||
filename = abs_path
|
filename = abs_path
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ This module implements WSGI related helpers adapted from ``werkzeug.wsgi``
|
||||||
"""
|
"""
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
from raven.utils import six
|
from raven._compat import iteritems
|
||||||
from raven.utils.compat import urllib_quote
|
from raven.utils.compat import urllib_quote
|
||||||
|
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ def get_headers(environ):
|
||||||
"""
|
"""
|
||||||
Returns only proper HTTP headers.
|
Returns only proper HTTP headers.
|
||||||
"""
|
"""
|
||||||
for key, value in six.iteritems(environ):
|
for key, value in iteritems(environ):
|
||||||
key = str(key)
|
key = str(key)
|
||||||
if key.startswith('HTTP_') and key not in \
|
if key.startswith('HTTP_') and key not in \
|
||||||
('HTTP_CONTENT_TYPE', 'HTTP_CONTENT_LENGTH'):
|
('HTTP_CONTENT_TYPE', 'HTTP_CONTENT_LENGTH'):
|
||||||
|
|
|
@ -8,8 +8,7 @@ except ImportError:
|
||||||
# pkg_resource is not available on Google App Engine
|
# pkg_resource is not available on Google App Engine
|
||||||
pkg_resources = None
|
pkg_resources = None
|
||||||
|
|
||||||
from raven.utils import six
|
from raven._compat import text_type
|
||||||
|
|
||||||
from .exceptions import InvalidGitRepository
|
from .exceptions import InvalidGitRepository
|
||||||
|
|
||||||
__all__ = ('fetch_git_sha', 'fetch_package_version')
|
__all__ = ('fetch_git_sha', 'fetch_package_version')
|
||||||
|
@ -22,10 +21,11 @@ def fetch_git_sha(path, head=None):
|
||||||
if not head:
|
if not head:
|
||||||
head_path = os.path.join(path, '.git', 'HEAD')
|
head_path = os.path.join(path, '.git', 'HEAD')
|
||||||
if not os.path.exists(head_path):
|
if not os.path.exists(head_path):
|
||||||
raise InvalidGitRepository('Cannot identify HEAD for git repository at %s' % (path,))
|
raise InvalidGitRepository(
|
||||||
|
'Cannot identify HEAD for git repository at %s' % (path,))
|
||||||
|
|
||||||
with open(head_path, 'r') as fp:
|
with open(head_path, 'r') as fp:
|
||||||
head = six.text_type(fp.read()).strip()
|
head = text_type(fp.read()).strip()
|
||||||
|
|
||||||
if head.startswith('ref: '):
|
if head.startswith('ref: '):
|
||||||
revision_file = os.path.join(
|
revision_file = os.path.join(
|
||||||
|
@ -38,12 +38,14 @@ def fetch_git_sha(path, head=None):
|
||||||
|
|
||||||
if not os.path.exists(revision_file):
|
if not os.path.exists(revision_file):
|
||||||
if not os.path.exists(os.path.join(path, '.git')):
|
if not os.path.exists(os.path.join(path, '.git')):
|
||||||
raise InvalidGitRepository('%s does not seem to be the root of a git repository' % (path,))
|
raise InvalidGitRepository(
|
||||||
raise InvalidGitRepository('Unable to find ref to head "%s" in repository' % (head,))
|
'%s does not seem to be the root of a git repository' % (path,))
|
||||||
|
raise InvalidGitRepository(
|
||||||
|
'Unable to find ref to head "%s" in repository' % (head,))
|
||||||
|
|
||||||
fh = open(revision_file, 'r')
|
fh = open(revision_file, 'r')
|
||||||
try:
|
try:
|
||||||
return six.text_type(fh.read()).strip()
|
return text_type(fh.read()).strip()
|
||||||
finally:
|
finally:
|
||||||
fh.close()
|
fh.close()
|
||||||
|
|
||||||
|
@ -53,6 +55,7 @@ def fetch_package_version(dist_name):
|
||||||
>>> fetch_package_version('sentry')
|
>>> fetch_package_version('sentry')
|
||||||
"""
|
"""
|
||||||
if pkg_resources is None:
|
if pkg_resources is None:
|
||||||
raise NotImplementedError('pkg_resources is not available on this Python install')
|
raise NotImplementedError('pkg_resources is not available '
|
||||||
|
'on this Python install')
|
||||||
dist = pkg_resources.get_distribution(dist_name)
|
dist = pkg_resources.get_distribution(dist_name)
|
||||||
return dist.version
|
return dist.version
|
||||||
|
|
1
setup.py
1
setup.py
|
@ -53,6 +53,7 @@ if sys.version_info[0] == 3:
|
||||||
install_requires.remove('contextlib2')
|
install_requires.remove('contextlib2')
|
||||||
|
|
||||||
tests_require = [
|
tests_require = [
|
||||||
|
'six',
|
||||||
'bottle',
|
'bottle',
|
||||||
'celery>=2.5',
|
'celery>=2.5',
|
||||||
'Django>=1.4',
|
'Django>=1.4',
|
||||||
|
|
|
@ -5,13 +5,13 @@ import inspect
|
||||||
import mock
|
import mock
|
||||||
import raven
|
import raven
|
||||||
import time
|
import time
|
||||||
|
import six
|
||||||
|
|
||||||
from raven.base import Client, ClientState
|
from raven.base import Client, ClientState
|
||||||
from raven.exceptions import RateLimited
|
from raven.exceptions import RateLimited
|
||||||
from raven.transport import AsyncTransport
|
from raven.transport import AsyncTransport
|
||||||
from raven.transport.http import HTTPTransport
|
from raven.transport.http import HTTPTransport
|
||||||
from raven.utils.stacks import iter_stack_frames
|
from raven.utils.stacks import iter_stack_frames
|
||||||
from raven.utils import six
|
|
||||||
from raven.utils.testutils import TestCase
|
from raven.utils.testutils import TestCase
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,10 @@ import logging
|
||||||
import mock
|
import mock
|
||||||
import pytest
|
import pytest
|
||||||
import re
|
import re
|
||||||
|
import six
|
||||||
import sys # NOQA
|
import sys # NOQA
|
||||||
from exam import fixture
|
from exam import fixture
|
||||||
|
from six import StringIO
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
|
@ -33,8 +35,6 @@ from raven.contrib.django.templatetags.raven import sentry_public_dsn
|
||||||
from raven.contrib.django.views import is_valid_origin
|
from raven.contrib.django.views import is_valid_origin
|
||||||
from raven.transport import HTTPTransport
|
from raven.transport import HTTPTransport
|
||||||
from raven.utils.serializer import transform
|
from raven.utils.serializer import transform
|
||||||
from raven.utils import six
|
|
||||||
from raven.utils.six import StringIO
|
|
||||||
|
|
||||||
from django.test.client import Client as TestClient, ClientHandler as TestClientHandler
|
from django.test.client import Client as TestClient, ClientHandler as TestClientHandler
|
||||||
from .models import TestModel
|
from .models import TestModel
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import six
|
||||||
from mock import patch
|
from mock import patch
|
||||||
from tornado import web, gen, testing
|
from tornado import web, gen, testing
|
||||||
from tornado.concurrent import Future
|
from tornado.concurrent import Future
|
||||||
from tornado.httpclient import HTTPError
|
from tornado.httpclient import HTTPError
|
||||||
from raven.contrib.tornado import SentryMixin, AsyncSentryClient
|
from raven.contrib.tornado import SentryMixin, AsyncSentryClient
|
||||||
from raven.utils import six
|
|
||||||
|
|
||||||
|
|
||||||
class AnErrorProneHandler(SentryMixin, web.RequestHandler):
|
class AnErrorProneHandler(SentryMixin, web.RequestHandler):
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
from __future__ import with_statement
|
from __future__ import with_statement
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import six
|
||||||
import logbook
|
import logbook
|
||||||
from raven.utils.testutils import TestCase
|
from raven.utils.testutils import TestCase
|
||||||
from raven.utils import six
|
|
||||||
from raven.base import Client
|
from raven.base import Client
|
||||||
from raven.handlers.logbook import SentryHandler
|
from raven.handlers.logbook import SentryHandler
|
||||||
|
|
||||||
|
|
|
@ -3,10 +3,10 @@ from __future__ import unicode_literals
|
||||||
import logging
|
import logging
|
||||||
import sys
|
import sys
|
||||||
import mock
|
import mock
|
||||||
|
import six
|
||||||
|
|
||||||
from raven.base import Client
|
from raven.base import Client
|
||||||
from raven.handlers.logging import SentryHandler
|
from raven.handlers.logging import SentryHandler
|
||||||
from raven.utils import six
|
|
||||||
from raven.utils.stacks import iter_stack_frames
|
from raven.utils.stacks import iter_stack_frames
|
||||||
from raven.utils.testutils import TestCase
|
from raven.utils.testutils import TestCase
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import pytest
|
import pytest
|
||||||
import uuid
|
import uuid
|
||||||
|
import six
|
||||||
|
|
||||||
from raven.utils import six, json
|
from raven.utils import json
|
||||||
from raven.utils.testutils import TestCase
|
from raven.utils.testutils import TestCase
|
||||||
from raven.utils.serializer import transform
|
from raven.utils.serializer import transform
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import six
|
||||||
|
|
||||||
from mock import Mock
|
from mock import Mock
|
||||||
from raven.utils.testutils import TestCase
|
from raven.utils.testutils import TestCase
|
||||||
from raven.utils import six
|
|
||||||
|
|
||||||
from raven.utils.stacks import get_culprit, get_stack_info, get_lines_from_file
|
from raven.utils.stacks import get_culprit, get_stack_info, get_lines_from_file
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
import six
|
||||||
|
|
||||||
import raven
|
import raven
|
||||||
|
|
||||||
from raven.utils import six
|
|
||||||
from raven.utils.imports import import_string
|
from raven.utils.imports import import_string
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3,11 +3,11 @@ from __future__ import absolute_import
|
||||||
import os.path
|
import os.path
|
||||||
import pytest
|
import pytest
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import six
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
from raven.versioning import fetch_git_sha, fetch_package_version
|
from raven.versioning import fetch_git_sha, fetch_package_version
|
||||||
from raven.utils import six
|
|
||||||
|
|
||||||
|
|
||||||
def has_git_requirements():
|
def has_git_requirements():
|
||||||
|
|
Loading…
Reference in New Issue