Ignore:
Timestamp:
Jul 19, 2014, 8:56:27 AM (5 years ago)
Author:
Stefan Schwarzer <sschwarzer@…>
Branch:
default
Message:
Extracted `BufferedIO` from `file.py` for reuse in other projects.

This applies to my own projects and to other people's projects!
File:
1 edited

Legend:

Unmodified
Added
Removed
  • ftputil/file.py

    r1513 r1549  
    1414import ftputil.compat
    1515import ftputil.error
     16import ftputil.socket_file_adapter
    1617
    1718
    1819# This module shouldn't be used by clients of the ftputil library.
    1920__all__ = []
    20 
    21 
    22 class BufferedIO(io.BufferedIOBase):
    23     """
    24     Adapt a file object returned from `socket.makefile` to the
    25     interfaces of `io.BufferedReader` or `io.BufferedWriter`, so that
    26     the new object can be wrapped by `io.TextIOWrapper`.
    27 
    28     This is only needed with Python 2, since in Python 3
    29     `socket.makefile` already returns a `BufferedReader` or
    30     `BufferedWriter` object (depending on mode).
    31     """
    32 
    33     def __init__(self, fobj, is_readable=False, is_writable=False):
    34         # Don't call baseclass constructor for this adapter.
    35         # pylint: disable=super-init-not-called
    36         #
    37         # This is the return value of `socket.makefile` and is already
    38         # buffered.
    39         self.raw = fobj
    40         self._is_readable = is_readable
    41         self._is_writable = is_writable
    42 
    43     @property
    44     def closed(self):
    45         # pylint: disable=missing-docstring
    46         return self.raw.closed
    47 
    48     def close(self):
    49         self.raw.close()
    50 
    51     def fileno(self):
    52         return self.raw.fileno()
    53 
    54     def isatty(self):
    55         # It's highly unlikely that this file is interactive.
    56         return False
    57 
    58     def seekable(self):
    59         return False
    60 
    61     #
    62     # Interface for `BufferedReader`
    63     #
    64     def readable(self):
    65         return self._is_readable
    66 
    67     def read(self, *arg):
    68         return self.raw.read(*arg)
    69 
    70     read1 = read
    71 
    72     def readline(self, *arg):
    73         return self.raw.readline(*arg)
    74 
    75     def readlines(self, *arg):
    76         return self.raw.readlines(*arg)
    77 
    78     def readinto(self, bytearray_):
    79         data = self.raw.read(len(bytearray_))
    80         bytearray_[:len(data)] = data
    81         return len(data)
    82 
    83     #
    84     # Interface for `BufferedWriter`
    85     #
    86     def writable(self):
    87         return self._is_writable
    88 
    89     def flush(self):
    90         self.raw.flush()
    91 
    92     # Derived from `socket.py` in Python 2.6 and 2.7.
    93     # There doesn't seem to be a public API for this.
    94     def _write_buffer_size(self):
    95         """Return current size of the write buffer in bytes."""
    96         # pylint: disable=protected-access
    97         if hasattr(self.raw, "_wbuf_len"):
    98             # Python 2.6.3 - 2.7.5
    99             return self.raw._wbuf_len
    100         elif hasattr(self.raw, "_get_wbuf_len"):
    101             # Python 2.6 - 2.6.2. (Strictly speaking, all other
    102             # Python 2.6 versions have a `_get_wbuf_len` method, but
    103             # for 2.6.3 and up it returns `_wbuf_len`).
    104             return self.raw._get_wbuf_len()
    105         else:
    106             # Fallback. In the context of `write` this means the file
    107             # appears to be unbuffered.
    108             return 0
    109 
    110     def write(self, bytes_or_bytearray):
    111         # `BufferedWriter.write` has to return the number of written
    112         # bytes, but files returned from `socket.makefile` in Python 2
    113         # return `None`. Hence provide a workaround.
    114         old_buffer_byte_count = self._write_buffer_size()
    115         added_byte_count = len(bytes_or_bytearray)
    116         self.raw.write(bytes_or_bytearray)
    117         new_buffer_byte_count = self._write_buffer_size()
    118         return (old_buffer_byte_count + added_byte_count -
    119                 new_buffer_byte_count)
    120 
    121     def writelines(self, lines):
    122         self.raw.writelines(lines)
    12321
    12422
     
    19795        fobj = self._conn.makefile(makefile_mode)
    19896        if ftputil.compat.python_version == 2:
     97            BufferedIOAdapter = ftputil.socket_file_adapter.BufferedIOAdapter
    19998            if is_read_mode:
    200                 fobj = BufferedIO(fobj, is_readable=True)
     99                fobj = BufferedIOAdapter(fobj, is_readable=True)
    201100            else:
    202                 fobj = BufferedIO(fobj, is_writable=True)
     101                fobj = BufferedIOAdapter(fobj, is_writable=True)
    203102        if not is_binary_mode:
    204103            fobj = io.TextIOWrapper(fobj, encoding=encoding,
Note: See TracChangeset for help on using the changeset viewer.