##// END OF EJS Templates
Checkpoint with more tests working....
Fernando Perez -
Show More
@@ -0,0 +1,146 b''
1 ## The basic trick is to generate the source code for the decorated function
2 ## with the right signature and to evaluate it.
3 ## Uncomment the statement 'print >> sys.stderr, func_src' in _decorate
4 ## to understand what is going on.
5
6 __all__ = ["decorator", "update_wrapper", "getinfo"]
7
8 import inspect, sys
9
10 def getinfo(func):
11 """
12 Returns an info dictionary containing:
13 - name (the name of the function : str)
14 - argnames (the names of the arguments : list)
15 - defaults (the values of the default arguments : tuple)
16 - signature (the signature : str)
17 - doc (the docstring : str)
18 - module (the module name : str)
19 - dict (the function __dict__ : str)
20
21 >>> def f(self, x=1, y=2, *args, **kw): pass
22
23 >>> info = getinfo(f)
24
25 >>> info["name"]
26 'f'
27 >>> info["argnames"]
28 ['self', 'x', 'y', 'args', 'kw']
29
30 >>> info["defaults"]
31 (1, 2)
32
33 >>> info["signature"]
34 'self, x, y, *args, **kw'
35 """
36 assert inspect.ismethod(func) or inspect.isfunction(func)
37 regargs, varargs, varkwargs, defaults = inspect.getargspec(func)
38 argnames = list(regargs)
39 if varargs:
40 argnames.append(varargs)
41 if varkwargs:
42 argnames.append(varkwargs)
43 signature = inspect.formatargspec(regargs, varargs, varkwargs, defaults,
44 formatvalue=lambda value: "")[1:-1]
45 return dict(name=func.__name__, argnames=argnames, signature=signature,
46 defaults = func.func_defaults, doc=func.__doc__,
47 module=func.__module__, dict=func.__dict__,
48 globals=func.func_globals, closure=func.func_closure)
49
50 def update_wrapper(wrapper, wrapped, create=False):
51 """
52 An improvement over functools.update_wrapper. By default it works the
53 same, but if the 'create' flag is set, generates a copy of the wrapper
54 with the right signature and update the copy, not the original.
55 Moreovoer, 'wrapped' can be a dictionary with keys 'name', 'doc', 'module',
56 'dict', 'defaults'.
57 """
58 if isinstance(wrapped, dict):
59 infodict = wrapped
60 else: # assume wrapped is a function
61 infodict = getinfo(wrapped)
62 assert not '_wrapper_' in infodict["argnames"], \
63 '"_wrapper_" is a reserved argument name!'
64 if create: # create a brand new wrapper with the right signature
65 src = "lambda %(signature)s: _wrapper_(%(signature)s)" % infodict
66 # import sys; print >> sys.stderr, src # for debugging purposes
67 wrapper = eval(src, dict(_wrapper_=wrapper))
68 try:
69 wrapper.__name__ = infodict['name']
70 except: # Python version < 2.4
71 pass
72 wrapper.__doc__ = infodict['doc']
73 wrapper.__module__ = infodict['module']
74 wrapper.__dict__.update(infodict['dict'])
75 wrapper.func_defaults = infodict['defaults']
76 return wrapper
77
78 # the real meat is here
79 def _decorator(caller, func):
80 infodict = getinfo(func)
81 argnames = infodict['argnames']
82 assert not ('_call_' in argnames or '_func_' in argnames), \
83 'You cannot use _call_ or _func_ as argument names!'
84 src = "lambda %(signature)s: _call_(_func_, %(signature)s)" % infodict
85 dec_func = eval(src, dict(_func_=func, _call_=caller))
86 return update_wrapper(dec_func, func)
87
88 def decorator(caller, func=None):
89 """
90 General purpose decorator factory: takes a caller function as
91 input and returns a decorator with the same attributes.
92 A caller function is any function like this::
93
94 def caller(func, *args, **kw):
95 # do something
96 return func(*args, **kw)
97
98 Here is an example of usage:
99
100 >>> @decorator
101 ... def chatty(f, *args, **kw):
102 ... print "Calling %r" % f.__name__
103 ... return f(*args, **kw)
104
105 >>> chatty.__name__
106 'chatty'
107
108 >>> @chatty
109 ... def f(): pass
110 ...
111 >>> f()
112 Calling 'f'
113
114 For sake of convenience, the decorator factory can also be called with
115 two arguments. In this casem ``decorator(caller, func)`` is just a
116 shortcut for ``decorator(caller)(func)``.
117 """
118 if func is None: # return a decorator function
119 return update_wrapper(lambda f : _decorator(caller, f), caller)
120 else: # return a decorated function
121 return _decorator(caller, func)
122
123 if __name__ == "__main__":
124 import doctest; doctest.testmod()
125
126 ####################### LEGALESE ##################################
127
128 ## Redistributions of source code must retain the above copyright
129 ## notice, this list of conditions and the following disclaimer.
130 ## Redistributions in bytecode form must reproduce the above copyright
131 ## notice, this list of conditions and the following disclaimer in
132 ## the documentation and/or other materials provided with the
133 ## distribution.
134
135 ## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
136 ## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
137 ## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
138 ## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
139 ## HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
140 ## INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
141 ## BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
142 ## OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
143 ## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
144 ## TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
145 ## USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
146 ## DAMAGE.
@@ -0,0 +1,144 b''
1 """Decorators for labeling test objects.
2
3 Decorators that merely return a modified version of the original
4 function object are straightforward. Decorators that return a new
5 function object need to use
6 nose.tools.make_decorator(original_function)(decorator) in returning
7 the decorator, in order to preserve metadata such as function name,
8 setup and teardown functions and so on - see nose.tools for more
9 information.
10
11 NOTE: This file contains IPython-specific decorators and imports the
12 numpy.testing.decorators file, which we've copied verbatim. Any of our own
13 code will be added at the bottom if we end up extending this.
14 """
15
16 # Stdlib imports
17 import inspect
18
19 # Third-party imports
20
21 # This is Michele Simionato's decorator module, also kept verbatim.
22 from decorator_msim import decorator
23
24 # Grab the numpy-specific decorators which we keep in a file that we
25 # occasionally update from upstream: decorators_numpy.py is an IDENTICAL copy
26 # of numpy.testing.decorators.
27 from decorators_numpy import *
28
29 ##############################################################################
30 # Local code begins
31
32 # Utility functions
33
34 def apply_wrapper(wrapper,func):
35 """Apply a wrapper to a function for decoration.
36
37 This mixes Michele Simionato's decorator tool with nose's make_decorator,
38 to apply a wrapper in a decorator so that all nose attributes, as well as
39 function signature and other properties, survive the decoration cleanly.
40 This will ensure that wrapped functions can still be well introspected via
41 IPython, for example.
42 """
43 import nose.tools
44
45 return decorator(wrapper,nose.tools.make_decorator(func)(wrapper))
46
47
48 def make_label_dec(label,ds=None):
49 """Factory function to create a decorator that applies one or more labels.
50
51 :Parameters:
52 label : string or sequence
53 One or more labels that will be applied by the decorator to the functions
54 it decorates. Labels are attributes of the decorated function with their
55 value set to True.
56
57 :Keywords:
58 ds : string
59 An optional docstring for the resulting decorator. If not given, a
60 default docstring is auto-generated.
61
62 :Returns:
63 A decorator.
64
65 :Examples:
66
67 A simple labeling decorator:
68 >>> slow = make_label_dec('slow')
69 >>> print slow.__doc__
70 Labels a test as 'slow'.
71
72 And one that uses multiple labels and a custom docstring:
73 >>> rare = make_label_dec(['slow','hard'],
74 ... "Mix labels 'slow' and 'hard' for rare tests.")
75 >>> print rare.__doc__
76 Mix labels 'slow' and 'hard' for rare tests.
77
78 Now, let's test using this one:
79 >>> @rare
80 ... def f(): pass
81 ...
82 >>>
83 >>> f.slow
84 True
85 >>> f.hard
86 True
87 """
88
89 if isinstance(label,basestring):
90 labels = [label]
91 else:
92 labels = label
93
94 # Validate that the given label(s) are OK for use in setattr() by doing a
95 # dry run on a dummy function.
96 tmp = lambda : None
97 for label in labels:
98 setattr(tmp,label,True)
99
100 # This is the actual decorator we'll return
101 def decor(f):
102 for label in labels:
103 setattr(f,label,True)
104 return f
105
106 # Apply the user's docstring, or autogenerate a basic one
107 if ds is None:
108 ds = "Labels a test as %r." % label
109 decor.__doc__ = ds
110
111 return decor
112
113 #-----------------------------------------------------------------------------
114 # Decorators for public use
115
116 def skip_doctest(func):
117 """Decorator - mark a function for skipping its doctest.
118
119 This decorator allows you to mark a function whose docstring you wish to
120 omit from testing, while preserving the docstring for introspection, help,
121 etc."""
122
123 # We just return the function unmodified, but the wrapping has the effect
124 # of making the doctest plugin skip the doctest.
125 def wrapper(*a,**k):
126 return func(*a,**k)
127
128 # Here we use plain 'decorator' and not apply_wrapper, because we don't
129 # need all the nose-protection machinery (functions containing doctests
130 # can't be full-blown nose tests, so we don't need to prserve
131 # setup/teardown).
132 return decorator(wrapper,func)
133
134
135 def skip(func):
136 """Decorator - mark a test function for skipping from test suite."""
137
138 import nose
139
140 def wrapper(*a,**k):
141 raise nose.SkipTest("Skipping test for function: %s" %
142 func.__name__)
143
144 return apply_wrapper(wrapper,func)
@@ -0,0 +1,94 b''
1 """Decorators for labeling test objects
2
3 Decorators that merely return a modified version of the original
4 function object are straightforward. Decorators that return a new
5 function object need to use
6 nose.tools.make_decorator(original_function)(decorator) in returning
7 the decorator, in order to preserve metadata such as function name,
8 setup and teardown functions and so on - see nose.tools for more
9 information.
10
11 """
12
13 def slow(t):
14 """Labels a test as 'slow'.
15
16 The exact definition of a slow test is obviously both subjective and
17 hardware-dependent, but in general any individual test that requires more
18 than a second or two should be labeled as slow (the whole suite consits of
19 thousands of tests, so even a second is significant)."""
20
21 t.slow = True
22 return t
23
24 def setastest(tf=True):
25 ''' Signals to nose that this function is or is not a test
26
27 Parameters
28 ----------
29 tf : bool
30 If True specifies this is a test, not a test otherwise
31
32 e.g
33 >>> from numpy.testing.decorators import setastest
34 >>> @setastest(False)
35 ... def func_with_test_in_name(arg1, arg2): pass
36 ...
37 >>>
38
39 This decorator cannot use the nose namespace, because it can be
40 called from a non-test module. See also istest and nottest in
41 nose.tools
42
43 '''
44 def set_test(t):
45 t.__test__ = tf
46 return t
47 return set_test
48
49 def skipif(skip_condition, msg=None):
50 ''' Make function raise SkipTest exception if skip_condition is true
51
52 Parameters
53 ---------
54 skip_condition : bool
55 Flag to determine whether to skip test (True) or not (False)
56 msg : string
57 Message to give on raising a SkipTest exception
58
59 Returns
60 -------
61 decorator : function
62 Decorator, which, when applied to a function, causes SkipTest
63 to be raised when the skip_condition was True, and the function
64 to be called normally otherwise.
65
66 Notes
67 -----
68 You will see from the code that we had to further decorate the
69 decorator with the nose.tools.make_decorator function in order to
70 transmit function name, and various other metadata.
71 '''
72 if msg is None:
73 msg = 'Test skipped due to test condition'
74 def skip_decorator(f):
75 # Local import to avoid a hard nose dependency and only incur the
76 # import time overhead at actual test-time.
77 import nose
78 def skipper(*args, **kwargs):
79 if skip_condition:
80 raise nose.SkipTest, msg
81 else:
82 return f(*args, **kwargs)
83 return nose.tools.make_decorator(f)(skipper)
84 return skip_decorator
85
86 def skipknownfailure(f):
87 ''' Decorator to raise SkipTest for test known to fail
88 '''
89 # Local import to avoid a hard nose dependency and only incur the
90 # import time overhead at actual test-time.
91 import nose
92 def skipper(*args, **kwargs):
93 raise nose.SkipTest, 'This test is known to fail'
94 return nose.tools.make_decorator(f)(skipper)
@@ -0,0 +1,2 b''
1 x = 1
2 print 'x is:',x
@@ -1,32 +1,48 b''
1 # Set this prefix to where you want to install the plugin
1 # Set this prefix to where you want to install the plugin
2 PREFIX=~/usr/local
2 PREFIX=~/usr/local
3 PREFIX=~/tmp/local
3 PREFIX=~/tmp/local
4
4
5 NOSE0=nosetests -vs --with-doctest --doctest-tests
6 NOSE=nosetests -vvs --with-ipdoctest --doctest-tests --doctest-extension=txt
7
8 #--with-color
9
10 SRC=ipdoctest.py setup.py decorators.py
11
5 plugin: IPython_doctest_plugin.egg-info
12 plugin: IPython_doctest_plugin.egg-info
6
13
7 dtest: plugin dtexample.py
14 dtest: plugin dtexample.py
8 nosetests -vs --with-ipdoctest --doctest-tests --doctest-extension=txt \
15 $(NOSE) dtexample.py
9 dtexample.py
10
16
11 # Note: this test is double counting!!!
17 # Note: this test is double counting!!!
12 rtest: plugin dtexample.py
18 rtest: plugin dtexample.py
13 nosetests -vs --with-ipdoctest --doctest-tests test_refs.py
19 $(NOSE) test_refs.py
20
21 std: plugin
22 nosetests -vs --with-doctest --doctest-tests IPython.strdispatch
23 $(NOSE) IPython.strdispatch
14
24
15 test: plugin dtexample.py
25 test: plugin dtexample.py
16 nosetests -vs --with-ipdoctest --doctest-tests --doctest-extension=txt \
26 $(NOSE) dtexample.py test*.py test*.txt
17 dtexample.py test*.py test*.txt
18
27
19 deb: plugin dtexample.py
28 deb: plugin dtexample.py
20 nosetests -vs --with-ipdoctest --doctest-tests --doctest-extension=txt \
29 $(NOSE) test_combo.txt
21 test_combo.txt
22
30
23 iptest: plugin
31 iptest: plugin
24 nosetests -vs --with-ipdoctest --doctest-tests --doctest-extension=txt \
32 $(NOSE) IPython
25 IPython
33
34 deco:
35 $(NOSE0) decorators.py
36
37 sr: rtest std
38
39 base: dtest rtest test std deco
40
41 all: base iptest
26
42
27 IPython_doctest_plugin.egg-info: ipdoctest.py setup.py
43 IPython_doctest_plugin.egg-info: $(SRC)
28 python setup.py install --prefix=$(PREFIX)
44 python setup.py install --prefix=$(PREFIX)
29 touch $@
45 touch $@
30
46
31 clean:
47 clean:
32 rm -rf IPython_doctest_plugin.egg-info *~ *pyc build/ dist/
48 rm -rf IPython_doctest_plugin.egg-info *~ *pyc build/ dist/
@@ -1,628 +1,867 b''
1 """Nose Plugin that supports IPython doctests.
1 """Nose Plugin that supports IPython doctests.
2
2
3 Limitations:
3 Limitations:
4
4
5 - When generating examples for use as doctests, make sure that you have
5 - When generating examples for use as doctests, make sure that you have
6 pretty-printing OFF. This can be done either by starting ipython with the
6 pretty-printing OFF. This can be done either by starting ipython with the
7 flag '--nopprint', by setting pprint to 0 in your ipythonrc file, or by
7 flag '--nopprint', by setting pprint to 0 in your ipythonrc file, or by
8 interactively disabling it with %Pprint. This is required so that IPython
8 interactively disabling it with %Pprint. This is required so that IPython
9 output matches that of normal Python, which is used by doctest for internal
9 output matches that of normal Python, which is used by doctest for internal
10 execution.
10 execution.
11
11
12 - Do not rely on specific prompt numbers for results (such as using
12 - Do not rely on specific prompt numbers for results (such as using
13 '_34==True', for example). For IPython tests run via an external process the
13 '_34==True', for example). For IPython tests run via an external process the
14 prompt numbers may be different, and IPython tests run as normal python code
14 prompt numbers may be different, and IPython tests run as normal python code
15 won't even have these special _NN variables set at all.
15 won't even have these special _NN variables set at all.
16
16
17 - IPython functions that produce output as a side-effect of calling a system
17 - IPython functions that produce output as a side-effect of calling a system
18 process (e.g. 'ls') can be doc-tested, but they must be handled in an
18 process (e.g. 'ls') can be doc-tested, but they must be handled in an
19 external IPython process. Such doctests must be tagged with:
19 external IPython process. Such doctests must be tagged with:
20
20
21 # ipdoctest: EXTERNAL
21 # ipdoctest: EXTERNAL
22
22
23 so that the testing machinery handles them differently. Since these are run
23 so that the testing machinery handles them differently. Since these are run
24 via pexpect in an external process, they can't deal with exceptions or other
24 via pexpect in an external process, they can't deal with exceptions or other
25 fancy featurs of regular doctests. You must limit such tests to simple
25 fancy featurs of regular doctests. You must limit such tests to simple
26 matching of the output. For this reason, I recommend you limit these kinds
26 matching of the output. For this reason, I recommend you limit these kinds
27 of doctests to features that truly require a separate process, and use the
27 of doctests to features that truly require a separate process, and use the
28 normal IPython ones (which have all the features of normal doctests) for
28 normal IPython ones (which have all the features of normal doctests) for
29 everything else. See the examples at the bottom of this file for a
29 everything else. See the examples at the bottom of this file for a
30 comparison of what can be done with both types.
30 comparison of what can be done with both types.
31 """
31 """
32
32
33
33
34 #-----------------------------------------------------------------------------
34 #-----------------------------------------------------------------------------
35 # Module imports
35 # Module imports
36
36
37 # From the standard library
37 # From the standard library
38 import __builtin__
38 import __builtin__
39 import commands
39 import commands
40 import doctest
40 import doctest
41 import inspect
41 import inspect
42 import logging
42 import logging
43 import os
43 import os
44 import re
44 import re
45 import sys
45 import sys
46 import unittest
46 import unittest
47
47
48 from inspect import getmodule
48 from inspect import getmodule
49
49
50 # Third-party modules
50 # Third-party modules
51 import nose.core
51 import nose.core
52
52
53 from nose.plugins import doctests, Plugin
53 from nose.plugins import doctests, Plugin
54 from nose.util import anyp, getpackage, test_address, resolve_name, tolist
54 from nose.util import anyp, getpackage, test_address, resolve_name, tolist
55
55
56 # Our own imports
56 # Our own imports
57 #from extdoctest import ExtensionDoctest, DocTestFinder
57 #from extdoctest import ExtensionDoctest, DocTestFinder
58 #from dttools import DocTestFinder, DocTestCase
58 #from dttools import DocTestFinder, DocTestCase
59 #-----------------------------------------------------------------------------
59 #-----------------------------------------------------------------------------
60 # Module globals and other constants
60 # Module globals and other constants
61
61
62 log = logging.getLogger(__name__)
62 log = logging.getLogger(__name__)
63
63
64 ###########################################################################
64 ###########################################################################
65 # *** HACK ***
65 # *** HACK ***
66 # We must start our own ipython object and heavily muck with it so that all the
66 # We must start our own ipython object and heavily muck with it so that all the
67 # modifications IPython makes to system behavior don't send the doctest
67 # modifications IPython makes to system behavior don't send the doctest
68 # machinery into a fit. This code should be considered a gross hack, but it
68 # machinery into a fit. This code should be considered a gross hack, but it
69 # gets the job done.
69 # gets the job done.
70
70
71 class ncdict(dict):
72 """Non-copying dict class.
73
74 This is a special-purpose dict subclass that overrides the .copy() method
75 to return the original object itself. We need it to ensure that doctests
76 happen in the IPython namespace, but doctest always makes a shallow copy of
77 the given globals for execution. Since we actually *want* this namespace
78 to be persistent (this is how the user's session maintains state), we
79 simply fool doctest by returning the original object upoon copy.
80 """
81
82 def copy(self):
83 return self
84
85
86 def _my_run(self,arg_s,runner=None):
87 """
88 """
89 #print 'HA!' # dbg
90
91 return _ip.IP.magic_run_ori(arg_s,runner)
92
93
71 def start_ipython():
94 def start_ipython():
72 """Start a global IPython shell, which we need for IPython-specific syntax.
95 """Start a global IPython shell, which we need for IPython-specific syntax.
73 """
96 """
74 import IPython
97 import IPython
75
98
76 def xsys(cmd):
99 def xsys(cmd):
77 """Execute a command and print its output.
100 """Execute a command and print its output.
78
101
79 This is just a convenience function to replace the IPython system call
102 This is just a convenience function to replace the IPython system call
80 with one that is more doctest-friendly.
103 with one that is more doctest-friendly.
81 """
104 """
82 cmd = _ip.IP.var_expand(cmd,depth=1)
105 cmd = _ip.IP.var_expand(cmd,depth=1)
83 sys.stdout.write(commands.getoutput(cmd))
106 sys.stdout.write(commands.getoutput(cmd))
84 sys.stdout.flush()
107 sys.stdout.flush()
85
108
86 # Store certain global objects that IPython modifies
109 # Store certain global objects that IPython modifies
87 _displayhook = sys.displayhook
110 _displayhook = sys.displayhook
88 _excepthook = sys.excepthook
111 _excepthook = sys.excepthook
89 _main = sys.modules.get('__main__')
112 _main = sys.modules.get('__main__')
90
113
91 # Start IPython instance
114 # Start IPython instance. We customize it to start with minimal frills and
92 IPython.Shell.IPShell(['--classic','--noterm_title'])
115 # with our own namespace.
116 argv = ['--classic','--noterm_title']
117 user_ns = ncdict()
118 IPython.Shell.IPShell(argv,user_ns)
93
119
94 # Deactivate the various python system hooks added by ipython for
120 # Deactivate the various python system hooks added by ipython for
95 # interactive convenience so we don't confuse the doctest system
121 # interactive convenience so we don't confuse the doctest system
96 sys.modules['__main__'] = _main
122 sys.modules['__main__'] = _main
97 sys.displayhook = _displayhook
123 sys.displayhook = _displayhook
98 sys.excepthook = _excepthook
124 sys.excepthook = _excepthook
99
125
100 # So that ipython magics and aliases can be doctested (they work by making
126 # So that ipython magics and aliases can be doctested (they work by making
101 # a call into a global _ip object)
127 # a call into a global _ip object)
102 _ip = IPython.ipapi.get()
128 _ip = IPython.ipapi.get()
103 __builtin__._ip = _ip
129 __builtin__._ip = _ip
104
130
105 # Modify the IPython system call with one that uses getoutput, so that we
131 # Modify the IPython system call with one that uses getoutput, so that we
106 # can capture subcommands and print them to Python's stdout, otherwise the
132 # can capture subcommands and print them to Python's stdout, otherwise the
107 # doctest machinery would miss them.
133 # doctest machinery would miss them.
108 _ip.system = xsys
134 _ip.system = xsys
109
135
136 import new
137 im = new.instancemethod(_my_run,_ip.IP, _ip.IP.__class__)
138 _ip.IP.magic_run_ori = _ip.IP.magic_run
139 _ip.IP.magic_run = im
140
110 # The start call MUST be made here. I'm not sure yet why it doesn't work if
141 # The start call MUST be made here. I'm not sure yet why it doesn't work if
111 # it is made later, at plugin initialization time, but in all my tests, that's
142 # it is made later, at plugin initialization time, but in all my tests, that's
112 # the case.
143 # the case.
113 start_ipython()
144 start_ipython()
114
145
115 # *** END HACK ***
146 # *** END HACK ***
116 ###########################################################################
147 ###########################################################################
117
148
118 # Classes and functions
149 # Classes and functions
119
150
120 def is_extension_module(filename):
151 def is_extension_module(filename):
121 """Return whether the given filename is an extension module.
152 """Return whether the given filename is an extension module.
122
153
123 This simply checks that the extension is either .so or .pyd.
154 This simply checks that the extension is either .so or .pyd.
124 """
155 """
125 return os.path.splitext(filename)[1].lower() in ('.so','.pyd')
156 return os.path.splitext(filename)[1].lower() in ('.so','.pyd')
126
157
127
158
128 # Modified version of the one in the stdlib, that fixes a python bug (doctests
159 # Modified version of the one in the stdlib, that fixes a python bug (doctests
129 # not found in extension modules, http://bugs.python.org/issue3158)
160 # not found in extension modules, http://bugs.python.org/issue3158)
130 class DocTestFinder(doctest.DocTestFinder):
161 class DocTestFinder(doctest.DocTestFinder):
131
162
132 def _from_module(self, module, object):
163 def _from_module(self, module, object):
133 """
164 """
134 Return true if the given object is defined in the given
165 Return true if the given object is defined in the given
135 module.
166 module.
136 """
167 """
137 if module is None:
168 if module is None:
138 #print '_fm C1' # dbg
169 #print '_fm C1' # dbg
139 return True
170 return True
140 elif inspect.isfunction(object):
171 elif inspect.isfunction(object):
141 #print '_fm C2' # dbg
172 #print '_fm C2' # dbg
142 return module.__dict__ is object.func_globals
173 return module.__dict__ is object.func_globals
143 elif inspect.isbuiltin(object):
174 elif inspect.isbuiltin(object):
144 #print '_fm C2-1' # dbg
175 #print '_fm C2-1' # dbg
145 return module.__name__ == object.__module__
176 return module.__name__ == object.__module__
146 elif inspect.isclass(object):
177 elif inspect.isclass(object):
147 #print '_fm C3' # dbg
178 #print '_fm C3' # dbg
148 return module.__name__ == object.__module__
179 return module.__name__ == object.__module__
149 elif inspect.ismethod(object):
180 elif inspect.ismethod(object):
150 # This one may be a bug in cython that fails to correctly set the
181 # This one may be a bug in cython that fails to correctly set the
151 # __module__ attribute of methods, but since the same error is easy
182 # __module__ attribute of methods, but since the same error is easy
152 # to make by extension code writers, having this safety in place
183 # to make by extension code writers, having this safety in place
153 # isn't such a bad idea
184 # isn't such a bad idea
154 #print '_fm C3-1' # dbg
185 #print '_fm C3-1' # dbg
155 return module.__name__ == object.im_class.__module__
186 return module.__name__ == object.im_class.__module__
156 elif inspect.getmodule(object) is not None:
187 elif inspect.getmodule(object) is not None:
157 #print '_fm C4' # dbg
188 #print '_fm C4' # dbg
158 #print 'C4 mod',module,'obj',object # dbg
189 #print 'C4 mod',module,'obj',object # dbg
159 return module is inspect.getmodule(object)
190 return module is inspect.getmodule(object)
160 elif hasattr(object, '__module__'):
191 elif hasattr(object, '__module__'):
161 #print '_fm C5' # dbg
192 #print '_fm C5' # dbg
162 return module.__name__ == object.__module__
193 return module.__name__ == object.__module__
163 elif isinstance(object, property):
194 elif isinstance(object, property):
164 #print '_fm C6' # dbg
195 #print '_fm C6' # dbg
165 return True # [XX] no way not be sure.
196 return True # [XX] no way not be sure.
166 else:
197 else:
167 raise ValueError("object must be a class or function")
198 raise ValueError("object must be a class or function")
168
199
169 def _find(self, tests, obj, name, module, source_lines, globs, seen):
200 def _find(self, tests, obj, name, module, source_lines, globs, seen):
170 """
201 """
171 Find tests for the given object and any contained objects, and
202 Find tests for the given object and any contained objects, and
172 add them to `tests`.
203 add them to `tests`.
173 """
204 """
174
205
175 doctest.DocTestFinder._find(self,tests, obj, name, module,
206 doctest.DocTestFinder._find(self,tests, obj, name, module,
176 source_lines, globs, seen)
207 source_lines, globs, seen)
177
208
178 # Below we re-run pieces of the above method with manual modifications,
209 # Below we re-run pieces of the above method with manual modifications,
179 # because the original code is buggy and fails to correctly identify
210 # because the original code is buggy and fails to correctly identify
180 # doctests in extension modules.
211 # doctests in extension modules.
181
212
182 # Local shorthands
213 # Local shorthands
183 from inspect import isroutine, isclass, ismodule
214 from inspect import isroutine, isclass, ismodule
184
215
185 # Look for tests in a module's contained objects.
216 # Look for tests in a module's contained objects.
186 if inspect.ismodule(obj) and self._recurse:
217 if inspect.ismodule(obj) and self._recurse:
187 for valname, val in obj.__dict__.items():
218 for valname, val in obj.__dict__.items():
188 valname1 = '%s.%s' % (name, valname)
219 valname1 = '%s.%s' % (name, valname)
189 if ( (isroutine(val) or isclass(val))
220 if ( (isroutine(val) or isclass(val))
190 and self._from_module(module, val) ):
221 and self._from_module(module, val) ):
191
222
192 self._find(tests, val, valname1, module, source_lines,
223 self._find(tests, val, valname1, module, source_lines,
193 globs, seen)
224 globs, seen)
194
225
195 # Look for tests in a class's contained objects.
226 # Look for tests in a class's contained objects.
196 if inspect.isclass(obj) and self._recurse:
227 if inspect.isclass(obj) and self._recurse:
197 #print 'RECURSE into class:',obj # dbg
228 #print 'RECURSE into class:',obj # dbg
198 for valname, val in obj.__dict__.items():
229 for valname, val in obj.__dict__.items():
199 #valname1 = '%s.%s' % (name, valname) # dbg
230 #valname1 = '%s.%s' % (name, valname) # dbg
200 #print 'N',name,'VN:',valname,'val:',str(val)[:77] # dbg
231 #print 'N',name,'VN:',valname,'val:',str(val)[:77] # dbg
201 # Special handling for staticmethod/classmethod.
232 # Special handling for staticmethod/classmethod.
202 if isinstance(val, staticmethod):
233 if isinstance(val, staticmethod):
203 val = getattr(obj, valname)
234 val = getattr(obj, valname)
204 if isinstance(val, classmethod):
235 if isinstance(val, classmethod):
205 val = getattr(obj, valname).im_func
236 val = getattr(obj, valname).im_func
206
237
207 # Recurse to methods, properties, and nested classes.
238 # Recurse to methods, properties, and nested classes.
208 if ((inspect.isfunction(val) or inspect.isclass(val) or
239 if ((inspect.isfunction(val) or inspect.isclass(val) or
209 inspect.ismethod(val) or
240 inspect.ismethod(val) or
210 isinstance(val, property)) and
241 isinstance(val, property)) and
211 self._from_module(module, val)):
242 self._from_module(module, val)):
212 valname = '%s.%s' % (name, valname)
243 valname = '%s.%s' % (name, valname)
213 self._find(tests, val, valname, module, source_lines,
244 self._find(tests, val, valname, module, source_lines,
214 globs, seen)
245 globs, seen)
215
246
216
247
217 # second-chance checker; if the default comparison doesn't
248 # second-chance checker; if the default comparison doesn't
218 # pass, then see if the expected output string contains flags that
249 # pass, then see if the expected output string contains flags that
219 # tell us to ignore the output
250 # tell us to ignore the output
220 class IPDoctestOutputChecker(doctest.OutputChecker):
251 class IPDoctestOutputChecker(doctest.OutputChecker):
221 def check_output(self, want, got, optionflags):
252 def check_output(self, want, got, optionflags):
222 #print '*** My Checker!' # dbg
253 #print '*** My Checker!' # dbg
223
254
224 ret = doctest.OutputChecker.check_output(self, want, got,
255 ret = doctest.OutputChecker.check_output(self, want, got,
225 optionflags)
256 optionflags)
226 if not ret:
257 if not ret:
227 if "#random" in want:
258 if "#random" in want:
228 return True
259 return True
229
260
230 return ret
261 return ret
231
262
232
263
233 class DocTestCase(doctests.DocTestCase):
264 class DocTestCase(doctests.DocTestCase):
234 """Proxy for DocTestCase: provides an address() method that
265 """Proxy for DocTestCase: provides an address() method that
235 returns the correct address for the doctest case. Otherwise
266 returns the correct address for the doctest case. Otherwise
236 acts as a proxy to the test case. To provide hints for address(),
267 acts as a proxy to the test case. To provide hints for address(),
237 an obj may also be passed -- this will be used as the test object
268 an obj may also be passed -- this will be used as the test object
238 for purposes of determining the test address, if it is provided.
269 for purposes of determining the test address, if it is provided.
239 """
270 """
240
271
241 # Note: this method was taken from numpy's nosetester module.
272 # Note: this method was taken from numpy's nosetester module.
242
273
243 # Subclass nose.plugins.doctests.DocTestCase to work around a bug in
274 # Subclass nose.plugins.doctests.DocTestCase to work around a bug in
244 # its constructor that blocks non-default arguments from being passed
275 # its constructor that blocks non-default arguments from being passed
245 # down into doctest.DocTestCase
276 # down into doctest.DocTestCase
246
277
247 def __init__(self, test, optionflags=0, setUp=None, tearDown=None,
278 def __init__(self, test, optionflags=0, setUp=None, tearDown=None,
248 checker=None, obj=None, result_var='_'):
279 checker=None, obj=None, result_var='_'):
249 self._result_var = result_var
280 self._result_var = result_var
250 doctests.DocTestCase.__init__(self, test,
281 doctests.DocTestCase.__init__(self, test,
251 optionflags=optionflags,
282 optionflags=optionflags,
252 setUp=setUp, tearDown=tearDown,
283 setUp=setUp, tearDown=tearDown,
253 checker=checker)
284 checker=checker)
254 # Now we must actually copy the original constructor from the stdlib
285 # Now we must actually copy the original constructor from the stdlib
255 # doctest class, because we can't call it directly and a bug in nose
286 # doctest class, because we can't call it directly and a bug in nose
256 # means it never gets passed the right arguments.
287 # means it never gets passed the right arguments.
257
288
258 self._dt_optionflags = optionflags
289 self._dt_optionflags = optionflags
259 self._dt_checker = checker
290 self._dt_checker = checker
260 self._dt_test = test
291 self._dt_test = test
261 self._dt_setUp = setUp
292 self._dt_setUp = setUp
262 self._dt_tearDown = tearDown
293 self._dt_tearDown = tearDown
263
294
264
295
265
296
266 # A simple subclassing of the original with a different class name, so we can
297 # A simple subclassing of the original with a different class name, so we can
267 # distinguish and treat differently IPython examples from pure python ones.
298 # distinguish and treat differently IPython examples from pure python ones.
268 class IPExample(doctest.Example): pass
299 class IPExample(doctest.Example): pass
269
300
270
301
271 class IPExternalExample(doctest.Example):
302 class IPExternalExample(doctest.Example):
272 """Doctest examples to be run in an external process."""
303 """Doctest examples to be run in an external process."""
273
304
274 def __init__(self, source, want, exc_msg=None, lineno=0, indent=0,
305 def __init__(self, source, want, exc_msg=None, lineno=0, indent=0,
275 options=None):
306 options=None):
276 # Parent constructor
307 # Parent constructor
277 doctest.Example.__init__(self,source,want,exc_msg,lineno,indent,options)
308 doctest.Example.__init__(self,source,want,exc_msg,lineno,indent,options)
278
309
279 # An EXTRA newline is needed to prevent pexpect hangs
310 # An EXTRA newline is needed to prevent pexpect hangs
280 self.source += '\n'
311 self.source += '\n'
281
312
282
313
283 class IPDocTestParser(doctest.DocTestParser):
314 class IPDocTestParser(doctest.DocTestParser):
284 """
315 """
285 A class used to parse strings containing doctest examples.
316 A class used to parse strings containing doctest examples.
286
317
287 Note: This is a version modified to properly recognize IPython input and
318 Note: This is a version modified to properly recognize IPython input and
288 convert any IPython examples into valid Python ones.
319 convert any IPython examples into valid Python ones.
289 """
320 """
290 # This regular expression is used to find doctest examples in a
321 # This regular expression is used to find doctest examples in a
291 # string. It defines three groups: `source` is the source code
322 # string. It defines three groups: `source` is the source code
292 # (including leading indentation and prompts); `indent` is the
323 # (including leading indentation and prompts); `indent` is the
293 # indentation of the first (PS1) line of the source code; and
324 # indentation of the first (PS1) line of the source code; and
294 # `want` is the expected output (including leading indentation).
325 # `want` is the expected output (including leading indentation).
295
326
296 # Classic Python prompts or default IPython ones
327 # Classic Python prompts or default IPython ones
297 _PS1_PY = r'>>>'
328 _PS1_PY = r'>>>'
298 _PS2_PY = r'\.\.\.'
329 _PS2_PY = r'\.\.\.'
299
330
300 _PS1_IP = r'In\ \[\d+\]:'
331 _PS1_IP = r'In\ \[\d+\]:'
301 _PS2_IP = r'\ \ \ \.\.\.+:'
332 _PS2_IP = r'\ \ \ \.\.\.+:'
302
333
303 _RE_TPL = r'''
334 _RE_TPL = r'''
304 # Source consists of a PS1 line followed by zero or more PS2 lines.
335 # Source consists of a PS1 line followed by zero or more PS2 lines.
305 (?P<source>
336 (?P<source>
306 (?:^(?P<indent> [ ]*) (?P<ps1> %s) .*) # PS1 line
337 (?:^(?P<indent> [ ]*) (?P<ps1> %s) .*) # PS1 line
307 (?:\n [ ]* (?P<ps2> %s) .*)*) # PS2 lines
338 (?:\n [ ]* (?P<ps2> %s) .*)*) # PS2 lines
308 \n? # a newline
339 \n? # a newline
309 # Want consists of any non-blank lines that do not start with PS1.
340 # Want consists of any non-blank lines that do not start with PS1.
310 (?P<want> (?:(?![ ]*$) # Not a blank line
341 (?P<want> (?:(?![ ]*$) # Not a blank line
311 (?![ ]*%s) # Not a line starting with PS1
342 (?![ ]*%s) # Not a line starting with PS1
312 (?![ ]*%s) # Not a line starting with PS2
343 (?![ ]*%s) # Not a line starting with PS2
313 .*$\n? # But any other line
344 .*$\n? # But any other line
314 )*)
345 )*)
315 '''
346 '''
316
347
317 _EXAMPLE_RE_PY = re.compile( _RE_TPL % (_PS1_PY,_PS2_PY,_PS1_PY,_PS2_PY),
348 _EXAMPLE_RE_PY = re.compile( _RE_TPL % (_PS1_PY,_PS2_PY,_PS1_PY,_PS2_PY),
318 re.MULTILINE | re.VERBOSE)
349 re.MULTILINE | re.VERBOSE)
319
350
320 _EXAMPLE_RE_IP = re.compile( _RE_TPL % (_PS1_IP,_PS2_IP,_PS1_IP,_PS2_IP),
351 _EXAMPLE_RE_IP = re.compile( _RE_TPL % (_PS1_IP,_PS2_IP,_PS1_IP,_PS2_IP),
321 re.MULTILINE | re.VERBOSE)
352 re.MULTILINE | re.VERBOSE)
322
353
323 def ip2py(self,source):
354 def ip2py(self,source):
324 """Convert input IPython source into valid Python."""
355 """Convert input IPython source into valid Python."""
325 out = []
356 out = []
326 newline = out.append
357 newline = out.append
327 for lnum,line in enumerate(source.splitlines()):
358 for lnum,line in enumerate(source.splitlines()):
328 #newline(_ip.IPipython.prefilter(line,True))
329 newline(_ip.IP.prefilter(line,lnum>0))
359 newline(_ip.IP.prefilter(line,lnum>0))
330 newline('') # ensure a closing newline, needed by doctest
360 newline('') # ensure a closing newline, needed by doctest
361 #print "PYSRC:", '\n'.join(out) # dbg
331 return '\n'.join(out)
362 return '\n'.join(out)
332
363
333 def parse(self, string, name='<string>'):
364 def parse(self, string, name='<string>'):
334 """
365 """
335 Divide the given string into examples and intervening text,
366 Divide the given string into examples and intervening text,
336 and return them as a list of alternating Examples and strings.
367 and return them as a list of alternating Examples and strings.
337 Line numbers for the Examples are 0-based. The optional
368 Line numbers for the Examples are 0-based. The optional
338 argument `name` is a name identifying this string, and is only
369 argument `name` is a name identifying this string, and is only
339 used for error messages.
370 used for error messages.
340 """
371 """
341
372
342 #print 'Parse string:\n',string # dbg
373 #print 'Parse string:\n',string # dbg
343
374
344 string = string.expandtabs()
375 string = string.expandtabs()
345 # If all lines begin with the same indentation, then strip it.
376 # If all lines begin with the same indentation, then strip it.
346 min_indent = self._min_indent(string)
377 min_indent = self._min_indent(string)
347 if min_indent > 0:
378 if min_indent > 0:
348 string = '\n'.join([l[min_indent:] for l in string.split('\n')])
379 string = '\n'.join([l[min_indent:] for l in string.split('\n')])
349
380
350 output = []
381 output = []
351 charno, lineno = 0, 0
382 charno, lineno = 0, 0
352
383
353 # Whether to convert the input from ipython to python syntax
384 # Whether to convert the input from ipython to python syntax
354 ip2py = False
385 ip2py = False
355 # Find all doctest examples in the string. First, try them as Python
386 # Find all doctest examples in the string. First, try them as Python
356 # examples, then as IPython ones
387 # examples, then as IPython ones
357 terms = list(self._EXAMPLE_RE_PY.finditer(string))
388 terms = list(self._EXAMPLE_RE_PY.finditer(string))
358 if terms:
389 if terms:
359 # Normal Python example
390 # Normal Python example
360 #print '-'*70 # dbg
391 #print '-'*70 # dbg
361 #print 'PyExample, Source:\n',string # dbg
392 #print 'PyExample, Source:\n',string # dbg
362 #print '-'*70 # dbg
393 #print '-'*70 # dbg
363 Example = doctest.Example
394 Example = doctest.Example
364 else:
395 else:
365 # It's an ipython example. Note that IPExamples are run
396 # It's an ipython example. Note that IPExamples are run
366 # in-process, so their syntax must be turned into valid python.
397 # in-process, so their syntax must be turned into valid python.
367 # IPExternalExamples are run out-of-process (via pexpect) so they
398 # IPExternalExamples are run out-of-process (via pexpect) so they
368 # don't need any filtering (a real ipython will be executing them).
399 # don't need any filtering (a real ipython will be executing them).
369 terms = list(self._EXAMPLE_RE_IP.finditer(string))
400 terms = list(self._EXAMPLE_RE_IP.finditer(string))
370 if re.search(r'#\s*ipdoctest:\s*EXTERNAL',string):
401 if re.search(r'#\s*ipdoctest:\s*EXTERNAL',string):
371 #print '-'*70 # dbg
402 #print '-'*70 # dbg
372 #print 'IPExternalExample, Source:\n',string # dbg
403 #print 'IPExternalExample, Source:\n',string # dbg
373 #print '-'*70 # dbg
404 #print '-'*70 # dbg
374 Example = IPExternalExample
405 Example = IPExternalExample
375 else:
406 else:
376 #print '-'*70 # dbg
407 #print '-'*70 # dbg
377 #print 'IPExample, Source:\n',string # dbg
408 #print 'IPExample, Source:\n',string # dbg
378 #print '-'*70 # dbg
409 #print '-'*70 # dbg
379 Example = IPExample
410 Example = IPExample
380 ip2py = True
411 ip2py = True
381
412
382 for m in terms:
413 for m in terms:
383 # Add the pre-example text to `output`.
414 # Add the pre-example text to `output`.
384 output.append(string[charno:m.start()])
415 output.append(string[charno:m.start()])
385 # Update lineno (lines before this example)
416 # Update lineno (lines before this example)
386 lineno += string.count('\n', charno, m.start())
417 lineno += string.count('\n', charno, m.start())
387 # Extract info from the regexp match.
418 # Extract info from the regexp match.
388 (source, options, want, exc_msg) = \
419 (source, options, want, exc_msg) = \
389 self._parse_example(m, name, lineno,ip2py)
420 self._parse_example(m, name, lineno,ip2py)
390 if Example is IPExternalExample:
421 if Example is IPExternalExample:
391 options[doctest.NORMALIZE_WHITESPACE] = True
422 options[doctest.NORMALIZE_WHITESPACE] = True
392 want += '\n'
423 want += '\n'
393 # Create an Example, and add it to the list.
424 # Create an Example, and add it to the list.
394 if not self._IS_BLANK_OR_COMMENT(source):
425 if not self._IS_BLANK_OR_COMMENT(source):
395 #print 'Example source:', source # dbg
426 #print 'Example source:', source # dbg
396 output.append(Example(source, want, exc_msg,
427 output.append(Example(source, want, exc_msg,
397 lineno=lineno,
428 lineno=lineno,
398 indent=min_indent+len(m.group('indent')),
429 indent=min_indent+len(m.group('indent')),
399 options=options))
430 options=options))
400 # Update lineno (lines inside this example)
431 # Update lineno (lines inside this example)
401 lineno += string.count('\n', m.start(), m.end())
432 lineno += string.count('\n', m.start(), m.end())
402 # Update charno.
433 # Update charno.
403 charno = m.end()
434 charno = m.end()
404 # Add any remaining post-example text to `output`.
435 # Add any remaining post-example text to `output`.
405 output.append(string[charno:])
436 output.append(string[charno:])
406 return output
437 return output
407
438
408 def _parse_example(self, m, name, lineno,ip2py=False):
439 def _parse_example(self, m, name, lineno,ip2py=False):
409 """
440 """
410 Given a regular expression match from `_EXAMPLE_RE` (`m`),
441 Given a regular expression match from `_EXAMPLE_RE` (`m`),
411 return a pair `(source, want)`, where `source` is the matched
442 return a pair `(source, want)`, where `source` is the matched
412 example's source code (with prompts and indentation stripped);
443 example's source code (with prompts and indentation stripped);
413 and `want` is the example's expected output (with indentation
444 and `want` is the example's expected output (with indentation
414 stripped).
445 stripped).
415
446
416 `name` is the string's name, and `lineno` is the line number
447 `name` is the string's name, and `lineno` is the line number
417 where the example starts; both are used for error messages.
448 where the example starts; both are used for error messages.
418
449
419 Optional:
450 Optional:
420 `ip2py`: if true, filter the input via IPython to convert the syntax
451 `ip2py`: if true, filter the input via IPython to convert the syntax
421 into valid python.
452 into valid python.
422 """
453 """
423
454
424 # Get the example's indentation level.
455 # Get the example's indentation level.
425 indent = len(m.group('indent'))
456 indent = len(m.group('indent'))
426
457
427 # Divide source into lines; check that they're properly
458 # Divide source into lines; check that they're properly
428 # indented; and then strip their indentation & prompts.
459 # indented; and then strip their indentation & prompts.
429 source_lines = m.group('source').split('\n')
460 source_lines = m.group('source').split('\n')
430
461
431 # We're using variable-length input prompts
462 # We're using variable-length input prompts
432 ps1 = m.group('ps1')
463 ps1 = m.group('ps1')
433 ps2 = m.group('ps2')
464 ps2 = m.group('ps2')
434 ps1_len = len(ps1)
465 ps1_len = len(ps1)
435
466
436 self._check_prompt_blank(source_lines, indent, name, lineno,ps1_len)
467 self._check_prompt_blank(source_lines, indent, name, lineno,ps1_len)
437 if ps2:
468 if ps2:
438 self._check_prefix(source_lines[1:], ' '*indent + ps2, name, lineno)
469 self._check_prefix(source_lines[1:], ' '*indent + ps2, name, lineno)
439
470
440 source = '\n'.join([sl[indent+ps1_len+1:] for sl in source_lines])
471 source = '\n'.join([sl[indent+ps1_len+1:] for sl in source_lines])
441
472
442 if ip2py:
473 if ip2py:
443 # Convert source input from IPython into valid Python syntax
474 # Convert source input from IPython into valid Python syntax
444 source = self.ip2py(source)
475 source = self.ip2py(source)
445
476
446 # Divide want into lines; check that it's properly indented; and
477 # Divide want into lines; check that it's properly indented; and
447 # then strip the indentation. Spaces before the last newline should
478 # then strip the indentation. Spaces before the last newline should
448 # be preserved, so plain rstrip() isn't good enough.
479 # be preserved, so plain rstrip() isn't good enough.
449 want = m.group('want')
480 want = m.group('want')
450 want_lines = want.split('\n')
481 want_lines = want.split('\n')
451 if len(want_lines) > 1 and re.match(r' *$', want_lines[-1]):
482 if len(want_lines) > 1 and re.match(r' *$', want_lines[-1]):
452 del want_lines[-1] # forget final newline & spaces after it
483 del want_lines[-1] # forget final newline & spaces after it
453 self._check_prefix(want_lines, ' '*indent, name,
484 self._check_prefix(want_lines, ' '*indent, name,
454 lineno + len(source_lines))
485 lineno + len(source_lines))
455
486
456 # Remove ipython output prompt that might be present in the first line
487 # Remove ipython output prompt that might be present in the first line
457 want_lines[0] = re.sub(r'Out\[\d+\]: \s*?\n?','',want_lines[0])
488 want_lines[0] = re.sub(r'Out\[\d+\]: \s*?\n?','',want_lines[0])
458
489
459 want = '\n'.join([wl[indent:] for wl in want_lines])
490 want = '\n'.join([wl[indent:] for wl in want_lines])
460
491
461 # If `want` contains a traceback message, then extract it.
492 # If `want` contains a traceback message, then extract it.
462 m = self._EXCEPTION_RE.match(want)
493 m = self._EXCEPTION_RE.match(want)
463 if m:
494 if m:
464 exc_msg = m.group('msg')
495 exc_msg = m.group('msg')
465 else:
496 else:
466 exc_msg = None
497 exc_msg = None
467
498
468 # Extract options from the source.
499 # Extract options from the source.
469 options = self._find_options(source, name, lineno)
500 options = self._find_options(source, name, lineno)
470
501
471 return source, options, want, exc_msg
502 return source, options, want, exc_msg
472
503
473 def _check_prompt_blank(self, lines, indent, name, lineno, ps1_len):
504 def _check_prompt_blank(self, lines, indent, name, lineno, ps1_len):
474 """
505 """
475 Given the lines of a source string (including prompts and
506 Given the lines of a source string (including prompts and
476 leading indentation), check to make sure that every prompt is
507 leading indentation), check to make sure that every prompt is
477 followed by a space character. If any line is not followed by
508 followed by a space character. If any line is not followed by
478 a space character, then raise ValueError.
509 a space character, then raise ValueError.
479
510
480 Note: IPython-modified version which takes the input prompt length as a
511 Note: IPython-modified version which takes the input prompt length as a
481 parameter, so that prompts of variable length can be dealt with.
512 parameter, so that prompts of variable length can be dealt with.
482 """
513 """
483 space_idx = indent+ps1_len
514 space_idx = indent+ps1_len
484 min_len = space_idx+1
515 min_len = space_idx+1
485 for i, line in enumerate(lines):
516 for i, line in enumerate(lines):
486 if len(line) >= min_len and line[space_idx] != ' ':
517 if len(line) >= min_len and line[space_idx] != ' ':
487 raise ValueError('line %r of the docstring for %s '
518 raise ValueError('line %r of the docstring for %s '
488 'lacks blank after %s: %r' %
519 'lacks blank after %s: %r' %
489 (lineno+i+1, name,
520 (lineno+i+1, name,
490 line[indent:space_idx], line))
521 line[indent:space_idx], line))
491
522
492 SKIP = doctest.register_optionflag('SKIP')
523 SKIP = doctest.register_optionflag('SKIP')
493
524
494
525
526 class IPDocTestRunner(doctest.DocTestRunner):
527
528 # Unfortunately, doctest uses a private method (__run) for the actual run
529 # execution, so we can't cleanly override just that part. Instead, we have
530 # to copy/paste the entire run() implementation so we can call our own
531 # customized runner.
532 #/////////////////////////////////////////////////////////////////
533 # DocTest Running
534 #/////////////////////////////////////////////////////////////////
535
536 def __run(self, test, compileflags, out):
537 """
538 Run the examples in `test`. Write the outcome of each example
539 with one of the `DocTestRunner.report_*` methods, using the
540 writer function `out`. `compileflags` is the set of compiler
541 flags that should be used to execute examples. Return a tuple
542 `(f, t)`, where `t` is the number of examples tried, and `f`
543 is the number of examples that failed. The examples are run
544 in the namespace `test.globs`.
545 """
546 # Keep track of the number of failures and tries.
547 failures = tries = 0
548
549 # Save the option flags (since option directives can be used
550 # to modify them).
551 original_optionflags = self.optionflags
552
553 SUCCESS, FAILURE, BOOM = range(3) # `outcome` state
554
555 check = self._checker.check_output
556
557 # Process each example.
558 for examplenum, example in enumerate(test.examples):
559
560 # If REPORT_ONLY_FIRST_FAILURE is set, then supress
561 # reporting after the first failure.
562 quiet = (self.optionflags & REPORT_ONLY_FIRST_FAILURE and
563 failures > 0)
564
565 # Merge in the example's options.
566 self.optionflags = original_optionflags
567 if example.options:
568 for (optionflag, val) in example.options.items():
569 if val:
570 self.optionflags |= optionflag
571 else:
572 self.optionflags &= ~optionflag
573
574 # If 'SKIP' is set, then skip this example.
575 if self.optionflags & SKIP:
576 continue
577
578 # Record that we started this example.
579 tries += 1
580 if not quiet:
581 self.report_start(out, test, example)
582
583 # Use a special filename for compile(), so we can retrieve
584 # the source code during interactive debugging (see
585 # __patched_linecache_getlines).
586 filename = '<doctest %s[%d]>' % (test.name, examplenum)
587
588 # Run the example in the given context (globs), and record
589 # any exception that gets raised. (But don't intercept
590 # keyboard interrupts.)
591 try:
592 # Don't blink! This is where the user's code gets run.
593 exec compile(example.source, filename, "single",
594 compileflags, 1) in test.globs
595 self.debugger.set_continue() # ==== Example Finished ====
596 exception = None
597 except KeyboardInterrupt:
598 raise
599 except:
600 exception = sys.exc_info()
601 self.debugger.set_continue() # ==== Example Finished ====
602
603 got = self._fakeout.getvalue() # the actual output
604 self._fakeout.truncate(0)
605 outcome = FAILURE # guilty until proved innocent or insane
606
607 # If the example executed without raising any exceptions,
608 # verify its output.
609 if exception is None:
610 if check(example.want, got, self.optionflags):
611 outcome = SUCCESS
612
613 # The example raised an exception: check if it was expected.
614 else:
615 exc_info = sys.exc_info()
616 exc_msg = traceback.format_exception_only(*exc_info[:2])[-1]
617 if not quiet:
618 got += _exception_traceback(exc_info)
619
620 # If `example.exc_msg` is None, then we weren't expecting
621 # an exception.
622 if example.exc_msg is None:
623 outcome = BOOM
624
625 # We expected an exception: see whether it matches.
626 elif check(example.exc_msg, exc_msg, self.optionflags):
627 outcome = SUCCESS
628
629 # Another chance if they didn't care about the detail.
630 elif self.optionflags & IGNORE_EXCEPTION_DETAIL:
631 m1 = re.match(r'[^:]*:', example.exc_msg)
632 m2 = re.match(r'[^:]*:', exc_msg)
633 if m1 and m2 and check(m1.group(0), m2.group(0),
634 self.optionflags):
635 outcome = SUCCESS
636
637 # Report the outcome.
638 if outcome is SUCCESS:
639 if not quiet:
640 self.report_success(out, test, example, got)
641 elif outcome is FAILURE:
642 if not quiet:
643 self.report_failure(out, test, example, got)
644 failures += 1
645 elif outcome is BOOM:
646 if not quiet:
647 self.report_unexpected_exception(out, test, example,
648 exc_info)
649 failures += 1
650 else:
651 assert False, ("unknown outcome", outcome)
652
653 # Restore the option flags (in case they were modified)
654 self.optionflags = original_optionflags
655
656 # Record and return the number of failures and tries.
657
658 #self.__record_outcome(test, failures, tries)
659
660 # Hack to access a parent private method by working around Python's
661 # name mangling (which is fortunately simple).
662 doctest.DocTestRunner._DocTestRunner__record_outcome(self,test,
663 failures, tries)
664 return failures, tries
665
666 def run(self, test, compileflags=None, out=None, clear_globs=True):
667 """
668 Run the examples in `test`, and display the results using the
669 writer function `out`.
670
671 The examples are run in the namespace `test.globs`. If
672 `clear_globs` is true (the default), then this namespace will
673 be cleared after the test runs, to help with garbage
674 collection. If you would like to examine the namespace after
675 the test completes, then use `clear_globs=False`.
676
677 `compileflags` gives the set of flags that should be used by
678 the Python compiler when running the examples. If not
679 specified, then it will default to the set of future-import
680 flags that apply to `globs`.
681
682 The output of each example is checked using
683 `DocTestRunner.check_output`, and the results are formatted by
684 the `DocTestRunner.report_*` methods.
685 """
686 self.test = test
687
688 if compileflags is None:
689 compileflags = _extract_future_flags(test.globs)
690
691 save_stdout = sys.stdout
692 if out is None:
693 out = save_stdout.write
694 sys.stdout = self._fakeout
695
696 # Patch pdb.set_trace to restore sys.stdout during interactive
697 # debugging (so it's not still redirected to self._fakeout).
698 # Note that the interactive output will go to *our*
699 # save_stdout, even if that's not the real sys.stdout; this
700 # allows us to write test cases for the set_trace behavior.
701 save_set_trace = pdb.set_trace
702 self.debugger = _OutputRedirectingPdb(save_stdout)
703 self.debugger.reset()
704 pdb.set_trace = self.debugger.set_trace
705
706 # Patch linecache.getlines, so we can see the example's source
707 # when we're inside the debugger.
708 self.save_linecache_getlines = linecache.getlines
709 linecache.getlines = self.__patched_linecache_getlines
710
711 try:
712 return self.__run(test, compileflags, out)
713 finally:
714 sys.stdout = save_stdout
715 pdb.set_trace = save_set_trace
716 linecache.getlines = self.save_linecache_getlines
717 if clear_globs:
718 test.globs.clear()
719
720
495 class DocFileCase(doctest.DocFileCase):
721 class DocFileCase(doctest.DocFileCase):
496 """Overrides to provide filename
722 """Overrides to provide filename
497 """
723 """
498 def address(self):
724 def address(self):
499 return (self._dt_test.filename, None, None)
725 return (self._dt_test.filename, None, None)
500
726
501
727
502 class ExtensionDoctest(doctests.Doctest):
728 class ExtensionDoctest(doctests.Doctest):
503 """Nose Plugin that supports doctests in extension modules.
729 """Nose Plugin that supports doctests in extension modules.
504 """
730 """
505 name = 'extdoctest' # call nosetests with --with-extdoctest
731 name = 'extdoctest' # call nosetests with --with-extdoctest
506 enabled = True
732 enabled = True
507
733
508 def options(self, parser, env=os.environ):
734 def options(self, parser, env=os.environ):
509 Plugin.options(self, parser, env)
735 Plugin.options(self, parser, env)
510
736
511 def configure(self, options, config):
737 def configure(self, options, config):
512 Plugin.configure(self, options, config)
738 Plugin.configure(self, options, config)
513 self.doctest_tests = options.doctest_tests
739 self.doctest_tests = options.doctest_tests
514 self.extension = tolist(options.doctestExtension)
740 self.extension = tolist(options.doctestExtension)
515 self.finder = DocTestFinder()
741 self.finder = DocTestFinder()
516 self.parser = doctest.DocTestParser()
742 self.parser = doctest.DocTestParser()
517
743 self.globs = None
744 self.extraglobs = None
518
745
519 def loadTestsFromExtensionModule(self,filename):
746 def loadTestsFromExtensionModule(self,filename):
520 bpath,mod = os.path.split(filename)
747 bpath,mod = os.path.split(filename)
521 modname = os.path.splitext(mod)[0]
748 modname = os.path.splitext(mod)[0]
522 try:
749 try:
523 sys.path.append(bpath)
750 sys.path.append(bpath)
524 module = __import__(modname)
751 module = __import__(modname)
525 tests = list(self.loadTestsFromModule(module))
752 tests = list(self.loadTestsFromModule(module))
526 finally:
753 finally:
527 sys.path.pop()
754 sys.path.pop()
528 return tests
755 return tests
529
756
530 # NOTE: the method below is almost a copy of the original one in nose, with
757 # NOTE: the method below is almost a copy of the original one in nose, with
531 # a few modifications to control output checking.
758 # a few modifications to control output checking.
532
759
533 def loadTestsFromModule(self, module):
760 def loadTestsFromModule(self, module):
534 #print 'lTM',module # dbg
761 #print 'lTM',module # dbg
535
762
536 if not self.matches(module.__name__):
763 if not self.matches(module.__name__):
537 log.debug("Doctest doesn't want module %s", module)
764 log.debug("Doctest doesn't want module %s", module)
538 return
765 return
539 tests = self.finder.find(module)
766
767 ## try:
768 ## print 'Globs:',self.globs.keys() # dbg
769 ## except:
770 ## pass
771
772 tests = self.finder.find(module,globs=self.globs,
773 extraglobs=self.extraglobs)
540 if not tests:
774 if not tests:
541 return
775 return
542 tests.sort()
776 tests.sort()
543 module_file = module.__file__
777 module_file = module.__file__
544 if module_file[-4:] in ('.pyc', '.pyo'):
778 if module_file[-4:] in ('.pyc', '.pyo'):
545 module_file = module_file[:-1]
779 module_file = module_file[:-1]
546 for test in tests:
780 for test in tests:
547 if not test.examples:
781 if not test.examples:
548 continue
782 continue
549 if not test.filename:
783 if not test.filename:
550 test.filename = module_file
784 test.filename = module_file
551
785
552 #yield DocTestCase(test)
786 # xxx - checker and options may be ok instantiated once outside loop
553
787
554 # always use whitespace and ellipsis options
788 # always use whitespace and ellipsis options
555 optionflags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
789 optionflags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
556 checker = IPDoctestOutputChecker()
790 checker = IPDoctestOutputChecker()
557 yield DocTestCase(test,
791
792 yield DocTestCase(test,
558 optionflags=optionflags,
793 optionflags=optionflags,
559 checker=checker)
794 checker=checker)
560
795
561 def loadTestsFromFile(self, filename):
796 def loadTestsFromFile(self, filename):
562 #print 'lTF',filename # dbg
797 #print 'lTF',filename # dbg
563
798
564 if is_extension_module(filename):
799 if is_extension_module(filename):
565 for t in self.loadTestsFromExtensionModule(filename):
800 for t in self.loadTestsFromExtensionModule(filename):
566 yield t
801 yield t
567 else:
802 else:
568 ## for t in list(doctests.Doctest.loadTestsFromFile(self,filename)):
803 if self.extension and anyp(filename.endswith, self.extension):
569 ## yield t
804 name = os.path.basename(filename)
570 pass
805 dh = open(filename)
571
806 try:
572 if self.extension and anyp(filename.endswith, self.extension):
807 doc = dh.read()
573 name = os.path.basename(filename)
808 finally:
574 dh = open(filename)
809 dh.close()
575 try:
810 test = self.parser.get_doctest(
576 doc = dh.read()
811 doc, globs={'__file__': filename}, name=name,
577 finally:
812 filename=filename, lineno=0)
578 dh.close()
813 if test.examples:
579 test = self.parser.get_doctest(
814 #print 'FileCase:',test.examples # dbg
580 doc, globs={'__file__': filename}, name=name,
815 yield DocFileCase(test)
581 filename=filename, lineno=0)
816 else:
582 if test.examples:
817 yield False # no tests to load
583 #print 'FileCase:',test.examples # dbg
584 yield DocFileCase(test)
585 else:
586 yield False # no tests to load
587
818
588 def wantFile(self,filename):
819 def wantFile(self,filename):
589 """Return whether the given filename should be scanned for tests.
820 """Return whether the given filename should be scanned for tests.
590
821
591 Modified version that accepts extension modules as valid containers for
822 Modified version that accepts extension modules as valid containers for
592 doctests.
823 doctests.
593 """
824 """
594 print 'Filename:',filename # dbg
825 #print 'Filename:',filename # dbg
595
826
596 # temporarily hardcoded list, will move to driver later
827 # temporarily hardcoded list, will move to driver later
597 exclude = ['IPython/external/',
828 exclude = ['IPython/external/',
598 'IPython/Extensions/ipy_',
829 'IPython/Extensions/ipy_',
599 'IPython/platutils_win32',
830 'IPython/platutils_win32',
600 'IPython/frontend/cocoa',
831 'IPython/frontend/cocoa',
601 'IPython_doctest_plugin',
832 'IPython_doctest_plugin',
602 'IPython/Gnuplot',
833 'IPython/Gnuplot',
603 'IPython/Extensions/PhysicalQIn']
834 'IPython/Extensions/PhysicalQIn']
604
835
605 for fex in exclude:
836 for fex in exclude:
606 if fex in filename: # substring
837 if fex in filename: # substring
607 #print '###>>> SKIP:',filename # dbg
838 #print '###>>> SKIP:',filename # dbg
608 return False
839 return False
609
840
610 if is_extension_module(filename):
841 if is_extension_module(filename):
611 return True
842 return True
612 else:
843 else:
613 return doctests.Doctest.wantFile(self,filename)
844 return doctests.Doctest.wantFile(self,filename)
614
845
615
846
616 class IPythonDoctest(ExtensionDoctest):
847 class IPythonDoctest(ExtensionDoctest):
617 """Nose Plugin that supports doctests in extension modules.
848 """Nose Plugin that supports doctests in extension modules.
618 """
849 """
619 name = 'ipdoctest' # call nosetests with --with-ipdoctest
850 name = 'ipdoctest' # call nosetests with --with-ipdoctest
620 enabled = True
851 enabled = True
621
852
622 def configure(self, options, config):
853 def configure(self, options, config):
623
854
624 Plugin.configure(self, options, config)
855 Plugin.configure(self, options, config)
625 self.doctest_tests = options.doctest_tests
856 self.doctest_tests = options.doctest_tests
626 self.extension = tolist(options.doctestExtension)
857 self.extension = tolist(options.doctestExtension)
627 self.parser = IPDocTestParser()
858 self.parser = IPDocTestParser()
628 self.finder = DocTestFinder(parser=self.parser)
859 self.finder = DocTestFinder(parser=self.parser)
860
861 # XXX - we need to run in the ipython user's namespace, but doing so is
862 # breaking normal doctests!
863
864 #self.globs = _ip.user_ns
865 self.globs = None
866
867 self.extraglobs = None
@@ -1,11 +1,122 b''
1 def test_refs():
1 # Module imports
2 # Std lib
3 import inspect
4
5 # Third party
6
7 # Our own
8 import decorators as dec
9
10 #-----------------------------------------------------------------------------
11 # Utilities
12
13 # Note: copied from OInspect, kept here so the testing stuff doesn't create
14 # circular dependencies and is easier to reuse.
15 def getargspec(obj):
16 """Get the names and default values of a function's arguments.
17
18 A tuple of four things is returned: (args, varargs, varkw, defaults).
19 'args' is a list of the argument names (it may contain nested lists).
20 'varargs' and 'varkw' are the names of the * and ** arguments or None.
21 'defaults' is an n-tuple of the default values of the last n arguments.
22
23 Modified version of inspect.getargspec from the Python Standard
24 Library."""
25
26 if inspect.isfunction(obj):
27 func_obj = obj
28 elif inspect.ismethod(obj):
29 func_obj = obj.im_func
30 else:
31 raise TypeError, 'arg is not a Python function'
32 args, varargs, varkw = inspect.getargs(func_obj.func_code)
33 return args, varargs, varkw, func_obj.func_defaults
34
35 #-----------------------------------------------------------------------------
36 # Testing functions
37
38 def test_trivial():
39 """A trivial passing test."""
40 pass
41
42
43 @dec.skip
44 def test_deliberately_broken():
45 """A deliberately broken test - we want to skip this one."""
46 1/0
47
48
49 # Verify that we can correctly skip the doctest for a function at will, but
50 # that the docstring itself is NOT destroyed by the decorator.
51 @dec.skip_doctest
52 def doctest_bad(x,y=1,**k):
53 """A function whose doctest we need to skip.
54
55 >>> 1+1
56 3
57 """
58 z=2
59
60
61 def test_skip_dt_decorator():
62 """Doctest-skipping decorator should preserve the docstring.
63 """
64 # Careful: 'check' must be a *verbatim* copy of the doctest_bad docstring!
65 check = """A function whose doctest we need to skip.
66
67 >>> 1+1
68 3
69 """
70 # Fetch the docstring from doctest_bad after decoration.
71 val = doctest_bad.__doc__
72
73 assert check==val,"doctest_bad docstrings don't match"
74
75
76 def test_skip_dt_decorator2():
77 """Doctest-skipping decorator should preserve function signature.
78 """
79 # Hardcoded correct answer
80 dtargs = (['x', 'y'], None, 'k', (1,))
81 # Introspect out the value
82 dtargsr = getargspec(doctest_bad)
83 assert dtargsr==dtargs, \
84 "Incorrectly reconstructed args for doctest_bad: %s" % (dtargsr,)
85
86
87 def doctest_run():
88 """Test running a trivial script.
89
90 In [13]: run simplevars.py
91 x is: 1
92 """
93
94 #@dec.skip_doctest
95 def doctest_runvars():
96 """Test that variables defined in scripts get loaded correcly via %run.
97
98 In [13]: run simplevars.py
99 x is: 1
100
101 In [14]: x
102 Out[14]: 1
103 """
104
105 def doctest_ivars():
106 """Test that variables defined interactively are picked up.
107 In [5]: zz=1
108
109 In [6]: zz
110 Out[6]: 1
111 """
112
113 @dec.skip_doctest
114 def doctest_refs():
2 """DocTest reference holding issues when running scripts.
115 """DocTest reference holding issues when running scripts.
3
116
4 In [32]: run show_refs.py
117 In [32]: run show_refs.py
5 c referrers: [<type 'dict'>]
118 c referrers: [<type 'dict'>]
6
119
7 In [33]: map(type,gc.get_referrers(c))
120 In [33]: map(type,gc.get_referrers(c))
8 Out[33]: [<type 'dict'>]
121 Out[33]: [<type 'dict'>]
9
10 """
122 """
11 pass
General Comments 0
You need to be logged in to leave comments. Login now