summaryrefslogtreecommitdiff
path: root/paste/util/import_string.py
diff options
context:
space:
mode:
Diffstat (limited to 'paste/util/import_string.py')
-rw-r--r--paste/util/import_string.py95
1 files changed, 95 insertions, 0 deletions
diff --git a/paste/util/import_string.py b/paste/util/import_string.py
new file mode 100644
index 0000000..a10db18
--- /dev/null
+++ b/paste/util/import_string.py
@@ -0,0 +1,95 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+
+"""
+'imports' a string -- converts a string to a Python object, importing
+any necessary modules and evaluating the expression. Everything
+before the : in an import expression is the module path; everything
+after is an expression to be evaluated in the namespace of that
+module.
+
+Alternately, if no : is present, then import the modules and get the
+attributes as necessary. Arbitrary expressions are not allowed in
+that case.
+"""
+
+def eval_import(s):
+ """
+ Import a module, or import an object from a module.
+
+ A module name like ``foo.bar:baz()`` can be used, where
+ ``foo.bar`` is the module, and ``baz()`` is an expression
+ evaluated in the context of that module. Note this is not safe on
+ arbitrary strings because of the eval.
+ """
+ if ':' not in s:
+ return simple_import(s)
+ module_name, expr = s.split(':', 1)
+ module = import_module(module_name)
+ obj = eval(expr, module.__dict__)
+ return obj
+
+def simple_import(s):
+ """
+ Import a module, or import an object from a module.
+
+ A name like ``foo.bar.baz`` can be a module ``foo.bar.baz`` or a
+ module ``foo.bar`` with an object ``baz`` in it, or a module
+ ``foo`` with an object ``bar`` with an attribute ``baz``.
+ """
+ parts = s.split('.')
+ module = import_module(parts[0])
+ name = parts[0]
+ parts = parts[1:]
+ last_import_error = None
+ while parts:
+ name += '.' + parts[0]
+ try:
+ module = import_module(name)
+ parts = parts[1:]
+ except ImportError as e:
+ last_import_error = e
+ break
+ obj = module
+ while parts:
+ try:
+ obj = getattr(module, parts[0])
+ except AttributeError:
+ raise ImportError(
+ "Cannot find %s in module %r (stopped importing modules with error %s)" % (parts[0], module, last_import_error))
+ parts = parts[1:]
+ return obj
+
+def import_module(s):
+ """
+ Import a module.
+ """
+ mod = __import__(s)
+ parts = s.split('.')
+ for part in parts[1:]:
+ mod = getattr(mod, part)
+ return mod
+
+def try_import_module(module_name):
+ """
+ Imports a module, but catches import errors. Only catches errors
+ when that module doesn't exist; if that module itself has an
+ import error it will still get raised. Returns None if the module
+ doesn't exist.
+ """
+ try:
+ return import_module(module_name)
+ except ImportError as e:
+ if not getattr(e, 'args', None):
+ raise
+ desc = e.args[0]
+ if not desc.startswith('No module named '):
+ raise
+ desc = desc[len('No module named '):]
+ # If you import foo.bar.baz, the bad import could be any
+ # of foo.bar.baz, bar.baz, or baz; we'll test them all:
+ parts = module_name.split('.')
+ for i in range(len(parts)):
+ if desc == '.'.join(parts[i:]):
+ return None
+ raise