Skip to content

Commit

Permalink
DEV: Allow streams to not be context managers
Browse files Browse the repository at this point in the history
Many existing stdio capture and wrapper streams are only partial
implementations, most commonly missing `__enter__` and `__exit__`.
When StdioManager needs to integrate those streams into its service
it needs to suppress exceptions caused by those missing methods.
  • Loading branch information
jayvdb committed Sep 6, 2019
1 parent c24cd4c commit 1b6da37
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 1 deletion.
3 changes: 2 additions & 1 deletion src/stdio_mgr/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,8 @@ class _MultiCloseContextManager(StdioTuple):
def __enter__(self):
"""Enter context of all members."""
with ExitStack() as stack:
all(map(stack.enter_context, self))
# If not all items are TextIOBase, they may not have __exit__
self.suppress_all(AttributeError, stack.enter_context)

self._close_files = stack.pop_all().close

Expand Down
19 changes: 19 additions & 0 deletions tests/test_stdiomgr_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@

from stdio_mgr import stdio_mgr, StdioManager
from stdio_mgr.stdio_mgr import _Tee
from stdio_mgr.types import _MultiCloseContextManager, StdioTuple, TextIOTuple


def test_context_manager_instance():
Expand Down Expand Up @@ -543,6 +544,24 @@ def test_tee_type():
assert str(err.value) == "tee must be a TextIOBase."


def test_non_closing_type():
"""Test that incorrect type doesnt raise exceptions."""
# Ensure the type used has no __exit__ or close()
assert not hasattr("", "__exit__")
assert not hasattr("", "close")

with StdioTuple(("", "", "")):
pass

with _MultiCloseContextManager(("", "", "")):
pass

with pytest.raises(AssertionError) as err:
TextIOTuple(("", "", ""))

assert str(err.value) == "iterable must contain only TextIOBase"


@pytest.mark.xfail(reason="Want to ensure 'real' warnings aren't suppressed")
def test_bare_warning(skip_warnings):
"""Test that a "real" warning is exposed when raised."""
Expand Down

0 comments on commit 1b6da37

Please sign in to comment.