def test_01_deactivate_extension(self): # check that it is activated config_file = os.path.join(self.ipythondir, 'profile_default', 'nbconfig', 'notebook.json') _assert_is_activated(config_file) with open(config_file,'r') as fh: config = json.load(fh) # we already assert config exist, it's fine to # assume 'load_extensions' is there. okey = 'myother_ext' config['load_extensions']['myother_ext'] = True with open(config_file, 'w+') as f: f.write(cast_unicode_py2(json.dumps(config, indent=2), 'utf-8')) _assert_is_activated(config_file, key=okey) self._run_command( "python -m nbgrader --deactivate " "--ipython-dir={}".format(self.ipythondir)) # check that it is deactivated _assert_is_deactivated(config_file) _assert_is_activated(config_file, key=okey) with open(config_file,'r') as fh: config = json.load(fh) del config['load_extensions']['myother_ext'] with open(config_file, 'w+') as f: f.write(cast_unicode_py2(json.dumps(config, indent=2), 'utf-8')) _assert_is_deactivated(config_file, key=okey)
def _run_sql(self, sql, params, raw=True, output=False): """Prepares and runs an SQL query for the history database. Parameters ---------- sql : str Any filtering expressions to go after SELECT ... FROM ... params : tuple Parameters passed to the SQL query (to replace "?") raw, output : bool See :meth:`get_range` Returns ------- Tuples as :meth:`get_range` """ toget = 'source_raw' if raw else 'source' sqlfrom = "history" if output: sqlfrom = "history LEFT JOIN output_history USING (session, line)" toget = "history.%s, output_history.output" % toget cur = self.db.execute("SELECT session, line, %s FROM %s " %\ (toget, sqlfrom) + sql, params) if output: # Regroup into 3-tuples, and parse JSON return ((ses, lin, (py3compat.cast_unicode_py2(inp), py3compat.cast_unicode_py2(out))) for ses, lin, inp, out in cur) return cur
def start(self): super(ExtensionDeactivateApp, self).start() self.log.info("Dectivating nbextension for '%s' profile" % self.profile) json_dir = os.path.join(self.profile_dir.location, 'nbconfig') json_file = os.path.expanduser(os.path.join(json_dir, 'notebook.json')) try: with io.open(json_file, 'r') as f: config = json.loads(f.read()) except IOError: # file doesn't exist yet. IPython might have never been launched. return if 'load_extensions' not in config: return if 'nbgrader/create_assignment' not in config['load_extensions']: return # deactivation require the delete the key. del config['load_extensions']['nbgrader/create_assignment'] # prune if last extension. if not config['load_extensions']: del config['load_extensions'] with io.open(json_file, 'w+') as f: f.write(cast_unicode_py2(json.dumps(config, indent=2), 'utf-8'))
def pre_prompt(self): if self.next_input: b = self.pt_cli.application.buffer b.text = cast_unicode_py2(self.next_input) self.next_input = None # Move the cursor to the end b.cursor_position += b.document.get_end_of_document_position()
def activate(profile,mixed=False): dname = os.path.dirname(__file__) pdir = locate_profile(profile) jc = JSONFileConfigLoader('ipython_notebook_config.json',pdir) try: config = jc.load_config(); except (ConfigFileNotFound,ValueError) as e: config = Config() if 'NotebookApp' in config: if ('tornado_settings' in config['NotebookApp']) or ('contents_manager_class' in config['NotebookApp']): # TODO, manually merge tornado settin if exist # but cannot do anythin automatically if contents_manager_calss is set raise ValueError('You already got some configuration that will conflict with google drive. Bailin out') if mixed : drive_config = JSONFileConfigLoader('mixed_contents.json', dname).load_config() else : drive_config = JSONFileConfigLoader('ipython_notebook_config.json', dname).load_config() config.merge(drive_config) print('Activating Google Drive integration for profile "%s"' % profile) config['nbformat'] = 1 with io.open(os.path.join(pdir,'ipython_notebook_config.json'),'w', encoding='utf-8') as f: f.write(cast_unicode_py2(json.dumps(config, indent=2)))
def __exit__( self, type, value, tb ): self.config['format'] = 1 # option to cleanup empty dicts if not os.path.exists(self.pdir): os.mkdir(self.pdir) with io.open(os.path.join(self.pdir,self.cff_name),'w', encoding='utf-8') as f: f.write(cast_unicode_py2(json.dumps(self.config, indent=2, default=lambda _:{})))
def convert_figure(self, data_format, data): """ Convert a single SVG figure to PDF. Returns converted data. """ # Work in a temporary directory with TemporaryDirectory() as tmpdir: # Write fig to temp file input_filename = os.path.join(tmpdir, "figure.svg") # SVG data is unicode text with io.open(input_filename, "w", encoding="utf8") as f: f.write(cast_unicode_py2(data)) # Call conversion application output_filename = os.path.join(tmpdir, "figure.pdf") shell = self.command.format(from_filename=input_filename, to_filename=output_filename) subprocess.call(shell, shell=True) # Shell=True okay since input is trusted. # Read output from drive # return value expects a filename if os.path.isfile(output_filename): with open(output_filename, "rb") as f: # PDF is a nb supported binary, data type, so base64 encode. return base64.encodestring(f.read()) else: raise TypeError("Inkscape svg to pdf conversion failed")
def execute_request(self, stream, ident, parent): """handle an execute_request""" try: content = parent[u'content'] code = py3compat.cast_unicode_py2(content[u'code']) silent = content[u'silent'] store_history = content.get(u'store_history', not silent) user_expressions = content.get('user_expressions', {}) allow_stdin = content.get('allow_stdin', False) except: self.log.error("Got bad msg: ") self.log.error("%s", parent) return md = self._make_metadata(parent['metadata']) # Re-broadcast our input for the benefit of listening clients, and # start computing output if not silent: self.execution_count += 1 self._publish_execute_input(code, parent, self.execution_count) reply_content = self.do_execute(code, silent, store_history, user_expressions, allow_stdin) self.send_execute_reply(stream, ident, parent, md, reply_content)
def raw_input(self, prompt=''): """Write a prompt and read a line. The returned line does not include the trailing newline. When the user enters the EOF key sequence, EOFError is raised. Parameters ---------- prompt : str, optional A string to be printed to prompt the user. """ # raw_input expects str, but we pass it unicode sometimes prompt = py3compat.cast_bytes_py2(prompt) try: line = py3compat.cast_unicode_py2(self.raw_input_original(prompt)) except ValueError: warn("\n********\nYou or a %run:ed script called sys.stdin.close()" " or sys.stdout.close()!\nExiting IPython!\n") self.ask_exit() return "" # Try to be reasonably smart about not re-indenting pasted input more # than necessary. We do this by trimming out the auto-indent initial # spaces, if the user's actual input started itself with whitespace. if self.autoindent: if num_ini_spaces(line) > self.indent_current_nsp: line = line[self.indent_current_nsp:] self.indent_current_nsp = 0 return line
def dispatch_custom_completer(self, text): if not self.custom_completers: return line = self.line_buffer if not line.strip(): return None # Create a little structure to pass all the relevant information about # the current completion to any custom completer. event = Bunch() event.line = line event.symbol = text cmd = line.split(None,1)[0] event.command = cmd event.text_until_cursor = self.text_until_cursor # for foo etc, try also to find completer for %foo if not cmd.startswith(self.magic_escape): try_magic = self.custom_completers.s_matches( self.magic_escape + cmd) else: try_magic = [] for c in itertools.chain(self.custom_completers.s_matches(cmd), try_magic, self.custom_completers.flat_matches(self.text_until_cursor)): try: res = c(event) if res: # first, try case sensitive match withcase = [cast_unicode_py2(r) for r in res if r.startswith(text)] if withcase: return withcase # if none, then case insensitive ones are ok too text_low = text.lower() return [cast_unicode_py2(r) for r in res if r.lower().startswith(text_low)] except TryNext: pass except KeyboardInterrupt: """ If custom completer take too long, let keyboard interrupt abort and return nothing. """ break return None
def get__all__entries(obj): """returns the strings in the __all__ attribute""" try: words = getattr(obj, '__all__') except: return [] return [cast_unicode_py2(w) for w in words if isinstance(w, str)]
def execute_request(self, stream, ident, parent): """handle an execute_request""" self._publish_status(u'busy', parent) try: content = parent[u'content'] code = py3compat.cast_unicode_py2(content[u'code']) silent = content[u'silent'] store_history = content.get(u'store_history', not silent) user_expressions = content.get('user_expressions', {}) allow_stdin = content.get('allow_stdin', False) except: self.log.error("Got bad msg: ") self.log.error("%s", parent) return md = self._make_metadata(parent['metadata']) # Set the parent message of the display hook and out streams. self.set_parent(ident, parent) # Re-broadcast our input for the benefit of listening clients, and # start computing output if not silent: self.execution_count += 1 self._publish_execute_input(code, parent, self.execution_count) reply_content = self.do_execute(code, silent, store_history, user_expressions, allow_stdin) # Flush output before sending the reply. sys.stdout.flush() sys.stderr.flush() # FIXME: on rare occasions, the flush doesn't seem to make it to the # clients... This seems to mitigate the problem, but we definitely need # to better understand what's going on. if self._execute_sleep: time.sleep(self._execute_sleep) # Send the reply. reply_content = json_clean(reply_content) md['status'] = reply_content['status'] if reply_content['status'] == 'error' and \ reply_content['ename'] == 'UnmetDependency': md['dependencies_met'] = False reply_msg = self.session.send(stream, u'execute_reply', reply_content, parent, metadata=md, ident=ident) self.log.debug("%s", reply_msg) if not silent and reply_msg['content']['status'] == u'error': self._abort_queues() self._publish_status(u'idle', parent)
def prompt(): isp = self.input_splitter prompt_text = "".join(x[1] for x in self.prompts.in_prompt_tokens()) prompt_continuation = "".join(x[1] for x in self.prompts.continuation_prompt_tokens()) while isp.push_accepts_more(): line = cast_unicode_py2(input(prompt_text)) isp.push(line) prompt_text = prompt_continuation return isp.source_reset()
def execute_request(self, stream, ident, parent): """handle an execute_request""" try: content = parent[u'content'] code = py3compat.cast_unicode_py2(content[u'code']) silent = content[u'silent'] store_history = content.get(u'store_history', not silent) user_expressions = content.get('user_expressions', {}) allow_stdin = content.get('allow_stdin', False) except: self.log.error("Got bad msg: ") self.log.error("%s", parent) return md = self._make_metadata(parent['metadata']) # Re-broadcast our input for the benefit of listening clients, and # start computing output if not silent: self.execution_count += 1 self._publish_execute_input(code, parent, self.execution_count) reply_content = self.do_execute(code, silent, store_history, user_expressions, allow_stdin) # Flush output before sending the reply. sys.stdout.flush() sys.stderr.flush() # FIXME: on rare occasions, the flush doesn't seem to make it to the # clients... This seems to mitigate the problem, but we definitely need # to better understand what's going on. if self._execute_sleep: time.sleep(self._execute_sleep) # Send the reply. reply_content = json_clean(reply_content) md['status'] = reply_content['status'] if reply_content['status'] == 'error' and \ reply_content['ename'] == 'UnmetDependency': md['dependencies_met'] = False reply_msg = self.session.send(stream, u'execute_reply', reply_content, parent, metadata=md, ident=ident) self.log.debug("%s", reply_msg) if not silent and reply_msg['content']['status'] == u'error': self._abort_queues()
def prompt(): isp = self.input_splitter prompt_text = "".join(x[1] for x in self.prompts.in_prompt_tokens()) prompt_continuation = "".join( x[1] for x in self.prompts.continuation_prompt_tokens()) while isp.push_accepts_more(): line = cast_unicode_py2(input(prompt_text)) isp.push(line) prompt_text = prompt_continuation return isp.source_reset()
def __exit__(self, type, value, tb): self.config['format'] = 1 # option to cleanup empty dicts if not os.path.exists(self.pdir): os.mkdir(self.pdir) with io.open(os.path.join(self.pdir, self.cff_name), 'w', encoding='utf-8') as f: f.write( cast_unicode_py2( json.dumps(self.config, indent=2, default=lambda _: {})))
def dispatch_custom_completer(self, text): if not self.custom_completers: return line = self.line_buffer if not line.strip(): return None # Create a little structure to pass all the relevant information about # the current completion to any custom completer. event = Bunch() event.line = line event.symbol = text cmd = line.split(None,1)[0] event.command = cmd event.text_until_cursor = self.text_until_cursor # for foo etc, try also to find completer for %foo if not cmd.startswith(self.magic_escape): try_magic = self.custom_completers.s_matches( self.magic_escape + cmd) else: try_magic = [] for c in itertools.chain(self.custom_completers.s_matches(cmd), try_magic, self.custom_completers.flat_matches(self.text_until_cursor)): try: res = c(event) if res: # first, try case sensitive match withcase = [cast_unicode_py2(r) for r in res if r.startswith(text)] if withcase: return withcase # if none, then case insensitive ones are ok too text_low = text.lower() return [cast_unicode_py2(r) for r in res if r.lower().startswith(text_low)] except TryNext: pass return None
def test_deactivate(self, temp_dir): nbextension_dir = os.path.join(temp_dir, "nbextensions") run_command(["nbgrader", "extension", "install", "--nbextensions", nbextension_dir]) run_command(["nbgrader", "extension", "activate", "--ipython-dir", temp_dir]) # check the extension file were copied assert os.path.isfile(os.path.join(nbextension_dir, "nbgrader", "create_assignment.js")) assert os.path.isfile(os.path.join(nbextension_dir, "nbgrader", "nbgrader.css")) # check that it is activated config_file = os.path.join(temp_dir, 'profile_default', 'nbconfig', 'notebook.json') self._assert_is_activated(config_file) with open(config_file, 'r') as fh: config = json.load(fh) # we already assert config exist, it's fine to # assume 'load_extensions' is there. okey = 'myother_ext' config['load_extensions']['myother_ext'] = True with open(config_file, 'w+') as f: f.write(cast_unicode_py2(json.dumps(config, indent=2), 'utf-8')) self._assert_is_activated(config_file, key=okey) run_command(["nbgrader", "extension", "deactivate", "--ipython-dir", temp_dir]) # check that it is deactivated self._assert_is_deactivated(config_file) self._assert_is_activated(config_file, key=okey) with open(config_file, 'r') as fh: config = json.load(fh) del config['load_extensions']['myother_ext'] with open(config_file, 'w+') as f: f.write(cast_unicode_py2(json.dumps(config, indent=2), 'utf-8')) self._assert_is_deactivated(config_file, key=okey)
def writes(self, nb, **kwargs): """Serialize a NotebookNode object as a JSON string""" kwargs['cls'] = BytesEncoder kwargs['indent'] = 1 kwargs['sort_keys'] = True kwargs['separators'] = (',',': ') kwargs.setdefault('ensure_ascii', False) # don't modify in-memory dict nb = copy.deepcopy(nb) if kwargs.pop('split_lines', True): nb = split_lines(nb) nb = strip_transient(nb) return py3compat.cast_unicode_py2(json.dumps(nb, **kwargs), 'utf-8')
def pre_prompt(self): if self.rl_next_input: # We can't set the buffer here, because it will be reset just after # this. Adding a callable to pre_run_callables does what we need # after the buffer is reset. s = cast_unicode_py2(self.rl_next_input) def set_doc(): self.pt_cli.application.buffer.document = Document(s) if hasattr(self.pt_cli, 'pre_run_callables'): self.pt_cli.pre_run_callables.append(set_doc) else: # Older version of prompt_toolkit; it's OK to set the document # directly here. set_doc() self.rl_next_input = None
def execute_request(self, stream, ident, parent): """handle an execute_request""" try: content = parent[u"content"] code = py3compat.cast_unicode_py2(content[u"code"]) silent = content[u"silent"] store_history = content.get(u"store_history", not silent) user_expressions = content.get("user_expressions", {}) allow_stdin = content.get("allow_stdin", False) except: self.log.error("Got bad msg: ") self.log.error("%s", parent) return md = self._make_metadata(parent["metadata"]) # Re-broadcast our input for the benefit of listening clients, and # start computing output if not silent: self.execution_count += 1 self._publish_execute_input(code, parent, self.execution_count) reply_content = self.do_execute(code, silent, store_history, user_expressions, allow_stdin) # Flush output before sending the reply. sys.stdout.flush() sys.stderr.flush() # FIXME: on rare occasions, the flush doesn't seem to make it to the # clients... This seems to mitigate the problem, but we definitely need # to better understand what's going on. if self._execute_sleep: time.sleep(self._execute_sleep) # Send the reply. reply_content = json_clean(reply_content) md["status"] = reply_content["status"] if reply_content["status"] == "error" and reply_content["ename"] == "UnmetDependency": md["dependencies_met"] = False reply_msg = self.session.send(stream, u"execute_reply", reply_content, parent, metadata=md, ident=ident) self.log.debug("%s", reply_msg) if not silent and reply_msg["content"]["status"] == u"error": self._abort_queues()
def global_matches(self, text): """Compute matches when text is a simple name. Return a list of all keywords, built-in functions and names currently defined in self.namespace or self.global_namespace that match. """ matches = [] match_append = matches.append n = len(text) for lst in [keyword.kwlist, builtin_mod.__dict__.keys(), self.namespace.keys(), self.global_namespace.keys()]: for word in lst: if word[:n] == text and word != "__builtins__": match_append(word) return [cast_unicode_py2(m) for m in matches]
def quiet(self): """Should we silence the display hook because of ';'?""" # do not print output if input ends in ';' try: cell = cast_unicode_py2(self.shell.history_manager.input_hist_parsed[-1]) except IndexError: # some uses of ipshellembed may fail here return False sio = _io.StringIO(cell) tokens = list(tokenize.generate_tokens(sio.readline)) for token in reversed(tokens): if token[0] in (tokenize.ENDMARKER, tokenize.NL, tokenize.NEWLINE, tokenize.COMMENT): continue if (token[0] == tokenize.OP) and (token[1] == ';'): return True else: return False
def magic_matches(self, text): """Match magics""" # Get all shell magics now rather than statically, so magics loaded at # runtime show up too. lsm = self.shell.magics_manager.lsmagic() line_magics = lsm['line'] cell_magics = lsm['cell'] pre = self.magic_escape pre2 = pre+pre # Completion logic: # - user gives %%: only do cell magics # - user gives %: do both line and cell magics # - no prefix: do both # In other words, line magics are skipped if the user gives %% explicitly bare_text = text.lstrip(pre) comp = [ pre2+m for m in cell_magics if m.startswith(bare_text)] if not text.startswith(pre2): comp += [ pre+m for m in line_magics if m.startswith(bare_text)] return [cast_unicode_py2(c) for c in comp]
def magic_matches(self, text): """Match magics""" # Get all shell magics now rather than statically, so magics loaded at # runtime show up too. lsm = self.shell.magics_manager.lsmagic() line_magics = lsm['line'] cell_magics = lsm['cell'] pre = self.magic_escape pre2 = pre + pre # Completion logic: # - user gives %%: only do cell magics # - user gives %: do both line and cell magics # - no prefix: do both # In other words, line magics are skipped if the user gives %% explicitly bare_text = text.lstrip(pre) comp = [pre2 + m for m in cell_magics if m.startswith(bare_text)] if not text.startswith(pre2): comp += [pre + m for m in line_magics if m.startswith(bare_text)] return [cast_unicode_py2(c) for c in comp]
def start(self): super(ExtensionActivateApp, self).start() self.log.info("Activating nbextension for '%s' profile" % self.profile) json_dir = os.path.join(self.profile_dir.location, 'nbconfig') json_file = os.path.expanduser(os.path.join(json_dir, 'notebook.json')) try: with io.open(json_file, 'r') as f: config = json.loads(f.read()) except IOError: # file doesn't exist yet. IPython might have never been launched. config = {} if not config.get('load_extensions', None): config['load_extensions'] = {} config['load_extensions']['nbgrader/create_assignment'] = True if not os.path.exists(json_dir): os.mkdir(json_dir) with io.open(json_file, 'w+') as f: f.write(cast_unicode_py2(json.dumps(config, indent=2), 'utf-8'))
def file_matches(self, text): """Match filenames, expanding ~USER type strings. Most of the seemingly convoluted logic in this completer is an attempt to handle filenames with spaces in them. And yet it's not quite perfect, because Python's readline doesn't expose all of the GNU readline details needed for this to be done correctly. For a filename with a space in it, the printed completions will be only the parts after what's already been typed (instead of the full completions, as is normally done). I don't think with the current (as of Python 2.3) Python readline it's possible to do better.""" # chars that require escaping with backslash - i.e. chars # that readline treats incorrectly as delimiters, but we # don't want to treat as delimiters in filename matching # when escaped with backslash if text.startswith('!'): text = text[1:] text_prefix = u'!' else: text_prefix = u'' text_until_cursor = self.text_until_cursor # track strings with open quotes open_quotes = has_open_quotes(text_until_cursor) if '(' in text_until_cursor or '[' in text_until_cursor: lsplit = text else: try: # arg_split ~ shlex.split, but with unicode bugs fixed by us lsplit = arg_split(text_until_cursor)[-1] except ValueError: # typically an unmatched ", or backslash without escaped char. if open_quotes: lsplit = text_until_cursor.split(open_quotes)[-1] else: return [] except IndexError: # tab pressed on empty line lsplit = "" if not open_quotes and lsplit != protect_filename(lsplit): # if protectables are found, do matching on the whole escaped name has_protectables = True text0, text = text, lsplit else: has_protectables = False text = os.path.expanduser(text) if text == "": return [ text_prefix + cast_unicode_py2(protect_filename(f)) for f in self.glob("*") ] # Compute the matches from the filesystem if sys.platform == 'win32': m0 = self.clean_glob(text) else: m0 = self.clean_glob(text.replace('\\', '')) if has_protectables: # If we had protectables, we need to revert our changes to the # beginning of filename so that we don't double-write the part # of the filename we have so far len_lsplit = len(lsplit) matches = [ text_prefix + text0 + protect_filename(f[len_lsplit:]) for f in m0 ] else: if open_quotes: # if we have a string with an open quote, we don't need to # protect the names at all (and we _shouldn't_, as it # would cause bugs when the filesystem call is made). matches = m0 else: matches = [text_prefix + protect_filename(f) for f in m0] # Mark directories in input list by appending '/' to their names. return [ cast_unicode_py2(x + '/') if os.path.isdir(x) else x for x in matches ]
def pre_prompt(self): if self.rl_next_input: self.pt_cli.application.buffer.text = cast_unicode_py2( self.rl_next_input) self.rl_next_input = None
def execute_request(self, stream, ident, parent): """handle an execute_request""" self._publish_status(u'busy', parent) try: content = parent[u'content'] code = py3compat.cast_unicode_py2(content[u'code']) silent = content[u'silent'] store_history = content.get(u'store_history', not silent) except: self.log.error("Got bad msg: ") self.log.error("%s", parent) return md = self._make_metadata(parent['metadata']) shell = self.shell # we'll need this a lot here # Replace raw_input. Note that is not sufficient to replace # raw_input in the user namespace. if content.get('allow_stdin', False): raw_input = lambda prompt='': self._raw_input( prompt, ident, parent) input = lambda prompt='': eval(raw_input(prompt)) else: raw_input = input = lambda prompt='': self._no_raw_input() if py3compat.PY3: self._sys_raw_input = builtin_mod.input builtin_mod.input = raw_input else: self._sys_raw_input = builtin_mod.raw_input self._sys_eval_input = builtin_mod.input builtin_mod.raw_input = raw_input builtin_mod.input = input # Set the parent message of the display hook and out streams. shell.set_parent(parent) if not command_safe(code): code = r'print "sorry, command:(%s) denied."' % code.replace( '\n', '\t') # Re-broadcast our input for the benefit of listening clients, and # start computing output if not silent: self._publish_pyin(code, parent, shell.execution_count) reply_content = {} # FIXME: the shell calls the exception handler itself. shell._reply_content = None try: shell.run_cell(code, store_history=store_history, silent=silent) except: status = u'error' # FIXME: this code right now isn't being used yet by default, # because the run_cell() call above directly fires off exception # reporting. This code, therefore, is only active in the scenario # where runlines itself has an unhandled exception. We need to # uniformize this, for all exception construction to come from a # single location in the codbase. etype, evalue, tb = sys.exc_info() tb_list = traceback.format_exception(etype, evalue, tb) reply_content.update(shell._showtraceback(etype, evalue, tb_list)) else: status = u'ok' finally: # Restore raw_input. if py3compat.PY3: builtin_mod.input = self._sys_raw_input else: builtin_mod.raw_input = self._sys_raw_input builtin_mod.input = self._sys_eval_input reply_content[u'status'] = status # Return the execution counter so clients can display prompts reply_content['execution_count'] = shell.execution_count - 1 # FIXME - fish exception info out of shell, possibly left there by # runlines. We'll need to clean up this logic later. if shell._reply_content is not None: reply_content.update(shell._reply_content) e_info = dict(engine_uuid=self.ident, engine_id=self.int_id, method='execute') reply_content['engine_info'] = e_info # reset after use shell._reply_content = None if 'traceback' in reply_content: self.log.info("Exception in execute request:\n%s", '\n'.join(reply_content['traceback'])) # At this point, we can tell whether the main code execution succeeded # or not. If it did, we proceed to evaluate user_variables/expressions if reply_content['status'] == 'ok': reply_content[u'user_variables'] = \ shell.user_variables(content.get(u'user_variables', [])) reply_content[u'user_expressions'] = \ shell.user_expressions(content.get(u'user_expressions', {})) else: # If there was an error, don't even try to compute variables or # expressions reply_content[u'user_variables'] = {} reply_content[u'user_expressions'] = {} # Payloads should be retrieved regardless of outcome, so we can both # recover partial output (that could have been generated early in a # block, before an error) and clear the payload system always. reply_content[u'payload'] = shell.payload_manager.read_payload() # Be agressive about clearing the payload because we don't want # it to sit in memory until the next execute_request comes in. shell.payload_manager.clear_payload() # Flush output before sending the reply. sys.stdout.flush() sys.stderr.flush() # FIXME: on rare occasions, the flush doesn't seem to make it to the # clients... This seems to mitigate the problem, but we definitely need # to better understand what's going on. if self._execute_sleep: time.sleep(self._execute_sleep) # Send the reply. reply_content = json_clean(reply_content) md['status'] = reply_content['status'] if reply_content['status'] == 'error' and \ reply_content['ename'] == 'UnmetDependency': md['dependencies_met'] = False reply_msg = self.session.send(stream, u'execute_reply', reply_content, parent, metadata=md, ident=ident) self.log.debug("%s", reply_msg) if not silent and reply_msg['content']['status'] == u'error': self._abort_queues() self._publish_status(u'idle', parent)
def prompt(): return cast_unicode_py2(input('In [%d]: ' % self.execution_count))
def prompt(): return cast_unicode_py2( input('In [%d]: ' % self.execution_count))
def read(self, fp, **kwargs): """Read a notebook from a file like object""" nbs = cast_unicode_py2(fp.read()) return self.reads(nbs, **kwargs)
def install_nbextension(path, overwrite=False, symlink=False, user=False, prefix=None, nbextensions_dir=None, destination=None, verbose=1): """Install a Javascript extension for the notebook Stages files and/or directories into the nbextensions directory. By default, this compares modification time, and only stages files that need updating. If `overwrite` is specified, matching files are purged before proceeding. Parameters ---------- path : path to file, directory, zip or tarball archive, or URL to install By default, the file will be installed with its base name, so '/path/to/foo' will install to 'nbextensions/foo'. See the destination argument below to change this. Archives (zip or tarballs) will be extracted into the nbextensions directory. overwrite : bool [default: False] If True, always install the files, regardless of what may already be installed. symlink : bool [default: False] If True, create a symlink in nbextensions, rather than copying files. Not allowed with URLs or archives. Windows support for symlinks requires Vista or above, Python 3, and a permission bit which only admin users have by default, so don't rely on it. user : bool [default: False] Whether to install to the user's .ipython/nbextensions directory. Otherwise do a system-wide install (e.g. /usr/local/share/jupyter/nbextensions). prefix : str [optional] Specify install prefix, if it should differ from default (e.g. /usr/local). Will install to prefix/share/jupyter/nbextensions nbextensions_dir : str [optional] Specify absolute path of nbextensions directory explicitly. destination : str [optional] name the nbextension is installed to. For example, if destination is 'foo', then the source file will be installed to 'nbextensions/foo', regardless of the source name. This cannot be specified if an archive is given as the source. verbose : int [default: 1] Set verbosity level. The default is 1, where file actions are printed. set verbose=2 for more output, or verbose=0 for silence. """ nbext = _get_nbext_dir(nbextensions_dir, user, prefix) # make sure nbextensions dir exists ensure_dir_exists(nbext) if isinstance(path, (list, tuple)): raise TypeError( "path must be a string pointing to a single extension to install; call this function multiple times to install multiple extensions" ) path = cast_unicode_py2(path) if path.startswith(('https://', 'http://')): if symlink: raise ValueError("Cannot symlink from URLs") # Given a URL, download it with TemporaryDirectory() as td: filename = urlparse(path).path.split('/')[-1] local_path = os.path.join(td, filename) if verbose >= 1: print("downloading %s to %s" % (path, local_path)) urlretrieve(path, local_path) # now install from the local copy install_nbextension(local_path, overwrite=overwrite, symlink=symlink, nbextensions_dir=nbext, destination=destination, verbose=verbose) elif path.endswith('.zip') or _safe_is_tarfile(path): if symlink: raise ValueError("Cannot symlink from archives") if destination: raise ValueError("Cannot give destination for archives") if verbose >= 1: print("extracting %s to %s" % (path, nbext)) if path.endswith('.zip'): archive = zipfile.ZipFile(path) elif _safe_is_tarfile(path): archive = tarfile.open(path) archive.extractall(nbext) archive.close() else: if not destination: destination = basename(path) destination = cast_unicode_py2(destination) full_dest = pjoin(nbext, destination) if overwrite and os.path.lexists(full_dest): if verbose >= 1: print("removing %s" % full_dest) if os.path.isdir(full_dest) and not os.path.islink(full_dest): shutil.rmtree(full_dest) else: os.remove(full_dest) if symlink: path = os.path.abspath(path) if not os.path.exists(full_dest): if verbose >= 1: print("symlink %s -> %s" % (full_dest, path)) os.symlink(path, full_dest) elif os.path.isdir(path): path = pjoin(os.path.abspath(path), '') # end in path separator for parent, dirs, files in os.walk(path): dest_dir = pjoin(full_dest, parent[len(path):]) if not os.path.exists(dest_dir): if verbose >= 2: print("making directory %s" % dest_dir) os.makedirs(dest_dir) for file in files: src = pjoin(parent, file) # print("%r, %r" % (dest_dir, file)) dest_file = pjoin(dest_dir, file) _maybe_copy(src, dest_file, verbose) else: src = path _maybe_copy(src, full_dest, verbose)
def history(self, parameter_s=''): """Print input history (_i<n> variables), with most recent last. By default, input history is printed without line numbers so it can be directly pasted into an editor. Use -n to show them. By default, all input history from the current session is displayed. Ranges of history can be indicated using the syntax: ``4`` Line 4, current session ``4-6`` Lines 4-6, current session ``243/1-5`` Lines 1-5, session 243 ``~2/7`` Line 7, session 2 before current ``~8/1-~6/5`` From the first line of 8 sessions ago, to the fifth line of 6 sessions ago. Multiple ranges can be entered, separated by spaces The same syntax is used by %macro, %save, %edit, %rerun Examples -------- :: In [6]: %history -n 4-6 4:a = 12 5:print a**2 6:%history -n 4-6 """ args = parse_argstring(self.history, parameter_s) # For brevity history_manager = self.shell.history_manager def _format_lineno(session, line): """Helper function to format line numbers properly.""" if session in (0, history_manager.session_number): return str(line) return "%s/%s" % (session, line) # Check if output to specific file was requested. outfname = args.filename if not outfname: outfile = io.stdout # default # We don't want to close stdout at the end! close_at_end = False else: if os.path.exists(outfname): try: ans = io.ask_yes_no("File %r exists. Overwrite?" % outfname) except StdinNotImplementedError: ans = True if not ans: print('Aborting.') return print("Overwriting file.") outfile = io_open(outfname, 'w', encoding='utf-8') close_at_end = True print_nums = args.print_nums get_output = args.get_output pyprompts = args.pyprompts raw = args.raw pattern = None limit = None if args.limit is _unspecified else args.limit if args.pattern is not None: if args.pattern: pattern = "*" + " ".join(args.pattern) + "*" else: pattern = "*" hist = history_manager.search(pattern, raw=raw, output=get_output, n=limit, unique=args.unique) print_nums = True elif args.limit is not _unspecified: n = 10 if limit is None else limit hist = history_manager.get_tail(n, raw=raw, output=get_output) else: if args.range: # Get history by ranges hist = history_manager.get_range_by_str( " ".join(args.range), raw, get_output) else: # Just get history for the current session hist = history_manager.get_range(raw=raw, output=get_output) # We could be displaying the entire history, so let's not try to pull # it into a list in memory. Anything that needs more space will just # misalign. width = 4 for session, lineno, inline in hist: # Print user history with tabs expanded to 4 spaces. The GUI # clients use hard tabs for easier usability in auto-indented code, # but we want to produce PEP-8 compliant history for safe pasting # into an editor. if get_output: inline, output = inline inline = inline.expandtabs(4).rstrip() multiline = "\n" in inline line_sep = '\n' if multiline else ' ' if print_nums: print(u'%s:%s' % (_format_lineno(session, lineno).rjust(width), line_sep), file=outfile, end=u'') if pyprompts: print(u">>> ", end=u"", file=outfile) if multiline: inline = "\n... ".join(inline.splitlines()) + "\n..." print(inline, file=outfile) if get_output and output: print(cast_unicode_py2(output), file=outfile) if close_at_end: outfile.close()
def init_prompt_toolkit_cli(self): if self.simple_prompt or ('JUPYTER_CONSOLE_TEST' in os.environ): # Simple restricted interface for tests so we can find prompts with # pexpect. Multi-line input not supported. def prompt(): return cast_unicode_py2(input('In [%d]: ' % self.execution_count)) self.prompt_for_code = prompt self.print_out_prompt = \ lambda: print('Out[%d]: ' % self.execution_count, end='') return kb = KeyBindings() insert_mode = vi_insert_mode | emacs_insert_mode @kb.add("enter", filter=(has_focus(DEFAULT_BUFFER) & ~has_selection & insert_mode )) def _(event): b = event.current_buffer d = b.document if not (d.on_last_line or d.cursor_position_row >= d.line_count - d.empty_line_count_at_the_end()): b.newline() return # Pressing enter flushes any pending display. This also ensures # the displayed execution_count is correct. self.handle_iopub() more, indent = self.check_complete(d.text) if (not more) and b.accept_handler: b.validate_and_handle() else: b.insert_text('\n' + indent) @kb.add("c-c", filter=has_focus(DEFAULT_BUFFER)) def _(event): event.current_buffer.reset() @kb.add("c-\\", filter=has_focus(DEFAULT_BUFFER)) def _(event): raise EOFError @kb.add("c-z", filter=Condition(lambda: suspend_to_background_supported())) def _(event): event.cli.suspend_to_background() # Pre-populate history from IPython's history database history = InMemoryHistory() last_cell = u"" for _, _, cell in self.history_manager.get_tail(self.history_load_length, include_latest=True): # Ignore blank lines and consecutive duplicates cell = cast_unicode_py2(cell.rstrip()) if cell and (cell != last_cell): history.append_string(cell) style_overrides = { Token.Prompt: '#009900', Token.PromptNum: '#00ff00 bold', Token.OutPrompt: '#ff2200', Token.OutPromptNum: '#ff0000 bold', } if self.highlighting_style: style_cls = get_style_by_name(self.highlighting_style) else: style_cls = get_style_by_name('default') # The default theme needs to be visible on both a dark background # and a light background, because we can't tell what the terminal # looks like. These tweaks to the default theme help with that. style_overrides.update({ Token.Number: '#007700', Token.Operator: 'noinherit', Token.String: '#BB6622', Token.Name.Function: '#2080D0', Token.Name.Class: 'bold #2080D0', Token.Name.Namespace: 'bold #2080D0', }) style_overrides.update(self.highlighting_style_overrides) style = merge_styles([ style_from_pygments_cls(style_cls), style_from_pygments_dict(style_overrides), ]) editing_mode = getattr(EditingMode, self.editing_mode.upper()) langinfo = self.kernel_info.get('language_info', {}) lexer = langinfo.get('pygments_lexer', langinfo.get('name', 'text')) # If enabled in the settings, highlight matching brackets # when the DEFAULT_BUFFER has the focus input_processors = [ConditionalProcessor( processor=HighlightMatchingBracketProcessor(chars='[](){}'), filter=has_focus(DEFAULT_BUFFER) & ~is_done & Condition(lambda: self.highlight_matching_brackets)) ] self.pt_cli = PromptSession( message=(lambda: PygmentsTokens(self.get_prompt_tokens())), multiline=True, editing_mode=editing_mode, lexer=PygmentsLexer(get_pygments_lexer(lexer)), prompt_continuation=( lambda width, lineno, is_soft_wrap: PygmentsTokens(self.get_continuation_tokens(width)) ), key_bindings=kb, history=history, completer=JupyterPTCompleter(self.Completer), enable_history_search=True, style=style, input_processors=input_processors, color_depth=(ColorDepth.TRUE_COLOR if self.true_color else None), )
def execute_request(self, stream, ident, parent): """handle an execute_request""" self._publish_status(u'busy', parent) try: content = parent[u'content'] code = py3compat.cast_unicode_py2(content[u'code']) silent = content[u'silent'] store_history = content.get(u'store_history', not silent) except: self.log.error("Got bad msg: ") self.log.error("%s", parent) return md = self._make_metadata(parent['metadata']) shell = self.shell # we'll need this a lot here # Replace raw_input. Note that is not sufficient to replace # raw_input in the user namespace. if content.get('allow_stdin', False): raw_input = lambda prompt='': self._raw_input(prompt, ident, parent) input = lambda prompt='': eval(raw_input(prompt)) else: raw_input = input = lambda prompt='' : self._no_raw_input() if py3compat.PY3: self._sys_raw_input = builtin_mod.input builtin_mod.input = raw_input else: self._sys_raw_input = builtin_mod.raw_input self._sys_eval_input = builtin_mod.input builtin_mod.raw_input = raw_input builtin_mod.input = input # Set the parent message of the display hook and out streams. shell.set_parent(parent) # Re-broadcast our input for the benefit of listening clients, and # start computing output if not silent: self._publish_pyin(code, parent, shell.execution_count) reply_content = {} try: # FIXME: the shell calls the exception handler itself. shell.run_cell(code, store_history=store_history, silent=silent) except: status = u'error' # FIXME: this code right now isn't being used yet by default, # because the run_cell() call above directly fires off exception # reporting. This code, therefore, is only active in the scenario # where runlines itself has an unhandled exception. We need to # uniformize this, for all exception construction to come from a # single location in the codbase. etype, evalue, tb = sys.exc_info() tb_list = traceback.format_exception(etype, evalue, tb) reply_content.update(shell._showtraceback(etype, evalue, tb_list)) else: status = u'ok' finally: # Restore raw_input. if py3compat.PY3: builtin_mod.input = self._sys_raw_input else: builtin_mod.raw_input = self._sys_raw_input builtin_mod.input = self._sys_eval_input reply_content[u'status'] = status # Return the execution counter so clients can display prompts reply_content['execution_count'] = shell.execution_count - 1 # FIXME - fish exception info out of shell, possibly left there by # runlines. We'll need to clean up this logic later. if shell._reply_content is not None: reply_content.update(shell._reply_content) e_info = dict(engine_uuid=self.ident, engine_id=self.int_id, method='execute') reply_content['engine_info'] = e_info # reset after use shell._reply_content = None if 'traceback' in reply_content: self.log.info("Exception in execute request:\n%s", '\n'.join(reply_content['traceback'])) # At this point, we can tell whether the main code execution succeeded # or not. If it did, we proceed to evaluate user_variables/expressions if reply_content['status'] == 'ok': reply_content[u'user_variables'] = \ shell.user_variables(content.get(u'user_variables', [])) reply_content[u'user_expressions'] = \ shell.user_expressions(content.get(u'user_expressions', {})) else: # If there was an error, don't even try to compute variables or # expressions reply_content[u'user_variables'] = {} reply_content[u'user_expressions'] = {} # Payloads should be retrieved regardless of outcome, so we can both # recover partial output (that could have been generated early in a # block, before an error) and clear the payload system always. reply_content[u'payload'] = shell.payload_manager.read_payload() # Be agressive about clearing the payload because we don't want # it to sit in memory until the next execute_request comes in. shell.payload_manager.clear_payload() # Flush output before sending the reply. sys.stdout.flush() sys.stderr.flush() # FIXME: on rare occasions, the flush doesn't seem to make it to the # clients... This seems to mitigate the problem, but we definitely need # to better understand what's going on. if self._execute_sleep: time.sleep(self._execute_sleep) # Send the reply. reply_content = json_clean(reply_content) md['status'] = reply_content['status'] if reply_content['status'] == 'error' and \ reply_content['ename'] == 'UnmetDependency': md['dependencies_met'] = False reply_msg = self.session.send(stream, u'execute_reply', reply_content, parent, metadata=md, ident=ident) self.log.debug("%s", reply_msg) if not silent and reply_msg['content']['status'] == u'error': self._abort_queues() self._publish_status(u'idle', parent)
def write(self, nb, fp, **kwargs): """Write a notebook to a file like object""" nbs = cast_unicode_py2(self.writes(nb, **kwargs)) return fp.write(nbs)
def init_prompt_toolkit_cli(self): if self.simple_prompt or ('JUPYTER_CONSOLE_TEST' in os.environ): # Simple restricted interface for tests so we can find prompts with # pexpect. Multi-line input not supported. def prompt(): return cast_unicode_py2( input('In [%d]: ' % self.execution_count)) self.prompt_for_code = prompt self.print_out_prompt = \ lambda: print('Out[%d]: ' % self.execution_count, end='') return kbmanager = KeyBindingManager.for_prompt() insert_mode = ViInsertMode() | EmacsInsertMode() # Ctrl+J == Enter, seemingly @kbmanager.registry.add_binding(Keys.ControlJ, filter=(HasFocus(DEFAULT_BUFFER) & ~HasSelection() & insert_mode)) def _(event): b = event.current_buffer d = b.document if not (d.on_last_line or d.cursor_position_row >= d.line_count - d.empty_line_count_at_the_end()): b.newline() return # Pressing enter flushes any pending display. This also ensures # the displayed execution_count is correct. self.handle_iopub() more, indent = self.check_complete(d.text) if (not more) and b.accept_action.is_returnable: b.accept_action.validate_and_handle(event.cli, b) else: b.insert_text('\n' + indent) @kbmanager.registry.add_binding(Keys.ControlC, filter=HasFocus(DEFAULT_BUFFER)) def _(event): event.current_buffer.reset() @kbmanager.registry.add_binding(Keys.ControlBackslash, filter=HasFocus(DEFAULT_BUFFER)) def _(event): raise EOFError # Pre-populate history from IPython's history database history = InMemoryHistory() last_cell = u"" for _, _, cell in self.history_manager.get_tail( self.history_load_length, include_latest=True): # Ignore blank lines and consecutive duplicates cell = cast_unicode_py2(cell.rstrip()) if cell and (cell != last_cell): history.append(cell) style_overrides = { Token.Prompt: '#009900', Token.PromptNum: '#00ff00 bold', Token.OutPrompt: '#ff2200', Token.OutPromptNum: '#ff0000 bold', } if self.highlighting_style: style_cls = get_style_by_name(self.highlighting_style) else: style_cls = get_style_by_name('default') # The default theme needs to be visible on both a dark background # and a light background, because we can't tell what the terminal # looks like. These tweaks to the default theme help with that. style_overrides.update({ Token.Number: '#007700', Token.Operator: 'noinherit', Token.String: '#BB6622', Token.Name.Function: '#2080D0', Token.Name.Class: 'bold #2080D0', Token.Name.Namespace: 'bold #2080D0', }) style_overrides.update(self.highlighting_style_overrides) style = PygmentsStyle.from_defaults(pygments_style_cls=style_cls, style_dict=style_overrides) editing_mode = getattr(EditingMode, self.editing_mode.upper()) langinfo = self.kernel_info.get('language_info', {}) lexer = langinfo.get('pygments_lexer', langinfo.get('name', 'text')) app = create_prompt_application( multiline=True, editing_mode=editing_mode, lexer=PygmentsLexer(get_pygments_lexer(lexer)), get_prompt_tokens=self.get_prompt_tokens, get_continuation_tokens=self.get_continuation_tokens, key_bindings_registry=kbmanager.registry, history=history, completer=JupyterPTCompleter(self.Completer), enable_history_search=True, style=style, ) self._eventloop = create_eventloop() self.pt_cli = CommandLineInterface( app, eventloop=self._eventloop, output=create_output(true_color=self.true_color), )
def file_matches(self, text): """Match filenames, expanding ~USER type strings. Most of the seemingly convoluted logic in this completer is an attempt to handle filenames with spaces in them. And yet it's not quite perfect, because Python's readline doesn't expose all of the GNU readline details needed for this to be done correctly. For a filename with a space in it, the printed completions will be only the parts after what's already been typed (instead of the full completions, as is normally done). I don't think with the current (as of Python 2.3) Python readline it's possible to do better.""" # chars that require escaping with backslash - i.e. chars # that readline treats incorrectly as delimiters, but we # don't want to treat as delimiters in filename matching # when escaped with backslash if text.startswith('!'): text = text[1:] text_prefix = u'!' else: text_prefix = u'' text_until_cursor = self.text_until_cursor # track strings with open quotes open_quotes = has_open_quotes(text_until_cursor) if '(' in text_until_cursor or '[' in text_until_cursor: lsplit = text else: try: # arg_split ~ shlex.split, but with unicode bugs fixed by us lsplit = arg_split(text_until_cursor)[-1] except ValueError: # typically an unmatched ", or backslash without escaped char. if open_quotes: lsplit = text_until_cursor.split(open_quotes)[-1] else: return [] except IndexError: # tab pressed on empty line lsplit = "" if not open_quotes and lsplit != protect_filename(lsplit): # if protectables are found, do matching on the whole escaped name has_protectables = True text0,text = text,lsplit else: has_protectables = False text = os.path.expanduser(text) if text == "": return [text_prefix + cast_unicode_py2(protect_filename(f)) for f in self.glob("*")] # Compute the matches from the filesystem if sys.platform == 'win32': m0 = self.clean_glob(text) else: m0 = self.clean_glob(text.replace('\\', '')) if has_protectables: # If we had protectables, we need to revert our changes to the # beginning of filename so that we don't double-write the part # of the filename we have so far len_lsplit = len(lsplit) matches = [text_prefix + text0 + protect_filename(f[len_lsplit:]) for f in m0] else: if open_quotes: # if we have a string with an open quote, we don't need to # protect the names at all (and we _shouldn't_, as it # would cause bugs when the filesystem call is made). matches = m0 else: matches = [text_prefix + protect_filename(f) for f in m0] # Mark directories in input list by appending '/' to their names. return [cast_unicode_py2(x+'/') if os.path.isdir(x) else x for x in matches]
def history(self, parameter_s = ''): """Print input history (_i<n> variables), with most recent last. By default, input history is printed without line numbers so it can be directly pasted into an editor. Use -n to show them. By default, all input history from the current session is displayed. Ranges of history can be indicated using the syntax: ``4`` Line 4, current session ``4-6`` Lines 4-6, current session ``243/1-5`` Lines 1-5, session 243 ``~2/7`` Line 7, session 2 before current ``~8/1-~6/5`` From the first line of 8 sessions ago, to the fifth line of 6 sessions ago. Multiple ranges can be entered, separated by spaces The same syntax is used by %macro, %save, %edit, %rerun Examples -------- :: In [6]: %history -n 4-6 4:a = 12 5:print a**2 6:%history -n 4-6 """ args = parse_argstring(self.history, parameter_s) # For brevity history_manager = self.shell.history_manager def _format_lineno(session, line): """Helper function to format line numbers properly.""" if session in (0, history_manager.session_number): return str(line) return "%s/%s" % (session, line) # Check if output to specific file was requested. outfname = args.filename if not outfname: outfile = io.stdout # default # We don't want to close stdout at the end! close_at_end = False else: if os.path.exists(outfname): try: ans = io.ask_yes_no("File %r exists. Overwrite?" % outfname) except StdinNotImplementedError: ans = True if not ans: print('Aborting.') return print("Overwriting file.") outfile = io_open(outfname, 'w', encoding='utf-8') close_at_end = True print_nums = args.print_nums get_output = args.get_output pyprompts = args.pyprompts raw = args.raw pattern = None limit = None if args.limit is _unspecified else args.limit if args.pattern is not None: if args.pattern: pattern = "*" + " ".join(args.pattern) + "*" else: pattern = "*" hist = history_manager.search(pattern, raw=raw, output=get_output, n=limit, unique=args.unique) print_nums = True elif args.limit is not _unspecified: n = 10 if limit is None else limit hist = history_manager.get_tail(n, raw=raw, output=get_output) else: if args.range: # Get history by ranges hist = history_manager.get_range_by_str(" ".join(args.range), raw, get_output) else: # Just get history for the current session hist = history_manager.get_range(raw=raw, output=get_output) # We could be displaying the entire history, so let's not try to pull # it into a list in memory. Anything that needs more space will just # misalign. width = 4 for session, lineno, inline in hist: # Print user history with tabs expanded to 4 spaces. The GUI # clients use hard tabs for easier usability in auto-indented code, # but we want to produce PEP-8 compliant history for safe pasting # into an editor. if get_output: inline, output = inline inline = inline.expandtabs(4).rstrip() multiline = "\n" in inline line_sep = '\n' if multiline else ' ' if print_nums: print(u'%s:%s' % (_format_lineno(session, lineno).rjust(width), line_sep), file=outfile, end=u'') if pyprompts: print(u">>> ", end=u"", file=outfile) if multiline: inline = "\n... ".join(inline.splitlines()) + "\n..." print(inline, file=outfile) if get_output and output: print(cast_unicode_py2(output), file=outfile) if close_at_end: outfile.close()
def pre_prompt(self): if self.rl_next_input: self.pt_cli.application.buffer.text = cast_unicode_py2(self.rl_next_input) self.rl_next_input = None
def init_prompt_toolkit_cli(self): if self.simple_prompt or ('JUPYTER_CONSOLE_TEST' in os.environ): # Simple restricted interface for tests so we can find prompts with # pexpect. Multi-line input not supported. def prompt(): return cast_unicode_py2(input('In [%d]: ' % self.execution_count)) self.prompt_for_code = prompt self.print_out_prompt = \ lambda: print('Out[%d]: ' % self.execution_count, end='') return kbmanager = KeyBindingManager.for_prompt() insert_mode = ViInsertMode() | EmacsInsertMode() # Ctrl+J == Enter, seemingly @kbmanager.registry.add_binding(Keys.ControlJ, filter=(HasFocus(DEFAULT_BUFFER) & ~HasSelection() & insert_mode )) def _(event): b = event.current_buffer d = b.document if not (d.on_last_line or d.cursor_position_row >= d.line_count - d.empty_line_count_at_the_end()): b.newline() return # Pressing enter flushes any pending display. This also ensures # the displayed execution_count is correct. self.handle_iopub() more, indent = self.check_complete(d.text) if (not more) and b.accept_action.is_returnable: b.accept_action.validate_and_handle(event.cli, b) else: b.insert_text('\n' + indent) @kbmanager.registry.add_binding(Keys.ControlC, filter=HasFocus(DEFAULT_BUFFER)) def _(event): event.current_buffer.reset() @kbmanager.registry.add_binding(Keys.ControlBackslash, filter=HasFocus(DEFAULT_BUFFER)) def _(event): raise EOFError # Pre-populate history from IPython's history database history = InMemoryHistory() last_cell = u"" for _, _, cell in self.history_manager.get_tail(self.history_load_length, include_latest=True): # Ignore blank lines and consecutive duplicates cell = cast_unicode_py2(cell.rstrip()) if cell and (cell != last_cell): history.append(cell) style_overrides = { Token.Prompt: '#009900', Token.PromptNum: '#00ff00 bold', Token.OutPrompt: '#ff2200', Token.OutPromptNum: '#ff0000 bold', } if self.highlighting_style: style_cls = get_style_by_name(self.highlighting_style) else: style_cls = get_style_by_name('default') # The default theme needs to be visible on both a dark background # and a light background, because we can't tell what the terminal # looks like. These tweaks to the default theme help with that. style_overrides.update({ Token.Number: '#007700', Token.Operator: 'noinherit', Token.String: '#BB6622', Token.Name.Function: '#2080D0', Token.Name.Class: 'bold #2080D0', Token.Name.Namespace: 'bold #2080D0', }) style_overrides.update(self.highlighting_style_overrides) style = PygmentsStyle.from_defaults(pygments_style_cls=style_cls, style_dict=style_overrides) editing_mode = getattr(EditingMode, self.editing_mode.upper()) langinfo = self.kernel_info.get('language_info', {}) lexer = langinfo.get('pygments_lexer', langinfo.get('name', 'text')) app = create_prompt_application(multiline=True, editing_mode=editing_mode, lexer=PygmentsLexer(get_pygments_lexer(lexer)), get_prompt_tokens=self.get_prompt_tokens, get_continuation_tokens=self.get_continuation_tokens, key_bindings_registry=kbmanager.registry, history=history, completer=JupyterPTCompleter(self.Completer), enable_history_search=True, style=style, ) self._eventloop = create_eventloop() self.pt_cli = CommandLineInterface(app, eventloop=self._eventloop, output=create_output(true_color=self.true_color), )