70 |
71 |
71 Completer instances should be used as the completion mechanism of |
72 Completer instances should be used as the completion mechanism of |
72 readline via the set_completer() call: |
73 readline via the set_completer() call: |
73 |
74 |
74 readline.set_completer(Completer(my_namespace).complete) |
75 readline.set_completer(Completer(my_namespace).complete) |
75 |
76 |
76 @param namespace The namespace for the completer. |
77 @param namespace The namespace for the completer. |
77 @exception TypeError raised to indicate a wrong data structure of |
78 @exception TypeError raised to indicate a wrong data structure of |
78 the namespace object |
79 the namespace object |
79 """ |
80 """ |
80 if namespace and not isinstance(namespace, dict): |
81 if namespace and not isinstance(namespace, dict): |
81 raise TypeError('namespace must be a dictionary') |
82 raise TypeError("namespace must be a dictionary") |
82 |
83 |
83 # Don't bind to namespace quite yet, but flag whether the user wants a |
84 # Don't bind to namespace quite yet, but flag whether the user wants a |
84 # specific namespace or to use __main__.__dict__. This will allow us |
85 # specific namespace or to use __main__.__dict__. This will allow us |
85 # to bind to __main__.__dict__ at completion time, not now. |
86 # to bind to __main__.__dict__ at completion time, not now. |
86 if namespace is None: |
87 if namespace is None: |
93 """ |
94 """ |
94 Public method to return the next possible completion for 'text'. |
95 Public method to return the next possible completion for 'text'. |
95 |
96 |
96 This is called successively with state == 0, 1, 2, ... until it |
97 This is called successively with state == 0, 1, 2, ... until it |
97 returns None. The completion should begin with 'text'. |
98 returns None. The completion should begin with 'text'. |
98 |
99 |
99 @param text The text to be completed. (string) |
100 @param text The text to be completed. (string) |
100 @param state The state of the completion. (integer) |
101 @param state The state of the completion. (integer) |
101 @return The possible completions as a list of strings. |
102 @return The possible completions as a list of strings. |
102 """ |
103 """ |
103 if self.use_main_ns: |
104 if self.use_main_ns: |
104 self.namespace = __main__.__dict__ |
105 self.namespace = __main__.__dict__ |
105 |
106 |
106 if state == 0: |
107 if state == 0: |
107 if "." in text: |
108 if "." in text: |
108 self.matches = self.attr_matches(text) |
109 self.matches = self.attr_matches(text) |
109 else: |
110 else: |
110 self.matches = self.global_matches(text) |
111 self.matches = self.global_matches(text) |
132 @param text The text to be completed. (string) |
133 @param text The text to be completed. (string) |
133 @return A list of all keywords, built-in functions and names currently |
134 @return A list of all keywords, built-in functions and names currently |
134 defined in self.namespace that match. |
135 defined in self.namespace that match. |
135 """ |
136 """ |
136 import keyword |
137 import keyword |
|
138 |
137 matches = [] |
139 matches = [] |
138 seen = {"__builtins__"} |
140 seen = {"__builtins__"} |
139 n = len(text) |
141 n = len(text) |
140 for word in keyword.kwlist: |
142 for word in keyword.kwlist: |
141 if word[:n] == text: |
143 if word[:n] == text: |
142 seen.add(word) |
144 seen.add(word) |
143 if word in {'finally', 'try'}: |
145 if word in {"finally", "try"}: |
144 word += ':' |
146 word += ":" |
145 elif word not in {'False', 'None', 'True', |
147 elif word not in { |
146 'break', 'continue', 'pass', |
148 "False", |
147 'else'}: |
149 "None", |
148 word += ' ' |
150 "True", |
|
151 "break", |
|
152 "continue", |
|
153 "pass", |
|
154 "else", |
|
155 }: |
|
156 word += " " |
149 matches.append(word) |
157 matches.append(word) |
150 for nspace in [self.namespace, builtins.__dict__]: |
158 for nspace in [self.namespace, builtins.__dict__]: |
151 for word, val in nspace.items(): |
159 for word, val in nspace.items(): |
152 if word[:n] == text and word not in seen: |
160 if word[:n] == text and word not in seen: |
153 seen.add(word) |
161 seen.add(word) |
163 (as revealed by dir()) are used as possible completions. (For class |
171 (as revealed by dir()) are used as possible completions. (For class |
164 instances, class members are are also considered.) |
172 instances, class members are are also considered.) |
165 |
173 |
166 <b>WARNING</b>: this can still invoke arbitrary C code, if an object |
174 <b>WARNING</b>: this can still invoke arbitrary C code, if an object |
167 with a __getattr__ hook is evaluated. |
175 with a __getattr__ hook is evaluated. |
168 |
176 |
169 @param text The text to be completed. (string) |
177 @param text The text to be completed. (string) |
170 @return A list of all matches. |
178 @return A list of all matches. |
171 """ |
179 """ |
172 import re |
180 import re |
173 |
181 |
174 m = re.match(r"(\w+(\.\w+)*)\.(\w*)", text) |
182 m = re.match(r"(\w+(\.\w+)*)\.(\w*)", text) |
175 if not m: |
183 if not m: |
176 return [] |
184 return [] |
177 expr, attr = m.group(1, 3) |
185 expr, attr = m.group(1, 3) |
178 try: |
186 try: |
179 thisobject = eval(expr, self.namespace) # secok |
187 thisobject = eval(expr, self.namespace) # secok |
180 except Exception: |
188 except Exception: |
181 return [] |
189 return [] |
182 |
190 |
183 # get the content of the object, except __builtins__ |
191 # get the content of the object, except __builtins__ |
184 words = set(dir(thisobject)) |
192 words = set(dir(thisobject)) |
185 words.discard("__builtins__") |
193 words.discard("__builtins__") |
186 |
194 |
187 if hasattr(object, '__class__'): |
195 if hasattr(object, "__class__"): |
188 words.add('__class__') |
196 words.add("__class__") |
189 words.update(get_class_members(thisobject.__class__)) |
197 words.update(get_class_members(thisobject.__class__)) |
190 matches = [] |
198 matches = [] |
191 n = len(attr) |
199 n = len(attr) |
192 if attr == '': |
200 if attr == "": |
193 noprefix = '_' |
201 noprefix = "_" |
194 elif attr == '_': |
202 elif attr == "_": |
195 noprefix = '__' |
203 noprefix = "__" |
196 else: |
204 else: |
197 noprefix = None |
205 noprefix = None |
198 while True: |
206 while True: |
199 for word in words: |
207 for word in words: |
200 if (word[:n] == attr and |
208 if word[:n] == attr and not (noprefix and word[: n + 1] == noprefix): |
201 not (noprefix and word[:n + 1] == noprefix)): |
|
202 match = "{0}.{1}".format(expr, word) |
209 match = "{0}.{1}".format(expr, word) |
203 try: |
210 try: |
204 val = getattr(thisobject, word) |
211 val = getattr(thisobject, word) |
205 except Exception: # secok |
212 except Exception: # secok |
206 pass # Include even if attribute not set |
213 pass # Include even if attribute not set |
207 else: |
214 else: |
208 match = self._callable_postfix(val, match) |
215 match = self._callable_postfix(val, match) |
209 matches.append(match) |
216 matches.append(match) |
210 if matches or not noprefix: |
217 if matches or not noprefix: |
211 break |
218 break |
212 noprefix = '__' if noprefix == '_' else None |
219 noprefix = "__" if noprefix == "_" else None |
213 matches.sort() |
220 matches.sort() |
214 return matches |
221 return matches |
215 |
222 |
216 |
223 |
217 def get_class_members(klass): |
224 def get_class_members(klass): |
218 """ |
225 """ |
219 Module function to retrieve the class members. |
226 Module function to retrieve the class members. |
220 |
227 |
221 @param klass The class object to be analysed. |
228 @param klass The class object to be analysed. |
222 @return A list of all names defined in the class. |
229 @return A list of all names defined in the class. |
223 """ |
230 """ |
224 ret = dir(klass) |
231 ret = dir(klass) |
225 if hasattr(klass, '__bases__'): |
232 if hasattr(klass, "__bases__"): |
226 for base in klass.__bases__: |
233 for base in klass.__bases__: |
227 ret += get_class_members(base) |
234 ret += get_class_members(base) |
228 return ret |
235 return ret |
229 |
236 |
|
237 |
230 # |
238 # |
231 # eflag: noqa = M111 |
239 # eflag: noqa = M111 |