lib.files
1import os 2from pathlib import Path 3from typing import Literal 4import json 5import loguru 6 7 8def readFile(filePath: str, mode: Literal["txt", "json"] = "txt"): 9 """Read a file and return its contents. 10 11 Args: 12 filePath: Path to the file. 13 mode: `txt` to return raw str, `json` to return parsed JSON. 14 15 Returns: 16 File contents as str or parsed JSON. 17 """ 18 with open(filePath, encoding="utf-8") as openedFile: 19 if mode == "json": 20 return json.load(openedFile) 21 else: 22 return openedFile.read() 23 24 25def readFileLines(filePath: str) -> list[str]: 26 """Read a text file and return its lines as a list. 27 28 Args: 29 filePath: Path to the text file. 30 Returns: 31 List of lines from the file, with whitespace stripped. 32 """ 33 with open(filePath, encoding="utf-8") as openedFile: 34 return [line.strip() for line in openedFile.readlines()] 35 36 37def createFolder(path: str) -> str: 38 """Create folder if non-existent, return its path. 39 40 Args: 41 path: Path to the folder. 42 43 Returns: 44 The path if created or exists, otherwise an empty string. 45 """ 46 try: 47 # ? Create parent directories recursively, ignore error if exists 48 os.makedirs(path, exist_ok=True) 49 return path 50 except Exception as e: 51 if isDirectory(path): 52 return path 53 else: 54 loguru.logger.warning( 55 "Error creating folder for path '{}' with exception {}", path, e 56 ) 57 # Return empty string if failed => write to root 58 return "" 59 60 61def saveImage(filePath: str | Path) -> str: 62 """Save the current DrawBot drawing with an incremented unique suffix. 63 64 The helper always saves to a suffixed path and scans sibling files to pick 65 the next numeric suffix before the extension, e.g. ``image.png`` -> 66 ``image-1.png`` -> ``image-2.png``. 67 68 Args: 69 filePath: Target file path including file name and extension. 70 Accepts both str and pathlib.Path. 71 72 Returns: 73 The final saved file path as str. 74 """ 75 import drawBot 76 77 filePath = str(filePath) 78 folderPath = os.path.dirname(filePath) 79 if folderPath: 80 createFolder(folderPath) 81 82 fileStem, fileExtension = os.path.splitext(filePath) 83 highestSuffix = 0 84 baseName = os.path.basename(fileStem) 85 86 for siblingName in os.listdir(folderPath or "."): 87 siblingStem, siblingExtension = os.path.splitext(siblingName) 88 if siblingExtension != fileExtension: 89 continue 90 91 if not siblingStem.startswith(f"{baseName}-"): 92 continue 93 94 siblingSuffix = siblingStem.removeprefix(f"{baseName}-") 95 if siblingSuffix.isdigit(): 96 highestSuffix = max(highestSuffix, int(siblingSuffix)) 97 98 resolvedPath = f"{fileStem}-{highestSuffix + 1}{fileExtension}" 99 100 drawBot.saveImage(resolvedPath) 101 return resolvedPath 102 103 104def isFile(string: str) -> bool: 105 """Returns True if the string is a path to a non-empty file.""" 106 return ( 107 isinstance(string, str) 108 and os.path.isfile(string) 109 and os.path.getsize(string) > 0 110 ) 111 112 113def isDirectory(string: str) -> bool: 114 """Returns True if the string is a directory path.""" 115 return os.path.isdir(string)
def
readFile(filePath: str, mode: Literal['txt', 'json'] = 'txt'):
9def readFile(filePath: str, mode: Literal["txt", "json"] = "txt"): 10 """Read a file and return its contents. 11 12 Args: 13 filePath: Path to the file. 14 mode: `txt` to return raw str, `json` to return parsed JSON. 15 16 Returns: 17 File contents as str or parsed JSON. 18 """ 19 with open(filePath, encoding="utf-8") as openedFile: 20 if mode == "json": 21 return json.load(openedFile) 22 else: 23 return openedFile.read()
Read a file and return its contents.
Arguments:
- filePath: Path to the file.
- mode:
txtto return raw str,jsonto return parsed JSON.
Returns:
File contents as str or parsed JSON.
def
readFileLines(filePath: str) -> list[str]:
26def readFileLines(filePath: str) -> list[str]: 27 """Read a text file and return its lines as a list. 28 29 Args: 30 filePath: Path to the text file. 31 Returns: 32 List of lines from the file, with whitespace stripped. 33 """ 34 with open(filePath, encoding="utf-8") as openedFile: 35 return [line.strip() for line in openedFile.readlines()]
Read a text file and return its lines as a list.
Arguments:
- filePath: Path to the text file.
Returns:
List of lines from the file, with whitespace stripped.
def
createFolder(path: str) -> str:
38def createFolder(path: str) -> str: 39 """Create folder if non-existent, return its path. 40 41 Args: 42 path: Path to the folder. 43 44 Returns: 45 The path if created or exists, otherwise an empty string. 46 """ 47 try: 48 # ? Create parent directories recursively, ignore error if exists 49 os.makedirs(path, exist_ok=True) 50 return path 51 except Exception as e: 52 if isDirectory(path): 53 return path 54 else: 55 loguru.logger.warning( 56 "Error creating folder for path '{}' with exception {}", path, e 57 ) 58 # Return empty string if failed => write to root 59 return ""
Create folder if non-existent, return its path.
Arguments:
- path: Path to the folder.
Returns:
The path if created or exists, otherwise an empty string.
def
saveImage(filePath: str | pathlib.Path) -> str:
62def saveImage(filePath: str | Path) -> str: 63 """Save the current DrawBot drawing with an incremented unique suffix. 64 65 The helper always saves to a suffixed path and scans sibling files to pick 66 the next numeric suffix before the extension, e.g. ``image.png`` -> 67 ``image-1.png`` -> ``image-2.png``. 68 69 Args: 70 filePath: Target file path including file name and extension. 71 Accepts both str and pathlib.Path. 72 73 Returns: 74 The final saved file path as str. 75 """ 76 import drawBot 77 78 filePath = str(filePath) 79 folderPath = os.path.dirname(filePath) 80 if folderPath: 81 createFolder(folderPath) 82 83 fileStem, fileExtension = os.path.splitext(filePath) 84 highestSuffix = 0 85 baseName = os.path.basename(fileStem) 86 87 for siblingName in os.listdir(folderPath or "."): 88 siblingStem, siblingExtension = os.path.splitext(siblingName) 89 if siblingExtension != fileExtension: 90 continue 91 92 if not siblingStem.startswith(f"{baseName}-"): 93 continue 94 95 siblingSuffix = siblingStem.removeprefix(f"{baseName}-") 96 if siblingSuffix.isdigit(): 97 highestSuffix = max(highestSuffix, int(siblingSuffix)) 98 99 resolvedPath = f"{fileStem}-{highestSuffix + 1}{fileExtension}" 100 101 drawBot.saveImage(resolvedPath) 102 return resolvedPath
Save the current DrawBot drawing with an incremented unique suffix.
The helper always saves to a suffixed path and scans sibling files to pick
the next numeric suffix before the extension, e.g. image.png ->
image-1.png -> image-2.png.
Arguments:
- filePath: Target file path including file name and extension. Accepts both str and pathlib.Path.
Returns:
The final saved file path as str.
def
isFile(string: str) -> bool:
105def isFile(string: str) -> bool: 106 """Returns True if the string is a path to a non-empty file.""" 107 return ( 108 isinstance(string, str) 109 and os.path.isfile(string) 110 and os.path.getsize(string) > 0 111 )
Returns True if the string is a path to a non-empty file.
def
isDirectory(string: str) -> bool:
114def isDirectory(string: str) -> bool: 115 """Returns True if the string is a directory path.""" 116 return os.path.isdir(string)
Returns True if the string is a directory path.