summaryrefslogtreecommitdiff
path: root/pyuno
diff options
context:
space:
mode:
authorDavid Bolen <db3l.net@gmail.com>2013-07-29 12:44:26 +0200
committerStephan Bergmann <sbergman@redhat.com>2013-07-29 12:44:26 +0200
commit52a533cc31f630ad482fe0fde8d925b459c787bf (patch)
tree316548dfecf43cce6fa07cd5a68f1ece9c26fc49 /pyuno
parentdf3b3f7e31a78aa8fb9228fc44a299fc4b88de9d (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. Cherry-picked from 948b6ea02ea9de7fb4e1e2baf95ecae3ba1cd54e plus previous patches leading up to that, 7fd81244c21ad54a8b9766902fd7c34e8055b165 "fdo#66025: Improve ImportError raised from _uno_import," 329125abb63061214897e4f215d41cfa4b13b4b0 "fdo#66025: Minor clean-up of previous patch," and fbe28de6fbfdce41544e4e93168d32661add8285 "fdo#66025: Simplify new ImportError logic." Change-Id: I8c22f22c2d96bdd7fb99a87273ba574e22a86923 Signed-off-by: Stephan Bergmann <sbergman@redhat.com>
Diffstat (limited to 'pyuno')
-rw-r--r--pyuno/source/module/uno.py50
1 files changed, 41 insertions, 9 deletions
diff --git a/pyuno/source/module/uno.py b/pyuno/source/module/uno.py
index 86011f3b4c97..d99884a64d68 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
@@ -281,26 +284,55 @@ def _uno_import( name, *optargs, **kwargs ):
RuntimeException = pyuno.getClass( "com.sun.star.uno.RuntimeException" )
for x in fromlist:
if x not in d:
+ failed = False
if x.startswith( "typeOf" ):
try:
d[x] = pyuno.getTypeByName( name + "." + x[6:len(x)] )
- except RuntimeException as e:
- raise ImportError( "type " + name + "." + x[6:len(x)] +" is unknown" )
+ except RuntimeException:
+ failed = True
else:
try:
# check for structs, exceptions or interfaces
d[x] = pyuno.getClass( name + "." + x )
- except RuntimeException as e:
+ except RuntimeException:
# check for enums
try:
d[x] = Enum( name , x )
- except RuntimeException as e2:
+ except RuntimeException:
# check for constants
try:
d[x] = getConstantByName( name + "." + x )
- except RuntimeException as e3:
- # no known uno type !
- raise ImportError( "type "+ name + "." +x + " is unknown" )
+ except RuntimeException:
+ failed = True
+
+ if failed:
+ # 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
# private function, don't use