##// END OF EJS Templates
Hide private names by default in tab completion....
Hide private names by default in tab completion. This is the most reasonable behavior for new users, and it's important to have a good default until we can make the qt console fully configurable.

File last commit:

r3224:c77a02a1
r3238:76796b5c
Show More
displayhook.py
304 lines | 11.8 KiB | text/x-python | PythonLexer
# -*- coding: utf-8 -*-
"""Displayhook for IPython.
Authors:
* Fernando Perez
* Brian Granger
"""
#-----------------------------------------------------------------------------
# Copyright (C) 2008-2010 The IPython Development Team
# Copyright (C) 2001-2007 Fernando Perez <fperez@colorado.edu>
#
# Distributed under the terms of the BSD License. The full license is in
# the file COPYING, distributed as part of this software.
#-----------------------------------------------------------------------------
#-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------
import __builtin__
from IPython.config.configurable import Configurable
from IPython.core import prompts
import IPython.utils.generics
import IPython.utils.io
from IPython.utils.traitlets import Instance, List
from IPython.utils.warn import warn
from IPython.core.formatters import DefaultFormatter
#-----------------------------------------------------------------------------
# Main displayhook class
#-----------------------------------------------------------------------------
# TODO: The DisplayHook class should be split into two classes, one that
# manages the prompts and their synchronization and another that just does the
# displayhook logic and calls into the prompt manager.
# TODO: Move the various attributes (cache_size, colors, input_sep,
# output_sep, output_sep2, ps1, ps2, ps_out, pad_left). Some of these are also
# attributes of InteractiveShell. They should be on ONE object only and the
# other objects should ask that one object for their values.
class DisplayHook(Configurable):
"""The custom IPython displayhook to replace sys.displayhook.
This class does many things, but the basic idea is that it is a callable
that gets called anytime user code returns a value.
Currently this class does more than just the displayhook logic and that
extra logic should eventually be moved out of here.
"""
shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
# The default formatter.
default_formatter = Instance('IPython.core.formatters.FormatterABC')
def _default_formatter_default(self):
# FIXME: backwards compatibility for the InteractiveShell.pprint option?
return DefaultFormatter(config=self.config)
# Any additional FormatterABC instances we use.
# FIXME: currently unused.
extra_formatters = List(config=True)
# Each call to the In[] prompt raises it by 1, even the first.
#prompt_count = Int(0)
def __init__(self, shell=None, cache_size=1000,
colors='NoColor', input_sep='\n',
output_sep='\n', output_sep2='',
ps1 = None, ps2 = None, ps_out = None, pad_left=True,
config=None):
super(DisplayHook, self).__init__(shell=shell, config=config)
cache_size_min = 3
if cache_size <= 0:
self.do_full_cache = 0
cache_size = 0
elif cache_size < cache_size_min:
self.do_full_cache = 0
cache_size = 0
warn('caching was disabled (min value for cache size is %s).' %
cache_size_min,level=3)
else:
self.do_full_cache = 1
self.cache_size = cache_size
self.input_sep = input_sep
# we need a reference to the user-level namespace
self.shell = shell
# Set input prompt strings and colors
if cache_size == 0:
if ps1.find('%n') > -1 or ps1.find(r'\#') > -1 \
or ps1.find(r'\N') > -1:
ps1 = '>>> '
if ps2.find('%n') > -1 or ps2.find(r'\#') > -1 \
or ps2.find(r'\N') > -1:
ps2 = '... '
self.ps1_str = self._set_prompt_str(ps1,'In [\\#]: ','>>> ')
self.ps2_str = self._set_prompt_str(ps2,' .\\D.: ','... ')
self.ps_out_str = self._set_prompt_str(ps_out,'Out[\\#]: ','')
self.color_table = prompts.PromptColors
self.prompt1 = prompts.Prompt1(self,sep=input_sep,prompt=self.ps1_str,
pad_left=pad_left)
self.prompt2 = prompts.Prompt2(self,prompt=self.ps2_str,pad_left=pad_left)
self.prompt_out = prompts.PromptOut(self,sep='',prompt=self.ps_out_str,
pad_left=pad_left)
self.set_colors(colors)
# Store the last prompt string each time, we need it for aligning
# continuation and auto-rewrite prompts
self.last_prompt = ''
self.output_sep = output_sep
self.output_sep2 = output_sep2
self._,self.__,self.___ = '','',''
# these are deliberately global:
to_user_ns = {'_':self._,'__':self.__,'___':self.___}
self.shell.user_ns.update(to_user_ns)
@property
def prompt_count(self):
return self.shell.execution_count
def _set_prompt_str(self,p_str,cache_def,no_cache_def):
if p_str is None:
if self.do_full_cache:
return cache_def
else:
return no_cache_def
else:
return p_str
def set_colors(self, colors):
"""Set the active color scheme and configure colors for the three
prompt subsystems."""
# FIXME: This modifying of the global prompts.prompt_specials needs
# to be fixed. We need to refactor all of the prompts stuff to use
# proper configuration and traits notifications.
if colors.lower()=='nocolor':
prompts.prompt_specials = prompts.prompt_specials_nocolor
else:
prompts.prompt_specials = prompts.prompt_specials_color
self.color_table.set_active_scheme(colors)
self.prompt1.set_colors()
self.prompt2.set_colors()
self.prompt_out.set_colors()
#-------------------------------------------------------------------------
# Methods used in __call__. Override these methods to modify the behavior
# of the displayhook.
#-------------------------------------------------------------------------
def check_for_underscore(self):
"""Check if the user has set the '_' variable by hand."""
# If something injected a '_' variable in __builtin__, delete
# ipython's automatic one so we don't clobber that. gettext() in
# particular uses _, so we need to stay away from it.
if '_' in __builtin__.__dict__:
try:
del self.shell.user_ns['_']
except KeyError:
pass
def quiet(self):
"""Should we silence the display hook because of ';'?"""
# do not print output if input ends in ';'
try:
if self.shell.input_hist[self.prompt_count].endswith(';\n'):
return True
except IndexError:
# some uses of ipshellembed may fail here
pass
return False
def start_displayhook(self):
"""Start the displayhook, initializing resources."""
pass
def write_output_prompt(self):
"""Write the output prompt."""
# Use write, not print which adds an extra space.
IPython.utils.io.Term.cout.write(self.output_sep)
outprompt = str(self.prompt_out)
if self.do_full_cache:
IPython.utils.io.Term.cout.write(outprompt)
def compute_result_repr(self, result):
"""Compute and return the repr of the object to be displayed.
This method only compute the string form of the repr and should NOT
actually print or write that to a stream.
"""
result_repr = self.default_formatter(result)
extra_formats = []
for f in self.extra_formatters:
try:
data = f(result)
except Exception:
# FIXME: log the exception.
continue
if data is not None:
extra_formats.append((f.id, f.format, data))
return result_repr, extra_formats
def write_result_repr(self, result_repr, extra_formats):
# We want to print because we want to always make sure we have a
# newline, even if all the prompt separators are ''. This is the
# standard IPython behavior.
if '\n' in result_repr:
# So that multi-line strings line up with the left column of
# the screen, instead of having the output prompt mess up
# their first line.
# We use the ps_out_str template instead of the expanded prompt
# because the expansion may add ANSI escapes that will interfere
# with our ability to determine whether or not we should add
# a newline.
if self.ps_out_str and not self.ps_out_str.endswith('\n'):
# But avoid extraneous empty lines.
result_repr = '\n' + result_repr
print >>IPython.utils.io.Term.cout, result_repr
def update_user_ns(self, result):
"""Update user_ns with various things like _, __, _1, etc."""
# Avoid recursive reference when displaying _oh/Out
if result is not self.shell.user_ns['_oh']:
if len(self.shell.user_ns['_oh']) >= self.cache_size and self.do_full_cache:
warn('Output cache limit (currently '+
`self.cache_size`+' entries) hit.\n'
'Flushing cache and resetting history counter...\n'
'The only history variables available will be _,__,___ and _1\n'
'with the current result.')
self.flush()
# Don't overwrite '_' and friends if '_' is in __builtin__ (otherwise
# we cause buggy behavior for things like gettext).
if '_' not in __builtin__.__dict__:
self.___ = self.__
self.__ = self._
self._ = result
self.shell.user_ns.update({'_':self._,'__':self.__,'___':self.___})
# hackish access to top-level namespace to create _1,_2... dynamically
to_main = {}
if self.do_full_cache:
new_result = '_'+`self.prompt_count`
to_main[new_result] = result
self.shell.user_ns.update(to_main)
self.shell.user_ns['_oh'][self.prompt_count] = result
def log_output(self, result):
"""Log the output."""
if self.shell.logger.log_output:
self.shell.logger.log_write(repr(result), 'output')
def finish_displayhook(self):
"""Finish up all displayhook activities."""
IPython.utils.io.Term.cout.write(self.output_sep2)
IPython.utils.io.Term.cout.flush()
def __call__(self, result=None):
"""Printing with history cache management.
This is invoked everytime the interpreter needs to print, and is
activated by setting the variable sys.displayhook to it.
"""
self.check_for_underscore()
if result is not None and not self.quiet():
self.start_displayhook()
self.write_output_prompt()
result_repr, extra_formats = self.compute_result_repr(result)
self.write_result_repr(result_repr, extra_formats)
self.update_user_ns(result)
self.log_output(result)
self.finish_displayhook()
def flush(self):
if not self.do_full_cache:
raise ValueError,"You shouldn't have reached the cache flush "\
"if full caching is not enabled!"
# delete auto-generated vars from global namespace
for n in range(1,self.prompt_count + 1):
key = '_'+`n`
try:
del self.shell.user_ns[key]
except: pass
self.shell.user_ns['_oh'].clear()
if '_' not in __builtin__.__dict__:
self.shell.user_ns.update({'_':None,'__':None, '___':None})
import gc
gc.collect() # xxx needed?