]>
Commit | Line | Data |
---|---|---|
53e6db90 DC |
1 | import sys |
2 | import types | |
3 | ||
4 | from pydoc import safeimport, resolve, ErrorDuringImport | |
5 | from pkgutil import iter_modules | |
6 | ||
7 | from elpy import compat | |
8 | ||
9 | # Types we want to recurse into (nodes). | |
10 | CONTAINER_TYPES = (type, types.ModuleType) | |
11 | # Types of attributes we can get documentation for (leaves). | |
12 | PYDOC_TYPES = (type, | |
13 | types.FunctionType, | |
14 | types.BuiltinFunctionType, | |
15 | types.BuiltinMethodType, | |
16 | types.MethodType, | |
17 | types.ModuleType) | |
18 | if not compat.PYTHON3: # pragma: nocover | |
19 | # Python 2 old style classes | |
20 | CONTAINER_TYPES = tuple(list(CONTAINER_TYPES) + [types.ClassType]) | |
21 | PYDOC_TYPES = tuple(list(PYDOC_TYPES) + [types.ClassType]) | |
22 | ||
23 | ||
24 | def get_pydoc_completions(modulename): | |
25 | """Get possible completions for modulename for pydoc. | |
26 | ||
27 | Returns a list of possible values to be passed to pydoc. | |
28 | ||
29 | """ | |
30 | modulename = compat.ensure_not_unicode(modulename) | |
31 | modulename = modulename.rstrip(".") | |
32 | if modulename == "": | |
33 | return sorted(get_modules()) | |
34 | candidates = get_completions(modulename) | |
35 | if candidates: | |
36 | return sorted(candidates) | |
37 | needle = modulename | |
38 | if "." in needle: | |
39 | modulename, part = needle.rsplit(".", 1) | |
40 | candidates = get_completions(modulename) | |
41 | else: | |
42 | candidates = get_modules() | |
43 | return sorted(candidate for candidate in candidates | |
44 | if candidate.startswith(needle)) | |
45 | ||
46 | ||
47 | def get_completions(modulename): | |
48 | modules = set("{0}.{1}".format(modulename, module) | |
49 | for module in get_modules(modulename)) | |
50 | ||
51 | try: | |
52 | module, name = resolve(modulename) | |
53 | except ImportError: | |
54 | return modules | |
55 | if isinstance(module, CONTAINER_TYPES): | |
56 | modules.update("{0}.{1}".format(modulename, name) | |
57 | for name in dir(module) | |
58 | if not name.startswith("_") and | |
59 | isinstance(getattr(module, name), | |
60 | PYDOC_TYPES)) | |
61 | return modules | |
62 | ||
63 | ||
64 | def get_modules(modulename=None): | |
65 | """Return a list of modules and packages under modulename. | |
66 | ||
67 | If modulename is not given, return a list of all top level modules | |
68 | and packages. | |
69 | ||
70 | """ | |
71 | modulename = compat.ensure_not_unicode(modulename) | |
72 | if not modulename: | |
73 | try: | |
74 | return ([modname for (importer, modname, ispkg) | |
75 | in iter_modules() | |
76 | if not modname.startswith("_")] + | |
77 | list(sys.builtin_module_names)) | |
78 | except OSError: | |
79 | # Bug in Python 2.6, see #275 | |
80 | return list(sys.builtin_module_names) | |
81 | try: | |
82 | module = safeimport(modulename) | |
83 | except ErrorDuringImport: | |
84 | return [] | |
85 | if module is None: | |
86 | return [] | |
87 | if hasattr(module, "__path__"): | |
88 | return [modname for (importer, modname, ispkg) | |
89 | in iter_modules(module.__path__) | |
90 | if not modname.startswith("_")] | |
91 | return [] |