[Python-Dev] proposed os.fspath() change (original) (raw)

Ethan Furman ethan at stoneleaf.us
Wed Jun 15 14:46:21 EDT 2016


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:

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



More information about the Python-Dev mailing list