Search code examples
pythonpython-typingmypy

How should a NamedTemporaryFile be annotated?


I tried typing.IO as suggested in Type hint for a file or file-like object?, but it doesn't work:

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()))

for this, mypy tells me:

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

and Python runs fine. So the code is ok.


Solution

  • I don't think this can be easily type hinted.

    If you check the definition of NamedTemporaryFile, you'll see that it's a function that ends in:

    return _TemporaryFileWrapper(file, name, delete)
    

    And _TemporaryFileWrapper is defined as:

    class _TemporaryFileWrapper:
    

    Which means there isn't a super-class that can be indicated, and _TemporaryFileWrapper is "module-private". It also doesn't look like it has any members that make it a part of an existing Protocol * (except for Iterable and ContextManager; but you aren't using those methods here).

    I think you'll need to use _TemporaryFileWrapper and ignore the warnings:

    from tempfile import _TemporaryFileWrapper  # Weak error
    
    def example(tmp: _TemporaryFileWrapper) -> str:
        print(tmp.file)
        return tmp.name
    

    If you really want a clean solution, you could implement your own Protocol that includes the attributes you need, and have it also inherit from Iterable and ContextManager. Then you can type-hint using your custom Protocol.


    * It was later pointed out that it does fulfil IO, but the OP requires attributes that aren't in IO, so that can't be used.