Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/bskinn/stdio-mgr
Context manager for mocking/wrapping stdin/stdout/stderr
https://github.com/bskinn/stdio-mgr
context-manager mocking python3 stderr stdin stdout
Last synced: 2 months ago
JSON representation
Context manager for mocking/wrapping stdin/stdout/stderr
- Host: GitHub
- URL: https://github.com/bskinn/stdio-mgr
- Owner: bskinn
- License: mit
- Created: 2018-03-24T17:06:12.000Z (almost 7 years ago)
- Default Branch: master
- Last Pushed: 2024-09-26T03:33:02.000Z (3 months ago)
- Last Synced: 2024-10-12T06:28:35.271Z (3 months ago)
- Topics: context-manager, mocking, python3, stderr, stdin, stdout
- Language: Python
- Homepage:
- Size: 154 KB
- Stars: 14
- Watchers: 4
- Forks: 4
- Open Issues: 45
-
Metadata Files:
- Readme: README.rst
- Changelog: CHANGELOG.md
- License: LICENSE.txt
Awesome Lists containing this project
README
stdio Manager: Context manager for mocking/wrapping ``stdin``/``stdout``/``stderr``
===================================================================================**Current Development Version:**
.. image:: https://travis-ci.org/bskinn/stdio-mgr.svg?branch=master
:target: https://travis-ci.org/bskinn/stdio-mgr.. image:: https://codecov.io/gh/bskinn/stdio-mgr/branch/master/graph/badge.svg
:target: https://codecov.io/gh/bskinn/stdio-mgr**Most Recent Stable Release:**
.. image:: https://img.shields.io/pypi/v/stdio_mgr.svg
:target: https://pypi.org/project/stdio-mgr.. image:: https://img.shields.io/pypi/pyversions/stdio-mgr.svg
**Info:**
.. image:: https://img.shields.io/github/license/mashape/apistatus.svg
:target: https://github.com/bskinn/stdio-mgr/blob/stable/LICENSE.txt.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
:target: https://github.com/ambv/black----
**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:**
.. code::
$ pip install stdio-mgr
Then use!
All of the below examples assume ``stdio_mgr`` has already
been imported via:.. code::
>>> from stdio_mgr import stdio_mgr
**Mock** ``stdout``\ **:**
.. code::
>>> with stdio_mgr() as (in_, out_, err_):
... print('foobar')
... out_cap = out_.getvalue().replace(os.linesep, '\n')
>>> out_cap
'foobar\n'
>>> in_.closed and out_.closed and err_.closed
TrueBy 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``\ **:**
.. code ::
>>> import warnings
>>> with stdio_mgr() as (in_, out_, err_):
... warnings.warn("foo has no bar")
... err_cap = err_.getvalue().replace(os.linesep, '\n')
>>> err_cap
'...UserWarning: foo has no bar\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:.. code::
>>> 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().replace(os.linesep, '\n')
>>> in_cap
'foobar'
>>> in_cap2
'foo'
>>> out_cap
'baz\n??? foobar\n??? foo\n'The ``_ =`` assignment suppresses ``print``\ ing 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:.. code::
>>> 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. |
===============================----
Available on `PyPI `__
(``pip install stdio-mgr``).Source on `GitHub `__. Bug reports
and feature requests are welcomed at the
`Issues `__ page there.Copyright \(c) 2018-2019 Brian Skinn
License: The MIT License. See `LICENSE.txt `__
for full license terms.