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

Error with mixing str and pathlib.Path in command line arguments list #13004

Open
amatyukhin0 opened this issue Jun 21, 2022 · 2 comments
Open
Labels
bug mypy got something wrong topic-join-v-union Using join vs. using unions

Comments

@amatyukhin0
Copy link

Bug Report

mypy raises error if list of command line arguments (passing to subprocess.call) contains items of different types (for example, str and pathlib.Path). It can be fixed by adding type hint to variable, but it's too annoying.

To Reproduce

import pathlib
import subprocess

cmd = [pathlib.Path('bash'), '-c', 'echo Hello']
subprocess.call(cmd)

Expected Behavior

mypy should not raise any error.

Actual Behavior

main.py:5: error: Argument 1 to "check_call" has incompatible type "List[object]"; expected "Union[Union[str, bytes, PathLike[str], PathLike[bytes]], Sequence[Union[str, bytes, PathLike[str], PathLike[bytes]]]]"
Found 1 error in 1 file (checked 1 source file)

Why can't mypy recognize cmd type as List[Union[pathlib.Path, str]], not List[object]?

Environment

  • Mypy version used: 0.961
  • Python version used: 3.10
  • Operating system: Linux
@amatyukhin0 amatyukhin0 added the bug mypy got something wrong label Jun 21, 2022
@AlexWaygood AlexWaygood added the topic-join-v-union Using join vs. using unions label Jun 21, 2022
@AlexWaygood
Copy link
Member

In the absence of an explicit annotation, mypy infers the type of cmd as being of type list[object] due to its preference for join/meet operations instead of unions in many situations (see #12056 for more examples of where this causes issues).

As a workaround, you can fix the error here by providing an explicit annotation:

import pathlib
import subprocess
from os import PathLike

# either like this:

cmd2: list[pathlib.Path | str] = [pathlib.Path('bash'), '-c', 'echo Hello']
subprocess.call(cmd2)

# or like this:

cmd3: list[PathLike[str] | str] = [pathlib.Path('bash'), '-c', 'echo Hello']
subprocess.call(cmd3)

Or you can just pass the list to subprocess.call directly, without creating the cmd variable at all:

subprocess.call([pathlib.Path('bash'), '-c', 'echo Hello'])

https://mypy-play.net/?mypy=latest&python=3.10&gist=76f5bc0e9d76d7791490918e829734e1

@KotlinIsland
Copy link
Contributor

this is handled correctly in basedmypy:

import pathlib
import subprocess

cmd = [pathlib.Path("bash"), "-c", "echo Hello"]
reveal_type(cmd)  # list[pathlib.Path | str]
subprocess.call(cmd)  # no error

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong topic-join-v-union Using join vs. using unions
Projects
None yet
Development

No branches or pull requests

3 participants