rest of files, not sorted

This commit is contained in:
WorldTeacher
2024-05-17 08:35:37 +02:00
parent 7a0f7ed1f1
commit d7853ab67d
82 changed files with 10724 additions and 2309 deletions

View File

@@ -212,4 +212,4 @@ SEMAP_MEDIA_ACCOUNTS = {
"178": "1008017766",
"179": "1008017899",
"180": "1008017922",
}
}

View File

@@ -7,15 +7,16 @@ def csv_to_list(path: str) -> list[str]:
"""
Extracts the data from a csv file and returns it as a pandas dataframe
"""
with open(path, newline='') as csvfile:
reader = csv.reader(csvfile, delimiter=';', quotechar='|')
with open(path, newline="") as csvfile:
reader = csv.reader(csvfile, delimiter=";", quotechar="|")
ret = []
for row in reader:
print(row)
ret.append(row[0].replace('"', ""))
return ret
return ret
if __name__ == "__main__":
text = csv_to_list("C:/Users/aky547/Desktop/semap/71.csv")
#remove linebreaks
print(text)
# remove linebreaks
print(text)

View File

@@ -2,6 +2,7 @@ import re
from dataclasses import dataclass, field
from enum import Enum
@dataclass
class ApparatData:
prof_title: str | None = None
@@ -101,17 +102,17 @@ class Subjects(Enum):
TECHNIC = (22, "Technik")
THEOLOGY = (23, "Theologie")
ECONOMICS = (24, "Wirtschaftslehre")
@property
def id(self):
return self.value[0]
@property
def name(self):
return self.value[1]
@classmethod
def get_index(cls, name):
for i in cls:
if i.name == name:
return i.id -1
return i.id - 1

View File

@@ -1,24 +1,23 @@
from docx import Document
data={}
wordDoc = Document('files/Semesterapparat - Anmeldung.docx')
data = {}
wordDoc = Document("files/Semesterapparat - Anmeldung.docx")
paragraphs = wordDoc.tables
for table in paragraphs:
for column in table.columns:
cellcount=0
cellcount = 0
for cell in column.cells:
if cellcount<12:
cellcount+=1
print(f'cell:{cell.text}')
if cellcount < 12:
cellcount += 1
print(f"cell:{cell.text}")
# print(f'paragraphs[{i}]: {paragraphs[i]}')
# data[i] = paragraphs[i]
# for i in range(0, len(paragraphs)):
# for i in range(2, len(paragraphs)):
# data[i] = paragraphs[i]
print(data)
# for table in wordDoc.tables:
@@ -26,6 +25,3 @@ print(data)
# print('---')
# for cell in row.cells:
# print(f'cell:{cell.text}')

View File

@@ -1,11 +1,10 @@
import tabula
file = "files/Semesterapparat - Anmeldung.pdf"
file="files/Semesterapparat - Anmeldung.pdf"
def extract_book_data(file):
tables=tabula.read_pdf(file,pages="all",encoding="utf-8",multiple_tables=True)
tabula.read_pdf(file, pages="all", encoding="utf-8", multiple_tables=True)
tabula.convert_into(file, file.replace(".pdf"), output_format="csv", pages="all")
with open("files/Semesterapparat - Anmeldung.csv", "r") as f:
content=f.read()
f.read()

View File

