Come dovrebbe essere annotato un NamedTemporaryFile?

Oct 19 2020

Ho provato typing.IOcome suggerito in Suggerimento tipo per un file o un oggetto simile a un file? , ma non funziona:

from __future__ import annotations
from tempfile import NamedTemporaryFile
from typing import IO

def example(tmp: IO) -> str:
    print(tmp.file)
    return tmp.name


print(example(NamedTemporaryFile()))

per questo, mypy mi dice:

test.py:6: error: "IO[Any]" has no attribute "file"; maybe "fileno"?

e Python funziona bene. Quindi il codice è ok.

Risposte

4 Carcigenicate Oct 19 2020 at 21:15

Non penso che questo possa essere facilmente suggerito dal tipo.

Se controlli la definizione di NamedTemporaryFile, vedrai che è una funzione che termina con:

return _TemporaryFileWrapper(file, name, delete)

Ed _TemporaryFileWrapperè definito come:

class _TemporaryFileWrapper:

Ciò significa che non esiste una superclasse che può essere indicata ed _TemporaryFileWrapperè "module-private". Inoltre, non sembra che abbia membri che lo rendono parte di un esistente Protocol(ad eccezione di Iterablee ContextManager; ma non stai usando questi metodi qui).

Penso che dovrai usare _TemporaryFileWrappere ignorare gli avvisi:

from tempfile import _TemporaryFileWrapper  # Weak error

def example(tmp: _TemporaryFileWrapper) -> str:
    print(tmp.file)
    return tmp.name

Se vuoi davvero una soluzione pulita, puoi implementarne una tua Protocol che includa gli attributi di cui hai bisogno e che erediti anche da Iterablee ContextManager. Quindi puoi digitare il suggerimento usando il tuo file personalizzato Protocol.