You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
'_Stream' object has no attribute 'seekable' #124293
From a recent application, I have found tarfile._Stream doesn't have a seekable() method. A quick reproduction of the problem is as follows:
importtarfileimportiodata=b"Test data."buf=io.BytesIO()
withtarfile.open(fileobj=buf, mode="w") astf:
ti=tarfile.TarInfo(name="test.txt")
ti.size=len(data)
tf.addfile(tarinfo=ti, fileobj=io.BytesIO(data))
buf.seek(0)
tf=tarfile.open(fileobj=buf, mode="r|")
forentryintf:
f=tf.extractfile(entry) # `f` is in type of `class ExFileObject(io.BufferedReader)`f.seekable() # AttributeErrorf.seek(0) # AttributeError
Output:
Traceback (most recent call last):
File "a.py", line 17, in <module>
print(f.seekable())
File "AppData\Local\Programs\Python\Python310\lib\tarfile.py", line 641, in seekable
return self.fileobj.seekable()
AttributeError: '_Stream' object has no attribute 'seekable'
When opening tarfile with r| mode, ExFileObject.fileobj would be a _Stream object. So when calling ExFileObject.seekable(), as _Stream object dun have seekable() method, it will raise AttributeError.
Also, as BufferedReader.seek() will also check its raw.seekable() (i.e. in Modules/_io/bufferedio.c, func _io__Buffered_seek_impl(), there is a call to _PyIOBase_check_seekable(state, self->raw, Py_True)), f.seek() in the above example will also raise AttributeError.
I have thought of if we can simply define seekable() in _Stream object, but as it is only "forward-seekable", I am not sure if directly returning a true/false in _Stream.seekable() is appropriate or not. However, this issue does break the IOBase interface and there should be a solution.
Thanks for everyone's time and effort for looking into this.
Thank you for the report, @GLGDLY! Confirmed this on 3.12, 3.13, and the main branch. We can't do anything about <3.12, because those are security-only.
I'm pretty sure the fix is to simply define seekable as:
defseekable(self):
returnTrue
This is OK, because AFAIK, there's nothing in the IOBase interface about negative seeking. The requirement in the interface is that if seekable returns False, then seekalways fails with an OSError. Otherwise, it's fine for seek to sometimes work.
Thank you for the report, @GLGDLY! Confirmed this on 3.12, 3.13, and the main branch. We can't do anything about <3.12, because those are security-only.
I'm pretty sure the fix is to simply define seekable as:
defseekable(self):
returnTrue
This is OK, because AFAIK, there's nothing in the IOBase interface about negative seeking. The requirement in the interface is that if seekable returns False, then seekalways fails with an OSError. Otherwise, it's fine for seek to sometimes work.
Generally, it's good courtesy to let someone else write the PR if they have already said they wanted to. Though, thanks for finding the test failures!
Based on the traceback, it seems that this issue is expected behavior, somewhat:
Traceback (most recent call last):
File "/home/zero/Desktop/Projects/Python/cpython/Lib/test/test_tarfile.py", line 520, in test_extractfile_attrs
self.assertRaises(AttributeError, fobj.seekable)
~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: AttributeError not raised by seekable
Though, I'm not sure why AttributeError is something we're testing for here. If it really was intentional to not support seeking, then seekable should just return false, rather than raising.
Activity
ZeroIntensity commentedon Sep 21, 2024
Thank you for the report, @GLGDLY! Confirmed this on 3.12, 3.13, and the main branch. We can't do anything about <3.12, because those are security-only.
I'm pretty sure the fix is to simply define
seekableas:This is OK, because AFAIK, there's nothing in the
IOBaseinterface about negative seeking. The requirement in the interface is that ifseekablereturnsFalse, thenseekalways fails with anOSError. Otherwise, it's fine forseekto sometimes work.Would you like to author the PR?
GLGDLY commentedon Sep 23, 2024
sure, i will handle that these few days
soufrabi commentedon Sep 28, 2024
Can i work on this issue ?
soufrabi commentedon Sep 28, 2024
Upon adding the
seekablefunction it fails test_tarfile testsoufrabi commentedon Sep 28, 2024
Change in Lib/tarfile.py
test_tarfile test fails
ZeroIntensity commentedon Sep 28, 2024
Generally, it's good courtesy to let someone else write the PR if they have already said they wanted to. Though, thanks for finding the test failures!
Based on the traceback, it seems that this issue is expected behavior, somewhat:
Though, I'm not sure why
AttributeErroris something we're testing for here. If it really was intentional to not support seeking, thenseekableshould just return false, rather than raising.cc @serhiy-storchaka, who wrote that test.
soufrabi commentedon Sep 28, 2024
@ZeroIntensity Thanks for the feedback.