pathier

1from .pathier import Pathier
2
3__all__ = ["Pathier"]
class Pathier(pathlib.Path):
 12class Pathier(pathlib.Path):
 13    """Subclasses the standard library pathlib.Path class."""
 14
 15    def __new__(cls, *args, **kwargs):
 16        if cls is Pathier:
 17            cls = WindowsPath if os.name == "nt" else PosixPath
 18        self = cls._from_parts(args)
 19        if not self._flavour.is_supported:
 20            raise NotImplementedError(
 21                "cannot instantiate %r on your system" % (cls.__name__,)
 22            )
 23        return self
 24
 25    def mkdir(self, mode: int = 511, parents: bool = True, exist_ok: bool = True):
 26        """Create this directory.
 27        Same as Path().mkdir() except
 28        'parents' and 'exist_ok' default
 29        to True instead of False."""
 30        super().mkdir(mode, parents, exist_ok)
 31
 32    def touch(self):
 33        """Create file and parents if necessary."""
 34        self.parent.mkdir()
 35        super().touch()
 36
 37    def write_text(
 38        self,
 39        data: Any,
 40        encoding: Any | None = None,
 41        errors: Any | None = None,
 42        newline: Any | None = None,
 43        parents: bool = True,
 44    ):
 45        """Write data to file. If a TypeError is raised, the function
 46        will attempt to case data to a str and try the write again.
 47        If a FileNotFoundError is raised and parents = True,
 48        self.parent will be created."""
 49        write = functools.partial(
 50            super().write_text,
 51            encoding=encoding,
 52            errors=errors,
 53            newline=newline,
 54        )
 55        try:
 56            write(data)
 57        except TypeError:
 58            data = str(data)
 59            write(data)
 60        except FileNotFoundError:
 61            if parents:
 62                self.parent.mkdir(parents=True)
 63                write(data)
 64            else:
 65                raise
 66        except Exception as e:
 67            raise
 68
 69    def write_bytes(self, data: bytes, parents: bool = True):
 70        """Write bytes to file.
 71
 72        :param parents: If True and the write operation fails
 73        with a FileNotFoundError, make the parent directory
 74        and retry the write."""
 75        try:
 76            super().write_bytes(data)
 77        except FileNotFoundError:
 78            if parents:
 79                self.parent.mkdir(parents=True)
 80                super().write_bytes(data)
 81            else:
 82                raise
 83        except Exception as e:
 84            raise
 85
 86    def json_loads(self, encoding: Any | None = None, errors: Any | None = None) -> Any:
 87        """Load json file."""
 88        return json.loads(self.read_text(encoding, errors))
 89
 90    def json_dumps(
 91        self,
 92        data: Any,
 93        encoding: Any | None = None,
 94        errors: Any | None = None,
 95        newline: Any | None = None,
 96        sort_keys: bool = False,
 97        indent: Any | None = None,
 98        default: Any | None = None,
 99        parents: bool = True,
100    ) -> Any:
101        """Dump data to json file."""
102        self.write_text(
103            json.dumps(data, indent=indent, default=default, sort_keys=sort_keys),
104            encoding,
105            errors,
106            newline,
107            parents,
108        )
109
110    def toml_loads(self, encoding: Any | None = None, errors: Any | None = None) -> Any:
111        """Load toml file."""
112        return tomlkit.loads(self.read_text(encoding, errors))
113
114    def toml_dumps(
115        self,
116        data: Any,
117        encoding: Any | None = None,
118        errors: Any | None = None,
119        newline: Any | None = None,
120        sort_keys: bool = False,
121        parents: bool = True,
122    ):
123        """Dump data to toml file."""
124        self.write_text(
125            tomlkit.dumps(data, sort_keys), encoding, errors, newline, parents
126        )
127
128    def loads(self, encoding: Any | None = None, errors: Any | None = None) -> Any:
129        """Load a json or toml file based off this instance's suffix."""
130        match self.suffix:
131            case ".json":
132                return self.json_loads(encoding, errors)
133            case ".toml":
134                return self.toml_loads(encoding, errors)
135
136    def dumps(
137        self,
138        data: Any,
139        encoding: Any | None = None,
140        errors: Any | None = None,
141        newline: Any | None = None,
142        sort_keys: bool = False,
143        indent: Any | None = None,
144        default: Any | None = None,
145        parents: bool = True,
146    ):
147        """Dump data to a json or toml file based off this instance's suffix."""
148        match self.suffix:
149            case ".json":
150                self.json_dumps(
151                    data, encoding, errors, newline, sort_keys, indent, default, parents
152                )
153            case ".toml":
154                self.toml_dumps(data, encoding, errors, newline, sort_keys, parents)
155
156    def delete(self, missing_ok: bool = True):
157        """Delete the file or folder pointed to by this instance.
158        Uses self.unlink() if a file and uses shutil.rmtree() if a directory."""
159        if self.is_file():
160            self.unlink(missing_ok)
161        elif self.is_dir():
162            shutil.rmtree(self)
163
164    def copy(
165        self, new_path: Self | pathlib.Path | str, overwrite: bool = False
166    ) -> Self:
167        """Copy the path pointed to by this instance
168        to the instance pointed to by new_path using shutil.copyfile
169        or shutil.copytree. Returns the new path.
170
171        :param new_path: The copy destination.
172
173        :param overwrite: If True, files already existing in new_path
174        will be overwritten. If False, only files that don't exist in new_path
175        will be copied."""
176        new_path = Pathier(new_path)
177        if self.is_dir():
178            if overwrite or not new_path.exists():
179                shutil.copytree(self, new_path, dirs_exist_ok=True)
180            else:
181                files = self.rglob("*.*")
182                for file in files:
183                    dst = new_path.with_name(file.name)
184                    if not dst.exists():
185                        shutil.copyfile(file, dst)
186        elif self.is_file():
187            if overwrite or not new_path.exists():
188                shutil.copyfile(self, new_path)
189        return new_path

