##// END OF EJS Templates
Implement support for all random tests. Other minor cleanups.
Fernando Perez -
Show More
@@ -21,9 +21,9 b' def pyfunc():'
21 ...
21 ...
22 0 1 1 2 2 3
22 0 1 1 2 2 3
23 """
23 """
24
25 return 'pyfunc'
24 return 'pyfunc'
26
25
26
27 def ipfunc():
27 def ipfunc():
28 """Some ipython tests...
28 """Some ipython tests...
29
29
@@ -67,14 +67,13 b' def ipfunc():'
67 In [9]: ipfunc()
67 In [9]: ipfunc()
68 Out[9]: 'ipfunc'
68 Out[9]: 'ipfunc'
69 """
69 """
70
71 return 'ipfunc'
70 return 'ipfunc'
72
71
73
72
74 def ranfunc():
73 def ranfunc():
75 """A function with some random output.
74 """A function with some random output.
76
75
77 Normal inputs are verified as usual:
76 Normal examples are verified as usual:
78 >>> 1+3
77 >>> 1+3
79 4
78 4
80
79
@@ -101,24 +100,26 b' def ranfunc():'
101 return 'ranfunc'
100 return 'ranfunc'
102
101
103
102
104 if 0:
103 def random_all():
105 def ranf2():
104 """A function where we ignore the output of ALL examples.
106 """A function whose examples' output are completely ignored.
107
105
108 Examples:
106 Examples:
109
107
110 #all-random
108 # all-random
111
109
112 >>> 1+3
110 This mark tells the testing machinery that all subsequent examples should
113 junk goes here...
111 be treated as random (ignoring their output). They are still executed,
112 so if a they raise an error, it will be detected as such, but their
113 output is completely ignored.
114
114
115 >>> 1+3
115 >>> 1+3
116 klasdfj;
116 junk goes here...
117
117
118 >>> 1+2
118 >>> 1+3
119 again, anything goes
119 klasdfj;
120 blah...
121
122 """
123 return 'ranf2'
124
120
121 >>> 1+2
122 again, anything goes
123 blah...
124 """
125 pass
@@ -78,20 +78,6 b' log = logging.getLogger(__name__)'
78 # machinery into a fit. This code should be considered a gross hack, but it
78 # machinery into a fit. This code should be considered a gross hack, but it
79 # gets the job done.
79 # gets the job done.
80
80
81 class ncdict(dict):
82 """Non-copying dict class.
83
84 This is a special-purpose dict subclass that overrides the .copy() method
85 to return the original object itself. We need it to ensure that doctests
86 happen in the IPython namespace, but doctest always makes a shallow copy of
87 the given globals for execution. Since we actually *want* this namespace
88 to be persistent (this is how the user's session maintains state), we
89 simply fool doctest by returning the original object upoon copy.
90 """
91
92 def copy(self):
93 return self
94
95
81
96 # XXX - Hack to modify the %run command so we can sync the user's namespace
82 # XXX - Hack to modify the %run command so we can sync the user's namespace
97 # with the test globals. Once we move over to a clean magic system, this will
83 # with the test globals. Once we move over to a clean magic system, this will
@@ -130,11 +116,8 b' def start_ipython():'
130 _excepthook = sys.excepthook
116 _excepthook = sys.excepthook
131 _main = sys.modules.get('__main__')
117 _main = sys.modules.get('__main__')
132
118
133 # Start IPython instance. We customize it to start with minimal frills and
119 # Start IPython instance. We customize it to start with minimal frills.
134 # with our own namespace.
120 IPython.Shell.IPShell(['--classic','--noterm_title'])
135 argv = ['--classic','--noterm_title']
136 user_ns = ncdict()
137 IPython.Shell.IPShell(argv,user_ns)
138
121
139 # Deactivate the various python system hooks added by ipython for
122 # Deactivate the various python system hooks added by ipython for
140 # interactive convenience so we don't confuse the doctest system
123 # interactive convenience so we don't confuse the doctest system
@@ -152,6 +135,7 b' def start_ipython():'
152 # doctest machinery would miss them.
135 # doctest machinery would miss them.
153 _ip.system = xsys
136 _ip.system = xsys
154
137
138 # Also patch our %run function in.
155 im = new.instancemethod(_run_ns_sync,_ip.IP, _ip.IP.__class__)
139 im = new.instancemethod(_run_ns_sync,_ip.IP, _ip.IP.__class__)
156 _ip.IP.magic_run_ori = _ip.IP.magic_run
140 _ip.IP.magic_run_ori = _ip.IP.magic_run
157 _ip.IP.magic_run = im
141 _ip.IP.magic_run = im
@@ -406,6 +390,12 b' class IPDocTestParser(doctest.DocTestParser):'
406 _EXAMPLE_RE_IP = re.compile( _RE_TPL % (_PS1_IP,_PS2_IP,_PS1_IP,_PS2_IP),
390 _EXAMPLE_RE_IP = re.compile( _RE_TPL % (_PS1_IP,_PS2_IP,_PS1_IP,_PS2_IP),
407 re.MULTILINE | re.VERBOSE)
391 re.MULTILINE | re.VERBOSE)
408
392
393 # Mark a test as being fully random. In this case, we simply append the
394 # random marker ('#random') to each individual example's output. This way
395 # we don't need to modify any other code.
396 _RANDOM_TEST = re.compile(r'#\s*all-random')
397
398 # Mark tests to be executed in an external process - currently unsupported.
409 _EXTERNAL_IP = re.compile(r'#\s*ipdoctest:\s*EXTERNAL')
399 _EXTERNAL_IP = re.compile(r'#\s*ipdoctest:\s*EXTERNAL')
410
400
411 def ip2py(self,source):
401 def ip2py(self,source):
@@ -438,6 +428,11 b' class IPDocTestParser(doctest.DocTestParser):'
438 output = []
428 output = []
439 charno, lineno = 0, 0
429 charno, lineno = 0, 0
440
430
431 if self._RANDOM_TEST.search(string):
432 random_marker = '\n# random'
433 else:
434 random_marker = ''
435
441 # Whether to convert the input from ipython to python syntax
436 # Whether to convert the input from ipython to python syntax
442 ip2py = False
437 ip2py = False
443 # Find all doctest examples in the string. First, try them as Python
438 # Find all doctest examples in the string. First, try them as Python
@@ -475,9 +470,15 b' class IPDocTestParser(doctest.DocTestParser):'
475 # Extract info from the regexp match.
470 # Extract info from the regexp match.
476 (source, options, want, exc_msg) = \
471 (source, options, want, exc_msg) = \
477 self._parse_example(m, name, lineno,ip2py)
472 self._parse_example(m, name, lineno,ip2py)
473
474 # Append the random-output marker (it defaults to empty in most
475 # cases, it's only non-empty for 'all-random' tests):
476 want += random_marker
477
478 if Example is IPExternalExample:
478 if Example is IPExternalExample:
479 options[doctest.NORMALIZE_WHITESPACE] = True
479 options[doctest.NORMALIZE_WHITESPACE] = True
480 want += '\n'
480 want += '\n'
481
481 # Create an Example, and add it to the list.
482 # Create an Example, and add it to the list.
482 if not self._IS_BLANK_OR_COMMENT(source):
483 if not self._IS_BLANK_OR_COMMENT(source):
483 #print 'Example source:', source # dbg
484 #print 'Example source:', source # dbg
General Comments 0
You need to be logged in to leave comments. Login now