1from __future__ import absolute_import
2
3import os
4import imp
5import sys
6import re
7import marshal
8import warnings
9
10try:
11    unicode
12except NameError:
13    unicode = str
14
15
16if sys.version_info[0] == 2:
17    from StringIO import StringIO as BytesIO
18    from StringIO import StringIO
19
20else:
21    from io import BytesIO, StringIO
22
23
24
25def imp_find_module(name, path=None):
26    """
27    same as imp.find_module, but handles dotted names
28    """
29    names = name.split('.')
30    if path is not None:
31        if isinstance(path, (str, unicode)):
32            path = [os.path.realpath(path)]
33    for name in names:
34        result = imp.find_module(name, path)
35        if result[0] is not None:
36            result[0].close()
37        path = [result[1]]
38    return result
39
40def _check_importer_for_path(name, path_item):
41    try:
42        importer = sys.path_importer_cache[path_item]
43    except KeyError:
44        for path_hook in sys.path_hooks:
45            try:
46                importer = path_hook(path_item)
47                break
48            except ImportError:
49                pass
50        else:
51            importer = None
52        sys.path_importer_cache.setdefault(path_item, importer)
53
54
55    if importer is None:
56        try:
57            return imp.find_module(name, [path_item])
58        except ImportError:
59            return None
60    return importer.find_module(name)
61
62def imp_walk(name):
63    """
64    yields namepart, tuple_or_importer for each path item
65
66    raise ImportError if a name can not be found.
67    """
68    warnings.warn("imp_walk will be removed in a future version", DeprecationWarning)
69
70    if name in sys.builtin_module_names:
71        yield name, (None, None, ("", "", imp.C_BUILTIN))
72        return
73    paths = sys.path
74    res = None
75    for namepart in name.split('.'):
76        for path_item in paths:
77            res = _check_importer_for_path(namepart, path_item)
78            if hasattr(res, 'load_module'):
79                if res.path.endswith('.py') or res.path.endswith('.pyw'):
80                    fp = StringIO(res.get_source(namepart))
81                    res = (fp, res.path, ('.py', 'rU', imp.PY_SOURCE))
82                elif res.path.endswith('.pyc') or res.path.endswith('.pyo'):
83                    co  = res.get_code(namepart)
84                    fp = BytesIO(imp.get_magic() + b'\0\0\0\0' + marshal.dumps(co))
85                    res = (fp, res.path, ('.pyc', 'rb', imp.PY_COMPILED))
86
87                else:
88                    res = (None, loader.path, (os.path.splitext(loader.path)[-1], 'rb', imp.C_EXTENSION))
89
90                break
91            elif isinstance(res, tuple):
92                break
93        else:
94            break
95
96        yield namepart, res
97        paths = [os.path.join(path_item, namepart)]
98    else:
99        return
100
101    raise ImportError('No module named %s' % (name,))
102
103
104cookie_re = re.compile(b"coding[:=]\s*([-\w.]+)")
105if sys.version_info[0] == 2:
106    default_encoding = 'ascii'
107else:
108    default_encoding = 'utf-8'
109
110def guess_encoding(fp):
111
112    for i in range(2):
113        ln = fp.readline()
114
115        m = cookie_re.search(ln)
116        if m is not None:
117            return m.group(1).decode('ascii')
118
119    return default_encoding
120