Add method last_bytes in fileutils
Method last_bytes is used in some projects[1]. It's good to bring this method in fileutils according to discussion in dev ML[2]. [1] http://codesearch.openstack.org/?q=last_bytes&i=nope&files=&repos= [2] http://lists.openstack.org/pipermail/openstack-dev/2017-July/120259.html Change-Id: I1cd61de58b759916ecd0569afb2485de0b31c405
This commit is contained in:
parent
58fb709f58
commit
4d35db56f8
@ -124,3 +124,27 @@ def compute_file_checksum(path, read_chunksize=65536, algorithm='sha256'):
|
|||||||
for chunk in iter(lambda: f.read(read_chunksize), b''):
|
for chunk in iter(lambda: f.read(read_chunksize), b''):
|
||||||
checksum.update(chunk)
|
checksum.update(chunk)
|
||||||
return checksum.hexdigest()
|
return checksum.hexdigest()
|
||||||
|
|
||||||
|
|
||||||
|
def last_bytes(path, num):
|
||||||
|
"""Return num bytes from the end of the file, and unread byte count.
|
||||||
|
|
||||||
|
:param path: The file path to read
|
||||||
|
:param num: The number of bytes to return
|
||||||
|
|
||||||
|
:returns: (data, unread_bytes)
|
||||||
|
"""
|
||||||
|
|
||||||
|
with open(path, 'rb') as fp:
|
||||||
|
try:
|
||||||
|
fp.seek(-num, os.SEEK_END)
|
||||||
|
except IOError as e:
|
||||||
|
# seek() fails with EINVAL when trying to go before the start of
|
||||||
|
# the file. It means that num is larger than the file size, so
|
||||||
|
# just go to the start.
|
||||||
|
if e.errno == errno.EINVAL:
|
||||||
|
fp.seek(0, os.SEEK_SET)
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
unread_bytes = fp.tell()
|
||||||
|
return (fp.read(), unread_bytes)
|
||||||
|
@ -244,3 +244,29 @@ class TestComputeFileChecksum(test_base.BaseTestCase):
|
|||||||
def test_generic_io_error(self):
|
def test_generic_io_error(self):
|
||||||
tempdir = tempfile.mkdtemp()
|
tempdir = tempfile.mkdtemp()
|
||||||
self.assertRaises(IOError, fileutils.compute_file_checksum, tempdir)
|
self.assertRaises(IOError, fileutils.compute_file_checksum, tempdir)
|
||||||
|
|
||||||
|
|
||||||
|
class LastBytesTestCase(test_base.BaseTestCase):
|
||||||
|
"""Test the last_bytes() utility method."""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(LastBytesTestCase, self).setUp()
|
||||||
|
self.content = b'1234567890'
|
||||||
|
|
||||||
|
def test_truncated(self):
|
||||||
|
res = fileutils.write_to_tempfile(self.content)
|
||||||
|
self.assertTrue(os.path.exists(res))
|
||||||
|
out, unread_bytes = fileutils.last_bytes(res, 5)
|
||||||
|
self.assertEqual(b'67890', out)
|
||||||
|
self.assertGreater(unread_bytes, 0)
|
||||||
|
|
||||||
|
def test_read_all(self):
|
||||||
|
res = fileutils.write_to_tempfile(self.content)
|
||||||
|
self.assertTrue(os.path.exists(res))
|
||||||
|
out, unread_bytes = fileutils.last_bytes(res, 1000)
|
||||||
|
self.assertEqual(b'1234567890', out)
|
||||||
|
self.assertEqual(0, unread_bytes)
|
||||||
|
|
||||||
|
def test_non_exist_file(self):
|
||||||
|
self.assertRaises(IOError, fileutils.last_bytes,
|
||||||
|
'non_exist_file', 1000)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user