diff options
author | David Bolen <db3l.net@gmail.com> | 2013-07-26 14:59:48 -0400 |
---|---|---|
committer | Stephan Bergmann <sbergman@redhat.com> | 2013-07-29 11:35:18 +0200 |
commit | 948b6ea02ea9de7fb4e1e2baf95ecae3ba1cd54e (patch) | |
tree | 9024e84801555e607e486024246bef14244a2af5 /pyuno/source | |
parent | adf9406450652046e19dbfc4246ce1228b8aceea (diff) |
fdo#66025: Improve accuracy of ImportError traceback and message
The ImportError raised on an import failure with the uno module loaded
now includes a complete traceback and the original Python exception
message text, combined with the most relevant (nearest to failure if
imports are nested) uno lookup that also failed.
Change-Id: Id968d84d7f09d555a81017a99369beb503d61439
Signed-off-by: Stephan Bergmann <sbergman@redhat.com>
Diffstat (limited to 'pyuno/source')
-rw-r--r-- | pyuno/source/module/uno.py | 49 |
1 files changed, 31 insertions, 18 deletions
diff --git a/pyuno/source/module/uno.py b/pyuno/source/module/uno.py index 15af94a304fa..1b2581644c61 100644 --- a/pyuno/source/module/uno.py +++ b/pyuno/source/module/uno.py @@ -263,11 +263,14 @@ def _uno_import( name, *optargs, **kwargs ): try: # print "optargs = " + repr(optargs) return _g_delegatee( name, *optargs, **kwargs ) - except ImportError: + except ImportError as e: # process optargs globals, locals, fromlist = list(optargs)[:3] + [kwargs.get('globals',{}), kwargs.get('locals',{}), kwargs.get('fromlist',[])][len(optargs):] - if not fromlist: + # from import form only, but skip if an uno lookup has already failed + if not fromlist or hasattr(e, '_uno_import_failed'): raise + # hang onto exception for possible use on subsequent uno lookup failure + py_import_exc = e modnames = name.split( "." ) mod = None d = sys.modules @@ -303,22 +306,32 @@ def _uno_import( name, *optargs, **kwargs ): failed = True if failed: - # This can be a bad uno reference, or it can just result from any - # python import failure (in a "from xxx import yyy" statement). - # Synthesize a general purpose exception, reusing the original - # traceback to provide information for either case. We don't use - # the original python exception as uno failures will typically - # just reflect a missing top level module (such as "com"). - - # Note that we raise this outside of the nested exception handlers - # above, or otherwise Python 3 will generate additional tracebacks - # for each of the nested exceptions. - - e = ImportError("No module named '%s' or '%s.%s' is unknown" % - (name, name, x)) - e.__traceback__ = sys.exc_info()[2] - - raise e + # We have an import failure, but cannot distinguish between + # uno and non-uno errors as uno lookups are attempted for all + # "from xxx import yyy" imports following a python failure. + # + # The traceback from the original python exception is kept to + # pinpoint the actual failing location, but in Python 3 the + # original message is most likely unhelpful for uno failures, + # as it will most commonly be a missing top level module, + # like 'com'. Our exception appends the uno lookup failure. + # This is more ambiguous, but it plus the traceback should be + # sufficient to identify a root cause for python or uno issues. + # + # Our exception is raised outside of the nested exception + # handlers above, to avoid Python 3 nested exception + # information for the RuntimeExceptions during lookups. + # + # Finally, a private attribute is used to prevent further + # processing if this failure was in a nested import. That + # keeps the exception relevant to the primary failure point, + # preventing us from re-processing our own import errors. + + uno_import_exc = ImportError( + "%s (or '%s.%s' is unknown)" % (py_import_exc, name, x) + ).with_traceback(py_import_exc.__traceback__) + uno_import_exc._uno_import_failed = True + raise uno_import_exc return mod |