Support the whence parameter in GFile's .seek() to match Python's file

semantics. Also rename position to offset to match Python's file parameter
naming.

Fixes numpy.load() from gfile.
Change: 153655962
This commit is contained in:
Jonathan Hseu 2017-04-19 16:20:42 -08:00 committed by TensorFlower Gardener
parent 7821dbee6a
commit fd14d0ac6a
5 changed files with 81 additions and 6 deletions

View File

@ -27,6 +27,7 @@ import uuid
from tensorflow.python import pywrap_tensorflow
from tensorflow.python.framework import errors
from tensorflow.python.util import compat
from tensorflow.python.util import deprecation
class FileIO(object):
@ -121,11 +122,51 @@ class FileIO(object):
return self._prepare_value(
pywrap_tensorflow.ReadFromStream(self._read_buf, length, status))
def seek(self, position):
"""Seeks to the position in the file."""
@deprecation.deprecated_args(
None,
"position is deprecated in favor of the offset argument.",
"position")
def seek(self, offset=None, whence=0, position=None):
# TODO(jhseu): Delete later. Used to omit `position` from docs.
# pylint: disable=g-doc-args
"""Seeks to the offset in the file.
Args:
offset: The byte count relative to the whence argument.
whence: Valid values for whence are:
0: start of the file (default)
1: relative to the current position of the file
2: relative to the end of file. offset is usually negative.
"""
# pylint: enable=g-doc-args
self._preread_check()
# We needed to make offset a keyword argument for backwards-compatibility.
# This check exists so that we can convert back to having offset be a
# positional argument.
# TODO(jhseu): Make `offset` a positional argument after `position` is
# deprecated.
if offset is None and position is None:
raise TypeError("seek(): offset argument required")
if offset is not None and position is not None:
raise TypeError("seek(): offset and position may not be set "
"simultaneously.")
if position is not None:
offset = position
with errors.raise_exception_on_not_ok_status() as status:
ret_status = self._read_buf.Seek(position)
if whence == 0:
pass
elif whence == 1:
offset += self.tell()
elif whence == 2:
offset += self.size()
else:
raise errors.InvalidArgumentError(
None, None,
"Invalid whence argument: {}. Valid values are 0, 1, or 2."
.format(whence))
ret_status = self._read_buf.Seek(offset)
pywrap_tensorflow.Set_TF_Status_from_Status(status, ret_status)
def readline(self):

View File

@ -392,6 +392,40 @@ class FileIoTest(test.TestCase):
with self.assertRaises(errors.InvalidArgumentError):
f.seek(-1)
with self.assertRaises(TypeError):
f.seek()
# TODO(jhseu): Delete after position deprecation.
with self.assertRaises(TypeError):
f.seek(offset=0, position=0)
f.seek(position=9)
self.assertEqual(9, f.tell())
self.assertEqual("testing2\n", f.readline())
def testSeekFromWhat(self):
file_path = os.path.join(self._base_dir, "temp_file")
with file_io.FileIO(file_path, mode="r+") as f:
f.write("testing1\ntesting2\ntesting3\n\ntesting5")
self.assertEqual("testing1\n", f.readline())
self.assertEqual(9, f.tell())
# Seek to 18
f.seek(9, 1)
self.assertEqual(18, f.tell())
self.assertEqual("testing3\n", f.readline())
# Seek back to 9
f.seek(9, 0)
self.assertEqual(9, f.tell())
self.assertEqual("testing2\n", f.readline())
f.seek(-f.size(), 2)
self.assertEqual(0, f.tell())
self.assertEqual("testing1\n", f.readline())
with self.assertRaises(errors.InvalidArgumentError):
f.seek(0, 3)
def testReadingIterator(self):
file_path = os.path.join(self._base_dir, "temp_file")
data = ["testing1\n", "testing2\n", "testing3\n", "\n", "testing5"]

View File

@ -41,7 +41,7 @@ tf_class {
}
member_method {
name: "seek"
argspec: "args=[\'self\', \'position\'], varargs=None, keywords=None, defaults=None"
argspec: "args=[], varargs=args, keywords=kwargs, defaults=None"
}
member_method {
name: "size"

View File

@ -41,7 +41,7 @@ tf_class {
}
member_method {
name: "seek"
argspec: "args=[\'self\', \'position\'], varargs=None, keywords=None, defaults=None"
argspec: "args=[], varargs=args, keywords=kwargs, defaults=None"
}
member_method {
name: "size"

View File

@ -41,7 +41,7 @@ tf_class {
}
member_method {
name: "seek"
argspec: "args=[\'self\', \'position\'], varargs=None, keywords=None, defaults=None"
argspec: "args=[], varargs=args, keywords=kwargs, defaults=None"
}
member_method {
name: "size"