Subclasses the standard library pathlib.Path class.

Pathier()
def mkdir(self, mode: int = 511, parents: bool = True, exist_ok: bool = True):
25    def mkdir(self, mode: int = 511, parents: bool = True, exist_ok: bool = True):
26        """Create this directory.
27        Same as Path().mkdir() except
28        'parents' and 'exist_ok' default
29        to True instead of False."""
30        super().mkdir(mode, parents, exist_ok)

Create this directory. Same as Path().mkdir() except 'parents' and 'exist_ok' default to True instead of False.

def touch(self):
32    def touch(self):
33        """Create file and parents if necessary."""
34        self.parent.mkdir()
35        super().touch()

Create file and parents if necessary.

def write_text( self, data: Any, encoding: typing.Any | None = None, errors: typing.Any | None = None, newline: typing.Any | None = None, parents: bool = True):
37    def write_text(
38        self,
39        data: Any,
40        encoding: Any | None = None,
41        errors: Any | None = None,
42        newline: Any | None = None,
43        parents: bool = True,
44    ):
45        """Write data to file. If a TypeError is raised, the function
46        will attempt to case data to a str and try the write again.
47        If a FileNotFoundError is raised and parents = True,
48        self.parent will be created."""
49        write = functools.partial(
50            super().write_text,
51            encoding=encoding,
52            errors=errors,
53            newline=newline,
54        )
55        try:
56            write(data)
57        except TypeError:
58            data = str(data)
59            write(data)
60        except FileNotFoundError:
61            if parents:
62                self.parent.mkdir(parents=True)
63                write(data)
64            else:
65                raise
66        except Exception as e:
67            raise

Write data to file. If a TypeError is raised, the function will attempt to case data to a str and try the write again. If a FileNotFoundError is raised and parents = True, self.parent will be created.

def write_bytes(self, data: bytes, parents: bool = True):
69    def write_bytes(self, data: bytes, parents: bool = True):
70        """Write bytes to file.
71
72        :param parents: If True and the write operation fails
73        with a FileNotFoundError, make the parent directory
74        and retry the write."""
75        try:
76            super().write_bytes(data)
77        except FileNotFoundError:
78            if parents:
79                self.parent.mkdir(parents=True)
80                super().write_bytes(data)
81            else:
82                raise
83        except Exception as e:
84            raise

Write bytes to file.

Parameters
  • parents: If True and the write operation fails with a FileNotFoundError, make the parent directory and retry the write.
def json_loads( self, encoding: typing.Any | None = None, errors: typing.Any | None = None) -> Any:
86    def json_loads(self, encoding: Any | None = None, errors: Any | None = None) -> Any:
87        """Load json file."""
88        return json.loads(self.read_text(encoding, errors))

Load json file.

def json_dumps( self, data: Any, encoding: typing.Any | None = None, errors: typing.Any | None = None, newline: typing.Any | None = None, sort_keys: bool = False, indent: typing.Any | None = None, default: typing.Any | None = None, parents: bool = True) -> Any:
 90    def json_dumps(
 91        self,
 92        data: Any,
 93        encoding: Any | None = None,
 94        errors: Any | None = None,
 95        newline: Any | None = None,
 96        sort_keys: bool = False,
 97        indent: Any | None = None,
 98        default: Any | None = None,
 99        parents: bool = True,
100    ) -> Any:
101        """Dump data to json file."""
102        self.write_text(
103            json.dumps(data, indent=indent, default=default, sort_keys=sort_keys),
104            encoding,
105            errors,
106            newline,
107            parents,
108        )

