bskinn / stdio-mgr

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

May need to rewrite stdio_mgr as explicit class, to allow better curation of stream contents on error in managed code? #10

Closed bskinn closed 5 years ago

bskinn commented 6 years ago

Definitely don't want stdio_mgr to swallow any information in the enclosing code that might help to diagnose an error.

Exception information should propagate back out without a problem, since the traceback & message &c. are encapsulated in the Exception that was raised.

However, the input/output itself may be informative, and as currently written that content is just dumped when the streams are closed.

Could either:

  1. Push the stdout/stderr mock streams to their respective real streams on error, and do... something?... with the contents of the stdin mock; or,
  2. Implement a custom Exception that holds the contents of all three streams (or--all three streams themselves), and raise from whatever exception was raised.
jayvdb commented 5 years ago

Another benefit of having a class is that it can have a constructor, allowing some args of a more global nature to be provided there.

A good example is a debugging switch https://github.com/bskinn/stdio-mgr/issues/43

Also it allows nested managers to re-use the same objects; untested hacking pseudocode

class StdIoManager():
   def __init__(in=None, out=None, err=None, debug=False):
       if not in: in = sys.stdin
       if not out: in = sys.stdout
       if not err: in = sys.stdout
       ...

def managed_io_action(stdio_manager):
    with stdio_manager(close=False) as (i, o, e):
        ...

        nested_stdio_manager = StdIoManager()
        with nested_stdio_manager() as (not_i, not_o, not_e):
            ...
        assert not_i.closed

        assert not i.closed

real_stdio_manager = RealStdIoManager()

with real_stdio_manager(close=False) as (i, o, e):
    ...
    managed_io_action(real_stdio_manager)

    debug_stdio_manager = StdIoManager(i, o, e)
    with debug_stdio_manager(close=False) as (i2, o2, e2):
        ...
bskinn commented 5 years ago

@jayvdb, the more I think about this, the more likely it seems that it will either be desirable, or outright necessary, to make this conversion from stdio_mgr as a decorated function to a full class. (I really like the debug logging switch in particular -- that's definitely a priority.)

I would rather make the change now, as part of bumping to 2.0, rather than waiting and then (1) potentially having to make the change to a class with a lot more surrounding code and (2) having to bump again to 3.0.

If you concur, would you work on this next? I'm envisioning an initial PR for now that's a "no-op" -- just converting from stdio_mgr to StdioMgr, no new features. The enhancements you mention above and have identified in, e.g., #43, would then come in subsequent development.

I'd plan to work on #29 in parallel.

jayvdb commented 5 years ago

Sure, you can assign it to me, but I wont be able to get a OR up until the end of the weekend.

bskinn commented 5 years ago

Should retain stdio_mgr for backward compatibility. Probably best done as a factory method, generating a StdioMgr instance?