Repository: ipython/ipython

Issue:
User defined context in print_stack_entry
When using `ipdb`'s `set_trace()`, `print_stack_entry` sets the [default context to 3 lines](https://github.com/ipython/ipython/blob/master/IPython/core/debugger.py#L335). While this does preserve space, it can be very helpful to have a user defined context size, rather than continuously hitting `l` (list) to display more lines.

It would be great to add a keyword to `ipdb's`'s `set_trace` (such as `context` or even `c`) that passes a context value to [Pdb](https://github.com/ipython/ipython/blob/master/IPython/core/debugger.py#L201). The change to ipython would be minimal: Adding a `context` keyword to `Pdb` and `print_stack_entry`.

Not sure if there is a cleaner way to integrate this (perhaps into [Tracer's set_trace](https://github.com/ipython/ipython/blob/master/IPython/core/debugger.py#L170)?)



Discussion:
We should likely (also) overwrite `do_where` to take as argument the number of line of context to show. 

@Carreau can you elaborate on overwritting `do_where`? 

See #9093 for pull request. 

![do_w](https://cloud.githubusercontent.com/assets/335567/11941616/39cf0252-a831-11e5-9ec4-7487e59da705.gif)

Cool! Can we integrate `do_where` with `print_stack_entry`? 

See [ipdb#35](https://github.com/gotcha/ipdb/issues/35). It seems like there are two ways of adding user defined context values: By editing `bdb.set_trace()`, or by passing a context keyword to `ipdb.set_trace(context=10)`, and pass that to [IPython's Pdb](https://github.com/ipython/ipython/blob/master/IPython/core/debugger.py#L201) as an instance variable, then use that in `print_stack_entry`.  

Unfortunately, there is no easy way to [amend to your PR](https://help.github.com/articles/checking-out-pull-requests-locally/), so I can include your commits in my PR.

> Unfortunately, there is no easy way to amend to your PR, so I can include your commits in my PR.

Oh, you just have the right to push on my PR, but you can send a PR againt my PR or send a new one. I updated mine to add a `context` kwarg and  instance variable. 


Resolving patch:
diff --git a/IPython/core/debugger.py b/IPython/core/debugger.py
--- a/IPython/core/debugger.py
+++ b/IPython/core/debugger.py
@@ -29,7 +29,6 @@
 import bdb
 import functools
 import inspect
-import linecache
 import sys
 
 from IPython import get_ipython
@@ -54,7 +53,6 @@
 
 if has_pydb:
     from pydb import Pdb as OldPdb
-    #print "Using pydb for %run -d and post-mortem" #dbg
     prompt = 'ipydb> '
 else:
     from pdb import Pdb as OldPdb
@@ -94,7 +92,7 @@ class Tracer(object):
     """
 
     @skip_doctest
-    def __init__(self,colors=None):
+    def __init__(self, colors=None):
         """Create a local debugger instance.
 
         Parameters
@@ -202,9 +200,16 @@ class Pdb(OldPdb):
     """Modified Pdb class, does not load readline."""
 
     def __init__(self,color_scheme='NoColor',completekey=None,
-                 stdin=None, stdout=None):
+                 stdin=None, stdout=None, context=5):
 
         # Parent constructor:
+        try:
+            self.context=int(context)
+            if self.context <= 0:
+                raise ValueError("Context must be a positive integer")
+        except (TypeError, ValueError):
+                raise ValueError("Context must be a positive integer")
+
         if has_pydb and completekey is None:
             OldPdb.__init__(self,stdin=stdin,stdout=io.stdout)
         else:
@@ -324,16 +329,31 @@ def new_do_restart(self, arg):
     def postloop(self):
         self.shell.set_completer_frame(None)
 
-    def print_stack_trace(self):
+    def print_stack_trace(self, context=None):
+        if context is None:
+            context = self.context
+        try:
+            context=int(context)
+            if context <= 0:
+                raise ValueError("Context must be a positive integer")
+        except (TypeError, ValueError):
+                raise ValueError("Context must be a positive integer")
         try:
             for frame_lineno in self.stack:
-                self.print_stack_entry(frame_lineno, context = 5)
+                self.print_stack_entry(frame_lineno, context=context)
         except KeyboardInterrupt:
             pass
 
     def print_stack_entry(self,frame_lineno,prompt_prefix='\n-> ',
-                          context = 3):
-        #frame, lineno = frame_lineno
+                          context=None):
+        if context is None:
+            context = self.context
+        try:
+            context=int(context)
+            if context <= 0:
+                raise ValueError("Context must be a positive integer")
+        except (TypeError, ValueError):
+                raise ValueError("Context must be a positive integer")
         print(self.format_stack_entry(frame_lineno, '', context), file=io.stdout)
 
         # vds: >>
@@ -342,7 +362,15 @@ def print_stack_entry(self,frame_lineno,prompt_prefix='\n-> ',
         self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
         # vds: <<
 
-    def format_stack_entry(self, frame_lineno, lprefix=': ', context = 3):
+    def format_stack_entry(self, frame_lineno, lprefix=': ', context=None):
+        if context is None:
+            context = self.context
+        try:
+            context=int(context)
+            if context <= 0:
+                print("Context must be a positive integer")
+        except (TypeError, ValueError):
+                print("Context must be a positive integer")
         try:
             import reprlib  # Py 3
         except ImportError:
@@ -530,7 +558,6 @@ def getsourcelines(self, obj):
     def do_longlist(self, arg):
         self.lastcmd = 'longlist'
         filename = self.curframe.f_code.co_filename
-        breaklist = self.get_file_breaks(filename)
         try:
             lines, lineno = self.getsourcelines(self.curframe)
         except OSError as err:
@@ -586,3 +613,20 @@ def do_psource(self, arg):
         namespaces = [('Locals', self.curframe.f_locals),
                       ('Globals', self.curframe.f_globals)]
         self.shell.find_line_magic('psource')(arg, namespaces=namespaces)
+
+    if sys.version_info > (3, ):
+        def do_where(self, arg):
+            """w(here)
+            Print a stack trace, with the most recent frame at the bottom.
+            An arrow indicates the "current frame", which determines the
+            context of most commands. 'bt' is an alias for this command.
+
+            Take a number as argument as an (optional) number of context line to
+            print"""
+            if arg:
+                context = int(arg)
+                self.print_stack_trace(context)
+            else:
+                self.print_stack_trace()
+
+        do_w = do_where


Test patch: