##// END OF EJS Templates
Merge pull request #13314 from Kojoley/refactor-doctest-skipping-implementation...
Matthias Bussonnier -
r27124:a8ca8395 merge
parent child Browse files
Show More
@@ -132,6 +132,7 b' from IPython.core.error import TryNext'
132 from IPython.core.inputtransformer2 import ESC_MAGIC
132 from IPython.core.inputtransformer2 import ESC_MAGIC
133 from IPython.core.latex_symbols import latex_symbols, reverse_latex_symbol
133 from IPython.core.latex_symbols import latex_symbols, reverse_latex_symbol
134 from IPython.core.oinspect import InspectColors
134 from IPython.core.oinspect import InspectColors
135 from IPython.testing.skipdoctest import skip_doctest
135 from IPython.utils import generics
136 from IPython.utils import generics
136 from IPython.utils.dir2 import dir2, get_real_method
137 from IPython.utils.dir2 import dir2, get_real_method
137 from IPython.utils.path import ensure_dir_exists
138 from IPython.utils.path import ensure_dir_exists
@@ -190,6 +191,8 b' class ProvisionalCompleterWarning(FutureWarning):'
190
191
191 warnings.filterwarnings('error', category=ProvisionalCompleterWarning)
192 warnings.filterwarnings('error', category=ProvisionalCompleterWarning)
192
193
194
195 @skip_doctest
193 @contextmanager
196 @contextmanager
194 def provisionalcompleter(action='ignore'):
197 def provisionalcompleter(action='ignore'):
195 """
198 """
@@ -114,7 +114,6 b' from IPython import get_ipython'
114 from IPython.utils import PyColorize
114 from IPython.utils import PyColorize
115 from IPython.utils import coloransi, py3compat
115 from IPython.utils import coloransi, py3compat
116 from IPython.core.excolors import exception_colors
116 from IPython.core.excolors import exception_colors
117 from IPython.testing.skipdoctest import skip_doctest
118
117
119 # skip module docstests
118 # skip module docstests
120 __skip_doctest__ = True
119 __skip_doctest__ = True
@@ -180,7 +179,6 b' class Tracer(object):'
180 while functioning acceptably (though with limitations) if outside of it.
179 while functioning acceptably (though with limitations) if outside of it.
181 """
180 """
182
181
183 @skip_doctest
184 def __init__(self, colors=None):
182 def __init__(self, colors=None):
185 """
183 """
186 DEPRECATED
184 DEPRECATED
@@ -921,7 +919,6 b' class Pdb(OldPdb):'
921 return True
919 return True
922 return False
920 return False
923
921
924 @skip_doctest
925 def _is_in_decorator_internal_and_should_skip(self, frame):
922 def _is_in_decorator_internal_and_should_skip(self, frame):
926 """
923 """
927 Utility to tell us whether we are in a decorator internal and should stop.
924 Utility to tell us whether we are in a decorator internal and should stop.
@@ -413,7 +413,6 b' class ExecutionMagics(Magics):'
413 self.shell.call_pdb = new_pdb
413 self.shell.call_pdb = new_pdb
414 print('Automatic pdb calling has been turned',on_off(new_pdb))
414 print('Automatic pdb calling has been turned',on_off(new_pdb))
415
415
416 @skip_doctest
417 @magic_arguments.magic_arguments()
416 @magic_arguments.magic_arguments()
418 @magic_arguments.argument('--breakpoint', '-b', metavar='FILE:LINE',
417 @magic_arguments.argument('--breakpoint', '-b', metavar='FILE:LINE',
419 help="""
418 help="""
@@ -63,7 +63,6 b' class OSMagics(Magics):'
63 super().__init__(shell=shell, **kwargs)
63 super().__init__(shell=shell, **kwargs)
64
64
65
65
66 @skip_doctest
67 def _isexec_POSIX(self, file):
66 def _isexec_POSIX(self, file):
68 """
67 """
69 Test for executable on a POSIX system
68 Test for executable on a POSIX system
@@ -75,14 +74,12 b' class OSMagics(Magics):'
75
74
76
75
77
76
78 @skip_doctest
79 def _isexec_WIN(self, file):
77 def _isexec_WIN(self, file):
80 """
78 """
81 Test for executable file on non POSIX system
79 Test for executable file on non POSIX system
82 """
80 """
83 return file.is_file() and self.execre.match(file.name) is not None
81 return file.is_file() and self.execre.match(file.name) is not None
84
82
85 @skip_doctest
86 def isexec(self, file):
83 def isexec(self, file):
87 """
84 """
88 Test for executable file on non POSIX system
85 Test for executable file on non POSIX system
@@ -633,8 +630,8 b' class OSMagics(Magics):'
633
630
634 # while the list form is useful to loop over:
631 # while the list form is useful to loop over:
635 In [6]: for f in a.l:
632 In [6]: for f in a.l:
636 ...: !wc -l $f
633 ...: !wc -l $f
637 ...:
634 ...:
638 146 setup.py
635 146 setup.py
639 130 win32_manual_post_install.py
636 130 win32_manual_post_install.py
640
637
@@ -20,7 +20,6 b' Limitations:'
20
20
21 # From the standard library
21 # From the standard library
22 import doctest
22 import doctest
23 import inspect
24 import logging
23 import logging
25 import os
24 import os
26 import re
25 import re
@@ -38,106 +37,16 b' log = logging.getLogger(__name__)'
38 # Classes and functions
37 # Classes and functions
39 #-----------------------------------------------------------------------------
38 #-----------------------------------------------------------------------------
40
39
41 class DocTestSkip(object):
42 """Object wrapper for doctests to be skipped."""
43
40
44 ds_skip = """Doctest to skip.
45 >>> 1 #doctest: +SKIP
46 """
47
48 def __init__(self,obj):
49 self.obj = obj
50
51 def __getattribute__(self,key):
52 if key == '__doc__':
53 return DocTestSkip.ds_skip
54 else:
55 return getattr(object.__getattribute__(self,'obj'),key)
56
57 # Modified version of the one in the stdlib, that fixes a python bug (doctests
58 # not found in extension modules, http://bugs.python.org/issue3158)
59 class DocTestFinder(doctest.DocTestFinder):
41 class DocTestFinder(doctest.DocTestFinder):
42 def _get_test(self, obj, name, module, globs, source_lines):
43 test = super()._get_test(obj, name, module, globs, source_lines)
60
44
61 def _from_module(self, module, object):
45 if bool(getattr(obj, "__skip_doctest__", False)) and test is not None:
62 """
46 for example in test.examples:
63 Return true if the given object is defined in the given
47 example.options[doctest.SKIP] = True
64 module.
65 """
66 if module is None:
67 return True
68 elif inspect.isfunction(object):
69 return module.__dict__ is object.__globals__
70 elif inspect.isbuiltin(object):
71 return module.__name__ == object.__module__
72 elif inspect.isclass(object):
73 return module.__name__ == object.__module__
74 elif inspect.ismethod(object):
75 # This one may be a bug in cython that fails to correctly set the
76 # __module__ attribute of methods, but since the same error is easy
77 # to make by extension code writers, having this safety in place
78 # isn't such a bad idea
79 return module.__name__ == object.__self__.__class__.__module__
80 elif inspect.getmodule(object) is not None:
81 return module is inspect.getmodule(object)
82 elif hasattr(object, '__module__'):
83 return module.__name__ == object.__module__
84 elif isinstance(object, property):
85 return True # [XX] no way not be sure.
86 elif inspect.ismethoddescriptor(object):
87 # Unbound PyQt signals reach this point in Python 3.4b3, and we want
88 # to avoid throwing an error. See also http://bugs.python.org/issue3158
89 return False
90 else:
91 raise ValueError("object must be a class or function, got %r" % object)
92
48
93 def _find(self, tests, obj, name, module, source_lines, globs, seen):
49 return test
94 """
95 Find tests for the given object and any contained objects, and
96 add them to `tests`.
97 """
98 print('_find for:', obj, name, module) # dbg
99 if bool(getattr(obj, "__skip_doctest__", False)):
100 #print 'SKIPPING DOCTEST FOR:',obj # dbg
101 obj = DocTestSkip(obj)
102
103 doctest.DocTestFinder._find(self,tests, obj, name, module,
104 source_lines, globs, seen)
105
106 # Below we re-run pieces of the above method with manual modifications,
107 # because the original code is buggy and fails to correctly identify
108 # doctests in extension modules.
109
110 # Local shorthands
111 from inspect import isroutine, isclass
112
113 # Look for tests in a module's contained objects.
114 if inspect.ismodule(obj) and self._recurse:
115 for valname, val in obj.__dict__.items():
116 valname1 = '%s.%s' % (name, valname)
117 if ( (isroutine(val) or isclass(val))
118 and self._from_module(module, val) ):
119
120 self._find(tests, val, valname1, module, source_lines,
121 globs, seen)
122
123 # Look for tests in a class's contained objects.
124 if inspect.isclass(obj) and self._recurse:
125 #print 'RECURSE into class:',obj # dbg
126 for valname, val in obj.__dict__.items():
127 # Special handling for staticmethod/classmethod.
128 if isinstance(val, staticmethod):
129 val = getattr(obj, valname)
130 if isinstance(val, classmethod):
131 val = getattr(obj, valname).__func__
132
133 # Recurse to methods, properties, and nested classes.
134 if ((inspect.isfunction(val) or inspect.isclass(val) or
135 inspect.ismethod(val) or
136 isinstance(val, property)) and
137 self._from_module(module, val)):
138 valname = '%s.%s' % (name, valname)
139 self._find(tests, val, valname, module, source_lines,
140 globs, seen)
141
50
142
51
143 class IPDoctestOutputChecker(doctest.OutputChecker):
52 class IPDoctestOutputChecker(doctest.OutputChecker):
General Comments 0
You need to be logged in to leave comments. Login now