How shutil
was converted to accept pathlib.Path
objects in Python 3.6
As mentioned at in this answer, shutil in Python 3.6 can take pathlib.Path
objects.
Since this felt quite magic, I decided to investigate a little bit how it was implemented to see if I would be able to reuse this magic on my own classes.
The improvement was a result of PEP 519.
This generalized a lot of stdlib functionality, and documentation was not consistently updated as a result, including most of shutil
which as of 3.7 only documents support in a single function. Welcome to the joys of dynamic typing.
Where documented, the stlib links to the glossary for "path-like objects".
An object representing a file system path. A path-like object is either a str or bytes object representing a path, or an object implementing the os.PathLike protocol. An object that supports the os.PathLike protocol can be converted to a str or bytes file system path by calling the os.fspath() function; os.fsdecode() and os.fsencode() can be used to guarantee a str or bytes result instead, respectively. Introduced by PEP 519.
and that then links to the documentation of os.PathLike
:
An abstract base class for objects representing a file system path, e.g. pathlib.PurePath.
New in version 3.6.
abstractmethod __fspath__()
Return the file system path representation of the object.
The method should only return a str or bytes object, with the preference being for str.
The key implementation commits seem to be:
If you want to implement your own path-like classes, you can do it like:
#!/usr/bin/env python3
class MyPath:
def __init__(self, path):
self.path = path
def __fspath__(self):
return self.path
with open(MyPath('f'), 'w'):
pass
Tested in Python 3.6.7, Ubuntu 18.10.