Skip to main content

Python context manager for mocking/wrapping stdin/stdout/stderr

https://travis-ci.org/bskinn/stdio-mgr.svg?branch=dev https://codecov.io/gh/bskinn/stdio-mgr/branch/dev/graph/badge.svg https://img.shields.io/pypi/v/stdio_mgr.svg https://img.shields.io/pypi/pyversions/stdio-mgr.svg https://img.shields.io/github/license/mashape/apistatus.svg

Have a CLI Python application?

Want to automate testing of the actual console input & output of your user-facing components?

stdio Manager can help.

While some functionality here is more or less duplicative of redirect_stdout and redirect_stderr in contextlib within the standard library, it provides (i) a much more concise way to mock both stdout and stderr at the same time, and (ii) a mechanism for mocking stdin, which is not available in contextlib.

First, install:

$ pip install stdio-mgr

Then use!

All of the below examples assume stdio_mgr has already been imported via:

from stdio_mgr import stdio_mgr

Mock stdout:

>>> with stdio_mgr() as (in_, out_, err_):
...     print('foobar')
...     out_cap = out_.getvalue()
>>> out_cap
'foobar\n'
>>> in_.closed and out_.closed and err_.closed
True

By default print appends a newline after each argument, which is why out_cap is 'foobar\n' and not just 'foobar'.

As currently implemented, stdio_mgr closes all three mocked streams upon exiting the managed context.

Mock stderr:

>>> import warnings
>>> with stdio_mgr() as (in_, out_, err_):
...     warnings.warn("'foo' has no 'bar'")
...     err_cap = err_.getvalue()
>>> err_cap
"...README.rst:2: UserWarning: 'foo' has no 'bar'\n  =============\n"

Mock stdin:

The simulated user input has to be pre-loaded to the mocked stream. Be sure to include newlines in the input to correspond to each mocked Enter keypress! Otherwise, input will hang, waiting for a newline that will never come.

If the entirety of the input is known in advance, it can just be provided as an argument to stdio_mgr. Otherwise, .append() mocked input to in_ within the managed context as needed:

>>> with stdio_mgr('foobar\n') as (in_, out_, err_):
...     print('baz')
...     in_cap = input('??? ')
...
...     _ = in_.append(in_cap[:3] + '\n')
...     in_cap2 = input('??? ')
...
...     out_cap = out_.getvalue()
>>> in_cap
'foobar'
>>> in_cap2
'foo'
>>> out_cap
'baz\n??? foobar\n??? foo\n'

The _ = assignment suppresses printing of the return value from the in_.append() call–otherwise, it would be interleaved in out_cap, since this example is shown for an interactive context. For non-interactive execution, as with unittest, pytest, etc., these ‘muting’ assignments should not be necessary.

Both the '??? ' prompts for input and the mocked input strings are echoed to out_, mimicking what a CLI user would see.

A subtlety: While the trailing newline on, e.g., 'foobar\n' is stripped by input, it is retained in out_. This is because in_ tees the content read from it to out_ before that content is passed to input.

Want to modify internal print calls within a function or method?

In addition to mocking, stdio_mgr can also be used to wrap functions that directly output to stdout/stderr. A stdout example:

>>> def emboxen(func):
...     def func_wrapper(s):
...         from stdio_mgr import stdio_mgr
...
...         with stdio_mgr() as (in_, out_, err_):
...             func(s)
...             content = out_.getvalue()
...
...         max_len = max(map(len, content.splitlines()))
...         fmt_str = '| {{: <{0}}} |\n'.format(max_len)
...
...         newcontent = '=' * (max_len + 4) + '\n'
...         for line in content.splitlines():
...             newcontent += fmt_str.format(line)
...         newcontent += '=' * (max_len + 4)
...
...         print(newcontent)
...
...     return func_wrapper

>>> @emboxen
... def testfunc(s):
...     print(s)

>>> testfunc("""\
... Foo bar baz quux.
... Lorem ipsum dolor sit amet.""")
===============================
| Foo bar baz quux.           |
| Lorem ipsum dolor sit amet. |
===============================

Feature requests or bug reports?

Please submit them as GitHub Issues.

(c) 2018 Brian Skinn

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

stdio-mgr-1.0.tar.gz (6.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

stdio_mgr-1.0-py3-none-any.whl (8.8 kB view details)

Uploaded Python 3

File details

Details for the file stdio-mgr-1.0.tar.gz.

File metadata

  • Download URL: stdio-mgr-1.0.tar.gz
  • Upload date:
  • Size: 6.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No

File hashes

Hashes for stdio-mgr-1.0.tar.gz
Algorithm Hash digest
SHA256 3e8398ebba9e22c69d373b02676fba618172ea418ea57c1f2a72e45d62361d6d
MD5 5c9a5dfbab4e5422d5e8ed128273b7fe
BLAKE2b-256 eac4744db436f530b5d7e9a7c96e6e7e8c0684a1a26c90dbac92419a68ea6c11

See more details on using hashes here.

File details

Details for the file stdio_mgr-1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for stdio_mgr-1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ec8da381a000f42bcaea699508fc0631bbe7f1965e2b8d9820d339af35a289f3
MD5 a6208cb9319a435c0cf4ab7643136987
BLAKE2b-256 a93c90b6e7e957a6ad8d134b4d4687cb639539172a32611bf7c8dc4937be46f7

See more details on using hashes here.

Release history Release notifications | RSS feed

1.0.1.1

2 files

1.0.1

2 files

This release

1.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page