Module database
--Expand source code -
-import datetime
-import os
-import re
-import sqlite3 as sql
-import tempfile
-from src.logic.log import MyLogger
-#from icecream import ic
-from typing import List, Tuple, Dict, Any, Optional, Union
-from pathlib import Path
-from omegaconf import OmegaConf
-from src.backend.db import CREATE_TABLE_APPARAT, CREATE_TABLE_MESSAGES, CREATE_TABLE_MEDIA, CREATE_TABLE_APPKONTOS, CREATE_TABLE_FILES, CREATE_TABLE_PROF, CREATE_TABLE_USER, CREATE_TABLE_SUBJECTS
-from src.logic.constants import SEMAP_MEDIA_ACCOUNTS
-from src.logic.dataclass import ApparatData, BookData
-from src.errors import NoResultError, AppPresentError
-from src.utils import load_pickle, dump_pickle,create_blob
-config = OmegaConf.load("config.yaml")
-logger = MyLogger(__name__)
-
-
-class Database:
- """
- Initialize the database and create the tables if they do not exist.
- """
- def __init__(self, db_path: str = None):
- """
- Default constructor for the database class
-
- Args:
- db_path (str, optional): Optional Path for testing / specific purposes. Defaults to None.
- """
- if db_path is None:
- self.db_path = config.database.path + config.database.name
- self.db_path = self.db_path.replace("~", str(Path.home()))
- else:
- self.db_path = db_path
- if self.get_db_contents() is None:
- logger.log_critical("Database does not exist, creating tables")
- self.create_tables()
- def get_db_contents(self)->Union[List[Tuple], None]:
- """
- Get the contents of the
-
- Returns:
- Union[List[Tuple], None]: _description_
- """
- try:
- with sql.connect(self.db_path) as conn:
- cursor = conn.cursor()
- cursor.execute("SELECT * FROM sqlite_master WHERE type='table'")
- return cursor.fetchall()
- except sql.OperationalError:
- return None
- def connect(self)->sql.Connection:
- """
- Connect to the database
-
- Returns:
- sql.Connection: The active connection to the database
- """
- return sql.connect(self.db_path)
- def close_connection(self, conn: sql.Connection):
- """
- closes the connection to the database
-
- Args:
- ----
- - conn (sql.Connection): the connection to be closed
- """
- conn.close()
- def create_tables(self):
- """
- Create the tables in the database
- """
- conn = self.connect()
- cursor = conn.cursor()
- cursor.execute(CREATE_TABLE_APPARAT)
- cursor.execute(CREATE_TABLE_MESSAGES)
- cursor.execute(CREATE_TABLE_MEDIA)
- cursor.execute(CREATE_TABLE_APPKONTOS)
- cursor.execute(CREATE_TABLE_FILES)
- cursor.execute(CREATE_TABLE_PROF)
- cursor.execute(CREATE_TABLE_USER)
- cursor.execute(CREATE_TABLE_SUBJECTS)
- conn.commit()
- self.close_connection(conn)
- def insertInto(self, query:str, params:Tuple) -> None:
- """
- Insert sent data into the database
-
- Args:
- query (str): The query to be executed
- params (Tuple): the parameters to be inserted into the database
- """
- conn = self.connect()
- cursor = conn.cursor()
- logger.log_info(f"Inserting {params} into database with query {query}")
- cursor.execute(query, params)
- conn.commit()
- self.close_connection(conn)
- def query_db(self, query: str, args: Tuple = (), one: bool = False)->Union[Tuple, List[Tuple]]:
- """
- Query the Database for the sent query.
-
- Args:
- query (str): The query to be executed
- args (Tuple, optional): The arguments for the query. Defaults to ().
- one (bool, optional): Return the first result only. Defaults to False.
-
- Returns:
- Union[Typle|List[Tuple]]: Returns the result of the query
- """
- conn = self.connect()
- cursor = conn.cursor()
- logger.log_info(f"Querying database with query {query}, args: {args}")
- cursor.execute(query, args)
- rv = cursor.fetchall()
- conn.commit()
- self.close_connection(conn)
- return (rv[0] if rv else None) if one else rv
-
- # Books
- def addBookToDatabase(self, bookdata:BookData,app_id:Union[str,int], prof_id:Union[str,int]):
- """
- Add books to the database. Both app_id and prof_id are required to add the book to the database, as the app_id and prof_id are used to select the books later on.
-
- Args:
- bookdata (BookData): The metadata of the book to be added
- app_id (str): The apparat id where the book should be added to
- prof_id (str): The id of the professor where the book should be added to.
- """
- conn = self.connect()
- cursor = conn.cursor()
- t_query = (
- f"SELECT bookdata FROM media WHERE app_id={app_id} AND prof_id={prof_id}"
- )
- # print(t_query)
- result = cursor.execute(t_query).fetchall()
- result = [load_pickle(i[0]) for i in result]
- if bookdata in result:
- print("Bookdata already in database")
- # check if the book was deleted in the apparat
- query = (
- "SELECT deleted FROM media WHERE app_id=? AND prof_id=? AND bookdata=?"
- )
- params = (app_id, prof_id, dump_pickle(bookdata))
- result = cursor.execute(query, params).fetchone()
- if result[0] == 1:
- print("Book was deleted, updating bookdata")
- query = "UPDATE media SET deleted=0 WHERE app_id=? AND prof_id=? AND bookdata=?"
- params = (app_id, prof_id, dump_pickle(bookdata))
- cursor.execute(query, params)
- conn.commit()
- return
-
- query = (
- "INSERT INTO media (bookdata, app_id, prof_id,deleted) VALUES (?, ?, ?,?)"
- )
- converted = dump_pickle(bookdata)
- params = (converted, app_id, prof_id, 0)
- cursor.execute(query, params)
- conn.commit()
- self.close_connection(conn)
- def getBookIdBasedOnSignature(self, app_id:Union[str,int], prof_id:Union[str,int],signature:str)->int:
- """
- Get a book id based on the signature of the book.
-
- Args:
- app_id (str): The apparat id the book should be associated with
- prof_id (str): The professor id the book should be associated with
- signature (str): The signature of the book
-
- Returns:
- int: The id of the book
- """
- result = self.query_db("SELECT bookdata, id FROM media WHERE app_id=? AND prof_id=?", (app_id,prof_id))
- books = [(load_pickle(i[0]),i[1]) for i in result]
- book = [i for i in books if i[0].signature == signature][0][1]
- return book
- def getBookBasedOnSignature(self, app_id:Union[str,int], prof_id:Union[str,int],signature:str)->BookData:
- """
- Get the book based on the signature of the book.
-
- Args:
- app_id (str): The apparat id the book should be associated with
- prof_id (str): The professor id the book should be associated with
- signature (str): The signature of the book
-
- Returns:
- BookData: The total metadata of the book wrapped in a BookData object
- """
- result = self.query_db("SELECT bookdata FROM media WHERE app_id=? AND prof_id=?", (app_id,prof_id))
- books = [load_pickle(i[0]) for i in result]
- book = [i for i in books if i.signature == signature][0]
- return book
- def getLastBookId(self)->int:
- """
- Get the last book id in the database
-
- Returns:
- int: ID of the last book in the database
- """
- return self.query_db("SELECT id FROM media ORDER BY id DESC", one=True)[0]
- def searchBook(self, data:dict[str, str])->list[tuple[BookData, int]]:
- """
- Search a book in the database based on the sent data.
-
- Args:
- data (dict[str, str]): A dictionary containing the data to be searched for. The dictionary can contain the following:
- - signature: The signature of the book
- - title: The title of the book
-
- Returns:
- list[tuple[BookData, int]]: A list of tuples containing the wrapped Metadata and the id of the book
- """
- rdata = self.query_db("SELECT * FROM media WHERE deleted=0")
- #ic(rdata, len(rdata))
- mode = 0
- if len(data)== 1:
- if "signature" in data.keys():
- mode = 1
- elif "title" in data.keys():
- mode = 2
- elif len(data) == 2:
- mode = 3
- else:
- return None
- ret = []
- for book in rdata:
- bookdata = load_pickle(book[1])
- app_id = book[2]
- prof_id = book[3]
- if mode == 1:
- if data["signature"] in bookdata.signature:
- ret.append((bookdata,app_id,prof_id))
- elif mode == 2:
- if data["title"] in bookdata.title:
- ret.append((bookdata,app_id,prof_id))
- elif mode == 3:
- if data["signature"] in bookdata.signature and data["title"] in bookdata.title:
- ret.append((bookdata,app_id,prof_id))
- #ic(ret)
- return ret
- def setAvailability(self, book_id:str, available:str):
- """
- Set the availability of a book in the database
-
- Args:
- book_id (str): The id of the book
- available (str): The availability of the book
- """
- self.query_db("UPDATE media SET available=? WHERE id=?", (available,book_id))
- def getBookId(self, bookdata:BookData, app_id:Union[str,int], prof_id:Union[str,int])->int:
- """
- Get the id of a book based on the metadata of the book
-
- Args:
- bookdata (BookData): The wrapped metadata of the book
- app_id (str): The apparat id the book should be associated with
- prof_id (str): The professor id the book should be associated with
-
- Returns:
- int: ID of the book
- """
- result = self.query_db("SELECT id FROM media WHERE bookdata=? AND app_id=? AND prof_id=?", (dump_pickle(bookdata),app_id,prof_id), one=True)
- return result[0]
- def getBook(self,book_id:int)->BookData:
- """
- Get the book based on the id in the database
-
- Args:
- book_id (int): The id of the book
-
- Returns:
- BookData: The metadata of the book wrapped in a BookData object
- """
- return load_pickle(self.query_db("SELECT bookdata FROM media WHERE id=?", (book_id,), one=True)[0])
- def getBooks(self, app_id:Union[str,int], prof_id:Union[str,int], deleted=0)->list[dict[int, BookData, int]]:
- """
- Get the Books based on the apparat id and the professor id
-
- Args:
- app_id (str): The ID of the apparat
- prof_id (str): The ID of the professor
- deleted (int, optional): The state of the book. Set to 1 to include deleted ones. Defaults to 0.
-
- Returns:
- list[dict[int, BookData, int]]: A list of dictionaries containing the id, the metadata of the book and the availability of the book
- """
- qdata = self.query_db(f"SELECT id,bookdata,available FROM media WHERE (app_id={app_id} AND prof_id={prof_id}) AND (deleted={deleted if deleted == 0 else '1 OR deleted=0'})")
- ret_result = []
- for result_a in qdata:
- data = {"id": int, "bookdata": BookData, "available": int}
- data["id"] = result_a[0]
- data["bookdata"] = load_pickle(result_a[1])
- data["available"] = result_a[2]
- ret_result.append(data)
- return ret_result
- def updateBookdata(self, book_id, bookdata:BookData):
- """
- Update the bookdata in the database
-
- Args:
- book_id (str): The id of the book
- bookdata (BookData): The new metadata of the book
- """
- self.query_db("UPDATE media SET bookdata=? WHERE id=?", (dump_pickle(bookdata),book_id))
- def deleteBook(self, book_id):
- """
- Delete a book from the database
-
- Args:
- book_id (str): ID of the book
- """
- self.query_db("UPDATE media SET deleted=1 WHERE id=?", (book_id,))
-
- # File Interactions
- def getBlob(self, filename, app_id:Union[str,int]):
- """
- Get a blob from the database
-
- Args:
- filename (str): The name of the file
- app_id (str): ID of the apparat
-
- Returns:
- bytes: The file stored in
- """
- return self.query_db("SELECT fileblob FROM files WHERE filename=? AND app_id=?", (filename,app_id), one=True)[0]
- def insertFile(self, file: list[dict], app_id:Union[str,int], prof_id:Union[str,int]):
- """Instert a list of files into the database
-
- Args:
- file (list[dict]): a list containing all the files to be inserted
- Structured: [{"name": "filename", "path": "path", "type": "filetype"}]
- app_id (int): the id of the apparat
- prof_id (str): the id of the professor
- """
- for f in file:
- filename = f["name"]
- path = f["path"]
- filetyp = f["type"]
- if path == "Database":
- continue
- blob = create_blob(path)
- query = "INSERT OR IGNORE INTO files (filename, fileblob, app_id, filetyp,prof_id) VALUES (?, ?, ?, ?,?)"
- self.query_db(query, (filename, blob, app_id, filetyp,prof_id))
- def recreateFile(self, filename:str, app_id:Union[str,int],filetype:str)->str:
- """Recreate a file from the database
-
- Args:
- filename (str): the name of the file
- app_id (Union[str,int]): the id of the apparat
- filetype (str): the extension of the file to be created
-
- Returns:
- str: The filename of the recreated file
- """
- blob = self.getBlob(filename, app_id)
- tempdir = config.database.tempdir
- tempdir = tempdir.replace("~", str(Path.home()))
- tempdir_path = Path(tempdir)
- if not os.path.exists(tempdir_path):
- os.mkdir(tempdir_path)
- file = tempfile.NamedTemporaryFile(
- delete=False, dir=tempdir_path, mode="wb", suffix=f".{filetype}"
- )
- file.write(blob)
- print("file created")
- return file.name
- def getFiles(self, app_id:Union[str,int], prof_id:int)->list[tuple]:
- """Get all the files associated with the apparat and the professor
-
- Args:
- app_id (Union[str,int]): The id of the apparat
- prof_id (Union[str,int]): the id of the professor
-
- Returns:
- list[tuple]: a list of tuples containing the filename and the filetype for the corresponding apparat and professor
- """
- return self.query_db("SELECT filename, filetyp FROM files WHERE app_id=? AND prof_id=?", (app_id,prof_id))
-
- def getSemersters(self)->list[str]:
- """Return all the unique semesters in the database
-
- Returns:
- list: a list of strings containing the semesters
- """
- data = self.query_db("SELECT DISTINCT erstellsemester FROM semesterapparat")
- return [i[0] for i in data]
-
- def getSubjects(self):
- """Get all the subjects in the database
-
- Returns:
- list[tuple]: a list of tuples containing the subjects
- """
- return self.query_db("SELECT * FROM subjects")
-
- # Messages
- def addMessage(self, message:dict,user:str, app_id:Union[str,int]):
- """add a Message to the database
-
- Args:
- message (dict): the message to be added
- user (str): the user who added the message
- app_id (Union[str,int]): the id of the apparat
- """
- def __getUserId(user):
- return self.query_db("SELECT id FROM user WHERE username=?", (user,), one=True)[0]
- user_id = __getUserId(user)
- self.query_db("INSERT INTO messages (message, user_id, remind_at,appnr) VALUES (?,?,?,?)", (message["message"],user_id,message["remind_at"],app_id))
- def getMessages(self, date:str)->list[dict[str, str, str, str]]:
- """Get all the messages for a specific date
-
- Args:
- date (str): a date.datetime object formatted as a string in the format "YYYY-MM-DD"
-
- Returns:
- list[dict[str, str, str, str]]: a list of dictionaries containing the message, the user who added the message, the apparat id and the id of the message
- """
- def __get_user_name(user_id):
- return self.query_db("SELECT username FROM user WHERE id=?", (user_id,), one=True)[0]
- messages = self.query_db("SELECT * FROM messages WHERE remind_at=?", (date,))
- ret = [
- {
- "message": i[2],
- "user": __get_user_name(i[4]),
- "appnr": i[5],
- "id": i[0]
- }
- for i in messages
- ]
- return ret
- def deleteMessage(self, message_id):
- """Delete a message from the database
-
- Args:
- message_id (str): the id of the message
- """
- self.query_db("DELETE FROM messages WHERE id=?", (message_id,))
-
- # Prof data
- def getProfNameById(self, prof_id:Union[str,int],add_title:bool=False)->str:
- """Get a professor name based on the id
-
- Args:
- prof_id (Union[str,int]): The id of the professor
- add_title (bool, optional): wether to add the title or no. Defaults to False.
-
- Returns:
- str: The name of the professor
- """
- prof = self.query_db("SELECT fullname FROM prof WHERE id=?", (prof_id,), one=True)
- if add_title:
- return f"{self.getTitleById(prof_id)}{prof[0]}"
- else:
- return prof[0]
- def getTitleById(self, prof_id:Union[str,int])->str:
- """get the title of a professor based on the id
-
- Args:
- prof_id (Union[str,int]): the id of the professor
-
- Returns:
- str: the title of the professor, with an added whitespace at the end, if no title is present, an empty string is returned
- """
- title = self.query_db("SELECT titel FROM prof WHERE id=?", (prof_id,), one=True)[0]
- return f"{title} " if title is not None else ""
- def getProfByName(self, prof_name:str)->tuple:
- """get all the data of a professor based on the name
-
- Args:
- prof_name (str): the name of the professor
-
- Returns:
- tuple: the data of the professor
- """
- return self.query_db("SELECT * FROM prof WHERE fullname=?", (prof_name,), one=True)
- def getProfId(self, prof_name:str)->Optional[int]:
- """Get the id of a professor based on the name
-
- Args:
- prof_name (str): the name of the professor
-
- Returns:
- Optional[int]: the id of the professor, if the professor is not found, None is returned
- """
-
- data = self.getProfByName(prof_name.replace(",", ""))
- if data is None:
- return None
- else:
- return data[0]
- def getSpecificProfData(self, prof_id:Union[str,int], fields:List[str])->tuple:
- """A customisable function to get specific data of a professor based on the id
-
- Args:
- prof_id (Union[str,int]): the id of the professor
- fields (List[str]): a list of fields to be returned
-
- Returns:
- tuple: a tuple containing the requested data
- """
- query = "SELECT "
- for field in fields:
- query += f"{field},"
- query = query[:-1]
- query += " FROM prof WHERE id=?"
- return self.query_db(query, (prof_id,), one=True)[0]
- def getProfData(self, profname:str):
- """Get mail, telephone number and title of a professor based on the name
-
- Args:
- profname (str): name of the professor
-
- Returns:
- tuple: the mail, telephone number and title of the professor
- """
- data = self.query_db("SELECT mail, telnr, titel FROM prof WHERE fullname=?", (profname.replace(",",""),), one=True)
- return data
- def createProf(self, prof_details:dict):
- """Create a professor in the database
-
- Args:
- prof_details (dict): a dictionary containing the details of the professor
- """
- prof_title = prof_details["prof_title"]
- prof_fname = prof_details["profname"].split(",")[1]
- prof_fname = prof_fname.strip()
- prof_lname = prof_details["profname"].split(",")[0]
- prof_lname = prof_lname.strip()
- prof_fullname = prof_details["profname"].replace(",", "")
- prof_mail = prof_details["prof_mail"]
- prof_tel = prof_details["prof_tel"]
- params = (prof_title, prof_fname, prof_lname, prof_mail, prof_tel, prof_fullname)
- query = "INSERT OR IGNORE INTO prof (titel, fname, lname, mail, telnr, fullname) VALUES (?, ?, ?, ?, ?, ?)"
- self.insertInto(query=query, params=params)
- def getProfs(self)->list[tuple]:
- """Return all the professors in the database
-
- Returns:
- list[tuple]: a list containing all the professors in individual tuples
- """
- return self.query_db("SELECT * FROM prof")
-
- # Apparat
- def getAllAparats(self,deleted=0)->list[tuple]:
- """Get all the apparats in the database
-
- Args:
- deleted (int, optional): Switch the result to use . Defaults to 0.
-
- Returns:
- list[tuple]: a list of tuples containing the apparats
- """
- return self.query_db("SELECT * FROM semesterapparat WHERE deletion_status=?", (deleted,))
- def getApparatData(self, appnr, appname)->ApparatData:
- """Get the Apparat data based on the apparat number and the name
-
- Args:
- appnr (str): the apparat number
- appname (str): the name of the apparat
-
- Raises:
- NoResultError: an error is raised if no result is found
-
- Returns:
- ApparatData: the appended data of the apparat wrapped in an ApparatData object
- """
- result = self.query_db("SELECT * FROM semesterapparat WHERE appnr=? AND name=?", (appnr,appname), one=True)
- if result is None:
- raise NoResultError("No result found")
- apparat = ApparatData()
- apparat.appname = result[1]
- apparat.appnr = result[4]
- apparat.dauerapp = True if result[7] == 1 else False
- prof_data = self.getProfData(self.getProfNameById(result[2]))
- apparat.profname = self.getProfNameById(result[2])
- apparat.prof_mail = prof_data[0]
- apparat.prof_tel = prof_data[1]
- apparat.prof_title = prof_data[2]
- apparat.app_fach = result[3]
- apparat.erstellsemester = result[5]
- apparat.semester = result[8]
- apparat.deleted = result[9]
- apparat.apparat_adis_id = result[11]
- apparat.prof_adis_id = result[12]
- return apparat
- def getUnavailableApparatNumbers(self)->List[int]:
- """Get a list of all the apparat numbers in the database that are currently in use
-
- Returns:
- List[int]: the list of used apparat numbers
- """
- numbers = self.query_db("SELECT appnr FROM semesterapparat WHERE deletion_status=0")
- numbers = [i[0] for i in numbers]
- logger.log_info(f"Currently used apparat numbers: {numbers}")
- return numbers
- def setNewSemesterDate(self, app_id:Union[str,int], newDate, dauerapp=False):
- """Set the new semester date for an apparat
-
- Args:
- app_id (Union[str,int]): the id of the apparat
- newDate (str): the new date
- dauerapp (bool, optional): if the apparat was changed to dauerapparat. Defaults to False.
- """
- date = datetime.datetime.strptime(newDate, "%d.%m.%Y").strftime("%Y-%m-%d")
- if dauerapp:
- self.query_db("UPDATE semesterapparat SET verlängerung_bis=?, dauerapp=? WHERE appnr=?", (date,dauerapp,app_id))
- else:
- self.query_db("UPDATE semesterapparat SET endsemester=? WHERE appnr=?", (date,app_id))
- def getApparatId(self, apparat_name)->Optional[int]:
- """get the id of an apparat based on the name
-
- Args:
- apparat_name (str): the name of the apparat e.g. "Semesterapparat 1"
-
- Returns:
- Optional[int]: the id of the apparat, if the apparat is not found, None is returned
- """
- data = self.query_db("SELECT appnr FROM semesterapparat WHERE name=?", (apparat_name,), one=True)
- if data is None:
- return None
- else:
- return data[0]
- def createApparat(self, apparat:ApparatData)->int:
- """create the apparat in the database
-
- Args:
- apparat (ApparatData): the wrapped metadata of the apparat
-
- Raises:
- AppPresentError: an error describing that the apparats chosen id is already present in the database
-
- Returns:
- Optional[int]: the id of the apparat
- """
-
- prof_id = self.getProfId(apparat.profname)
- app_id = self.getApparatId(apparat.appname)
- if app_id:
- raise AppPresentError(app_id)
-
- self.createProf(apparat.get_prof_details())
- prof_id = self.getProfId(apparat.profname)
- #ic(prof_id)
- query = f"INSERT OR IGNORE INTO semesterapparat (appnr, name, erstellsemester, dauer, prof_id, fach,deletion_status,konto) VALUES ('{apparat.appnr}', '{apparat.appname}', '{apparat.semester}', '{apparat.dauerapp}', {prof_id}, '{apparat.app_fach}', '{0}', '{SEMAP_MEDIA_ACCOUNTS[apparat.appnr]}')"
- logger.log_info(query)
- self.query_db(query)
- return self.getApparatId(apparat.appname)
- def getApparatsByProf(self, prof_id:Union[str,int])->list[tuple]:
- """Get all apparats based on the professor id
-
- Args:
- prof_id (Union[str,int]): the id of the professor
-
- Returns:
- list[tuple]: a list of tuples containing the apparats
- """
- return self.query_db("SELECT * FROM semesterapparat WHERE prof_id=?", (prof_id,))
- def getApparatsBySemester(self, semester:str)->dict[list]:
- """get all apparats based on the semester
-
- Args:
- semester (str): the selected semester
-
- Returns:
- dict[list]: a list off all created and deleted apparats for the selected semester
- """
- data = self.query_db("SELECT name, prof_id FROM semesterapparat WHERE erstellsemester=?", (semester,))
- conn = self.connect()
- cursor = conn.cursor()
- c_tmp = []
- for i in data:
- c_tmp.append((i[0], self.getProfNameById(i[1])))
- query = (
- f"SELECT name,prof_id FROM semesterapparat WHERE deleted_date='{semester}'"
- )
- result = cursor.execute(query).fetchall()
- d_tmp = []
- for i in result:
- d_tmp.append((i[0], self.getProfNameById(i[1])))
- # group the apparats by prof
- c_ret = {}
- for i in c_tmp:
- if i[1] not in c_ret.keys():
- c_ret[i[1]] = [i[0]]
- else:
- c_ret[i[1]].append(i[0])
- d_ret = {}
- for i in d_tmp:
- if i[1] not in d_ret.keys():
- d_ret[i[1]] = [i[0]]
- else:
- d_ret[i[1]].append(i[0])
- self.close_connection(conn)
- return {"created": c_ret, "deleted": d_ret}
- def getApparatCountBySemester(self)->tuple[list[str],list[int]]:
- """get a list of all apparats created and deleted by semester
-
- Returns:
- tuple[list[str],list[int]]: a tuple containing two lists, the first list contains the semesters, the second list contains the amount of apparats created and deleted for the corresponding semester
- """
- conn = self.connect()
- cursor = conn.cursor()
- semesters = self.getSemersters()
- created = []
- deleted = []
- for semester in semesters:
- query = f"SELECT COUNT(*) FROM semesterapparat WHERE erstellsemester='{semester}'"
- result = cursor.execute(query).fetchone()
- created.append(result[0])
- query = f"SELECT COUNT(*) FROM semesterapparat WHERE deletion_status=1 AND deleted_date='{semester}'"
- result = cursor.execute(query).fetchone()
- deleted.append(result[0])
- # store data in a tuple
- ret = []
- e_tuple = ()
- for sem in semesters:
- e_tuple = (
- sem,
- created[semesters.index(sem)],
- deleted[semesters.index(sem)],
- )
- ret.append(e_tuple)
- self.close_connection(conn)
- return ret
- def deleteApparat(self, app_id:Union[str,int], semester:str):
- """Delete an apparat from the database
-
- Args:
- app_id (Union[str, int]): the id of the apparat
- semester (str): the semester the apparat should be deleted from
- """
- self.query_db("UPDATE semesterapparat SET deletion_status=1, deleted_date=? WHERE appnr=?", (semester,app_id))
- def isEternal(self, id):
- """check if the apparat is eternal (dauerapparat)
-
- Args:
- id (int): the id of the apparat to be checked
-
- Returns:
- int: the state of the apparat
- """
- return self.query_db("SELECT dauer FROM semesterapparat WHERE appnr=?", (id,), one=True)
- def getApparatName(self, app_id:Union[str,int], prof_id:Union[str,int]):
- """get the name of the apparat based on the id
-
- Args:
- app_id (Union[str,int]): the id of the apparat
- prof_id (Union[str,int]): the id of the professor
-
- Returns:
- str: the name of the apparat
- """
- return self.query_db("SELECT name FROM semesterapparat WHERE appnr=? AND prof_id=?", (app_id,prof_id), one=True)[0]
- def updateApparat(self, apparat_data:ApparatData):
- """Update an apparat in the database
-
- Args:
- apparat_data (ApparatData): the new metadata of the apparat
- """
- query = f"UPDATE semesterapparat SET name = ?, fach = ?, dauer = ?, prof_id = ? WHERE appnr = ?"
- params = (
- apparat_data.appname,
- apparat_data.app_fach,
- apparat_data.dauerapp,
- self.getProfId(apparat_data.profname),
- apparat_data.appnr,
- )
- self.query_db(query, params)
- def checkApparatExists(self, apparat_name:str):
- """check if the apparat is already present in the database based on the name
-
- Args:
- apparat_name (str): the name of the apparat
-
- Returns:
- bool: True if the apparat is present, False if not
- """
- return True if self.query_db("SELECT appnr FROM semesterapparat WHERE name=?", (apparat_name,), one=True) else False
- def checkApparatExistsById(self, app_id:Union[str,int])->bool:
- """a check to see if the apparat is already present in the database, based on the id
-
- Args:
- app_id (Union[str, int]): the id of the apparat
-
- Returns:
- bool: True if the apparat is present, False if not
- """
- return True if self.query_db("SELECT appnr FROM semesterapparat WHERE appnr=?", (app_id,), one=True) else False
- # Statistics
- def statistic_request(self, **kwargs: Any):
- """Take n amount of kwargs and return the result of the query
- """
- def __query(query):
- """execute the query and return the result
-
- Args:
- query (str): the constructed query
-
- Returns:
- list: the result of the query
- """
- conn = self.connect()
- cursor = conn.cursor()
- result = cursor.execute(query).fetchall()
- for result_a in result:
- orig_value = result_a
- prof_name = self.getProfNameById(result_a[2])
- # replace the prof_id with the prof_name
- result_a = list(result_a)
- result_a[2] = prof_name
- result_a = tuple(result_a)
- result[result.index(orig_value)] = result_a
- self.close_connection(conn)
- return result
- if "deletable" in kwargs.keys():
- query = f"SELECT * FROM semesterapparat WHERE deletion_status=0 AND dauer=0 AND (erstellsemester!='{kwargs['deletesemester']}' OR verlängerung_bis!='{kwargs['deletesemester']}')"
- return __query(query)
- if "dauer" in kwargs.keys():
- kwargs["dauer"] = kwargs["dauer"].replace("Ja", "1").replace("Nein", "0")
- query = "SELECT * FROM semesterapparat WHERE "
- for key, value in kwargs.items() if kwargs.items() is not None else {}:
- print(key, value)
- query += f"{key}='{value}' AND "
- print(query)
- # remove deletesemester part from normal query, as this will be added to the database upon deleting the apparat
- if "deletesemester" in kwargs.keys():
- query = query.replace(
- f"deletesemester='{kwargs['deletesemester']}' AND ", ""
- )
- if "endsemester" in kwargs.keys():
- if "erstellsemester" in kwargs.keys():
- query = query.replace(f"endsemester='{kwargs['endsemester']}' AND ", "")
- query = query.replace(
- f"erstellsemester='{kwargs['erstellsemester']} AND ", "xyz"
- )
- else:
- query = query.replace(
- f"endsemester='{kwargs['endsemester']}' AND ", "xyz"
- )
- print("replaced")
- query = query.replace(
- "xyz",
- f"(erstellsemester='{kwargs['endsemester']}' OR verlängerung_bis='{kwargs['endsemester']}') AND ",
- )
- # remove all x="" parts from the query where x is a key in kwargs
- query = query[:-5]
- print(query)
- return __query(query)
-
- # Admin data
- def getUser(self):
- """Get a single user from the database"""
- return self.query_db("SELECT * FROM user", one=True)
- def getUsers(self)->list[tuple]:
- """Return a list of tuples of all the users in the database"""
- return self.query_db("SELECT * FROM user")
-
- def login(self, user, hashed_password):
- """try to login the user.
- The salt for the user will be requested from the database and then added to the hashed password. The password will then be compared to the password in the database
-
- Args:
- user (str): username that tries to login
- hashed_password (str): the password the user tries to login with
-
- Returns:
- bool: True if the login was successful, False if not
- """
- salt = self.query_db("SELECT salt FROM user WHERE username=?", (user,), one=True)[0]
- if salt is None:
- return False
- hashed_password = salt + hashed_password
- password = self.query_db("SELECT password FROM user WHERE username=?", (user,), one=True)[0]
- if password == hashed_password:
- return True
- else:
- return False
- def changePassword(self, user, new_password):
- """change the password of a user.
- The password will be added with the salt and then committed to the database
-
- Args:
- user (str): username
- new_password (str): the hashed password
- """
- salt = self.query_db("SELECT salt FROM user WHERE username=?", (user,), one=True)[0]
- new_password = salt + new_password
- self.query_db("UPDATE user SET password=? WHERE username=?", (new_password,user))
- def getRole(self, user):
- """get the role of the user
-
- Args:
- user (str): username
-
- Returns:
- str: the name of the role
- """
- return self.query_db("SELECT role FROM user WHERE username=?", (user,), one=True)[0]
- def getRoles(self)->list[tuple]:
- """get all the roles in the database
-
- Returns:
- list[str]: a list of all the roles
- """
- return self.query_db("SELECT role FROM user")
- def checkUsername(self, user)->bool:
- """a check to see if the username is already present in the database
-
- Args:
- user (str): the username
-
- Returns:
- bool: True if the username is present, False if not
- """
- data = self.query_db("SELECT username FROM user WHERE username=?", (user,), one=True)
- return True if data is not None else False
- def createUser(self, user, password, role, salt):
- """create an user from the AdminCommands class.
-
- Args:
- user (str): the username of the user
- password (str): a hashed password
- role (str): the role of the user
- salt (str): a salt for the password
- """
- self.query_db("INSERT OR IGNORE INTO user (username, password, role, salt) VALUES (?,?,?,?)", (user,password,role,salt))
- def deleteUser(self, user):
- """delete an unser
-
- Args:
- user (str): username of the user
- """
- self.query_db("DELETE FROM user WHERE username=?", (user,))
- def updateUser(self, username, data:dict[str, str]):
- """changge the data of a user
-
- Args:
- username (str): the username of the user
- data (dict[str, str]): the data to be changed
- """
- conn = self.connect()
- cursor = conn.cursor()
- query = "UPDATE user SET "
- for key,value in data.items():
- if key == "username":
- continue
- query += f"{key}='{value}',"
- query = query[:-1]
- query += " WHERE username=?"
- params = (username,)
- cursor.execute(query, params)
- conn.commit()
- self.close_connection(conn)
- def getFacultyMember(self, name:str)->tuple:
- """get a faculty member based on the name
-
- Args:
- name (str): the name to be searched for
-
- Returns:
- tuple: a tuple containing the data of the faculty member
- """
- return self.query_db("SELECT titel, fname,lname,mail,telnr,fullname FROM prof WHERE fullname=?", (name,), one=True)
- def updateFacultyMember(self, data:dict, oldlname:str, oldfname:str):
- """update the data of a faculty member
-
- Args:
- data (dict): a dictionary containing the data to be updated
- oldlname (str): the old last name of the faculty member
- oldfname (str): the old first name of the faculty member
- """
- placeholders = ", ".join([f"{i}=:{i} " for i in data.keys()])
- query = f"UPDATE prof SET {placeholders} WHERE lname = :oldlname AND fname = :oldfname"
- data["oldlname"] = oldlname
- data["oldfname"] = oldfname
- self.query_db(query, data)
- def getFacultyMembers(self):
- """get a list of all faculty members
-
- Returns:
- list[tuple]: a list of tuples containing the faculty members
- """
- return self.query_db("SELECT titel, fname,lname,mail,telnr,fullname FROM prof")
-Classes
--
-
-class Database -(db_path: str = None) -
--
--
Initialize the database and create the tables if they do not exist.
-Default constructor for the database class
-Args
--
-
db_path:str, optional
-- Optional Path for testing / specific purposes. Defaults to None. -
---Expand source code -
-
-class Database: - """ - Initialize the database and create the tables if they do not exist. - """ - def __init__(self, db_path: str = None): - """ - Default constructor for the database class - - Args: - db_path (str, optional): Optional Path for testing / specific purposes. Defaults to None. - """ - if db_path is None: - self.db_path = config.database.path + config.database.name - self.db_path = self.db_path.replace("~", str(Path.home())) - else: - self.db_path = db_path - if self.get_db_contents() is None: - logger.log_critical("Database does not exist, creating tables") - self.create_tables() - def get_db_contents(self)->Union[List[Tuple], None]: - """ - Get the contents of the - - Returns: - Union[List[Tuple], None]: _description_ - """ - try: - with sql.connect(self.db_path) as conn: - cursor = conn.cursor() - cursor.execute("SELECT * FROM sqlite_master WHERE type='table'") - return cursor.fetchall() - except sql.OperationalError: - return None - def connect(self)->sql.Connection: - """ - Connect to the database - - Returns: - sql.Connection: The active connection to the database - """ - return sql.connect(self.db_path) - def close_connection(self, conn: sql.Connection): - """ - closes the connection to the database - - Args: - ---- - - conn (sql.Connection): the connection to be closed - """ - conn.close() - def create_tables(self): - """ - Create the tables in the database - """ - conn = self.connect() - cursor = conn.cursor() - cursor.execute(CREATE_TABLE_APPARAT) - cursor.execute(CREATE_TABLE_MESSAGES) - cursor.execute(CREATE_TABLE_MEDIA) - cursor.execute(CREATE_TABLE_APPKONTOS) - cursor.execute(CREATE_TABLE_FILES) - cursor.execute(CREATE_TABLE_PROF) - cursor.execute(CREATE_TABLE_USER) - cursor.execute(CREATE_TABLE_SUBJECTS) - conn.commit() - self.close_connection(conn) - def insertInto(self, query:str, params:Tuple) -> None: - """ - Insert sent data into the database - - Args: - query (str): The query to be executed - params (Tuple): the parameters to be inserted into the database - """ - conn = self.connect() - cursor = conn.cursor() - logger.log_info(f"Inserting {params} into database with query {query}") - cursor.execute(query, params) - conn.commit() - self.close_connection(conn) - def query_db(self, query: str, args: Tuple = (), one: bool = False)->Union[Tuple, List[Tuple]]: - """ - Query the Database for the sent query. - - Args: - query (str): The query to be executed - args (Tuple, optional): The arguments for the query. Defaults to (). - one (bool, optional): Return the first result only. Defaults to False. - - Returns: - Union[Typle|List[Tuple]]: Returns the result of the query - """ - conn = self.connect() - cursor = conn.cursor() - logger.log_info(f"Querying database with query {query}, args: {args}") - cursor.execute(query, args) - rv = cursor.fetchall() - conn.commit() - self.close_connection(conn) - return (rv[0] if rv else None) if one else rv - - # Books - def addBookToDatabase(self, bookdata:BookData,app_id:Union[str,int], prof_id:Union[str,int]): - """ - Add books to the database. Both app_id and prof_id are required to add the book to the database, as the app_id and prof_id are used to select the books later on. - - Args: - bookdata (BookData): The metadata of the book to be added - app_id (str): The apparat id where the book should be added to - prof_id (str): The id of the professor where the book should be added to. - """ - conn = self.connect() - cursor = conn.cursor() - t_query = ( - f"SELECT bookdata FROM media WHERE app_id={app_id} AND prof_id={prof_id}" - ) - # print(t_query) - result = cursor.execute(t_query).fetchall() - result = [load_pickle(i[0]) for i in result] - if bookdata in result: - print("Bookdata already in database") - # check if the book was deleted in the apparat - query = ( - "SELECT deleted FROM media WHERE app_id=? AND prof_id=? AND bookdata=?" - ) - params = (app_id, prof_id, dump_pickle(bookdata)) - result = cursor.execute(query, params).fetchone() - if result[0] == 1: - print("Book was deleted, updating bookdata") - query = "UPDATE media SET deleted=0 WHERE app_id=? AND prof_id=? AND bookdata=?" - params = (app_id, prof_id, dump_pickle(bookdata)) - cursor.execute(query, params) - conn.commit() - return - - query = ( - "INSERT INTO media (bookdata, app_id, prof_id,deleted) VALUES (?, ?, ?,?)" - ) - converted = dump_pickle(bookdata) - params = (converted, app_id, prof_id, 0) - cursor.execute(query, params) - conn.commit() - self.close_connection(conn) - def getBookIdBasedOnSignature(self, app_id:Union[str,int], prof_id:Union[str,int],signature:str)->int: - """ - Get a book id based on the signature of the book. - - Args: - app_id (str): The apparat id the book should be associated with - prof_id (str): The professor id the book should be associated with - signature (str): The signature of the book - - Returns: - int: The id of the book - """ - result = self.query_db("SELECT bookdata, id FROM media WHERE app_id=? AND prof_id=?", (app_id,prof_id)) - books = [(load_pickle(i[0]),i[1]) for i in result] - book = [i for i in books if i[0].signature == signature][0][1] - return book - def getBookBasedOnSignature(self, app_id:Union[str,int], prof_id:Union[str,int],signature:str)->BookData: - """ - Get the book based on the signature of the book. - - Args: - app_id (str): The apparat id the book should be associated with - prof_id (str): The professor id the book should be associated with - signature (str): The signature of the book - - Returns: - BookData: The total metadata of the book wrapped in a BookData object - """ - result = self.query_db("SELECT bookdata FROM media WHERE app_id=? AND prof_id=?", (app_id,prof_id)) - books = [load_pickle(i[0]) for i in result] - book = [i for i in books if i.signature == signature][0] - return book - def getLastBookId(self)->int: - """ - Get the last book id in the database - - Returns: - int: ID of the last book in the database - """ - return self.query_db("SELECT id FROM media ORDER BY id DESC", one=True)[0] - def searchBook(self, data:dict[str, str])->list[tuple[BookData, int]]: - """ - Search a book in the database based on the sent data. - - Args: - data (dict[str, str]): A dictionary containing the data to be searched for. The dictionary can contain the following: - - signature: The signature of the book - - title: The title of the book - - Returns: - list[tuple[BookData, int]]: A list of tuples containing the wrapped Metadata and the id of the book - """ - rdata = self.query_db("SELECT * FROM media WHERE deleted=0") - #ic(rdata, len(rdata)) - mode = 0 - if len(data)== 1: - if "signature" in data.keys(): - mode = 1 - elif "title" in data.keys(): - mode = 2 - elif len(data) == 2: - mode = 3 - else: - return None - ret = [] - for book in rdata: - bookdata = load_pickle(book[1]) - app_id = book[2] - prof_id = book[3] - if mode == 1: - if data["signature"] in bookdata.signature: - ret.append((bookdata,app_id,prof_id)) - elif mode == 2: - if data["title"] in bookdata.title: - ret.append((bookdata,app_id,prof_id)) - elif mode == 3: - if data["signature"] in bookdata.signature and data["title"] in bookdata.title: - ret.append((bookdata,app_id,prof_id)) - #ic(ret) - return ret - def setAvailability(self, book_id:str, available:str): - """ - Set the availability of a book in the database - - Args: - book_id (str): The id of the book - available (str): The availability of the book - """ - self.query_db("UPDATE media SET available=? WHERE id=?", (available,book_id)) - def getBookId(self, bookdata:BookData, app_id:Union[str,int], prof_id:Union[str,int])->int: - """ - Get the id of a book based on the metadata of the book - - Args: - bookdata (BookData): The wrapped metadata of the book - app_id (str): The apparat id the book should be associated with - prof_id (str): The professor id the book should be associated with - - Returns: - int: ID of the book - """ - result = self.query_db("SELECT id FROM media WHERE bookdata=? AND app_id=? AND prof_id=?", (dump_pickle(bookdata),app_id,prof_id), one=True) - return result[0] - def getBook(self,book_id:int)->BookData: - """ - Get the book based on the id in the database - - Args: - book_id (int): The id of the book - - Returns: - BookData: The metadata of the book wrapped in a BookData object - """ - return load_pickle(self.query_db("SELECT bookdata FROM media WHERE id=?", (book_id,), one=True)[0]) - def getBooks(self, app_id:Union[str,int], prof_id:Union[str,int], deleted=0)->list[dict[int, BookData, int]]: - """ - Get the Books based on the apparat id and the professor id - - Args: - app_id (str): The ID of the apparat - prof_id (str): The ID of the professor - deleted (int, optional): The state of the book. Set to 1 to include deleted ones. Defaults to 0. - - Returns: - list[dict[int, BookData, int]]: A list of dictionaries containing the id, the metadata of the book and the availability of the book - """ - qdata = self.query_db(f"SELECT id,bookdata,available FROM media WHERE (app_id={app_id} AND prof_id={prof_id}) AND (deleted={deleted if deleted == 0 else '1 OR deleted=0'})") - ret_result = [] - for result_a in qdata: - data = {"id": int, "bookdata": BookData, "available": int} - data["id"] = result_a[0] - data["bookdata"] = load_pickle(result_a[1]) - data["available"] = result_a[2] - ret_result.append(data) - return ret_result - def updateBookdata(self, book_id, bookdata:BookData): - """ - Update the bookdata in the database - - Args: - book_id (str): The id of the book - bookdata (BookData): The new metadata of the book - """ - self.query_db("UPDATE media SET bookdata=? WHERE id=?", (dump_pickle(bookdata),book_id)) - def deleteBook(self, book_id): - """ - Delete a book from the database - - Args: - book_id (str): ID of the book - """ - self.query_db("UPDATE media SET deleted=1 WHERE id=?", (book_id,)) - - # File Interactions - def getBlob(self, filename, app_id:Union[str,int]): - """ - Get a blob from the database - - Args: - filename (str): The name of the file - app_id (str): ID of the apparat - - Returns: - bytes: The file stored in - """ - return self.query_db("SELECT fileblob FROM files WHERE filename=? AND app_id=?", (filename,app_id), one=True)[0] - def insertFile(self, file: list[dict], app_id:Union[str,int], prof_id:Union[str,int]): - """Instert a list of files into the database - - Args: - file (list[dict]): a list containing all the files to be inserted - Structured: [{"name": "filename", "path": "path", "type": "filetype"}] - app_id (int): the id of the apparat - prof_id (str): the id of the professor - """ - for f in file: - filename = f["name"] - path = f["path"] - filetyp = f["type"] - if path == "Database": - continue - blob = create_blob(path) - query = "INSERT OR IGNORE INTO files (filename, fileblob, app_id, filetyp,prof_id) VALUES (?, ?, ?, ?,?)" - self.query_db(query, (filename, blob, app_id, filetyp,prof_id)) - def recreateFile(self, filename:str, app_id:Union[str,int],filetype:str)->str: - """Recreate a file from the database - - Args: - filename (str): the name of the file - app_id (Union[str,int]): the id of the apparat - filetype (str): the extension of the file to be created - - Returns: - str: The filename of the recreated file - """ - blob = self.getBlob(filename, app_id) - tempdir = config.database.tempdir - tempdir = tempdir.replace("~", str(Path.home())) - tempdir_path = Path(tempdir) - if not os.path.exists(tempdir_path): - os.mkdir(tempdir_path) - file = tempfile.NamedTemporaryFile( - delete=False, dir=tempdir_path, mode="wb", suffix=f".{filetype}" - ) - file.write(blob) - print("file created") - return file.name - def getFiles(self, app_id:Union[str,int], prof_id:int)->list[tuple]: - """Get all the files associated with the apparat and the professor - - Args: - app_id (Union[str,int]): The id of the apparat - prof_id (Union[str,int]): the id of the professor - - Returns: - list[tuple]: a list of tuples containing the filename and the filetype for the corresponding apparat and professor - """ - return self.query_db("SELECT filename, filetyp FROM files WHERE app_id=? AND prof_id=?", (app_id,prof_id)) - - def getSemersters(self)->list[str]: - """Return all the unique semesters in the database - - Returns: - list: a list of strings containing the semesters - """ - data = self.query_db("SELECT DISTINCT erstellsemester FROM semesterapparat") - return [i[0] for i in data] - - def getSubjects(self): - """Get all the subjects in the database - - Returns: - list[tuple]: a list of tuples containing the subjects - """ - return self.query_db("SELECT * FROM subjects") - - # Messages - def addMessage(self, message:dict,user:str, app_id:Union[str,int]): - """add a Message to the database - - Args: - message (dict): the message to be added - user (str): the user who added the message - app_id (Union[str,int]): the id of the apparat - """ - def __getUserId(user): - return self.query_db("SELECT id FROM user WHERE username=?", (user,), one=True)[0] - user_id = __getUserId(user) - self.query_db("INSERT INTO messages (message, user_id, remind_at,appnr) VALUES (?,?,?,?)", (message["message"],user_id,message["remind_at"],app_id)) - def getMessages(self, date:str)->list[dict[str, str, str, str]]: - """Get all the messages for a specific date - - Args: - date (str): a date.datetime object formatted as a string in the format "YYYY-MM-DD" - - Returns: - list[dict[str, str, str, str]]: a list of dictionaries containing the message, the user who added the message, the apparat id and the id of the message - """ - def __get_user_name(user_id): - return self.query_db("SELECT username FROM user WHERE id=?", (user_id,), one=True)[0] - messages = self.query_db("SELECT * FROM messages WHERE remind_at=?", (date,)) - ret = [ - { - "message": i[2], - "user": __get_user_name(i[4]), - "appnr": i[5], - "id": i[0] - } - for i in messages - ] - return ret - def deleteMessage(self, message_id): - """Delete a message from the database - - Args: - message_id (str): the id of the message - """ - self.query_db("DELETE FROM messages WHERE id=?", (message_id,)) - - # Prof data - def getProfNameById(self, prof_id:Union[str,int],add_title:bool=False)->str: - """Get a professor name based on the id - - Args: - prof_id (Union[str,int]): The id of the professor - add_title (bool, optional): wether to add the title or no. Defaults to False. - - Returns: - str: The name of the professor - """ - prof = self.query_db("SELECT fullname FROM prof WHERE id=?", (prof_id,), one=True) - if add_title: - return f"{self.getTitleById(prof_id)}{prof[0]}" - else: - return prof[0] - def getTitleById(self, prof_id:Union[str,int])->str: - """get the title of a professor based on the id - - Args: - prof_id (Union[str,int]): the id of the professor - - Returns: - str: the title of the professor, with an added whitespace at the end, if no title is present, an empty string is returned - """ - title = self.query_db("SELECT titel FROM prof WHERE id=?", (prof_id,), one=True)[0] - return f"{title} " if title is not None else "" - def getProfByName(self, prof_name:str)->tuple: - """get all the data of a professor based on the name - - Args: - prof_name (str): the name of the professor - - Returns: - tuple: the data of the professor - """ - return self.query_db("SELECT * FROM prof WHERE fullname=?", (prof_name,), one=True) - def getProfId(self, prof_name:str)->Optional[int]: - """Get the id of a professor based on the name - - Args: - prof_name (str): the name of the professor - - Returns: - Optional[int]: the id of the professor, if the professor is not found, None is returned - """ - - data = self.getProfByName(prof_name.replace(",", "")) - if data is None: - return None - else: - return data[0] - def getSpecificProfData(self, prof_id:Union[str,int], fields:List[str])->tuple: - """A customisable function to get specific data of a professor based on the id - - Args: - prof_id (Union[str,int]): the id of the professor - fields (List[str]): a list of fields to be returned - - Returns: - tuple: a tuple containing the requested data - """ - query = "SELECT " - for field in fields: - query += f"{field}," - query = query[:-1] - query += " FROM prof WHERE id=?" - return self.query_db(query, (prof_id,), one=True)[0] - def getProfData(self, profname:str): - """Get mail, telephone number and title of a professor based on the name - - Args: - profname (str): name of the professor - - Returns: - tuple: the mail, telephone number and title of the professor - """ - data = self.query_db("SELECT mail, telnr, titel FROM prof WHERE fullname=?", (profname.replace(",",""),), one=True) - return data - def createProf(self, prof_details:dict): - """Create a professor in the database - - Args: - prof_details (dict): a dictionary containing the details of the professor - """ - prof_title = prof_details["prof_title"] - prof_fname = prof_details["profname"].split(",")[1] - prof_fname = prof_fname.strip() - prof_lname = prof_details["profname"].split(",")[0] - prof_lname = prof_lname.strip() - prof_fullname = prof_details["profname"].replace(",", "") - prof_mail = prof_details["prof_mail"] - prof_tel = prof_details["prof_tel"] - params = (prof_title, prof_fname, prof_lname, prof_mail, prof_tel, prof_fullname) - query = "INSERT OR IGNORE INTO prof (titel, fname, lname, mail, telnr, fullname) VALUES (?, ?, ?, ?, ?, ?)" - self.insertInto(query=query, params=params) - def getProfs(self)->list[tuple]: - """Return all the professors in the database - - Returns: - list[tuple]: a list containing all the professors in individual tuples - """ - return self.query_db("SELECT * FROM prof") - - # Apparat - def getAllAparats(self,deleted=0)->list[tuple]: - """Get all the apparats in the database - - Args: - deleted (int, optional): Switch the result to use . Defaults to 0. - - Returns: - list[tuple]: a list of tuples containing the apparats - """ - return self.query_db("SELECT * FROM semesterapparat WHERE deletion_status=?", (deleted,)) - def getApparatData(self, appnr, appname)->ApparatData: - """Get the Apparat data based on the apparat number and the name - - Args: - appnr (str): the apparat number - appname (str): the name of the apparat - - Raises: - NoResultError: an error is raised if no result is found - - Returns: - ApparatData: the appended data of the apparat wrapped in an ApparatData object - """ - result = self.query_db("SELECT * FROM semesterapparat WHERE appnr=? AND name=?", (appnr,appname), one=True) - if result is None: - raise NoResultError("No result found") - apparat = ApparatData() - apparat.appname = result[1] - apparat.appnr = result[4] - apparat.dauerapp = True if result[7] == 1 else False - prof_data = self.getProfData(self.getProfNameById(result[2])) - apparat.profname = self.getProfNameById(result[2]) - apparat.prof_mail = prof_data[0] - apparat.prof_tel = prof_data[1] - apparat.prof_title = prof_data[2] - apparat.app_fach = result[3] - apparat.erstellsemester = result[5] - apparat.semester = result[8] - apparat.deleted = result[9] - apparat.apparat_adis_id = result[11] - apparat.prof_adis_id = result[12] - return apparat - def getUnavailableApparatNumbers(self)->List[int]: - """Get a list of all the apparat numbers in the database that are currently in use - - Returns: - List[int]: the list of used apparat numbers - """ - numbers = self.query_db("SELECT appnr FROM semesterapparat WHERE deletion_status=0") - numbers = [i[0] for i in numbers] - logger.log_info(f"Currently used apparat numbers: {numbers}") - return numbers - def setNewSemesterDate(self, app_id:Union[str,int], newDate, dauerapp=False): - """Set the new semester date for an apparat - - Args: - app_id (Union[str,int]): the id of the apparat - newDate (str): the new date - dauerapp (bool, optional): if the apparat was changed to dauerapparat. Defaults to False. - """ - date = datetime.datetime.strptime(newDate, "%d.%m.%Y").strftime("%Y-%m-%d") - if dauerapp: - self.query_db("UPDATE semesterapparat SET verlängerung_bis=?, dauerapp=? WHERE appnr=?", (date,dauerapp,app_id)) - else: - self.query_db("UPDATE semesterapparat SET endsemester=? WHERE appnr=?", (date,app_id)) - def getApparatId(self, apparat_name)->Optional[int]: - """get the id of an apparat based on the name - - Args: - apparat_name (str): the name of the apparat e.g. "Semesterapparat 1" - - Returns: - Optional[int]: the id of the apparat, if the apparat is not found, None is returned - """ - data = self.query_db("SELECT appnr FROM semesterapparat WHERE name=?", (apparat_name,), one=True) - if data is None: - return None - else: - return data[0] - def createApparat(self, apparat:ApparatData)->int: - """create the apparat in the database - - Args: - apparat (ApparatData): the wrapped metadata of the apparat - - Raises: - AppPresentError: an error describing that the apparats chosen id is already present in the database - - Returns: - Optional[int]: the id of the apparat - """ - - prof_id = self.getProfId(apparat.profname) - app_id = self.getApparatId(apparat.appname) - if app_id: - raise AppPresentError(app_id) - - self.createProf(apparat.get_prof_details()) - prof_id = self.getProfId(apparat.profname) - #ic(prof_id) - query = f"INSERT OR IGNORE INTO semesterapparat (appnr, name, erstellsemester, dauer, prof_id, fach,deletion_status,konto) VALUES ('{apparat.appnr}', '{apparat.appname}', '{apparat.semester}', '{apparat.dauerapp}', {prof_id}, '{apparat.app_fach}', '{0}', '{SEMAP_MEDIA_ACCOUNTS[apparat.appnr]}')" - logger.log_info(query) - self.query_db(query) - return self.getApparatId(apparat.appname) - def getApparatsByProf(self, prof_id:Union[str,int])->list[tuple]: - """Get all apparats based on the professor id - - Args: - prof_id (Union[str,int]): the id of the professor - - Returns: - list[tuple]: a list of tuples containing the apparats - """ - return self.query_db("SELECT * FROM semesterapparat WHERE prof_id=?", (prof_id,)) - def getApparatsBySemester(self, semester:str)->dict[list]: - """get all apparats based on the semester - - Args: - semester (str): the selected semester - - Returns: - dict[list]: a list off all created and deleted apparats for the selected semester - """ - data = self.query_db("SELECT name, prof_id FROM semesterapparat WHERE erstellsemester=?", (semester,)) - conn = self.connect() - cursor = conn.cursor() - c_tmp = [] - for i in data: - c_tmp.append((i[0], self.getProfNameById(i[1]))) - query = ( - f"SELECT name,prof_id FROM semesterapparat WHERE deleted_date='{semester}'" - ) - result = cursor.execute(query).fetchall() - d_tmp = [] - for i in result: - d_tmp.append((i[0], self.getProfNameById(i[1]))) - # group the apparats by prof - c_ret = {} - for i in c_tmp: - if i[1] not in c_ret.keys(): - c_ret[i[1]] = [i[0]] - else: - c_ret[i[1]].append(i[0]) - d_ret = {} - for i in d_tmp: - if i[1] not in d_ret.keys(): - d_ret[i[1]] = [i[0]] - else: - d_ret[i[1]].append(i[0]) - self.close_connection(conn) - return {"created": c_ret, "deleted": d_ret} - def getApparatCountBySemester(self)->tuple[list[str],list[int]]: - """get a list of all apparats created and deleted by semester - - Returns: - tuple[list[str],list[int]]: a tuple containing two lists, the first list contains the semesters, the second list contains the amount of apparats created and deleted for the corresponding semester - """ - conn = self.connect() - cursor = conn.cursor() - semesters = self.getSemersters() - created = [] - deleted = [] - for semester in semesters: - query = f"SELECT COUNT(*) FROM semesterapparat WHERE erstellsemester='{semester}'" - result = cursor.execute(query).fetchone() - created.append(result[0]) - query = f"SELECT COUNT(*) FROM semesterapparat WHERE deletion_status=1 AND deleted_date='{semester}'" - result = cursor.execute(query).fetchone() - deleted.append(result[0]) - # store data in a tuple - ret = [] - e_tuple = () - for sem in semesters: - e_tuple = ( - sem, - created[semesters.index(sem)], - deleted[semesters.index(sem)], - ) - ret.append(e_tuple) - self.close_connection(conn) - return ret - def deleteApparat(self, app_id:Union[str,int], semester:str): - """Delete an apparat from the database - - Args: - app_id (Union[str, int]): the id of the apparat - semester (str): the semester the apparat should be deleted from - """ - self.query_db("UPDATE semesterapparat SET deletion_status=1, deleted_date=? WHERE appnr=?", (semester,app_id)) - def isEternal(self, id): - """check if the apparat is eternal (dauerapparat) - - Args: - id (int): the id of the apparat to be checked - - Returns: - int: the state of the apparat - """ - return self.query_db("SELECT dauer FROM semesterapparat WHERE appnr=?", (id,), one=True) - def getApparatName(self, app_id:Union[str,int], prof_id:Union[str,int]): - """get the name of the apparat based on the id - - Args: - app_id (Union[str,int]): the id of the apparat - prof_id (Union[str,int]): the id of the professor - - Returns: - str: the name of the apparat - """ - return self.query_db("SELECT name FROM semesterapparat WHERE appnr=? AND prof_id=?", (app_id,prof_id), one=True)[0] - def updateApparat(self, apparat_data:ApparatData): - """Update an apparat in the database - - Args: - apparat_data (ApparatData): the new metadata of the apparat - """ - query = f"UPDATE semesterapparat SET name = ?, fach = ?, dauer = ?, prof_id = ? WHERE appnr = ?" - params = ( - apparat_data.appname, - apparat_data.app_fach, - apparat_data.dauerapp, - self.getProfId(apparat_data.profname), - apparat_data.appnr, - ) - self.query_db(query, params) - def checkApparatExists(self, apparat_name:str): - """check if the apparat is already present in the database based on the name - - Args: - apparat_name (str): the name of the apparat - - Returns: - bool: True if the apparat is present, False if not - """ - return True if self.query_db("SELECT appnr FROM semesterapparat WHERE name=?", (apparat_name,), one=True) else False - def checkApparatExistsById(self, app_id:Union[str,int])->bool: - """a check to see if the apparat is already present in the database, based on the id - - Args: - app_id (Union[str, int]): the id of the apparat - - Returns: - bool: True if the apparat is present, False if not - """ - return True if self.query_db("SELECT appnr FROM semesterapparat WHERE appnr=?", (app_id,), one=True) else False - # Statistics - def statistic_request(self, **kwargs: Any): - """Take n amount of kwargs and return the result of the query - """ - def __query(query): - """execute the query and return the result - - Args: - query (str): the constructed query - - Returns: - list: the result of the query - """ - conn = self.connect() - cursor = conn.cursor() - result = cursor.execute(query).fetchall() - for result_a in result: - orig_value = result_a - prof_name = self.getProfNameById(result_a[2]) - # replace the prof_id with the prof_name - result_a = list(result_a) - result_a[2] = prof_name - result_a = tuple(result_a) - result[result.index(orig_value)] = result_a - self.close_connection(conn) - return result - if "deletable" in kwargs.keys(): - query = f"SELECT * FROM semesterapparat WHERE deletion_status=0 AND dauer=0 AND (erstellsemester!='{kwargs['deletesemester']}' OR verlängerung_bis!='{kwargs['deletesemester']}')" - return __query(query) - if "dauer" in kwargs.keys(): - kwargs["dauer"] = kwargs["dauer"].replace("Ja", "1").replace("Nein", "0") - query = "SELECT * FROM semesterapparat WHERE " - for key, value in kwargs.items() if kwargs.items() is not None else {}: - print(key, value) - query += f"{key}='{value}' AND " - print(query) - # remove deletesemester part from normal query, as this will be added to the database upon deleting the apparat - if "deletesemester" in kwargs.keys(): - query = query.replace( - f"deletesemester='{kwargs['deletesemester']}' AND ", "" - ) - if "endsemester" in kwargs.keys(): - if "erstellsemester" in kwargs.keys(): - query = query.replace(f"endsemester='{kwargs['endsemester']}' AND ", "") - query = query.replace( - f"erstellsemester='{kwargs['erstellsemester']} AND ", "xyz" - ) - else: - query = query.replace( - f"endsemester='{kwargs['endsemester']}' AND ", "xyz" - ) - print("replaced") - query = query.replace( - "xyz", - f"(erstellsemester='{kwargs['endsemester']}' OR verlängerung_bis='{kwargs['endsemester']}') AND ", - ) - # remove all x="" parts from the query where x is a key in kwargs - query = query[:-5] - print(query) - return __query(query) - - # Admin data - def getUser(self): - """Get a single user from the database""" - return self.query_db("SELECT * FROM user", one=True) - def getUsers(self)->list[tuple]: - """Return a list of tuples of all the users in the database""" - return self.query_db("SELECT * FROM user") - - def login(self, user, hashed_password): - """try to login the user. - The salt for the user will be requested from the database and then added to the hashed password. The password will then be compared to the password in the database - - Args: - user (str): username that tries to login - hashed_password (str): the password the user tries to login with - - Returns: - bool: True if the login was successful, False if not - """ - salt = self.query_db("SELECT salt FROM user WHERE username=?", (user,), one=True)[0] - if salt is None: - return False - hashed_password = salt + hashed_password - password = self.query_db("SELECT password FROM user WHERE username=?", (user,), one=True)[0] - if password == hashed_password: - return True - else: - return False - def changePassword(self, user, new_password): - """change the password of a user. - The password will be added with the salt and then committed to the database - - Args: - user (str): username - new_password (str): the hashed password - """ - salt = self.query_db("SELECT salt FROM user WHERE username=?", (user,), one=True)[0] - new_password = salt + new_password - self.query_db("UPDATE user SET password=? WHERE username=?", (new_password,user)) - def getRole(self, user): - """get the role of the user - - Args: - user (str): username - - Returns: - str: the name of the role - """ - return self.query_db("SELECT role FROM user WHERE username=?", (user,), one=True)[0] - def getRoles(self)->list[tuple]: - """get all the roles in the database - - Returns: - list[str]: a list of all the roles - """ - return self.query_db("SELECT role FROM user") - def checkUsername(self, user)->bool: - """a check to see if the username is already present in the database - - Args: - user (str): the username - - Returns: - bool: True if the username is present, False if not - """ - data = self.query_db("SELECT username FROM user WHERE username=?", (user,), one=True) - return True if data is not None else False - def createUser(self, user, password, role, salt): - """create an user from the AdminCommands class. - - Args: - user (str): the username of the user - password (str): a hashed password - role (str): the role of the user - salt (str): a salt for the password - """ - self.query_db("INSERT OR IGNORE INTO user (username, password, role, salt) VALUES (?,?,?,?)", (user,password,role,salt)) - def deleteUser(self, user): - """delete an unser - - Args: - user (str): username of the user - """ - self.query_db("DELETE FROM user WHERE username=?", (user,)) - def updateUser(self, username, data:dict[str, str]): - """changge the data of a user - - Args: - username (str): the username of the user - data (dict[str, str]): the data to be changed - """ - conn = self.connect() - cursor = conn.cursor() - query = "UPDATE user SET " - for key,value in data.items(): - if key == "username": - continue - query += f"{key}='{value}'," - query = query[:-1] - query += " WHERE username=?" - params = (username,) - cursor.execute(query, params) - conn.commit() - self.close_connection(conn) - def getFacultyMember(self, name:str)->tuple: - """get a faculty member based on the name - - Args: - name (str): the name to be searched for - - Returns: - tuple: a tuple containing the data of the faculty member - """ - return self.query_db("SELECT titel, fname,lname,mail,telnr,fullname FROM prof WHERE fullname=?", (name,), one=True) - def updateFacultyMember(self, data:dict, oldlname:str, oldfname:str): - """update the data of a faculty member - - Args: - data (dict): a dictionary containing the data to be updated - oldlname (str): the old last name of the faculty member - oldfname (str): the old first name of the faculty member - """ - placeholders = ", ".join([f"{i}=:{i} " for i in data.keys()]) - query = f"UPDATE prof SET {placeholders} WHERE lname = :oldlname AND fname = :oldfname" - data["oldlname"] = oldlname - data["oldfname"] = oldfname - self.query_db(query, data) - def getFacultyMembers(self): - """get a list of all faculty members - - Returns: - list[tuple]: a list of tuples containing the faculty members - """ - return self.query_db("SELECT titel, fname,lname,mail,telnr,fullname FROM prof")Methods
--
-
-def addBookToDatabase(self, bookdata: src.logic.dataclass.BookData, app_id: Union[str, int], prof_id: Union[str, int]) -
--
--
Add books to the database. Both app_id and prof_id are required to add the book to the database, as the app_id and prof_id are used to select the books later on.
-Args
--
-
bookdata:BookData
-- The metadata of the book to be added -
app_id:str
-- The apparat id where the book should be added to -
prof_id:str
-- The id of the professor where the book should be added to. -
---Expand source code -
-
-def addBookToDatabase(self, bookdata:BookData,app_id:Union[str,int], prof_id:Union[str,int]): - """ - Add books to the database. Both app_id and prof_id are required to add the book to the database, as the app_id and prof_id are used to select the books later on. - - Args: - bookdata (BookData): The metadata of the book to be added - app_id (str): The apparat id where the book should be added to - prof_id (str): The id of the professor where the book should be added to. - """ - conn = self.connect() - cursor = conn.cursor() - t_query = ( - f"SELECT bookdata FROM media WHERE app_id={app_id} AND prof_id={prof_id}" - ) - # print(t_query) - result = cursor.execute(t_query).fetchall() - result = [load_pickle(i[0]) for i in result] - if bookdata in result: - print("Bookdata already in database") - # check if the book was deleted in the apparat - query = ( - "SELECT deleted FROM media WHERE app_id=? AND prof_id=? AND bookdata=?" - ) - params = (app_id, prof_id, dump_pickle(bookdata)) - result = cursor.execute(query, params).fetchone() - if result[0] == 1: - print("Book was deleted, updating bookdata") - query = "UPDATE media SET deleted=0 WHERE app_id=? AND prof_id=? AND bookdata=?" - params = (app_id, prof_id, dump_pickle(bookdata)) - cursor.execute(query, params) - conn.commit() - return - - query = ( - "INSERT INTO media (bookdata, app_id, prof_id,deleted) VALUES (?, ?, ?,?)" - ) - converted = dump_pickle(bookdata) - params = (converted, app_id, prof_id, 0) - cursor.execute(query, params) - conn.commit() - self.close_connection(conn)
- -def addMessage(self, message: dict, user: str, app_id: Union[str, int]) -
--
--
add a Message to the database
-Args
--
-
message:dict
-- the message to be added -
user:str
-- the user who added the message -
app_id:Union[str,int]
-- the id of the apparat -
---Expand source code -
-
-def addMessage(self, message:dict,user:str, app_id:Union[str,int]): - """add a Message to the database - - Args: - message (dict): the message to be added - user (str): the user who added the message - app_id (Union[str,int]): the id of the apparat - """ - def __getUserId(user): - return self.query_db("SELECT id FROM user WHERE username=?", (user,), one=True)[0] - user_id = __getUserId(user) - self.query_db("INSERT INTO messages (message, user_id, remind_at,appnr) VALUES (?,?,?,?)", (message["message"],user_id,message["remind_at"],app_id))
- -def changePassword(self, user, new_password) -
--
--
change the password of a user. -The password will be added with the salt and then committed to the database
-Args
--
-
user:str
-- username -
new_password:str
-- the hashed password -
---Expand source code -
-
-def changePassword(self, user, new_password): - """change the password of a user. - The password will be added with the salt and then committed to the database - - Args: - user (str): username - new_password (str): the hashed password - """ - salt = self.query_db("SELECT salt FROM user WHERE username=?", (user,), one=True)[0] - new_password = salt + new_password - self.query_db("UPDATE user SET password=? WHERE username=?", (new_password,user))
- -def checkApparatExists(self, apparat_name: str) -
--
--
check if the apparat is already present in the database based on the name
-Args
--
-
apparat_name:str
-- the name of the apparat -
Returns
--
-
bool
-- True if the apparat is present, False if not -
---Expand source code -
-
-def checkApparatExists(self, apparat_name:str): - """check if the apparat is already present in the database based on the name - - Args: - apparat_name (str): the name of the apparat - - Returns: - bool: True if the apparat is present, False if not - """ - return True if self.query_db("SELECT appnr FROM semesterapparat WHERE name=?", (apparat_name,), one=True) else False
- -def checkApparatExistsById(self, app_id: Union[str, int]) ‑> bool -
--
--
a check to see if the apparat is already present in the database, based on the id
-Args
--
-
app_id:Union[str, int]
-- the id of the apparat -
Returns
--
-
bool
-- True if the apparat is present, False if not -
---Expand source code -
-
-def checkApparatExistsById(self, app_id:Union[str,int])->bool: - """a check to see if the apparat is already present in the database, based on the id - - Args: - app_id (Union[str, int]): the id of the apparat - - Returns: - bool: True if the apparat is present, False if not - """ - return True if self.query_db("SELECT appnr FROM semesterapparat WHERE appnr=?", (app_id,), one=True) else False
- -def checkUsername(self, user) ‑> bool -
--
--
a check to see if the username is already present in the database
-Args
--
-
user:str
-- the username -
Returns
--
-
bool
-- True if the username is present, False if not -
---Expand source code -
-
-def checkUsername(self, user)->bool: - """a check to see if the username is already present in the database - - Args: - user (str): the username - - Returns: - bool: True if the username is present, False if not - """ - data = self.query_db("SELECT username FROM user WHERE username=?", (user,), one=True) - return True if data is not None else False
- -def close_connection(self, conn: sqlite3.Connection) -
--
--
closes the connection to the database
-Args:
-- conn (sql.Connection): the connection to be closed ----Expand source code -
-
-def close_connection(self, conn: sql.Connection): - """ - closes the connection to the database - - Args: - ---- - - conn (sql.Connection): the connection to be closed - """ - conn.close()
- -def connect(self) ‑> sqlite3.Connection -
--
--
Connect to the database
-Returns
--
-
sql.Connection
-- The active connection to the database -
---Expand source code -
-
-def connect(self)->sql.Connection: - """ - Connect to the database - - Returns: - sql.Connection: The active connection to the database - """ - return sql.connect(self.db_path)
- -def createApparat(self, apparat: src.logic.dataclass.ApparatData) ‑> int -
--
--
create the apparat in the database
-Args
--
-
apparat:ApparatData
-- the wrapped metadata of the apparat -
Raises
--
-
AppPresentError
-- an error describing that the apparats chosen id is already present in the database -
Returns
--
-
Optional[int]
-- the id of the apparat -
---Expand source code -
-
-def createApparat(self, apparat:ApparatData)->int: - """create the apparat in the database - - Args: - apparat (ApparatData): the wrapped metadata of the apparat - - Raises: - AppPresentError: an error describing that the apparats chosen id is already present in the database - - Returns: - Optional[int]: the id of the apparat - """ - - prof_id = self.getProfId(apparat.profname) - app_id = self.getApparatId(apparat.appname) - if app_id: - raise AppPresentError(app_id) - - self.createProf(apparat.get_prof_details()) - prof_id = self.getProfId(apparat.profname) - #ic(prof_id) - query = f"INSERT OR IGNORE INTO semesterapparat (appnr, name, erstellsemester, dauer, prof_id, fach,deletion_status,konto) VALUES ('{apparat.appnr}', '{apparat.appname}', '{apparat.semester}', '{apparat.dauerapp}', {prof_id}, '{apparat.app_fach}', '{0}', '{SEMAP_MEDIA_ACCOUNTS[apparat.appnr]}')" - logger.log_info(query) - self.query_db(query) - return self.getApparatId(apparat.appname)
- -def createProf(self, prof_details: dict) -
--
--
Create a professor in the database
-Args
--
-
prof_details:dict
-- a dictionary containing the details of the professor -
---Expand source code -
-
-def createProf(self, prof_details:dict): - """Create a professor in the database - - Args: - prof_details (dict): a dictionary containing the details of the professor - """ - prof_title = prof_details["prof_title"] - prof_fname = prof_details["profname"].split(",")[1] - prof_fname = prof_fname.strip() - prof_lname = prof_details["profname"].split(",")[0] - prof_lname = prof_lname.strip() - prof_fullname = prof_details["profname"].replace(",", "") - prof_mail = prof_details["prof_mail"] - prof_tel = prof_details["prof_tel"] - params = (prof_title, prof_fname, prof_lname, prof_mail, prof_tel, prof_fullname) - query = "INSERT OR IGNORE INTO prof (titel, fname, lname, mail, telnr, fullname) VALUES (?, ?, ?, ?, ?, ?)" - self.insertInto(query=query, params=params)
- -def createUser(self, user, password, role, salt) -
--
--
create an user from the AdminCommands class.
-Args
--
-
user:str
-- the username of the user -
password:str
-- a hashed password -
role:str
-- the role of the user -
salt:str
-- a salt for the password -
---Expand source code -
-
-def createUser(self, user, password, role, salt): - """create an user from the AdminCommands class. - - Args: - user (str): the username of the user - password (str): a hashed password - role (str): the role of the user - salt (str): a salt for the password - """ - self.query_db("INSERT OR IGNORE INTO user (username, password, role, salt) VALUES (?,?,?,?)", (user,password,role,salt))
- -def create_tables(self) -
--
--
Create the tables in the database
---Expand source code -
-
-def create_tables(self): - """ - Create the tables in the database - """ - conn = self.connect() - cursor = conn.cursor() - cursor.execute(CREATE_TABLE_APPARAT) - cursor.execute(CREATE_TABLE_MESSAGES) - cursor.execute(CREATE_TABLE_MEDIA) - cursor.execute(CREATE_TABLE_APPKONTOS) - cursor.execute(CREATE_TABLE_FILES) - cursor.execute(CREATE_TABLE_PROF) - cursor.execute(CREATE_TABLE_USER) - cursor.execute(CREATE_TABLE_SUBJECTS) - conn.commit() - self.close_connection(conn)
- -def deleteApparat(self, app_id: Union[str, int], semester: str) -
--
--
Delete an apparat from the database
-Args
--
-
app_id:Union[str, int]
-- the id of the apparat -
semester:str
-- the semester the apparat should be deleted from -
---Expand source code -
-
-def deleteApparat(self, app_id:Union[str,int], semester:str): - """Delete an apparat from the database - - Args: - app_id (Union[str, int]): the id of the apparat - semester (str): the semester the apparat should be deleted from - """ - self.query_db("UPDATE semesterapparat SET deletion_status=1, deleted_date=? WHERE appnr=?", (semester,app_id))
- -def deleteBook(self, book_id) -
--
--
Delete a book from the database
-Args
--
-
book_id:str
-- ID of the book -
---Expand source code -
-
-def deleteBook(self, book_id): - """ - Delete a book from the database - - Args: - book_id (str): ID of the book - """ - self.query_db("UPDATE media SET deleted=1 WHERE id=?", (book_id,))
- -def deleteMessage(self, message_id) -
--
--
Delete a message from the database
-Args
--
-
message_id:str
-- the id of the message -
---Expand source code -
-
-def deleteMessage(self, message_id): - """Delete a message from the database - - Args: - message_id (str): the id of the message - """ - self.query_db("DELETE FROM messages WHERE id=?", (message_id,))
- -def deleteUser(self, user) -
--
--
delete an unser
-Args
--
-
user:str
-- username of the user -
---Expand source code -
-
-def deleteUser(self, user): - """delete an unser - - Args: - user (str): username of the user - """ - self.query_db("DELETE FROM user WHERE username=?", (user,))
- -def getAllAparats(self, deleted=0) ‑> list[tuple] -
--
--
Get all the apparats in the database
-Args
--
-
deleted:int, optional
-- Switch the result to use . Defaults to 0. -
Returns
--
-
list[tuple]
-- a list of tuples containing the apparats -
---Expand source code -
-
-def getAllAparats(self,deleted=0)->list[tuple]: - """Get all the apparats in the database - - Args: - deleted (int, optional): Switch the result to use . Defaults to 0. - - Returns: - list[tuple]: a list of tuples containing the apparats - """ - return self.query_db("SELECT * FROM semesterapparat WHERE deletion_status=?", (deleted,))
- -def getApparatCountBySemester(self) ‑> tuple[list[str], list[int]] -
--
--
get a list of all apparats created and deleted by semester
-Returns
--
-
tuple[list[str],list[int]]
-- a tuple containing two lists, the first list contains the semesters, the second list contains the amount of apparats created and deleted for the corresponding semester -
---Expand source code -
-
-def getApparatCountBySemester(self)->tuple[list[str],list[int]]: - """get a list of all apparats created and deleted by semester - - Returns: - tuple[list[str],list[int]]: a tuple containing two lists, the first list contains the semesters, the second list contains the amount of apparats created and deleted for the corresponding semester - """ - conn = self.connect() - cursor = conn.cursor() - semesters = self.getSemersters() - created = [] - deleted = [] - for semester in semesters: - query = f"SELECT COUNT(*) FROM semesterapparat WHERE erstellsemester='{semester}'" - result = cursor.execute(query).fetchone() - created.append(result[0]) - query = f"SELECT COUNT(*) FROM semesterapparat WHERE deletion_status=1 AND deleted_date='{semester}'" - result = cursor.execute(query).fetchone() - deleted.append(result[0]) - # store data in a tuple - ret = [] - e_tuple = () - for sem in semesters: - e_tuple = ( - sem, - created[semesters.index(sem)], - deleted[semesters.index(sem)], - ) - ret.append(e_tuple) - self.close_connection(conn) - return ret
- -def getApparatData(self, appnr, appname) ‑> src.logic.dataclass.ApparatData -
--
--
Get the Apparat data based on the apparat number and the name
-Args
--
-
appnr:str
-- the apparat number -
appname:str
-- the name of the apparat -
Raises
--
-
NoResultError
-- an error is raised if no result is found -
Returns
--
-
ApparatData
-- the appended data of the apparat wrapped in an ApparatData object -
---Expand source code -
-
-def getApparatData(self, appnr, appname)->ApparatData: - """Get the Apparat data based on the apparat number and the name - - Args: - appnr (str): the apparat number - appname (str): the name of the apparat - - Raises: - NoResultError: an error is raised if no result is found - - Returns: - ApparatData: the appended data of the apparat wrapped in an ApparatData object - """ - result = self.query_db("SELECT * FROM semesterapparat WHERE appnr=? AND name=?", (appnr,appname), one=True) - if result is None: - raise NoResultError("No result found") - apparat = ApparatData() - apparat.appname = result[1] - apparat.appnr = result[4] - apparat.dauerapp = True if result[7] == 1 else False - prof_data = self.getProfData(self.getProfNameById(result[2])) - apparat.profname = self.getProfNameById(result[2]) - apparat.prof_mail = prof_data[0] - apparat.prof_tel = prof_data[1] - apparat.prof_title = prof_data[2] - apparat.app_fach = result[3] - apparat.erstellsemester = result[5] - apparat.semester = result[8] - apparat.deleted = result[9] - apparat.apparat_adis_id = result[11] - apparat.prof_adis_id = result[12] - return apparat
- -def getApparatId(self, apparat_name) ‑> Optional[int] -
--
--
get the id of an apparat based on the name
-Args
--
-
apparat_name:str
-- the name of the apparat e.g. "Semesterapparat 1" -
Returns
--
-
Optional[int]
-- the id of the apparat, if the apparat is not found, None is returned -
---Expand source code -
-
-def getApparatId(self, apparat_name)->Optional[int]: - """get the id of an apparat based on the name - - Args: - apparat_name (str): the name of the apparat e.g. "Semesterapparat 1" - - Returns: - Optional[int]: the id of the apparat, if the apparat is not found, None is returned - """ - data = self.query_db("SELECT appnr FROM semesterapparat WHERE name=?", (apparat_name,), one=True) - if data is None: - return None - else: - return data[0]
- -def getApparatName(self, app_id: Union[str, int], prof_id: Union[str, int]) -
--
--
get the name of the apparat based on the id
-Args
--
-
app_id:Union[str,int]
-- the id of the apparat -
prof_id:Union[str,int]
-- the id of the professor -
Returns
--
-
str
-- the name of the apparat -
---Expand source code -
-
-def getApparatName(self, app_id:Union[str,int], prof_id:Union[str,int]): - """get the name of the apparat based on the id - - Args: - app_id (Union[str,int]): the id of the apparat - prof_id (Union[str,int]): the id of the professor - - Returns: - str: the name of the apparat - """ - return self.query_db("SELECT name FROM semesterapparat WHERE appnr=? AND prof_id=?", (app_id,prof_id), one=True)[0]
- -def getApparatsByProf(self, prof_id: Union[str, int]) ‑> list[tuple] -
--
--
Get all apparats based on the professor id
-Args
--
-
prof_id:Union[str,int]
-- the id of the professor -
Returns
--
-
list[tuple]
-- a list of tuples containing the apparats -
---Expand source code -
-
-def getApparatsByProf(self, prof_id:Union[str,int])->list[tuple]: - """Get all apparats based on the professor id - - Args: - prof_id (Union[str,int]): the id of the professor - - Returns: - list[tuple]: a list of tuples containing the apparats - """ - return self.query_db("SELECT * FROM semesterapparat WHERE prof_id=?", (prof_id,))
- -def getApparatsBySemester(self, semester: str) ‑> dict[list] -
--
--
get all apparats based on the semester
-Args
--
-
semester:str
-- the selected semester -
Returns
--
-
dict[list]
-- a list off all created and deleted apparats for the selected semester -
---Expand source code -
-
-def getApparatsBySemester(self, semester:str)->dict[list]: - """get all apparats based on the semester - - Args: - semester (str): the selected semester - - Returns: - dict[list]: a list off all created and deleted apparats for the selected semester - """ - data = self.query_db("SELECT name, prof_id FROM semesterapparat WHERE erstellsemester=?", (semester,)) - conn = self.connect() - cursor = conn.cursor() - c_tmp = [] - for i in data: - c_tmp.append((i[0], self.getProfNameById(i[1]))) - query = ( - f"SELECT name,prof_id FROM semesterapparat WHERE deleted_date='{semester}'" - ) - result = cursor.execute(query).fetchall() - d_tmp = [] - for i in result: - d_tmp.append((i[0], self.getProfNameById(i[1]))) - # group the apparats by prof - c_ret = {} - for i in c_tmp: - if i[1] not in c_ret.keys(): - c_ret[i[1]] = [i[0]] - else: - c_ret[i[1]].append(i[0]) - d_ret = {} - for i in d_tmp: - if i[1] not in d_ret.keys(): - d_ret[i[1]] = [i[0]] - else: - d_ret[i[1]].append(i[0]) - self.close_connection(conn) - return {"created": c_ret, "deleted": d_ret}
- -def getBlob(self, filename, app_id: Union[str, int]) -
--
--
Get a blob from the database
-Args
--
-
filename:str
-- The name of the file -
app_id:str
-- ID of the apparat -
Returns
--
-
bytes
-- The file stored in -
---Expand source code -
-
-def getBlob(self, filename, app_id:Union[str,int]): - """ - Get a blob from the database - - Args: - filename (str): The name of the file - app_id (str): ID of the apparat - - Returns: - bytes: The file stored in - """ - return self.query_db("SELECT fileblob FROM files WHERE filename=? AND app_id=?", (filename,app_id), one=True)[0]
- -def getBook(self, book_id: int) ‑> src.logic.dataclass.BookData -
--
--
Get the book based on the id in the database
-Args
--
-
book_id:int
-- The id of the book -
Returns
--
-
BookData
-- The metadata of the book wrapped in a BookData object -
---Expand source code -
-
-def getBook(self,book_id:int)->BookData: - """ - Get the book based on the id in the database - - Args: - book_id (int): The id of the book - - Returns: - BookData: The metadata of the book wrapped in a BookData object - """ - return load_pickle(self.query_db("SELECT bookdata FROM media WHERE id=?", (book_id,), one=True)[0])
- -def getBookBasedOnSignature(self, app_id: Union[str, int], prof_id: Union[str, int], signature: str) ‑> src.logic.dataclass.BookData -
--
--
Get the book based on the signature of the book.
-Args
--
-
app_id:str
-- The apparat id the book should be associated with -
prof_id:str
-- The professor id the book should be associated with -
signature:str
-- The signature of the book -
Returns
--
-
BookData
-- The total metadata of the book wrapped in a BookData object -
---Expand source code -
-
-def getBookBasedOnSignature(self, app_id:Union[str,int], prof_id:Union[str,int],signature:str)->BookData: - """ - Get the book based on the signature of the book. - - Args: - app_id (str): The apparat id the book should be associated with - prof_id (str): The professor id the book should be associated with - signature (str): The signature of the book - - Returns: - BookData: The total metadata of the book wrapped in a BookData object - """ - result = self.query_db("SELECT bookdata FROM media WHERE app_id=? AND prof_id=?", (app_id,prof_id)) - books = [load_pickle(i[0]) for i in result] - book = [i for i in books if i.signature == signature][0] - return book
- -def getBookId(self, bookdata: src.logic.dataclass.BookData, app_id: Union[str, int], prof_id: Union[str, int]) ‑> int -
--
--
Get the id of a book based on the metadata of the book
-Args
--
-
bookdata:BookData
-- The wrapped metadata of the book -
app_id:str
-- The apparat id the book should be associated with -
prof_id:str
-- The professor id the book should be associated with -
Returns
--
-
int
-- ID of the book -
---Expand source code -
-
-def getBookId(self, bookdata:BookData, app_id:Union[str,int], prof_id:Union[str,int])->int: - """ - Get the id of a book based on the metadata of the book - - Args: - bookdata (BookData): The wrapped metadata of the book - app_id (str): The apparat id the book should be associated with - prof_id (str): The professor id the book should be associated with - - Returns: - int: ID of the book - """ - result = self.query_db("SELECT id FROM media WHERE bookdata=? AND app_id=? AND prof_id=?", (dump_pickle(bookdata),app_id,prof_id), one=True) - return result[0]
- -def getBookIdBasedOnSignature(self, app_id: Union[str, int], prof_id: Union[str, int], signature: str) ‑> int -
--
--
Get a book id based on the signature of the book.
-Args
--
-
app_id:str
-- The apparat id the book should be associated with -
prof_id:str
-- The professor id the book should be associated with -
signature:str
-- The signature of the book -
Returns
--
-
int
-- The id of the book -
---Expand source code -
-
-def getBookIdBasedOnSignature(self, app_id:Union[str,int], prof_id:Union[str,int],signature:str)->int: - """ - Get a book id based on the signature of the book. - - Args: - app_id (str): The apparat id the book should be associated with - prof_id (str): The professor id the book should be associated with - signature (str): The signature of the book - - Returns: - int: The id of the book - """ - result = self.query_db("SELECT bookdata, id FROM media WHERE app_id=? AND prof_id=?", (app_id,prof_id)) - books = [(load_pickle(i[0]),i[1]) for i in result] - book = [i for i in books if i[0].signature == signature][0][1] - return book
- -def getBooks(self, app_id: Union[str, int], prof_id: Union[str, int], deleted=0) ‑> list[dict[int, src.logic.dataclass.BookData, int]] -
--
--
Get the Books based on the apparat id and the professor id
-Args
--
-
app_id:str
-- The ID of the apparat -
prof_id:str
-- The ID of the professor -
deleted:int, optional
-- The state of the book. Set to 1 to include deleted ones. Defaults to 0. -
Returns
--
-
list[dict[int, BookData, int]]
-- A list of dictionaries containing the id, the metadata of the book and the availability of the book -
---Expand source code -
-
-def getBooks(self, app_id:Union[str,int], prof_id:Union[str,int], deleted=0)->list[dict[int, BookData, int]]: - """ - Get the Books based on the apparat id and the professor id - - Args: - app_id (str): The ID of the apparat - prof_id (str): The ID of the professor - deleted (int, optional): The state of the book. Set to 1 to include deleted ones. Defaults to 0. - - Returns: - list[dict[int, BookData, int]]: A list of dictionaries containing the id, the metadata of the book and the availability of the book - """ - qdata = self.query_db(f"SELECT id,bookdata,available FROM media WHERE (app_id={app_id} AND prof_id={prof_id}) AND (deleted={deleted if deleted == 0 else '1 OR deleted=0'})") - ret_result = [] - for result_a in qdata: - data = {"id": int, "bookdata": BookData, "available": int} - data["id"] = result_a[0] - data["bookdata"] = load_pickle(result_a[1]) - data["available"] = result_a[2] - ret_result.append(data) - return ret_result
- -def getFacultyMember(self, name: str) ‑> tuple -
--
--
get a faculty member based on the name
-Args
--
-
name:str
-- the name to be searched for -
Returns
--
-
tuple
-- a tuple containing the data of the faculty member -
---Expand source code -
-
-def getFacultyMember(self, name:str)->tuple: - """get a faculty member based on the name - - Args: - name (str): the name to be searched for - - Returns: - tuple: a tuple containing the data of the faculty member - """ - return self.query_db("SELECT titel, fname,lname,mail,telnr,fullname FROM prof WHERE fullname=?", (name,), one=True)
- -def getFacultyMembers(self) -
--
--
get a list of all faculty members
-Returns
--
-
list[tuple]
-- a list of tuples containing the faculty members -
---Expand source code -
-
-def getFacultyMembers(self): - """get a list of all faculty members - - Returns: - list[tuple]: a list of tuples containing the faculty members - """ - return self.query_db("SELECT titel, fname,lname,mail,telnr,fullname FROM prof")
- -def getFiles(self, app_id: Union[str, int], prof_id: int) ‑> list[tuple] -
--
--
Get all the files associated with the apparat and the professor
-Args
--
-
app_id:Union[str,int]
-- The id of the apparat -
prof_id:Union[str,int]
-- the id of the professor -
Returns
--
-
list[tuple]
-- a list of tuples containing the filename and the filetype for the corresponding apparat and professor -
---Expand source code -
-
-def getFiles(self, app_id:Union[str,int], prof_id:int)->list[tuple]: - """Get all the files associated with the apparat and the professor - - Args: - app_id (Union[str,int]): The id of the apparat - prof_id (Union[str,int]): the id of the professor - - Returns: - list[tuple]: a list of tuples containing the filename and the filetype for the corresponding apparat and professor - """ - return self.query_db("SELECT filename, filetyp FROM files WHERE app_id=? AND prof_id=?", (app_id,prof_id))
- -def getLastBookId(self) ‑> int -
--
--
Get the last book id in the database
-Returns
--
-
int
-- ID of the last book in the database -
---Expand source code -
-
-def getLastBookId(self)->int: - """ - Get the last book id in the database - - Returns: - int: ID of the last book in the database - """ - return self.query_db("SELECT id FROM media ORDER BY id DESC", one=True)[0]
- -def getMessages(self, date: str) ‑> list[dict[str, str, str, str]] -
--
--
Get all the messages for a specific date
-Args
--
-
date:str
-- a date.datetime object formatted as a string in the format "YYYY-MM-DD" -
Returns
--
-
list[dict[str, str, str, str]]
-- a list of dictionaries containing the message, the user who added the message, the apparat id and the id of the message -
---Expand source code -
-
-def getMessages(self, date:str)->list[dict[str, str, str, str]]: - """Get all the messages for a specific date - - Args: - date (str): a date.datetime object formatted as a string in the format "YYYY-MM-DD" - - Returns: - list[dict[str, str, str, str]]: a list of dictionaries containing the message, the user who added the message, the apparat id and the id of the message - """ - def __get_user_name(user_id): - return self.query_db("SELECT username FROM user WHERE id=?", (user_id,), one=True)[0] - messages = self.query_db("SELECT * FROM messages WHERE remind_at=?", (date,)) - ret = [ - { - "message": i[2], - "user": __get_user_name(i[4]), - "appnr": i[5], - "id": i[0] - } - for i in messages - ] - return ret
- -def getProfByName(self, prof_name: str) ‑> tuple -
--
--
get all the data of a professor based on the name
-Args
--
-
prof_name:str
-- the name of the professor -
Returns
--
-
tuple
-- the data of the professor -
---Expand source code -
-
-def getProfByName(self, prof_name:str)->tuple: - """get all the data of a professor based on the name - - Args: - prof_name (str): the name of the professor - - Returns: - tuple: the data of the professor - """ - return self.query_db("SELECT * FROM prof WHERE fullname=?", (prof_name,), one=True)
- -def getProfData(self, profname: str) -
--
--
Get mail, telephone number and title of a professor based on the name
-Args
--
-
profname:str
-- name of the professor -
Returns
--
-
tuple
-- the mail, telephone number and title of the professor -
---Expand source code -
-
-def getProfData(self, profname:str): - """Get mail, telephone number and title of a professor based on the name - - Args: - profname (str): name of the professor - - Returns: - tuple: the mail, telephone number and title of the professor - """ - data = self.query_db("SELECT mail, telnr, titel FROM prof WHERE fullname=?", (profname.replace(",",""),), one=True) - return data
- -def getProfId(self, prof_name: str) ‑> Optional[int] -
--
--
Get the id of a professor based on the name
-Args
--
-
prof_name:str
-- the name of the professor -
Returns
--
-
Optional[int]
-- the id of the professor, if the professor is not found, None is returned -
---Expand source code -
-
-def getProfId(self, prof_name:str)->Optional[int]: - """Get the id of a professor based on the name - - Args: - prof_name (str): the name of the professor - - Returns: - Optional[int]: the id of the professor, if the professor is not found, None is returned - """ - - data = self.getProfByName(prof_name.replace(",", "")) - if data is None: - return None - else: - return data[0]
- -def getProfNameById(self, prof_id: Union[str, int], add_title: bool = False) ‑> str -
--
--
Get a professor name based on the id
-Args
--
-
prof_id:Union[str,int]
-- The id of the professor -
add_title:bool, optional
-- wether to add the title or no. Defaults to False. -
Returns
--
-
str
-- The name of the professor -
---Expand source code -
-
-def getProfNameById(self, prof_id:Union[str,int],add_title:bool=False)->str: - """Get a professor name based on the id - - Args: - prof_id (Union[str,int]): The id of the professor - add_title (bool, optional): wether to add the title or no. Defaults to False. - - Returns: - str: The name of the professor - """ - prof = self.query_db("SELECT fullname FROM prof WHERE id=?", (prof_id,), one=True) - if add_title: - return f"{self.getTitleById(prof_id)}{prof[0]}" - else: - return prof[0]
- -def getProfs(self) ‑> list[tuple] -
--
--
Return all the professors in the database
-Returns
--
-
list[tuple]
-- a list containing all the professors in individual tuples -
---Expand source code -
-
-def getProfs(self)->list[tuple]: - """Return all the professors in the database - - Returns: - list[tuple]: a list containing all the professors in individual tuples - """ - return self.query_db("SELECT * FROM prof")
- -def getRole(self, user) -
--
--
get the role of the user
-Args
--
-
user:str
-- username -
Returns
--
-
str
-- the name of the role -
---Expand source code -
-
-def getRole(self, user): - """get the role of the user - - Args: - user (str): username - - Returns: - str: the name of the role - """ - return self.query_db("SELECT role FROM user WHERE username=?", (user,), one=True)[0]
- -def getRoles(self) ‑> list[tuple] -
--
--
get all the roles in the database
-Returns
--
-
list[str]
-- a list of all the roles -
---Expand source code -
-
-def getRoles(self)->list[tuple]: - """get all the roles in the database - - Returns: - list[str]: a list of all the roles - """ - return self.query_db("SELECT role FROM user")
- -def getSemersters(self) ‑> list[str] -
--
--
Return all the unique semesters in the database
-Returns
--
-
list
-- a list of strings containing the semesters -
---Expand source code -
-
-def getSemersters(self)->list[str]: - """Return all the unique semesters in the database - - Returns: - list: a list of strings containing the semesters - """ - data = self.query_db("SELECT DISTINCT erstellsemester FROM semesterapparat") - return [i[0] for i in data]
- -def getSpecificProfData(self, prof_id: Union[str, int], fields: List[str]) ‑> tuple -
--
--
A customisable function to get specific data of a professor based on the id
-Args
--
-
prof_id:Union[str,int]
-- the id of the professor -
fields:List[str]
-- a list of fields to be returned -
Returns
--
-
tuple
-- a tuple containing the requested data -
---Expand source code -
-
-def getSpecificProfData(self, prof_id:Union[str,int], fields:List[str])->tuple: - """A customisable function to get specific data of a professor based on the id - - Args: - prof_id (Union[str,int]): the id of the professor - fields (List[str]): a list of fields to be returned - - Returns: - tuple: a tuple containing the requested data - """ - query = "SELECT " - for field in fields: - query += f"{field}," - query = query[:-1] - query += " FROM prof WHERE id=?" - return self.query_db(query, (prof_id,), one=True)[0]
- -def getSubjects(self) -
--
--
Get all the subjects in the database
-Returns
--
-
list[tuple]
-- a list of tuples containing the subjects -
---Expand source code -
-
-def getSubjects(self): - """Get all the subjects in the database - - Returns: - list[tuple]: a list of tuples containing the subjects - """ - return self.query_db("SELECT * FROM subjects")
- -def getTitleById(self, prof_id: Union[str, int]) ‑> str -
--
--
get the title of a professor based on the id
-Args
--
-
prof_id:Union[str,int]
-- the id of the professor -
Returns
--
-
str
-- the title of the professor, with an added whitespace at the end, if no title is present, an empty string is returned -
---Expand source code -
-
-def getTitleById(self, prof_id:Union[str,int])->str: - """get the title of a professor based on the id - - Args: - prof_id (Union[str,int]): the id of the professor - - Returns: - str: the title of the professor, with an added whitespace at the end, if no title is present, an empty string is returned - """ - title = self.query_db("SELECT titel FROM prof WHERE id=?", (prof_id,), one=True)[0] - return f"{title} " if title is not None else ""
-
- -
--
Get a list of all the apparat numbers in the database that are currently in use
-Returns
--
-
List[int]
-- the list of used apparat numbers -
---Expand source code -
-
-def getUnavailableApparatNumbers(self)->List[int]: - """Get a list of all the apparat numbers in the database that are currently in use - - Returns: - List[int]: the list of used apparat numbers - """ - numbers = self.query_db("SELECT appnr FROM semesterapparat WHERE deletion_status=0") - numbers = [i[0] for i in numbers] - logger.log_info(f"Currently used apparat numbers: {numbers}") - return numbers
- -def getUser(self) -
--
--
Get a single user from the database
---Expand source code -
-
-def getUser(self): - """Get a single user from the database""" - return self.query_db("SELECT * FROM user", one=True)
- -def getUsers(self) ‑> list[tuple] -
--
--
Return a list of tuples of all the users in the database
---Expand source code -
-
-def getUsers(self)->list[tuple]: - """Return a list of tuples of all the users in the database""" - return self.query_db("SELECT * FROM user")
- -def get_db_contents(self) ‑> Optional[List[Tuple]] -
--
--
Get the contents of the
-Returns
--
-
Union[List[Tuple], None]
-- description -
---Expand source code -
-
-def get_db_contents(self)->Union[List[Tuple], None]: - """ - Get the contents of the - - Returns: - Union[List[Tuple], None]: _description_ - """ - try: - with sql.connect(self.db_path) as conn: - cursor = conn.cursor() - cursor.execute("SELECT * FROM sqlite_master WHERE type='table'") - return cursor.fetchall() - except sql.OperationalError: - return None
- -def insertFile(self, file: list[dict], app_id: Union[str, int], prof_id: Union[str, int]) -
--
--
Instert a list of files into the database
-Args
--
-
file:list[dict]
-- a list containing all the files to be inserted -
Structured
-- [{"name": "filename", "path": "path", "type": "filetype"}] -
app_id:int
-- the id of the apparat -
prof_id:str
-- the id of the professor -
---Expand source code -
-
-def insertFile(self, file: list[dict], app_id:Union[str,int], prof_id:Union[str,int]): - """Instert a list of files into the database - - Args: - file (list[dict]): a list containing all the files to be inserted - Structured: [{"name": "filename", "path": "path", "type": "filetype"}] - app_id (int): the id of the apparat - prof_id (str): the id of the professor - """ - for f in file: - filename = f["name"] - path = f["path"] - filetyp = f["type"] - if path == "Database": - continue - blob = create_blob(path) - query = "INSERT OR IGNORE INTO files (filename, fileblob, app_id, filetyp,prof_id) VALUES (?, ?, ?, ?,?)" - self.query_db(query, (filename, blob, app_id, filetyp,prof_id))
- -def insertInto(self, query: str, params: Tuple) ‑> None -
--
--
Insert sent data into the database
-Args
--
-
query:str
-- The query to be executed -
params:Tuple
-- the parameters to be inserted into the database -
---Expand source code -
-
-def insertInto(self, query:str, params:Tuple) -> None: - """ - Insert sent data into the database - - Args: - query (str): The query to be executed - params (Tuple): the parameters to be inserted into the database - """ - conn = self.connect() - cursor = conn.cursor() - logger.log_info(f"Inserting {params} into database with query {query}") - cursor.execute(query, params) - conn.commit() - self.close_connection(conn)
- -def isEternal(self, id) -
--
--
check if the apparat is eternal (dauerapparat)
-Args
--
-
id:int
-- the id of the apparat to be checked -
Returns
--
-
int
-- the state of the apparat -
---Expand source code -
-
-def isEternal(self, id): - """check if the apparat is eternal (dauerapparat) - - Args: - id (int): the id of the apparat to be checked - - Returns: - int: the state of the apparat - """ - return self.query_db("SELECT dauer FROM semesterapparat WHERE appnr=?", (id,), one=True)
- -def login(self, user, hashed_password) -
--
--
try to login the user. -The salt for the user will be requested from the database and then added to the hashed password. The password will then be compared to the password in the database
-Args
--
-
user:str
-- username that tries to login -
hashed_password:str
-- the password the user tries to login with -
Returns
--
-
bool
-- True if the login was successful, False if not -
---Expand source code -
-
-def login(self, user, hashed_password): - """try to login the user. - The salt for the user will be requested from the database and then added to the hashed password. The password will then be compared to the password in the database - - Args: - user (str): username that tries to login - hashed_password (str): the password the user tries to login with - - Returns: - bool: True if the login was successful, False if not - """ - salt = self.query_db("SELECT salt FROM user WHERE username=?", (user,), one=True)[0] - if salt is None: - return False - hashed_password = salt + hashed_password - password = self.query_db("SELECT password FROM user WHERE username=?", (user,), one=True)[0] - if password == hashed_password: - return True - else: - return False
- -def query_db(self, query: str, args: Tuple = (), one: bool = False) ‑> Union[Tuple, List[Tuple]] -
--
--
Query the Database for the sent query.
-Args
--
-
query:str
-- The query to be executed -
args:Tuple, optional
-- The arguments for the query. Defaults to (). -
one:bool, optional
-- Return the first result only. Defaults to False. -
Returns
-Union[Typle|List[Tuple]]: Returns the result of the query
---Expand source code -
-
-def query_db(self, query: str, args: Tuple = (), one: bool = False)->Union[Tuple, List[Tuple]]: - """ - Query the Database for the sent query. - - Args: - query (str): The query to be executed - args (Tuple, optional): The arguments for the query. Defaults to (). - one (bool, optional): Return the first result only. Defaults to False. - - Returns: - Union[Typle|List[Tuple]]: Returns the result of the query - """ - conn = self.connect() - cursor = conn.cursor() - logger.log_info(f"Querying database with query {query}, args: {args}") - cursor.execute(query, args) - rv = cursor.fetchall() - conn.commit() - self.close_connection(conn) - return (rv[0] if rv else None) if one else rv
- -def recreateFile(self, filename: str, app_id: Union[str, int], filetype: str) ‑> str -
--
--
Recreate a file from the database
-Args
--
-
filename:str
-- the name of the file -
app_id:Union[str,int]
-- the id of the apparat -
filetype:str
-- the extension of the file to be created -
Returns
--
-
str
-- The filename of the recreated file -
---Expand source code -
-
-def recreateFile(self, filename:str, app_id:Union[str,int],filetype:str)->str: - """Recreate a file from the database - - Args: - filename (str): the name of the file - app_id (Union[str,int]): the id of the apparat - filetype (str): the extension of the file to be created - - Returns: - str: The filename of the recreated file - """ - blob = self.getBlob(filename, app_id) - tempdir = config.database.tempdir - tempdir = tempdir.replace("~", str(Path.home())) - tempdir_path = Path(tempdir) - if not os.path.exists(tempdir_path): - os.mkdir(tempdir_path) - file = tempfile.NamedTemporaryFile( - delete=False, dir=tempdir_path, mode="wb", suffix=f".{filetype}" - ) - file.write(blob) - print("file created") - return file.name
- -def searchBook(self, data: dict[str, str]) ‑> list[tuple[src.logic.dataclass.BookData, int]] -
--
--
Search a book in the database based on the sent data.
-Args
--
-
data:dict[str, str]
-- A dictionary containing the data to be searched for. The dictionary can contain the following: -
-
-
- signature: The signature of the book -
- title: The title of the book -
Returns
--
-
list[tuple[BookData, int]]
-- A list of tuples containing the wrapped Metadata and the id of the book -
---Expand source code -
-
-def searchBook(self, data:dict[str, str])->list[tuple[BookData, int]]: - """ - Search a book in the database based on the sent data. - - Args: - data (dict[str, str]): A dictionary containing the data to be searched for. The dictionary can contain the following: - - signature: The signature of the book - - title: The title of the book - - Returns: - list[tuple[BookData, int]]: A list of tuples containing the wrapped Metadata and the id of the book - """ - rdata = self.query_db("SELECT * FROM media WHERE deleted=0") - #ic(rdata, len(rdata)) - mode = 0 - if len(data)== 1: - if "signature" in data.keys(): - mode = 1 - elif "title" in data.keys(): - mode = 2 - elif len(data) == 2: - mode = 3 - else: - return None - ret = [] - for book in rdata: - bookdata = load_pickle(book[1]) - app_id = book[2] - prof_id = book[3] - if mode == 1: - if data["signature"] in bookdata.signature: - ret.append((bookdata,app_id,prof_id)) - elif mode == 2: - if data["title"] in bookdata.title: - ret.append((bookdata,app_id,prof_id)) - elif mode == 3: - if data["signature"] in bookdata.signature and data["title"] in bookdata.title: - ret.append((bookdata,app_id,prof_id)) - #ic(ret) - return ret
- -def setAvailability(self, book_id: str, available: str) -
--
--
Set the availability of a book in the database
-Args
--
-
book_id:str
-- The id of the book -
available:str
-- The availability of the book -
---Expand source code -
-
-def setAvailability(self, book_id:str, available:str): - """ - Set the availability of a book in the database - - Args: - book_id (str): The id of the book - available (str): The availability of the book - """ - self.query_db("UPDATE media SET available=? WHERE id=?", (available,book_id))
- -def setNewSemesterDate(self, app_id: Union[str, int], newDate, dauerapp=False) -
--
--
Set the new semester date for an apparat
-Args
--
-
app_id:Union[str,int]
-- the id of the apparat -
newDate:str
-- the new date -
dauerapp:bool, optional
-- if the apparat was changed to dauerapparat. Defaults to False. -
---Expand source code -
-
-def setNewSemesterDate(self, app_id:Union[str,int], newDate, dauerapp=False): - """Set the new semester date for an apparat - - Args: - app_id (Union[str,int]): the id of the apparat - newDate (str): the new date - dauerapp (bool, optional): if the apparat was changed to dauerapparat. Defaults to False. - """ - date = datetime.datetime.strptime(newDate, "%d.%m.%Y").strftime("%Y-%m-%d") - if dauerapp: - self.query_db("UPDATE semesterapparat SET verlängerung_bis=?, dauerapp=? WHERE appnr=?", (date,dauerapp,app_id)) - else: - self.query_db("UPDATE semesterapparat SET endsemester=? WHERE appnr=?", (date,app_id))
- -def statistic_request(self, **kwargs: Any) -
--
--
Take n amount of kwargs and return the result of the query
---Expand source code -
-
-def statistic_request(self, **kwargs: Any): - """Take n amount of kwargs and return the result of the query - """ - def __query(query): - """execute the query and return the result - - Args: - query (str): the constructed query - - Returns: - list: the result of the query - """ - conn = self.connect() - cursor = conn.cursor() - result = cursor.execute(query).fetchall() - for result_a in result: - orig_value = result_a - prof_name = self.getProfNameById(result_a[2]) - # replace the prof_id with the prof_name - result_a = list(result_a) - result_a[2] = prof_name - result_a = tuple(result_a) - result[result.index(orig_value)] = result_a - self.close_connection(conn) - return result - if "deletable" in kwargs.keys(): - query = f"SELECT * FROM semesterapparat WHERE deletion_status=0 AND dauer=0 AND (erstellsemester!='{kwargs['deletesemester']}' OR verlängerung_bis!='{kwargs['deletesemester']}')" - return __query(query) - if "dauer" in kwargs.keys(): - kwargs["dauer"] = kwargs["dauer"].replace("Ja", "1").replace("Nein", "0") - query = "SELECT * FROM semesterapparat WHERE " - for key, value in kwargs.items() if kwargs.items() is not None else {}: - print(key, value) - query += f"{key}='{value}' AND " - print(query) - # remove deletesemester part from normal query, as this will be added to the database upon deleting the apparat - if "deletesemester" in kwargs.keys(): - query = query.replace( - f"deletesemester='{kwargs['deletesemester']}' AND ", "" - ) - if "endsemester" in kwargs.keys(): - if "erstellsemester" in kwargs.keys(): - query = query.replace(f"endsemester='{kwargs['endsemester']}' AND ", "") - query = query.replace( - f"erstellsemester='{kwargs['erstellsemester']} AND ", "xyz" - ) - else: - query = query.replace( - f"endsemester='{kwargs['endsemester']}' AND ", "xyz" - ) - print("replaced") - query = query.replace( - "xyz", - f"(erstellsemester='{kwargs['endsemester']}' OR verlängerung_bis='{kwargs['endsemester']}') AND ", - ) - # remove all x="" parts from the query where x is a key in kwargs - query = query[:-5] - print(query) - return __query(query)
- -def updateApparat(self, apparat_data: src.logic.dataclass.ApparatData) -
--
--
Update an apparat in the database
-Args
--
-
apparat_data:ApparatData
-- the new metadata of the apparat -
---Expand source code -
-
-def updateApparat(self, apparat_data:ApparatData): - """Update an apparat in the database - - Args: - apparat_data (ApparatData): the new metadata of the apparat - """ - query = f"UPDATE semesterapparat SET name = ?, fach = ?, dauer = ?, prof_id = ? WHERE appnr = ?" - params = ( - apparat_data.appname, - apparat_data.app_fach, - apparat_data.dauerapp, - self.getProfId(apparat_data.profname), - apparat_data.appnr, - ) - self.query_db(query, params)
- -def updateBookdata(self, book_id, bookdata: src.logic.dataclass.BookData) -
--
--
Update the bookdata in the database
-Args
--
-
book_id:str
-- The id of the book -
bookdata:BookData
-- The new metadata of the book -
---Expand source code -
-
-def updateBookdata(self, book_id, bookdata:BookData): - """ - Update the bookdata in the database - - Args: - book_id (str): The id of the book - bookdata (BookData): The new metadata of the book - """ - self.query_db("UPDATE media SET bookdata=? WHERE id=?", (dump_pickle(bookdata),book_id))
- -def updateFacultyMember(self, data: dict, oldlname: str, oldfname: str) -
--
--
update the data of a faculty member
-Args
--
-
data:dict
-- a dictionary containing the data to be updated -
oldlname:str
-- the old last name of the faculty member -
oldfname:str
-- the old first name of the faculty member -
---Expand source code -
-
-def updateFacultyMember(self, data:dict, oldlname:str, oldfname:str): - """update the data of a faculty member - - Args: - data (dict): a dictionary containing the data to be updated - oldlname (str): the old last name of the faculty member - oldfname (str): the old first name of the faculty member - """ - placeholders = ", ".join([f"{i}=:{i} " for i in data.keys()]) - query = f"UPDATE prof SET {placeholders} WHERE lname = :oldlname AND fname = :oldfname" - data["oldlname"] = oldlname - data["oldfname"] = oldfname - self.query_db(query, data)
- -def updateUser(self, username, data: dict[str, str]) -
--
--
changge the data of a user
-Args
--
-
username:str
-- the username of the user -
data:dict[str, str]
-- the data to be changed -
---Expand source code -
-
-def updateUser(self, username, data:dict[str, str]): - """changge the data of a user - - Args: - username (str): the username of the user - data (dict[str, str]): the data to be changed - """ - conn = self.connect() - cursor = conn.cursor() - query = "UPDATE user SET " - for key,value in data.items(): - if key == "username": - continue - query += f"{key}='{value}'," - query = query[:-1] - query += " WHERE username=?" - params = (username,) - cursor.execute(query, params) - conn.commit() - self.close_connection(conn)
-
-