def set_p_str(self): import os, time # needed in locals for prompt string handling loc = locals() self.p_str = ItplNS( '%s%s%s' % ('${self.col_p2}', multiple_replace(prompt_specials, self.p_template), '$self.col_norm'), self.cache.user_ns, loc) self.p_str_nocolor = ItplNS( multiple_replace(prompt_specials_nocolor, self.p_template), self.cache.user_ns, loc)
def set_p_str(self): """ Set the interpolating prompt strings. This must be called every time the color settings change, because the prompt_specials global may have changed.""" import os,time # needed in locals for prompt string handling loc = locals() self.p_str = ItplNS('%s%s%s' % ('${self.sep}${self.col_p}', multiple_replace(prompt_specials, self.p_template), '${self.col_norm}'),self.cache.user_ns,loc) self.p_str_nocolor = ItplNS(multiple_replace(prompt_specials_nocolor, self.p_template), self.cache.user_ns,loc)
def extend_shell_behavior(ip): # Instead of making signature a global variable tie it to IPSHELL. # In future if it is required to distinguish between different # shells we can assign a signature per shell basis ip.IP.__sig__ = 0xa005 # mark the IPSHELL with this signature ip.IP.user_ns['__builtins__'].__dict__['__sig__'] = ip.IP.__sig__ from IPython.Itpl import ItplNS from IPython.genutils import shell # utility to expand user variables via Itpl # xxx do something sensible with depth? ip.IP.var_expand = lambda cmd, lvars=None, depth=2: \ str(ItplNS(cmd, ip.IP.user_ns, get_locals())) def get_locals(): """ Substituting a variable through Itpl deep inside the IPSHELL stack requires the knowledge of all the variables in scope upto the last IPSHELL frame. This routine simply merges all the local variables on the IPSHELL stack without worrying about their scope rules """ import sys # note lambda expression constitues a function call # hence fno should be incremented by one getsig = lambda fno: sys._getframe(fno+1).f_globals \ ['__builtins__'].__dict__['__sig__'] getlvars = lambda fno: sys._getframe(fno + 1).f_locals # trackback until we enter the IPSHELL frame_no = 1 sig = ip.IP.__sig__ fsig = ~sig while fsig != sig: try: fsig = getsig(frame_no) except (AttributeError, KeyError): frame_no += 1 except ValueError: # stack is depleted # call did not originate from IPSHELL return {} first_frame = frame_no # walk further back until we exit from IPSHELL or deplete stack try: while (sig == getsig(frame_no + 1)): frame_no += 1 except (AttributeError, KeyError, ValueError): pass # merge the locals from top down hence overriding # any re-definitions of variables, functions etc. lvars = {} for fno in range(frame_no, first_frame - 1, -1): lvars.update(getlvars(fno)) #print '\n'*5, first_frame, frame_no, '\n', lvars, '\n'*5 #dbg return lvars def _runlines(lines): """Run a string of one or more lines of source. This method is capable of running a string containing multiple source lines, as if they had been entered at the IPython prompt. Since it exposes IPython's processing machinery, the given strings can contain magic calls (%magic), special shell access (!cmd), etc.""" # We must start with a clean buffer, in case this is run from an # interactive IPython session (via a magic, for example). ip.IP.resetbuffer() lines = lines.split('\n') more = 0 command = '' for line in lines: # skip blank lines so we don't mess up the prompt counter, but do # NOT skip even a blank line if we are in a code block (more is # true) # if command is not empty trim the line if command != '': line = line.strip() # add the broken line to the command if line and line[-1] == '\\': command += line[0:-1] + ' ' more = True continue else: # add the last (current) line to the command command += line if command or more: # push to raw history, so hist line numbers stay in sync ip.IP.input_hist_raw.append("# " + command + "\n") more = ip.IP.push(ip.IP.prefilter(command, more)) command = '' # IPython's runsource returns None if there was an error # compiling the code. This allows us to stop processing right # away, so the user gets the error message at the right place. if more is None: break # final newline in case the input didn't have it, so that the code # actually does get executed if more: ip.IP.push('\n') ip.IP.runlines = _runlines