{"id":18041180,"url":"https://github.com/bskinn/stdio-mgr","last_synced_at":"2025-06-10T22:33:54.207Z","repository":{"id":57471305,"uuid":"126621527","full_name":"bskinn/stdio-mgr","owner":"bskinn","description":"Context manager for mocking/wrapping stdin/stdout/stderr","archived":false,"fork":false,"pushed_at":"2024-09-26T03:33:02.000Z","size":158,"stargazers_count":14,"open_issues_count":45,"forks_count":4,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-23T18:54:16.711Z","etag":null,"topics":["context-manager","mocking","python3","stderr","stdin","stdout"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bskinn.png","metadata":{"files":{"readme":"README.rst","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-03-24T17:06:12.000Z","updated_at":"2024-12-30T22:23:30.000Z","dependencies_parsed_at":"2022-09-10T11:40:50.492Z","dependency_job_id":null,"html_url":"https://github.com/bskinn/stdio-mgr","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bskinn%2Fstdio-mgr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bskinn%2Fstdio-mgr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bskinn%2Fstdio-mgr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bskinn%2Fstdio-mgr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bskinn","download_url":"https://codeload.github.com/bskinn/stdio-mgr/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248070042,"owners_count":21042754,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["context-manager","mocking","python3","stderr","stdin","stdout"],"created_at":"2024-10-30T15:08:44.003Z","updated_at":"2025-04-09T16:44:59.003Z","avatar_url":"https://github.com/bskinn.png","language":"Python","readme":"stdio Manager: Context manager for mocking/wrapping ``stdin``/``stdout``/``stderr``\n===================================================================================\n\n**Current Development Version:**\n\n.. image:: https://travis-ci.org/bskinn/stdio-mgr.svg?branch=master\n    :target: https://travis-ci.org/bskinn/stdio-mgr\n\n.. image:: https://codecov.io/gh/bskinn/stdio-mgr/branch/master/graph/badge.svg\n    :target: https://codecov.io/gh/bskinn/stdio-mgr\n\n**Most Recent Stable Release:**\n\n.. image:: https://img.shields.io/pypi/v/stdio_mgr.svg\n    :target: https://pypi.org/project/stdio-mgr\n\n.. image:: https://img.shields.io/pypi/pyversions/stdio-mgr.svg\n\n**Info:**\n\n.. image:: https://img.shields.io/github/license/mashape/apistatus.svg\n    :target: https://github.com/bskinn/stdio-mgr/blob/stable/LICENSE.txt\n\n.. image:: https://img.shields.io/badge/code%20style-black-000000.svg\n    :target: https://github.com/ambv/black\n\n----\n\n**Have a CLI Python application?**\n\n**Want to automate testing of the actual console input \u0026 output\nof your user-facing components?**\n\n`stdio Manager` can help.\n\nWhile some functionality here is more or less duplicative of\n``redirect_stdout`` and ``redirect_stderr`` in ``contextlib``\n`within the standard library \u003chttps://docs.python.org/3/library/contextlib.html#contextlib.redirect_stdout\u003e`__,\nit provides (i) a much more concise way to mock both ``stdout`` and ``stderr`` at the same time,\nand (ii) a mechanism for mocking ``stdin``, which is not available in ``contextlib``.\n\n**First, install:**\n\n.. code::\n\n    $ pip install stdio-mgr\n\nThen use!\n\nAll of the below examples assume ``stdio_mgr`` has already\nbeen imported via:\n\n.. code::\n\n    \u003e\u003e\u003e from stdio_mgr import stdio_mgr\n\n**Mock** ``stdout``\\ **:**\n\n.. code::\n\n    \u003e\u003e\u003e with stdio_mgr() as (in_, out_, err_):\n    ...     print('foobar')\n    ...     out_cap = out_.getvalue().replace(os.linesep, '\\n')\n    \u003e\u003e\u003e out_cap\n    'foobar\\n'\n    \u003e\u003e\u003e in_.closed and out_.closed and err_.closed\n    True\n\nBy default ``print``\n`appends a newline \u003chttps://docs.python.org/3/library/functions.html#print\u003e`__\nafter each argument, which is why ``out_cap`` is ``'foobar\\n'``\nand not just ``'foobar'``.\n\nAs currently implemented, ``stdio_mgr`` closes all three mocked streams\nupon exiting the managed context.\n\n\n**Mock** ``stderr``\\ **:**\n\n.. code ::\n\n    \u003e\u003e\u003e import warnings\n    \u003e\u003e\u003e with stdio_mgr() as (in_, out_, err_):\n    ...     warnings.warn(\"foo has no bar\")\n    ...     err_cap = err_.getvalue().replace(os.linesep, '\\n')\n    \u003e\u003e\u003e err_cap\n    '...UserWarning: foo has no bar\\n...'\n\n\n**Mock** ``stdin``\\ **:**\n\nThe simulated user input has to be pre-loaded to the mocked stream.\n**Be sure to include newlines in the input to correspond to\neach mocked** `Enter` **keypress!**\nOtherwise, ``input`` will hang, waiting for a newline\nthat will never come.\n\nIf the entirety of the input is known in advance,\nit can just be provided as an argument to ``stdio_mgr``.\nOtherwise, ``.append()`` mocked input to ``in_``\nwithin the managed context as needed:\n\n.. code::\n\n    \u003e\u003e\u003e with stdio_mgr('foobar\\n') as (in_, out_, err_):\n    ...     print('baz')\n    ...     in_cap = input('??? ')\n    ... \n    ...     _ = in_.append(in_cap[:3] + '\\n')\n    ...     in_cap2 = input('??? ')\n    ... \n    ...     out_cap = out_.getvalue().replace(os.linesep, '\\n')\n    \u003e\u003e\u003e in_cap\n    'foobar'\n    \u003e\u003e\u003e in_cap2\n    'foo'\n    \u003e\u003e\u003e out_cap\n    'baz\\n??? foobar\\n??? foo\\n'\n\nThe ``_ =`` assignment suppresses ``print``\\ ing of the return value\nfrom the ``in_.append()`` call--otherwise, it would be interleaved\nin ``out_cap``, since this example is shown for an interactive context.\nFor non-interactive execution, as with ``unittest``, ``pytest``, etc.,\nthese 'muting' assignments should not be necessary.\n\n**Both** the ``'??? '`` prompts for ``input``\n**and** the mocked input strings\nare echoed to ``out_``, mimicking what a CLI user would see.\n\nA subtlety: While the trailing newline on, e.g., ``'foobar\\n'`` is stripped\nby ``input``, it is *retained* in ``out_``.\nThis is because ``in_`` tees the content read from it to ``out_``\n*before* that content is passed to ``input``.\n\n\n**Want to modify internal** ``print`` **calls\nwithin a function or method?**\n\nIn addition to mocking, ``stdio_mgr`` can also be used to\nwrap functions that directly output to ``stdout``/``stderr``. A ``stdout`` example:\n\n.. code::\n\n    \u003e\u003e\u003e def emboxen(func):\n    ...     def func_wrapper(s):\n    ...         from stdio_mgr import stdio_mgr\n    ... \n    ...         with stdio_mgr() as (in_, out_, err_):\n    ...             func(s)\n    ...             content = out_.getvalue()\n    ... \n    ...         max_len = max(map(len, content.splitlines()))\n    ...         fmt_str = '| {{: \u003c{0}}} |\\n'.format(max_len)\n    ... \n    ...         newcontent = '=' * (max_len + 4) + '\\n'\n    ...         for line in content.splitlines():\n    ...             newcontent += fmt_str.format(line)\n    ...         newcontent += '=' * (max_len + 4)\n    ... \n    ...         print(newcontent)\n    ... \n    ...     return func_wrapper\n\n    \u003e\u003e\u003e @emboxen\n    ... def testfunc(s):\n    ...     print(s)\n\n    \u003e\u003e\u003e testfunc(\"\"\"\\\n    ... Foo bar baz quux.\n    ... Lorem ipsum dolor sit amet.\"\"\")\n    ===============================\n    | Foo bar baz quux.           |\n    | Lorem ipsum dolor sit amet. |\n    ===============================\n\n----\n\nAvailable on `PyPI \u003chttps://pypi.python.org/pypi/stdio-mgr\u003e`__\n(``pip install stdio-mgr``).\n\nSource on `GitHub \u003chttps://github.com/bskinn/stdio-mgr\u003e`__.  Bug reports\nand feature requests are welcomed at the\n`Issues \u003chttps://github.com/bskinn/stdio-mgr/issues\u003e`__ page there.\n\nCopyright \\(c) 2018-2019 Brian Skinn\n\nLicense: The MIT License. See `LICENSE.txt \u003chttps://github.com/bskinn/stdio-mgr/blob/stable/LICENSE.txt\u003e`__\nfor full license terms.\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbskinn%2Fstdio-mgr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbskinn%2Fstdio-mgr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbskinn%2Fstdio-mgr/lists"}