Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support working directly with file descriptors #659

Merged
merged 5 commits into from
Oct 10, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions smart_open/compression.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ def compression_wrapper(file_obj, mode, compression):
elif compression == INFER_FROM_EXTENSION:
try:
filename = file_obj.name
filename.upper() # make sure this thing is a string
piskvorky marked this conversation as resolved.
Show resolved Hide resolved
except (AttributeError, TypeError):
logger.warning(
'unable to transparently decompress %r because it '
Expand Down
11 changes: 11 additions & 0 deletions smart_open/smart_open_lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,17 @@ def _open_binary_stream(uri, mode, transport_params):
uri.name = getattr(uri, 'name', 'unknown')
return uri

if isinstance(uri, int):
#
# We're working with a file descriptor. If we open it, its name is
# just the integer value, which isn't helpful. Unfortunately, there's
# no easy cross-platform way to go from a file descriptor to the filename,
# so we just give up here. The user will have to handle their own
# compression, etc. explicitly.
#
fobj = _builtin_open(uri, mode, closefd=False)
return fobj

if not isinstance(uri, str):
raise TypeError("don't know how to handle uri %s" % repr(uri))

Expand Down
22 changes: 22 additions & 0 deletions smart_open/tests/test_smart_open.py
Original file line number Diff line number Diff line change
Expand Up @@ -2060,6 +2060,28 @@ def test_backwards_compatibility_wrapper():
smart_open.smart_open(fpath, unsupported_keyword_param=123)


@pytest.mark.skipif(os.name == "nt", reason="this test does not work on Windows")
def test_read_file_descriptor():
with smart_open.open(__file__) as fin:
expected = fin.read()

fd = os.open(__file__, os.O_RDONLY)
with smart_open.open(fd) as fin:
actual = fin.read()

assert actual == expected


@pytest.mark.skipif(os.name == "nt", reason="this test does not work on Windows")
def test_write_file_descriptor():
with tempfile.NamedTemporaryFile() as tmp:
with smart_open.open(os.open(tmp.name, os.O_WRONLY), 'wt') as fout:
fout.write("hello world")

with smart_open.open(tmp, 'rt') as fin:
assert fin.read() == "hello world"


if __name__ == '__main__':
logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.DEBUG)
unittest.main()