summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Bolen <db3l.net@gmail.com>2013-07-26 14:59:48 -0400
committerStephan Bergmann <sbergman@redhat.com>2013-07-29 11:35:18 +0200
commit948b6ea02ea9de7fb4e1e2baf95ecae3ba1cd54e (patch)
tree9024e84801555e607e486024246bef14244a2af5
parentadf9406450652046e19dbfc4246ce1228b8aceea (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>
-rw-r--r--pyuno/source/module/uno.py49
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