|
1 # Copyright 2000-2004 Michael Hudson mwh@python.net |
|
2 # |
|
3 # All Rights Reserved |
|
4 # |
|
5 # |
|
6 # Permission to use, copy, modify, and distribute this software and |
|
7 # its documentation for any purpose is hereby granted without fee, |
|
8 # provided that the above copyright notice appear in all copies and |
|
9 # that both that copyright notice and this permission notice appear in |
|
10 # supporting documentation. |
|
11 # |
|
12 # THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO |
|
13 # THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY |
|
14 # AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, |
|
15 # INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER |
|
16 # RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF |
|
17 # CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
|
18 # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
|
19 |
|
20 import __builtin__ |
|
21 |
|
22 class Completer: |
|
23 def __init__(self, ns): |
|
24 self.ns = ns |
|
25 |
|
26 def complete(self, text): |
|
27 if "." in text: |
|
28 return self.attr_matches(text) |
|
29 else: |
|
30 return self.global_matches(text) |
|
31 |
|
32 def global_matches(self, text): |
|
33 """Compute matches when text is a simple name. |
|
34 |
|
35 Return a list of all keywords, built-in functions and names |
|
36 currently defines in __main__ that match. |
|
37 |
|
38 """ |
|
39 import keyword |
|
40 matches = [] |
|
41 n = len(text) |
|
42 for list in [keyword.kwlist, |
|
43 __builtin__.__dict__.keys(), |
|
44 self.ns.keys()]: |
|
45 for word in list: |
|
46 if word[:n] == text and word != "__builtins__": |
|
47 matches.append(word) |
|
48 return matches |
|
49 |
|
50 def attr_matches(self, text): |
|
51 """Compute matches when text contains a dot. |
|
52 |
|
53 Assuming the text is of the form NAME.NAME....[NAME], and is |
|
54 evaluatable in the globals of __main__, it will be evaluated |
|
55 and its attributes (as revealed by dir()) are used as possible |
|
56 completions. (For class instances, class members are are also |
|
57 considered.) |
|
58 |
|
59 WARNING: this can still invoke arbitrary C code, if an object |
|
60 with a __getattr__ hook is evaluated. |
|
61 |
|
62 """ |
|
63 import re |
|
64 m = re.match(r"(\w+(\.\w+)*)\.(\w*)", text) |
|
65 if not m: |
|
66 return [] |
|
67 expr, attr = m.group(1, 3) |
|
68 object = eval(expr, self.ns) |
|
69 words = dir(object) |
|
70 if hasattr(object, '__class__'): |
|
71 words.append('__class__') |
|
72 words = words + get_class_members(object.__class__) |
|
73 matches = [] |
|
74 n = len(attr) |
|
75 for word in words: |
|
76 if word[:n] == attr and word != "__builtins__": |
|
77 matches.append("%s.%s" % (expr, word)) |
|
78 return matches |
|
79 |
|
80 def get_class_members(klass): |
|
81 ret = dir(klass) |
|
82 if hasattr(klass, '__bases__'): |
|
83 for base in klass.__bases__: |
|
84 ret = ret + get_class_members(base) |
|
85 return ret |
|
86 |
|
87 |