Issues with solving value constrained type var in presence of Any
Bug Report
In 1.11.0, classes that inherit from os.PathLike could be used with os.path methods. As of 3.12, these methods claim to accept "any object implementing the os.PathLike protocol". However, in 1.12.0, mypy emits an error.
To Reproduce
import os
class MyPath(os.PathLike):
def __init__(self, path: str):
super().__init__()
self.path = path
def __fspath__(self):
return self.path
print(os.path.abspath(MyPath(".")))
Expected Behavior
Unless I'm missing something, MyPath should be valid to pass, no?
Actual Behavior
pathlike.py:13: error: Value of type variable "AnyStr" of "abspath" cannot be "MyPath | Any"
Your Environment
- Mypy version used: 1.12.0
- Mypy command-line flags: N/A
- Mypy configuration options from
mypy.ini(and other config files): N/A - Python version used: 3.12
Bisects to https://github.com/python/mypy/pull/17458 , probably caused by https://github.com/python/typeshed/pull/12208 Are you interested in opening a PR to typeshed reverting that change?
Note explicitly inheriting from os.PathLike[str] will fix.
~~Looks like the same change may have broken Python 3.8 support of passing a StrPath to these methods. I know 3.8 just went EOL, but I thought I'd let others know in case they also get the Value of type variable "AnyStr" of "abspath" cannot be "Union[str, PathLike[Any], Any]" [type-var] error on Python 3.8.~~
Edit: See my other comment below
Setuptools failure: https://github.com/pypa/setuptools/pull/4688 & https://github.com/pypa/setuptools/actions/runs/11389961011/job/31690481419?pr=4688#step:9:68
Are you interested in picking up reverting that typeshed PR?
Nevermind, after failing to replicate in a typeshed test, and further investigation, mine was an issue with a setuptools declaration that was revealed by mypy 1.12 https://github.com/pypa/setuptools/blob/89b44013c79d2295ac0941e91b6904c0ce5522ba/setuptools/_path.py#L14-L17
if sys.version_info >= (3, 9):
StrPath: TypeAlias = Union[str, os.PathLike[str]] # Same as _typeshed.StrPath
else:
StrPath: TypeAlias = Union[str, os.PathLike]
Changing to:
if TYPE_CHECKING:
StrPath: TypeAlias = Union[str, os.PathLike[str]] # Same as _typeshed.StrPath
else:
# Python 3.8 support
StrPath: TypeAlias = Union[str, os.PathLike]
Which explains why I was only seeing this on 3.8. As far as I'm concerned, I don't see my case as a regression, but rather a mypy finding a missing generic param it didn't see before.
For OP's issue and another related regression I found in setuptools: https://github.com/python/typeshed/pull/12837
For the purposes of making further changes to mypy, here's a repro that's independent of abspath in typeshed:
# mypy: disable-error-code=empty-body
import os
from typing import AnyStr
class MyPath(os.PathLike):
def __init__(self, path: str):
self.path = path
def __fspath__(self):
return self.pat
def abspath(path: os.PathLike[AnyStr] | AnyStr) -> AnyStr: ...
reveal_type(abspath(MyPath(".")))
1.12.1 reverts the typeshed change, so there is no regression. Underlying issue still remains, so changing title. Possibly same thing as https://github.com/python/mypy/issues/11880
(Also linking that https://github.com/python/mypy/issues/3644 was the fix that led to the change in typeshed being attempted)