Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

read of SpooledTemporaryFile returns bytes, mypy assumes str #3360

Closed
maweki opened this issue Oct 14, 2019 · 4 comments · Fixed by #3526
Closed

read of SpooledTemporaryFile returns bytes, mypy assumes str #3360

maweki opened this issue Oct 14, 2019 · 4 comments · Fixed by #3526
Labels
stubs: false negative Type checkers do not report an error, but should stubs: false positive Type checkers report false errors

Comments

@maweki
Copy link

maweki commented Oct 14, 2019

I think this is correct here and not in the mypy repo (if I'm wrong, I am happy to open a ticket there):

following code

from tempfile import SpooledTemporaryFile
stderrfile = SpooledTemporaryFile()
sterr_output = stderrfile.read().decode()

works fine with python3.7 . Using mypy (also with python 3.7) I get the following error:

$ python3 -m mypy test.py 
test.py:3: error: "str" has no attribute "decode"; maybe "encode"?

Mypy incorrectly assumes that the result of the read is a str but using the interactive interpreter you'll see that the read method actually returns a byte object. The type annotations (https://github.com/python/typeshed/blob/master/stdlib/3/tempfile.pyi) say AnyStr as return type which is too narrow in this case.

@srittau srittau added reason: inexpressable Closed, because this can't be expressed within the current type system stubs: false negative Type checkers do not report an error, but should stubs: false positive Type checkers report false errors labels Oct 14, 2019
@srittau
Copy link
Collaborator

srittau commented Oct 14, 2019

Unfortunately, there is no good way to express this in typeshed at this point. I have filed python/typing#680, but I don't foresee that this will be implemented any time soon. The best you could do is to use an explicit type annotation:

from tempfile import SpooledTemporaryFile
stderrfile: SpooledTemporaryFile[bytes] = SpooledTemporaryFile()
sterr_output = stderrfile.read().decode()

@maweki
Copy link
Author

maweki commented Oct 14, 2019

@srittau ah, okay. Now I understand the problem. If I open this in w+ mode read returns str and in (the default) w+b mode it returns byte.

Yeah, the question is whether the annotation is correct in giving the restricted type AnyStr or the more unrestricted type Union[str,bytes]. As it turns out, in my case I can just change the mode since I only use string data anyways. But this is a problem in general.

@maweki
Copy link
Author

maweki commented Oct 17, 2019

@srittau
The question is whether the annotation is correct in giving the restricted type AnyStr or the less restricted type Union[AnyStr,bytes]. Can you elaborate on that?

If I'd write a function with multiple return types, I would annotate it this way.

@srittau
Copy link
Collaborator

srittau commented Oct 17, 2019

A Union return type is actually more restricted than an any type. We try to avoid Union return types, since it forces the user to use isinstance checks, especially in cases like this, where the user will know in the majority of cases what the return type will be.

@srittau srittau removed the reason: inexpressable Closed, because this can't be expressed within the current type system label Sep 27, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stubs: false negative Type checkers do not report an error, but should stubs: false positive Type checkers report false errors
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants