-
Notifications
You must be signed in to change notification settings - Fork 0
/
helpers.py
207 lines (179 loc) · 6.84 KB
/
helpers.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
import logging
import sys
import urllib
import urllib2
import uuid
from hashlib import md5
import django
from django.conf import settings
from django.utils.encoding import force_unicode
from sentry import conf
_FILTER_CACHE = None
def get_filters():
global _FILTER_CACHE
if _FILTER_CACHE is None:
filters = []
for filter_ in conf.FILTERS:
module_name, class_name = filter_.rsplit('.', 1)
try:
module = __import__(module_name, {}, {}, class_name)
filter_ = getattr(module, class_name)
except Exception:
logging.exception('Unable to import %s' % (filter_,))
continue
filters.append(filter_)
_FILTER_CACHE = filters
for f in _FILTER_CACHE:
yield f
def get_db_engine(alias='default'):
has_multidb = django.VERSION >= (1, 2)
if has_multidb:
value = settings.DATABASES[alias]['ENGINE']
else:
assert alias == 'default', 'You cannot fetch a database engine other than the default on Django < 1.2'
value = settings.DATABASE_ENGINE
return value.rsplit('.', 1)[-1]
def construct_checksum(level=logging.ERROR, class_name='', traceback='', message='', **kwargs):
checksum = md5(str(level))
checksum.update(class_name or '')
if traceback:
traceback = '\n'.join(traceback.split('\n')[:-3])
message = traceback or message
if isinstance(message, unicode):
message = message.encode('utf-8', 'replace')
checksum.update(message)
return checksum.hexdigest()
def varmap(func, var):
if isinstance(var, dict):
return dict((k, varmap(func, v)) for k, v in var.iteritems())
elif isinstance(var, (list, tuple)):
return [varmap(func, f) for f in var]
else:
return func(var)
def transform(value):
# TODO: make this extendable
# TODO: include some sane defaults, like UUID
# TODO: dont coerce strings to unicode, leave them as strings
if isinstance(value, (tuple, list, set, frozenset)):
return type(value)(transform(o) for o in value)
elif isinstance(value, uuid.UUID):
return repr(value)
elif isinstance(value, dict):
return dict((k, transform(v)) for k, v in value.iteritems())
elif isinstance(value, unicode):
return to_unicode(value)
elif isinstance(value, str):
try:
return str(value)
except:
return to_unicode(value)
elif callable(getattr(value, '__sentry__', None)):
return value.__sentry__()
elif not isinstance(value, (int, bool)) and value is not None:
# XXX: we could do transform(repr(value)) here
return to_unicode(value)
return value
def to_unicode(value):
try:
value = unicode(force_unicode(value))
except (UnicodeEncodeError, UnicodeDecodeError):
value = '(Error decoding value)'
except Exception: # in some cases we get a different exception
try:
value = str(repr(type(value)))
except Exception:
value = '(Error decoding value)'
return value
def get_installed_apps():
"""
Generate a list of modules in settings.INSTALLED_APPS.
"""
out = set()
for app in settings.INSTALLED_APPS:
out.add(app)
return out
class _Missing(object):
def __repr__(self):
return 'no value'
def __reduce__(self):
return '_missing'
_missing = _Missing()
class cached_property(object):
# This is borrowed from werkzeug : http://bytebucket.org/mitsuhiko/werkzeug-main
"""A decorator that converts a function into a lazy property. The
function wrapped is called the first time to retrieve the result
and then that calculated result is used the next time you access
the value::
class Foo(object):
@cached_property
def foo(self):
# calculate something important here
return 42
The class has to have a `__dict__` in order for this property to
work.
.. versionchanged:: 0.6
the `writeable` attribute and parameter was deprecated. If a
cached property is writeable or not has to be documented now.
For performance reasons the implementation does not honor the
writeable setting and will always make the property writeable.
"""
# implementation detail: this property is implemented as non-data
# descriptor. non-data descriptors are only invoked if there is
# no entry with the same name in the instance's __dict__.
# this allows us to completely get rid of the access function call
# overhead. If one choses to invoke __get__ by hand the property
# will still work as expected because the lookup logic is replicated
# in __get__ for manual invocation.
def __init__(self, func, name=None, doc=None, writeable=False):
if writeable:
from warnings import warn
warn(DeprecationWarning('the writeable argument to the '
'cached property is a noop since 0.6 '
'because the property is writeable '
'by default for performance reasons'))
self.__name__ = name or func.__name__
self.__module__ = func.__module__
self.__doc__ = doc or func.__doc__
self.func = func
def __get__(self, obj, type=None):
if obj is None:
return self
value = obj.__dict__.get(self.__name__, _missing)
if value is _missing:
value = self.func(obj)
obj.__dict__[self.__name__] = value
return value
def urlread(url, get={}, post={}, headers={}, timeout=None):
req = urllib2.Request(url, urllib.urlencode(get), headers=headers)
try:
response = urllib2.urlopen(req, urllib.urlencode(post), timeout).read()
except:
response = urllib2.urlopen(req, urllib.urlencode(post)).read()
return response
def get_versions(module_list=None):
if not module_list:
module_list = settings.INSTALLED_APPS + ('django',)
ext_module_list = set()
for m in module_list:
parts = m.split('.')
ext_module_list.update('.'.join(parts[:idx]) for idx in xrange(1, len(parts)+1))
versions = {}
for module_name in ext_module_list:
__import__(module_name)
app = sys.modules[module_name]
if hasattr(app, 'get_version'):
get_version = app.get_version
if callable(get_version):
version = get_version()
else:
version = get_version
elif hasattr(app, 'VERSION'):
version = app.VERSION
elif hasattr(app, '__version__'):
version = app.__version__
else:
continue
if isinstance(version, (list, tuple)):
version = '.'.join(str(o) for o in version)
versions[module_name] = version
return versions