0
|
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 |
|