1import inspect
2import six
3import sys
4
5from importlib import import_module
6
7from django.core.exceptions import ImproperlyConfigured
8
9
10def isuppercase(name):
11    return name == name.upper() and not name.startswith('_')
12
13
14def uppercase_attributes(obj):
15    return dict((name, getattr(obj, name))
16                for name in filter(isuppercase, dir(obj)))
17
18
19def import_by_path(dotted_path, error_prefix=''):
20    """
21    Import a dotted module path and return the attribute/class designated by
22    the last name in the path. Raise ImproperlyConfigured if something goes
23    wrong.
24
25    Backported from Django 1.6.
26    """
27    try:
28        module_path, class_name = dotted_path.rsplit('.', 1)
29    except ValueError:
30        raise ImproperlyConfigured("{0}{1} doesn't look like "
31                                   "a module path".format(error_prefix,
32                                                          dotted_path))
33    try:
34        module = import_module(module_path)
35    except ImportError as err:
36        msg = '{0}Error importing module {1}: "{2}"'.format(error_prefix,
37                                                            module_path,
38                                                            err)
39        six.reraise(ImproperlyConfigured, ImproperlyConfigured(msg),
40                    sys.exc_info()[2])
41    try:
42        attr = getattr(module, class_name)
43    except AttributeError:
44        raise ImproperlyConfigured('{0}Module "{1}" does not define a '
45                                   '"{2}" attribute/class'.format(error_prefix,
46                                                                  module_path,
47                                                                  class_name))
48    return attr
49
50
51def reraise(exc, prefix=None, suffix=None):
52    args = exc.args
53    if not args:
54        args = ('',)
55    if prefix is None:
56        prefix = ''
57    elif not prefix.endswith((':', ': ')):
58        prefix = prefix + ': '
59    if suffix is None:
60        suffix = ''
61    elif not (suffix.startswith('(') and suffix.endswith(')')):
62        suffix = '(' + suffix + ')'
63    exc.args = ('{0} {1} {2}'.format(prefix, args[0], suffix),) + args[1:]
64    raise
65
66
67# Copied over from Sphinx
68if sys.version_info >= (3, 0):
69    from functools import partial
70
71    def getargspec(func):
72        """Like inspect.getargspec but supports functools.partial as well."""
73        if inspect.ismethod(func):
74            func = func.__func__
75        if type(func) is partial:
76            orig_func = func.func
77            argspec = getargspec(orig_func)
78            args = list(argspec[0])
79            defaults = list(argspec[3] or ())
80            kwoargs = list(argspec[4])
81            kwodefs = dict(argspec[5] or {})
82            if func.args:
83                args = args[len(func.args):]
84            for arg in func.keywords or ():
85                try:
86                    i = args.index(arg) - len(args)
87                    del args[i]
88                    try:
89                        del defaults[i]
90                    except IndexError:
91                        pass
92                except ValueError:   # must be a kwonly arg
93                    i = kwoargs.index(arg)
94                    del kwoargs[i]
95                    del kwodefs[arg]
96            return inspect.FullArgSpec(args, argspec[1], argspec[2],
97                                       tuple(defaults), kwoargs,
98                                       kwodefs, argspec[6])
99        while hasattr(func, '__wrapped__'):
100            func = func.__wrapped__
101        if not inspect.isfunction(func):
102            raise TypeError('%r is not a Python function' % func)
103        return inspect.getfullargspec(func)
104
105else:  # 2.6, 2.7
106    from functools import partial
107
108    def getargspec(func):
109        """Like inspect.getargspec but supports functools.partial as well."""
110        if inspect.ismethod(func):
111            func = func.im_func
112        parts = 0, ()
113        if type(func) is partial:
114            keywords = func.keywords
115            if keywords is None:
116                keywords = {}
117            parts = len(func.args), keywords.keys()
118            func = func.func
119        if not inspect.isfunction(func):
120            raise TypeError('%r is not a Python function' % func)
121        args, varargs, varkw = inspect.getargs(func.func_code)
122        func_defaults = func.func_defaults
123        if func_defaults is None:
124            func_defaults = []
125        else:
126            func_defaults = list(func_defaults)
127        if parts[0]:
128            args = args[parts[0]:]
129        if parts[1]:
130            for arg in parts[1]:
131                i = args.index(arg) - len(args)
132                del args[i]
133                try:
134                    del func_defaults[i]
135                except IndexError:
136                    pass
137        return inspect.ArgSpec(args, varargs, varkw, func_defaults)
138