Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(1075)

Side by Side Diff: Lib/_pyio.py

Issue 10142: Support for SEEK_HOLE/SEEK_DATA
Patch Set: Created 1 year ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « Doc/library/os.rst ('k') | Lib/os.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 """ 1 """
2 Python implementation of the io module. 2 Python implementation of the io module.
3 """ 3 """
4 4
5 import os 5 import os
6 import abc 6 import abc
7 import codecs 7 import codecs
8 import warnings 8 import warnings
9 import errno 9 import errno
10 # Import _thread instead of threading to reduce startup cost 10 # Import _thread instead of threading to reduce startup cost
11 try: 11 try:
12 from _thread import allocate_lock as Lock 12 from _thread import allocate_lock as Lock
13 except ImportError: 13 except ImportError:
14 from _dummy_thread import allocate_lock as Lock 14 from _dummy_thread import allocate_lock as Lock
15 15
16 import io 16 import io
17 from io import (__all__, SEEK_SET, SEEK_CUR, SEEK_END) 17 from io import (__all__, SEEK_SET, SEEK_CUR, SEEK_END)
18
19 valid_seek_flags = {0, 1, 2} # Hardwired values
20 if hasattr(os, 'SEEK_HOLE') :
21 valid_seek_flags.add(os.SEEK_HOLE)
22 valid_seek_flags.add(os.SEEK_DATA)
18 23
19 # open() uses st_blksize whenever we can 24 # open() uses st_blksize whenever we can
20 DEFAULT_BUFFER_SIZE = 8 * 1024 # bytes 25 DEFAULT_BUFFER_SIZE = 8 * 1024 # bytes
21 26
22 # NOTE: Base classes defined here are registered with the "official" ABCs 27 # NOTE: Base classes defined here are registered with the "official" ABCs
23 # defined in io.py. We don't use real inheritance though, because we don't 28 # defined in io.py. We don't use real inheritance though, because we don't
24 # want to inherit the C implementations. 29 # want to inherit the C implementations.
25 30
26 # Rebind for compatibility 31 # Rebind for compatibility
27 BlockingIOError = BlockingIOError 32 BlockingIOError = BlockingIOError
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after
299 def seek(self, pos, whence=0): 304 def seek(self, pos, whence=0):
300 """Change stream position. 305 """Change stream position.
301 306
302 Change the stream position to byte offset offset. offset is 307 Change the stream position to byte offset offset. offset is
303 interpreted relative to the position indicated by whence. Values 308 interpreted relative to the position indicated by whence. Values
304 for whence are ints: 309 for whence are ints:
305 310
306 * 0 -- start of stream (the default); offset should be zero or positive 311 * 0 -- start of stream (the default); offset should be zero or positive
307 * 1 -- current stream position; offset may be negative 312 * 1 -- current stream position; offset may be negative
308 * 2 -- end of stream; offset is usually negative 313 * 2 -- end of stream; offset is usually negative
314 Some operating systems / file systems could provide additional values.
309 315
310 Return an int indicating the new absolute position. 316 Return an int indicating the new absolute position.
311 """ 317 """
312 self._unsupported("seek") 318 self._unsupported("seek")
313 319
314 def tell(self): 320 def tell(self):
315 """Return an int indicating the current stream position.""" 321 """Return an int indicating the current stream position."""
316 return self.seek(0, 1) 322 return self.seek(0, 1)
317 323
318 def truncate(self, pos=None): 324 def truncate(self, pos=None):
(...skipping 540 matching lines...) Expand 10 before | Expand all | Expand 10 after
859 raise TypeError("an integer is required") from err 865 raise TypeError("an integer is required") from err
860 if whence == 0: 866 if whence == 0:
861 if pos < 0: 867 if pos < 0:
862 raise ValueError("negative seek position %r" % (pos,)) 868 raise ValueError("negative seek position %r" % (pos,))
863 self._pos = pos 869 self._pos = pos
864 elif whence == 1: 870 elif whence == 1:
865 self._pos = max(0, self._pos + pos) 871 self._pos = max(0, self._pos + pos)
866 elif whence == 2: 872 elif whence == 2:
867 self._pos = max(0, len(self._buffer) + pos) 873 self._pos = max(0, len(self._buffer) + pos)
868 else: 874 else:
869 raise ValueError("invalid whence value") 875 raise ValueError("unsupported whence value")
870 return self._pos 876 return self._pos
871 877
872 def tell(self): 878 def tell(self):
873 if self.closed: 879 if self.closed:
874 raise ValueError("tell on closed file") 880 raise ValueError("tell on closed file")
875 return self._pos 881 return self._pos
876 882
877 def truncate(self, pos=None): 883 def truncate(self, pos=None):
878 if self.closed: 884 if self.closed:
879 raise ValueError("truncate on closed file") 885 raise ValueError("truncate on closed file")
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
1034 return b"" 1040 return b""
1035 with self._read_lock: 1041 with self._read_lock:
1036 self._peek_unlocked(1) 1042 self._peek_unlocked(1)
1037 return self._read_unlocked( 1043 return self._read_unlocked(
1038 min(n, len(self._read_buf) - self._read_pos)) 1044 min(n, len(self._read_buf) - self._read_pos))
1039 1045
1040 def tell(self): 1046 def tell(self):
1041 return _BufferedIOMixin.tell(self) - len(self._read_buf) + self._read_po s 1047 return _BufferedIOMixin.tell(self) - len(self._read_buf) + self._read_po s
1042 1048
1043 def seek(self, pos, whence=0): 1049 def seek(self, pos, whence=0):
1044 if not (0 <= whence <= 2): 1050 if whence not in valid_seek_flags:
1045 raise ValueError("invalid whence value") 1051 raise ValueError("invalid whence value")
1046 with self._read_lock: 1052 with self._read_lock:
1047 if whence == 1: 1053 if whence == 1:
1048 pos -= len(self._read_buf) - self._read_pos 1054 pos -= len(self._read_buf) - self._read_pos
1049 pos = _BufferedIOMixin.seek(self, pos, whence) 1055 pos = _BufferedIOMixin.seek(self, pos, whence)
1050 self._reset_read_buf() 1056 self._reset_read_buf()
1051 return pos 1057 return pos
1052 1058
1053 class BufferedWriter(_BufferedIOMixin): 1059 class BufferedWriter(_BufferedIOMixin):
1054 1060
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
1131 errno.EAGAIN, 1137 errno.EAGAIN,
1132 "write could not complete without blocking", 0) 1138 "write could not complete without blocking", 0)
1133 if n > len(self._write_buf) or n < 0: 1139 if n > len(self._write_buf) or n < 0:
1134 raise IOError("write() returned incorrect number of bytes") 1140 raise IOError("write() returned incorrect number of bytes")
1135 del self._write_buf[:n] 1141 del self._write_buf[:n]
1136 1142
1137 def tell(self): 1143 def tell(self):
1138 return _BufferedIOMixin.tell(self) + len(self._write_buf) 1144 return _BufferedIOMixin.tell(self) + len(self._write_buf)
1139 1145
1140 def seek(self, pos, whence=0): 1146 def seek(self, pos, whence=0):
1141 if not (0 <= whence <= 2): 1147 if whence not in valid_seek_flags:
1142 raise ValueError("invalid whence") 1148 raise ValueError("invalid whence value")
1143 with self._write_lock: 1149 with self._write_lock:
1144 self._flush_unlocked() 1150 self._flush_unlocked()
1145 return _BufferedIOMixin.seek(self, pos, whence) 1151 return _BufferedIOMixin.seek(self, pos, whence)
1146 1152
1147 1153
1148 class BufferedRWPair(BufferedIOBase): 1154 class BufferedRWPair(BufferedIOBase):
1149 1155
1150 """A buffered reader and writer object together. 1156 """A buffered reader and writer object together.
1151 1157
1152 A buffered reader object and buffered writer object put together to 1158 A buffered reader object and buffered writer object put together to
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
1228 1234
1229 _warning_stack_offset = 3 1235 _warning_stack_offset = 3
1230 1236
1231 def __init__(self, raw, 1237 def __init__(self, raw,
1232 buffer_size=DEFAULT_BUFFER_SIZE, max_buffer_size=None): 1238 buffer_size=DEFAULT_BUFFER_SIZE, max_buffer_size=None):
1233 raw._checkSeekable() 1239 raw._checkSeekable()
1234 BufferedReader.__init__(self, raw, buffer_size) 1240 BufferedReader.__init__(self, raw, buffer_size)
1235 BufferedWriter.__init__(self, raw, buffer_size, max_buffer_size) 1241 BufferedWriter.__init__(self, raw, buffer_size, max_buffer_size)
1236 1242
1237 def seek(self, pos, whence=0): 1243 def seek(self, pos, whence=0):
1238 if not (0 <= whence <= 2): 1244 if whence not in valid_seek_flags:
1239 raise ValueError("invalid whence") 1245 raise ValueError("invalid whence value")
1240 self.flush() 1246 self.flush()
1241 if self._read_buf: 1247 if self._read_buf:
1242 # Undo read ahead. 1248 # Undo read ahead.
1243 with self._read_lock: 1249 with self._read_lock:
1244 self.raw.seek(self._read_pos - len(self._read_buf), 1) 1250 self.raw.seek(self._read_pos - len(self._read_buf), 1)
1245 # First do the raw seek, then empty the read buffer, so that 1251 # First do the raw seek, then empty the read buffer, so that
1246 # if the raw seek fails, we don't lose buffered data forever. 1252 # if the raw seek fails, we don't lose buffered data forever.
1247 pos = self.raw.seek(pos, whence) 1253 pos = self.raw.seek(pos, whence)
1248 with self._read_lock: 1254 with self._read_lock:
1249 self._reset_read_buf() 1255 self._reset_read_buf()
(...skipping 595 matching lines...) Expand 10 before | Expand all | Expand 10 after
1845 if cookie != 0: 1851 if cookie != 0:
1846 raise UnsupportedOperation("can't do nonzero end-relative seeks" ) 1852 raise UnsupportedOperation("can't do nonzero end-relative seeks" )
1847 self.flush() 1853 self.flush()
1848 position = self.buffer.seek(0, 2) 1854 position = self.buffer.seek(0, 2)
1849 self._set_decoded_chars('') 1855 self._set_decoded_chars('')
1850 self._snapshot = None 1856 self._snapshot = None
1851 if self._decoder: 1857 if self._decoder:
1852 self._decoder.reset() 1858 self._decoder.reset()
1853 return position 1859 return position
1854 if whence != 0: 1860 if whence != 0:
1855 raise ValueError("invalid whence (%r, should be 0, 1 or 2)" % 1861 raise ValueError("unsupported whence (%r)" % (whence,))
1856 (whence,))
1857 if cookie < 0: 1862 if cookie < 0:
1858 raise ValueError("negative seek position %r" % (cookie,)) 1863 raise ValueError("negative seek position %r" % (cookie,))
1859 self.flush() 1864 self.flush()
1860 1865
1861 # The strategy of seek() is to go back to the safe start point 1866 # The strategy of seek() is to go back to the safe start point
1862 # and replay the effect of read(chars_to_skip) from there. 1867 # and replay the effect of read(chars_to_skip) from there.
1863 start_pos, dec_flags, bytes_to_feed, need_eof, chars_to_skip = \ 1868 start_pos, dec_flags, bytes_to_feed, need_eof, chars_to_skip = \
1864 self._unpack_cookie(cookie) 1869 self._unpack_cookie(cookie)
1865 1870
1866 # Seek back to the safe start point. 1871 # Seek back to the safe start point.
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
2065 def errors(self): 2070 def errors(self):
2066 return None 2071 return None
2067 2072
2068 @property 2073 @property
2069 def encoding(self): 2074 def encoding(self):
2070 return None 2075 return None
2071 2076
2072 def detach(self): 2077 def detach(self):
2073 # This doesn't make sense on StringIO. 2078 # This doesn't make sense on StringIO.
2074 self._unsupported("detach") 2079 self._unsupported("detach")
OLDNEW
« no previous file with comments | « Doc/library/os.rst ('k') | Lib/os.py » ('j') | no next file with comments »

RSS Feeds Recent Issues | This issue
This is Rietveld cbc36f91f3f7