1*cda5da8dSAndroid Build Coastguard Worker"""Word completion for GNU readline. 2*cda5da8dSAndroid Build Coastguard Worker 3*cda5da8dSAndroid Build Coastguard WorkerThe completer completes keywords, built-ins and globals in a selectable 4*cda5da8dSAndroid Build Coastguard Workernamespace (which defaults to __main__); when completing NAME.NAME..., it 5*cda5da8dSAndroid Build Coastguard Workerevaluates (!) the expression up to the last dot and completes its attributes. 6*cda5da8dSAndroid Build Coastguard Worker 7*cda5da8dSAndroid Build Coastguard WorkerIt's very cool to do "import sys" type "sys.", hit the completion key (twice), 8*cda5da8dSAndroid Build Coastguard Workerand see the list of names defined by the sys module! 9*cda5da8dSAndroid Build Coastguard Worker 10*cda5da8dSAndroid Build Coastguard WorkerTip: to use the tab key as the completion key, call 11*cda5da8dSAndroid Build Coastguard Worker 12*cda5da8dSAndroid Build Coastguard Worker readline.parse_and_bind("tab: complete") 13*cda5da8dSAndroid Build Coastguard Worker 14*cda5da8dSAndroid Build Coastguard WorkerNotes: 15*cda5da8dSAndroid Build Coastguard Worker 16*cda5da8dSAndroid Build Coastguard Worker- Exceptions raised by the completer function are *ignored* (and generally cause 17*cda5da8dSAndroid Build Coastguard Worker the completion to fail). This is a feature -- since readline sets the tty 18*cda5da8dSAndroid Build Coastguard Worker device in raw (or cbreak) mode, printing a traceback wouldn't work well 19*cda5da8dSAndroid Build Coastguard Worker without some complicated hoopla to save, reset and restore the tty state. 20*cda5da8dSAndroid Build Coastguard Worker 21*cda5da8dSAndroid Build Coastguard Worker- The evaluation of the NAME.NAME... form may cause arbitrary application 22*cda5da8dSAndroid Build Coastguard Worker defined code to be executed if an object with a __getattr__ hook is found. 23*cda5da8dSAndroid Build Coastguard Worker Since it is the responsibility of the application (or the user) to enable this 24*cda5da8dSAndroid Build Coastguard Worker feature, I consider this an acceptable risk. More complicated expressions 25*cda5da8dSAndroid Build Coastguard Worker (e.g. function calls or indexing operations) are *not* evaluated. 26*cda5da8dSAndroid Build Coastguard Worker 27*cda5da8dSAndroid Build Coastguard Worker- When the original stdin is not a tty device, GNU readline is never 28*cda5da8dSAndroid Build Coastguard Worker used, and this module (and the readline module) are silently inactive. 29*cda5da8dSAndroid Build Coastguard Worker 30*cda5da8dSAndroid Build Coastguard Worker""" 31*cda5da8dSAndroid Build Coastguard Worker 32*cda5da8dSAndroid Build Coastguard Workerimport atexit 33*cda5da8dSAndroid Build Coastguard Workerimport builtins 34*cda5da8dSAndroid Build Coastguard Workerimport inspect 35*cda5da8dSAndroid Build Coastguard Workerimport keyword 36*cda5da8dSAndroid Build Coastguard Workerimport re 37*cda5da8dSAndroid Build Coastguard Workerimport __main__ 38*cda5da8dSAndroid Build Coastguard Worker 39*cda5da8dSAndroid Build Coastguard Worker__all__ = ["Completer"] 40*cda5da8dSAndroid Build Coastguard Worker 41*cda5da8dSAndroid Build Coastguard Workerclass Completer: 42*cda5da8dSAndroid Build Coastguard Worker def __init__(self, namespace = None): 43*cda5da8dSAndroid Build Coastguard Worker """Create a new completer for the command line. 44*cda5da8dSAndroid Build Coastguard Worker 45*cda5da8dSAndroid Build Coastguard Worker Completer([namespace]) -> completer instance. 46*cda5da8dSAndroid Build Coastguard Worker 47*cda5da8dSAndroid Build Coastguard Worker If unspecified, the default namespace where completions are performed 48*cda5da8dSAndroid Build Coastguard Worker is __main__ (technically, __main__.__dict__). Namespaces should be 49*cda5da8dSAndroid Build Coastguard Worker given as dictionaries. 50*cda5da8dSAndroid Build Coastguard Worker 51*cda5da8dSAndroid Build Coastguard Worker Completer instances should be used as the completion mechanism of 52*cda5da8dSAndroid Build Coastguard Worker readline via the set_completer() call: 53*cda5da8dSAndroid Build Coastguard Worker 54*cda5da8dSAndroid Build Coastguard Worker readline.set_completer(Completer(my_namespace).complete) 55*cda5da8dSAndroid Build Coastguard Worker """ 56*cda5da8dSAndroid Build Coastguard Worker 57*cda5da8dSAndroid Build Coastguard Worker if namespace and not isinstance(namespace, dict): 58*cda5da8dSAndroid Build Coastguard Worker raise TypeError('namespace must be a dictionary') 59*cda5da8dSAndroid Build Coastguard Worker 60*cda5da8dSAndroid Build Coastguard Worker # Don't bind to namespace quite yet, but flag whether the user wants a 61*cda5da8dSAndroid Build Coastguard Worker # specific namespace or to use __main__.__dict__. This will allow us 62*cda5da8dSAndroid Build Coastguard Worker # to bind to __main__.__dict__ at completion time, not now. 63*cda5da8dSAndroid Build Coastguard Worker if namespace is None: 64*cda5da8dSAndroid Build Coastguard Worker self.use_main_ns = 1 65*cda5da8dSAndroid Build Coastguard Worker else: 66*cda5da8dSAndroid Build Coastguard Worker self.use_main_ns = 0 67*cda5da8dSAndroid Build Coastguard Worker self.namespace = namespace 68*cda5da8dSAndroid Build Coastguard Worker 69*cda5da8dSAndroid Build Coastguard Worker def complete(self, text, state): 70*cda5da8dSAndroid Build Coastguard Worker """Return the next possible completion for 'text'. 71*cda5da8dSAndroid Build Coastguard Worker 72*cda5da8dSAndroid Build Coastguard Worker This is called successively with state == 0, 1, 2, ... until it 73*cda5da8dSAndroid Build Coastguard Worker returns None. The completion should begin with 'text'. 74*cda5da8dSAndroid Build Coastguard Worker 75*cda5da8dSAndroid Build Coastguard Worker """ 76*cda5da8dSAndroid Build Coastguard Worker if self.use_main_ns: 77*cda5da8dSAndroid Build Coastguard Worker self.namespace = __main__.__dict__ 78*cda5da8dSAndroid Build Coastguard Worker 79*cda5da8dSAndroid Build Coastguard Worker if not text.strip(): 80*cda5da8dSAndroid Build Coastguard Worker if state == 0: 81*cda5da8dSAndroid Build Coastguard Worker if _readline_available: 82*cda5da8dSAndroid Build Coastguard Worker readline.insert_text('\t') 83*cda5da8dSAndroid Build Coastguard Worker readline.redisplay() 84*cda5da8dSAndroid Build Coastguard Worker return '' 85*cda5da8dSAndroid Build Coastguard Worker else: 86*cda5da8dSAndroid Build Coastguard Worker return '\t' 87*cda5da8dSAndroid Build Coastguard Worker else: 88*cda5da8dSAndroid Build Coastguard Worker return None 89*cda5da8dSAndroid Build Coastguard Worker 90*cda5da8dSAndroid Build Coastguard Worker if state == 0: 91*cda5da8dSAndroid Build Coastguard Worker if "." in text: 92*cda5da8dSAndroid Build Coastguard Worker self.matches = self.attr_matches(text) 93*cda5da8dSAndroid Build Coastguard Worker else: 94*cda5da8dSAndroid Build Coastguard Worker self.matches = self.global_matches(text) 95*cda5da8dSAndroid Build Coastguard Worker try: 96*cda5da8dSAndroid Build Coastguard Worker return self.matches[state] 97*cda5da8dSAndroid Build Coastguard Worker except IndexError: 98*cda5da8dSAndroid Build Coastguard Worker return None 99*cda5da8dSAndroid Build Coastguard Worker 100*cda5da8dSAndroid Build Coastguard Worker def _callable_postfix(self, val, word): 101*cda5da8dSAndroid Build Coastguard Worker if callable(val): 102*cda5da8dSAndroid Build Coastguard Worker word += "(" 103*cda5da8dSAndroid Build Coastguard Worker try: 104*cda5da8dSAndroid Build Coastguard Worker if not inspect.signature(val).parameters: 105*cda5da8dSAndroid Build Coastguard Worker word += ")" 106*cda5da8dSAndroid Build Coastguard Worker except ValueError: 107*cda5da8dSAndroid Build Coastguard Worker pass 108*cda5da8dSAndroid Build Coastguard Worker 109*cda5da8dSAndroid Build Coastguard Worker return word 110*cda5da8dSAndroid Build Coastguard Worker 111*cda5da8dSAndroid Build Coastguard Worker def global_matches(self, text): 112*cda5da8dSAndroid Build Coastguard Worker """Compute matches when text is a simple name. 113*cda5da8dSAndroid Build Coastguard Worker 114*cda5da8dSAndroid Build Coastguard Worker Return a list of all keywords, built-in functions and names currently 115*cda5da8dSAndroid Build Coastguard Worker defined in self.namespace that match. 116*cda5da8dSAndroid Build Coastguard Worker 117*cda5da8dSAndroid Build Coastguard Worker """ 118*cda5da8dSAndroid Build Coastguard Worker matches = [] 119*cda5da8dSAndroid Build Coastguard Worker seen = {"__builtins__"} 120*cda5da8dSAndroid Build Coastguard Worker n = len(text) 121*cda5da8dSAndroid Build Coastguard Worker for word in keyword.kwlist + keyword.softkwlist: 122*cda5da8dSAndroid Build Coastguard Worker if word[:n] == text: 123*cda5da8dSAndroid Build Coastguard Worker seen.add(word) 124*cda5da8dSAndroid Build Coastguard Worker if word in {'finally', 'try'}: 125*cda5da8dSAndroid Build Coastguard Worker word = word + ':' 126*cda5da8dSAndroid Build Coastguard Worker elif word not in {'False', 'None', 'True', 127*cda5da8dSAndroid Build Coastguard Worker 'break', 'continue', 'pass', 128*cda5da8dSAndroid Build Coastguard Worker 'else', '_'}: 129*cda5da8dSAndroid Build Coastguard Worker word = word + ' ' 130*cda5da8dSAndroid Build Coastguard Worker matches.append(word) 131*cda5da8dSAndroid Build Coastguard Worker for nspace in [self.namespace, builtins.__dict__]: 132*cda5da8dSAndroid Build Coastguard Worker for word, val in nspace.items(): 133*cda5da8dSAndroid Build Coastguard Worker if word[:n] == text and word not in seen: 134*cda5da8dSAndroid Build Coastguard Worker seen.add(word) 135*cda5da8dSAndroid Build Coastguard Worker matches.append(self._callable_postfix(val, word)) 136*cda5da8dSAndroid Build Coastguard Worker return matches 137*cda5da8dSAndroid Build Coastguard Worker 138*cda5da8dSAndroid Build Coastguard Worker def attr_matches(self, text): 139*cda5da8dSAndroid Build Coastguard Worker """Compute matches when text contains a dot. 140*cda5da8dSAndroid Build Coastguard Worker 141*cda5da8dSAndroid Build Coastguard Worker Assuming the text is of the form NAME.NAME....[NAME], and is 142*cda5da8dSAndroid Build Coastguard Worker evaluable in self.namespace, it will be evaluated and its attributes 143*cda5da8dSAndroid Build Coastguard Worker (as revealed by dir()) are used as possible completions. (For class 144*cda5da8dSAndroid Build Coastguard Worker instances, class members are also considered.) 145*cda5da8dSAndroid Build Coastguard Worker 146*cda5da8dSAndroid Build Coastguard Worker WARNING: this can still invoke arbitrary C code, if an object 147*cda5da8dSAndroid Build Coastguard Worker with a __getattr__ hook is evaluated. 148*cda5da8dSAndroid Build Coastguard Worker 149*cda5da8dSAndroid Build Coastguard Worker """ 150*cda5da8dSAndroid Build Coastguard Worker m = re.match(r"(\w+(\.\w+)*)\.(\w*)", text) 151*cda5da8dSAndroid Build Coastguard Worker if not m: 152*cda5da8dSAndroid Build Coastguard Worker return [] 153*cda5da8dSAndroid Build Coastguard Worker expr, attr = m.group(1, 3) 154*cda5da8dSAndroid Build Coastguard Worker try: 155*cda5da8dSAndroid Build Coastguard Worker thisobject = eval(expr, self.namespace) 156*cda5da8dSAndroid Build Coastguard Worker except Exception: 157*cda5da8dSAndroid Build Coastguard Worker return [] 158*cda5da8dSAndroid Build Coastguard Worker 159*cda5da8dSAndroid Build Coastguard Worker # get the content of the object, except __builtins__ 160*cda5da8dSAndroid Build Coastguard Worker words = set(dir(thisobject)) 161*cda5da8dSAndroid Build Coastguard Worker words.discard("__builtins__") 162*cda5da8dSAndroid Build Coastguard Worker 163*cda5da8dSAndroid Build Coastguard Worker if hasattr(thisobject, '__class__'): 164*cda5da8dSAndroid Build Coastguard Worker words.add('__class__') 165*cda5da8dSAndroid Build Coastguard Worker words.update(get_class_members(thisobject.__class__)) 166*cda5da8dSAndroid Build Coastguard Worker matches = [] 167*cda5da8dSAndroid Build Coastguard Worker n = len(attr) 168*cda5da8dSAndroid Build Coastguard Worker if attr == '': 169*cda5da8dSAndroid Build Coastguard Worker noprefix = '_' 170*cda5da8dSAndroid Build Coastguard Worker elif attr == '_': 171*cda5da8dSAndroid Build Coastguard Worker noprefix = '__' 172*cda5da8dSAndroid Build Coastguard Worker else: 173*cda5da8dSAndroid Build Coastguard Worker noprefix = None 174*cda5da8dSAndroid Build Coastguard Worker while True: 175*cda5da8dSAndroid Build Coastguard Worker for word in words: 176*cda5da8dSAndroid Build Coastguard Worker if (word[:n] == attr and 177*cda5da8dSAndroid Build Coastguard Worker not (noprefix and word[:n+1] == noprefix)): 178*cda5da8dSAndroid Build Coastguard Worker match = "%s.%s" % (expr, word) 179*cda5da8dSAndroid Build Coastguard Worker if isinstance(getattr(type(thisobject), word, None), 180*cda5da8dSAndroid Build Coastguard Worker property): 181*cda5da8dSAndroid Build Coastguard Worker # bpo-44752: thisobject.word is a method decorated by 182*cda5da8dSAndroid Build Coastguard Worker # `@property`. What follows applies a postfix if 183*cda5da8dSAndroid Build Coastguard Worker # thisobject.word is callable, but know we know that 184*cda5da8dSAndroid Build Coastguard Worker # this is not callable (because it is a property). 185*cda5da8dSAndroid Build Coastguard Worker # Also, getattr(thisobject, word) will evaluate the 186*cda5da8dSAndroid Build Coastguard Worker # property method, which is not desirable. 187*cda5da8dSAndroid Build Coastguard Worker matches.append(match) 188*cda5da8dSAndroid Build Coastguard Worker continue 189*cda5da8dSAndroid Build Coastguard Worker if (value := getattr(thisobject, word, None)) is not None: 190*cda5da8dSAndroid Build Coastguard Worker matches.append(self._callable_postfix(value, match)) 191*cda5da8dSAndroid Build Coastguard Worker else: 192*cda5da8dSAndroid Build Coastguard Worker matches.append(match) 193*cda5da8dSAndroid Build Coastguard Worker if matches or not noprefix: 194*cda5da8dSAndroid Build Coastguard Worker break 195*cda5da8dSAndroid Build Coastguard Worker if noprefix == '_': 196*cda5da8dSAndroid Build Coastguard Worker noprefix = '__' 197*cda5da8dSAndroid Build Coastguard Worker else: 198*cda5da8dSAndroid Build Coastguard Worker noprefix = None 199*cda5da8dSAndroid Build Coastguard Worker matches.sort() 200*cda5da8dSAndroid Build Coastguard Worker return matches 201*cda5da8dSAndroid Build Coastguard Worker 202*cda5da8dSAndroid Build Coastguard Workerdef get_class_members(klass): 203*cda5da8dSAndroid Build Coastguard Worker ret = dir(klass) 204*cda5da8dSAndroid Build Coastguard Worker if hasattr(klass,'__bases__'): 205*cda5da8dSAndroid Build Coastguard Worker for base in klass.__bases__: 206*cda5da8dSAndroid Build Coastguard Worker ret = ret + get_class_members(base) 207*cda5da8dSAndroid Build Coastguard Worker return ret 208*cda5da8dSAndroid Build Coastguard Worker 209*cda5da8dSAndroid Build Coastguard Workertry: 210*cda5da8dSAndroid Build Coastguard Worker import readline 211*cda5da8dSAndroid Build Coastguard Workerexcept ImportError: 212*cda5da8dSAndroid Build Coastguard Worker _readline_available = False 213*cda5da8dSAndroid Build Coastguard Workerelse: 214*cda5da8dSAndroid Build Coastguard Worker readline.set_completer(Completer().complete) 215*cda5da8dSAndroid Build Coastguard Worker # Release references early at shutdown (the readline module's 216*cda5da8dSAndroid Build Coastguard Worker # contents are quasi-immortal, and the completer function holds a 217*cda5da8dSAndroid Build Coastguard Worker # reference to globals). 218*cda5da8dSAndroid Build Coastguard Worker atexit.register(lambda: readline.set_completer(None)) 219*cda5da8dSAndroid Build Coastguard Worker _readline_available = True 220