| 108 | return names |
| 109 | |
| 110 | def _attr_matches(self, text): |
| 111 | expr, attr = text.rsplit('.', 1) |
| 112 | if '(' in expr or ')' in expr: # don't call functions |
| 113 | return expr, attr, [], [] |
| 114 | try: |
| 115 | thisobject = eval(expr, self.namespace) |
| 116 | except Exception: |
| 117 | return expr, attr, [], [] |
| 118 | |
| 119 | # get the content of the object, except __builtins__ |
| 120 | words = set(dir(thisobject)) - {'__builtins__'} |
| 121 | |
| 122 | if hasattr(thisobject, '__class__'): |
| 123 | words.add('__class__') |
| 124 | words.update(rlcompleter.get_class_members(thisobject.__class__)) |
| 125 | names = [] |
| 126 | values = [] |
| 127 | n = len(attr) |
| 128 | if attr == '': |
| 129 | noprefix = '_' |
| 130 | elif attr == '_': |
| 131 | noprefix = '__' |
| 132 | else: |
| 133 | noprefix = None |
| 134 | |
| 135 | # sort the words now to make sure to return completions in |
| 136 | # alphabetical order. It's easier to do it now, else we would need to |
| 137 | # sort 'names' later but make sure that 'values' in kept in sync, |
| 138 | # which is annoying. |
| 139 | words = sorted(words) |
| 140 | while True: |
| 141 | for word in words: |
| 142 | if ( |
| 143 | word[:n] == attr |
| 144 | and not (noprefix and word[:n+1] == noprefix) |
| 145 | ): |
| 146 | # Mirror rlcompleter's safeguards so completion does not |
| 147 | # call properties or reify lazy module attributes. |
| 148 | if isinstance(getattr(type(thisobject), word, None), property): |
| 149 | value = None |
| 150 | elif ( |
| 151 | isinstance(thisobject, types.ModuleType) |
| 152 | and isinstance( |
| 153 | thisobject.__dict__.get(word), |
| 154 | types.LazyImportType, |
| 155 | ) |
| 156 | ): |
| 157 | value = thisobject.__dict__.get(word) |
| 158 | else: |
| 159 | value = getattr(thisobject, word, None) |
| 160 | |
| 161 | names.append(word) |
| 162 | values.append(value) |
| 163 | if names or not noprefix: |
| 164 | break |
| 165 | if noprefix == '_': |
| 166 | noprefix = '__' |
| 167 | else: |