From 9ccbf202c4b61db2e4f5555dd10526cb0ea8c630 2006-05-26 07:52:45
From: fperez
Date: 2006-05-26 07:52:45
Subject: [PATCH] - fix bug where aliases would shadow variables when autocall was fully off.

- add a flag to controlat what detail level strings are computed when foo?
is requested.

Both after problems reported by SAGE

---

diff --git a/IPython/OInspect.py b/IPython/OInspect.py
index 64a429d..f4df4bd 100644
--- a/IPython/OInspect.py
+++ b/IPython/OInspect.py
@@ -6,7 +6,7 @@ Uses syntax highlighting for presenting the various information elements.
 Similar in spirit to the inspect module, but all calls take a name argument to
 reference the name under which an object is being read.
 
-$Id: OInspect.py 1300 2006-05-15 16:27:36Z vivainio $
+$Id: OInspect.py 1329 2006-05-26 07:52:45Z fperez $
 """
 
 #*****************************************************************************
@@ -107,10 +107,12 @@ class myStringIO(StringIO.StringIO):
         self.write('\n')
 
 class Inspector:
-    def __init__(self,color_table,code_color_table,scheme):
+    def __init__(self,color_table,code_color_table,scheme,
+                 str_detail_level=0):
         self.color_table = color_table
         self.parser = PyColorize.Parser(code_color_table,out='str')
         self.format = self.parser.format
+        self.str_detail_level = str_detail_level
         self.set_active_scheme(scheme)
 
     def __getargspec(self,obj):
@@ -302,21 +304,22 @@ class Inspector:
         except: pass
 
         # String form, but snip if too long in ? form (full in ??)
-        try:
-            ostr = str(obj)
-            str_head = 'String Form:'
-            if not detail_level and len(ostr)>string_max:
-                ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
-                ostr = ("\n" + " " * len(str_head.expandtabs())).\
-                       join(map(string.strip,ostr.split("\n")))
-            if ostr.find('\n') > -1:
-                # Print multi-line strings starting at the next line.
-                str_sep = '\n'
-            else:
-                str_sep = '\t'
-            out.writeln("%s%s%s" % (header(str_head),str_sep,ostr))
-        except:
-            pass
+        if detail_level >= self.str_detail_level:
+            try:
+                ostr = str(obj)
+                str_head = 'String Form:'
+                if not detail_level and len(ostr)>string_max:
+                    ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
+                    ostr = ("\n" + " " * len(str_head.expandtabs())).\
+                           join(map(string.strip,ostr.split("\n")))
+                if ostr.find('\n') > -1:
+                    # Print multi-line strings starting at the next line.
+                    str_sep = '\n'
+                else:
+                    str_sep = '\t'
+                out.writeln("%s%s%s" % (header(str_head),str_sep,ostr))
+            except:
+                pass
 
         if ospace:
             out.writeln(header('Namespace:\t')+ospace)
diff --git a/IPython/UserConfig/ipythonrc b/IPython/UserConfig/ipythonrc
index 9de6488..33ebc28 100644
--- a/IPython/UserConfig/ipythonrc
+++ b/IPython/UserConfig/ipythonrc
@@ -1,5 +1,5 @@
 # -*- Mode: Shell-Script -*-  Not really, but shows comments correctly
-# $Id: ipythonrc 1324 2006-05-24 20:25:11Z fperez $
+# $Id: ipythonrc 1329 2006-05-26 07:52:45Z fperez $
 
 #***************************************************************************
 #
@@ -299,6 +299,16 @@ nosep 0
 
 wildcards_case_sensitive 1
 
+# Object information: at what level of detail to display the string form of an
+# object.  If set to 0, ipython will compute the string form of any object X,
+# by calling str(X), when X? is typed.  If set to 1, str(X) will only be
+# computed when X?? is given, and if set to 2 or higher, it will never be
+# computed (there is no X??? level of detail).  This is mostly of use to
+# people who frequently manipulate objects whose string representation is
+# extremely expensive to compute.
+
+object_info_string_level 0
+
 # xmode - Exception reporting mode. 
 
 # Valid modes: Plain, Context and Verbose.
diff --git a/IPython/iplib.py b/IPython/iplib.py
index cb4de0a..3e8b250 100644
--- a/IPython/iplib.py
+++ b/IPython/iplib.py
@@ -6,7 +6,7 @@ Requires Python 2.3 or newer.
 
 This file contains all the classes and helper functions specific to IPython.
 
-$Id: iplib.py 1326 2006-05-25 02:07:11Z fperez $
+$Id: iplib.py 1329 2006-05-26 07:52:45Z fperez $
 """
 
 #*****************************************************************************
