We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
logging: __sentry__ isn't always callable
acdha@0af552b18d72594b183b18834ba7245a1ff5ade1 contains a trivial "fix" to avoid crashing when handling a value which has `__sentry__` set to `None` but I haven't had time to learn what `__sentry__` is supposed to do. `logging` is configured exactly as in the documentation, the code in question made a simple `logging.exception` call inside an `except` clause.

Here's a traceback - it's oddly formatted because the bug in question happened inside a django-tastypie resource handler:

```
Traceback (most recent call last):

  File "/Users/cadams/.virtualenvs/MyProject/lib/python2.6/site-packages/tastypie/resources.py", line 178, in wrapper
    return getattr(self,
     view)(request,
     *args,
     **kwargs)

  File "/Users/cadams/Projects/MyProject/MyProject/apps/api/resources.py", line 133, in dispatch_notes
    return self.dispatch('notes',
     request,
     **kwargs)

  File "/Users/cadams/.virtualenvs/MyProject/lib/python2.6/site-packages/tastypie/resources.py", line 350, in dispatch
    response = method(request,
     **kwargs)

  File "/Users/cadams/Projects/MyProject/MyProject/apps/api/resources.py", line 167, in post_notes
    bundle.data)

  File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/logging/__init__.py", line 1419, in exception
    error(*((msg,
    )+args),
     **
    {
        'exc_info': 1
    }
    )

  File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/logging/__init__.py", line 1412, in error
    root.error(*((msg,
    )+args),
     **kwargs)

  File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/logging/__init__.py", line 1047, in error
    self._log(ERROR,
     msg,
     args,
     **kwargs)

  File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/logging/__init__.py", line 1129, in _log
    self.handle(record)

  File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/logging/__init__.py", line 1139, in handle
    self.callHandlers(record)

  File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/logging/__init__.py", line 1176, in callHandlers
    hdlr.handle(record)

  File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/logging/__init__.py", line 662, in handle
    self.emit(record)

  File "/Users/cadams/Projects/django-sentry/sentry/client/handlers.py", line 14, in emit
    get_client().create_from_record(record)

  File "/Users/cadams/Projects/django-sentry/sentry/client/base.py", line 157, in create_from_record
    return self.create_from_exception(record.exc_info,
     **kwargs)

  File "/Users/cadams/Projects/django-sentry/sentry/client/base.py", line 189, in create_from_exception
    frames = varmap(shorten,
     reporter.get_traceback_frames())

  File "/Users/cadams/Projects/django-sentry/sentry/helpers.py", line 58, in varmap
    return 
    [
        varmap(func,
         f) for f in var
    ]


  File "/Users/cadams/Projects/django-sentry/sentry/helpers.py", line 56, in varmap
    return dict((k,
     varmap(func,
     v)) for k,
     v in var.iteritems())

  File "/Users/cadams/Projects/django-sentry/sentry/helpers.py", line 56, in <genexpr>
    return dict((k,
     varmap(func,
     v)) for k,
     v in var.iteritems())

  File "/Users/cadams/Projects/django-sentry/sentry/helpers.py", line 58, in varmap
    return 
    [
        varmap(func,
         f) for f in var
    ]


  File "/Users/cadams/Projects/django-sentry/sentry/helpers.py", line 58, in varmap
    return 
    [
        varmap(func,
         f) for f in var
    ]


  File "/Users/cadams/Projects/django-sentry/sentry/helpers.py", line 60, in varmap
    return func(var)

  File "/Users/cadams/Projects/django-sentry/sentry/client/base.py", line 183, in shorten
    var = transform(var)

  File "/Users/cadams/Projects/django-sentry/sentry/helpers.py", line 80, in transform
    return value.__sentry__()

TypeError: 'NoneType' object is not callable
```


--- END ISSUE ---

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

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/sentry/helpers.py b/sentry/helpers.py
--- a/sentry/helpers.py
+++ b/sentry/helpers.py
@@ -76,7 +76,7 @@
             return str(value)
         except:
             return to_unicode(value)
-    elif hasattr(value, '__sentry__'):
+    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