@@ -1,25 +1,38 @@
import logging
import logging.handlers
import os
if not os.path.exists("logs"):
os.mkdir("logs")
#open and close the file to create it
# open and close the file to create it
with open("logs/application.log", "w") as f:
pass
log_filesize = 10 * 1024**2 # 10MB
backups = 5
# Create a common file handler for all loggers
common_file_handler = logging.FileHandler("logs/application.log")
common_file_handler = logging.handlers.RotatingFileHandler(
"logs/application.log",
mode="a",
encoding="utf-8",
maxBytes=log_filesize,
backupCount=backups,
)
common_file_handler.setLevel(logging.DEBUG)
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
common_file_handler.setFormatter(formatter)
#set max file size to 10MB, if exceeded, create a new file
# set max file size to 10MB, if exceeded, create a new file
class MyLogger:
def __init__(self, logger_name):
self.logger = logging.getLogger(logger_name)
self.logger.setLevel(logging.DEBUG)
self.logger.addHandler(common_file_handler)
self.encoding = "utf-8"
def log_info(self, message: str):
# ensure that the message is encoded in utf-8
@@ -61,6 +74,6 @@ if __name__ == "__main__":
try:
# Simulate an exception
raise Exception("An exception occurred")
except Exception as e:
except Exception:
logger1.log_exception("An exception occurred in Logger1")
logger2.log_exception("An exception occurred in Logger2")

View File

