python / python/cpython

'_Stream' object has no attribute 'seekable'

Aperta
#124,293 7 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

3.12 3.13 3.14 stdlib type-bug
Lingua principale
Python
Stelle
77.2k
Fork
35.9k
Metriche di merge delle PR
Metriche PR in attesa

Descrizione

Bug report

Bug description:

From a recent application, I have found tarfile._Stream doesn't have a seekable() method. A quick reproduction of the problem is as follows:

import tarfile
import io

data = b"Test data."
buf = io.BytesIO()
with tarfile.open(fileobj=buf, mode="w") as tf:
    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|")
for entry in tf:
    f = tf.extractfile(entry)  # `f` is in type of `class ExFileObject(io.BufferedReader)`
    f.seekable()  # AttributeError
    f.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.

CPython versions tested on:

3.10, 3.11, 3.12, 3.13, CPython main branch

Operating systems tested on:

Linux, Windows

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Direzione di ricerca

Inizia eseguendo la riproduzione fornita di tarfile in r| mode, quindi esamina tarfile._Stream ed ExFileObject in tarfile.py insieme a _io__Buffered_seek_impl() in Modules/_io/bufferedio.c. Determina il comportamento appropriato di seek per gli stream di sola avanzamento e verifica che gli AttributeErrors segnalati di seekable() e seek() siano risolti senza interrompere la semantica dello streaming.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
python
Ambito
backend
Tipo di issue
Bug
Difficoltà
4/5
Tempo stimato
3-5 giorni
Stato di attività
Ferma
Chiarezza
Abbastanza chiara
Idoneità per principianti
38/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.