2021-11-20 14:40:07 +00:00
|
|
|
from classes.chunk import Chunk
|
|
|
|
from classes.database import Database
|
|
|
|
|
2021-11-25 09:40:25 +00:00
|
|
|
from typing import Optional
|
|
|
|
|
2021-11-20 14:40:07 +00:00
|
|
|
import hashlib
|
2021-11-25 15:31:49 +00:00
|
|
|
import os.path
|
2021-11-20 14:40:07 +00:00
|
|
|
|
2021-11-25 09:40:25 +00:00
|
|
|
|
2021-11-20 14:40:07 +00:00
|
|
|
class File:
|
2021-11-25 15:31:49 +00:00
|
|
|
"""Object representing a file found in a local Directory
|
|
|
|
"""
|
|
|
|
|
2021-11-25 09:40:25 +00:00
|
|
|
def __init__(self, name: str, directory, uuid: Optional[str] = None) -> None:
|
|
|
|
"""Initialize new File object
|
2021-11-20 14:40:07 +00:00
|
|
|
|
2021-11-25 09:40:25 +00:00
|
|
|
Args:
|
|
|
|
name (str): Filename (basename without path) of the File to create
|
|
|
|
directory (classes.directory.Directory): Directory object the File
|
|
|
|
is located within
|
|
|
|
uuid (str, optional): Unique identifier of this File object. Will
|
|
|
|
be retrieved from database if None. Defaults to None.
|
2021-11-25 15:31:49 +00:00
|
|
|
|
|
|
|
Raises:
|
|
|
|
FileNotFoundError: Raised if the specified File does not exist
|
2021-11-25 09:40:25 +00:00
|
|
|
"""
|
2021-11-20 14:40:07 +00:00
|
|
|
self.name = name
|
|
|
|
self.directory = directory
|
2021-11-25 15:31:49 +00:00
|
|
|
|
|
|
|
if not self.exists():
|
2021-11-26 10:23:39 +00:00
|
|
|
raise FileNotFoundError(f"File {self.name} does not exist in {self.directory.name}!")
|
2021-11-25 15:31:49 +00:00
|
|
|
|
2021-11-20 14:40:07 +00:00
|
|
|
self.uuid = uuid or self.getUUID()
|
|
|
|
|
2021-11-25 15:31:49 +00:00
|
|
|
def exists(self) -> bool:
|
|
|
|
"""Check if the File exists on the local file system
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
bool: True if the File exists, else False
|
|
|
|
"""
|
|
|
|
return os.path.isfile(self.directory.location / self.name)
|
2021-11-25 09:40:25 +00:00
|
|
|
|
|
|
|
def getUUID(self) -> str:
|
|
|
|
"""Return unique identifier for this File object
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
str: File object's UUID retrieved from Database
|
|
|
|
"""
|
|
|
|
db = Database()
|
|
|
|
return db.getFileUUID(self)
|
|
|
|
|
|
|
|
def getFullPath(self) -> str:
|
|
|
|
"""Get the full path of the File
|
2021-11-20 14:40:07 +00:00
|
|
|
|
2021-11-25 09:40:25 +00:00
|
|
|
Returns:
|
|
|
|
str: Full path of the File on the local file system
|
|
|
|
"""
|
|
|
|
return self.directory.location / self.name
|
|
|
|
|
|
|
|
def getHash(self) -> str:
|
|
|
|
"""Get hash for this File
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
str: SHA256 for the full content of this File
|
|
|
|
"""
|
2021-11-20 14:40:07 +00:00
|
|
|
return self.getChunk(-1).getHash()
|
|
|
|
|
2021-11-25 09:40:25 +00:00
|
|
|
def getChunk(self, count: int, size: Optional[int] = None) -> Chunk:
|
|
|
|
"""Get a Chunk of this File
|
|
|
|
|
|
|
|
Args:
|
|
|
|
count (int): Position of the Chunk in a list of equally large
|
|
|
|
Chunks (first index: 0). -1 represents a Chunk containing the
|
|
|
|
complete file.
|
|
|
|
size (int, optional): Size of the Chunk to create in Bytes. Must
|
|
|
|
be set if count is not -1. Defaults to None.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
classes.chunk.Chunk: Chunk object containing File content from
|
|
|
|
(count * size) bytes to ((count + 1) * size - 1) bytes
|
|
|
|
|
|
|
|
Raises:
|
|
|
|
ValueError: Raised if size is not set for a count that is not -1
|
|
|
|
"""
|
|
|
|
if count != -1 and not size:
|
|
|
|
raise ValueError(
|
|
|
|
"A Chunk size needs to be passed to getChunk() if not using the complete file (-1)!")
|
|
|
|
|
2021-11-20 14:40:07 +00:00
|
|
|
with open(self.getFullPath(), "rb") as binary:
|
|
|
|
binary.seek((count * size) if count > 0 else 0)
|
|
|
|
data = binary.read(size if count >= 0 else None)
|
|
|
|
|
2021-11-25 09:40:25 +00:00
|
|
|
return Chunk(self, count, data)
|