Skip to content

nibabel.openers.Opener does not guarantee file mode when provided with a file handler #1143

Open
@anibalsolon

Description

@anibalsolon

Following the discussion from #1140 with @effigies , the Opener does not guarantee the file mode (or err) when a file handler is provided instead of a filename. E.g.:

fd = open('file', 'r')
with Opener(fd, 'w') as bigO:
    bigO.write('hello')  # trying to write in read mode

fd = open('file', 'r')
with Opener(fd, 'rb') as bigO:
    assert bigO.read(5) == b'hello'  # 'hello' != b'hello'

For read/write, it seems to me that it is no-brainer- just check for the correct chars in the .mode and err when it is different. This change in the contract may require a DeprecationWarning.

Now for text/binary mode, let me know if that's too hacky: When opening in text mode on Py3, the file object has an attribute 'buffer' which is the same as opening the file in binary mode. So something like this would guarantee to always be binary (when requested + for the default mode):

class Opener(object):
    def __init__(self, fileish, *args, **kwargs):
        mode = kwargs['mode']  # all that kwargs processing
        if self._is_fileobj(fileish):
            # binary mode is requested, but fileish mode is text
            if 'b' in mode and 'b' not in fileish.mode:
                self.fobj = fileish.buffer
            else:
                self.fobj = fileish
            ...

fd = open('file', 'r')
with Opener(fd, 'rb') as bigO:
    assert bigO.read(5) == 'hello'  # b'hello' == b'hello'

however, if fd is binary mode and Opener requests text mode, probably a TextIOWrapper needs to be used to convert between modes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions