Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do not silence exceptions on custom plugins #487

Closed
2 of 8 tasks
ingenieroariel opened this issue Nov 22, 2016 · 3 comments
Closed
2 of 8 tasks

Do not silence exceptions on custom plugins #487

ingenieroariel opened this issue Nov 22, 2016 · 3 comments
Assignees
Milestone

Comments

@ingenieroariel
Copy link
Contributor

Description

A somewhat cryptic error 'Csw' object has no attribute 'repository' comes out when I make mistakes on a custom plugin or the database has not been set up.

It'd be great if pycsw can return a python error pointing to the line that causes the problem instead of that generic error.

Environment

  • operating system: OSX

  • Python version: 2.7

  • pycsw version: 2.1-dev

  • source/distribution

  • git clone

  • DebianGIS/UbuntuGIS

  • PyPI

  • zip/tar.gz

  • other (please specify):
    testpypi

  • web server

  • Apache/mod_wsgi

  • CGI

  • other (please specify):
    Custom WSGI app based on Django.

Steps to Reproduce

Create a custom plugin like:

from pycsw.core.repository import Repository

class RegistryRepository(Repository):
    def __init__(self, *args, **kwargs):
        assert False

You will get the following exception which does not include the line with the assert False:

Traceback (most recent call last):
  File "/Users/x/.venvs/registry/lib/python2.7/site-packages/django/core/handlers/exception.py", line 39, in inner
    response = get_response(request)
  File "/Users/x/.venvs/registry/lib/python2.7/site-packages/django/core/handlers/base.py", line 249, in _legacy_get_response
    response = self._get_response(request)
  File "/Users/x/.venvs/registry/lib/python2.7/site-packages/django/core/handlers/base.py", line 187, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/Users/x/.venvs/registry/lib/python2.7/site-packages/django/core/handlers/base.py", line 185, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/Users/x/.venvs/registry/lib/python2.7/site-packages/django/utils/decorators.py", line 67, in _wrapper
    return bound_func(*args, **kwargs)
  File "/Users/x/.venvs/registry/lib/python2.7/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
    return view_func(*args, **kwargs)
  File "/Users/x/.venvs/registry/lib/python2.7/site-packages/django/utils/decorators.py", line 63, in bound_func
    return func.__get__(self, type(self))(*args2, **kwargs2)
  File "/code/registry/registry.py", line 228, in csw_view
    status, content = csw.dispatch_wsgi()
  File "/Users/x/.venvs/registry/lib/python2.7/site-packages/pycsw/server.py", line 270, in dispatch_wsgi
    return self.dispatch()
  File "/Users/x/.venvs/registry/lib/python2.7/site-packages/pycsw/server.py", line 554, in dispatch
    self.response = self.iface.getcapabilities()
  File "/Users/x/.venvs/registry/lib/python2.7/site-packages/pycsw/ogc/csw/csw3.py", line 343, in getcapabilities
    for qbl in sorted(self.parent.repository.queryables.keys()):
AttributeError: 'Csw' object has no attribute 'repository'

Additional Information

I think the way to fix it is to not try to wrap exceptions in CSW objects if the repository has not been initialized. In order to help developers and system administrators catch problems in their code.

@tomkralidis
Copy link
Member

@ingenieroariel thanks for the report. The patch below throws error when loading the repository results in an exception. Can you test? I'll clean up / push accordingly thereafter.

diff --git a/pycsw/server.py b/pycsw/server.py
index e5d49a3..fb7291c 100644
--- a/pycsw/server.py
+++ b/pycsw/server.py
@@ -269,6 +269,7 @@ class Csw(object):
     def dispatch(self, writer=sys.stdout, write_headers=True):
         """ Handle incoming HTTP request """
 
+        error = 0
         if self.requesttype == 'GET':
             self.kvp = self.normalize_kvp(self.kvp)
             version_202 = ('version' in self.kvp and
@@ -380,9 +381,14 @@ class Csw(object):
                 self.repository = rs_cls(self.context, repo_filter)
                 LOGGER.debug('Custom repository %s loaded (%s)', rs, self.repository.dbtype)
             except Exception as err:
-                self.response = self.iface.exceptionreport(
-                    'NoApplicableCode', 'service',
-                    'Could not load custom repository %s: %s' % (rs, str(err)))
+                LOGGER.error('Could not load custom repository %s: %s' % (rs, str(err)))
+                error = 1
+                code = 'NoApplicableCode'
+                locator = 'service'
+                text = 'Could not initialize repository. Check server logs'
+                #self.response = self.iface.exceptionreport(
+                #    'NoApplicableCode', 'service',
+                #    'Could not load custom repository %s: %s' % (rs, str(err)))
 
         else:  # load default repository
             self.orm = 'sqlalchemy'
@@ -398,16 +404,21 @@ class Csw(object):
                 LOGGER.debug(
                     'Repository loaded (local): %s.' % self.repository.dbtype)
             except Exception as err:
-                self.response = self.iface.exceptionreport(
-                    'NoApplicableCode', 'service',
-                    'Could not load repository (local): %s' % str(err)
-                )
+                LOGGER.error('Could not load repository  (local): %s' % str(err))
+                error = 1
+                code = 'NoApplicableCode'
+                locator = 'service'
+                text = 'Could not initialize repository. Check server logs'
+                #self.response = self.iface.exceptionreport(
+                #    'NoApplicableCode', 'service',
+                #    'Could not load repository (local): %s' % str(err)
+                #)
 
         if self.requesttype == 'POST':
             LOGGER.debug(self.iface.version)
             self.kvp = self.iface.parse_postdata(self.request)
 
-        error = 0
+        #error = 0
 
         if isinstance(self.kvp, str):  # it's an exception
             error = 1

@ingenieroariel
Copy link
Contributor Author

I have not had a chance to test it but will do this week and report back. Thanks!

@tomkralidis
Copy link
Member

Fixed in #527

minhd added a commit to minhd/pycsw that referenced this issue Jun 9, 2017
* master:
  Do not silence exceptions on custom plugins (geopython#487) (geopython#527)
  decouple requirements files in lieu of assembling via tox config (geopython#521) (geopython#497)
  from mock import Mock as MagicMock
  codecov integration (geopython#525)
  fixed code review issues
  version is now stored on a single file, VERSION.txt
  removed python 2.6 from the tox settings
  fix ref (geopython#514)
  Fixed harvesting WMS. calling undefined function (geopython#518)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants