Allow arbitrary database type to be passed in preparation for Academon integration

This commit is contained in:
Kumi 2022-09-19 07:25:19 +00:00
parent b736226140
commit d5e560d945
Signed by: kumi
GPG key ID: ECBCC9082395383F
5 changed files with 32 additions and 20 deletions

View file

@ -5,15 +5,18 @@ from typing import Union
from classes.vessel import Vessel from classes.vessel import Vessel
from classes.directory import Directory from classes.directory import Directory
from classes.database import Database
class MonsterConfig: class MonsterConfig:
def readFile(self, path: Union[str, Path]) -> None: def readFile(self, path: Union[str, Path], dbclass: type = Database) -> None:
"""Read .ini file into MonsterConfig object """Read .ini file into MonsterConfig object
Args: Args:
path (str, pathlib.Path): Location of the .ini file to read path (str, pathlib.Path): Location of the .ini file to read
(absolute or relative to the working directory) (absolute or relative to the working directory)
dbclass (type): Class to use for database connections. Defaults to
built-in Database using sqlite3.
Raises: Raises:
ValueError: Raised if the passed file is not a ContentMonster .ini ValueError: Raised if the passed file is not a ContentMonster .ini
@ -43,7 +46,8 @@ class MonsterConfig:
# Read Vessels from the config file # Read Vessels from the config file
elif section.startswith("Vessel"): elif section.startswith("Vessel"):
self.vessels.append(Vessel.fromConfig(parser[section])) self.vessels.append(
Vessel.fromConfig(parser[section], dbclass))
def __init__(self) -> None: def __init__(self) -> None:
"""Initialize a new (empty) MonsterConfig object """Initialize a new (empty) MonsterConfig object

View file

@ -11,7 +11,7 @@ class File:
"""Object representing a file found in a local Directory """Object representing a file found in a local Directory
""" """
def __init__(self, name: str, directory, uuid: Optional[str] = None) -> None: def __init__(self, name: str, directory, uuid: Optional[str] = None, dbclass: type = Database) -> None:
"""Initialize new File object """Initialize new File object
Args: Args:
@ -20,12 +20,15 @@ class File:
is located within is located within
uuid (str, optional): Unique identifier of this File object. Will uuid (str, optional): Unique identifier of this File object. Will
be retrieved from database if None. Defaults to None. be retrieved from database if None. Defaults to None.
dbclass (type): Class to use for database connections. Defaults to
built-in Database using sqlite3.
Raises: Raises:
FileNotFoundError: Raised if the specified File does not exist FileNotFoundError: Raised if the specified File does not exist
""" """
self.name = name self.name = name
self.directory = directory self.directory = directory
self.dbclass = dbclass
if not self.exists(): if not self.exists():
raise FileNotFoundError(f"File {self.name} does not exist in {self.directory.name}!") raise FileNotFoundError(f"File {self.name} does not exist in {self.directory.name}!")
@ -47,9 +50,9 @@ class File:
"""Return unique identifier for this File object """Return unique identifier for this File object
Returns: Returns:
str: File object's UUID retrieved from Database str: File object's UUID retrieved from database
""" """
db = Database() db = self.dbclass()
return db.getFileUUID(self) return db.getFileUUID(self)
def getFullPath(self) -> str: def getFullPath(self) -> str:

View file

@ -16,7 +16,7 @@ import os.path
class ShoreThread(Process): class ShoreThread(Process):
"""Thread handling the discovery of shore-side file changes """Thread handling the discovery of shore-side file changes
""" """
def __init__(self, state: dict) -> None: def __init__(self, state: dict, dbclass: type = Database) -> None:
"""Create a new ShoreThread object """Create a new ShoreThread object
Args: Args:
@ -27,6 +27,7 @@ class ShoreThread(Process):
self._state = state self._state = state
self.queue = Queue() self.queue = Queue()
self._logger = Logger() self._logger = Logger()
self._dbclass = dbclass
def getAllFiles(self) -> list: def getAllFiles(self) -> list:
"""Return File objects for all files in all Directories """Return File objects for all files in all Directories
@ -107,7 +108,7 @@ class ShoreThread(Process):
# Remove file from database # Remove file from database
self._logger.debug(f"Purging file {name} from database") self._logger.debug(f"Purging file {name} from database")
db = Database() db = self._dbclass()
db.removeFile(directory, name) db.removeFile(directory, name)
def addFile(self, fileobj): def addFile(self, fileobj):
@ -142,7 +143,7 @@ class ShoreThread(Process):
self._state["files"].append(f) self._state["files"].append(f)
def checkFileCompletion(self, fileobj: File) -> bool: def checkFileCompletion(self, fileobj: File) -> bool:
db = Database() db = self._dbclass()
complete = db.getCompletionByFileUUID(fileobj.uuid) complete = db.getCompletionByFileUUID(fileobj.uuid)
del(db) del(db)

View file

@ -14,12 +14,14 @@ class Vessel:
"""Class describing a Vessel (= a replication destination) """Class describing a Vessel (= a replication destination)
""" """
@classmethod @classmethod
def fromConfig(cls, config: SectionProxy): def fromConfig(cls, config: SectionProxy, dbclass: type = Database):
"""Create Vessel object from a Vessel section in the Config file """Create Vessel object from a Vessel section in the Config file
Args: Args:
config (configparser.SectionProxy): Vessel section defining a config (configparser.SectionProxy): Vessel section defining a
Vessel Vessel
dbclass (type): Class to use for database connections. Defaults to
built-in Database using sqlite3.
Raises: Raises:
ValueError: Raised if section does not contain Address parameter ValueError: Raised if section does not contain Address parameter
@ -60,7 +62,7 @@ class Vessel:
if "Address" in config.keys(): if "Address" in config.keys():
return cls(config.name.split()[1], config["Address"], username, return cls(config.name.split()[1], config["Address"], username,
password, passphrase, port, timeout, tempdir, ignoredirs) password, passphrase, port, timeout, tempdir, ignoredirs, dbclass)
else: else:
raise ValueError("Definition for Vessel " + raise ValueError("Definition for Vessel " +
config.name.split()[1] + " does not contain Address!") config.name.split()[1] + " does not contain Address!")
@ -69,7 +71,7 @@ class Vessel:
password: Optional[str] = None, passphrase: Optional[str] = None, password: Optional[str] = None, passphrase: Optional[str] = None,
port: Optional[int] = None, timeout: Optional[int] = None, port: Optional[int] = None, timeout: Optional[int] = None,
tempdir: Optional[Union[str, pathlib.Path]] = None, tempdir: Optional[Union[str, pathlib.Path]] = None,
ignoredirs: list[Optional[str]] = []) -> None: ignoredirs: list[Optional[str]] = [], dbclass: type = Database) -> None:
"""Initialize new Vessel object """Initialize new Vessel object
Args: Args:
@ -89,6 +91,7 @@ class Vessel:
self._connection = None self._connection = None
self._uploaded = self.getUploadedFromDB() # Files already uploaded self._uploaded = self.getUploadedFromDB() # Files already uploaded
self._ignoredirs = ignoredirs # Directories not replicated to this vessel self._ignoredirs = ignoredirs # Directories not replicated to this vessel
self._dbclass = dbclass
@property @property
def connection(self) -> Connection: def connection(self) -> Connection:
@ -116,7 +119,7 @@ class Vessel:
Returns: Returns:
list: List of UUIDs of Files that have been successfully uploaded list: List of UUIDs of Files that have been successfully uploaded
""" """
db = Database() db = self._dbclass()
return db.getCompletionForVessel(self) return db.getCompletionForVessel(self)
def currentUpload(self) -> Optional[tuple[str, str, str]]: def currentUpload(self) -> Optional[tuple[str, str, str]]:
@ -131,7 +134,7 @@ class Vessel:
""" """
self.assertTempDirectory() # After a reboot, the tempdir may be gone self.assertTempDirectory() # After a reboot, the tempdir may be gone
db = Database() db = self._dbclass()
output = db.getFileByUUID(self.connection.getCurrentUploadUUID()) output = db.getFileByUUID(self.connection.getCurrentUploadUUID())
del db del db

View file

@ -16,7 +16,7 @@ class VesselThread(Process):
"""Thread processing uploads to a single vessel """Thread processing uploads to a single vessel
""" """
def __init__(self, vessel: Vessel, state: dict) -> None: def __init__(self, vessel: Vessel, state: dict, dbclass: type = Database) -> None:
"""Initialize a new VesselThread """Initialize a new VesselThread
Args: Args:
@ -27,6 +27,7 @@ class VesselThread(Process):
self.vessel = vessel self.vessel = vessel
self._state = state self._state = state
self._logger = Logger() self._logger = Logger()
self._dbclass = dbclass
def run(self) -> NoReturn: def run(self) -> NoReturn:
"""Run thread and process uploads to the vessel """Run thread and process uploads to the vessel
@ -95,7 +96,7 @@ class VesselThread(Process):
f"Start processing file {fileobj.name} in directory {fileobj.directory.name} on vessel {self.vessel.name}") f"Start processing file {fileobj.name} in directory {fileobj.directory.name} on vessel {self.vessel.name}")
while True: while True:
db = Database() db = self._dbclass()
if not db.getFileByUUID(fileobj.uuid): if not db.getFileByUUID(fileobj.uuid):
self._logger.debug( self._logger.debug(
f"File {fileobj.name} in directory {fileobj.directory.name} does not exist anymore - deleting from {self.vessel.name}") f"File {fileobj.name} in directory {fileobj.directory.name} does not exist anymore - deleting from {self.vessel.name}")
@ -111,7 +112,7 @@ class VesselThread(Process):
f"File {fileobj.name} uploaded to vessel {self.vessel.name} completely - finalizing") f"File {fileobj.name} uploaded to vessel {self.vessel.name} completely - finalizing")
remotefile.finalizeUpload() remotefile.finalizeUpload()
db = Database() db = self._dbclass()
db.logCompletion(fileobj, self.vessel) db.logCompletion(fileobj, self.vessel)
del(db) del(db)
@ -143,7 +144,7 @@ class VesselThread(Process):
self.vessel.compileComplete(remotefile) self.vessel.compileComplete(remotefile)
def checkFileCompletion(self, fileobj: File) -> None: def checkFileCompletion(self, fileobj: File) -> None:
db = Database() db = self._dbclass()
complete = db.getCompletionByFileUUID(fileobj.uuid) complete = db.getCompletionByFileUUID(fileobj.uuid)
del(db) del(db)