<div dir="ltr"><br><br><div class="gmail_quote"><div dir="ltr">On Wed, 6 Apr 2016 at 15:22 Paul Moore <<a href="mailto:p.f.moore@gmail.com">p.f.moore@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On 6 April 2016 at 20:39, Brett Cannon <<a href="mailto:brett@python.org" target="_blank">brett@python.org</a>> wrote:<br>
>> I'm a little confused by this. To support the older pathlib, they have<br>
>> to do patharg = str(patharg), because *none* of the proposed<br>
>> attributes (path or __path__) will exist.<br>
>><br>
>> The getattr trick is needed to support the *new* pathlib, when you<br>
>> need a real string. Currently you need a string if you call stdlib<br>
>> functions or builtins. If we fix the stdlib/builtins, the need goes<br>
>> away for those cases, but remains if you need to call libraries that<br>
>> *don't* support pathlib (os.path will likely be one of those) or do<br>
>> direct string manipulation.<br>
>><br>
>> In practice, I see the getattr trick as an "easy fix" for libraries<br>
>> that want to add support but in a minimally-intrusive way. On that<br>
>> basis, making the trick easy to use is important, which argues for an<br>
>> attribute.<br>
><br>
> So then where's the confusion? :) You seem to get the points. I personally<br>
> find `path.__path__() if hasattr(path, '__path__') else path` also readable<br>
> (if obviously a bit longer).<br>
<br>
The confusion is that you seem to be saying that people can use<br>
getattr(path, '__path__', path) to support older versions of Python.<br>
But the older versions are precisely the ones that don't have __path__<br>
so you won't be supporting them.<br></blockquote><div><br></div><div>Because pathlib is provisional the change will go into the next releases of Python 3.4, 3.5, and in 3.6 so new-old will have whatever we do. :) I think the key point is that this sort of thing will occur before you have access to some new built-in or something.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
>> >> >  3. Built-in? (name is dependent on #1 if we add one)<br>
>> >><br>
>> >> fspath() -- and it would be handy to have a function that return either<br>
>> >> the __fspath__ results, or the string (if it was one), or raise an<br>
>> >> exception if neither of the above work out.<br>
>><br>
>> fspath regardless of the name chosen in #1 - a new builtin called path<br>
>> just has too much likelihood of clashing with user code.<br>
>><br>
>> But I'm not sure we need a builtin. I'm not at all clear how<br>
>> frequently we expect user code to need to use this protocol. Users<br>
>> can't use the builtin if they want to be backward compatible, But code<br>
>> that doesn't need backward compatibility can probably just work with<br>
>> pathlib (and the stdlib support for it) directly. For display, the<br>
>> implicit conversion to str is fine. For "get me a string representing<br>
>> the path", is the "path" attribute being abandoned in favour of this<br>
>> special method?<br>
><br>
> Yes.<br>
<br>
OK. So the idiom to get a string from a known Path object would be any of:<br>
<br>
1. str(path)<br>
2. fspath(path)<br>
3. path.__path__()<br>
<br>
(1) is safe if you know you have a Path object, but could incorrectly<br>
convert non-Path objects. (2) is safe in all cases. (3) is ugly. Did I<br>
miss any options?<br></blockquote><div><br></div><div>Other than path.__path__ being an attribute, nope.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
So I think we need a builtin.<br></blockquote><div><br></div><div>Well, the ugliness shouldn't survive forever if the community shifts over to using pathlib while the built-in will. We also don't have a built-in for __index__() so it depends on whether we expect this sort of thing to be the purview of library authors or if normal people will be interacting with it (it's probably both during the transition, but I don't know afterwards).</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
Code that needs to be backward compatible will still have to use<br>
str(path), because neither the builtin nor the __path__ protocol will<br>
exist in older versions of Python.</blockquote><div><br></div><div>str(path) will definitely work, path.__path__ will work if you're running the next set of bugfix releases. fspath(path) will only work in Python 3.6 and newer.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"> Maybe a compatibility library could<br>
add<br>
<br>
try:<br>
    fspath<br>
except NameError:<br>
    try:<br>
        import pathlib<br>
        def fspath(p):<br>
            if isinstance(p, pathlib.Path):<br>
                return str(p)<br>
            return p<br>
    except ImportError:<br>
        def fspath(p):<br>
            return p<br>
<br>
It's messy, like all compatibility code, but it allows code to use<br>
fspath(p) in older versions.<br></blockquote><div><br></div><div>I would tweak it to check for __fspath__ before it resorted to calling str(), but yes, that could be something people use.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
>> I'm inclined to think that if you are writing "pure<br>
>> pathlib" code, pathobj.path looks more readable than fspath(pathobj) -<br>
>> certainly no *less* readable.<br>
><br>
> I don't' know what you mean by "pure pathlib". You mean code that only works<br>
> with pathlib objects? Or do you mean code that accepts pathlib objects but<br>
> uses strings internally?<br>
<br>
I mean code that knows it has a Path object to work with (and not a<br>
string or anything else). But the point is moot if the path attribute<br>
is going away.<br>
<br>
Other than to say that I do prefer the name "path", I just don't think<br>
it's a reasonable name for a builtin. Even if it's OK for user<br>
variables to have the same name as builtins, IDEs tend to colour<br>
builtins differently, which is distracting. (Temporary variables named<br>
"file" or "dir" are the ones I hit frequently...)<br>
<br>
If all we're debating is the name, though, I think we're pretty much there :-)<br></blockquote><div><br></div><div>It seems like __fspath__ may be leading as a name, but not that many people have spoken up. But that is not the only thing still up for debate. :)</div><div><br></div><div>We have not settled on whether a built-in is necessary.  Maybe whatever function we come with should live in pathlib itself and not have it be a built-in?</div><div><br></div><div>We have also not settled on whether __fspath__ should be a method or attribute as that changes the boilerplate one-liner people may use if a built-in isn't available. This is the first half of the protocol.</div><div><br></div><div>What exactly should this helper function do? E.g. does it simply return its argument if __fspath__ isn't defined, or does it check for __fspath__, then if it's an instance of str, then TypeError? This is the second half of the protocol and will end up defining what a "path-like object" represents.<br></div></div></div>