From 07595d8260accf2e5252b9fbd1333e37c36f2075 2010-10-29 20:34:58 From: Robert Kern Date: 2010-10-29 20:34:58 Subject: [PATCH] ENH: Allow configurability of the DefaultFormatter and the DisplayHook. --- diff --git a/IPython/core/displayhook.py b/IPython/core/displayhook.py index 89b83d8..cca5b92 100644 --- a/IPython/core/displayhook.py +++ b/IPython/core/displayhook.py @@ -20,15 +20,14 @@ Authors: #----------------------------------------------------------------------------- import __builtin__ -from pprint import PrettyPrinter -pformat = PrettyPrinter().pformat 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, Int +from IPython.utils.traitlets import Instance, List from IPython.utils.warn import warn +from IPython.core.formatters import DefaultFormatter #----------------------------------------------------------------------------- # Main displayhook class @@ -55,6 +54,16 @@ class DisplayHook(Configurable): 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) @@ -109,7 +118,6 @@ class DisplayHook(Configurable): self.output_sep = output_sep self.output_sep2 = output_sep2 self._,self.__,self.___ = '','','' - self.pprint_types = map(type,[(),[],{}]) # these are deliberately global: to_user_ns = {'_':self._,'__':self.__,'___':self.___} @@ -184,37 +192,23 @@ class DisplayHook(Configurable): if self.do_full_cache: IPython.utils.io.Term.cout.write(outprompt) - # TODO: Make this method an extension point. The previous implementation - # has both a result_display hook as well as a result_display generic - # function to customize the repr on a per class basis. We need to rethink - # the hooks mechanism before doing this though. 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 - actual print or write that to a stream. This method may also transform - the result itself, but the default implementation passes the original - through. + actual print or write that to a stream. """ - try: - if self.shell.pprint: - try: - result_repr = pformat(result) - except: - # Work around possible bugs in pformat - result_repr = repr(result) - 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. - result_repr = '\n' + result_repr - else: - result_repr = repr(result) - except TypeError: - # This happens when result.__repr__ doesn't return a string, - # such as when it returns None. - result_repr = '\n' - return result, result_repr + result_repr = self.default_formatter(result) + 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. + outprompt = str(self.prompt_out) + if outprompt and not outprompt.endswith('\n'): + # But avoid extraneous empty lines. + result_repr = '\n' + result_repr + + return result_repr def write_result_repr(self, result_repr): # We want to print because we want to always make sure we have a @@ -271,7 +265,7 @@ class DisplayHook(Configurable): if result is not None and not self.quiet(): self.start_displayhook() self.write_output_prompt() - result, result_repr = self.compute_result_repr(result) + result_repr = self.compute_result_repr(result) self.write_result_repr(result_repr) self.update_user_ns(result) self.log_output(result) diff --git a/IPython/core/formatters.py b/IPython/core/formatters.py index a40313c..9faab6c 100644 --- a/IPython/core/formatters.py +++ b/IPython/core/formatters.py @@ -25,32 +25,32 @@ class DefaultFormatter(Configurable): format = Str('text') # Whether to pretty-print or not. - pprint = Bool(True) + pprint = Bool(True, config=True) # Whether to be verbose or not. - verbose = Bool(False) + verbose = Bool(False, config=True) # The maximum width. - max_width = Int(79) + max_width = Int(79, config=True) # The newline character. - newline = Str('\n') + newline = Str('\n', config=True) # The singleton prettyprinters. # Maps the IDs of the builtin singleton objects to the format functions. - singleton_pprinters = Dict() + singleton_pprinters = Dict(config=True) def _singleton_pprinters_default(self): return pretty._singleton_pprinters.copy() # The type-specific prettyprinters. # Map type objects to the format functions. - type_pprinters = Dict() + type_pprinters = Dict(config=True) def _type_pprinters_default(self): return pretty._type_pprinters.copy() # The deferred-import type-specific prettyprinters. # Map (modulename, classname) pairs to the format functions. - deferred_pprinters = Dict() + deferred_pprinters = Dict(config=True) def _deferred_pprinters_default(self): return pretty._deferred_type_pprinters.copy() @@ -60,11 +60,10 @@ class DefaultFormatter(Configurable): """ Format the object. """ if not self.pprint: - r = repr(obj) - if r is None: - # It can happen. - r = '' - return r + try: + return repr(obj) + except TypeError: + return '' else: stream = StringIO() printer = pretty.RepresentationPrinter(stream, self.verbose, diff --git a/IPython/core/interactiveshell.py b/IPython/core/interactiveshell.py index e12af7e..01c5c96 100644 --- a/IPython/core/interactiveshell.py +++ b/IPython/core/interactiveshell.py @@ -475,6 +475,7 @@ class InteractiveShell(Configurable, Magic): def init_displayhook(self): # Initialize displayhook, set in/out prompts and printing system self.displayhook = self.displayhook_class( + config=self.config, shell=self, cache_size=self.cache_size, input_sep = self.separate_in,