Subclassing of pathlib.Path
In my case, I wanted to enhance the functionality of pathlib.Path
to include additional methods for file or directory operations specific to my project.
For example, I wanted to add a method that would allow me to easily zip a directory or a file directly from the Path
object:
from pathlib import Path
class EnhancePath(Path):
def zip(self):
print('zip file')
EnhancePath.cwd()
This code works normally on python 3.13
, but it raises an error on python 3.11
and below (I don't test on 3.12
):
AttributeError: type object 'EnhancePath' has no attribute '_flavour'
Solution
Read the source code of pathlib.Path
on python 3.11
:
class Path(PurePath):
def __new__(cls, *args, **kwargs):
if cls is Path:
cls = WindowsPath if os.name == 'nt' else PosixPath
self = cls._from_parts(args)
if not self._flavour.is_supported:
raise NotImplementedError("cannot instantiate %r on your system"
% (cls.__name__,))
return self
class PosixPath(Path, PurePosixPath):
...
class PurePosixPath(PurePath):
_flavour = _posix_flavour
__new__
implements factory function functionality, which means that when you use Path
,
it will return either a PosixPath
or a WindowsPath
object depending on the operating system.
When we subclass Path
, the __new__
method is inherited, and since cls
is not pathlib.Path
,
In the previous example, cls
is __main__.EnhancePath
, so it will not change cls
to PosixPath
or WindowsPath
.
So, we need to optimize our code like this:
import sys
from pathlib import Path
class EnhancePath(Path if sys.version_info >= (3, 13) else type(Path())):
def zip(self):
print('zip file')
EnhancePath.cwd()
type(Path())
will return PosixPath
or WindowsPath
depending on the operating system,