pyrefly
pyrefly copied to clipboard
Type Inference for `Popen.communicate()`
Describe the Bug
import subprocess
p = subprocess.Popen(["ls"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = p.communicate()
stdout.decode("utf-8") # Object of class `str` has no attribute `decode` [missing-attribute]
stderr.decode("utf-8") # Object of class `str` has no attribute `decode` [missing-attribute]
assert isinstance(stdout, bytes)
assert not isinstance(stdout, str)
pyrefly infers stdout and stderr as str, but they are bytes unless text mode is enabled.
Per the Python doc
By default, all communication is in bytes, and therefore any "input" should be bytes, and the (stdout, stderr) will be bytes. If in text mode (indicated by self.text_mode), any "input" should be a string, and (stdout, stderr) will be strings decoded according to locale encoding, or by "encoding" if set. Text mode is triggered by setting any of text, encoding, errors or universal_newlines.
Inside the communicate method:
if stdout is not None:
# it's bytes here
stdout = b''.join(stdout)
if self.text_mode:
if stdout is not None:
# reassigned as str here
stdout = self._translate_newlines(stdout,
self.stdout.encoding,
self.stdout.errors)
.....
Expected
pyrefly infers the correct types of stdout and stderr
Sandbox Link
(Only applicable for extension issues) IDE Information
pyrefly 0.15.0
A simple snippet:
def pp(flag: bool) -> str | int:
if flag:
return "STR"
return 123
a = pp(True)
assert a.lower() == "str"
Result:
....: Object of class `int` has no attribute `lower` [missing-attribute]
Just a note for whenever someone can take this up: we have a series of issues that are related to some combination of overload and __new__ resolution, it's not always immediately obvious which is responsible.
In this case there is no __new__ so I think the bug must be in overload resolution of __init__, which is heavily overloaded including on the self parameter, and the overload probably needs to correctly "pin" the type argument.
This may be connected to the need for a backtracking-like mechanism in overload resolution