Some `isinstance(obj, os.PathLike)` widen the type of `obj`
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 20.6k
- Forks
- 3.3k
- PR merge metrics
- PR metrics pending
Description
Bug Report
Given an object of type Union[None, str, pathlib.Path] the revealed type before and after a check
if isinstance(obj, os.PathLike):
# code
widens from the given type before to builtin.object afterwards.
To Reproduce
Unfortunately, I have not been able to make a minimal reproducer, since all my attempts have type checked fine.
We've encounted this in this commit of the PR https://github.com/systemd/mkosi/pull/2373. The codebase is stdlib only and targets Python 3.9 (because it is shipped in RHEL).
One of the two examples can be found in the function built_uki here. The incoming Context object is a dataclass that holds many things, but relevant for this issue is context.config.secure_boot_key, which has type Union[None, str, pathlib.Path]. This type is defined on the dataclass and mypy reveals it at the beginning of the function.
Adding a lot of reveal_type statements I could find that this line building a command line for a program
reveal_type(context.config.secure_boot_key)
if isinstance(context.config.secure_boot_key, os.PathLike):
options += ["--ro-bind", context.config.secure_boot_key, context.config.secure_boot_key]
reveal_type(context.config.secure_boot_key)
switches the revealed type:
mkosi/__init__.py:1906:25: note: Revealed type is "Union[pathlib.Path, builtins.str]"
mkosi/__init__.py:1909:25: note: Revealed type is "builtins.object"
mkosi/__init__.py:1931:38: error: List item 1 has incompatible type "object"; expected "Union[Path, str]" [list-item]
"--pcr-private-key", context.config.secure_boot_key,
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Found 1 error in 1 file (checked 42 source files)
Looking further the changes in the commit, not all isinstance(context.config.secure_boot_key, os.PathLike) checks added there suffer from this problem.
The problem has been encountered with
$ mypy --version
mypy 1.8.0 (compiled: no)
but pyright reveals the proper type.
Expected Behavior
The type of the object does not change.
Actual Behavior
The type is widened to builtin.object
mkosi/__init__.py:1906:25: note: Revealed type is "Union[pathlib.Path, builtins.str]"
mkosi/__init__.py:1909:25: note: Revealed type is "builtins.object"
mkosi/__init__.py:1931:38: error: List item 1 has incompatible type "object"; expected "Union[Path, str]" [list-item]
"--pcr-private-key", context.config.secure_boot_key,
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Found 1 error in 1 file (checked 42 source files)
The problem can be worked around by changing the check
-if isinstance(context.config.secure_boot_key, os.PathLike):
+if context.config.secure_boot_key and not isinstance(context.config.secure_boot_key, str):
Your Environment
- Mypy version used: 1.8.0
- Mypy command-line flags: None
- Mypy configuration options from
mypy.ini(and other config files): The following section inpyproject.tomlis used to configure mypy:
[tool.mypy]
python_version = 3.9
# belonging to --strict
warn_unused_configs = true
disallow_any_generics = true
disallow_subclassing_any = true
disallow_untyped_calls = true
disallow_untyped_defs = true
disallow_untyped_decorators = true
disallow_incomplete_defs = true
check_untyped_defs = true
no_implicit_optional = true
warn_redundant_casts = true
warn_unused_ignores = false
warn_return_any = true
no_implicit_reexport = true
# extra options not in --strict
pretty = true
show_error_codes = true
show_column_numbers = true
warn_unreachable = true
allow_redefinition = true
strict_equality = true
- Python version used: 3.11.7 on Arch Linux
I'm happy to provide more details
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the reported behavior from the mkosi/init.py built_uki example, using mypy 1.8.0 and the shown Union[None, str, pathlib.Path] value. Trace the isinstance narrowing and add a regression case showing that the type remains usable as Union[Path, str] after the check.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100