0

I failed to sublcass pathlib.Path, see my question here

Hacky solutions were offered, the linter complains about them. What I'm doing at the moment is this:

from pathlib import Path
class ExtendedPath:
    def __init__(self, path):
        self.orig_path_object = Path(path)

So, no inheritance from path. But now in order to access methods of Path I have to refer to the attribute orig_path_object which is not convenient.

My question: I wonder if there is an elegant way to make methods of Path available to ExtendedPath without inheritence, specifically, through the orig_path_object.

Alex Deft
  • 2,531
  • 1
  • 19
  • 34
  • Does this: https://stackoverflow.com/questions/7749914/add-method-to-loaded-class-module-in-python?lq=1 answer your initial question? – Krish May 09 '20 at 21:03

2 Answers2

0

Add this method:

    def __getattr__(self, item):
        return getattr(self.orig_path_object, item)
Alex Deft
  • 2,531
  • 1
  • 19
  • 34
-1

You can try to extend the the getattr functionality by checking if the attribute is something belonging to the orig_path_object or not. If so, delegate that to orig_path_object.

from pathlib import Path


class ExtendedPath:
    def __init__(self, path):
        self.orig_path_object = Path(path)

    def __getattr__(self, item):
        if item in self.orig_path_object.__dict__:
            return getattr(self.orig_path_object, item)
        else:
            return ... # handle normal case

epath = ExtendedPath(Path('.'))
print(epath.cwd())  # should print the cwd from orig_path_object
rdas
  • 20,604
  • 6
  • 33
  • 46
  • Exactly what I'm looking for. Can you please fill the missing part? how do you handle normal cases and make it revert to methods of `ExtendedPath`? – Alex Deft May 09 '20 at 21:06
  • You'll need to check `item` & call the specific methods. If you use `getattr` there you'll end up with infinite recursion. – rdas May 09 '20 at 21:07
  • Are you saying there's going to be some ugly if statements, as many as my methods? – Alex Deft May 09 '20 at 21:09
  • Or you can get the `item` from `self.__dict__` like `return self.__dict__[item]` – rdas May 09 '20 at 21:10
  • The `else` for the normal case is not needed because `__getattr__()` is only called for attributes which aren't part of the current class. – martineau May 09 '20 at 21:10
  • 1
    It's not. Also, the `__dict__` check isn't going to find methods. – user2357112 May 09 '20 at 21:15
  • @user2357112supportsMonica Yes, I just realized that, so I discarded that if statement and went straight `return self.orig_path_object.__getattr__(item)` that should work – Alex Deft May 09 '20 at 21:18
  • @AlexDeft: Nope. The original path object doesn't have a `__getattr__`, and it would be the wrong thing to delegate to anyway. – user2357112 May 09 '20 at 21:26
  • @user2357112supportsMonica I just verified that. Please figure out a solution for me. How come that `Path` has no `getattr` ! – Alex Deft May 09 '20 at 21:29
  • @AlexDeft: `__getattr__` is a completely different thing from `getattr`. – user2357112 May 09 '20 at 21:30
  • @user2357112supportsMonica Both don't work anyway. I guess we need to tap into the dangerous `getattribute` – Alex Deft May 09 '20 at 21:32