* fix too-many-open files issue with fd based io-capturing
* workaround 2.6 issue with pickling of objects from global conftest.py files --HG-- branch : trunk
This commit is contained in:
parent
ed216e77d0
commit
e61e7b1e26
|
@ -22,14 +22,14 @@ class Capture(object):
|
||||||
call = classmethod(call)
|
call = classmethod(call)
|
||||||
|
|
||||||
def reset(self):
|
def reset(self):
|
||||||
""" reset sys.stdout and sys.stderr
|
""" reset sys.stdout and sys.stderr and return captured output
|
||||||
|
as strings and restore sys.stdout/err.
|
||||||
returns a tuple of file objects (out, err) for the captured
|
|
||||||
data
|
|
||||||
"""
|
"""
|
||||||
outfile, errfile = self.done()
|
x, y = self.done()
|
||||||
return outfile.read(), errfile.read()
|
outerr = x.read(), y.read()
|
||||||
|
x.close()
|
||||||
|
y.close()
|
||||||
|
return outerr
|
||||||
|
|
||||||
class StdCaptureFD(Capture):
|
class StdCaptureFD(Capture):
|
||||||
""" This class allows to capture writes to FD1 and FD2
|
""" This class allows to capture writes to FD1 and FD2
|
||||||
|
@ -58,11 +58,14 @@ class StdCaptureFD(Capture):
|
||||||
|
|
||||||
def done(self):
|
def done(self):
|
||||||
""" return (outfile, errfile) and stop capturing. """
|
""" return (outfile, errfile) and stop capturing. """
|
||||||
outfile = errfile = emptyfile
|
|
||||||
if hasattr(self, 'out'):
|
if hasattr(self, 'out'):
|
||||||
outfile = self.out.done()
|
outfile = self.out.done()
|
||||||
|
else:
|
||||||
|
outfile = StringIO()
|
||||||
if hasattr(self, 'err'):
|
if hasattr(self, 'err'):
|
||||||
errfile = self.err.done()
|
errfile = self.err.done()
|
||||||
|
else:
|
||||||
|
errfile = StringIO()
|
||||||
if hasattr(self, '_oldin'):
|
if hasattr(self, '_oldin'):
|
||||||
oldsys, oldfd = self._oldin
|
oldsys, oldfd = self._oldin
|
||||||
os.dup2(oldfd, 0)
|
os.dup2(oldfd, 0)
|
||||||
|
@ -94,15 +97,9 @@ class StdCapture(Capture):
|
||||||
self.oldin = sys.stdin
|
self.oldin = sys.stdin
|
||||||
sys.stdin = self.newin = DontReadFromInput()
|
sys.stdin = self.newin = DontReadFromInput()
|
||||||
|
|
||||||
def reset(self):
|
|
||||||
""" return captured output as strings and restore sys.stdout/err."""
|
|
||||||
x, y = self.done()
|
|
||||||
return x.read(), y.read()
|
|
||||||
|
|
||||||
def done(self):
|
def done(self):
|
||||||
""" return (outfile, errfile) and stop capturing. """
|
""" return (outfile, errfile) and stop capturing. """
|
||||||
o,e = sys.stdout, sys.stderr
|
o,e = sys.stdout, sys.stderr
|
||||||
outfile = errfile = emptyfile
|
|
||||||
if self._out:
|
if self._out:
|
||||||
try:
|
try:
|
||||||
sys.stdout = self.oldout
|
sys.stdout = self.oldout
|
||||||
|
@ -111,6 +108,8 @@ class StdCapture(Capture):
|
||||||
del self.oldout
|
del self.oldout
|
||||||
outfile = self.newout
|
outfile = self.newout
|
||||||
outfile.seek(0)
|
outfile.seek(0)
|
||||||
|
else:
|
||||||
|
outfile = StringIO()
|
||||||
if self._err:
|
if self._err:
|
||||||
try:
|
try:
|
||||||
sys.stderr = self.olderr
|
sys.stderr = self.olderr
|
||||||
|
@ -119,6 +118,8 @@ class StdCapture(Capture):
|
||||||
del self.olderr
|
del self.olderr
|
||||||
errfile = self.newerr
|
errfile = self.newerr
|
||||||
errfile.seek(0)
|
errfile.seek(0)
|
||||||
|
else:
|
||||||
|
errfile = StringIO()
|
||||||
if self._in:
|
if self._in:
|
||||||
sys.stdin = self.oldin
|
sys.stdin = self.oldin
|
||||||
return outfile, errfile
|
return outfile, errfile
|
||||||
|
@ -144,5 +145,4 @@ except AttributeError:
|
||||||
else:
|
else:
|
||||||
devnullpath = '/dev/null'
|
devnullpath = '/dev/null'
|
||||||
|
|
||||||
emptyfile = StringIO()
|
|
||||||
|
|
||||||
|
|
|
@ -61,11 +61,7 @@ def pytest_runtest_call(item):
|
||||||
item.runtest()
|
item.runtest()
|
||||||
|
|
||||||
def pytest_runtest_makereport(item, call):
|
def pytest_runtest_makereport(item, call):
|
||||||
if isinstance(call, str):
|
return ItemTestReport(item, call.excinfo, call.when, call.outerr)
|
||||||
# crashed item
|
|
||||||
return ItemTestReport(item, excinfo=call, when="???")
|
|
||||||
else:
|
|
||||||
return ItemTestReport(item, call.excinfo, call.when, call.outerr)
|
|
||||||
|
|
||||||
def pytest_runtest_teardown(item):
|
def pytest_runtest_teardown(item):
|
||||||
item.config._setupstate.teardown_exact(item)
|
item.config._setupstate.teardown_exact(item)
|
||||||
|
@ -101,10 +97,15 @@ class RuntestHookCall:
|
||||||
self.outerr = capture.reset()
|
self.outerr = capture.reset()
|
||||||
|
|
||||||
def forked_run_report(item):
|
def forked_run_report(item):
|
||||||
|
# for now, we run setup/teardown in the subprocess
|
||||||
|
# XXX optionally allow sharing of setup/teardown
|
||||||
EXITSTATUS_TESTEXIT = 4
|
EXITSTATUS_TESTEXIT = 4
|
||||||
from py.__.test.dist.mypickle import ImmutablePickler
|
from py.__.test.dist.mypickle import ImmutablePickler
|
||||||
ipickle = ImmutablePickler(uneven=0)
|
ipickle = ImmutablePickler(uneven=0)
|
||||||
ipickle.selfmemoize(item.config)
|
ipickle.selfmemoize(item.config)
|
||||||
|
# XXX workaround the issue that 2.6 cannot pickle
|
||||||
|
# instances of classes defined in global conftest.py files
|
||||||
|
ipickle.selfmemoize(item)
|
||||||
def runforked():
|
def runforked():
|
||||||
try:
|
try:
|
||||||
reports = runtestprotocol(item, log=False)
|
reports = runtestprotocol(item, log=False)
|
||||||
|
|
Loading…
Reference in New Issue