Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/IPython/dtutils.py
blob: 37e7aa2c9f437b014d4416b172718d26ca3db556 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
"""Doctest-related utilities for IPython.

For most common uses, all you should need to run is::

  from IPython.dtutils import idoctest

See the idoctest docstring below for usage details.
"""

import doctest
import sys

import IPython.ipapi
ip = IPython.ipapi.get()

def rundoctest(text,ns=None,eraise=False):
    """Run a the input source as a doctest, in the caller's namespace.

    :Parameters:
      text : str
        Source to execute.

    :Keywords:
      ns : dict (None)
        Namespace where the code should be executed.  If not given, the
        caller's locals and globals are used.
      eraise : bool (False)
        If true, immediately raise any exceptions instead of reporting them at
        the end.  This allows you to then do interactive debugging via
        IPython's facilities (use %debug after the fact, or with %pdb for
        automatic activation).
    """

    name = 'interactive doctest'
    filename = '<IPython console>'

    if eraise:
        runner = doctest.DebugRunner()
    else:
        runner = doctest.DocTestRunner()
        
    parser = doctest.DocTestParser()
    if ns is None:
        f = sys._getframe(1)
        ns = f.f_globals.copy()
        ns.update(f.f_locals)
        
    test = parser.get_doctest(text,ns,name,filename,0)
    runner.run(test)
    runner.summarize(True)

       
def idoctest(ns=None,eraise=False):
    """Interactively prompt for input and run it as a doctest.

    To finish entering input, enter two blank lines or Ctrl-D (EOF).  If you
    use Ctrl-C, the example is aborted and all input discarded.

    :Keywords:
      ns : dict (None)
        Namespace where the code should be executed.  If not given, the IPython
        interactive namespace is used.
      eraise : bool (False)
        If true, immediately raise any exceptions instead of reporting them at
        the end.  This allows you to then do interactive debugging via
        IPython's facilities (use %debug after the fact, or with %pdb for
        automatic activation).
      end_mark : str ('--')
        String to explicitly indicate the end of input.

    """
    
    inlines = []
    empty_lines = 0  # count consecutive empty lines
    run_test = True

    if ns is None:
        ns = ip.user_ns

    ip.IP.savehist()
    try:
        while True:
            line = raw_input()
            if not line or line.isspace():
                empty_lines += 1
            else:
                empty_lines = 0

            if empty_lines>=2:
                break

            inlines.append(line)
    except EOFError:
        pass
    except KeyboardInterrupt:
        print "KeyboardInterrupt - Discarding input."
        run_test = False
    
    ip.IP.reloadhist()

    if run_test:
        # Extra blank line at the end to ensure that the final docstring has a
        # closing newline
        inlines.append('')
        rundoctest('\n'.join(inlines),ns,eraise)


# For debugging of this module itself.
if __name__ == "__main__":
    t = """
    >>> for i in range(10):
    ...     print i,
    ...
    0 1 2 3 4 5 6 7 8 9
    """

    t2 = """
        A simple example::

          >>> for i in range(10):
          ...     print i,
          ...
          0 1 2 3 4 5 6 7 8 9

        Some more details::

          >>> print "hello"
          hello
    """

    t3 = """
        A failing example::

          >>> x=1
          >>> x+1
          3
    """