Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 3926d6d

Browse files
committed
Local checkpoint of changes to testing machinery. Work in progress.
1 parent 5c27948 commit 3926d6d

5 files changed

Lines changed: 132 additions & 81 deletions

File tree

IPython/testing/plugin/Makefile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,13 @@ dtest: plugin dtexample.py
88
nosetests -vs --with-ipdoctest --doctest-tests --doctest-extension=txt \
99
dtexample.py
1010

11+
# Note: this test is double counting!!!
12+
rtest: plugin dtexample.py
13+
nosetests -vs --with-ipdoctest --doctest-tests test_refs.py
14+
1115
test: plugin dtexample.py
1216
nosetests -vs --with-ipdoctest --doctest-tests --doctest-extension=txt \
13-
dtexample.py test*.txt
17+
dtexample.py test*.py test*.txt
1418

1519
deb: plugin dtexample.py
1620
nosetests -vs --with-ipdoctest --doctest-tests --doctest-extension=txt \

IPython/testing/plugin/dtexample.py

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -71,37 +71,47 @@ def ipfunc():
7171
return 'ipfunc'
7272

7373

74-
def ranfunc():
75-
"""A function with some random output.
74+
if 1:
75+
def ranfunc():
76+
"""A function with some random output.
7677
77-
>>> 1+3 #random
78-
junk goes here...
78+
>>> 1+3
79+
junk goes here... #random
7980
80-
>>> 1+3
81-
4
81+
>>> 1+3
82+
4
8283
83-
>>> 1+2 #random
84-
again, anything goes
85-
"""
86-
return 'ranfunc'
84+
>>> 1+2
85+
again, anything goes #random
86+
if multiline, the random mark is only needed in teh first line.
8787
88+
>>> 1+3
89+
4
8890
89-
def ranf2():
90-
"""A function whose examples are all all random
91+
>>> ranfunc()
92+
'ranfunc'
93+
"""
94+
return 'ranfunc'
9195

92-
Examples:
9396

94-
#all-random
97+
if 0:
98+
def ranf2():
99+
"""A function whose examples'output are all to be ignored.
95100
96-
>>> 1+3 #random
97-
junk goes here...
101+
Examples:
98102
99-
>>> 1+3
100-
klasdfj;
103+
#all-random
101104
102-
>>> 1+2 #random
103-
again, anything goes
105+
>>> 1+3
106+
junk goes here...
104107
105-
"""
106-
return 'ranf2'
108+
>>> 1+3
109+
klasdfj;
110+
111+
>>> 1+2
112+
again, anything goes
113+
blah...
114+
115+
"""
116+
return 'ranf2'
107117

IPython/testing/plugin/ipdoctest.py

Lines changed: 67 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,22 @@ def _find(self, tests, obj, name, module, source_lines, globs, seen):
214214
globs, seen)
215215

216216

217+
# second-chance checker; if the default comparison doesn't
218+
# pass, then see if the expected output string contains flags that
219+
# tell us to ignore the output
220+
class IPDoctestOutputChecker(doctest.OutputChecker):
221+
def check_output(self, want, got, optionflags):
222+
#print '*** My Checker!' # dbg
223+
224+
ret = doctest.OutputChecker.check_output(self, want, got,
225+
optionflags)
226+
if not ret:
227+
if "#random" in want:
228+
return True
229+
230+
return ret
231+
232+
217233
class DocTestCase(doctests.DocTestCase):
218234
"""Proxy for DocTestCase: provides an address() method that
219235
returns the correct address for the doctest case. Otherwise
@@ -227,26 +243,23 @@ class DocTestCase(doctests.DocTestCase):
227243
# Subclass nose.plugins.doctests.DocTestCase to work around a bug in
228244
# its constructor that blocks non-default arguments from being passed
229245
# down into doctest.DocTestCase
230-
## def __init__(self, test, optionflags=0, setUp=None, tearDown=None,
231-
## checker=None, obj=None, result_var='_'):
232-
## self._result_var = result_var
233-
## self._nose_obj = obj
234-
## doctest.DocTestCase.__init__(self, test,
235-
## optionflags=optionflags,
236-
## setUp=setUp, tearDown=tearDown,
237-
## checker=checker)
238-
239-
# doctests loaded via find(obj) omit the module name
240-
# so we need to override id, __repr__ and shortDescription
241-
# bonus: this will squash a 2.3 vs 2.4 incompatiblity
242-
def id(self):
243-
name = self._dt_test.name
244-
filename = self._dt_test.filename
245-
if filename is not None:
246-
pk = getpackage(filename)
247-
if pk is not None and not name.startswith(pk):
248-
name = "%s.%s" % (pk, name)
249-
return name
246+
247+
def __init__(self, test, optionflags=0, setUp=None, tearDown=None,
248+
checker=None, obj=None, result_var='_'):
249+
self._result_var = result_var
250+
doctests.DocTestCase.__init__(self, test,
251+
optionflags=optionflags,
252+
setUp=setUp, tearDown=tearDown,
253+
checker=checker)
254+
# 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
256+
# means it never gets passed the right arguments.
257+
258+
self._dt_optionflags = optionflags
259+
self._dt_checker = checker
260+
self._dt_test = test
261+
self._dt_setUp = setUp
262+
self._dt_tearDown = tearDown
250263

251264

252265

@@ -325,8 +338,8 @@ def parse(self, string, name='<string>'):
325338
argument `name` is a name identifying this string, and is only
326339
used for error messages.
327340
"""
328-
329-
print 'Parse string:\n',string # dbg
341+
342+
#print 'Parse string:\n',string # dbg
330343

