From 4d02c2084cd4e2b0adf082604201e25dc09450c5 Mon Sep 17 00:00:00 2001 From: Thomas Kowalski Date: Sun, 18 Oct 2026 17:28:42 +0200 Subject: [PATCH 1/4] fix: FileIO.seekable incorrectly returning false --- Lib/test/test_io/test_fileio.py | 4 ++++ Modules/_io/fileio.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_io/test_fileio.py b/Lib/test/test_io/test_fileio.py index 21a160904a7f1e0..14db757964cf3d7 100644 --- a/Lib/test/test_io/test_fileio.py +++ b/Lib/test/test_io/test_fileio.py @@ -62,6 +62,10 @@ def testSeekTell(self): self.f.seek(-5, 2) self.assertEqual(self.f.tell(), 15) + def testSeekableAfterFailedSeek(self) -> None: + self.assertRaises(OSError, self.f.seek, -1) + self.assertTrue(self.f.seekable()) + def testAttributes(self): # verify expected attributes exist f = self.f diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c index e5cd7aca5de2f17..974369f107e927d 100644 --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -1013,7 +1013,7 @@ portable_lseek(fileio *self, PyObject *posobj, int whence, bool suppress_pipe_er _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS - if (self->seekable < 0) { + if (self->seekable < 0 && (res >= 0 || errno == ESPIPE || posobj == NULL)) { self->seekable = (res >= 0); } From 875e5fb552f40a82002208c864e0bedaaebd49b2 Mon Sep 17 00:00:00 2001 From: Thomas Kowalski Date: Sun, 18 Oct 2026 17:30:22 +0200 Subject: [PATCH 2/4] chore: add release note --- .../next/Library/2026-10-18-17-26-00.gh-issue-159677.fIoSk1.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2026-10-18-17-26-00.gh-issue-159677.fIoSk1.rst diff --git a/Misc/NEWS.d/next/Library/2026-10-18-17-26-00.gh-issue-159677.fIoSk1.rst b/Misc/NEWS.d/next/Library/2026-10-18-17-26-00.gh-issue-159677.fIoSk1.rst new file mode 100644 index 000000000000000..5bc84eb41f1b724 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-10-18-17-26-00.gh-issue-159677.fIoSk1.rst @@ -0,0 +1,2 @@ +Fix :meth:`io.FileIO.seekable` always returning ``False`` for a seekable file +when the first call to :meth:`~io.FileIO.seek` failed. From 06cf12d8abaefd26596dc00a1388bd44f273f3bf Mon Sep 17 00:00:00 2001 From: Thomas Kowalski Date: Sun, 18 Oct 2026 22:19:15 +0200 Subject: [PATCH 3/4] chore: update release note --- .../Library/2026-10-18-17-26-00.gh-issue-159677.fIoSk1.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Misc/NEWS.d/next/Library/2026-10-18-17-26-00.gh-issue-159677.fIoSk1.rst b/Misc/NEWS.d/next/Library/2026-10-18-17-26-00.gh-issue-159677.fIoSk1.rst index 5bc84eb41f1b724..93feb6c41c545a0 100644 --- a/Misc/NEWS.d/next/Library/2026-10-18-17-26-00.gh-issue-159677.fIoSk1.rst +++ b/Misc/NEWS.d/next/Library/2026-10-18-17-26-00.gh-issue-159677.fIoSk1.rst @@ -1,2 +1,2 @@ -Fix :meth:`io.FileIO.seekable` always returning ``False`` for a seekable file -when the first call to :meth:`~io.FileIO.seek` failed. +Fix :class:`io.FileIO` ``seekable`` being cached as false because of an invalid +argument to :meth:`!io.FileIO.seek` From 25fede6464c916c398f1ddf94648d2df38d5f509 Mon Sep 17 00:00:00 2001 From: Thomas Kowalski Date: Wed, 21 Oct 2026 23:12:54 +0200 Subject: [PATCH 4/4] review: update seekable ca ching logic --- Modules/_io/fileio.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c index 974369f107e927d..94a51afa4335457 100644 --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -1013,7 +1013,13 @@ portable_lseek(fileio *self, PyObject *posobj, int whence, bool suppress_pipe_er _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS - if (self->seekable < 0 && (res >= 0 || errno == ESPIPE || posobj == NULL)) { + if (self->seekable < 0 + && !(res < 0 && (errno == EINVAL +#ifdef EOVERFLOW + || errno == EOVERFLOW +#endif + || errno == ENXIO))) + { self->seekable = (res >= 0); }