Reputation: 5543
I've seen lines like that in typeshed:
But os.PathLike doesn't appear to be generic. It doesn't let strings be passed.
import os
import pathlib
def test(f: os.PathLike[str]):
print(pathlib.Path(f))
test(r"C:\Program Files")
The above snippet fails Mypy.
Upvotes: 12
Views: 9386
Reputation: 7559
The source code that you link to in your question shows that os.PathLike
is an Abstract Base Class that has a single abstractmethod
, __fspath__
. Due to the implementation of __subclasshook__
, any classes that define __fspath__
are considered to be subclasses of os.PathLike
even if PathLike
is not in the class's method resolution order.
The str
data type, however, does not have an __fspath__
method. As such, it does not conform to the PathLike
interface, and so it makes sense that MyPy should reject an argument of type str
if an argument of type PathLike
was expected.
If your function can accept either a str
object or a PathLike
object, you should annotate the argument as being of type Union[str, PathLike[str]]
, much as typeshed does here.
As an aside, I'm slightly confused as to why you say "os.PathLike
doesn't appear to be generic". The class defines __class_getitem__
, so it's perfectly parametriseable at runtime. In Python >= 3.9:
>>> from os import PathLike
>>> PathLike[str]
os.PathLike[str]
>>> PathLike[bytes]
os.PathLike[bytes]
>>> PathLike['idk, anything you like really']
os.PathLike['idk, anything you like really']
Upvotes: 12