bskinn / stdio-mgr

Context manager for mocking/wrapping stdin/stdout/stderr
MIT License
14 stars 4 forks source link

Add functionality for selective mocking/wrapping of individual streams or stream combinations #4

Open bskinn opened 6 years ago

bskinn commented 6 years ago

Only stdout, or only stderr; or stdout and stdin but not stderr; etc.

contextlib in the standard library already exists for singly mocking stdout and stderr, but there's potential for stdio_mgr to represent a more concise and customizeable means for mocking multiple streams. The stdin mock appears to be a novel capability, though?

jayvdb commented 5 years ago

For this, I would like to explore either

  1. always conceptualising the three as a discrete object, and using class methods to instantiate different tuples, or
  2. borrowing semantics from Popen and how it allows the three streams to be instantiated & managed.
bskinn commented 5 years ago

For this, I would like to explore either

  1. always conceptualising the three as a discrete object, and using class methods to instantiate different tuples, or

For this, would a user instantiate cm, use instance methods on cm to configure the desired redirection, and then enter the context?

>>> cm = StdioManager()
>>> cm.tee_stdin(cm.stdout)
>>> with cm:
...     ...
  1. borrowing semantics from Popen and how it allows the three streams to be instantiated & managed.

Do you mean syntax like the the Popen(..., stderr=subprocess.STDOUT)? (TBH, I'm still unclear on what subprocess.PIPE actually does.... <goes and reads the docs> Ohh, that connects pipes to the child process so that the output can be loaded into the communicate() return value in the parent.)

Separately, maybe it would make sense to have at least three redirection modes... tee-on-read, tee-on-write, and pipe? ('pipe' would pass anything written to the stream through to the target stream, without retaining an internal copy, as in bash's 2>&1.)

jayvdb commented 5 years ago

For this, would a user instantiate cm, use instance methods on cm to configure the desired redirection, and then enter the context?

Yes, like the example you have, but I am envisioning also the following for creation of new streams.

>>> with _current_stdio().tee(stdin="foo") as cm:
...     assert cm.stdout.getvalue() == "foo\n"

>>> with _current_stdio().tee(stdout=False, stderr=True) as cm:
...     print("foo")
...     assert cm.stderr.getvalue() == "foo\n"

Do you mean syntax like the the Popen(..., stderr=subprocess.STDOUT)?

Yes, specifically creating constants for the three streams, so non-default behaviour is written in semi-literate code.

Separately, maybe it would make sense to have at least three redirection modes... tee-on-read, tee-on-write, and pipe?

Sounds good. Thinking out loud ...

>>> with _current_stdio().pipe(in=stdio_mgr.STDIN, out=stdio_mgr.STDERR) as cm:
...     print("foo")
...     assert cm.stderr.getvalue() == "foo\n"