
On Thu, Dec 2, 2021 at 9:48 AM Eric Fahlgren <ericfahlgren@gmail.com> wrote:
wait, what? It seems so clear to me that "PathLike" (as a type specifier) would mean: anything that can be passed into os.fspath to give me a path. (or, of course to the stdlib functions that take paths)
Isn't the entire purpose of os.fspath that you can write code like:
def fun(some_kind_of_path): some_kind_of_path = os.fspath(some_kind_of_path)
(or just pass it to a function you takes PathLIke)
and go on your merry way -- e.g. duck typing, baby!
Is there really no way to annotate that simply now?
Assuming you want the return value of 'fun' to be covariant with the path input, I believe you would say this:
I just read the wikipedia page on "Covariant return type", and I either misunderstood what it means, or it's not relevant to my intended example.
def fun(some_kind_of_path: str) -> str: ... def fun(some_kind_of_path: bytes) -> bytes: ... def fun(some_kind_of_path: os.PathLike[AnyStr]) -> AnyStr: some_kind_of_path = os.fspath(some_kind_of_path) # transform it return some_kind_of_path
Ahh I see, I wasn't intending, in my example, to return the path -- my intent was a function that would need to use the path, to, e.g. open a file. This Strikes me as a very common use case -- you want your users to be able to pass multiple different types in, as long as they can be used as a path. I have a LOT of code that does this -- for years it accepted only string paths, and now I'm updating it to take PathLike as well. My usual code is one of: def fun_that_opens_a_file(the_path): # if I'm working with an "old" library, or one that, e.g. wraps a C lib: the_path = os.fspath(the_path) # if I'm working with things I know will take a Path object: the_path = Path(the_path)
I would love to be shown how to do this with just a one-line declaration of 'fun', but I've given up trying to figure it out.
Darn. could you at least use a Union type: def fun_that_opens_a_file(the_path: Union[str, Path]): ... which isn't too bad. Personally, I think accepting bytes is the way of madness, but you could add that too. On Thu, Dec 2, 2021 at 12:32 PM Brett Cannon <brett@python.org> wrote:
wait, what? It seems so clear to me that "PathLike" (as a type specifier) would mean: anything that can be passed into os.fspath to give me a path. (or, of course to the stdlib functions that take paths)
That is not what the docs say: https://docs.python.org/3/library/os.html#os.PathLike. And as the creator of that ABC it's very much on purpose (see https://www.python.org/dev/peps/pep-0519/ for details).
in my code I just take pathlib.Path or pathlib.PurePath and I'm done as I don't want to be dealing with encoded file paths and instead with objects
Sorry, I wasn't clear. By "PathLike" (as a type specifier)" I meant using it as, well, a type specifier, not as an ABC -- often we can use an ABC as a type specifier, but not always. But you've prompted me to go re-read the PEP and I see this: """ Provide specific type hinting support There was some consideration to providing a generic typing.PathLike class which would allow for e.g. typing.PathLike[str] to specify a type hint for a path object which returned a string representation. While potentially beneficial, the usefulness was deemed too small to bother adding the type hint class. This also removed any desire to have a class in the typing module which represented the union of all acceptable path-representing types as that can be represented with typing.Union[str, bytes, os.PathLike] easily enough and the hope is users will slowly gravitate to path objects only. """ I didn't pay any attention to that at the time, as I wasn't paying attention to typing. But personally, I think I do have that desire :-) But I can see that "the hope is users will slowly gravitate to path objects only". would lead to: that represent file paths. For my part, I'm not interested in encoded paths (e.g. bytes) -- that is absolutely not the right boundary to deal with file system encoding. (that's mentioned in the PEP) But I also don't want my users (or me, with old code, scripts, etc) to have to suddenly go in and wrap a call to Path() everywhere in order to continue to use my library. String paths are ubiquitous, and I think here to stay. I really like PEP 519 -- I think it not only provides a transition, but also a future in which Path objects and string paths can continue to play well together. While Union[PathLike, str] is a pretty light lift, this is one tiny example of what we "typing skeptics" are concerned about: a transition away from full on dynamic typing to a more static style. Maybe that won't come to pass -- we'll see. -CHB -- Christopher Barker, PhD (Chris) Python Language Consulting - Teaching - Scientific Software Development - Desktop GUI and Web Development - wxPython, numpy, scipy, Cython