Skip to content

Refactor Capture classes: move/rename CaptureIO classes #6765

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 5, 2020

Conversation

blueyed
Copy link
Contributor

@blueyed blueyed commented Feb 19, 2020

Pulled out of #6671

@blueyed blueyed force-pushed the capture-refactor-1 branch 2 times, most recently from db5feae to f2a3b1d Compare February 21, 2020 13:28
@blueyed blueyed changed the title Refactor Capture classes Refactor Capture classes: move/rename CaptureIO classes Feb 21, 2020
Copy link
Member

@bluetech bluetech left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense to me to move from compat.

I left a couple of comments on the other changes.

return self.buffer.getvalue().decode("UTF-8")


class PassthroughCaptureIO(CaptureIO):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the previous name was more clear. This new name sounds like a "no-op capture" (i.e. just passthough without capturing).

Alternative name would be TeeCaptureIO.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TeeCaptureIO sounds good - I've mainly wanted to have CaptureIO at the end.

else:
tmpfile = CaptureAndPassthroughIO(self._old)
self.tmpfile = tmpfile
def __init__(self, fd: int) -> None:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure this is really better, still duplicates some logic, and now it relies on SysCaptureBinary implementation instead of being independent.

Two possible alternatives, both are not ideal too but a bit better IMO:

  1. Add a passthrough: bool argument to SysCaptureBinary and use PassthroughCaptureIO if true.
  2. Add class attribute CaptureIOClass: Type[CaptureIO] = CaptureIO to SysCaptureBinary and use that in __init__, and override to PassthroughCaptureIO in TeeSysCapture.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I think it is quite simple/good.
Keep in mind that the "old" is only used for an assert, and can be removed.
As for your 2nd suggestion: this is basically what passing in tmpfile does, isn't it?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keep in mind that the "old" is only used for an assert, and can be removed.

You mean _old right?

As for your 2nd suggestion: this is basically what passing in tmpfile does, isn't it?

<offtopic>

The tmpfile argument exists for by FDCaptureBinary. I was surprised initially to see that FDCaptureBinary uses SysCapture under the hood. Turns out FDCaptureBinary not only redirects the FDs to a tempfile, it also additionally patches the sys file objects to redirect to the tempfile (this is where the argument is needed). It seemed redundant to me -- if we already redirect the FDs, there is no need to patch sys since the data will reach the tempfile anyway. So I tried to remove the sys patching from FDCaptureBinary. It actually works fine, but the problem is the flushing - if we don't patch sys, then data that remains in the file object buffer doesn't end up captured, i.e. an explicit flush() is sometimes needed before the capture fixture can be examined.

If backward compatibility wasn't a concern, I think that this is actually the better behavior for capfd. The implicit flush()s prevent a test from being able to verify that data is actually present in the underlying file at a point of time.

But, we can't break it now... So maybe it makes sense to add a new "fdonly" mode, and make fd an alias for "fd+sys" mode (for clarity).

</offtopic>

TL;DR: I think the tmpfile argument should go away eventually, so wouldn't want to add new uses for it...

@bluetech
Copy link
Member

bluetech commented May 5, 2020

So I think moving the Capture classes over to capture.py makes some obvious sense. The Tee change however makes things slightly worse IMO. I have some WIP work on capture which refactors it as well.

So to move forward on this PR, I'll remove the Tee changes, but keep the move.

Move {Passthrough,CaptureIO} to capture module, and rename Passthrough
-> Tee to match the existing terminology.

Co-authored-by: Ran Benita <[email protected]>
@bluetech bluetech force-pushed the capture-refactor-1 branch from f2a3b1d to 7647d1c Compare May 5, 2020 18:26
@bluetech bluetech merged commit b4be6cd into pytest-dev:master May 5, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants