diff --git a/_pytest/capture.py b/_pytest/capture.py index a4171f0fa84..21c72405f3d 100644 --- a/_pytest/capture.py +++ b/_pytest/capture.py @@ -19,7 +19,6 @@ patchsysdict = {0: 'stdin', 1: 'stdout', 2: 'stderr'} - def pytest_addoption(parser): group = parser.getgroup("general") group._addoption( @@ -211,7 +210,8 @@ def readouterr(self): @contextlib.contextmanager def disabled(self): - capmanager = self.request.config.pluginmanager.getplugin('capturemanager') + capmanager = self.request.config.pluginmanager.getplugin( + 'capturemanager') capmanager.suspendcapture_item(self.request.node, "call", in_=True) try: yield @@ -248,7 +248,10 @@ def __init__(self, buffer, encoding): def write(self, obj): if isinstance(obj, unicode): obj = obj.encode(self.encoding, "replace") - self.buffer.write(obj) + try: + self.buffer.write(obj) + except OSError: + self.buffer = open(os.devnull, "wb+") def writelines(self, linelist): data = ''.join(linelist) @@ -371,9 +374,14 @@ def start(self): self.syscapture.start() def snap(self): - f = self.tmpfile - f.seek(0) - res = f.read() + try: + f = self.tmpfile + f.seek(0) + res = f.read() + except OSError: + self.tmpfile = open(os.devnull, "r") + self.tmpfile_fd = self.tmpfile.fileno() + res = '' if res: enc = getattr(f, "encoding", None) if enc and isinstance(res, bytes): @@ -388,9 +396,10 @@ def done(self): seeked to position zero. """ targetfd_save = self.__dict__.pop("targetfd_save") os.dup2(targetfd_save, self.targetfd) - os.close(targetfd_save) + # os.close(targetfd_save) self.syscapture.done() - self.tmpfile.close() + # self.tmpfile.close() + raise Exception("Done method called!") def suspend(self): self.syscapture.suspend() @@ -398,7 +407,12 @@ def suspend(self): def resume(self): self.syscapture.resume() - os.dup2(self.tmpfile_fd, self.targetfd) + try: + os.dup2(self.tmpfile_fd, self.targetfd) + except OSError: + self.tmpfile = open(os.devnull, "r") + self.tmpfile_fd = self.tmpfile.fileno() + self.targetfd = open(os.devnull, "r").fileno() def writeorg(self, data): """ write to original file descriptor. """ @@ -432,7 +446,8 @@ def snap(self): def done(self): setattr(sys, self.name, self._old) del self._old - self.tmpfile.close() + # self.tmpfile.close() + raise Exception("Sys method called!") def suspend(self): setattr(sys, self.name, self._old) diff --git a/changelog/2633.bugfix b/changelog/2633.bugfix new file mode 100644 index 00000000000..08c4201c47d --- /dev/null +++ b/changelog/2633.bugfix @@ -0,0 +1,2 @@ +In some cases on windows stderr capturing may fail. Pytest now +attempts to recover from a capturing failure. \ No newline at end of file diff --git a/testing/test_capture.py b/testing/test_capture.py index 4dd5d8e099b..387aa8ea777 100644 --- a/testing/test_capture.py +++ b/testing/test_capture.py @@ -1159,3 +1159,6 @@ def test_pickling_and_unpickling_enocded_file(): ef = capture.EncodedFile(None, None) ef_as_str = pickle.dumps(ef) pickle.loads(ef_as_str) + +def test_closed_handle(): + sys.stderr.close()