##// 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 1 # Set this prefix to where you want to install the plugin
2 2 PREFIX=~/usr/local
3 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 12 plugin: IPython_doctest_plugin.egg-info
6 13
7 14 dtest: plugin dtexample.py
8 nosetests -vs --with-ipdoctest --doctest-tests --doctest-extension=txt \
9 dtexample.py
15 $(NOSE) dtexample.py
10 16
11 17 # Note: this test is double counting!!!
12 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 25 test: plugin dtexample.py
16 nosetests -vs --with-ipdoctest --doctest-tests --doctest-extension=txt \
17 dtexample.py test*.py test*.txt
26 $(NOSE) dtexample.py test*.py test*.txt
18 27
19 28 deb: plugin dtexample.py
20 nosetests -vs --with-ipdoctest --doctest-tests --doctest-extension=txt \
21 test_combo.txt
29 $(NOSE) test_combo.txt
22 30
23 31 iptest: plugin
24 nosetests -vs --with-ipdoctest --doctest-tests --doctest-extension=txt \
25 IPython
32 $(NOSE) 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 44 python setup.py install --prefix=$(PREFIX)
29 45 touch $@
30 46
31 47 clean:
32 48 rm -rf IPython_doctest_plugin.egg-info *~ *pyc build/ dist/
@@ -1,628 +1,867 b''
1 1 """Nose Plugin that supports IPython doctests.
2 2
3 3 Limitations:
4 4
5 5 - When generating examples for use as doctests, make sure that you have
6 6 pretty-printing OFF. This can be done either by starting ipython with the
7 7 flag '--nopprint', by setting pprint to 0 in your ipythonrc file, or by
8 8 interactively disabling it with %Pprint. This is required so that IPython
9 9 output matches that of normal Python, which is used by doctest for internal
10 10 execution.
11 11
12 12 - Do not rely on specific prompt numbers for results (such as using
13 13 '_34==True', for example). For IPython tests run via an external process the
14 14 prompt numbers may be different, and IPython tests run as normal python code
15 15 won't even have these special _NN variables set at all.
16 16
17 17 - IPython functions that produce output as a side-effect of calling a system
18 18 process (e.g. 'ls') can be doc-tested, but they must be handled in an
19 19 external IPython process. Such doctests must be tagged with:
20 20
21 21 # ipdoctest: EXTERNAL
22 22
23 23 so that the testing machinery handles them differently. Since these are run
24 24 via pexpect in an external process, they can't deal with exceptions or other
25 25 fancy featurs of regular doctests. You must limit such tests to simple
26 26 matching of the output. For this reason, I recommend you limit these kinds
27 27 of doctests to features that truly require a separate process, and use the
28 28 normal IPython ones (which have all the features of normal doctests) for
29 29 everything else. See the examples at the bottom of this file for a
30 30 comparison of what can be done with both types.
31 31 """
32 32
33 33
34 34 #-----------------------------------------------------------------------------
35 35 # Module imports
36 36
37 37 # From the standard library
38 38 import __builtin__
39 39 import commands
40 40 import doctest
41 41 import inspect
42 42 import logging
43 43 import os
44 44 import re
45 45 import sys
46 46 import unittest
47 47
48 48 from inspect import getmodule
49 49
50 50 # Third-party modules
51 51 import nose.core
52 52
53 53 from nose.plugins import doctests, Plugin
54 54 from nose.util import anyp, getpackage, test_address, resolve_name, tolist
55 55
56 56 # Our own imports
57 57 #from extdoctest import ExtensionDoctest, DocTestFinder
58 58 #from dttools import DocTestFinder, DocTestCase
59 59 #-----------------------------------------------------------------------------
60 60 # Module globals and other constants
61 61
62 62 log = logging.getLogger(__name__)
63 63
64 64 ###########################################################################
65 65 # *** HACK ***
66 66 # We must start our own ipython object and heavily muck with it so that all the
67 67 # modifications IPython makes to system behavior don't send the doctest
68 68 # machinery into a fit. This code should be considered a gross hack, but it
69 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 94 def start_ipython():
72 95 """Start a global IPython shell, which we need for IPython-specific syntax.
73 96 """
74 97 import IPython
75 98
76 99 def xsys(cmd):
77 100 """Execute a command and print its output.
78 101
79 102 This is just a convenience function to replace the IPython system call
80 103 with one that is more doctest-friendly.
81 104 """
82 105 cmd = _ip.IP.var_expand(cmd,depth=1)
83 106 sys.stdout.write(commands.getoutput(cmd))
84 107 sys.stdout.flush()
85 108
86 109 # Store certain global objects that IPython modifies
87 110 _displayhook = sys.displayhook
88 111 _excepthook = sys.excepthook
89 112 _main = sys.modules.get('__main__')
90 113
91 # Start IPython instance
92 IPython.Shell.IPShell(['--classic','--noterm_title'])
114 # Start IPython instance. We customize it to start with minimal frills and
115 # with our own namespace.
116 argv = ['--classic','--noterm_title']
117 user_ns = ncdict()
118 IPython.Shell.IPShell(argv,user_ns)
93 119
94 120 # Deactivate the various python system hooks added by ipython for
95 121 # interactive convenience so we don't confuse the doctest system
96 122 sys.modules['__main__'] = _main
97 123 sys.displayhook = _displayhook
98 124 sys.excepthook = _excepthook
99 125
100 126 # So that ipython magics and aliases can be doctested (they work by making
101 127 # a call into a global _ip object)
102 128 _ip = IPython.ipapi.get()
103 129 __builtin__._ip = _ip
104 130
105 131 # Modify the IPython system call with one that uses getoutput, so that we
106 132 # can capture subcommands and print them to Python's stdout, otherwise the
107 133 # doctest machinery would miss them.
108 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 141 # The start call MUST be made here. I'm not sure yet why it doesn't work if
111 142 # it is made later, at plugin initialization time, but in all my tests, that's
112 143 # the case.
113 144 start_ipython()
114 145
115 146 # *** END HACK ***
116 147 ###########################################################################
117 148
118 149 # Classes and functions
119 150
120 151 def is_extension_module(filename):
121 152 """Return whether the given filename is an extension module.
122 153
123 154 This simply checks that the extension is either .so or .pyd.
124 155 """
125 156 return os.path.splitext(filename)[1].lower() in ('.so','.pyd')
126 157
127 158
128 159 # Modified version of the one in the stdlib, that fixes a python bug (doctests
129 160 # not found in extension modules, http://bugs.python.org/issue3158)
130 161 class DocTestFinder(doctest.DocTestFinder):
131 162
132 163 def _from_module(self, module, object):
133 164 """
134 165 Return true if the given object is defined in the given
135 166 module.
136 167 """
137 168 if module is None:
138 169 #print '_fm C1' # dbg
139 170 return True
140 171 elif inspect.isfunction(object):
141 172 #print '_fm C2' # dbg
142 173 return module.__dict__ is object.func_globals
143 174 elif inspect.isbuiltin(object):
144 175 #print '_fm C2-1' # dbg
145 176 return module.__name__ == object.__module__
146 177 elif inspect.isclass(object):
147 178 #print '_fm C3' # dbg
148 179 return module.__name__ == object.__module__
149 180 elif inspect.ismethod(object):
150 181 # This one may be a bug in cython that fails to correctly set the
151 182 # __module__ attribute of methods, but since the same error is easy
152 183 # to make by extension code writers, having this safety in place
153 184 # isn't such a bad idea
154 185 #print '_fm C3-1' # dbg
155 186 return module.__name__ == object.im_class.__module__
156 187 elif inspect.getmodule(object) is not None:
157 188 #print '_fm C4' # dbg
158 189 #print 'C4 mod',module,'obj',object # dbg
159 190 return module is inspect.getmodule(object)
160 191 elif hasattr(object, '__module__'):
161 192 #print '_fm C5' # dbg
162 193 return module.__name__ == object.__module__
163 194 elif isinstance(object, property):
164 195 #print '_fm C6' # dbg
165 196 return True # [XX] no way not be sure.
166 197 else:
167 198 raise ValueError("object must be a class or function")
168 199
169 200 def _find(self, tests, obj, name, module, source_lines, globs, seen):
170 201 """
171 202 Find tests for the given object and any contained objects, and
172 203 add them to `tests`.
173 204 """
174 205
175 206 doctest.DocTestFinder._find(self,tests, obj, name, module,
176 207 source_lines, globs, seen)
177 208
178 209 # Below we re-run pieces of the above method with manual modifications,
179 210 # because the original code is buggy and fails to correctly identify
180 211 # doctests in extension modules.
181 212
182 213 # Local shorthands
183 214 from inspect import isroutine, isclass, ismodule
184 215
185 216 # Look for tests in a module's contained objects.
186 217 if inspect.ismodule(obj) and self._recurse:
187 218 for valname, val in obj.__dict__.items():
188 219 valname1 = '%s.%s' % (name, valname)
189 220 if ( (isroutine(val) or isclass(val))
190 221 and self._from_module(module, val) ):
191 222
192 223 self._find(tests, val, valname1, module, source_lines,
193 224 globs, seen)
194 225
195 226 # Look for tests in a class's contained objects.
196 227 if inspect.isclass(obj) and self._recurse:
197 228 #print 'RECURSE into class:',obj # dbg
198 229 for valname, val in obj.__dict__.items():
199 230 #valname1 = '%s.%s' % (name, valname) # dbg
200 231 #print 'N',name,'VN:',valname,'val:',str(val)[:77] # dbg
201 232 # Special handling for staticmethod/classmethod.
202 233 if isinstance(val, staticmethod):
203 234 val = getattr(obj, valname)
204 235 if isinstance(val, classmethod):
205 236 val = getattr(obj, valname).im_func
206 237
207 238 # Recurse to methods, properties, and nested classes.
208 239 if ((inspect.isfunction(val) or inspect.isclass(val) or
209 240 inspect.ismethod(val) or
210 241 isinstance(val, property)) and
211 242 self._from_module(module, val)):
212 243 valname = '%s.%s' % (name, valname)
213 244 self._find(tests, val, valname, module, source_lines,
214 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 249 # pass, then see if the expected output string contains flags that
219 250 # tell us to ignore the output
220 251 class IPDoctestOutputChecker(doctest.OutputChecker):
221 252 def check_output(self, want, got, optionflags):
222 253 #print '*** My Checker!' # dbg
223
224 ret = doctest.OutputChecker.check_output(self, want, got,
254
255 ret = doctest.OutputChecker.check_output(self, want, got,
225 256 optionflags)
226 257 if not ret:
227 258 if "#random" in want:
228 259 return True
229 260
230 261 return ret
231 262
232 263
233 264 class DocTestCase(doctests.DocTestCase):
234 265 """Proxy for DocTestCase: provides an address() method that
235 266 returns the correct address for the doctest case. Otherwise
236 267 acts as a proxy to the test case. To provide hints for address(),
237 268 an obj may also be passed -- this will be used as the test object
238 269 for purposes of determining the test address, if it is provided.
239 270 """
240 271
241 272 # Note: this method was taken from numpy's nosetester module.
242
243 # Subclass nose.plugins.doctests.DocTestCase to work around a bug in
273
274 # Subclass nose.plugins.doctests.DocTestCase to work around a bug in
244 275 # its constructor that blocks non-default arguments from being passed
245 276 # down into doctest.DocTestCase
246 277
247 278 def __init__(self, test, optionflags=0, setUp=None, tearDown=None,
248 279 checker=None, obj=None, result_var='_'):
249 280 self._result_var = result_var
250 doctests.DocTestCase.__init__(self, test,
281 doctests.DocTestCase.__init__(self, test,
251 282 optionflags=optionflags,
252 setUp=setUp, tearDown=tearDown,
283 setUp=setUp, tearDown=tearDown,
253 284 checker=checker)
254 285 # Now we must actually copy the original constructor from the stdlib
255 286 # doctest class, because we can't call it directly and a bug in nose
256 287 # means it never gets passed the right arguments.
257
288
258 289 self._dt_optionflags = optionflags
259 290 self._dt_checker = checker
260 291 self._dt_test = test
261 292 self._dt_setUp = setUp
262 293 self._dt_tearDown = tearDown
263 294
264 295
265 296
266 297 # A simple subclassing of the original with a different class name, so we can
267 298 # distinguish and treat differently IPython examples from pure python ones.
268 299 class IPExample(doctest.Example): pass
269 300
270 301
271 302 class IPExternalExample(doctest.Example):
272 303 """Doctest examples to be run in an external process."""
273 304
274 305 def __init__(self, source, want, exc_msg=None, lineno=0, indent=0,
275 306 options=None):
276 307 # Parent constructor
277 308 doctest.Example.__init__(self,source,want,exc_msg,lineno,indent,options)
278 309
279 310 # An EXTRA newline is needed to prevent pexpect hangs
280 311 self.source += '\n'
281 312
282 313
283 314 class IPDocTestParser(doctest.DocTestParser):
284 315 """
285 316 A class used to parse strings containing doctest examples.
286 317
287 318 Note: This is a version modified to properly recognize IPython input and
288 319 convert any IPython examples into valid Python ones.
289 320 """
290 321 # This regular expression is used to find doctest examples in a
291 322 # string. It defines three groups: `source` is the source code
292 323 # (including leading indentation and prompts); `indent` is the
293 324 # indentation of the first (PS1) line of the source code; and
294 325 # `want` is the expected output (including leading indentation).
295 326
296 327 # Classic Python prompts or default IPython ones
297 328 _PS1_PY = r'>>>'
298 329 _PS2_PY = r'\.\.\.'
299 330
300 331 _PS1_IP = r'In\ \[\d+\]:'
301 332 _PS2_IP = r'\ \ \ \.\.\.+:'
302 333
303 334 _RE_TPL = r'''
304 335 # Source consists of a PS1 line followed by zero or more PS2 lines.
305 336 (?P<source>
306 337 (?:^(?P<indent> [ ]*) (?P<ps1> %s) .*) # PS1 line
307 338 (?:\n [ ]* (?P<ps2> %s) .*)*) # PS2 lines
308 339 \n? # a newline
309 340 # Want consists of any non-blank lines that do not start with PS1.
310 341 (?P<want> (?:(?![ ]*$) # Not a blank line
311 342 (?![ ]*%s) # Not a line starting with PS1
312 343 (?![ ]*%s) # Not a line starting with PS2
313 344 .*$\n? # But any other line
314 345 )*)
315 346 '''
316 347
317 348 _EXAMPLE_RE_PY = re.compile( _RE_TPL % (_PS1_PY,_PS2_PY,_PS1_PY,_PS2_PY),
318 349 re.MULTILINE | re.VERBOSE)
319 350
320 351 _EXAMPLE_RE_IP = re.compile( _RE_TPL % (_PS1_IP,_PS2_IP,_PS1_IP,_PS2_IP),
321 352 re.MULTILINE | re.VERBOSE)
322 353
323 354 def ip2py(self,source):
324 355 """Convert input IPython source into valid Python."""
325 356 out = []
326 357 newline = out.append
327 358 for lnum,line in enumerate(source.splitlines()):
328 #newline(_ip.IPipython.prefilter(line,True))
329 359 newline(_ip.IP.prefilter(line,lnum>0))
330 360 newline('') # ensure a closing newline, needed by doctest
361 #print "PYSRC:", '\n'.join(out) # dbg
331 362 return '\n'.join(out)
332 363
333 364 def parse(self, string, name='<string>'):
334 365 """
335 366 Divide the given string into examples and intervening text,
336 367 and return them as a list of alternating Examples and strings.
337 368 Line numbers for the Examples are 0-based. The optional
338 369 argument `name` is a name identifying this string, and is only
339 370 used for error messages.
340 371 """
341
372
342 373 #print 'Parse string:\n',string # dbg
343 374
344 375 string = string.expandtabs()
345 376 # If all lines begin with the same indentation, then strip it.
346 377 min_indent = self._min_indent(string)
347 378 if min_indent > 0:
348 379 string = '\n'.join([l[min_indent:] for l in string.split('\n')])
349 380
350 381 output = []
351 382 charno, lineno = 0, 0
352 383
353 384 # Whether to convert the input from ipython to python syntax
354 385 ip2py = False
355 386 # Find all doctest examples in the string. First, try them as Python
356 387 # examples, then as IPython ones
357 388 terms = list(self._EXAMPLE_RE_PY.finditer(string))
358 389 if terms:
359 390 # Normal Python example
360 391 #print '-'*70 # dbg
361 392 #print 'PyExample, Source:\n',string # dbg
362 393 #print '-'*70 # dbg
363 394 Example = doctest.Example
364 395 else:
365 396 # It's an ipython example. Note that IPExamples are run
366 397 # in-process, so their syntax must be turned into valid python.
367 398 # IPExternalExamples are run out-of-process (via pexpect) so they
368 399 # don't need any filtering (a real ipython will be executing them).
369 400 terms = list(self._EXAMPLE_RE_IP.finditer(string))
370 401 if re.search(r'#\s*ipdoctest:\s*EXTERNAL',string):
371 402 #print '-'*70 # dbg
372 403 #print 'IPExternalExample, Source:\n',string # dbg
373 404 #print '-'*70 # dbg
374 405 Example = IPExternalExample
375 406 else:
376 407 #print '-'*70 # dbg
377 408 #print 'IPExample, Source:\n',string # dbg
378 409 #print '-'*70 # dbg
379 410 Example = IPExample
380 411 ip2py = True
381 412
382 413 for m in terms:
383 414 # Add the pre-example text to `output`.
384 415 output.append(string[charno:m.start()])
385 416 # Update lineno (lines before this example)
386 417 lineno += string.count('\n', charno, m.start())
387 418 # Extract info from the regexp match.
388 419 (source, options, want, exc_msg) = \
389 420 self._parse_example(m, name, lineno,ip2py)
390 421 if Example is IPExternalExample:
391 422 options[doctest.NORMALIZE_WHITESPACE] = True
392 423 want += '\n'
393 424 # Create an Example, and add it to the list.
394 425 if not self._IS_BLANK_OR_COMMENT(source):
395 426 #print 'Example source:', source # dbg
396 427 output.append(Example(source, want, exc_msg,
397 428 lineno=lineno,
398 429 indent=min_indent+len(m.group('indent')),
399 430 options=options))
400 431 # Update lineno (lines inside this example)
401 432 lineno += string.count('\n', m.start(), m.end())
402 433 # Update charno.
403 434 charno = m.end()
404 435 # Add any remaining post-example text to `output`.
405 436 output.append(string[charno:])
406 437 return output
407 438
408 439 def _parse_example(self, m, name, lineno,ip2py=False):
409 440 """
410 441 Given a regular expression match from `_EXAMPLE_RE` (`m`),
411 442 return a pair `(source, want)`, where `source` is the matched
412 443 example's source code (with prompts and indentation stripped);
413 444 and `want` is the example's expected output (with indentation
414 445 stripped).
415 446
416 447 `name` is the string's name, and `lineno` is the line number
417 448 where the example starts; both are used for error messages.
418 449
419 450 Optional:
420 451 `ip2py`: if true, filter the input via IPython to convert the syntax
421 452 into valid python.
422 453 """
423 454
424 455 # Get the example's indentation level.
425 456 indent = len(m.group('indent'))
426 457
427 458 # Divide source into lines; check that they're properly
428 459 # indented; and then strip their indentation & prompts.
429 460 source_lines = m.group('source').split('\n')
430 461
431 462 # We're using variable-length input prompts
432 463 ps1 = m.group('ps1')
433 464 ps2 = m.group('ps2')
434 465 ps1_len = len(ps1)
435 466
436 467 self._check_prompt_blank(source_lines, indent, name, lineno,ps1_len)
437 468 if ps2:
438 469 self._check_prefix(source_lines[1:], ' '*indent + ps2, name, lineno)
439 470
440 471 source = '\n'.join([sl[indent+ps1_len+1:] for sl in source_lines])
441 472
442 473 if ip2py:
443 474 # Convert source input from IPython into valid Python syntax
444 475 source = self.ip2py(source)
445 476
446 477 # Divide want into lines; check that it's properly indented; and
447 478 # then strip the indentation. Spaces before the last newline should
448 479 # be preserved, so plain rstrip() isn't good enough.
449 480 want = m.group('want')
450 481 want_lines = want.split('\n')
451 482 if len(want_lines) > 1 and re.match(r' *$', want_lines[-1]):
452 483 del want_lines[-1] # forget final newline & spaces after it
453 484 self._check_prefix(want_lines, ' '*indent, name,
454 485 lineno + len(source_lines))
455 486
456 487 # Remove ipython output prompt that might be present in the first line
457 488 want_lines[0] = re.sub(r'Out\[\d+\]: \s*?\n?','',want_lines[0])
458 489
459 490 want = '\n'.join([wl[indent:] for wl in want_lines])
460 491
461 492 # If `want` contains a traceback message, then extract it.
462 493 m = self._EXCEPTION_RE.match(want)
463 494 if m:
464 495 exc_msg = m.group('msg')
465 496 else:
466 497 exc_msg = None
467 498
468 499 # Extract options from the source.
469 500 options = self._find_options(source, name, lineno)
470 501
471 502 return source, options, want, exc_msg
472 503
473 504 def _check_prompt_blank(self, lines, indent, name, lineno, ps1_len):
474 505 """
475 506 Given the lines of a source string (including prompts and
476 507 leading indentation), check to make sure that every prompt is
477 508 followed by a space character. If any line is not followed by
478 509 a space character, then raise ValueError.
479 510
480 511 Note: IPython-modified version which takes the input prompt length as a
481 512 parameter, so that prompts of variable length can be dealt with.
482 513 """
483 514 space_idx = indent+ps1_len
484 515 min_len = space_idx+1
485 516 for i, line in enumerate(lines):
486 517 if len(line) >= min_len and line[space_idx] != ' ':
487 518 raise ValueError('line %r of the docstring for %s '
488 519 'lacks blank after %s: %r' %
489 520 (lineno+i+1, name,
490 521 line[indent:space_idx], line))
491 522
492 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 721 class DocFileCase(doctest.DocFileCase):
496 722 """Overrides to provide filename
497 723 """
498 724 def address(self):
499 725 return (self._dt_test.filename, None, None)
500 726
501 727
502 728 class ExtensionDoctest(doctests.Doctest):
503 729 """Nose Plugin that supports doctests in extension modules.
504 730 """
505 731 name = 'extdoctest' # call nosetests with --with-extdoctest
506 732 enabled = True
507 733
508 734 def options(self, parser, env=os.environ):
509 735 Plugin.options(self, parser, env)
510 736
511 737 def configure(self, options, config):
512 738 Plugin.configure(self, options, config)
513 739 self.doctest_tests = options.doctest_tests
514 740 self.extension = tolist(options.doctestExtension)
515 741 self.finder = DocTestFinder()
516 742 self.parser = doctest.DocTestParser()
517
743 self.globs = None
744 self.extraglobs = None
518 745
519 746 def loadTestsFromExtensionModule(self,filename):
520 747 bpath,mod = os.path.split(filename)
521 748 modname = os.path.splitext(mod)[0]
522 749 try:
523 750 sys.path.append(bpath)
524 751 module = __import__(modname)
525 752 tests = list(self.loadTestsFromModule(module))
526 753 finally:
527 754 sys.path.pop()
528 755 return tests
529 756
530 757 # NOTE: the method below is almost a copy of the original one in nose, with
531 758 # a few modifications to control output checking.
532
759
533 760 def loadTestsFromModule(self, module):
534 761 #print 'lTM',module # dbg
535 762
536 763 if not self.matches(module.__name__):
537 764 log.debug("Doctest doesn't want module %s", module)
538 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 774 if not tests:
541 775 return
542 776 tests.sort()
543 777 module_file = module.__file__
544 778 if module_file[-4:] in ('.pyc', '.pyo'):
545 779 module_file = module_file[:-1]
546 780 for test in tests:
547 781 if not test.examples:
548 782 continue
549 783 if not test.filename:
550 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 788 # always use whitespace and ellipsis options
555 789 optionflags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
556 790 checker = IPDoctestOutputChecker()
557 yield DocTestCase(test,
791
792 yield DocTestCase(test,
558 793 optionflags=optionflags,
559 794 checker=checker)
560 795
561 796 def loadTestsFromFile(self, filename):
562 797 #print 'lTF',filename # dbg
563 798
564 799 if is_extension_module(filename):
565 800 for t in self.loadTestsFromExtensionModule(filename):
566 801 yield t
567 802 else:
568 ## for t in list(doctests.Doctest.loadTestsFromFile(self,filename)):
569 ## yield t
570 pass
571
572 if self.extension and anyp(filename.endswith, self.extension):
573 name = os.path.basename(filename)
574 dh = open(filename)
575 try:
576 doc = dh.read()
577 finally:
578 dh.close()
579 test = self.parser.get_doctest(
580 doc, globs={'__file__': filename}, name=name,
581 filename=filename, lineno=0)
582 if test.examples:
583 #print 'FileCase:',test.examples # dbg
584 yield DocFileCase(test)
585 else:
586 yield False # no tests to load
803 if self.extension and anyp(filename.endswith, self.extension):
804 name = os.path.basename(filename)
805 dh = open(filename)
806 try:
807 doc = dh.read()
808 finally:
809 dh.close()
810 test = self.parser.get_doctest(
811 doc, globs={'__file__': filename}, name=name,
812 filename=filename, lineno=0)
813 if test.examples:
814 #print 'FileCase:',test.examples # dbg
815 yield DocFileCase(test)
816 else:
817 yield False # no tests to load
587 818
588 819 def wantFile(self,filename):
589 820 """Return whether the given filename should be scanned for tests.
590 821
591 822 Modified version that accepts extension modules as valid containers for
592 823 doctests.
593 824 """
594 print 'Filename:',filename # dbg
825 #print 'Filename:',filename # dbg
595 826
596 827 # temporarily hardcoded list, will move to driver later
597 828 exclude = ['IPython/external/',
598 829 'IPython/Extensions/ipy_',
599 830 'IPython/platutils_win32',
600 831 'IPython/frontend/cocoa',
601 832 'IPython_doctest_plugin',
602 833 'IPython/Gnuplot',
603 834 'IPython/Extensions/PhysicalQIn']
604 835
605 836 for fex in exclude:
606 837 if fex in filename: # substring
607 838 #print '###>>> SKIP:',filename # dbg
608 839 return False
609 840
610 841 if is_extension_module(filename):
611 842 return True
612 843 else:
613 844 return doctests.Doctest.wantFile(self,filename)
614 845
615 846
616 847 class IPythonDoctest(ExtensionDoctest):
617 848 """Nose Plugin that supports doctests in extension modules.
618 849 """
619 850 name = 'ipdoctest' # call nosetests with --with-ipdoctest
620 851 enabled = True
621 852
622 853 def configure(self, options, config):
623 854
624 855 Plugin.configure(self, options, config)
625 856 self.doctest_tests = options.doctest_tests
626 857 self.extension = tolist(options.doctestExtension)
627 858 self.parser = IPDocTestParser()
628 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 115 """DocTest reference holding issues when running scripts.
3 116
4 117 In [32]: run show_refs.py
5 118 c referrers: [<type 'dict'>]
6 119
7 120 In [33]: map(type,gc.get_referrers(c))
8 121 Out[33]: [<type 'dict'>]
9
10 122 """
11 pass
General Comments 0
You need to be logged in to leave comments. Login now