@@ -12,19 +12,15 @@ def pdf_to_csv(path: str) -> pd.DataFrame:
"""
file = PDFQuery(path)
file.load()
#get the text from the pdf file
text_elems = file.extract([
('with_formatter', 'text'),
('all_text', '*')
])
extracted_text = text_elems['all_text']
# get the text from the pdf file
text_elems = file.extract([("with_formatter", "text"), ("all_text", "*")])
extracted_text = text_elems["all_text"]
return extracted_text
if __name__ == "__main__":
text = pdf_to_csv("54_pdf.pdf")
#remove linebreaks
# remove linebreaks
text = text.replace("\n", "")
print(text)

View File

@@ -1,20 +1,24 @@
import yaml
from dataclasses import dataclass, field
import yaml
@dataclass
class Settings:
"""Settings for the app."""
save_path: str
database_name: str
database_path: str
default_apps:bool = True
default_apps: bool = True
custom_applications: list[dict] = field(default_factory=list)
def save_settings(self):
"""Save the settings to the config file."""
with open("config.yaml", "w") as f:
yaml.dump(self.__dict__, f)
#open the config file and load the settings
# open the config file and load the settings
with open("config.yaml", "r") as f:
data = yaml.safe_load(f)

View File

@@ -1,7 +1,8 @@
import sqlite3
import time
from PyQt6.QtCore import QThread, pyqtSignal as Signal
from PyQt6.QtCore import QThread
from PyQt6.QtCore import pyqtSignal as Signal
from src.backend.database import Database
from src.logic.log import MyLogger
@@ -62,8 +63,8 @@ class BookGrabber(QThread):
for rds_item in rds.items:
sign = rds_item.superlocation
loc = rds_item.location
#ic(sign, loc)
#ic(rds_item)
# ic(sign, loc)
# ic(rds_item)
if self.app_id in sign or self.app_id in loc:
state = 1
break

View File

@@ -2,10 +2,11 @@ import os
import sqlite3
import time
#from icecream import ic
# from icecream import ic
from omegaconf import OmegaConf
from PyQt6 import QtWidgets
from PyQt6.QtCore import QThread, pyqtSignal as Signal
from PyQt6.QtCore import QThread
from PyQt6.QtCore import pyqtSignal as Signal
from src.backend.database import Database
from src.logic.log import MyLogger
@@ -26,7 +27,7 @@ class BackgroundChecker(QThread):
class MockAvailCheck:
def __init__(
self, links: list = [], appnumber: int = None, parent=None, books=list[dict]
self, links: list = None, appnumber: int = None, parent=None, books=list[dict]
):
if links is None:
links = []
@@ -58,7 +59,7 @@ class MockAvailCheck:
for item in rds.items:
sign = item.superlocation
loc = item.location
#ic(item.location, item.superlocation)
# ic(item.location, item.superlocation)
if self.appnumber in sign or self.appnumber in loc:
state = 1
book_id = None
@@ -197,18 +198,3 @@ class MailThread(QThread):
def run(self):
self.show_ui()
self.updateSignal.emit(1)

View File

@@ -1,7 +1,8 @@
import time
#from icecream import ic
from PyQt6.QtCore import QThread, pyqtSignal as Signal
# from icecream import ic
from PyQt6.QtCore import QThread
from PyQt6.QtCore import pyqtSignal as Signal
from src.backend.database import Database
from src.logic.log import MyLogger

View File

@@ -1,7 +1,8 @@
import time
#from icecream import ic
from PyQt6.QtCore import QThread, pyqtSignal as Signal
# from icecream import ic
from PyQt6.QtCore import QThread
from PyQt6.QtCore import pyqtSignal as Signal
from src.backend.database import Database
from src.logic.log import MyLogger

View File

@@ -1,14 +1,16 @@
import os
import sqlite3
import threading
import time
import os
from PyQt6.QtCore import QThread, pyqtSignal
from src.backend.database import Database
from src.logic.log import MyLogger
from src.transformers import RDS_AVAIL_DATA
from src.logic.webrequest import BibTextTransformer, WebRequest
import sqlite3
#from icecream import ic
from src.transformers import RDS_AVAIL_DATA
# from icecream import ic
class BookGrabber(QThread):
@@ -19,8 +21,8 @@ class BookGrabber(QThread):
self.is_Running = True
self.logger = MyLogger("Worker")
self.logger.log_info("Starting worker thread")
self.data,self.app_id,self.prof_id,self.mode = self.readFile(filename)
self.data, self.app_id, self.prof_id, self.mode = self.readFile(filename)
self.book_id = None
time.sleep(2)
@@ -68,8 +70,8 @@ class BookGrabber(QThread):
for rds_item in rds.items:
sign = rds_item.superlocation
loc = rds_item.location
#ic(sign, loc)
#ic(rds_item)
# ic(sign, loc)
# ic(rds_item)
if self.app_id in sign or self.app_id in loc:
state = 1
break
@@ -213,7 +215,7 @@ class AutoAdder(QThread):
class MockAvailCheck:
def __init__(
self, links: list = [], appnumber: int = None, parent=None, books=list[dict]
self, links: list = None, appnumber: int = None, parent=None, books=list[dict]
):
if links is None:
links = []
@@ -245,7 +247,7 @@ class MockAvailCheck:
for item in rds.items:
sign = item.superlocation
loc = item.location
#ic(item.location, item.superlocation)
# ic(item.location, item.superlocation)
if self.appnumber in sign or self.appnumber in loc:
state = 1
book_id = None

View File

@@ -16,8 +16,6 @@ from PyQt6 import QtCore, QtGui, QtWidgets
from PyQt6.QtCore import QDate, QThread
from PyQt6.QtGui import QColor, QRegularExpressionValidator
# from src.logic.webrequest import BibTextTransformer, WebRequest
# from src.utils import documentationview
from src.backend.admin_console import AdminCommands
from src.backend.create_file import recreateFile
from src.backend.database import Database
@@ -29,7 +27,7 @@ from src.logic.csvparser import csv_to_list
from src.logic.dataclass import ApparatData, BookData
from src.logic.log import MyLogger
from src.logic.wordparser import word_docx_to_csv
from src.ui import ( # Mail_Dialog,
from src.ui import (
App_Ext_Dialog,
FilePicker,
GraphWidget,
@@ -63,7 +61,6 @@ class Medien(medienadder_ui):
return self.comboBox.currentText()
class MyComboBox(QtWidgets.QComboBox):
def __init__(self, parent=None):
@@ -184,18 +181,7 @@ class Ui(Ui_Semesterapparat):
QtWidgets.QScrollBar(), QtCore.Qt.AlignmentFlag.AlignRight
)
# connect contextmenuevent to tablewidget
self.tableWidget_apparate.setContextMenuPolicy(
QtCore.Qt.ContextMenuPolicy.CustomContextMenu
)
self.tableWidget_apparate.customContextMenuRequested.connect(
self.open_context_menu
)
self.tableWidget_apparat_media.setContextMenuPolicy(
QtCore.Qt.ContextMenuPolicy.CustomContextMenu
)
self.tableWidget_apparat_media.customContextMenuRequested.connect(
self.media_context_menu
)
# enable automatic resizing of columns for book_search_result
self.book_search_result.horizontalHeader().setSectionResizeMode(
QtWidgets.QHeaderView.ResizeMode.Stretch
@@ -235,6 +221,9 @@ class Ui(Ui_Semesterapparat):
self.label_20.hide()
self.line_3.hide()
self.avail_status.hide()
self.chkbx_show_del_media.hide()
self.groupBox_2.hide()
self.groupBox.hide()
self.check_deletable.stateChanged.connect(self.gridchange)
self.tableWidget.horizontalHeader().setSectionResizeMode(
QtWidgets.QHeaderView.ResizeMode.Stretch
@@ -247,6 +236,9 @@ class Ui(Ui_Semesterapparat):
self.tableWidget.resizeColumnsToContents()
self.tableWidget.resizeRowsToContents()
# set self.app_fach viable inputs to be
# self.app_fach.addItems([subject[1] for subject in self.db.getSubjects()])
# self.app_fach.addItem("")
# self.app_fach.setCurrentText("")
# create a thread, that continually checks the validity of the inputs
@@ -269,10 +261,6 @@ class Ui(Ui_Semesterapparat):
# self.thread_check()
### Admin interface ###
#!admin - create user
#!admin - delete user
#!admin - change user
# TODO:admin - change faculty
self.select_action_box.addItem("")
self.select_action_box.setCurrentText("")
self.hide_all()
@@ -282,7 +270,22 @@ class Ui(Ui_Semesterapparat):
)
self.book_search.clicked.connect(self.search_book)
# enable click functionality for the combobox to allow selection of roles
# Context Menus
self.tableWidget_apparate.setContextMenuPolicy(
QtCore.Qt.ContextMenuPolicy.CustomContextMenu
)
self.tableWidget_apparat_media.setContextMenuPolicy(
QtCore.Qt.ContextMenuPolicy.CustomContextMenu
)
self.tableWidget_apparate.customContextMenuRequested.connect(
self.open_context_menu
)
self.tableWidget_apparat_media.customContextMenuRequested.connect(
self.media_context_menu
)
self.tableWidget.customContextMenuRequested.connect(
self.statistics_table_context_menu
)
# admin buttons
self.user_frame_addUser.clicked.connect(self.add_user)
@@ -290,6 +293,7 @@ class Ui(Ui_Semesterapparat):
self.update_user.clicked.connect(self.update_user_data)
self.update_faculty_member.clicked.connect(self.edit_faculty_member_action)
# Create instances to be used by the threads in the application
self.bookGrabber = None
self.availChecker = None
self.mail_thread = None
@@ -322,7 +326,7 @@ class Ui(Ui_Semesterapparat):
"title": title if title != "" else None,
}
params = {key: value for key, value in params.items() if value is not None}
#ic(params)
# ic(params)
retdata = self.db.searchBook(params)
if retdata is None:
return
@@ -378,7 +382,7 @@ class Ui(Ui_Semesterapparat):
password = self.user_create_frame_password.text()
role = self.user_frame_userrole.currentText()
if self.db.checkUsername(username):
#ic("username already exists")
# ic("username already exists")
# self.user_create_frame_error.setText("Der Nutzername ist bereits vergeben")#TODO: implement error message
return
userdata = AdminCommands().create_password(password)
@@ -402,8 +406,10 @@ class Ui(Ui_Semesterapparat):
)
self.user_delete_confirm.setChecked(False)
else:
self.user_delete_err_message.setText("Bitte bestätigen Sie die Löschung des Nutzers") # TODO: implement error message
#ic("please confirm the deletion of the user")
self.user_delete_err_message.setText(
"Bitte bestätigen Sie die Löschung des Nutzers"
) # TODO: implement error message
# ic("please confirm the deletion of the user")
def update_user_data(self):
username = self.user_edit_frame_user_select.currentText()
@@ -752,15 +758,21 @@ class Ui(Ui_Semesterapparat):
def delete_selected_apparats(self):
# get all selected apparats
selected_apparats = []
selected_apparat_rows = []
for i in range(self.tableWidget.rowCount()):
if self.tableWidget.cellWidget(i, 0).isChecked():
selected_apparats.append(self.tableWidget.item(i, 2).text())
selected_apparat_rows.append(i)
# delete all selected apparats
print(selected_apparats)
for apparat in selected_apparats:
self.db.deleteApparat(apparat, self.generateSemester(today=True))
for row in selected_apparat_rows:
# set the background of the row to red
for j in range(5):
self.tableWidget.item(row, j).setBackground(QtGui.QColor(235, 74, 71))
# refresh the table
self.tab_changed()
self.populate_tab()
self.btn_del_select_apparats.setEnabled(False)
def statistics(self):
@@ -842,7 +854,7 @@ class Ui(Ui_Semesterapparat):
def populate_frame(self, appdata: ApparatData):
# populate the frame with the data from the database
#ic(appdata)
# ic(appdata)
self.drpdwn_app_nr.setCurrentText(str(appdata.appnr))
self.prof_title.setText(appdata.prof_title)
prof_name = appdata.profname.split(" ")
@@ -912,6 +924,8 @@ class Ui(Ui_Semesterapparat):
self.update_app_media_list()
self.cancel_active_selection.click()
self.check_send_mail.show()
self.chkbx_show_del_media.show()
def confirm_popup(self, message: str):
dial = QtWidgets.QDialog()
@@ -1052,7 +1066,7 @@ class Ui(Ui_Semesterapparat):
return
selected_prof = self.drpdwn_prof_name.currentText()
data = self.db.getProfData(selected_prof)
#ic(data)
# ic(data)
prof_title = data[2]
if prof_title == "None":
prof_title = "Kein Titel"
@@ -1071,12 +1085,13 @@ class Ui(Ui_Semesterapparat):
return None
def load_app_data(self, app_id=None):
print(type(app_id))
if isinstance(app_id, str):
# double click the tableWidget_apparate row with the given app_id
row, column = self.get_index_of_value(self.tableWidget_apparate, app_id)
# set the current index to the row
self.tableWidget_apparate.setCurrentCell(row, 0)
self.check_send_mail.hide()
app_pos = self.tableWidget_apparate.currentIndex()
appnr = self.tableWidget_apparate.item(app_pos.row(), 0).text()
appname = self.tableWidget_apparate.item(app_pos.row(), 1).text()
@@ -1089,6 +1104,7 @@ class Ui(Ui_Semesterapparat):
self.populate_frame(appdata)
self.btn_apparat_save.hide()
self.btn_reserve.show()
self.chkbx_show_del_media.show()
self.drpdwn_app_nr.setDisabled(True)
self.update_app_media_list()
self.update_documemt_list()
@@ -1128,9 +1144,7 @@ class Ui(Ui_Semesterapparat):
self.chkbx_show_del_media.setEnabled(True)
self.drpdwn_app_nr.setEnabled(True)
self.app_fach.setEnabled(True)
self.app_fach.addItems([subject[1] for subject in self.db.getSubjects()])
self.app_fach.addItem("")
self.app_fach.setCurrentText("")
if self.tableWidget_apparat_media.rowCount() > 0:
self.tableWidget_apparat_media.setRowCount(0)
# clear all fields
@@ -1281,6 +1295,9 @@ class Ui(Ui_Semesterapparat):
self.dokument_list.setRowCount(0)
self.frame.setEnabled(False)
self.app_fach.setCurrentText("")
self.chkbx_show_del_media.hide()
self.check_send_mail.hide()
self.btn_reserve.hide()
for child in self.frame.findChildren(QtWidgets.QLineEdit):
child.clear()
@@ -1297,7 +1314,7 @@ class Ui(Ui_Semesterapparat):
# booklist:list[BookData]=[book[0] for book in books]
self.tableWidget_apparat_media.setRowCount(0)
for book in books:
book_id = book["id"]
book["id"]
book_data = book["bookdata"]
availability = book["available"]
# bd = BookData().from_string(book)
@@ -1587,7 +1604,7 @@ class Ui(Ui_Semesterapparat):
]
signatures = [i for i in signatures if i != ""]
#ic(signatures)
# ic(signatures)
print("starting thread")
self.autoGrabber = BookGrabber(
mode="ARRAY", app_id=app_id, prof_id=prof_id, data=signatures
@@ -1638,6 +1655,7 @@ class Ui(Ui_Semesterapparat):
self.drpdwn_prof_name.clear()
self.tableWidget_apparat_media.setRowCount(0)
self.frame.setEnabled(False)
self.check_send_mail.setChecked(False)
if not self.validate_fields():
self.confirm_popup("Bitte alle Pflichtfelder ausfüllen!")
@@ -1718,7 +1736,7 @@ class Ui(Ui_Semesterapparat):
self.old_apparats = self.apparats
def insert_apparat_into_table(self, apparat):
#ic(apparat)
# ic(apparat)
def __dauer_check(apparat):
return "Ja" if apparat[7] == 1 else "Nein"
@@ -1741,7 +1759,7 @@ class Ui(Ui_Semesterapparat):
0,
3,
QtWidgets.QTableWidgetItem(
str(apparat[8]) if apparat[8] != None else apparat[5]
str(apparat[8]) if apparat[8] is not None else apparat[5]
),
)
self.tableWidget_apparate.setItem(
@@ -1766,6 +1784,23 @@ class Ui(Ui_Semesterapparat):
remind_action.triggered.connect(self.reminder)
menu.exec(self.tableWidget_apparate.mapToGlobal(position))
def statistics_table_context_menu(self, position):
menu = QtWidgets.QMenu()
restore_action = menu.addAction("Wiederherstellen")
menu.addAction(restore_action)
restore_action.triggered.connect(self.restore_apparat)
menu.exec(self.tableWidget.mapToGlobal(position))
def restore_apparat(self):
row = self.tableWidget.currentRow()
apparat = self.tableWidget.item(row, 1).text()
ic(apparat)
apparat_id = self.db.getApparatId(apparat)
# restore the apparat
self.db.restoreApparat(apparat_id)
# update the table
self.reload()
def reminder(self):
self.logger.log_info("Opening reminder dialog")
dialog = QtWidgets.QDialog()
@@ -1850,7 +1885,7 @@ class Ui(Ui_Semesterapparat):
print(data)
OmegaConf.save(data, "config.yaml")
# re-load the config
config = OmegaConf.load("config.yaml")
OmegaConf.load("config.yaml")
self.logger.log_info("Saved settings to config.yaml")
self.reload()
@@ -2080,43 +2115,3 @@ if __name__ == "__main__":
# app.exec()
# open login screen
launch_gui()

View File

@@ -2,11 +2,12 @@ import requests
from bs4 import BeautifulSoup
from omegaconf import OmegaConf
# import sleep_and_retry decorator to retry requests
from ratelimit import limits, sleep_and_retry
from src.logic.dataclass import BookData
from src.logic.log import MyLogger
from src.transformers import ARRAYData, BibTeXData, COinSData, RDSData, RISData
#import sleep_and_retry decorator to retry requests
from ratelimit import limits, sleep_and_retry
logger = MyLogger(__name__)
config = OmegaConf.load("config.yaml")
@@ -121,6 +122,7 @@ class BibTextTransformer:
if RDS_IDENT in line:
self.data = line
return self
def return_data(self, option=None) -> BookData:
"""Return Data to caller.