"""
mixins.sentry

A RequestHandler mixin for sending exceptions to Sentry

"""
version_info = (0, 2, 0)
__version__ = '.'.join(str(v) for v in version_info)


import math
import os
import pkg_resources
import re
import sys
import time
try:
    from urllib import parse
except ImportError:
    import urlparse as parse

import raven
from tornado import web

SENTRY_CLIENT = 'sentry_client'
URI_RE = re.compile(r'^[\w\+\-]+://.*:(\w+)@.*')


class SentryMixin(object):

    def initialize(self):
        self.sentry_tags = {}
        if not hasattr(self.application, SENTRY_CLIENT):
            sentry_dsn = os.environ.get('SENTRY_DSN')
            if sentry_dsn:
                setattr(self.application, SENTRY_CLIENT,
                        raven.Client(sentry_dsn))
        super(SentryMixin, self).initialize()

    def _strip_uri_passwords(self, values):
        for key in values.keys():
            matches = URI_RE.search(values[key])
            if matches:
                values[key] = values[key].replace(matches.group(1), '****')
        return values

    def _handle_request_exception(self, e):
        if isinstance(e, web.HTTPError):
            return super(SentryMixin, self)._handle_request_exception(e)

        if hasattr(self.application, SENTRY_CLIENT):
            duration = math.ceil((time.time() - self.request._start_time) * 1000)
            data = {}
            if hasattr(self, 'request'):
                data = {'request':
                            {'url': self.request.full_url(),
                             'method': self.request.method,
                             'data': self.request.body,
                             'query_string': self.request.query,
                             'cookies': self.request.headers.get('Cookie', {}),
                             'headers': dict(self.request.headers)},
                        'logger': 'sprockets.mixins.sentry',
                        'modules': self._get_module_data()}
            kwargs = {'extra':
                          {'handler': '{0}.{1}'.format(__name__,
                                                       self.__class__.__name__),
                           'env': self._strip_uri_passwords(dict(os.environ)),
                           'http_host': self.request.host,
                           'remote_ip': self.request.remote_ip},
                      'time_spent': duration}
            if self.sentry_tags:
                kwargs.update({'tags': self.sentry_tags})
            self.application.sentry_client.captureException(True, data=data,
                                                            **kwargs)
        super(SentryMixin, self)._handle_request_exception(e)

    def _get_module_data(self):
        modules = {}
        for module_name in sys.modules.keys():
            module = sys.modules[module_name]
            if hasattr(module, '__version__'):
                modules[module_name] = module.__version__
            elif hasattr(module, 'version'):
                modules[module_name] = module.version
            else:
                try:
                    version = self._get_version(module_name)
                    if version:
                        modules[module_name] = version
                except Exception:
                    pass
        return modules

    @staticmethod
    def _get_version(module_name):
        try:
            return pkg_resources.get_distribution(module_name).version
        except pkg_resources.DistributionNotFound:
            return None

@@ -533,52 +533,34 @@
  if 
-not hasattr(self.application, SENTRY_CLIENT)
+self.sentry_client is None
 :%0A  
@@ -1125,16 +1125,46 @@
 TPError)
+ or self.sentry_client is None
 :%0A      
@@ -1235,65 +1235,8 @@
 e)%0A%0A
-        if hasattr(self.application, SENTRY_CLIENT):%0A    
     
@@ -1321,26 +1321,227 @@
     
-    data = %7B%7D%0A    
+kwargs = %7B%0A            'extra': %7B%0A                'handler': '%7B0%7D.%7B1%7D'.format(__name__, self.__class__.__name__),%0A                'env': self._strip_uri_passwords(dict(os.environ))%7D,%0A            'time_spent': duration%7D%0A
     
@@ -1589,20 +1589,43 @@
     
-    
+kwargs%5B'
 data
+'%5D
  = %7B
+%0A                
 'req
@@ -1630,16 +1630,18 @@
 equest':
+ %7B
 %0A       
@@ -1653,25 +1653,16 @@
         
-        %7B
 'url': s
@@ -1705,25 +1705,16 @@
         
-         
 'method'
@@ -1756,25 +1756,16 @@
         
-    
-     
 'data': 
@@ -1803,25 +1803,16 @@
         
-        
- 
 'query_s
@@ -1839,25 +1839,16 @@
 .query,%0A
-         
         
@@ -1930,25 +1930,16 @@
         
-   
-      
 'headers
@@ -1986,24 +1986,16 @@
         
-      
-  
 'logger'
@@ -2023,24 +2023,16 @@
 entry',%0A
-        
         
@@ -2097,273 +2097,18 @@
 args
- = %7B
+%5B
 'extra'
-:%0A                          %7B'handler': '%7B0%7D.%7B1%7D'.format(__name__,%0A                                                       self.__class__.__name__),%0A                           'env': self._strip_uri_passwords(dict(os.environ)),%0A                           
+%5D%5B
 'htt
@@ -2114,17 +2114,19 @@
 tp_host'
-:
+%5D =
  self.re
@@ -2135,17 +2135,16 @@
 est.host
-,
 %0A       
@@ -2148,31 +2148,32 @@
         
-               
+kwargs%5B'extra'%5D%5B
 'remote_
@@ -2175,17 +2175,19 @@
 mote_ip'
-:
+%5D =
  self.re
@@ -2205,61 +2205,10 @@
 e_ip
-%7D,%0A                      'time_spent': duration%7D%0A    
+%0A%0A
     
@@ -2232,20 +2232,16 @@
 y_tags:%0A
-    
         
@@ -2298,29 +2298,13 @@
     
-    
 self.
-application.
 sent
@@ -2339,79 +2339,8 @@
 rue,
- data=data,%0A                                                           
  **k
@@ -2346,16 +2346,17 @@
 kwargs)%0A
+%0A
         
@@ -3218,16 +3218,16 @@
 tFound:%0A
-
         
@@ -3242,8 +3242,114 @@
 rn None%0A
+%0A    @property%0A    def sentry_client(self):%0A        return getattr(self.application, SENTRY_CLIENT, None)%0A

Introduce self.sentry_client + refactor a little.