{"golden_diff": "diff --git a/sentry/helpers.py b/sentry/helpers.py\n--- a/sentry/helpers.py\n+++ b/sentry/helpers.py\n@@ -76,7 +76,7 @@\n             return str(value)\n         except:\n             return to_unicode(value)\n-    elif hasattr(value, '__sentry__'):\n+    elif callable(getattr(value, '__sentry__', None)):\n         return value.__sentry__()\n     elif not isinstance(value, (int, bool)) and value is not None:\n         # XXX: we could do transform(repr(value)) here\n", "issue": "logging: __sentry__ isn't always callable\nacdha@0af552b18d72594b183b18834ba7245a1ff5ade1 contains a trivial \"fix\" to avoid crashing when handling a value which has `__sentry__` set to `None` but I haven't had time to learn what `__sentry__` is supposed to do. `logging` is configured exactly as in the documentation, the code in question made a simple `logging.exception` call inside an `except` clause.\n\nHere's a traceback - it's oddly formatted because the bug in question happened inside a django-tastypie resource handler:\n\n```\nTraceback (most recent call last):\n\n  File \"/Users/cadams/.virtualenvs/MyProject/lib/python2.6/site-packages/tastypie/resources.py\", line 178, in wrapper\n    return getattr(self,\n     view)(request,\n     *args,\n     **kwargs)\n\n  File \"/Users/cadams/Projects/MyProject/MyProject/apps/api/resources.py\", line 133, in dispatch_notes\n    return self.dispatch('notes',\n     request,\n     **kwargs)\n\n  File \"/Users/cadams/.virtualenvs/MyProject/lib/python2.6/site-packages/tastypie/resources.py\", line 350, in dispatch\n    response = method(request,\n     **kwargs)\n\n  File \"/Users/cadams/Projects/MyProject/MyProject/apps/api/resources.py\", line 167, in post_notes\n    bundle.data)\n\n  File \"/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/logging/__init__.py\", line 1419, in exception\n    error(*((msg,\n    )+args),\n     **\n    {\n        'exc_info': 1\n    }\n    )\n\n  File \"/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/logging/__init__.py\", line 1412, in error\n    root.error(*((msg,\n    )+args),\n     **kwargs)\n\n  File \"/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/logging/__init__.py\", line 1047, in error\n    self._log(ERROR,\n     msg,\n     args,\n     **kwargs)\n\n  File \"/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/logging/__init__.py\", line 1129, in _log\n    self.handle(record)\n\n  File \"/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/logging/__init__.py\", line 1139, in handle\n    self.callHandlers(record)\n\n  File \"/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/logging/__init__.py\", line 1176, in callHandlers\n    hdlr.handle(record)\n\n  File \"/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/logging/__init__.py\", line 662, in handle\n    self.emit(record)\n\n  File \"/Users/cadams/Projects/django-sentry/sentry/client/handlers.py\", line 14, in emit\n    get_client().create_from_record(record)\n\n  File \"/Users/cadams/Projects/django-sentry/sentry/client/base.py\", line 157, in create_from_record\n    return self.create_from_exception(record.exc_info,\n     **kwargs)\n\n  File \"/Users/cadams/Projects/django-sentry/sentry/client/base.py\", line 189, in create_from_exception\n    frames = varmap(shorten,\n     reporter.get_traceback_frames())\n\n  File \"/Users/cadams/Projects/django-sentry/sentry/helpers.py\", line 58, in varmap\n    return \n    [\n        varmap(func,\n         f) for f in var\n    ]\n\n\n  File \"/Users/cadams/Projects/django-sentry/sentry/helpers.py\", line 56, in varmap\n    return dict((k,\n     varmap(func,\n     v)) for k,\n     v in var.iteritems())\n\n  File \"/Users/cadams/Projects/django-sentry/sentry/helpers.py\", line 56, in <genexpr>\n    return dict((k,\n     varmap(func,\n     v)) for k,\n     v in var.iteritems())\n\n  File \"/Users/cadams/Projects/django-sentry/sentry/helpers.py\", line 58, in varmap\n    return \n    [\n        varmap(func,\n         f) for f in var\n    ]\n\n\n  File \"/Users/cadams/Projects/django-sentry/sentry/helpers.py\", line 58, in varmap\n    return \n    [\n        varmap(func,\n         f) for f in var\n    ]\n\n\n  File \"/Users/cadams/Projects/django-sentry/sentry/helpers.py\", line 60, in varmap\n    return func(var)\n\n  File \"/Users/cadams/Projects/django-sentry/sentry/client/base.py\", line 183, in shorten\n    var = transform(var)\n\n  File \"/Users/cadams/Projects/django-sentry/sentry/helpers.py\", line 80, in transform\n    return value.__sentry__()\n\nTypeError: 'NoneType' object is not callable\n```\n\n", "before_files": [{"content": "import logging\nimport sys\nimport urllib\nimport urllib2\nimport uuid\n\nimport django\nfrom django.conf import settings\nfrom django.utils.encoding import force_unicode\nfrom django.utils.hashcompat import md5_constructor\n\nfrom sentry import conf\n\n_FILTER_CACHE = None\ndef get_filters():\n    global _FILTER_CACHE\n    \n    if _FILTER_CACHE is None:\n        \n        filters = []\n        for filter_ in conf.FILTERS:\n            module_name, class_name = filter_.rsplit('.', 1)\n            try:\n                module = __import__(module_name, {}, {}, class_name)\n                filter_ = getattr(module, class_name)\n            except Exception:\n                logging.exception('Unable to import %s' % (filter_,))\n                continue\n            filters.append(filter_)\n        _FILTER_CACHE = filters\n    for f in _FILTER_CACHE:\n        yield f\n\ndef get_db_engine(alias='default'):\n    has_multidb = django.VERSION >= (1, 2)\n    if has_multidb:\n        value = settings.DATABASES[alias]['ENGINE']\n    else:\n        assert alias == 'default', 'You cannot fetch a database engine other than the default on Django < 1.2'\n        value = settings.DATABASE_ENGINE\n    return value.rsplit('.', 1)[-1]\n\ndef construct_checksum(level=logging.ERROR, class_name='', traceback='', message='', **kwargs):\n    checksum = md5_constructor(str(level))\n    checksum.update(class_name or '')\n    if traceback:\n        traceback = '\\n'.join(traceback.split('\\n')[:-3])\n    message = traceback or message\n    if isinstance(message, unicode):\n        message = message.encode('utf-8', 'replace')\n    checksum.update(message)\n    return checksum.hexdigest()\n\ndef varmap(func, var):\n    if isinstance(var, dict):\n        return dict((k, varmap(func, v)) for k, v in var.iteritems())\n    elif isinstance(var, (list, tuple)):\n        return [varmap(func, f) for f in var]\n    else:\n        return func(var)\n\ndef transform(value):\n    # TODO: make this extendable\n    # TODO: include some sane defaults, like UUID\n    # TODO: dont coerce strings to unicode, leave them as strings\n    if isinstance(value, (tuple, list, set, frozenset)):\n        return type(value)(transform(o) for o in value)\n    elif isinstance(value, uuid.UUID):\n        return repr(value)\n    elif isinstance(value, dict):\n        return dict((k, transform(v)) for k, v in value.iteritems())\n    elif isinstance(value, unicode):\n        return to_unicode(value)\n    elif isinstance(value, str):\n        try:\n            return str(value)\n        except:\n            return to_unicode(value)\n    elif hasattr(value, '__sentry__'):\n        return value.__sentry__()\n    elif not isinstance(value, (int, bool)) and value is not None:\n        # XXX: we could do transform(repr(value)) here\n        return to_unicode(value)\n    return value\n\ndef to_unicode(value):\n    try:\n        value = unicode(force_unicode(value))\n    except (UnicodeEncodeError, UnicodeDecodeError):\n        value = '(Error decoding value)'\n    except Exception: # in some cases we get a different exception\n        try:\n            value = str(repr(type(value)))\n        except Exception:\n            value = '(Error decoding value)'\n    return value\n\ndef get_installed_apps():\n    \"\"\"\n    Generate a list of modules in settings.INSTALLED_APPS.\n    \"\"\"\n    out = set()\n    for app in settings.INSTALLED_APPS:\n        out.add(app)\n    return out\n\nclass _Missing(object):\n\n    def __repr__(self):\n        return 'no value'\n\n    def __reduce__(self):\n        return '_missing'\n\n_missing = _Missing()\n\nclass cached_property(object):\n    # This is borrowed from werkzeug : http://bytebucket.org/mitsuhiko/werkzeug-main\n    \"\"\"A decorator that converts a function into a lazy property.  The\n    function wrapped is called the first time to retrieve the result\n    and then that calculated result is used the next time you access\n    the value::\n\n        class Foo(object):\n\n            @cached_property\n            def foo(self):\n                # calculate something important here\n                return 42\n\n    The class has to have a `__dict__` in order for this property to\n    work.\n\n    .. versionchanged:: 0.6\n       the `writeable` attribute and parameter was deprecated.  If a\n       cached property is writeable or not has to be documented now.\n       For performance reasons the implementation does not honor the\n       writeable setting and will always make the property writeable.\n    \"\"\"\n\n    # implementation detail: this property is implemented as non-data\n    # descriptor.  non-data descriptors are only invoked if there is\n    # no entry with the same name in the instance's __dict__.\n    # this allows us to completely get rid of the access function call\n    # overhead.  If one choses to invoke __get__ by hand the property\n    # will still work as expected because the lookup logic is replicated\n    # in __get__ for manual invocation.\n\n    def __init__(self, func, name=None, doc=None, writeable=False):\n        if writeable:\n            from warnings import warn\n            warn(DeprecationWarning('the writeable argument to the '\n                                    'cached property is a noop since 0.6 '\n                                    'because the property is writeable '\n                                    'by default for performance reasons'))\n\n        self.__name__ = name or func.__name__\n        self.__module__ = func.__module__\n        self.__doc__ = doc or func.__doc__\n        self.func = func\n\n    def __get__(self, obj, type=None):\n        if obj is None:\n            return self\n        value = obj.__dict__.get(self.__name__, _missing)\n        if value is _missing:\n            value = self.func(obj)\n            obj.__dict__[self.__name__] = value\n        return value\n\ndef urlread(url, get={}, post={}, headers={}, timeout=None):\n    req = urllib2.Request(url, urllib.urlencode(get), headers=headers)\n    try:\n        response = urllib2.urlopen(req, urllib.urlencode(post), timeout).read()\n    except:\n        response = urllib2.urlopen(req, urllib.urlencode(post)).read()\n    return response\n\ndef get_versions(module_list=None):\n    if not module_list:\n        module_list = settings.INSTALLED_APPS + ['django']\n\n    ext_module_list = set()\n    for m in module_list:\n        parts = m.split('.')\n        ext_module_list.update('.'.join(parts[:idx]) for idx in xrange(1, len(parts)+1))\n\n    versions = {}\n    for module_name in ext_module_list:\n        __import__(module_name)\n        app = sys.modules[module_name]\n        if hasattr(app, 'get_version'):\n            get_version = app.get_version\n            if callable(get_version):\n                version = get_version()\n            else:\n                version = get_version\n        elif hasattr(app, 'VERSION'):\n            version = app.VERSION\n        elif hasattr(app, '__version__'):\n            version = app.__version__\n        else:\n            continue\n        if isinstance(version, (list, tuple)):\n            version = '.'.join(str(o) for o in version)\n        versions[module_name] = version\n    return versions", "path": "sentry/helpers.py"}], "after_files": [{"content": "import logging\nimport sys\nimport urllib\nimport urllib2\nimport uuid\n\nimport django\nfrom django.conf import settings\nfrom django.utils.encoding import force_unicode\nfrom django.utils.hashcompat import md5_constructor\n\nfrom sentry import conf\n\n_FILTER_CACHE = None\ndef get_filters():\n    global _FILTER_CACHE\n    \n    if _FILTER_CACHE is None:\n        \n        filters = []\n        for filter_ in conf.FILTERS:\n            module_name, class_name = filter_.rsplit('.', 1)\n            try:\n                module = __import__(module_name, {}, {}, class_name)\n                filter_ = getattr(module, class_name)\n            except Exception:\n                logging.exception('Unable to import %s' % (filter_,))\n                continue\n            filters.append(filter_)\n        _FILTER_CACHE = filters\n    for f in _FILTER_CACHE:\n        yield f\n\ndef get_db_engine(alias='default'):\n    has_multidb = django.VERSION >= (1, 2)\n    if has_multidb:\n        value = settings.DATABASES[alias]['ENGINE']\n    else:\n        assert alias == 'default', 'You cannot fetch a database engine other than the default on Django < 1.2'\n        value = settings.DATABASE_ENGINE\n    return value.rsplit('.', 1)[-1]\n\ndef construct_checksum(level=logging.ERROR, class_name='', traceback='', message='', **kwargs):\n    checksum = md5_constructor(str(level))\n    checksum.update(class_name or '')\n    if traceback:\n        traceback = '\\n'.join(traceback.split('\\n')[:-3])\n    message = traceback or message\n    if isinstance(message, unicode):\n        message = message.encode('utf-8', 'replace')\n    checksum.update(message)\n    return checksum.hexdigest()\n\ndef varmap(func, var):\n    if isinstance(var, dict):\n        return dict((k, varmap(func, v)) for k, v in var.iteritems())\n    elif isinstance(var, (list, tuple)):\n        return [varmap(func, f) for f in var]\n    else:\n        return func(var)\n\ndef transform(value):\n    # TODO: make this extendable\n    # TODO: include some sane defaults, like UUID\n    # TODO: dont coerce strings to unicode, leave them as strings\n    if isinstance(value, (tuple, list, set, frozenset)):\n        return type(value)(transform(o) for o in value)\n    elif isinstance(value, uuid.UUID):\n        return repr(value)\n    elif isinstance(value, dict):\n        return dict((k, transform(v)) for k, v in value.iteritems())\n    elif isinstance(value, unicode):\n        return to_unicode(value)\n    elif isinstance(value, str):\n        try:\n            return str(value)\n        except:\n            return to_unicode(value)\n    elif callable(getattr(value, '__sentry__', None)):\n        return value.__sentry__()\n    elif not isinstance(value, (int, bool)) and value is not None:\n        # XXX: we could do transform(repr(value)) here\n        return to_unicode(value)\n    return value\n\ndef to_unicode(value):\n    try:\n        value = unicode(force_unicode(value))\n    except (UnicodeEncodeError, UnicodeDecodeError):\n        value = '(Error decoding value)'\n    except Exception: # in some cases we get a different exception\n        try:\n            value = str(repr(type(value)))\n        except Exception:\n            value = '(Error decoding value)'\n    return value\n\ndef get_installed_apps():\n    \"\"\"\n    Generate a list of modules in settings.INSTALLED_APPS.\n    \"\"\"\n    out = set()\n    for app in settings.INSTALLED_APPS:\n        out.add(app)\n    return out\n\nclass _Missing(object):\n\n    def __repr__(self):\n        return 'no value'\n\n    def __reduce__(self):\n        return '_missing'\n\n_missing = _Missing()\n\nclass cached_property(object):\n    # This is borrowed from werkzeug : http://bytebucket.org/mitsuhiko/werkzeug-main\n    \"\"\"A decorator that converts a function into a lazy property.  The\n    function wrapped is called the first time to retrieve the result\n    and then that calculated result is used the next time you access\n    the value::\n\n        class Foo(object):\n\n            @cached_property\n            def foo(self):\n                # calculate something important here\n                return 42\n\n    The class has to have a `__dict__` in order for this property to\n    work.\n\n    .. versionchanged:: 0.6\n       the `writeable` attribute and parameter was deprecated.  If a\n       cached property is writeable or not has to be documented now.\n       For performance reasons the implementation does not honor the\n       writeable setting and will always make the property writeable.\n    \"\"\"\n\n    # implementation detail: this property is implemented as non-data\n    # descriptor.  non-data descriptors are only invoked if there is\n    # no entry with the same name in the instance's __dict__.\n    # this allows us to completely get rid of the access function call\n    # overhead.  If one choses to invoke __get__ by hand the property\n    # will still work as expected because the lookup logic is replicated\n    # in __get__ for manual invocation.\n\n    def __init__(self, func, name=None, doc=None, writeable=False):\n        if writeable:\n            from warnings import warn\n            warn(DeprecationWarning('the writeable argument to the '\n                                    'cached property is a noop since 0.6 '\n                                    'because the property is writeable '\n                                    'by default for performance reasons'))\n\n        self.__name__ = name or func.__name__\n        self.__module__ = func.__module__\n        self.__doc__ = doc or func.__doc__\n        self.func = func\n\n    def __get__(self, obj, type=None):\n        if obj is None:\n            return self\n        value = obj.__dict__.get(self.__name__, _missing)\n        if value is _missing:\n            value = self.func(obj)\n            obj.__dict__[self.__name__] = value\n        return value\n\ndef urlread(url, get={}, post={}, headers={}, timeout=None):\n    req = urllib2.Request(url, urllib.urlencode(get), headers=headers)\n    try:\n        response = urllib2.urlopen(req, urllib.urlencode(post), timeout).read()\n    except:\n        response = urllib2.urlopen(req, urllib.urlencode(post)).read()\n    return response\n\ndef get_versions(module_list=None):\n    if not module_list:\n        module_list = settings.INSTALLED_APPS + ['django']\n\n    ext_module_list = set()\n    for m in module_list:\n        parts = m.split('.')\n        ext_module_list.update('.'.join(parts[:idx]) for idx in xrange(1, len(parts)+1))\n\n    versions = {}\n    for module_name in ext_module_list:\n        __import__(module_name)\n        app = sys.modules[module_name]\n        if hasattr(app, 'get_version'):\n            get_version = app.get_version\n            if callable(get_version):\n                version = get_version()\n            else:\n                version = get_version\n        elif hasattr(app, 'VERSION'):\n            version = app.VERSION\n        elif hasattr(app, '__version__'):\n            version = app.__version__\n        else:\n            continue\n        if isinstance(version, (list, tuple)):\n            version = '.'.join(str(o) for o in version)\n        versions[module_name] = version\n    return versions", "path": "sentry/helpers.py"}]}