Last active
July 4, 2024 20:07
-
-
Save sarmadgulzar/1d9b96b01b180b0f8e0b7f5e93890d7d to your computer and use it in GitHub Desktop.
A file helper that can create, read, update, delete & rename files.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import logging | |
import os | |
from pathlib import Path | |
class FileOperationError(Exception): | |
"""Custom exception for file operations.""" | |
class FileHelper: | |
""" | |
A utility class for performing various file operations. | |
This class provides methods for creating, reading, updating, renaming, | |
and deleting files. It uses logging for operation tracking and | |
implements robust error handling. | |
Attributes: | |
logger (logging.Logger): Logger instance for the class. | |
""" | |
def __init__(self, log_level: int = logging.INFO): | |
""" | |
Initialize the FileHelper with a configured logger. | |
Args: | |
log_level (int): The logging level to use. Defaults to logging.INFO. | |
""" | |
self.logger = self._setup_logger(log_level) | |
@staticmethod | |
def _setup_logger(log_level: int) -> logging.Logger: | |
""" | |
Set up and configure the logger. | |
Args: | |
log_level (int): The logging level to use. | |
Returns: | |
logging.Logger: Configured logger instance. | |
""" | |
logger = logging.getLogger(__name__) | |
logger.setLevel(log_level) | |
if not logger.handlers: | |
handler = logging.StreamHandler() | |
formatter = logging.Formatter( | |
"%(asctime)s - %(name)s - %(levelname)s - %(message)s" | |
) | |
handler.setFormatter(formatter) | |
logger.addHandler(handler) | |
return logger | |
def create(self, filename: str, content: str = "") -> None: | |
""" | |
Create a new file with optional content. | |
Args: | |
filename (str): The name of the file to create. | |
content (str, optional): The initial content of the file. Defaults to an empty string. | |
Raises: | |
FileOperationError: If there's an error creating the file. | |
""" | |
try: | |
with open(filename, "w") as file: | |
file.write(content) | |
self.logger.info(f"File '{filename}' created successfully.") | |
except IOError as e: | |
self.logger.error(f"Error creating file '{filename}': {str(e)}") | |
raise FileOperationError(f"Failed to create file '{filename}'") from e | |
def read(self, filename: str) -> str | None: | |
""" | |
Read and return the contents of a file. | |
Args: | |
filename (str): The name of the file to read. | |
Returns: | |
str | None: The contents of the file, or None if the file doesn't exist. | |
Raises: | |
FileOperationError: If there's an error reading the file. | |
""" | |
try: | |
with open(filename, "r") as file: | |
content = file.read() | |
self.logger.info(f"File '{filename}' read successfully.") | |
return content | |
except FileNotFoundError: | |
self.logger.warning(f"File '{filename}' not found.") | |
return None | |
except IOError as e: | |
self.logger.error(f"Error reading file '{filename}': {str(e)}") | |
raise FileOperationError(f"Failed to read file '{filename}'") from e | |
def update(self, filename: str, new_content: str) -> None: | |
""" | |
Update the entire contents of a file. | |
Args: | |
filename (str): The name of the file to update. | |
new_content (str): The new content to write to the file. | |
Raises: | |
FileOperationError: If there's an error updating the file. | |
""" | |
try: | |
with open(filename, "w") as file: | |
file.write(new_content) | |
self.logger.info(f"File '{filename}' updated successfully.") | |
except IOError as e: | |
self.logger.error(f"Error updating file '{filename}': {str(e)}") | |
raise FileOperationError(f"Failed to update file '{filename}'") from e | |
def rename(self, old_name: str, new_name: str) -> None: | |
""" | |
Rename a file. | |
Args: | |
old_name (str): The current name of the file. | |
new_name (str): The new name for the file. | |
Raises: | |
FileOperationError: If there's an error renaming the file. | |
""" | |
try: | |
os.rename(old_name, new_name) | |
self.logger.info( | |
f"File renamed from '{old_name}' to '{new_name}' successfully." | |
) | |
except FileNotFoundError: | |
self.logger.error(f"File '{old_name}' not found.") | |
raise FileOperationError(f"File '{old_name}' not found") from None | |
except FileExistsError: | |
self.logger.error(f"File '{new_name}' already exists.") | |
raise FileOperationError(f"File '{new_name}' already exists") from None | |
except OSError as e: | |
self.logger.error( | |
f"Error renaming file from '{old_name}' to '{new_name}': {str(e)}" | |
) | |
raise FileOperationError(f"Failed to rename file '{old_name}'") from e | |
def delete(self, filename: str) -> None: | |
""" | |
Delete a file. | |
Args: | |
filename (str): The name of the file to delete. | |
Raises: | |
FileOperationError: If there's an error deleting the file. | |
""" | |
try: | |
os.remove(filename) | |
self.logger.info(f"File '{filename}' deleted successfully.") | |
except FileNotFoundError: | |
self.logger.warning(f"File '{filename}' not found.") | |
except OSError as e: | |
self.logger.error(f"Error deleting file '{filename}': {str(e)}") | |
raise FileOperationError(f"Failed to delete file '{filename}'") from e | |
@staticmethod | |
def get_file_info(filename: str) -> dict: | |
""" | |
Get information about a file. | |
Args: | |
filename (str): The name of the file. | |
Returns: | |
dict: A dictionary containing file information (size, creation time, modification time). | |
Raises: | |
FileOperationError: If there's an error getting file information. | |
""" | |
try: | |
file_path = Path(filename) | |
stats = file_path.stat() | |
return { | |
"size": stats.st_size, | |
"created": stats.st_ctime, | |
"modified": stats.st_mtime, | |
} | |
except FileNotFoundError: | |
raise FileOperationError(f"File '{filename}' not found") | |
except OSError as e: | |
raise FileOperationError(f"Failed to get info for file '{filename}'") from e | |
# Example usage | |
if __name__ == "__main__": | |
helper = FileHelper(log_level=logging.DEBUG) | |
try: | |
helper.create("example.txt", "Hello, World!") | |
content = helper.read("example.txt") | |
print("File contents:", content) | |
helper.update("example.txt", "Updated content") | |
helper.rename("example.txt", "new_example.txt") | |
file_info = FileHelper.get_file_info("new_example.txt") | |
print("File info:", file_info) | |
helper.delete("new_example.txt") | |
except FileOperationError as e: | |
print(f"An error occurred: {str(e)}") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment