I am using subprocess.CompletedProcess as a return type of a function. When running mypy with --strict, it complains about Missing type parameters for generic type "CompletedProcess". This is a short example for which the problem occurs:
import subprocess
def run_command() -> subprocess.CompletedProcess:
return subprocess.CompletedProcess(args=[], returncode=0, stdout='')
I do not understand how CompletedProcess is a generic. I checked the reference (https://docs.python.org/3.9/library/subprocess.html#subprocess.CompletedProcess) and can't find any mention.
Randomly adding a generic parameter, for example -> subprocess.CompletedProcess[str], removes the error, but obviously that's not the point. I'd like to be able to hint the return type without defining a generic parameter.
I am using python 3.8.5 and mypy 0.761 and 0.910 (both give the same output).
The output (stdout/stderr) of a subprocess can be either str or bytes, depending on the arguments. The generic parameter to CompletedProcess is required to indicate the type of this.
import subprocess
def run_some_command() -> 'subprocess.CompletedProcess[str]':
"""Run some subprocess that captures output as ``str``"""
return subprocess.CompletedProcess(args=[], returncode=0, stdout='')
def run_other_command() -> 'subprocess.CompletedProcess[bytes]':
"""Run some subprocess that captures output as ``bytes``"""
return subprocess.CompletedProcess(args=[], returncode=0, stdout=b'')
reveal_type(run_some_command().stdout) # note: Revealed type is 'builtins.str*'
Since only the type hint but not the runtime subprocess.CompletedProcess type is generic, it must be quoted.
The type declarations for the standard library are part of typeshed. In specific, CompletedProcess is currently defined as follows:
class CompletedProcess(Generic[_T]):
# morally: _CMD
args: Any
returncode: int
# These are really both Optional, but requiring checks would be tedious
# and writing all the overloads would be horrific.
stdout: _T
stderr: _T
def __init__(self, args: _CMD, returncode: int, stdout: Optional[_T] = ..., stderr: Optional[_T] = ...) -> None: ...
def check_returncode(self) -> None: ...
if sys.version_info >= (3, 9):
def __class_getitem__(cls, item: Any) -> GenericAlias: ...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With