331344
string = string.expandtabs()
332345
# If all lines begin with the same indentation, then strip it.
@@ -390,9 +403,6 @@ def parse(self, string, name='<string>'):
390403
charno = m.end()
391404
# Add any remaining post-example text to `output`.
392405
output.append(string[charno:])
393-
394-
#print 'OUT:',output # dbg
395-
396406
return output
397407

398408
def _parse_example(self, m, name, lineno,ip2py=False):
@@ -517,8 +527,39 @@ def loadTestsFromExtensionModule(self,filename):
517527
sys.path.pop()
518528
return tests
519529

530+
# NOTE: the method below is almost a copy of the original one in nose, with
531+
# a few modifications to control output checking.
532+
533+
def loadTestsFromModule(self, module):
534+
#print 'lTM',module # dbg
535+
536+
if not self.matches(module.__name__):
537+
log.debug("Doctest doesn't want module %s", module)
538+
return
539+
tests = self.finder.find(module)
540+
if not tests:
541+
return
542+
tests.sort()
543+
module_file = module.__file__
544+
if module_file[-4:] in ('.pyc', '.pyo'):
545+
module_file = module_file[:-1]
546+
for test in tests:
547+
if not test.examples:
548+
continue
549+
if not test.filename:
550+
test.filename = module_file
551+
552+
#yield DocTestCase(test)
553+
554+
# always use whitespace and ellipsis options
555+
optionflags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
556+
checker = IPDoctestOutputChecker()
557+
yield DocTestCase(test,
558+
optionflags=optionflags,
559+
checker=checker)
560+
520561
def loadTestsFromFile(self, filename):
521-
print 'lTF',filename # dbg
562+
#print 'lTF',filename # dbg
522563

523564
if is_extension_module(filename):
524565
for t in self.loadTestsFromExtensionModule(filename):
@@ -571,38 +612,6 @@ def wantFile(self,filename):
571612
else:
572613
return doctests.Doctest.wantFile(self,filename)
573614

574-
# NOTE: the method below is almost a copy of the original one in nose, with
575-
# a few modifications to control output checking.
576-
577-
def loadTestsFromModule(self, module):
578-
#print 'lTM',module # dbg
579-
580-
if not self.matches(module.__name__):
581-
log.debug("Doctest doesn't want module %s", module)
582-
return
583-
tests = self.finder.find(module)
584-
if not tests:
585-
return
586-
tests.sort()
587-
module_file = module.__file__
588-
if module_file[-4:] in ('.pyc', '.pyo'):
589-
module_file = module_file[:-1]
590-
for test in tests:
591-
if not test.examples:
592-
continue
593-
if not test.filename:
594-
test.filename = module_file
595-
yield DocTestCase(test)
596-
597-
# always use whitespace and ellipsis options
598-
optionflags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
599-
#checker = DoctestOutputChecker()
600-
checker = None
601-
yield DocTestCase(test,
602-
optionflags=optionflags,
603-
checker=checker)
604-
605-
606615

607616
class IPythonDoctest(ExtensionDoctest):
608617
"""Nose Plugin that supports doctests in extension modules.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
"""Simple script to show reference holding behavior.
2+
3+
This is used by a companion test case.
4+
"""
5+
6+
import gc
7+
8+
class C(object):
9+
def __del__(self):
10+
print 'deleting object...'
11+
12+
c = C()
13+
14+
c_refs = gc.get_referrers(c)
15+
ref_ids = map(id,c_refs)
16+
17+
print 'c referrers:',map(type,c_refs)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
def test_refs():
2+
"""DocTest reference holding issues when running scripts.
3+
4+
In [32]: run show_refs.py
5+
c referrers: [<type 'dict'>]
6+
7+
In [33]: map(type,gc.get_referrers(c))
8+
Out[33]: [<type 'dict'>]
9+
10+
"""
11+
pass

0 commit comments

Comments
 (0)