@@ -537,10 +537,6 @@ class InteractiveShell(object,Magic):
         # and add any custom exception handlers the user may have specified
         self.set_custom_exc(*custom_exceptions)
 
-        # Object inspector
-        self.inspector = OInspect.Inspector(OInspect.InspectColors,
-                                            PyColorize.ANSICodeColors,
-                                            'NoColor')
         # indentation management
         self.autoindent = False
         self.indent_current_nsp = 0
@@ -607,6 +603,12 @@ class InteractiveShell(object,Magic):
         'finalize' the initialization."""
 
         rc = self.rc
+
+        # Object inspector
+        self.inspector = OInspect.Inspector(OInspect.InspectColors,
+                                            PyColorize.ANSICodeColors,
+                                            'NoColor',
+                                            rc.object_info_string_level)
         
         # Load readline proper
         if rc.readline:
@@ -1874,9 +1876,6 @@ want to merge them back into the new files.""" % locals()
             rewritten = pre + rewritten  # add indentation
             return self.handle_normal(rewritten)
             
-        
-        
-
         #print 'pre <%s> iFun <%s> rest <%s>' % (pre,iFun,theRest)  # dbg
 
         # First check for explicit escapes in the last/first character
@@ -1941,8 +1940,18 @@ want to merge them back into the new files.""" % locals()
                 # in this case, all that's left is either an alias or
                 # processing the line normally.
                 if iFun in self.alias_table:
-                    return self.handle_alias(line,continue_prompt,
-                                             pre,iFun,theRest)
+                    # if autocall is off, by not running _ofind we won't know
+                    # whether the given name may also exist in one of the
+                    # user's namespace.  At this point, it's best to do a
+                    # quick check just to be sure that we don't let aliases
+                    # shadow variables.
+                    head = iFun.split('.',1)[0]
+                    if head in self.user_ns or head in self.internal_ns \
+                       or head in __builtin__.__dict__:
+                        return self.handle_normal(line,continue_prompt)
+                    else:
+                        return self.handle_alias(line,continue_prompt,
+                                                 pre,iFun,theRest)
                  
                 else:
                     return self.handle_normal(line,continue_prompt)
diff --git a/IPython/ipmaker.py b/IPython/ipmaker.py
index 4a7eaa0..0dd7a34 100644
--- a/IPython/ipmaker.py
+++ b/IPython/ipmaker.py
@@ -6,7 +6,7 @@ Requires Python 2.1 or better.
 
 This file contains the main make_IPython() starter function.
 
-$Id: ipmaker.py 1328 2006-05-25 07:47:56Z fperez $"""
+$Id: ipmaker.py 1329 2006-05-26 07:52:45Z fperez $"""
 
 #*****************************************************************************
 #       Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu>
@@ -155,7 +155,8 @@ object? -> Details about 'object'. ?object also works, ?? prints more.
     # Make sure there's a space before each end of line (they get auto-joined!)
     cmdline_opts = ('autocall=i autoindent! automagic! banner! cache_size|cs=i '
                     'c=s classic|cl color_info! colors=s confirm_exit! '
-                    'debug! deep_reload! editor=s log|l messages! nosep pdb! '
+                    'debug! deep_reload! editor=s log|l messages! nosep '
+                    'object_info_string_level=i pdb! '
                     'pprint! prompt_in1|pi1=s prompt_in2|pi2=s prompt_out|po=s '
                     'quick screen_length|sl=i prompts_pad_left=i '
                     'logfile|lf=s logplay|lp=s profile|p=s '
@@ -202,6 +203,7 @@ object? -> Details about 'object'. ?object also works, ?? prints more.
                       logplay = '',
                       multi_line_specials = 1,
                       messages = 1,
+                      object_info_string_level = 0,
                       nosep = 0,
                       pdb = 0,
                       pprint = 0,
diff --git a/doc/ChangeLog b/doc/ChangeLog
index 1e27423..a8bce70 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -1,3 +1,18 @@
+2006-05-26  Fernando Perez  <Fernando.Perez@colorado.edu>
+
+	* IPython/iplib.py (_prefilter): fix bug where aliases would
+	shadow variables when autocall was fully off.  Reported by SAGE
+	author William Stein.
+
+	* IPython/OInspect.py (Inspector.__init__): add a flag to control
+	at what detail level strings are computed when foo? is requested.
+	This allows users to ask for example that the string form of an
+	object is only computed when foo?? is called, or even never, by
+	setting the object_info_string_level >= 2 in the configuration
+	file.  This new option has been added and documented.  After a
+	request by SAGE to be able to control the printing of very large
+	objects more easily.
+
 2006-05-25  Fernando Perez  <Fernando.Perez@colorado.edu>
 
 	* IPython/ipmaker.py (make_IPython): remove the ipython call path