diff --git a/Doc/library/io.rst b/Doc/library/io.rst index 7eec1f87583b87..04cb4a5fc36ed7 100644 --- a/Doc/library/io.rst +++ b/Doc/library/io.rst @@ -168,6 +168,19 @@ High-level Module Interface :func:`os.stat`) if possible. +.. data:: SEEK_SET + SEEK_CUR + SEEK_END + + Parameters to the :meth:`~IOBase.seek` method, + used to specify the relative position + Their values are 0, 1, and 2, respectively. + + .. seealso:: + + :data:`os.SEEK_SET`, :data:`os.SEEK_CUR`, and :data:`os.SEEK_END`. + + .. function:: open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None) This is an alias for the builtin :func:`open` function. @@ -405,18 +418,17 @@ I/O Base Classes .. method:: seek(offset, whence=SEEK_SET, /) - Change the stream position to the given byte *offset*. *offset* is - interpreted relative to the position indicated by *whence*. The default - value for *whence* is :data:`SEEK_SET`. Values for *whence* are: + Change the stream position to the given byte *offset*, + and return the new absolute position as an integer. + *offset* is interpreted relative to the position indicated by *whence*. + Valid values for *whence* are: - * :data:`SEEK_SET` or ``0`` -- start of the stream (the default); + * :data:`SEEK_SET` -- seek from the start of the stream (the default); *offset* should be zero or positive - * :data:`SEEK_CUR` or ``1`` -- current stream position; *offset* may - be negative - * :data:`SEEK_END` or ``2`` -- end of the stream; *offset* is usually - negative - - Return the new absolute position. + * :data:`SEEK_CUR` -- seek from current stream position; + *offset* may be negative + * :data:`SEEK_END` -- seek from the end of the stream; + *offset* is usually negative .. versionadded:: 3.1 The ``SEEK_*`` constants. @@ -911,21 +923,22 @@ Text I/O .. method:: seek(offset, whence=SEEK_SET, /) - Change the stream position to the given *offset*. Behaviour depends on - the *whence* parameter. The default value for *whence* is - :data:`SEEK_SET`. - - * :data:`SEEK_SET` or ``0``: seek from the start of the stream - (the default); *offset* must either be a number returned by - :meth:`TextIOBase.tell`, or zero. Any other *offset* value - produces undefined behaviour. - * :data:`SEEK_CUR` or ``1``: "seek" to the current position; - *offset* must be zero, which is a no-operation (all other values - are unsupported). - * :data:`SEEK_END` or ``2``: seek to the end of the stream; - *offset* must be zero (all other values are unsupported). - - Return the new absolute position as an opaque number. + Change the stream position to the given byte *offset*, + and return the new absolute position as an opaque number. + *offset* is interpreted relative to the position indicated by *whence*. + Valid values for *whence* are: + + * :data:`SEEK_SET` -- seek from the start of the stream (the default); + *offset* must either be a number returned by + :meth:`TextIOBase.tell`, or zero. + Any other *offset* value produces undefined behaviour. + * :data:`SEEK_CUR` -- seek from current stream position; + *offset* must be zero, which is a no-operation. + All other values are unsupported. + * :data:`SEEK_END` -- seek from the end of the stream; + *offset* must be zero. + All other values are unsupported. + .. versionadded:: 3.1 The ``SEEK_*`` constants. diff --git a/Doc/tutorial/inputoutput.rst b/Doc/tutorial/inputoutput.rst index f5cdd84cbadefe..5c415563d7ced7 100644 --- a/Doc/tutorial/inputoutput.rst +++ b/Doc/tutorial/inputoutput.rst @@ -433,10 +433,12 @@ an opaque number when in text mode. To change the file object's position, use ``f.seek(offset, whence)``. The position is computed from adding *offset* to a reference point; the reference point is selected by -the *whence* argument. A *whence* value of 0 measures from the beginning -of the file, 1 uses the current file position, and 2 uses the end of the file as -the reference point. *whence* can be omitted and defaults to 0, using the -beginning of the file as the reference point. :: +the *whence* argument. +A *whence* value of :data:`io.SEEK_SET` measures from the beginning of the file, +:data:`io.SEEK_CUR` uses the current file position, +and :data:`io.SEEK_END` uses the end of the file as the reference point. +*whence* can be omitted and defaults to :data:`!io.SEEK_SET`, +using the beginning of the file as the reference point. :: >>> f = open('workfile', 'rb+') >>> f.write(b'0123456789abcdef') @@ -445,14 +447,14 @@ beginning of the file as the reference point. :: 5 >>> f.read(1) b'5' - >>> f.seek(-3, 2) # Go to the 3rd byte before the end + >>> f.seek(-3, io.SEEK_END) # Go to the 3rd byte before the end 13 >>> f.read(1) b'd' In text files (those opened without a ``b`` in the mode string), only seeks relative to the beginning of the file are allowed (the exception being seeking -to the very file end with ``seek(0, 2)``) and the only valid *offset* values are +to the very file end with ``seek(0, io.SEEK_END)``) and the only valid *offset* values are those returned from the ``f.tell()``, or zero. Any other *offset* value produces undefined behaviour. diff --git a/Doc/whatsnew/3.1.rst b/Doc/whatsnew/3.1.rst index c399f007fd63fb..b4ab0181d04ad9 100644 --- a/Doc/whatsnew/3.1.rst +++ b/Doc/whatsnew/3.1.rst @@ -367,8 +367,8 @@ New, Improved, and Deprecated Modules (Contributed by Benjamin Peterson and Antoine Pitrou.) -* The :mod:`io` module has three new constants for the :meth:`seek` - method :data:`SEEK_SET`, :data:`SEEK_CUR`, and :data:`SEEK_END`. +* The :mod:`io` module has three new constants for the :meth:`~io.IOBase.seek` + method :data:`~io.SEEK_SET`, :data:`~io.SEEK_CUR`, and :data:`~io.SEEK_END`. * The :data:`sys.version_info` tuple is now a named tuple:: diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index 0983a7bd151f40..c13c16268d7637 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -1284,14 +1284,14 @@ _io__Buffered_tell_impl(buffered *self) /*[clinic input] _io._Buffered.seek - target as targetobj: object - whence: int = 0 + offset as targetobj: object + whence: int(c_default='0') = io.SEEK_SET / [clinic start generated code]*/ static PyObject * _io__Buffered_seek_impl(buffered *self, PyObject *targetobj, int whence) -/*[clinic end generated code: output=7ae0e8dc46efdefb input=a9c4920bfcba6163]*/ +/*[clinic end generated code: output=7ae0e8dc46efdefb input=d9ac57b8f178bc05]*/ { Py_off_t target, n; PyObject *res = NULL; diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c index 3ab503c9e3998d..f6fcc9445c0f66 100644 --- a/Modules/_io/bytesio.c +++ b/Modules/_io/bytesio.c @@ -636,22 +636,18 @@ bytesio_iternext(bytesio *self) /*[clinic input] _io.BytesIO.seek - pos: Py_ssize_t - whence: int = 0 + offset as pos: Py_ssize_t + whence: int(c_default='0') = io.SEEK_SET / -Change stream position. +Change stream position and return the new absolute position. -Seek to byte offset pos relative to position indicated by whence: - 0 Start of stream (the default). pos should be >= 0; - 1 Current position - pos may be negative; - 2 End of stream - pos usually negative. -Returns the new absolute position. +Set the byte offset 'offset', relative to position indicated by 'whence': [clinic start generated code]*/ static PyObject * _io_BytesIO_seek_impl(bytesio *self, Py_ssize_t pos, int whence) -/*[clinic end generated code: output=c26204a68e9190e4 input=1e875e6ebc652948]*/ +/*[clinic end generated code: output=c26204a68e9190e4 input=dbeeba9f5f031b6e]*/ { CHECK_CLOSED(self); diff --git a/Modules/_io/clinic/bufferedio.c.h b/Modules/_io/clinic/bufferedio.c.h index 4f40fdadf8ec85..671a4162b8226b 100644 --- a/Modules/_io/clinic/bufferedio.c.h +++ b/Modules/_io/clinic/bufferedio.c.h @@ -697,7 +697,7 @@ _io__Buffered_tell(buffered *self, PyObject *Py_UNUSED(ignored)) } PyDoc_STRVAR(_io__Buffered_seek__doc__, -"seek($self, target, whence=0, /)\n" +"seek($self, offset, whence=io.SEEK_SET, /)\n" "--\n" "\n"); @@ -1098,4 +1098,4 @@ _io_BufferedRandom___init__(PyObject *self, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=b7ddf84a5bc2bf34 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=24202f17f6d2f4f7 input=a9049054013a1b77]*/ diff --git a/Modules/_io/clinic/bytesio.c.h b/Modules/_io/clinic/bytesio.c.h index 9550c8728c251e..b7678ae8e0ee5f 100644 --- a/Modules/_io/clinic/bytesio.c.h +++ b/Modules/_io/clinic/bytesio.c.h @@ -385,16 +385,12 @@ _io_BytesIO_truncate(bytesio *self, PyObject *const *args, Py_ssize_t nargs) } PyDoc_STRVAR(_io_BytesIO_seek__doc__, -"seek($self, pos, whence=0, /)\n" +"seek($self, offset, whence=io.SEEK_SET, /)\n" "--\n" "\n" -"Change stream position.\n" +"Change stream position and return the new absolute position.\n" "\n" -"Seek to byte offset pos relative to position indicated by whence:\n" -" 0 Start of stream (the default). pos should be >= 0;\n" -" 1 Current position - pos may be negative;\n" -" 2 End of stream - pos usually negative.\n" -"Returns the new absolute position."); +"Set the byte offset \'offset\', relative to position indicated by \'whence\':"); #define _IO_BYTESIO_SEEK_METHODDEF \ {"seek", _PyCFunction_CAST(_io_BytesIO_seek), METH_FASTCALL, _io_BytesIO_seek__doc__}, @@ -538,4 +534,4 @@ _io_BytesIO___init__(PyObject *self, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=098584d485420b65 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=f9239531031159de input=a9049054013a1b77]*/ diff --git a/Modules/_io/clinic/fileio.c.h b/Modules/_io/clinic/fileio.c.h index 33a37a389d223d..e97508d5b0af1d 100644 --- a/Modules/_io/clinic/fileio.c.h +++ b/Modules/_io/clinic/fileio.c.h @@ -397,18 +397,9 @@ _io_FileIO_write(fileio *self, PyTypeObject *cls, PyObject *const *args, Py_ssiz } PyDoc_STRVAR(_io_FileIO_seek__doc__, -"seek($self, pos, whence=0, /)\n" +"seek($self, offset, whence=io.SEEK_SET, /)\n" "--\n" -"\n" -"Move to new file position and return the file position.\n" -"\n" -"Argument offset is a byte count. Optional argument whence defaults to\n" -"SEEK_SET or 0 (offset from start of file, offset should be >= 0); other values\n" -"are SEEK_CUR or 1 (move relative to current position, positive or negative),\n" -"and SEEK_END or 2 (move relative to end of file, usually negative, although\n" -"many platforms allow seeking beyond the end of a file).\n" -"\n" -"Note that not all file objects are seekable."); +"\n"); #define _IO_FILEIO_SEEK_METHODDEF \ {"seek", _PyCFunction_CAST(_io_FileIO_seek), METH_FASTCALL, _io_FileIO_seek__doc__}, @@ -421,7 +412,7 @@ _io_FileIO_seek(fileio *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *pos; - int whence = 0; + int whence = SEEK_SET; if (!_PyArg_CheckPositional("seek", nargs, 1, 2)) { goto exit; @@ -536,4 +527,4 @@ _io_FileIO_isatty(fileio *self, PyObject *Py_UNUSED(ignored)) #ifndef _IO_FILEIO_TRUNCATE_METHODDEF #define _IO_FILEIO_TRUNCATE_METHODDEF #endif /* !defined(_IO_FILEIO_TRUNCATE_METHODDEF) */ -/*[clinic end generated code: output=bef47b31b644996a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=7450ee2e06306599 input=a9049054013a1b77]*/ diff --git a/Modules/_io/clinic/iobase.c.h b/Modules/_io/clinic/iobase.c.h index 773e0010477053..6d0a794596496e 100644 --- a/Modules/_io/clinic/iobase.c.h +++ b/Modules/_io/clinic/iobase.c.h @@ -9,19 +9,28 @@ preserve PyDoc_STRVAR(_io__IOBase_seek__doc__, -"seek($self, offset, whence=os.SEEK_SET, /)\n" +"seek($self, offset, whence=io.SEEK_SET, /)\n" "--\n" "\n" -"Change the stream position to the given byte offset.\n" +"Change the stream position and return the new absolute position.\n" "\n" -"The offset is interpreted relative to the position indicated by whence.\n" -"Values for whence are:\n" +" offset\n" +" Offset as byte count.\n" +" Relative to the position given by \'whence\'.\n" +" whence\n" +" Relative position, used by \'offset\'. Valid values are:\n" +" * io.SEEK_SET -- Start of stream (the default)\n" +" * io.SEEK_CUR -- Current position\n" +" * io.SEEK_END -- End of stream\n" "\n" -"* os.SEEK_SET or 0 -- start of stream (the default); offset should be zero or positive\n" -"* os.SEEK_CUR or 1 -- current stream position; offset may be negative\n" -"* os.SEEK_END or 2 -- end of stream; offset is usually negative\n" +"Offsets relative to the start of the stream are usually zero or\n" +"positive, offsets relative to the current stream position may be\n" +"zero, positive or negative, and offsets relative to the end of the\n" +"stream are usually zero or negative.\n" "\n" -"Return the new absolute position."); +"Some platforms allow seeking beyond the end of a file.\n" +"\n" +"Note that not all file objects are seekable."); #define _IO__IOBASE_SEEK_METHODDEF \ {"seek", _PyCFunction_CAST(_io__IOBase_seek), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _io__IOBase_seek__doc__}, @@ -436,4 +445,4 @@ _io__RawIOBase_readall(PyObject *self, PyObject *Py_UNUSED(ignored)) { return _io__RawIOBase_readall_impl(self); } -/*[clinic end generated code: output=301b22f8f75ce3dc input=a9049054013a1b77]*/ +/*[clinic end generated code: output=386caf503869c9c2 input=a9049054013a1b77]*/ diff --git a/Modules/_io/clinic/stringio.c.h b/Modules/_io/clinic/stringio.c.h index d495dd10c16330..f5c2362b87d2b5 100644 --- a/Modules/_io/clinic/stringio.c.h +++ b/Modules/_io/clinic/stringio.c.h @@ -156,16 +156,18 @@ _io_StringIO_truncate(stringio *self, PyObject *const *args, Py_ssize_t nargs) } PyDoc_STRVAR(_io_StringIO_seek__doc__, -"seek($self, pos, whence=0, /)\n" +"seek($self, offset, whence=io.SEEK_SET, /)\n" "--\n" "\n" -"Change stream position.\n" +"Change the stream position and return the new absolute position.\n" "\n" -"Seek to character offset pos relative to position indicated by whence:\n" -" 0 Start of stream (the default). pos should be >= 0;\n" -" 1 Current position - pos must be 0;\n" -" 2 End of stream - pos must be 0.\n" -"Returns the new absolute position."); +"Offsets relative to the start of the stream are usually zero or positive.\n" +"Offsets relative to the current and end of file positions must zero;\n" +"any other values are unsupported, and will raise OSError.\n" +"\n" +"Some platforms allow seeking beyond the end of a file.\n" +"\n" +"Note that not all file objects are seekable."); #define _IO_STRINGIO_SEEK_METHODDEF \ {"seek", _PyCFunction_CAST(_io_StringIO_seek), METH_FASTCALL, _io_StringIO_seek__doc__}, @@ -367,4 +369,4 @@ _io_StringIO_seekable(stringio *self, PyObject *Py_UNUSED(ignored)) { return _io_StringIO_seekable_impl(self); } -/*[clinic end generated code: output=533f20ae9b773126 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=e57b92b21538d3df input=a9049054013a1b77]*/ diff --git a/Modules/_io/clinic/textio.c.h b/Modules/_io/clinic/textio.c.h index 5c2162529ff2dd..c59d3c6cf42d3c 100644 --- a/Modules/_io/clinic/textio.c.h +++ b/Modules/_io/clinic/textio.c.h @@ -756,9 +756,19 @@ _io_TextIOWrapper_readline(textio *self, PyObject *const *args, Py_ssize_t nargs } PyDoc_STRVAR(_io_TextIOWrapper_seek__doc__, -"seek($self, cookie, whence=0, /)\n" +"seek($self, offset, whence=io.SEEK_SET, /)\n" "--\n" -"\n"); +"\n" +"Change the file position and return the new absolute position.\n" +"\n" +"Offsets relative to the start of the file are usually zero or positive.\n" +"Offsets relative to the current and end of file positions must zero;\n" +"any other values are unsupported, and will raise the\n" +"io.UnsupportedOperation exception.\n" +"\n" +"Some platforms allow seeking beyond the end of a file.\n" +"\n" +"Note that not all file objects are seekable."); #define _IO_TEXTIOWRAPPER_SEEK_METHODDEF \ {"seek", _PyCFunction_CAST(_io_TextIOWrapper_seek), METH_FASTCALL, _io_TextIOWrapper_seek__doc__}, @@ -957,4 +967,4 @@ _io_TextIOWrapper_close(textio *self, PyObject *Py_UNUSED(ignored)) { return _io_TextIOWrapper_close_impl(self); } -/*[clinic end generated code: output=e1060638b65e8a63 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=6bdd72dabb204764 input=a9049054013a1b77]*/ diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c index 7fe37eee787e50..fe923c02e5bb0b 100644 --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -953,24 +953,14 @@ portable_lseek(fileio *self, PyObject *posobj, int whence, bool suppress_pipe_er /*[clinic input] _io.FileIO.seek - pos: object - whence: int = 0 + offset as pos: object + whence: int(c_default='SEEK_SET') = io.SEEK_SET / - -Move to new file position and return the file position. - -Argument offset is a byte count. Optional argument whence defaults to -SEEK_SET or 0 (offset from start of file, offset should be >= 0); other values -are SEEK_CUR or 1 (move relative to current position, positive or negative), -and SEEK_END or 2 (move relative to end of file, usually negative, although -many platforms allow seeking beyond the end of a file). - -Note that not all file objects are seekable. [clinic start generated code]*/ static PyObject * _io_FileIO_seek_impl(fileio *self, PyObject *pos, int whence) -/*[clinic end generated code: output=c976acdf054e6655 input=0439194b0774d454]*/ +/*[clinic end generated code: output=c976acdf054e6655 input=ec74977caf7c656b]*/ { if (self->fd < 0) return err_closed(); diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c index 5fd19895311c0c..647afbba868c91 100644 --- a/Modules/_io/iobase.c +++ b/Modules/_io/iobase.c @@ -83,25 +83,31 @@ iobase_unsupported(_PyIO_State *state, const char *message) _io._IOBase.seek cls: defining_class offset: int(unused=True) - whence: int(unused=True, c_default='0') = os.SEEK_SET + Offset as byte count. + Relative to the position given by 'whence'. + whence: int(unused=True, c_default='0') = io.SEEK_SET + Relative position, used by 'offset'. Valid values are: + * io.SEEK_SET -- Start of stream (the default) + * io.SEEK_CUR -- Current position + * io.SEEK_END -- End of stream / -Change the stream position to the given byte offset. +Change the stream position and return the new absolute position. -The offset is interpreted relative to the position indicated by whence. -Values for whence are: +Offsets relative to the start of the stream are usually zero or +positive, offsets relative to the current stream position may be +zero, positive or negative, and offsets relative to the end of the +stream are usually zero or negative. -* os.SEEK_SET or 0 -- start of stream (the default); offset should be zero or positive -* os.SEEK_CUR or 1 -- current stream position; offset may be negative -* os.SEEK_END or 2 -- end of stream; offset is usually negative +Some platforms allow seeking beyond the end of a file. -Return the new absolute position. +Note that not all file objects are seekable. [clinic start generated code]*/ static PyObject * _io__IOBase_seek_impl(PyObject *self, PyTypeObject *cls, int Py_UNUSED(offset), int Py_UNUSED(whence)) -/*[clinic end generated code: output=8bd74ea6538ded53 input=8d4e6adcd08292f2]*/ +/*[clinic end generated code: output=8bd74ea6538ded53 input=bcdff2c6dd398df8]*/ { _PyIO_State *state = get_io_state_by_cls(cls); return iobase_unsupported(state, "seek"); diff --git a/Modules/_io/stringio.c b/Modules/_io/stringio.c index 1856b07108bab6..0e0f36994bb08a 100644 --- a/Modules/_io/stringio.c +++ b/Modules/_io/stringio.c @@ -463,22 +463,24 @@ _io_StringIO_truncate_impl(stringio *self, Py_ssize_t size) /*[clinic input] _io.StringIO.seek - pos: Py_ssize_t - whence: int = 0 + offset as pos: Py_ssize_t + whence: int(c_default='0') = io.SEEK_SET / -Change stream position. +Change the stream position and return the new absolute position. -Seek to character offset pos relative to position indicated by whence: - 0 Start of stream (the default). pos should be >= 0; - 1 Current position - pos must be 0; - 2 End of stream - pos must be 0. -Returns the new absolute position. +Offsets relative to the start of the stream are usually zero or positive. +Offsets relative to the current and end of file positions must zero; +any other values are unsupported, and will raise OSError. + +Some platforms allow seeking beyond the end of a file. + +Note that not all file objects are seekable. [clinic start generated code]*/ static PyObject * _io_StringIO_seek_impl(stringio *self, Py_ssize_t pos, int whence) -/*[clinic end generated code: output=e9e0ac9a8ae71c25 input=e3855b24e7cae06a]*/ +/*[clinic end generated code: output=e9e0ac9a8ae71c25 input=50823fbdc8782825]*/ { CHECK_INITIALIZED(self); CHECK_CLOSED(self); diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c index 6ce90b2ed774c0..27a3cf6744c28f 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -2427,14 +2427,25 @@ _textiowrapper_encoder_setstate(textio *self, cookie_type *cookie) /*[clinic input] _io.TextIOWrapper.seek - cookie as cookieObj: object - whence: int = 0 + offset as cookieObj: object + whence: int(c_default='0') = io.SEEK_SET / + +Change the file position and return the new absolute position. + +Offsets relative to the start of the file are usually zero or positive. +Offsets relative to the current and end of file positions must zero; +any other values are unsupported, and will raise the +io.UnsupportedOperation exception. + +Some platforms allow seeking beyond the end of a file. + +Note that not all file objects are seekable. [clinic start generated code]*/ static PyObject * _io_TextIOWrapper_seek_impl(textio *self, PyObject *cookieObj, int whence) -/*[clinic end generated code: output=0a15679764e2d04d input=0458abeb3d7842be]*/ +/*[clinic end generated code: output=0a15679764e2d04d input=35d7e7156afb3e56]*/ { PyObject *posobj; cookie_type cookie;