Skip to content

Commit

Permalink
Merge branch '1.13' into 1.14
Browse files Browse the repository at this point in the history
  • Loading branch information
bitprophet committed Dec 18, 2014
2 parents 87047cc + fc59b7d commit cca8c51
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 5 deletions.
16 changes: 12 additions & 4 deletions paramiko/file.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ def readline(self, size=None):
if not (self._flags & self.FLAG_READ):
raise IOError('File not open for reading')
line = self._rbuffer
truncated = False
while True:
if self._at_trailing_cr and (self._flags & self.FLAG_UNIVERSAL_NEWLINE) and (len(line) > 0):
# edge case: the newline may be '\r\n' and we may have read
Expand All @@ -218,11 +219,11 @@ def readline(self, size=None):
# enough.
if (size is not None) and (size >= 0):
if len(line) >= size:
# truncate line and return
# truncate line
self._rbuffer = line[size:]
line = line[:size]
self._pos += len(line)
return line if self._flags & self.FLAG_BINARY else u(line)
truncated = True
break
n = size - len(line)
else:
n = self._bufsize
Expand All @@ -244,10 +245,17 @@ def readline(self, size=None):
rpos = line.find(cr_byte)
if (rpos >= 0) and (rpos < pos or pos < 0):
pos = rpos
if pos == -1:
# we couldn't find a newline in the truncated string, return it
self._pos += len(line)
return line if self._flags & self.FLAG_BINARY else u(line)
xpos = pos + 1
if (line[pos] == cr_byte_value) and (xpos < len(line)) and (line[xpos] == linefeed_byte_value):
xpos += 1
self._rbuffer = line[xpos:]
# if the string was truncated, _rbuffer needs to have the string after
# the newline character plus the truncated part of the line we stored
# earlier in _rbuffer
self._rbuffer = line[xpos:] + self._rbuffer if truncated else line[xpos:]
lf = line[pos:xpos]
line = line[:pos] + linefeed_byte
if (len(self._rbuffer) == 0) and (lf == cr_byte):
Expand Down
4 changes: 4 additions & 0 deletions sites/www/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
Changelog
=========

* :bug:`428` Fix an issue in `~paramiko.file.BufferedFile` (primarily used in
the SFTP modules) concerning incorrect behavior by
`~paramiko.file.BufferedFile.readlines` on files whose size exceeds the
buffer size. Thanks to ``@achapp`` for catch & patch.
* :support:`422` Clean up some unused imports. Courtesy of Olle Lundberg.
* :bug:`266` Change numbering of `~paramiko.transport.Transport` channels to
start at 0 instead of 1 for better compatibility with OpenSSH & certain
Expand Down
6 changes: 5 additions & 1 deletion tests/test_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,17 @@ def test_1_simple(self):

def test_2_readline(self):
f = LoopbackFile('r+U')
f.write(b'First line.\nSecond line.\r\nThird line.\nFinal line non-terminated.')
f.write(b'First line.\nSecond line.\r\nThird line.\n' +
b'Fourth line.\nFinal line non-terminated.')

self.assertEqual(f.readline(), 'First line.\n')
# universal newline mode should convert this linefeed:
self.assertEqual(f.readline(), 'Second line.\n')
# truncated line:
self.assertEqual(f.readline(7), 'Third l')
self.assertEqual(f.readline(), 'ine.\n')
# newline should be detected and only the fourth line returned
self.assertEqual(f.readline(39), 'Fourth line.\n')
self.assertEqual(f.readline(), 'Final line non-terminated.')
self.assertEqual(f.readline(), '')
f.close()
Expand Down

0 comments on commit cca8c51

Please sign in to comment.