[Python-ideas] tweaking the file system path protocol
Wolfgang Maier
wolfgang.maier at biologie.uni-freiburg.de
Tue May 23 06:12:11 EDT 2017
What do you think of this idea for a slight modification to os.fspath:
the current version checks whether its arg is an instance of str, bytes
or any subclass and, if so, returns the arg unchanged. In all other
cases it tries to call the type's __fspath__ method to see if it can get
str, bytes, or a subclass thereof this way.
My proposal is to change this to:
1) check whether the type of the argument is str or bytes *exactly*; if
so, return the argument unchanged
2) check wether __fspath__ can be called on the type and returns an
instance of str, bytes, or any subclass (just like in the current version)
3) check whether the type is a subclass of str or bytes and, if so,
return it unchanged
This would have the following implications:
a) it would speed up the very common case when the arg is either a str
or a bytes instance exactly
b) user-defined classes that inherit from str or bytes could control
their path representation just like any other class
c) subclasses of str/bytes that don't define __fspath__ would still work
like they do now, but their processing would be slower
d) subclasses of str/bytes that accidentally define a __fspath__ method
would change their behavior
I think cases c) and d) could be sufficiently rare that the pros
outweigh the cons?
Here's how the proposal could be implemented in the pure Python version
(os._fspath):
def _fspath(path):
path_type = type(path)
if path_type is str or path_type is bytes:
return path
# Work from the object's type to match method resolution of other magic
# methods.
try:
path_repr = path_type.__fspath__(path)
except AttributeError:
if hasattr(path_type, '__fspath__'):
raise
elif issubclass(path_type, (str, bytes)):
return path
else:
raise TypeError("expected str, bytes or os.PathLike object, "
"not " + path_type.__name__)
if isinstance(path_repr, (str, bytes)):
return path_repr
else:
raise TypeError("expected {}.__fspath__() to return str or bytes, "
"not {}".format(path_type.__name__,
type(path_repr).__name__))
More information about the Python-ideas
mailing list