I would like to enhance the class pathlib.Path
but the simple example above dose not work.
from pathlib import Path
class PPath(Path):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
test = PPath("dir", "test.txt")
Here is the error message I have.
Traceback (most recent call last):
File "/Users/projetmbc/test.py", line 14, in <module>
test = PPath("dir", "test.txt")
File "/anaconda/lib/python3.4/pathlib.py", line 907, in __new__
self = cls._from_parts(args, init=False)
File "/anaconda/lib/python3.4/pathlib.py", line 589, in _from_parts
drv, root, parts = self._parse_args(args)
File "/anaconda/lib/python3.4/pathlib.py", line 582, in _parse_args
return cls._flavour.parse_parts(parts)
AttributeError: type object 'PPath' has no attribute '_flavour'
What I am doing wrong ?
asked Apr 24, 2015 at 14:57
projetmbcprojetmbc1,49411 gold badge1313 silver badges2828 bronze badges
2You 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("я")
answered Dec 6, 2015 at 11:11
Oleh PrypinOleh Prypin34.3k1111 gold badges9494 silver badges100100 bronze badges
4Combining some of the previous answers you could also just write:
class MyPath(pathlib.Path):
_flavour = type(pathlib.Path())._flavour
UPDATE for Python 3.12
In Python 3.12 the pathlib.Path
class now supports subclassing (see What’s New In Python 3.12). Therefore, you can simply access the _flavour
attribute from your subclass without any workaround.
answered Mar 13, 2021 at 12:11
Night TrainNight Train2,59633 gold badges2222 silver badges4040 bronze badges
3Here 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.
answered Apr 24, 2015 at 15:09
KevinKevin30.3k1111 gold badges6666 silver badges8888 bronze badges
4You 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().
answered Mar 1, 2020 at 4:37
4I have been struggling with this too.
Here is what i did, studying from the pathlib module. Seems to me that is the cleaner way to do it, but if the pathlib module changes its implementation, it probably won't hold.
from pathlib import Path
import os
import pathlib
class PPath(Path):
_flavour = pathlib._windows_flavour if os.name == 'nt' else pathlib._posix_flavour
def __new__(cls, *args):
return super(PPath, cls).__new__(cls, *args)
def __init__(self, *args):
super().__init__() #Path.__init__ does not take any arg (all is done in new)
self._some_instance_ppath_value = self.exists() #Path method
def some_ppath_method(self, *args):
pass
test = PPath("dir", "test.txt")
answered Nov 9, 2018 at 18:07
A. MarchandA. Marchand33933 silver badges44 bronze badges
NoteI have opened a bug track here after a little discussion on the Python dev. list.
A temporary solutionSorry for this double answer but here is a way to achieve what I want. Thanks to Kevin that points me to the source of pathlib
and the fact we have here constructors.
import pathlib
import os
def _extramethod(cls, n):
print("=== "*n)
class PathPlus(pathlib.Path):
def __new__(cls, *args):
if cls is PathPlus:
cls = pathlib.WindowsPath if os.name == 'nt' else pathlib.PosixPath
setattr(cls, "extramethod", _extramethod)
return cls._from_parts(args)
test = PathPlus("C:", "Users", "projetmbc", "onefile.ext")
print("File ?", test.is_file())
print("Dir ?", test.is_dir())
print("New name:", test.with_name("new.name"))
print("Drive ?", test.drive)
test.extramethod(4)
This prints the following lines.
File ? False
Dir ? False
New name: C:/Users/projetmbc/new.name
Drive ?
=== === === ===
Anthon
77.9k3434 gold badges206206 silver badges287287 bronze badges
answered Apr 26, 2015 at 16:11
projetmbcprojetmbc1,49411 gold badge1313 silver badges2828 bronze badges
2With the latest Python version, _flavour
, _posix_flavour
are deprecated and we can pass flavour
keyword in our class.
import os
from pathlib import Path
class PPath(Path):
def __init__(self, *args) -> None:
# Determine the flavor based on the operating system
flavour = 'posix' if os.name == 'posix' else 'windows'
# Pass the flavor to the superclass constructor
super().__init__(*args, flavour=flavour)
Barmar
787k5757 gold badges552552 silver badges663663 bronze badges
answered Aug 20, 2024 at 2:41
Chillar AnandChillar Anand29.8k1010 gold badges124124 silver badges144144 bronze badges
2It's work too.
from pathlib import Path
class SystemConfigPath(type(Path())):
def __new__(cls, **kwargs):
path = cls._std_etc()
return super().__new__(cls, path, **kwargs)
@staticmethod
def _std_etc():
return '/etc'
name = SystemConfigPath()
name = name / 'apt'
print(name)
Printed:
/etc/apt
@staticmethod can be replaced by @classmethod
answered Aug 6, 2018 at 2:51
In order to inherit from pathlib.Path
, you need to specify which OS, or "flavour" you're representing. All you need to do is specify that you are using either Windows or Unix (seems to be Unix based on your traceback) by inheriting from pathlib.PosixPath
or pathlib.WindowsPath
.
import pathlib
class PPath(pathlib.PosixPath):
pass
test = PPath("dir", "test.txt")
print(test)
Which outputs:
dir\test.txt
Using type(pathlib.Path())
as proposed in this answer does the exact same thing as directly inheriting from pathlib.PosixPath
or pathlib.WindowsPath
since instantiating pathlib.Path
"creates either a PosixPath or a WindowsPath" (pathlib documentation).
If you know your application will not be cross-platform, it is simpler to directly inherit from the flavor Path that represents your OS.
answered Sep 30, 2021 at 16:45
Chris CollettChris Collett1,2981313 silver badges1818 bronze badges
Here is a simple way to do things regarding to the observation made by Kevin.
class PPath():
def __init__(self, *args, **kwargs):
self.path = Path(*args, **kwargs)
Then I will need to use a trick so as to automatically bind all the Path's methods to my PPpath class. I think that will be funny to do.
answered Apr 24, 2015 at 17:44
projetmbcprojetmbc1,49411 gold badge1313 silver badges2828 bronze badges
5Start asking to get answers
Find the answer to your question by asking.
Ask questionExplore related questions
See similar questions with these tags.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4