Dump data to json file.

def toml_loads( self, encoding: typing.Any | None = None, errors: typing.Any | None = None) -> Any:
110    def toml_loads(self, encoding: Any | None = None, errors: Any | None = None) -> Any:
111        """Load toml file."""
112        return tomlkit.loads(self.read_text(encoding, errors))

Load toml file.

def toml_dumps( self, data: Any, encoding: typing.Any | None = None, errors: typing.Any | None = None, newline: typing.Any | None = None, sort_keys: bool = False, parents: bool = True):
114    def toml_dumps(
115        self,
116        data: Any,
117        encoding: Any | None = None,
118        errors: Any | None = None,
119        newline: Any | None = None,
120        sort_keys: bool = False,
121        parents: bool = True,
122    ):
123        """Dump data to toml file."""
124        self.write_text(
125            tomlkit.dumps(data, sort_keys), encoding, errors, newline, parents
126        )

Dump data to toml file.

def loads( self, encoding: typing.Any | None = None, errors: typing.Any | None = None) -> Any:
128    def loads(self, encoding: Any | None = None, errors: Any | None = None) -> Any:
129        """Load a json or toml file based off this instance's suffix."""
130        match self.suffix:
131            case ".json":
132                return self.json_loads(encoding, errors)
133            case ".toml":
134                return self.toml_loads(encoding, errors)

Load a json or toml file based off this instance's suffix.

def dumps( self, data: Any, encoding: typing.Any | None = None, errors: typing.Any | None = None, newline: typing.Any | None = None, sort_keys: bool = False, indent: typing.Any | None = None, default: typing.Any | None = None, parents: bool = True):
136    def dumps(
137        self,
138        data: Any,
139        encoding: Any | None = None,
140        errors: Any | None = None,
141        newline: Any | None = None,
142        sort_keys: bool = False,
143        indent: Any | None = None,
144        default: Any | None = None,
145        parents: bool = True,
146    ):
147        """Dump data to a json or toml file based off this instance's suffix."""
148        match self.suffix:
149            case ".json":
150                self.json_dumps(
151                    data, encoding, errors, newline, sort_keys, indent, default, parents
152                )
153            case ".toml":
154                self.toml_dumps(data, encoding, errors, newline, sort_keys, parents)

Dump data to a json or toml file based off this instance's suffix.

def delete(self, missing_ok: bool = True):
156    def delete(self, missing_ok: bool = True):
157        """Delete the file or folder pointed to by this instance.
158        Uses self.unlink() if a file and uses shutil.rmtree() if a directory."""
159        if self.is_file():
160            self.unlink(missing_ok)
161        elif self.is_dir():
162            shutil.rmtree(self)

Delete the file or folder pointed to by this instance. Uses self.unlink() if a file and uses shutil.rmtree() if a directory.

def copy( self, new_path: Union[Self, pathlib.Path, str], overwrite: bool = False) -> Self:
164    def copy(
165        self, new_path: Self | pathlib.Path | str, overwrite: bool = False
166    ) -> Self:
167        """Copy the path pointed to by this instance
168        to the instance pointed to by new_path using shutil.copyfile
169        or shutil.copytree. Returns the new path.
170
171        :param new_path: The copy destination.
172
173        :param overwrite: If True, files already existing in new_path
174        will be overwritten. If False, only files that don't exist in new_path
175        will be copied."""
176        new_path = Pathier(new_path)
177        if self.is_dir():
178            if overwrite or not new_path.exists():
179                shutil.copytree(self, new_path, dirs_exist_ok=True)
180            else:
181                files = self.rglob("*.*")
182                for file in files:
183                    dst = new_path.with_name(file.name)
184                    if not dst.exists():
185                        shutil.copyfile(file, dst)
186        elif self.is_file():
187            if overwrite or not new_path.exists():
188                shutil.copyfile(self, new_path)
189        return new_path

Copy the path pointed to by this instance to the instance pointed to by new_path using shutil.copyfile or shutil.copytree. Returns the new path.

Parameters
  • new_path: The copy destination.

  • overwrite: If True, files already existing in new_path will be overwritten. If False, only files that don't exist in new_path will be copied.

Inherited Members
pathlib.Path
cwd
home
samefile
iterdir
glob
rglob
absolute
resolve
stat
owner
group
open
read_bytes
read_text
chmod
lchmod
rmdir
lstat
rename
replace
exists
is_dir
is_file
is_mount
is_block_device
is_char_device
is_fifo
is_socket
expanduser
pathlib.PurePath
as_posix
as_uri
drive
root
anchor
name
suffix
suffixes
stem
with_name
with_stem
with_suffix
relative_to
is_relative_to
parts
joinpath
parent
parents
is_absolute
is_reserved
match