title: AppEngine/Python: Why isn't the exception caught?
body: <p>I'm trying to write a Google-Appengine app that will fail nicely when datastore writes are disabled</p>
  
  <p>Currently my main() looks like this: </p>
  
  <pre><code>def main():
      make_datastore_readonly()
      try:
          run_wsgi_app(application)
      except CapabilityDisabledError:
          run_wsgi_app(NoWrite)
  </code></pre>
  
  <p><hr />
  If I set main to:</p>
  
  <pre><code>def main():
      run_wsgi_app(application)
  </code></pre>
  
  <p>My app displays a traceback when the exception is raised.</p>
  
  <p><hr />
  If I set main to:</p>
  
  <pre><code>def main():
      run_wsgi_app(NoWrite)
  </code></pre>
  
  <p>It will properly show my error message (although for every request).</p>
  
  <p><hr />
  Getting back to my modified version of main, this one:</p>
  
  <pre><code>def main():
      make_datastore_readonly()
      try:
          run_wsgi_app(application)
      except CapabilityDisabledError:
          run_wsgi_app(NoWrite)
  </code></pre>
  
  <p>Instead of getting my error message, I still get a traceback that looks like this:</p>
  
  <pre><code>Traceback (most recent call last):
    File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/webapp/_webapp25.py", line 703, in __call__
      handler.post(*groups)
    File "/Users/kevin/Sche/main.py", line 232, in post
      me.put();
    File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/db/__init__.py", line 1074, in put
      return datastore.Put(self._entity, **kwargs)
    File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/api/datastore.py", line 579, in Put
      return PutAsync(entities, **kwargs).get_result()
    File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/api/datastore.py", line 556, in PutAsync
      return _GetConnection().async_put(config, entities, local_extra_hook)
    File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/datastore/datastore_rpc.py", line 1553, in async_put
      return make_put_call(base_req, pbs, extra_hook)
    File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/datastore/datastore_rpc.py", line 1543, in make_put_call
      self.__put_hook, user_data)
    File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/datastore/datastore_rpc.py", line 1188, in make_rpc_call
      rpc.make_call(method, request, response, get_result_hook, user_data)
    File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/api/apiproxy_stub_map.py", line 519, in make_call
      self.__service, method, request, response, self.__rpc)
    File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/api/apiproxy_stub_map.py", line 207, in Call
      function(service, call, request, response)
    File "/Users/kevin/Sche/main.py", line 18, in hook
      raise CapabilityDisabledError('Datastore is in read-only mode')
  CapabilityDisabledError: Datastore is in read-only mode
  </code></pre>
  
  <p>So, my question is, why isn't the exception caught?</p>
  
  <p>Edit:</p>
  
  <p>This function is from <a href="https://stackoverflow.com/questions/2283824/app-engine-sdk-devserver-read-only-mode">this StackOverflow answer</a></p>
  
  <pre><code>def make_datastore_readonly():
    """Throw ReadOnlyError on put and delete operations."""
    def hook(service, call, request, response):
      assert(service == 'datastore_v3')
      if call in ('Put', 'Delete'):
        raise CapabilityDisabledError('Datastore is in read-only mode') //Line 18
    apiproxy_stub_map.apiproxy.GetPreCallHooks().Push('readonly_datastore', hook, 'datastore_v3')
  </code></pre>