Skip to content

Commit e3e57a7

Browse files
authored
Merge pull request #5083 from blueyed/capture-_suspended
capture: store _state
2 parents 79d5fc3 + 698c4e7 commit e3e57a7

File tree

2 files changed

+37
-9
lines changed

2 files changed

+37
-9
lines changed

src/_pytest/capture.py

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,7 @@ def __getattr__(self, name):
456456

457457
class MultiCapture(object):
458458
out = err = in_ = None
459+
_state = None
459460

460461
def __init__(self, out=True, err=True, in_=True, Capture=None):
461462
if in_:
@@ -466,9 +467,16 @@ def __init__(self, out=True, err=True, in_=True, Capture=None):
466467
self.err = Capture(2)
467468

468469
def __repr__(self):
469-
return "<MultiCapture out=%r err=%r in_=%r>" % (self.out, self.err, self.in_)
470+
return "<MultiCapture out=%r err=%r in_=%r _state=%r _in_suspended=%r>" % (
471+
self.out,
472+
self.err,
473+
self.in_,
474+
self._state,
475+
getattr(self, "_in_suspended", "<UNSET>"),
476+
)
470477

471478
def start_capturing(self):
479+
self._state = "started"
472480
if self.in_:
473481
self.in_.start()
474482
if self.out:
@@ -486,6 +494,7 @@ def pop_outerr_to_orig(self):
486494
return out, err
487495

488496
def suspend_capturing(self, in_=False):
497+
self._state = "suspended"
489498
if self.out:
490499
self.out.suspend()
491500
if self.err:
@@ -495,6 +504,7 @@ def suspend_capturing(self, in_=False):
495504
self._in_suspended = True
496505

497506
def resume_capturing(self):
507+
self._state = "resumed"
498508
if self.out:
499509
self.out.resume()
500510
if self.err:
@@ -505,9 +515,9 @@ def resume_capturing(self):
505515

506516
def stop_capturing(self):
507517
""" stop capturing and reset capturing streams """
508-
if hasattr(self, "_reset"):
518+
if self._state == "stopped":
509519
raise ValueError("was already stopped")
510-
self._reset = True
520+
self._state = "stopped"
511521
if self.out:
512522
self.out.done()
513523
if self.err:
@@ -535,6 +545,7 @@ class FDCaptureBinary(object):
535545
"""
536546

537547
EMPTY_BUFFER = b""
548+
_state = None
538549

539550
def __init__(self, targetfd, tmpfile=None):
540551
self.targetfd = targetfd
@@ -561,9 +572,10 @@ def __init__(self, targetfd, tmpfile=None):
561572
self.tmpfile_fd = tmpfile.fileno()
562573

563574
def __repr__(self):
564-
return "<FDCapture %s oldfd=%s>" % (
575+
return "<FDCapture %s oldfd=%s _state=%r>" % (
565576
self.targetfd,
566577
getattr(self, "targetfd_save", None),
578+
self._state,
567579
)
568580

569581
def start(self):
@@ -574,6 +586,7 @@ def start(self):
574586
raise ValueError("saved filedescriptor not valid anymore")
575587
os.dup2(self.tmpfile_fd, self.targetfd)
576588
self.syscapture.start()
589+
self._state = "started"
577590

578591
def snap(self):
579592
self.tmpfile.seek(0)
@@ -590,14 +603,17 @@ def done(self):
590603
os.close(targetfd_save)
591604
self.syscapture.done()
592605
_attempt_to_close_capture_file(self.tmpfile)
606+
self._state = "done"
593607

594608
def suspend(self):
595609
self.syscapture.suspend()
596610
os.dup2(self.targetfd_save, self.targetfd)
611+
self._state = "suspended"
597612

598613
def resume(self):
599614
self.syscapture.resume()
600615
os.dup2(self.tmpfile_fd, self.targetfd)
616+
self._state = "resumed"
601617

602618
def writeorg(self, data):
603619
""" write to original file descriptor. """
@@ -625,6 +641,7 @@ def snap(self):
625641
class SysCapture(object):
626642

627643
EMPTY_BUFFER = str()
644+
_state = None
628645

629646
def __init__(self, fd, tmpfile=None):
630647
name = patchsysdict[fd]
@@ -637,8 +654,17 @@ def __init__(self, fd, tmpfile=None):
637654
tmpfile = CaptureIO()
638655
self.tmpfile = tmpfile
639656

657+
def __repr__(self):
658+
return "<SysCapture %s _old=%r, tmpfile=%r _state=%r>" % (
659+
self.name,
660+
self._old,
661+
self.tmpfile,
662+
self._state,
663+
)
664+
640665
def start(self):
641666
setattr(sys, self.name, self.tmpfile)
667+
self._state = "started"
642668

643669
def snap(self):
644670
res = self.tmpfile.getvalue()
@@ -650,12 +676,15 @@ def done(self):
650676
setattr(sys, self.name, self._old)
651677
del self._old
652678
_attempt_to_close_capture_file(self.tmpfile)
679+
self._state = "done"
653680

654681
def suspend(self):
655682
setattr(sys, self.name, self._old)
683+
self._state = "suspended"
656684

657685
def resume(self):
658686
setattr(sys, self.name, self.tmpfile)
687+
self._state = "resumed"
659688

660689
def writeorg(self, data):
661690
self._old.write(data)

testing/test_capture.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1243,25 +1243,24 @@ def test_stdcapture_fd_invalid_fd(self, testdir):
12431243
from _pytest import capture
12441244
12451245
def StdCaptureFD(out=True, err=True, in_=True):
1246-
return capture.MultiCapture(out, err, in_,
1247-
Capture=capture.FDCapture)
1246+
return capture.MultiCapture(out, err, in_, Capture=capture.FDCapture)
12481247
12491248
def test_stdout():
12501249
os.close(1)
12511250
cap = StdCaptureFD(out=True, err=False, in_=False)
1252-
assert repr(cap.out) == "<FDCapture 1 oldfd=None>"
1251+
assert repr(cap.out) == "<FDCapture 1 oldfd=None _state=None>"
12531252
cap.stop_capturing()
12541253
12551254
def test_stderr():
12561255
os.close(2)
12571256
cap = StdCaptureFD(out=False, err=True, in_=False)
1258-
assert repr(cap.err) == "<FDCapture 2 oldfd=None>"
1257+
assert repr(cap.err) == "<FDCapture 2 oldfd=None _state=None>"
12591258
cap.stop_capturing()
12601259
12611260
def test_stdin():
12621261
os.close(0)
12631262
cap = StdCaptureFD(out=False, err=False, in_=True)
1264-
assert repr(cap.in_) == "<FDCapture 0 oldfd=None>"
1263+
assert repr(cap.in_) == "<FDCapture 0 oldfd=None _state=None>"
12651264
cap.stop_capturing()
12661265
"""
12671266
)

0 commit comments

Comments
 (0)