Join GitHub today
Check file type annotations against open mode #2337
I have a function argument whose type I want to limit to a file object that's open for binary reading — i.e. I want only an instance of
from typing import IO def parser(file_obj: IO[bytes]) -> None: pass
As I would expect, mypy runs without complaint on this code:
But it doesn't output an error for this:
In that case, I would want an error along the lines of
I was trying to type check if the file was open in binary mode too, and noticed a few things (and a workaround right at the end of all this)...
mypy -2 doesn't seem to know that io.BufferedReader is there.
If I run mypy in python3 mode, it passes.
Also if I change it to use _io, it works under mypy -2, but not in python3 mode.
With mypy in 3 mode I get:
In python python2.7 and 3.6, the types for io.open are like so.
Hacking about some more I make this mess below which does let me check that every file obj passed into the object is a BufferedReader. Of course, I need to manually cast every instance... not at all nice.
Finally I decide to have a separate open function wrapper for every mode. This way I can use a cast inside it, and the type checker works. Any file not using my custom wrappers also fails - which is great because I know where I have to track things down to check them.
I think this technique would work anywhere you have a factory pattern where the return types are dependent on logic inside the function, or the parameters. As long as number of combinations are not too big that is! (open_rb, open_r, open_w, open_wb)