I would not close the underlying stream. Passing in an already open file object means the caller has taken responsibility of that object and closing that object on __exit__
would be extremely annoying, at best.
PIL does something similar, albeit not in a context manager. When passing in a filename, it'll close the fileobject after it completes reading the image data. It sets a boolean flag just for that. Pass in a file object instead and it'll read but not close.
I'd do the same here:
class Foo(object):
_close_on_exit = False
def __init__(self, file_to_process):
if isinstance(file_to_process, str):
self._underlying_stream = open(file_to_process, "rb") # it's the path to a file
self._close_on_exit = True
elif isinstance(file_to_process, io.IOBase):
self._underlying_stream = file_to_process # its the file itself
else:
raise TypeError()
def __exit__(self, exc_type, exc_value, traceback):
if self._close_on_exit:
self._underlying_stream.close()