On 06/15/2016 10:59 AM, Brett Cannon wrote:
On Wed, 15 Jun 2016 at 09:48 Guido van Rossum wrote:
These are really two separate proposals.
I'm okay with checking the return value of calling obj.__fspath__;
that's an error in the object anyways, and it doesn't matter much
whether we do this or not (though when approving the PEP I
considered this and decided not to insert a check for this). But it
doesn't affect your example, does it? I guess it's easier to raise
now and change the API in the future to avoid raising in this case
(if we find that raising is undesirable) than the other way around,
so I'm +0 on this.
+0 from me as well. I know in some code in the stdlib that has been
ported which prior to adding support was explicitly checking for
str/bytes this will eliminate its own checking (obviously not a
motivating factor as it's pretty minor).
If we accept both parts of this proposal the checking will have to stay
in place as the original argument may not have been bytes, str, nor
os.PathLike.
The other proposal (passing anything that's not understood right
through) is more interesting and your use case is somewhat
compelling. Catching the exception coming out of os.fspath() would
certainly be much messier. The question remaining is whether, when
this behavior is not desired (e.g. when the caller of os.fspath()
just wants a string that it can pass to open()), the condition of
passing that's neither a string not supports __fspath__ still
produces an understandable error.
This is no different than before os.fspath() existed -- if the function
wasn't checking that the "filename" was a str but just used it as-is,
then whatever strange, possibly-hard-to-debug error they would get now
is the same as what they would have gotten before.
I'm not sure that that's the case.
E.g. open() accepts file descriptors in addition to paths, but I'm
not sure that accepting an integer is a good idea in most cases --
it either gives a mystery "Bad file descriptor" error or starts
reading/writing some random system file, which it then closes once
the stream is closed.
My vision of os.fspath() is simply to reduce rich-path objects to their
component str or bytes representation, and pass anything else through.
The advantage:
- if os.open accepts str/bytes/fd it can prep the argument by
calling os.fspath() and then do it's argument checking all
in one place;
- if lzma accepts bytes/str/filelike-obj it can prep its argument
by calling os.fspath() and then do it's argument checking all in
one place
- if Path accepts str/os.PathLike it can prep it's argument(s)
with os.fspath() and then do its argument checking all in one
place.
The FD issue of magically passing through an int was also a concern when
Ethan brought this up in an issue on the tracker. My argument is that
FDs are not file paths and so shouldn't magically pass through if we're
going to type-check anything or claim os.fspath() only works with paths
(FDs are already open file objects). So in my view either we go ahead
and type-check the return value of __fspath__() and thus restrict
everything coming out of os.fspath() to Union[str, bytes] or we don't
type check anything and be consistent that os.fspath() simply does is
call __fspath__() if present.
This is better than what os.fspath() currently does as it has all the
advantages listed above, but why is checking the output of __fspath__
incompatible with not checking anything else?
And just because I'm thinking about it, I would special-case the FDs,
not os.PathLike (clearer why you care and faster as it skips the
override of __subclasshook__):
# Can be a single-line ternary operator if preferred.
if not isinstance(filename, int):
filename = os.fspath(filename)
That example will not do the right thing in the lzma case.
--
~Ethan~
_______________________________________________
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe:
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com