pathier
15class Pathier(pathlib.Path): 16 """Subclasses the standard library pathlib.Path class.""" 17 18 def __new__(cls, *args, **kwargs): 19 if cls is Pathier: 20 cls = WindowsPath if os.name == "nt" else PosixPath 21 self = cls._from_parts(args) 22 if not self._flavour.is_supported: 23 raise NotImplementedError( 24 "cannot instantiate %r on your system" % (cls.__name__,) 25 ) 26 return self 27 28 # ===============================================stats=============================================== 29 @property 30 def dob(self) -> datetime.datetime | None: 31 """Returns the creation date of this file or directory as a `dateime.datetime` object.""" 32 if self.exists(): 33 return datetime.datetime.fromtimestamp(self.stat().st_ctime) 34 else: 35 return None 36 37 @property 38 def age(self) -> float | None: 39 """Returns the age in seconds of this file or directory.""" 40 if self.exists(): 41 return (datetime.datetime.now() - self.dob).total_seconds() 42 else: 43 return None 44 45 @property 46 def mod_date(self) -> datetime.datetime | None: 47 """Returns the modification date of this file or directory as a `datetime.datetime` object.""" 48 if self.exists(): 49 return datetime.datetime.fromtimestamp(self.stat().st_mtime) 50 else: 51 return None 52 53 @property 54 def mod_delta(self) -> float | None: 55 """Returns how long ago in seconds this file or directory was modified.""" 56 if self.exists(): 57 return (datetime.datetime.now() - self.mod_date).total_seconds() 58 else: 59 return None 60 61 def size(self, format: bool = False) -> int | str | None: 62 """Returns the size in bytes of this file or directory. 63 Returns `None` if this path doesn't exist. 64 65 #### :params: 66 67 `format`: If `True`, return value as a formatted string.""" 68 if not self.exists(): 69 return None 70 if self.is_file(): 71 size = self.stat().st_size 72 if self.is_dir(): 73 size = sum(file.stat().st_size for file in self.rglob("*.*")) 74 if format: 75 return self.format_size(size) 76 return size 77 78 @staticmethod 79 def format_size(size: int) -> str: 80 """Format `size` with common file size abbreviations and rounded to two decimal places. 81 >>> 1234 -> "1.23 kb" """ 82 for unit in ["bytes", "kb", "mb", "gb", "tb", "pb"]: 83 if unit != "bytes": 84 size *= 0.001 85 if size < 1000 or unit == "pb": 86 return f"{round(size, 2)} {unit}" 87 88 def is_larger(self, path: Self) -> bool: 89 """Returns whether this file or folder is larger than the one pointed to by `path`.""" 90 return self.size() > path.size() 91 92 def is_older(self, path: Self) -> bool: 93 """Returns whether this file or folder is older than the one pointed to by `path`.""" 94 return self.dob < path.dob 95 96 def modified_more_recently(self, path: Self) -> bool: 97 """Returns whether this file or folder was modified more recently than the one pointed to by `path`.""" 98 return self.mod_date > path.mod_date 99 100 # ===============================================navigation=============================================== 101 def mkcwd(self): 102 """Make this path your current working directory.""" 103 os.chdir(self) 104 105 @property 106 def in_PATH(self) -> bool: 107 """Return `True` if this path is in `sys.path`.""" 108 return str(self) in sys.path 109 110 def add_to_PATH(self, index: int = 0): 111 """Insert this path into `sys.path` if it isn't already there. 112 113 #### :params: 114 115 `index`: The index of `sys.path` to insert this path at.""" 116 path = str(self) 117 if not self.in_PATH: 118 sys.path.insert(index, path) 119 120 def append_to_PATH(self): 121 """Append this path to `sys.path` if it isn't already there.""" 122 path = str(self) 123 if not self.in_PATH: 124 sys.path.append(path) 125 126 def remove_from_PATH(self): 127 """Remove this path from `sys.path` if it's in `sys.path`.""" 128 if self.in_PATH: 129 sys.path.remove(str(self)) 130 131 def moveup(self, name: str) -> Self: 132 """Return a new `Pathier` object that is a parent of this instance. 133 134 `name` is case-sensitive and raises an exception if it isn't in `self.parts`. 135 >>> p = Pathier("C:\some\directory\in\your\system") 136 >>> print(p.moveup("directory")) 137 >>> "C:\some\directory" 138 >>> print(p.moveup("yeet")) 139 >>> "Exception: yeet is not a parent of C:\some\directory\in\your\system" """ 140 if name not in self.parts: 141 raise Exception(f"{name} is not a parent of {self}") 142 return Pathier(*(self.parts[: self.parts.index(name) + 1])) 143 144 def __sub__(self, levels: int) -> Self: 145 """Return a new `Pathier` object moved up `levels` number of parents from the current path. 146 >>> p = Pathier("C:\some\directory\in\your\system") 147 >>> new_p = p - 3 148 >>> print(new_p) 149 >>> "C:\some\directory" """ 150 path = self 151 for _ in range(levels): 152 path = path.parent 153 return path 154 155 def move_under(self, name: str) -> Self: 156 """Return a new `Pathier` object such that the stem is one level below the given folder `name`. 157 158 `name` is case-sensitive and raises an exception if it isn't in `self.parts`. 159 >>> p = Pathier("a/b/c/d/e/f/g") 160 >>> print(p.move_under("c")) 161 >>> 'a/b/c/d'""" 162 if name not in self.parts: 163 raise Exception(f"{name} is not a parent of {self}") 164 return self - (len(self.parts) - self.parts.index(name) - 2) 165 166 def separate(self, name: str, keep_name: bool = False) -> Self: 167 """Return a new `Pathier` object that is the relative child path after `name`. 168 169 `name` is case-sensitive and raises an exception if it isn't in `self.parts`. 170 171 #### :params: 172 173 `keep_name`: If `True`, the returned path will start with `name`. 174 >>> p = Pathier("a/b/c/d/e/f/g") 175 >>> print(p.separate("c")) 176 >>> 'd/e/f/g' 177 >>> print(p.separate("c", True)) 178 >>> 'c/d/e/f/g'""" 179 if name not in self.parts: 180 raise Exception(f"{name} is not a parent of {self}") 181 if keep_name: 182 return Pathier(*self.parts[self.parts.index(name) :]) 183 return Pathier(*self.parts[self.parts.index(name) + 1 :]) 184 185 # ============================================write and read============================================ 186 def mkdir(self, mode: int = 511, parents: bool = True, exist_ok: bool = True): 187 """Create this directory. 188 189 Same as `Path().mkdir()` except `parents` and `exist_ok` default to `True` instead of `False`.""" 190 super().mkdir(mode, parents, exist_ok) 191 192 def touch(self): 193 """Create file (and parents if necessary).""" 194 self.parent.mkdir() 195 super().touch() 196 197 def write_text( 198 self, 199 data: Any, 200 encoding: Any | None = None, 201 errors: Any | None = None, 202 newline: Any | None = None, 203 parents: bool = True, 204 ): 205 """Write data to file. 206 207 If a `TypeError` is raised, the function will attempt to cast `data` to a `str` and try the write again. 208 209 If a `FileNotFoundError` is raised and `parents = True`, `self.parent` will be created.""" 210 write = functools.partial( 211 super().write_text, 212 encoding=encoding, 213 errors=errors, 214 newline=newline, 215 ) 216 try: 217 write(data) 218 except TypeError: 219 data = str(data) 220 write(data) 221 except FileNotFoundError: 222 if parents: 223 self.parent.mkdir(parents=True) 224 write(data) 225 else: 226 raise 227 except Exception as e: 228 raise 229 230 def write_bytes(self, data: bytes, parents: bool = True): 231 """Write bytes to file. 232 233 #### :params: 234 235 `parents`: If `True` and the write operation fails with a `FileNotFoundError`, 236 make the parent directory and retry the write.""" 237 try: 238 super().write_bytes(data) 239 except FileNotFoundError: 240 if parents: 241 self.parent.mkdir(parents=True) 242 super().write_bytes(data) 243 else: 244 raise 245 except Exception as e: 246 raise 247 248 def replace( 249 self, 250 old_string: str, 251 new_string: str, 252 count: int = -1, 253 encoding: Any | None = None, 254 ): 255 """Replace `old_string` in a file with `new_string`. 256 257 #### :params: 258 259 `count`: Only replace this many occurences of `old_string`. 260 By default (`-1`), all occurences are replaced. 261 262 `encoding`: The file encoding to use. 263 264 e.g. 265 >>> path = Pathier("somefile.txt") 266 >>> 267 >>> path.replace("hello", "yeet") 268 equivalent to 269 >>> path.write_text(path.read_text().replace("hello", "yeet"))""" 270 self.write_text( 271 self.read_text(encoding).replace(old_string, new_string, count), 272 encoding=encoding, 273 ) 274 275 def json_loads(self, encoding: Any | None = None, errors: Any | None = None) -> Any: 276 """Load json file.""" 277 return json.loads(self.read_text(encoding, errors)) 278 279 def json_dumps( 280 self, 281 data: Any, 282 encoding: Any | None = None, 283 errors: Any | None = None, 284 newline: Any | None = None, 285 sort_keys: bool = False, 286 indent: Any | None = None, 287 default: Any | None = None, 288 parents: bool = True, 289 ) -> Any: 290 """Dump `data` to json file.""" 291 self.write_text( 292 json.dumps(data, indent=indent, default=default, sort_keys=sort_keys), 293 encoding, 294 errors, 295 newline, 296 parents, 297 ) 298 299 def toml_loads(self, encoding: Any | None = None, errors: Any | None = None) -> Any: 300 """Load toml file.""" 301 return tomlkit.loads(self.read_text(encoding, errors)) 302 303 def toml_dumps( 304 self, 305 data: Any, 306 encoding: Any | None = None, 307 errors: Any | None = None, 308 newline: Any | None = None, 309 sort_keys: bool = False, 310 parents: bool = True, 311 ): 312 """Dump `data` to toml file.""" 313 self.write_text( 314 tomlkit.dumps(data, sort_keys), encoding, errors, newline, parents 315 ) 316 317 def loads(self, encoding: Any | None = None, errors: Any | None = None) -> Any: 318 """Load a json or toml file based off this instance's suffix.""" 319 match self.suffix: 320 case ".json": 321 return self.json_loads(encoding, errors) 322 case ".toml": 323 return self.toml_loads(encoding, errors) 324 325 def dumps( 326 self, 327 data: Any, 328 encoding: Any | None = None, 329 errors: Any | None = None, 330 newline: Any | None = None, 331 sort_keys: bool = False, 332 indent: Any | None = None, 333 default: Any | None = None, 334 parents: bool = True, 335 ): 336 """Dump `data` to a json or toml file based off this instance's suffix.""" 337 match self.suffix: 338 case ".json": 339 self.json_dumps( 340 data, encoding, errors, newline, sort_keys, indent, default, parents 341 ) 342 case ".toml": 343 self.toml_dumps(data, encoding, errors, newline, sort_keys, parents) 344 345 def delete(self, missing_ok: bool = True): 346 """Delete the file or folder pointed to by this instance. 347 348 Uses `self.unlink()` if a file and uses `shutil.rmtree()` if a directory.""" 349 if self.is_file(): 350 self.unlink(missing_ok) 351 elif self.is_dir(): 352 shutil.rmtree(self) 353 354 def copy( 355 self, new_path: Self | pathlib.Path | str, overwrite: bool = False 356 ) -> Self: 357 """Copy the path pointed to by this instance 358 to the instance pointed to by `new_path` using `shutil.copyfile` 359 or `shutil.copytree`. 360 361 Returns the new path. 362 363 #### :params: 364 365 `new_path`: The copy destination. 366 367 `overwrite`: If `True`, files already existing in `new_path` will be overwritten. 368 If `False`, only files that don't exist in `new_path` will be copied.""" 369 new_path = Pathier(new_path) 370 if self.is_dir(): 371 if overwrite or not new_path.exists(): 372 shutil.copytree(self, new_path, dirs_exist_ok=True) 373 else: 374 files = self.rglob("*.*") 375 for file in files: 376 dst = new_path.with_name(file.name) 377 if not dst.exists(): 378 shutil.copyfile(file, dst) 379 elif self.is_file(): 380 if overwrite or not new_path.exists(): 381 shutil.copyfile(self, new_path) 382 return new_path 383 384 def backup(self, timestamp: bool = False) -> Self | None: 385 """Create a copy of this file or directory with `_backup` appended to the path stem. 386 If the path to be backed up doesn't exist, `None` is returned. 387 Otherwise a `Pathier` object for the backup is returned. 388 389 #### :params: 390 391 `timestamp`: Add a timestamp to the backup name to prevent overriding previous backups. 392 393 >>> path = Pathier("some_file.txt") 394 >>> path.backup() 395 >>> list(path.iterdir()) 396 >>> ['some_file.txt', 'some_file_backup.txt'] 397 >>> path.backup(True) 398 >>> list(path.iterdir()) 399 >>> ['some_file.txt', 'some_file_backup.txt', 'some_file_backup_04-28-2023-06_25_52_PM.txt']""" 400 if not self.exists(): 401 return None 402 backup_stem = f"{self.stem}_backup" 403 if timestamp: 404 backup_stem = f"{backup_stem}_{datetime.datetime.now().strftime('%m-%d-%Y-%I_%M_%S_%p')}" 405 backup_path = self.with_stem(backup_stem) 406 self.copy(backup_path, True) 407 return backup_path 408 409 def execute(self, command: str = "", args: str = "") -> int: 410 """Make a call to `os.system` using the path pointed to by this Pathier object. 411 412 #### :params: 413 414 `command`: Program/command to precede the path with. 415 416 `args`: Any arguments that should come after the path. 417 418 :returns: The integer output of `os.system`. 419 420 e.g. 421 >>> path = Pathier("mydirectory") / "myscript.py" 422 then 423 >>> path.execute("py", "--iterations 10") 424 equivalent to 425 >>> os.system(f"py {path} --iterations 10")""" 426 return os.system(f"{command} {self} {args}")
Subclasses the standard library pathlib.Path class.
Returns the creation date of this file or directory as a dateime.datetime
object.
Returns the modification date of this file or directory as a datetime.datetime
object.
61 def size(self, format: bool = False) -> int | str | None: 62 """Returns the size in bytes of this file or directory. 63 Returns `None` if this path doesn't exist. 64 65 #### :params: 66 67 `format`: If `True`, return value as a formatted string.""" 68 if not self.exists(): 69 return None 70 if self.is_file(): 71 size = self.stat().st_size 72 if self.is_dir(): 73 size = sum(file.stat().st_size for file in self.rglob("*.*")) 74 if format: 75 return self.format_size(size) 76 return size
Returns the size in bytes of this file or directory.
Returns None
if this path doesn't exist.
:params:
format
: If True
, return value as a formatted string.
78 @staticmethod 79 def format_size(size: int) -> str: 80 """Format `size` with common file size abbreviations and rounded to two decimal places. 81 >>> 1234 -> "1.23 kb" """ 82 for unit in ["bytes", "kb", "mb", "gb", "tb", "pb"]: 83 if unit != "bytes": 84 size *= 0.001 85 if size < 1000 or unit == "pb": 86 return f"{round(size, 2)} {unit}"
Format size
with common file size abbreviations and rounded to two decimal places.
>>> 1234 -> "1.23 kb"
88 def is_larger(self, path: Self) -> bool: 89 """Returns whether this file or folder is larger than the one pointed to by `path`.""" 90 return self.size() > path.size()
Returns whether this file or folder is larger than the one pointed to by path
.
92 def is_older(self, path: Self) -> bool: 93 """Returns whether this file or folder is older than the one pointed to by `path`.""" 94 return self.dob < path.dob
Returns whether this file or folder is older than the one pointed to by path
.
96 def modified_more_recently(self, path: Self) -> bool: 97 """Returns whether this file or folder was modified more recently than the one pointed to by `path`.""" 98 return self.mod_date > path.mod_date
Returns whether this file or folder was modified more recently than the one pointed to by path
.
110 def add_to_PATH(self, index: int = 0): 111 """Insert this path into `sys.path` if it isn't already there. 112 113 #### :params: 114 115 `index`: The index of `sys.path` to insert this path at.""" 116 path = str(self) 117 if not self.in_PATH: 118 sys.path.insert(index, path)
Insert this path into sys.path
if it isn't already there.
:params:
index
: The index of sys.path
to insert this path at.
120 def append_to_PATH(self): 121 """Append this path to `sys.path` if it isn't already there.""" 122 path = str(self) 123 if not self.in_PATH: 124 sys.path.append(path)
Append this path to sys.path
if it isn't already there.
126 def remove_from_PATH(self): 127 """Remove this path from `sys.path` if it's in `sys.path`.""" 128 if self.in_PATH: 129 sys.path.remove(str(self))
Remove this path from sys.path
if it's in sys.path
.
131 def moveup(self, name: str) -> Self: 132 """Return a new `Pathier` object that is a parent of this instance. 133 134 `name` is case-sensitive and raises an exception if it isn't in `self.parts`. 135 >>> p = Pathier("C:\some\directory\in\your\system") 136 >>> print(p.moveup("directory")) 137 >>> "C:\some\directory" 138 >>> print(p.moveup("yeet")) 139 >>> "Exception: yeet is not a parent of C:\some\directory\in\your\system" """ 140 if name not in self.parts: 141 raise Exception(f"{name} is not a parent of {self}") 142 return Pathier(*(self.parts[: self.parts.index(name) + 1]))
Return a new Pathier
object that is a parent of this instance.
name
is case-sensitive and raises an exception if it isn't in self.parts
.
>>> p = Pathier("C:\some\directory\in\your\system")
>>> print(p.moveup("directory"))
>>> "C:\some\directory"
>>> print(p.moveup("yeet"))
>>> "Exception: yeet is not a parent of C:\some\directory\in\your\system"
155 def move_under(self, name: str) -> Self: 156 """Return a new `Pathier` object such that the stem is one level below the given folder `name`. 157 158 `name` is case-sensitive and raises an exception if it isn't in `self.parts`. 159 >>> p = Pathier("a/b/c/d/e/f/g") 160 >>> print(p.move_under("c")) 161 >>> 'a/b/c/d'""" 162 if name not in self.parts: 163 raise Exception(f"{name} is not a parent of {self}") 164 return self - (len(self.parts) - self.parts.index(name) - 2)
166 def separate(self, name: str, keep_name: bool = False) -> Self: 167 """Return a new `Pathier` object that is the relative child path after `name`. 168 169 `name` is case-sensitive and raises an exception if it isn't in `self.parts`. 170 171 #### :params: 172 173 `keep_name`: If `True`, the returned path will start with `name`. 174 >>> p = Pathier("a/b/c/d/e/f/g") 175 >>> print(p.separate("c")) 176 >>> 'd/e/f/g' 177 >>> print(p.separate("c", True)) 178 >>> 'c/d/e/f/g'""" 179 if name not in self.parts: 180 raise Exception(f"{name} is not a parent of {self}") 181 if keep_name: 182 return Pathier(*self.parts[self.parts.index(name) :]) 183 return Pathier(*self.parts[self.parts.index(name) + 1 :])
Return a new Pathier
object that is the relative child path after name
.
name
is case-sensitive and raises an exception if it isn't in self.parts
.
:params:
keep_name
: If True
, the returned path will start with name
.
>>> p = Pathier("a/b/c/d/e/f/g")
>>> print(p.separate("c"))
>>> 'd/e/f/g'
>>> print(p.separate("c", True))
>>> 'c/d/e/f/g'
186 def mkdir(self, mode: int = 511, parents: bool = True, exist_ok: bool = True): 187 """Create this directory. 188 189 Same as `Path().mkdir()` except `parents` and `exist_ok` default to `True` instead of `False`.""" 190 super().mkdir(mode, parents, exist_ok)
Create this directory.
Same as Path().mkdir()
except parents
and exist_ok
default to True
instead of False
.
192 def touch(self): 193 """Create file (and parents if necessary).""" 194 self.parent.mkdir() 195 super().touch()
Create file (and parents if necessary).
197 def write_text( 198 self, 199 data: Any, 200 encoding: Any | None = None, 201 errors: Any | None = None, 202 newline: Any | None = None, 203 parents: bool = True, 204 ): 205 """Write data to file. 206 207 If a `TypeError` is raised, the function will attempt to cast `data` to a `str` and try the write again. 208 209 If a `FileNotFoundError` is raised and `parents = True`, `self.parent` will be created.""" 210 write = functools.partial( 211 super().write_text, 212 encoding=encoding, 213 errors=errors, 214 newline=newline, 215 ) 216 try: 217 write(data) 218 except TypeError: 219 data = str(data) 220 write(data) 221 except FileNotFoundError: 222 if parents: 223 self.parent.mkdir(parents=True) 224 write(data) 225 else: 226 raise 227 except Exception as e: 228 raise
Write data to file.
If a TypeError
is raised, the function will attempt to cast data
to a str
and try the write again.
If a FileNotFoundError
is raised and parents = True
, self.parent
will be created.
230 def write_bytes(self, data: bytes, parents: bool = True): 231 """Write bytes to file. 232 233 #### :params: 234 235 `parents`: If `True` and the write operation fails with a `FileNotFoundError`, 236 make the parent directory and retry the write.""" 237 try: 238 super().write_bytes(data) 239 except FileNotFoundError: 240 if parents: 241 self.parent.mkdir(parents=True) 242 super().write_bytes(data) 243 else: 244 raise 245 except Exception as e: 246 raise
Write bytes to file.
:params:
parents
: If True
and the write operation fails with a FileNotFoundError
,
make the parent directory and retry the write.
248 def replace( 249 self, 250 old_string: str, 251 new_string: str, 252 count: int = -1, 253 encoding: Any | None = None, 254 ): 255 """Replace `old_string` in a file with `new_string`. 256 257 #### :params: 258 259 `count`: Only replace this many occurences of `old_string`. 260 By default (`-1`), all occurences are replaced. 261 262 `encoding`: The file encoding to use. 263 264 e.g. 265 >>> path = Pathier("somefile.txt") 266 >>> 267 >>> path.replace("hello", "yeet") 268 equivalent to 269 >>> path.write_text(path.read_text().replace("hello", "yeet"))""" 270 self.write_text( 271 self.read_text(encoding).replace(old_string, new_string, count), 272 encoding=encoding, 273 )
Replace old_string
in a file with new_string
.
:params:
count
: Only replace this many occurences of old_string
.
By default (-1
), all occurences are replaced.
encoding
: The file encoding to use.
e.g.
>>> path = Pathier("somefile.txt")
>>>
>>> path.replace("hello", "yeet")
equivalent to
>>> path.write_text(path.read_text().replace("hello", "yeet"))
275 def json_loads(self, encoding: Any | None = None, errors: Any | None = None) -> Any: 276 """Load json file.""" 277 return json.loads(self.read_text(encoding, errors))
Load json file.
279 def json_dumps( 280 self, 281 data: Any, 282 encoding: Any | None = None, 283 errors: Any | None = None, 284 newline: Any | None = None, 285 sort_keys: bool = False, 286 indent: Any | None = None, 287 default: Any | None = None, 288 parents: bool = True, 289 ) -> Any: 290 """Dump `data` to json file.""" 291 self.write_text( 292 json.dumps(data, indent=indent, default=default, sort_keys=sort_keys), 293 encoding, 294 errors, 295 newline, 296 parents, 297 )
Dump data
to json file.
299 def toml_loads(self, encoding: Any | None = None, errors: Any | None = None) -> Any: 300 """Load toml file.""" 301 return tomlkit.loads(self.read_text(encoding, errors))
Load toml file.
303 def toml_dumps( 304 self, 305 data: Any, 306 encoding: Any | None = None, 307 errors: Any | None = None, 308 newline: Any | None = None, 309 sort_keys: bool = False, 310 parents: bool = True, 311 ): 312 """Dump `data` to toml file.""" 313 self.write_text( 314 tomlkit.dumps(data, sort_keys), encoding, errors, newline, parents 315 )
Dump data
to toml file.
317 def loads(self, encoding: Any | None = None, errors: Any | None = None) -> Any: 318 """Load a json or toml file based off this instance's suffix.""" 319 match self.suffix: 320 case ".json": 321 return self.json_loads(encoding, errors) 322 case ".toml": 323 return self.toml_loads(encoding, errors)
Load a json or toml file based off this instance's suffix.
325 def dumps( 326 self, 327 data: Any, 328 encoding: Any | None = None, 329 errors: Any | None = None, 330 newline: Any | None = None, 331 sort_keys: bool = False, 332 indent: Any | None = None, 333 default: Any | None = None, 334 parents: bool = True, 335 ): 336 """Dump `data` to a json or toml file based off this instance's suffix.""" 337 match self.suffix: 338 case ".json": 339 self.json_dumps( 340 data, encoding, errors, newline, sort_keys, indent, default, parents 341 ) 342 case ".toml": 343 self.toml_dumps(data, encoding, errors, newline, sort_keys, parents)
Dump data
to a json or toml file based off this instance's suffix.
345 def delete(self, missing_ok: bool = True): 346 """Delete the file or folder pointed to by this instance. 347 348 Uses `self.unlink()` if a file and uses `shutil.rmtree()` if a directory.""" 349 if self.is_file(): 350 self.unlink(missing_ok) 351 elif self.is_dir(): 352 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.
354 def copy( 355 self, new_path: Self | pathlib.Path | str, overwrite: bool = False 356 ) -> Self: 357 """Copy the path pointed to by this instance 358 to the instance pointed to by `new_path` using `shutil.copyfile` 359 or `shutil.copytree`. 360 361 Returns the new path. 362 363 #### :params: 364 365 `new_path`: The copy destination. 366 367 `overwrite`: If `True`, files already existing in `new_path` will be overwritten. 368 If `False`, only files that don't exist in `new_path` will be copied.""" 369 new_path = Pathier(new_path) 370 if self.is_dir(): 371 if overwrite or not new_path.exists(): 372 shutil.copytree(self, new_path, dirs_exist_ok=True) 373 else: 374 files = self.rglob("*.*") 375 for file in files: 376 dst = new_path.with_name(file.name) 377 if not dst.exists(): 378 shutil.copyfile(file, dst) 379 elif self.is_file(): 380 if overwrite or not new_path.exists(): 381 shutil.copyfile(self, new_path) 382 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.
:params:
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.
384 def backup(self, timestamp: bool = False) -> Self | None: 385 """Create a copy of this file or directory with `_backup` appended to the path stem. 386 If the path to be backed up doesn't exist, `None` is returned. 387 Otherwise a `Pathier` object for the backup is returned. 388 389 #### :params: 390 391 `timestamp`: Add a timestamp to the backup name to prevent overriding previous backups. 392 393 >>> path = Pathier("some_file.txt") 394 >>> path.backup() 395 >>> list(path.iterdir()) 396 >>> ['some_file.txt', 'some_file_backup.txt'] 397 >>> path.backup(True) 398 >>> list(path.iterdir()) 399 >>> ['some_file.txt', 'some_file_backup.txt', 'some_file_backup_04-28-2023-06_25_52_PM.txt']""" 400 if not self.exists(): 401 return None 402 backup_stem = f"{self.stem}_backup" 403 if timestamp: 404 backup_stem = f"{backup_stem}_{datetime.datetime.now().strftime('%m-%d-%Y-%I_%M_%S_%p')}" 405 backup_path = self.with_stem(backup_stem) 406 self.copy(backup_path, True) 407 return backup_path
Create a copy of this file or directory with _backup
appended to the path stem.
If the path to be backed up doesn't exist, None
is returned.
Otherwise a Pathier
object for the backup is returned.
:params:
timestamp
: Add a timestamp to the backup name to prevent overriding previous backups.
>>> path = Pathier("some_file.txt")
>>> path.backup()
>>> list(path.iterdir())
>>> ['some_file.txt', 'some_file_backup.txt']
>>> path.backup(True)
>>> list(path.iterdir())
>>> ['some_file.txt', 'some_file_backup.txt', 'some_file_backup_04-28-2023-06_25_52_PM.txt']
409 def execute(self, command: str = "", args: str = "") -> int: 410 """Make a call to `os.system` using the path pointed to by this Pathier object. 411 412 #### :params: 413 414 `command`: Program/command to precede the path with. 415 416 `args`: Any arguments that should come after the path. 417 418 :returns: The integer output of `os.system`. 419 420 e.g. 421 >>> path = Pathier("mydirectory") / "myscript.py" 422 then 423 >>> path.execute("py", "--iterations 10") 424 equivalent to 425 >>> os.system(f"py {path} --iterations 10")""" 426 return os.system(f"{command} {self} {args}")
Make a call to os.system
using the path pointed to by this Pathier object.
:params:
command
: Program/command to precede the path with.
args
: Any arguments that should come after the path.
:returns: The integer output of os.system
.
e.g.
>>> path = Pathier("mydirectory") / "myscript.py"
then
>>> path.execute("py", "--iterations 10")
equivalent to
>>> os.system(f"py {path} --iterations 10")
Inherited Members
- pathlib.Path
- cwd
- home
- samefile
- iterdir
- glob
- rglob
- absolute
- resolve
- stat
- owner
- group
- open
- read_bytes
- read_text
- readlink
- chmod
- lchmod
- unlink
- rmdir
- lstat
- rename
- symlink_to
- hardlink_to
- link_to
- exists
- is_dir
- is_file
- is_mount
- is_symlink
- 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