Subclass `pathlib.Path` fails

You can subclass the concrete implementation, so this works:

class Path(type(pathlib.Path())):

Here's what I did with this:

import pathlib

class Path(type(pathlib.Path())):
    def open(self, mode='r', buffering=-1, encoding=None, errors=None, newline=None):
        if encoding is None and 'b' not in mode:
            encoding = 'utf-8'
        return super().open(mode, buffering, encoding, errors, newline)

Path('/tmp/a.txt').write_text("я")

You may be able to simplify your life depending on why you want to extend Path (or PosixPath, or WindowsPath). In my case, I wanted to implement a File class that had all the methods of Path, and a few others. However, I didn't actually care if isinstance(File(), Path).

Delegation works beautifully:

class File:

    def __init__(self, path):
        self.path = pathlib.Path(path)
        ...

    def __getattr__(self, attr):
        return getattr(self.path, attr)

    def foobar(self):
        ...

Now, if file = File('/a/b/c'), I can use the entire Path interface on file, and also do file.foobar().


Here is the definition of the Path class. It does something rather clever. Rather than directly returning an instance of Path from its __new__(), it returns an instance of a subclass, but only if it's been invoked directly as Path() (and not as a subclass).

Otherwise, it expects to have been invoked via either WindowsPath() or PosixPath(), which both provide a _flavour class attribute via multiple inheritance. You must also provide this attribute when subclassing. You'll probably need to instantiate and/or subclass the _Flavour class to do this. This is not a supported part of the API, so your code might break in a future version of Python.

TL;DR: This idea is fraught with peril, and I fear that my answers to your questions will be interpreted as approval rather than reluctant assistance.

Tags:

Oop

Python 3.4