Anonymous committed 323f000

Updated configuration, fixed an import error for a dependency that might not be there. Also, cleaned up

Comments (0)

Files changed (4)

-There are more advanced options that can be used to customize your Hoptoad_ application::
-If you feel that you might be cluttering your with all these ``HOPTOAD_*`` settings, you can conveniently group them in a dictionary::
+There are more advanced options that can be used to customize your Hoptoad_ notification process; please go to `Configuration guide <>`_ to see more advanced configuration and usage options.


     HOPTOAD_IGNORE_AGENTS = ['Googlebot', 'Yahoo! Slurp', 'YahooSeeker']
+Using SSL to POST to Hoptoad
+If you desire to use SSL and your account plan supports it, then you can use the following setting to enable SSL POSTs:
+This will force all HTTP requests to use SSL. There's always a possibility, due to either an account downgrade, or, an expiration of a SSL certificate that Hoptoad might return an error code of `402` on a POST. There is built-in support automatically to try to re-POST the same error message without using SSL. To enable this feature, just add this option as well:
+This will force a fallback to a non-SSL HTTP post to Hoptoad.
+Asynchronous POSTs and Request Handlers
+On a highly trafficked website, there is a noticeable degree of a delay when POST'ing to hoptoad -- either due to error limitations, network instability, or other acts of God that can cause an HTTP request to slow down or fail. To fix this, django-hoptoad will spawn a daemon thread, by default, that will spawn a thread pool, with 4 threads, to queue up all errors for maximum throughput. However, this can be configured to your heart's content, including changing the notification handler completely. 
+To control the number of threads spawned per threadpool, you can set the following variable to your desired thread count per threadpool:
+In django-hoptoad, this variable defaults to 4.
+There is also built-in support for various other methods of communicating **synchronously** with Hoptoad, and that requires just one more setting:
+    HOPTOAD_HANDLER = "blocking"
+This variable is set to "threadpool" by default. 
+There are a few handlers to choose from, (i.e. possible `HOPTOAD_HANDLER` settings):
+### "threadpool" 
+> This is the default setting. Will return a daemonized thread with a 4 worker-thread thread pool to handle all enqueued errors.
+### "blocking" 
+> This will switch from the thread pool approach to a blocking HTTP POST where the entire Django process is halted until this blocking call returns.
+Over time, there will be more custom handlers with various options to control them.
+What if you do not want to use any of the default handlers, but instead, use your own proprietary system?
+There is support for drop-in replacements of handlers so that you might write your own custom handler. More documentation on this to follow.
+Hoptoad Notification URL
+Currently, Hoptoad has their notification URLs pointed to ``, but this has been the second time that this was changed. It, therefore, can be expected that this will change again, so it is configurable like so:
+    HOPTOAD_NOTIFICATION_URL = "Hoptoad Notification URL here."
+This defaults to ``.
+Hoptoad Setting Groupings
+As you've probably noticed, these hoptoad settings are getting to be extremely abundant, so in order to give you some organization support for your ``, we've included support for grouping them in a dictionary. You can group them using `HOPTOAD_SETTINGS` as a dictionary and django-hoptoad will have support for this:
+            'HOPTOAD_API_KEY' : 'a3eer..'
+            'HOPTOAD_HANDLER' : 'threadpool',
+            'HOPTOAD_THREAD_COUNT' : 2,
+            'HOPTOAD_USE_SSL' : True,
+            # etc, you get the point
+     }
 If you're having trouble you might want to take a look at the [Troubleshooting Guide][troubleshooting].
-[troubleshooting]: /troubleshooting/
+[troubleshooting]: /troubleshooting/


 import sys
 import traceback
 import urllib2
-import yaml
 from xml.dom.minidom import getDOMImplementation
 from django.views.debug import get_safe_settings
 def _class_name(class_):
     return class_.__class__.__name__
-def _handle_errors(request, response, exc):
+def _handle_errors(request, response):
     if response:
         code = "Http%s" % response
         msg = "%(code)s: %(response)s at %(uri)s" % {
         return (code, msg)
-    excc, inst = sys.exc_info()[:2]
-    if exc:
-        excc = exc
-    return _class_name(excc), _parse_message(excc)
+    exc, inst = sys.exc_info()[:2]
+    return _class_name(inst), _parse_message(inst)
-def generate_payload(request, response=None, exc=None):
+def generate_payload(request_tuple):
     """Generate an XML payload for a Hoptoad notification.
-    request -- A Django HTTPRequest.
+    request_tuple -- A tuple containing a Django HTTPRequest and a possible
+                     response code.
+    request, response = request_tuple
     hoptoad_settings = get_hoptoad_settings()
-    p_error_class, p_message = _handle_errors(request, response, exc)
+    p_error_class, p_message = _handle_errors(request, response)
     # api v2 from:
     xdoc = getDOMImplementation().createDocument(None, "notice", None)
     r = urllib2.Request(notification_url, payload, headers)
         if timeout:
             # timeout is 2.6 addition!!
     except urllib2.URLError:
-        # getcode is 2.6 addition!!
-        status = response.getcode()
+        try:
+            # getcode is 2.6 addition!!
+            status = response.getcode()
+        except AttributeError:
+            # default to just code
+            status = response.code
         if status == 403:
-            # if we can not use SSL, re-invoke w/o using SSL
-            _ride_the_toad(payload, timeout, use_ssl=False)
+            if get_hoptoad_settings().get('HOPTOAD_NO_SSL_FALLBACK', False):
+                # if we can not use SSL, re-invoke w/o using SSL
+                _ride_the_toad(payload, timeout, use_ssl=False)
         if status == 422:
             # couldn't send to hoptoad..


         sc = response.status_code
         if sc in [404, 403] and getattr(self, "notify_%d" % sc):
-            self.handler.enqueue(htv2.generate_payload(request, response=sc),
+            self.handler.enqueue(htv2.generate_payload((request, sc)),
         return response
         if self._ignore(request):
             return None
-        self.handler.enqueue(htv2.generate_payload(request, exc=exc),
+        self.handler.enqueue(htv2.generate_payload((request, None)),
         return None