On Thu, Dec 2, 2021 at 9:48 AM Eric Fahlgren <ericfahlg...@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 <br...@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).
>

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:

>  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
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
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/OMMZAMRLS7KHZ2PCS2VKK2IO4AYEIQSJ/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to