Compute matches when text contains a dot. Assuming the text is of the form NAME.NAME....[NAME], and is evaluable in self.namespace, it will be evaluated and its attributes (as revealed by dir()) are used as possible completions. (For class instances, class members are also considered.) W
(self, text)
| 163 | return [match for (_, match) in matches] |
| 164 | |
| 165 | def attr_matches(self, text): |
| 166 | """Compute matches when text contains a dot. |
| 167 | |
| 168 | Assuming the text is of the form NAME.NAME....[NAME], and is |
| 169 | evaluable in self.namespace, it will be evaluated and its attributes |
| 170 | (as revealed by dir()) are used as possible completions. (For class |
| 171 | instances, class members are also considered.) |
| 172 | |
| 173 | WARNING: this can still invoke arbitrary C code, if an object |
| 174 | with a __getattr__ hook is evaluated. |
| 175 | |
| 176 | """ |
| 177 | import re |
| 178 | m = re.match(r"([\w\[\]]+(\.[\w\[\]]+)*)\.([\w\[\]]*)", text) |
| 179 | if not m: |
| 180 | return [] |
| 181 | expr, attr = m.group(1, 3) |
| 182 | try: |
| 183 | thisobject = eval(expr, self.namespace) |
| 184 | except Exception: |
| 185 | return [] |
| 186 | |
| 187 | # get the content of the object, except __builtins__ |
| 188 | words = set(dir(thisobject)) |
| 189 | words.discard("__builtins__") |
| 190 | |
| 191 | if hasattr(thisobject, '__class__'): |
| 192 | words.add('__class__') |
| 193 | words.update(get_class_members(thisobject.__class__)) |
| 194 | matches = [] |
| 195 | n = len(attr) |
| 196 | if attr == '': |
| 197 | noprefix = '_' |
| 198 | elif attr == '_': |
| 199 | noprefix = '__' |
| 200 | else: |
| 201 | noprefix = None |
| 202 | while True: |
| 203 | for word in words: |
| 204 | score = fuzzy_match(word, attr) |
| 205 | if score is not None and (word[:n] == attr and not (noprefix and word[:n + 1] == noprefix)): |
| 206 | match = f"{expr}.{word}" |
| 207 | try: |
| 208 | val = inspect.getattr_static(thisobject, word) |
| 209 | except Exception: |
| 210 | pass # Include even if attribute not set |
| 211 | else: |
| 212 | match = self._callable_postfix(val, match) |
| 213 | matches.append((-score, match)) |
| 214 | if matches or not noprefix: |
| 215 | break |
| 216 | if noprefix == '_': |
| 217 | noprefix = '__' |
| 218 | else: |
| 219 | noprefix = None |
| 220 | matches.sort() |
| 221 | return [match for (_, match) in matches] |
| 222 |
no test coverage detected