Code cleanup.
This commit is contained in:
1
TODO.md
1
TODO.md
@@ -1,3 +1,4 @@
|
|||||||
|
- [ ] move functions from widgets.functions to... app?
|
||||||
- [x] Apply below fix to all other date-based queries.
|
- [x] Apply below fix to all other date-based queries.
|
||||||
- [x] Fix Control graph chart bug that excludes today's controls.
|
- [x] Fix Control graph chart bug that excludes today's controls.
|
||||||
- [x] Convert logger to a custom class.
|
- [x] Convert logger to a custom class.
|
||||||
|
|||||||
@@ -8,8 +8,6 @@ if check_if_app():
|
|||||||
|
|
||||||
# NOTE: setup custom logger
|
# NOTE: setup custom logger
|
||||||
logging.setLoggerClass(CustomLogger)
|
logging.setLoggerClass(CustomLogger)
|
||||||
# logger = logging.getLogger("submissions")
|
|
||||||
# logger = setup_logger(verbosity=3)
|
|
||||||
|
|
||||||
from PyQt6.QtWidgets import QApplication
|
from PyQt6.QtWidgets import QApplication
|
||||||
from frontend.widgets.app import App
|
from frontend.widgets.app import App
|
||||||
|
|||||||
@@ -1573,17 +1573,13 @@ class BacterialCulture(BasicSubmission):
|
|||||||
def get_provisional_controls(self, include: List[str] = []):
|
def get_provisional_controls(self, include: List[str] = []):
|
||||||
# NOTE To ensure Samples are done last.
|
# NOTE To ensure Samples are done last.
|
||||||
include = sorted(include)
|
include = sorted(include)
|
||||||
logger.debug(include)
|
# logger.debug(include)
|
||||||
pos_str = "(ATCC)|(MCS)"
|
pos_str = "(ATCC)|(MCS)"
|
||||||
pos_regex = re.compile(rf"^{pos_str}")
|
pos_regex = re.compile(rf"^{pos_str}")
|
||||||
neg_str = "(EN)"
|
neg_str = "(EN)"
|
||||||
neg_regex = re.compile(rf"^{neg_str}")
|
neg_regex = re.compile(rf"^{neg_str}")
|
||||||
total_str = pos_str + "|" + neg_str
|
|
||||||
total_regex = re.compile(rf"^{total_str}")
|
|
||||||
output = []
|
output = []
|
||||||
for item in include:
|
for item in include:
|
||||||
# if self.controls:
|
|
||||||
# logger.debug(item)
|
|
||||||
match item:
|
match item:
|
||||||
case "Positive":
|
case "Positive":
|
||||||
if self.controls:
|
if self.controls:
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ class IridaFigure(CustomFigure):
|
|||||||
self.df = df
|
self.df = df
|
||||||
self.construct_chart(df=df, modes=modes, start_date=settings['start_date'], end_date=settings['end_date'])
|
self.construct_chart(df=df, modes=modes, start_date=settings['start_date'], end_date=settings['end_date'])
|
||||||
|
|
||||||
|
|
||||||
def construct_chart(self, df: pd.DataFrame, modes: list, start_date: date, end_date:date):
|
def construct_chart(self, df: pd.DataFrame, modes: list, start_date: date, end_date:date):
|
||||||
"""
|
"""
|
||||||
Creates a plotly chart for controls from a pandas dataframe
|
Creates a plotly chart for controls from a pandas dataframe
|
||||||
|
|||||||
@@ -17,4 +17,4 @@ from .submission_widget import *
|
|||||||
from .summary import *
|
from .summary import *
|
||||||
from .turnaround import *
|
from .turnaround import *
|
||||||
from .omni_add_edit import *
|
from .omni_add_edit import *
|
||||||
from .omni_manager import *
|
from .omni_manager_pydant import *
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"""
|
"""
|
||||||
Constructs main application.
|
Constructs main application.
|
||||||
"""
|
"""
|
||||||
import getpass, logging, webbrowser, sys, shutil
|
import getpass, logging, webbrowser, sys
|
||||||
from pprint import pformat
|
from pprint import pformat
|
||||||
from PyQt6.QtCore import qInstallMessageHandler
|
from PyQt6.QtCore import qInstallMessageHandler
|
||||||
from PyQt6.QtWidgets import (
|
from PyQt6.QtWidgets import (
|
||||||
@@ -13,8 +13,7 @@ from PyQt6.QtGui import QAction
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from markdown import markdown
|
from markdown import markdown
|
||||||
from pandas import ExcelWriter
|
from pandas import ExcelWriter
|
||||||
from __init__ import project_path
|
from backend import Reagent, BasicSample, Organization, KitType, BasicSubmission
|
||||||
from backend import SubmissionType, Reagent, BasicSample, Organization, KitType, BasicSubmission
|
|
||||||
from tools import (
|
from tools import (
|
||||||
check_if_app, Settings, Report, jinja_template_loading, check_authorization, page_size, is_power_user,
|
check_if_app, Settings, Report, jinja_template_loading, check_authorization, page_size, is_power_user,
|
||||||
under_development
|
under_development
|
||||||
@@ -30,7 +29,6 @@ from .summary import Summary
|
|||||||
from .turnaround import TurnaroundTime
|
from .turnaround import TurnaroundTime
|
||||||
from .concentrations import Concentrations
|
from .concentrations import Concentrations
|
||||||
from .omni_search import SearchBox
|
from .omni_search import SearchBox
|
||||||
from .omni_manager import ManagerWindow
|
|
||||||
|
|
||||||
logger = logging.getLogger(f'submissions.{__name__}')
|
logger = logging.getLogger(f'submissions.{__name__}')
|
||||||
|
|
||||||
@@ -83,7 +81,6 @@ class App(QMainWindow):
|
|||||||
helpMenu.addAction(self.githubAction)
|
helpMenu.addAction(self.githubAction)
|
||||||
fileMenu.addAction(self.importAction)
|
fileMenu.addAction(self.importAction)
|
||||||
fileMenu.addAction(self.archiveSubmissionsAction)
|
fileMenu.addAction(self.archiveSubmissionsAction)
|
||||||
# fileMenu.addAction(self.yamlImportAction)
|
|
||||||
methodsMenu.addAction(self.searchSample)
|
methodsMenu.addAction(self.searchSample)
|
||||||
maintenanceMenu.addAction(self.joinExtractionAction)
|
maintenanceMenu.addAction(self.joinExtractionAction)
|
||||||
maintenanceMenu.addAction(self.joinPCRAction)
|
maintenanceMenu.addAction(self.joinPCRAction)
|
||||||
@@ -123,7 +120,7 @@ class App(QMainWindow):
|
|||||||
"""
|
"""
|
||||||
connect menu and tool bar item to functions
|
connect menu and tool bar item to functions
|
||||||
"""
|
"""
|
||||||
self.importAction.triggered.connect(self.table_widget.formwidget.importSubmission)
|
self.importAction.triggered.connect(lambda fname: self.table_widget.formwidget.import_submission_function(fname=fname))
|
||||||
self.addReagentAction.triggered.connect(self.table_widget.formwidget.add_reagent)
|
self.addReagentAction.triggered.connect(self.table_widget.formwidget.add_reagent)
|
||||||
self.joinExtractionAction.triggered.connect(self.table_widget.sub_wid.link_extractions)
|
self.joinExtractionAction.triggered.connect(self.table_widget.sub_wid.link_extractions)
|
||||||
self.joinPCRAction.triggered.connect(self.table_widget.sub_wid.link_pcr)
|
self.joinPCRAction.triggered.connect(self.table_widget.sub_wid.link_pcr)
|
||||||
@@ -192,7 +189,6 @@ class App(QMainWindow):
|
|||||||
# TODO: Change this to the Pydantic version.
|
# TODO: Change this to the Pydantic version.
|
||||||
def manage_orgs(self):
|
def manage_orgs(self):
|
||||||
from frontend.widgets.omni_manager_pydant import ManagerWindow as ManagerWindowPyd
|
from frontend.widgets.omni_manager_pydant import ManagerWindow as ManagerWindowPyd
|
||||||
# dlg = ManagerWindow(parent=self, object_type=Organization, extras=[], add_edit='edit', managers=set())
|
|
||||||
dlg = ManagerWindowPyd(parent=self, object_type=Organization, extras=[], add_edit='edit', managers=set())
|
dlg = ManagerWindowPyd(parent=self, object_type=Organization, extras=[], add_edit='edit', managers=set())
|
||||||
if dlg.exec():
|
if dlg.exec():
|
||||||
new_org = dlg.parse_form()
|
new_org = dlg.parse_form()
|
||||||
@@ -202,10 +198,10 @@ class App(QMainWindow):
|
|||||||
from frontend.widgets.omni_manager_pydant import ManagerWindow as ManagerWindowPyd
|
from frontend.widgets.omni_manager_pydant import ManagerWindow as ManagerWindowPyd
|
||||||
dlg = ManagerWindowPyd(parent=self, object_type=KitType, extras=[], add_edit='edit', managers=set())
|
dlg = ManagerWindowPyd(parent=self, object_type=KitType, extras=[], add_edit='edit', managers=set())
|
||||||
if dlg.exec():
|
if dlg.exec():
|
||||||
logger.debug("\n\nBeginning parsing\n\n")
|
# logger.debug("\n\nBeginning parsing\n\n")
|
||||||
output = dlg.parse_form()
|
output = dlg.parse_form()
|
||||||
logger.debug(f"Kit output: {pformat(output.__dict__)}")
|
# logger.debug(f"Kit output: {pformat(output.__dict__)}")
|
||||||
logger.debug("\n\nBeginning transformation\n\n")
|
# logger.debug("\n\nBeginning transformation\n\n")
|
||||||
sql = output.to_sql()
|
sql = output.to_sql()
|
||||||
assert isinstance(sql, KitType)
|
assert isinstance(sql, KitType)
|
||||||
sql.save()
|
sql.save()
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"""
|
"""
|
||||||
Pane showing BC control concentrations summary.
|
Pane showing BC control concentrations summary.
|
||||||
"""
|
"""
|
||||||
from PyQt6.QtWidgets import QWidget, QPushButton, QCheckBox, QLabel
|
from PyQt6.QtWidgets import QWidget, QPushButton, QLabel
|
||||||
from .info_tab import InfoPane
|
from .info_tab import InfoPane
|
||||||
from backend.excel.reports import ConcentrationMaker
|
from backend.excel.reports import ConcentrationMaker
|
||||||
from frontend.visualizations.concentrations_chart import ConcentrationsChart
|
from frontend.visualizations.concentrations_chart import ConcentrationsChart
|
||||||
@@ -25,6 +25,7 @@ class Concentrations(InfoPane):
|
|||||||
self.pos_neg = CheckableComboBox(parent=self)
|
self.pos_neg = CheckableComboBox(parent=self)
|
||||||
self.pos_neg.model().itemChanged.connect(self.update_data)
|
self.pos_neg.model().itemChanged.connect(self.update_data)
|
||||||
self.pos_neg.setEditable(False)
|
self.pos_neg.setEditable(False)
|
||||||
|
self.pos_neg.addItem("Select", header=True)
|
||||||
self.pos_neg.addItem("Positive")
|
self.pos_neg.addItem("Positive")
|
||||||
self.pos_neg.addItem("Negative")
|
self.pos_neg.addItem("Negative")
|
||||||
self.pos_neg.addItem("Samples", start_checked=False)
|
self.pos_neg.addItem("Samples", start_checked=False)
|
||||||
@@ -46,7 +47,6 @@ class Concentrations(InfoPane):
|
|||||||
super().update_data()
|
super().update_data()
|
||||||
months = self.diff_month(self.start_date, self.end_date)
|
months = self.diff_month(self.start_date, self.end_date)
|
||||||
# logger.debug(f"Box checked: {self.all_box.isChecked()}")
|
# logger.debug(f"Box checked: {self.all_box.isChecked()}")
|
||||||
# chart_settings = dict(start_date=self.start_date, end_date=self.end_date, controls_only=self.all_box.isChecked())
|
|
||||||
chart_settings = dict(start_date=self.start_date, end_date=self.end_date,
|
chart_settings = dict(start_date=self.start_date, end_date=self.end_date,
|
||||||
include=include)
|
include=include)
|
||||||
self.report_obj = ConcentrationMaker(**chart_settings)
|
self.report_obj = ConcentrationMaker(**chart_settings)
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ class ControlsViewer(InfoPane):
|
|||||||
parent=self,
|
parent=self,
|
||||||
months=months
|
months=months
|
||||||
)
|
)
|
||||||
logger.debug(f"Chart settings: {chart_settings}")
|
# logger.debug(f"Chart settings: {chart_settings}")
|
||||||
self.fig = self.archetype.instance_class.make_chart(chart_settings=chart_settings, parent=self, ctx=self.app.ctx)
|
self.fig = self.archetype.instance_class.make_chart(chart_settings=chart_settings, parent=self, ctx=self.app.ctx)
|
||||||
self.report_obj = ChartReportMaker(df=self.fig.df, sheet_name=self.archetype.name)
|
self.report_obj = ChartReportMaker(df=self.fig.df, sheet_name=self.archetype.name)
|
||||||
if issubclass(self.fig.__class__, CustomFigure):
|
if issubclass(self.fig.__class__, CustomFigure):
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
from PyQt6.QtWidgets import (
|
from PyQt6.QtWidgets import (
|
||||||
QLabel, QVBoxLayout, QDialog,
|
QVBoxLayout, QDialog, QDialogButtonBox
|
||||||
QDialogButtonBox, QMessageBox, QComboBox
|
|
||||||
)
|
)
|
||||||
from .misc import CheckableComboBox, StartEndDatePicker
|
from .misc import CheckableComboBox, StartEndDatePicker
|
||||||
from backend.db import SubmissionType
|
from backend.db import SubmissionType
|
||||||
@@ -28,7 +27,8 @@ class DateTypePicker(QDialog):
|
|||||||
self.setLayout(self.layout)
|
self.setLayout(self.layout)
|
||||||
|
|
||||||
def parse_form(self):
|
def parse_form(self):
|
||||||
sub_types = [self.typepicker.itemText(i) for i in range(self.typepicker.count()) if self.typepicker.itemChecked(i)]
|
# sub_types = [self.typepicker.itemText(i) for i in range(self.typepicker.count()) if self.typepicker.itemChecked(i)]
|
||||||
|
sub_types = self.typepicker.get_checked()
|
||||||
start_date = self.datepicker.start_date.date().toPyDate()
|
start_date = self.datepicker.start_date.date().toPyDate()
|
||||||
end_date = self.datepicker.end_date.date().toPyDate()
|
end_date = self.datepicker.end_date.date().toPyDate()
|
||||||
return dict(submissiontype=sub_types, start_date=start_date, end_date=end_date)
|
return dict(submissiontype=sub_types, start_date=start_date, end_date=end_date)
|
||||||
|
|||||||
@@ -74,10 +74,10 @@ class EquipmentUsage(QDialog):
|
|||||||
self.layout.addWidget(self.check, 0, 0)
|
self.layout.addWidget(self.check, 0, 0)
|
||||||
self.check.stateChanged.connect(self.check_all)
|
self.check.stateChanged.connect(self.check_all)
|
||||||
for iii, item in enumerate(["Role", "Equipment", "Process", "Tips"], start=1):
|
for iii, item in enumerate(["Role", "Equipment", "Process", "Tips"], start=1):
|
||||||
l = QLabel(item)
|
label = QLabel(item)
|
||||||
l.setMaximumWidth(200)
|
label.setMaximumWidth(200)
|
||||||
l.setMinimumWidth(200)
|
label.setMinimumWidth(200)
|
||||||
self.layout.addWidget(l, 0, iii, alignment=Qt.AlignmentFlag.AlignRight)
|
self.layout.addWidget(label, 0, iii, alignment=Qt.AlignmentFlag.AlignRight)
|
||||||
self.setLayout(self.layout)
|
self.setLayout(self.layout)
|
||||||
|
|
||||||
def check_all(self):
|
def check_all(self):
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"""
|
"""
|
||||||
A pane to show info e.g. cost reports and turnaround times.
|
A pane to show info e.g. cost reports and turnaround times.
|
||||||
"""
|
"""
|
||||||
from datetime import date, datetime
|
from datetime import date
|
||||||
from PyQt6.QtCore import QSignalBlocker
|
from PyQt6.QtCore import QSignalBlocker
|
||||||
from PyQt6.QtWebEngineWidgets import QWebEngineView
|
from PyQt6.QtWebEngineWidgets import QWebEngineView
|
||||||
from PyQt6.QtWidgets import QWidget, QGridLayout
|
from PyQt6.QtWidgets import QWidget, QGridLayout
|
||||||
@@ -32,11 +32,9 @@ class InfoPane(QWidget):
|
|||||||
@report_result
|
@report_result
|
||||||
def update_data(self, *args, **kwargs):
|
def update_data(self, *args, **kwargs):
|
||||||
report = Report()
|
report = Report()
|
||||||
# self.start_date = self.datepicker.start_date.date().toPyDate()
|
|
||||||
# self.end_date = self.datepicker.end_date.date().toPyDate()
|
|
||||||
self.start_date = self.datepicker.start_date.date().toPyDate()
|
self.start_date = self.datepicker.start_date.date().toPyDate()
|
||||||
self.end_date = self.datepicker.end_date.date().toPyDate()
|
self.end_date = self.datepicker.end_date.date().toPyDate()
|
||||||
logger.debug(f"Start date: {self.start_date}, End date: {self.end_date}")
|
# logger.debug(f"Start date: {self.start_date}, End date: {self.end_date}")
|
||||||
if self.datepicker.start_date.date() > self.datepicker.end_date.date():
|
if self.datepicker.start_date.date() > self.datepicker.end_date.date():
|
||||||
lastmonth = self.datepicker.end_date.date().addDays(-31)
|
lastmonth = self.datepicker.end_date.date().addDays(-31)
|
||||||
msg = f"Start date after end date is not allowed! Setting to {lastmonth.toString()}."
|
msg = f"Start date after end date is not allowed! Setting to {lastmonth.toString()}."
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ class StartEndDatePicker(QWidget):
|
|||||||
|
|
||||||
class CheckableComboBox(QComboBox):
|
class CheckableComboBox(QComboBox):
|
||||||
# once there is a checkState set, it is rendered
|
# once there is a checkState set, it is rendered
|
||||||
# here we assume default Unchecked
|
# here we assume default checked
|
||||||
|
|
||||||
def addItem(self, item, header: bool = False, start_checked: bool = True):
|
def addItem(self, item, header: bool = False, start_checked: bool = True):
|
||||||
super(CheckableComboBox, self).addItem(item)
|
super(CheckableComboBox, self).addItem(item)
|
||||||
@@ -64,8 +64,7 @@ class CheckableComboBox(QComboBox):
|
|||||||
self.updated.emit()
|
self.updated.emit()
|
||||||
|
|
||||||
def get_checked(self):
|
def get_checked(self):
|
||||||
checked = [self.itemText(i) for i in range(self.count()) if self.itemChecked(i)]
|
return [self.itemText(i) for i in range(self.count()) if self.itemChecked(i)]
|
||||||
return checked
|
|
||||||
|
|
||||||
|
|
||||||
class Pagifier(QWidget):
|
class Pagifier(QWidget):
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
"""
|
"""
|
||||||
A widget to handle adding/updating any database object.
|
A widget to handle adding/updating any database object.
|
||||||
"""
|
"""
|
||||||
from copy import deepcopy
|
|
||||||
from datetime import date
|
from datetime import date
|
||||||
from pprint import pformat
|
from pprint import pformat
|
||||||
from typing import Any, Tuple
|
from typing import Any, Tuple
|
||||||
@@ -11,7 +10,7 @@ from PyQt6.QtWidgets import (
|
|||||||
QCheckBox
|
QCheckBox
|
||||||
)
|
)
|
||||||
from sqlalchemy import String, TIMESTAMP, INTEGER, FLOAT, JSON, BLOB
|
from sqlalchemy import String, TIMESTAMP, INTEGER, FLOAT, JSON, BLOB
|
||||||
from sqlalchemy.orm import InstrumentedAttribute, ColumnProperty
|
from sqlalchemy.orm import ColumnProperty
|
||||||
import logging
|
import logging
|
||||||
from sqlalchemy.orm.relationships import _RelationshipDeclared
|
from sqlalchemy.orm.relationships import _RelationshipDeclared
|
||||||
from tools import Report, report_result
|
from tools import Report, report_result
|
||||||
@@ -23,18 +22,11 @@ class AddEdit(QDialog):
|
|||||||
|
|
||||||
def __init__(self, parent, instance: Any | None = None, managers: set = set()):
|
def __init__(self, parent, instance: Any | None = None, managers: set = set()):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
logger.debug(f"Managers: {managers}")
|
# logger.debug(f"Managers: {managers}")
|
||||||
self.instance = instance
|
self.instance = instance
|
||||||
self.object_type = instance.__class__
|
self.object_type = instance.__class__
|
||||||
# self.managers = deepcopy(managers)
|
|
||||||
self.managers = managers
|
self.managers = managers
|
||||||
# if instance.level < 2:
|
# logger.debug(f"Managers: {managers}")
|
||||||
# try:
|
|
||||||
# logger.debug(f"Parent instance: {self.parent().instance}")
|
|
||||||
# self.managers.add(self.parent().instance)
|
|
||||||
# except AttributeError:
|
|
||||||
# pass
|
|
||||||
logger.debug(f"Managers: {managers}")
|
|
||||||
self.layout = QGridLayout(self)
|
self.layout = QGridLayout(self)
|
||||||
QBtn = QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel
|
QBtn = QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel
|
||||||
self.buttonBox = QDialogButtonBox(QBtn)
|
self.buttonBox = QDialogButtonBox(QBtn)
|
||||||
@@ -72,11 +64,11 @@ class AddEdit(QDialog):
|
|||||||
report = Report()
|
report = Report()
|
||||||
parsed = {result[0].strip(":"): result[1] for result in
|
parsed = {result[0].strip(":"): result[1] for result in
|
||||||
[item.parse_form() for item in self.findChildren(EditProperty)] if result[0]}
|
[item.parse_form() for item in self.findChildren(EditProperty)] if result[0]}
|
||||||
logger.debug(f"Parsed form: {parsed}")
|
# logger.debug(f"Parsed form: {parsed}")
|
||||||
model = self.object_type.pydantic_model
|
model = self.object_type.pydantic_model
|
||||||
logger.debug(f"Model type: {model.__name__}")
|
# logger.debug(f"Model type: {model.__name__}")
|
||||||
if model.__name__ == "PydElastic":
|
if model.__name__ == "PydElastic":
|
||||||
logger.debug(f"We have an elastic model.")
|
# logger.debug(f"We have an elastic model.")
|
||||||
parsed['instance'] = self.instance
|
parsed['instance'] = self.instance
|
||||||
# NOTE: Hand-off to pydantic model for validation.
|
# NOTE: Hand-off to pydantic model for validation.
|
||||||
# NOTE: Also, why am I not just using the toSQL method here. I could write one for contacts.
|
# NOTE: Also, why am I not just using the toSQL method here. I could write one for contacts.
|
||||||
@@ -120,7 +112,7 @@ class EditProperty(QWidget):
|
|||||||
# logger.debug(self.parent().managers)
|
# logger.debug(self.parent().managers)
|
||||||
for manager in self.parent().managers:
|
for manager in self.parent().managers:
|
||||||
if self.name in manager.aliases:
|
if self.name in manager.aliases:
|
||||||
logger.debug(f"Name: {self.name} is in aliases: {manager.aliases}")
|
# logger.debug(f"Name: {self.name} is in aliases: {manager.aliases}")
|
||||||
choices = [manager.name]
|
choices = [manager.name]
|
||||||
self.widget.setEnabled(False)
|
self.widget.setEnabled(False)
|
||||||
break
|
break
|
||||||
@@ -139,7 +131,7 @@ class EditProperty(QWidget):
|
|||||||
self.widget.addItems(choices)
|
self.widget.addItems(choices)
|
||||||
|
|
||||||
def column_property_set(self, column_property, value=None):
|
def column_property_set(self, column_property, value=None):
|
||||||
logger.debug(f"Column Property: {column_property['class_attr'].expression} {column_property}, Value: {value}")
|
# logger.debug(f"Column Property: {column_property['class_attr'].expression} {column_property}, Value: {value}")
|
||||||
match column_property['class_attr'].expression.type:
|
match column_property['class_attr'].expression.type:
|
||||||
case String():
|
case String():
|
||||||
if value is None:
|
if value is None:
|
||||||
@@ -184,7 +176,8 @@ class EditProperty(QWidget):
|
|||||||
check = self.widget
|
check = self.widget
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
return None, None
|
return None, None
|
||||||
match self.widget:
|
# match self.widget
|
||||||
|
match check:
|
||||||
case QLineEdit():
|
case QLineEdit():
|
||||||
value = self.widget.text()
|
value = self.widget.text()
|
||||||
case QDateEdit():
|
case QDateEdit():
|
||||||
@@ -198,5 +191,3 @@ class EditProperty(QWidget):
|
|||||||
case _:
|
case _:
|
||||||
value = None
|
value = None
|
||||||
return self.objectName(), value
|
return self.objectName(), value
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,594 +0,0 @@
|
|||||||
"""
|
|
||||||
Provides a screen for managing all attributes of a database object.
|
|
||||||
"""
|
|
||||||
import json, logging
|
|
||||||
from pprint import pformat
|
|
||||||
from typing import Any, List, Literal
|
|
||||||
from PyQt6.QtCore import QSortFilterProxyModel, Qt
|
|
||||||
from PyQt6.QtGui import QAction, QCursor
|
|
||||||
from PyQt6.QtWidgets import (
|
|
||||||
QLabel, QDialog,
|
|
||||||
QTableView, QWidget, QLineEdit, QGridLayout, QComboBox, QPushButton, QDialogButtonBox, QDateEdit, QMenu,
|
|
||||||
QDoubleSpinBox, QSpinBox, QCheckBox, QTextEdit, QVBoxLayout, QHBoxLayout
|
|
||||||
)
|
|
||||||
from sqlalchemy import String, TIMESTAMP, FLOAT, INTEGER, JSON, BLOB
|
|
||||||
from sqlalchemy.orm import InstrumentedAttribute
|
|
||||||
from sqlalchemy.orm.properties import ColumnProperty
|
|
||||||
from sqlalchemy.orm.relationships import _RelationshipDeclared
|
|
||||||
from pandas import DataFrame
|
|
||||||
from backend import db
|
|
||||||
from tools import check_object_in_manager
|
|
||||||
from .omni_search import SearchBox
|
|
||||||
from frontend.widgets.submission_table import pandasModel
|
|
||||||
|
|
||||||
logger = logging.getLogger(f"submissions.{__name__}")
|
|
||||||
|
|
||||||
|
|
||||||
class ManagerWindow(QDialog):
|
|
||||||
"""
|
|
||||||
Initially this is a window to manage Organization Contacts, but hope to abstract it more later.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, parent,
|
|
||||||
object_type: Any,
|
|
||||||
extras: List[str],
|
|
||||||
manager: Any | None = None,
|
|
||||||
add_edit: Literal['add', 'edit'] = 'edit',
|
|
||||||
**kwargs):
|
|
||||||
super().__init__(parent)
|
|
||||||
self.class_object = self.original_type = object_type
|
|
||||||
self.add_edit = add_edit
|
|
||||||
# NOTE: Should I pass in an instance?
|
|
||||||
self.instance = None
|
|
||||||
if manager is None:
|
|
||||||
try:
|
|
||||||
self.manager = self.parent().instance
|
|
||||||
except AttributeError:
|
|
||||||
self.manager = None
|
|
||||||
else:
|
|
||||||
self.manager = manager
|
|
||||||
# logger.debug(f"Managers: {managers}")
|
|
||||||
self.extras = extras
|
|
||||||
self.context = kwargs
|
|
||||||
self.layout = QGridLayout(self)
|
|
||||||
QBtn = QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel
|
|
||||||
self.buttonBox = QDialogButtonBox(QBtn)
|
|
||||||
self.buttonBox.accepted.connect(self.accept)
|
|
||||||
self.buttonBox.rejected.connect(self.reject)
|
|
||||||
self.setMinimumSize(600, 600)
|
|
||||||
sub_classes = ["Any"] + [cls.__name__ for cls in self.class_object.__subclasses__()]
|
|
||||||
if len(sub_classes) > 1:
|
|
||||||
self.sub_class = QComboBox(self)
|
|
||||||
self.sub_class.setObjectName("sub_class")
|
|
||||||
self.sub_class.addItems(sub_classes)
|
|
||||||
self.sub_class.currentTextChanged.connect(self.update_options)
|
|
||||||
self.sub_class.setEditable(False)
|
|
||||||
self.sub_class.setMinimumWidth(self.minimumWidth())
|
|
||||||
self.layout.addWidget(self.sub_class, 0, 0)
|
|
||||||
else:
|
|
||||||
self.sub_class = None
|
|
||||||
if self.add_edit == "edit":
|
|
||||||
self.options = QComboBox(self)
|
|
||||||
self.options.setObjectName("options")
|
|
||||||
self.update_options()
|
|
||||||
else:
|
|
||||||
self.update_data(initial=True)
|
|
||||||
self.setLayout(self.layout)
|
|
||||||
self.setWindowTitle(f"Manage {self.class_object.__name__} - Manager: {self.manager}")
|
|
||||||
|
|
||||||
def update_options(self) -> None:
|
|
||||||
"""
|
|
||||||
Changes form inputs based on sample type
|
|
||||||
"""
|
|
||||||
# logger.debug(f"Instance: {self.instance}")
|
|
||||||
if self.sub_class:
|
|
||||||
self.class_object = getattr(db, self.sub_class.currentText())
|
|
||||||
# logger.debug(f"From update options, managers: {self.managers}")
|
|
||||||
try:
|
|
||||||
query_kwargs = {self.parent().instance.query_alias: self.parent().instance}
|
|
||||||
except AttributeError as e:
|
|
||||||
# logger.debug(f"Couldn't set query kwargs due to: {e}")
|
|
||||||
query_kwargs = {}
|
|
||||||
# logger.debug(f"Query kwargs: {query_kwargs}")
|
|
||||||
options = [item.name for item in self.class_object.query(**query_kwargs)]
|
|
||||||
# logger.debug(f"self.class_object: {self.class_object}")
|
|
||||||
if self.instance:
|
|
||||||
try:
|
|
||||||
inserter = options.pop(options.index(self.instance.name))
|
|
||||||
except ValueError:
|
|
||||||
inserter = self.instance.name
|
|
||||||
options.insert(0, inserter)
|
|
||||||
self.options.clear()
|
|
||||||
self.options.addItems(options)
|
|
||||||
self.options.setEditable(False)
|
|
||||||
self.options.setMinimumWidth(self.minimumWidth())
|
|
||||||
self.layout.addWidget(self.options, 1, 0, 1, 1)
|
|
||||||
self.add_button = QPushButton("Add New")
|
|
||||||
self.layout.addWidget(self.add_button, 1, 1, 1, 1)
|
|
||||||
self.add_button.clicked.connect(self.add_new)
|
|
||||||
self.options.currentTextChanged.connect(self.update_data)
|
|
||||||
# logger.debug(f"Instance: {self.instance}")
|
|
||||||
self.update_data()
|
|
||||||
|
|
||||||
def update_data(self, initial: bool = False) -> None:
|
|
||||||
"""
|
|
||||||
Performs updating of widgets on first run and after options change.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
None
|
|
||||||
"""
|
|
||||||
# NOTE: Remove all old widgets.
|
|
||||||
deletes = [item for item in self.findChildren(EditProperty)] + \
|
|
||||||
[item for item in self.findChildren(EditRelationship)] + \
|
|
||||||
[item for item in self.findChildren(QDialogButtonBox)]
|
|
||||||
for item in deletes:
|
|
||||||
item.setParent(None)
|
|
||||||
# logger.debug(f"Current options text lower: {self.options.currentText().lower()}")
|
|
||||||
if self.add_edit == "edit" and initial:
|
|
||||||
# logger.debug(f"Querying with {self.options.currentText()}")
|
|
||||||
self.instance = self.class_object.query(name=self.options.currentText(), limit=1)
|
|
||||||
# logger.debug(f"Instance: {self.instance}")
|
|
||||||
if not self.instance:
|
|
||||||
self.instance = self.class_object()
|
|
||||||
# logger.debug(f"self.instance: {self.instance}")
|
|
||||||
fields = self.instance.omnigui_instance_dict
|
|
||||||
for key, field in fields.items():
|
|
||||||
try:
|
|
||||||
value = getattr(self.instance, key)
|
|
||||||
except AttributeError:
|
|
||||||
value = None
|
|
||||||
match field['class_attr'].property:
|
|
||||||
# NOTE: ColumnProperties will be directly edited.
|
|
||||||
case ColumnProperty():
|
|
||||||
# NOTE: field.property.expression.type gives db column type eg. STRING or TIMESTAMP
|
|
||||||
widget = EditProperty(self, key=key, column_type=field,
|
|
||||||
value=value)
|
|
||||||
# NOTE: RelationshipDeclareds will be given a list of existing related objects.
|
|
||||||
case _RelationshipDeclared():
|
|
||||||
if key != "submissions":
|
|
||||||
# NOTE: field.comparator.class_object.class_ gives the relationship class
|
|
||||||
widget = EditRelationship(self, key=key, class_object=field['class_attr'].comparator.entity.class_,
|
|
||||||
value=value)
|
|
||||||
else:
|
|
||||||
continue
|
|
||||||
case _:
|
|
||||||
continue
|
|
||||||
if widget:
|
|
||||||
self.layout.addWidget(widget, self.layout.rowCount(), 0, 1, 2)
|
|
||||||
# NOTE: Add OK|Cancel to bottom of dialog.
|
|
||||||
self.layout.addWidget(self.buttonBox, self.layout.rowCount(), 0, 1, 2)
|
|
||||||
|
|
||||||
def parse_form(self) -> Any:
|
|
||||||
"""
|
|
||||||
Returns the instance associated with this window.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Any: The instance with updated fields.
|
|
||||||
"""
|
|
||||||
results = [item.parse_form() for item in self.findChildren(EditProperty)]
|
|
||||||
for result in results:
|
|
||||||
# logger.debug(f"Incoming result: {result}")
|
|
||||||
setattr(self.instance, result['field'], result['value'])
|
|
||||||
# logger.debug(f"Set result: {getattr(self.instance, result['field'])}")
|
|
||||||
results = [item.parse_form() for item in self.findChildren(EditRelationship)]
|
|
||||||
for result in results:
|
|
||||||
logger.debug(f"Incoming result: {result}")
|
|
||||||
if not getattr(self.instance, result['field']):
|
|
||||||
setattr(self.instance, result['field'], result['value'])
|
|
||||||
logger.debug(f"Set result: {getattr(self.instance, result['field'])}")
|
|
||||||
logger.debug(f"Instance coming from parsed form: {self.instance.__dict__}")
|
|
||||||
return self.instance
|
|
||||||
|
|
||||||
def add_new(self):
|
|
||||||
new_instance = self.class_object()
|
|
||||||
self.instance = new_instance
|
|
||||||
self.update_options()
|
|
||||||
|
|
||||||
def add_to_json(self, caller_child=None):
|
|
||||||
try:
|
|
||||||
name = caller_child.objectName()
|
|
||||||
except AttributeError:
|
|
||||||
name = "No Caller"
|
|
||||||
jsonedit = JsonEditScreen(parent=self, key=name)
|
|
||||||
if jsonedit.exec():
|
|
||||||
data = jsonedit.parse_form()
|
|
||||||
logger.debug(f"Data: {pformat(data)}")
|
|
||||||
current_value = getattr(self.instance, name)
|
|
||||||
if isinstance(jsonedit.json_field, dict):
|
|
||||||
value = data
|
|
||||||
elif isinstance(jsonedit.json_field, list):
|
|
||||||
if isinstance(data, list):
|
|
||||||
value = current_value + data
|
|
||||||
else:
|
|
||||||
value = current_value + [data]
|
|
||||||
setattr(self.instance, name, value)
|
|
||||||
|
|
||||||
def toggle_textedit(self, caller_child=None):
|
|
||||||
already_exists = self.findChildren(LargeTextEdit)
|
|
||||||
if not already_exists:
|
|
||||||
try:
|
|
||||||
name = caller_child.objectName()
|
|
||||||
except AttributeError:
|
|
||||||
name = "No Caller"
|
|
||||||
logger.debug(f"Name: {name}, instance: {self.instance}")
|
|
||||||
textedit = LargeTextEdit(parent=self, key=name)
|
|
||||||
self.layout.addWidget(textedit, 1, self.layout.columnCount(), self.layout.rowCount() - 1, 1)
|
|
||||||
data = getattr(self.instance, name)
|
|
||||||
logger.debug(f"Data: {data}")
|
|
||||||
data = json.dumps(data, indent=4)
|
|
||||||
textedit.widget.setText(data)
|
|
||||||
else:
|
|
||||||
for item in already_exists:
|
|
||||||
item.setParent(None)
|
|
||||||
item.destroy()
|
|
||||||
|
|
||||||
|
|
||||||
class EditProperty(QWidget):
|
|
||||||
|
|
||||||
def __init__(self, parent: ManagerWindow, key: str, column_type: Any, value):
|
|
||||||
super().__init__(parent)
|
|
||||||
self.label = QLabel(key.title().replace("_", " "))
|
|
||||||
self.layout = QGridLayout()
|
|
||||||
self.layout.addWidget(self.label, 0, 0, 1, 1)
|
|
||||||
self.setObjectName(key)
|
|
||||||
logger.debug(f"Column type for {key}: {column_type['class_attr'].property.expression.type}")
|
|
||||||
match column_type['class_attr'].property.expression.type:
|
|
||||||
case String():
|
|
||||||
self.widget = QLineEdit(self)
|
|
||||||
self.widget.setText(value)
|
|
||||||
case INTEGER():
|
|
||||||
if isinstance(column_type['instance_attr'], bool):
|
|
||||||
self.widget = QCheckBox()
|
|
||||||
self.widget.setChecked(value)
|
|
||||||
else:
|
|
||||||
if value is None:
|
|
||||||
value = 0
|
|
||||||
self.widget = QSpinBox()
|
|
||||||
self.widget.setMaximum(999)
|
|
||||||
self.widget.setValue(value)
|
|
||||||
case FLOAT():
|
|
||||||
if not value:
|
|
||||||
value = 0.0
|
|
||||||
self.widget = QDoubleSpinBox()
|
|
||||||
self.widget.setMaximum(999.99)
|
|
||||||
self.widget.setValue(value)
|
|
||||||
case TIMESTAMP():
|
|
||||||
self.widget = QDateEdit(self)
|
|
||||||
self.widget.setDate(value)
|
|
||||||
case JSON():
|
|
||||||
self.widget = JsonEditButton(parent=self, key=key)
|
|
||||||
self.widget.viewButton.clicked.connect(lambda: self.parent().toggle_textedit(self.widget))
|
|
||||||
self.widget.addButton.clicked.connect(lambda: self.parent().add_to_json(self.widget))
|
|
||||||
case BLOB():
|
|
||||||
self.widget = QLabel("BLOB Under construction")
|
|
||||||
case _:
|
|
||||||
self.widget = None
|
|
||||||
self.layout.addWidget(self.widget, 0, 1, 1, 3)
|
|
||||||
self.setLayout(self.layout)
|
|
||||||
|
|
||||||
def parse_form(self):
|
|
||||||
match self.widget:
|
|
||||||
case QLineEdit():
|
|
||||||
value = self.widget.text()
|
|
||||||
case QDateEdit():
|
|
||||||
value = self.widget.date()
|
|
||||||
case QSpinBox() | QDoubleSpinBox():
|
|
||||||
value = self.widget.value()
|
|
||||||
case QCheckBox():
|
|
||||||
value = self.widget.isChecked()
|
|
||||||
case _:
|
|
||||||
value = None
|
|
||||||
return dict(field=self.objectName(), value=value)
|
|
||||||
|
|
||||||
|
|
||||||
class EditRelationship(QWidget):
|
|
||||||
|
|
||||||
def __init__(self, parent, key: str, class_object: Any, value):
|
|
||||||
super().__init__(parent)
|
|
||||||
self.class_object = class_object #: The class of interest
|
|
||||||
self.setParent(parent)
|
|
||||||
# logger.debug(f"Edit relationship class_object: {self.class_object}")
|
|
||||||
self.label = QLabel(key.title().replace("_", " "))
|
|
||||||
self.setObjectName(key) #: key is the name of the relationship this represents
|
|
||||||
self.relationship = getattr(self.parent().instance.__class__,
|
|
||||||
key) #: relationship object for type differentiation
|
|
||||||
# logger.debug(f"self.relationship: {self.relationship}")
|
|
||||||
# logger.debug(f"Relationship uses list: {self.relationship.property.uselist}")
|
|
||||||
# NOTE: value is a database object in this case.
|
|
||||||
# logger.debug(f"Data for edit relationship: {self.data}")
|
|
||||||
self.widget = QTableView()
|
|
||||||
self.add_button = QPushButton("Add New")
|
|
||||||
self.add_button.clicked.connect(self.add_new)
|
|
||||||
self.existing_button = QPushButton("Add Existing")
|
|
||||||
self.existing_button.clicked.connect(self.add_existing)
|
|
||||||
# self.existing_button.setEnabled(self.class_object.level == 1)
|
|
||||||
if not isinstance(value, list):
|
|
||||||
if value is not None:
|
|
||||||
value = [value]
|
|
||||||
else:
|
|
||||||
value = []
|
|
||||||
self.data = value
|
|
||||||
checked_manager, is_primary = check_object_in_manager(self.parent().manager, self.objectName())
|
|
||||||
if checked_manager:
|
|
||||||
logger.debug(f"Checked manager for {self.objectName()}: {checked_manager}")
|
|
||||||
logger.debug(f"Omni will inherit: {self.class_object.omni_inheritable} from {self.parent().class_object}")
|
|
||||||
if checked_manager is not None and not self.data and self.objectName() in self.parent().class_object.omni_inheritable:
|
|
||||||
logger.debug(f"Setting {checked_manager} in self.data")
|
|
||||||
self.data = [checked_manager]
|
|
||||||
if not self.relationship.property.uselist:
|
|
||||||
self.add_button.setEnabled(False)
|
|
||||||
self.existing_button.setEnabled(False)
|
|
||||||
if is_primary:
|
|
||||||
self.widget.setEnabled(False)
|
|
||||||
self.layout = QGridLayout()
|
|
||||||
self.layout.addWidget(self.label, 0, 0, 1, 5)
|
|
||||||
self.layout.addWidget(self.widget, 1, 0, 1, 8)
|
|
||||||
self.layout.addWidget(self.add_button, 0, 6, 1, 1, alignment=Qt.AlignmentFlag.AlignRight)
|
|
||||||
self.layout.addWidget(self.existing_button, 0, 7, 1, 1, alignment=Qt.AlignmentFlag.AlignRight)
|
|
||||||
self.setLayout(self.layout)
|
|
||||||
self.set_data()
|
|
||||||
|
|
||||||
def update_buttons(self):
|
|
||||||
if not self.relationship.property.uselist and len(self.data) >= 1:
|
|
||||||
logger.debug(f"Property {self.relationship} doesn't use list and data is of length: {len(self.data)}")
|
|
||||||
self.add_button.setEnabled(False)
|
|
||||||
self.existing_button.setEnabled(False)
|
|
||||||
else:
|
|
||||||
self.add_button.setEnabled(True)
|
|
||||||
self.existing_button.setEnabled(True)
|
|
||||||
|
|
||||||
def parse_row(self, x):
|
|
||||||
context = {item: x.sibling(x.row(), self.df.columns.get_loc(item)).data() for item in self.df.columns}
|
|
||||||
try:
|
|
||||||
object = self.class_object.query(**context)
|
|
||||||
except KeyError:
|
|
||||||
object = None
|
|
||||||
self.widget.doubleClicked.disconnect()
|
|
||||||
self.add_edit(instance=object)
|
|
||||||
|
|
||||||
def add_new(self, instance: Any = None):
|
|
||||||
# NOTE: if an existing instance is not being edited, create a new instance
|
|
||||||
if not instance:
|
|
||||||
instance = self.class_object()
|
|
||||||
manager = self.parent().manager
|
|
||||||
# logger.debug(f"Managers going into add new: {managers}")
|
|
||||||
dlg = ManagerWindow(self.parent(), object_type=instance.__class__, extras=[], manager=manager, add_edit="add")
|
|
||||||
if dlg.exec():
|
|
||||||
new_instance = dlg.parse_form()
|
|
||||||
# NOTE: My custom __setattr__ should take care of any list problems.
|
|
||||||
self.parent().instance.__setattr__(self.objectName(), new_instance)
|
|
||||||
self.parent().update_data()
|
|
||||||
|
|
||||||
def add_existing(self):
|
|
||||||
dlg = SearchBox(self, object_type=self.class_object, returnable=True, extras=[])
|
|
||||||
if dlg.exec():
|
|
||||||
rows = dlg.return_selected_rows()
|
|
||||||
for row in rows:
|
|
||||||
# logger.debug(f"Querying with {row}")
|
|
||||||
instance = self.class_object.query(**row)
|
|
||||||
# NOTE: My custom __setattr__ should take care of any list problems.
|
|
||||||
self.parent().instance.__setattr__(self.objectName(), instance)
|
|
||||||
self.parent().update_data()
|
|
||||||
|
|
||||||
def set_data(self) -> None:
|
|
||||||
"""
|
|
||||||
sets data in model
|
|
||||||
"""
|
|
||||||
logger.debug(f"Self.data: {self.data}")
|
|
||||||
try:
|
|
||||||
records = [{k: v['instance_attr'] for k, v in item.omnigui_instance_dict.items()} for item in self.data]
|
|
||||||
except AttributeError:
|
|
||||||
records = []
|
|
||||||
# logger.debug(f"Records: {records}")
|
|
||||||
self.df = DataFrame.from_records(records)
|
|
||||||
try:
|
|
||||||
self.columns_of_interest = [dict(name=item, column=self.df.columns.get_loc(item)) for item in self.extras]
|
|
||||||
except (KeyError, AttributeError):
|
|
||||||
self.columns_of_interest = []
|
|
||||||
try:
|
|
||||||
self.df['id'] = self.df['id'].apply(str)
|
|
||||||
self.df['id'] = self.df['id'].str.zfill(4)
|
|
||||||
except KeyError as e:
|
|
||||||
logger.error(f"Could not alter id to string due to KeyError: {e}")
|
|
||||||
proxy_model = QSortFilterProxyModel()
|
|
||||||
proxy_model.setSourceModel(pandasModel(self.df))
|
|
||||||
self.widget.setModel(proxy_model)
|
|
||||||
self.widget.resizeColumnsToContents()
|
|
||||||
self.widget.resizeRowsToContents()
|
|
||||||
self.widget.setSortingEnabled(True)
|
|
||||||
self.widget.doubleClicked.connect(self.parse_row)
|
|
||||||
self.update_buttons()
|
|
||||||
|
|
||||||
def contextMenuEvent(self, event):
|
|
||||||
"""
|
|
||||||
Creates actions for right click menu events.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
event (_type_): the item of interest
|
|
||||||
"""
|
|
||||||
if not self.widget.isEnabled():
|
|
||||||
logger.warning(f"{self.objectName()} is disabled.")
|
|
||||||
return
|
|
||||||
id = self.widget.selectionModel().currentIndex()
|
|
||||||
# NOTE: the overly complicated {column_name: row_value} dictionary construction
|
|
||||||
row_data = {self.df.columns[column]: self.widget.model().index(id.row(), column).data() for column in
|
|
||||||
range(self.widget.model().columnCount())}
|
|
||||||
logger.debug(f"Row data: {row_data}")
|
|
||||||
logger.debug(f"Attempting to grab {self.objectName()} from {self.parent().instance}")
|
|
||||||
object = getattr(self.parent().instance, self.objectName())
|
|
||||||
if isinstance(object, list):
|
|
||||||
object = next((item for item in object if item.check_all_attributes(attributes=row_data)), None)
|
|
||||||
logger.debug(f"Object of interest: {object}")
|
|
||||||
# logger.debug(object)
|
|
||||||
self.menu = QMenu(self)
|
|
||||||
try:
|
|
||||||
remove_action = QAction(f"Remove {object.name}", self)
|
|
||||||
except AttributeError:
|
|
||||||
remove_action = QAction(f"Remove object", self)
|
|
||||||
remove_action.triggered.connect(lambda: self.remove_item(object=object))
|
|
||||||
self.menu.addAction(remove_action)
|
|
||||||
try:
|
|
||||||
edit_action = QAction(f"Edit {object.name}", self)
|
|
||||||
except AttributeError:
|
|
||||||
edit_action = QAction(f"Edit object", self)
|
|
||||||
edit_action.triggered.connect(lambda: self.add_new(instance=object))
|
|
||||||
self.menu.addAction(edit_action)
|
|
||||||
self.menu.popup(QCursor.pos())
|
|
||||||
|
|
||||||
def remove_item(self, object):
|
|
||||||
logger.debug(f"Attempting to remove {object} from {self.parent().instance.__dict__}")
|
|
||||||
editor = getattr(self.parent().instance, self.objectName().lower())
|
|
||||||
logger.debug(f"Editor: {editor}")
|
|
||||||
if object == self.parent().manager:
|
|
||||||
logger.error(f"Can't remove manager object.")
|
|
||||||
return
|
|
||||||
try:
|
|
||||||
self.data.remove(object)
|
|
||||||
except (AttributeError, ValueError) as e:
|
|
||||||
logger.error(f"Could remove object from self.data due to: {e}")
|
|
||||||
self.data = []
|
|
||||||
try:
|
|
||||||
logger.debug(f"Using remove technique")
|
|
||||||
editor.remove(object)
|
|
||||||
except AttributeError as e:
|
|
||||||
logger.error(f"Remove failed using set to None for {self.objectName().lower()}.")
|
|
||||||
setattr(self.parent().instance, self.objectName().lower(), None)
|
|
||||||
except ValueError as e:
|
|
||||||
logger.error(f"Remove failed for {self.objectName().lower()} due to {e}.")
|
|
||||||
self.parent().instance.save()
|
|
||||||
self.set_data()
|
|
||||||
|
|
||||||
def parse_form(self):
|
|
||||||
return dict(field=self.objectName(), value=self.data)
|
|
||||||
|
|
||||||
|
|
||||||
class JsonEditButton(QWidget):
|
|
||||||
|
|
||||||
def __init__(self, parent, key: str):
|
|
||||||
super().__init__(parent)
|
|
||||||
self.setParent(parent)
|
|
||||||
self.setObjectName(key)
|
|
||||||
self.addButton = QPushButton("Add Entry", parent=self)
|
|
||||||
self.viewButton = QPushButton("View >>>", parent=self)
|
|
||||||
self.layout = QGridLayout()
|
|
||||||
self.layout.addWidget(self.addButton, 0, 0)
|
|
||||||
self.layout.addWidget(self.viewButton, 0, 1)
|
|
||||||
self.setLayout(self.layout)
|
|
||||||
|
|
||||||
|
|
||||||
class JsonEditScreen(QDialog):
|
|
||||||
|
|
||||||
def __init__(self, parent, key: str):
|
|
||||||
super().__init__(parent)
|
|
||||||
self.class_obj = parent.class_object
|
|
||||||
self.layout = QGridLayout()
|
|
||||||
self.setWindowTitle(key)
|
|
||||||
self.json_field = self.class_obj.json_edit_fields
|
|
||||||
match self.json_field:
|
|
||||||
case dict():
|
|
||||||
for key, value in self.json_field.items():
|
|
||||||
logger.debug(f"Key: {key}, Value: {value}")
|
|
||||||
row = self.layout.rowCount()
|
|
||||||
self.layout.addWidget(QLabel(key), row, 0)
|
|
||||||
match value:
|
|
||||||
case "int":
|
|
||||||
self.widget = QSpinBox()
|
|
||||||
case "str":
|
|
||||||
self.widget = QLineEdit()
|
|
||||||
case dict():
|
|
||||||
self.widget = DictionaryJsonSubEdit(parent=self, key=key, dic=value)
|
|
||||||
case _:
|
|
||||||
continue
|
|
||||||
self.widget.setObjectName(key)
|
|
||||||
self.layout.addWidget(self.widget, row, 1)
|
|
||||||
QBtn = QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel
|
|
||||||
self.buttonBox = QDialogButtonBox(QBtn)
|
|
||||||
self.buttonBox.accepted.connect(self.accept)
|
|
||||||
self.buttonBox.rejected.connect(self.reject)
|
|
||||||
self.layout.addWidget(self.buttonBox, self.layout.rowCount(), 0, 1, 2)
|
|
||||||
self.setLayout(self.layout)
|
|
||||||
|
|
||||||
def parse_form(self):
|
|
||||||
widgets = [item for item in self.findChildren(QWidget) if item.objectName() in self.json_field.keys()]
|
|
||||||
logger.debug(f"Widgets: {widgets}")
|
|
||||||
logger.debug(type(self.json_field))
|
|
||||||
if isinstance(self.json_field, dict):
|
|
||||||
output = {}
|
|
||||||
elif isinstance(self.json_field, list):
|
|
||||||
output = []
|
|
||||||
else:
|
|
||||||
raise ValueError(f"Inappropriate data type: {type(self.json_field)}")
|
|
||||||
for widget in widgets:
|
|
||||||
logger.debug(f"JsonEditScreen Widget: {widget}")
|
|
||||||
key = widget.objectName()
|
|
||||||
match widget:
|
|
||||||
case QSpinBox():
|
|
||||||
value = widget.value()
|
|
||||||
case QLineEdit():
|
|
||||||
value = widget.text()
|
|
||||||
case DictionaryJsonSubEdit():
|
|
||||||
value = widget.parse_form()
|
|
||||||
case _:
|
|
||||||
continue
|
|
||||||
if isinstance(self.json_field, dict):
|
|
||||||
output[key] = value
|
|
||||||
elif isinstance(self.json_field, list):
|
|
||||||
if isinstance(value, list):
|
|
||||||
output += value
|
|
||||||
else:
|
|
||||||
output.append(value)
|
|
||||||
else:
|
|
||||||
raise ValueError(f"Inappropriate data type: {type(self.json_field)}")
|
|
||||||
return output
|
|
||||||
|
|
||||||
|
|
||||||
class DictionaryJsonSubEdit(QWidget):
|
|
||||||
|
|
||||||
def __init__(self, parent, key, dic: dict):
|
|
||||||
super().__init__(parent)
|
|
||||||
self.layout = QHBoxLayout()
|
|
||||||
self.setObjectName(key)
|
|
||||||
self.data = dic
|
|
||||||
for key, value in self.data.items():
|
|
||||||
self.layout.addWidget(QLabel(key))
|
|
||||||
match value:
|
|
||||||
case "int":
|
|
||||||
self.widget = QSpinBox()
|
|
||||||
case "str":
|
|
||||||
self.widget = QLineEdit()
|
|
||||||
case dict():
|
|
||||||
self.widget = DictionaryJsonSubEdit(parent, key=key, dic=value)
|
|
||||||
self.widget.setObjectName(key)
|
|
||||||
self.layout.addWidget(self.widget)
|
|
||||||
self.setLayout(self.layout)
|
|
||||||
|
|
||||||
def parse_form(self):
|
|
||||||
widgets = [item for item in self.findChildren(QWidget) if item.objectName() in self.data.keys()]
|
|
||||||
logger.debug(f"Widgets: {widgets}")
|
|
||||||
output = {}
|
|
||||||
for widget in widgets:
|
|
||||||
logger.debug(f"DictionaryJsonSubEdit Widget: {widget}")
|
|
||||||
key = widget.objectName()
|
|
||||||
match widget:
|
|
||||||
case QSpinBox():
|
|
||||||
value = widget.value()
|
|
||||||
case QLineEdit():
|
|
||||||
value = widget.text()
|
|
||||||
case DictionaryJsonSubEdit():
|
|
||||||
value = widget.parse_form()
|
|
||||||
case _:
|
|
||||||
continue
|
|
||||||
output[key] = value
|
|
||||||
return output
|
|
||||||
|
|
||||||
|
|
||||||
class LargeTextEdit(QWidget):
|
|
||||||
|
|
||||||
def __init__(self, parent, key: str):
|
|
||||||
super().__init__(parent)
|
|
||||||
self.setParent(parent)
|
|
||||||
self.setObjectName(key)
|
|
||||||
self.widget = QTextEdit()
|
|
||||||
self.layout = QVBoxLayout()
|
|
||||||
self.layout.addWidget(self.widget)
|
|
||||||
self.setLayout(self.layout)
|
|
||||||
@@ -358,7 +358,6 @@ class EditRelationship(QWidget):
|
|||||||
obj = getattr(self.parent().omni_object, self.objectName())
|
obj = getattr(self.parent().omni_object, self.objectName())
|
||||||
if isinstance(obj, list):
|
if isinstance(obj, list):
|
||||||
logger.debug(f"This is a list")
|
logger.debug(f"This is a list")
|
||||||
# obj = obj[index]
|
|
||||||
try:
|
try:
|
||||||
# NOTE: Okay, this will not work for editing, since by definition not all attributes will line up.
|
# NOTE: Okay, this will not work for editing, since by definition not all attributes will line up.
|
||||||
# NOTE: Set items to search by in the Omni object itself?
|
# NOTE: Set items to search by in the Omni object itself?
|
||||||
@@ -389,7 +388,7 @@ class EditRelationship(QWidget):
|
|||||||
"""
|
"""
|
||||||
sets data in model
|
sets data in model
|
||||||
"""
|
"""
|
||||||
logger.debug(f"Self.data: {self.data}")
|
# logger.debug(f"Self.data: {self.data}")
|
||||||
try:
|
try:
|
||||||
records = [item.to_dataframe_dict() for item in self.data]
|
records = [item.to_dataframe_dict() for item in self.data]
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
|
|||||||
@@ -172,7 +172,7 @@ class SearchResults(QTableView):
|
|||||||
self.extras = extras + [item for item in deepcopy(self.object_type.searchables)]
|
self.extras = extras + [item for item in deepcopy(self.object_type.searchables)]
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
self.extras = extras
|
self.extras = extras
|
||||||
logger.debug(f"Extras: {self.extras}")
|
# logger.debug(f"Extras: {self.extras}")
|
||||||
|
|
||||||
def setData(self, df: DataFrame) -> None:
|
def setData(self, df: DataFrame) -> None:
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -1,14 +1,11 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import List, Generator
|
from typing import List
|
||||||
|
|
||||||
from PyQt6.QtCore import Qt, pyqtSlot
|
from PyQt6.QtCore import Qt, pyqtSlot
|
||||||
from PyQt6.QtWebChannel import QWebChannel
|
from PyQt6.QtWebChannel import QWebChannel
|
||||||
from PyQt6.QtWebEngineWidgets import QWebEngineView
|
from PyQt6.QtWebEngineWidgets import QWebEngineView
|
||||||
from PyQt6.QtWidgets import (QDialog, QPushButton, QVBoxLayout,
|
from PyQt6.QtWidgets import QDialog, QDialogButtonBox, QGridLayout
|
||||||
QDialogButtonBox, QTextEdit, QGridLayout)
|
|
||||||
|
|
||||||
from backend.validators import PydSubmission
|
from backend.validators import PydSubmission
|
||||||
from tools import get_application_from_parent, jinja_template_loading
|
from tools import get_application_from_parent, jinja_template_loading
|
||||||
|
|
||||||
@@ -16,6 +13,7 @@ env = jinja_template_loading()
|
|||||||
|
|
||||||
logger = logging.getLogger(f"submissions.{__name__}")
|
logger = logging.getLogger(f"submissions.{__name__}")
|
||||||
|
|
||||||
|
|
||||||
class SampleChecker(QDialog):
|
class SampleChecker(QDialog):
|
||||||
|
|
||||||
def __init__(self, parent, title:str, pyd: PydSubmission):
|
def __init__(self, parent, title:str, pyd: PydSubmission):
|
||||||
@@ -32,7 +30,6 @@ class SampleChecker(QDialog):
|
|||||||
self.channel = QWebChannel()
|
self.channel = QWebChannel()
|
||||||
self.channel.registerObject('backend', self)
|
self.channel.registerObject('backend', self)
|
||||||
# NOTE: Used to maintain javascript functions.
|
# NOTE: Used to maintain javascript functions.
|
||||||
# self.webview.page().setWebChannel(self.channel)
|
|
||||||
template = env.get_template("sample_checker.html")
|
template = env.get_template("sample_checker.html")
|
||||||
template_path = Path(template.environment.loader.__getattribute__("searchpath")[0])
|
template_path = Path(template.environment.loader.__getattribute__("searchpath")[0])
|
||||||
with open(template_path.joinpath("css", "styles.css"), "r") as f:
|
with open(template_path.joinpath("css", "styles.css"), "r") as f:
|
||||||
@@ -72,7 +69,3 @@ class SampleChecker(QDialog):
|
|||||||
sample['color'] = "black"
|
sample['color'] = "black"
|
||||||
output.append(sample)
|
output.append(sample)
|
||||||
return output
|
return output
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ class SubmissionFormContainer(QWidget):
|
|||||||
self.setStyleSheet('background-color: light grey;')
|
self.setStyleSheet('background-color: light grey;')
|
||||||
self.setAcceptDrops(True)
|
self.setAcceptDrops(True)
|
||||||
# NOTE: if import_drag is emitted, importSubmission will fire
|
# NOTE: if import_drag is emitted, importSubmission will fire
|
||||||
self.import_drag.connect(self.importSubmission)
|
self.import_drag.connect(lambda fname: self.import_submission_function(fname=fname))
|
||||||
|
|
||||||
def dragEnterEvent(self, event):
|
def dragEnterEvent(self, event):
|
||||||
"""
|
"""
|
||||||
@@ -90,17 +90,6 @@ class SubmissionFormContainer(QWidget):
|
|||||||
self.app.last_dir = fname.parent
|
self.app.last_dir = fname.parent
|
||||||
self.import_drag.emit(fname)
|
self.import_drag.emit(fname)
|
||||||
|
|
||||||
@report_result
|
|
||||||
def importSubmission(self, fname: Path | None = None):
|
|
||||||
"""
|
|
||||||
import submission from excel sheet into form
|
|
||||||
"""
|
|
||||||
self.app.raise_()
|
|
||||||
self.app.activateWindow()
|
|
||||||
report = Report()
|
|
||||||
self.import_submission_function(fname)
|
|
||||||
return report
|
|
||||||
|
|
||||||
@report_result
|
@report_result
|
||||||
def import_submission_function(self, fname: Path | None = None) -> Report:
|
def import_submission_function(self, fname: Path | None = None) -> Report:
|
||||||
"""
|
"""
|
||||||
@@ -112,6 +101,8 @@ class SubmissionFormContainer(QWidget):
|
|||||||
Returns:
|
Returns:
|
||||||
Report: Object to give results of import.
|
Report: Object to give results of import.
|
||||||
"""
|
"""
|
||||||
|
self.app.raise_()
|
||||||
|
self.app.activateWindow()
|
||||||
logger.info(f"\n\nStarting Import...\n\n")
|
logger.info(f"\n\nStarting Import...\n\n")
|
||||||
report = Report()
|
report = Report()
|
||||||
# NOTE: Clear any previous forms.
|
# NOTE: Clear any previous forms.
|
||||||
@@ -436,7 +427,7 @@ class SubmissionFormWidget(QWidget):
|
|||||||
if field is not None:
|
if field is not None:
|
||||||
info[field] = value
|
info[field] = value
|
||||||
self.pyd.reagents = reagents
|
self.pyd.reagents = reagents
|
||||||
logger.debug(f"Reagents from form: {reagents}")
|
# logger.debug(f"Reagents from form: {reagents}")
|
||||||
for item in self.recover:
|
for item in self.recover:
|
||||||
if hasattr(self, item):
|
if hasattr(self, item):
|
||||||
value = getattr(self, item)
|
value = getattr(self, item)
|
||||||
@@ -446,6 +437,7 @@ class SubmissionFormWidget(QWidget):
|
|||||||
report.add_result(report)
|
report.add_result(report)
|
||||||
return report
|
return report
|
||||||
|
|
||||||
|
|
||||||
class InfoItem(QWidget):
|
class InfoItem(QWidget):
|
||||||
|
|
||||||
def __init__(self, parent: QWidget, key: str, value: dict, submission_type: str | SubmissionType | None = None,
|
def __init__(self, parent: QWidget, key: str, value: dict, submission_type: str | SubmissionType | None = None,
|
||||||
@@ -691,7 +683,6 @@ class SubmissionFormWidget(QWidget):
|
|||||||
if new:
|
if new:
|
||||||
dlg = QuestionAsker(title=f"Add {lot}?",
|
dlg = QuestionAsker(title=f"Add {lot}?",
|
||||||
message=f"Couldn't find reagent type {self.reagent.role}: {lot} in the database.\n\nWould you like to add it?")
|
message=f"Couldn't find reagent type {self.reagent.role}: {lot} in the database.\n\nWould you like to add it?")
|
||||||
|
|
||||||
if dlg.exec():
|
if dlg.exec():
|
||||||
wanted_reagent = self.parent.parent().add_reagent(instance=wanted_reagent)
|
wanted_reagent = self.parent.parent().add_reagent(instance=wanted_reagent)
|
||||||
return wanted_reagent, report
|
return wanted_reagent, report
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ class Summary(InfoPane):
|
|||||||
None
|
None
|
||||||
"""
|
"""
|
||||||
super().update_data()
|
super().update_data()
|
||||||
orgs = [self.org_select.itemText(i) for i in range(self.org_select.count()) if self.org_select.itemChecked(i)]
|
orgs = self.org_select.get_checked()
|
||||||
self.report_obj = ReportMaker(start_date=self.start_date, end_date=self.end_date, organizations=orgs)
|
self.report_obj = ReportMaker(start_date=self.start_date, end_date=self.end_date, organizations=orgs)
|
||||||
self.webview.setHtml(self.report_obj.html)
|
self.webview.setHtml(self.report_obj.html)
|
||||||
if self.report_obj.subs:
|
if self.report_obj.subs:
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ from sqlalchemy.exc import IntegrityError as sqlalcIntegrityError
|
|||||||
from pytz import timezone as tz
|
from pytz import timezone as tz
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
|
||||||
|
|
||||||
timezone = tz("America/Winnipeg")
|
timezone = tz("America/Winnipeg")
|
||||||
|
|
||||||
logger = logging.getLogger(f"submissions.{__name__}")
|
logger = logging.getLogger(f"submissions.{__name__}")
|
||||||
@@ -248,7 +249,6 @@ def timer(func):
|
|||||||
func (__function__): incoming function
|
func (__function__): incoming function
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@wraps(func)
|
@wraps(func)
|
||||||
def wrapper(*args, **kwargs):
|
def wrapper(*args, **kwargs):
|
||||||
start_time = time.perf_counter()
|
start_time = time.perf_counter()
|
||||||
@@ -257,7 +257,6 @@ def timer(func):
|
|||||||
run_time = end_time - start_time
|
run_time = end_time - start_time
|
||||||
print(f"Finished {func.__name__}() in {run_time:.4f} secs")
|
print(f"Finished {func.__name__}() in {run_time:.4f} secs")
|
||||||
return value
|
return value
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
@@ -483,12 +482,10 @@ def setup_lookup(func):
|
|||||||
elif v is not None:
|
elif v is not None:
|
||||||
sanitized_kwargs[k] = v
|
sanitized_kwargs[k] = v
|
||||||
return func(*args, **sanitized_kwargs)
|
return func(*args, **sanitized_kwargs)
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
def check_object_in_manager(manager: list, object_name: object) -> Tuple[Any, bool]:
|
def check_object_in_manager(manager: list, object_name: object) -> Tuple[Any, bool]:
|
||||||
# for manager in managers:
|
|
||||||
if manager is None:
|
if manager is None:
|
||||||
return None, False
|
return None, False
|
||||||
# logger.debug(f"Manager: {manager}, aliases: {manager.aliases}, Key: {object_name}")
|
# logger.debug(f"Manager: {manager}, aliases: {manager.aliases}, Key: {object_name}")
|
||||||
@@ -535,6 +532,7 @@ def get_application_from_parent(widget):
|
|||||||
|
|
||||||
|
|
||||||
class Result(BaseModel, arbitrary_types_allowed=True):
|
class Result(BaseModel, arbitrary_types_allowed=True):
|
||||||
|
|
||||||
owner: str = Field(default="", validate_default=True)
|
owner: str = Field(default="", validate_default=True)
|
||||||
code: int = Field(default=0)
|
code: int = Field(default=0)
|
||||||
msg: str | Exception
|
msg: str | Exception
|
||||||
@@ -639,7 +637,6 @@ def rreplace(s: str, old: str, new: str) -> str:
|
|||||||
|
|
||||||
|
|
||||||
def list_sort_dict(input_dict: dict, sort_list: list) -> dict:
|
def list_sort_dict(input_dict: dict, sort_list: list) -> dict:
|
||||||
# sort_list.reverse()
|
|
||||||
sort_list = reversed(sort_list)
|
sort_list = reversed(sort_list)
|
||||||
for item in sort_list:
|
for item in sort_list:
|
||||||
try:
|
try:
|
||||||
@@ -661,7 +658,10 @@ def remove_key_from_list_of_dicts(input_list: list, key: str) -> list:
|
|||||||
list: List of updated dictionaries
|
list: List of updated dictionaries
|
||||||
"""
|
"""
|
||||||
for item in input_list:
|
for item in input_list:
|
||||||
del item[key]
|
try:
|
||||||
|
del item[key]
|
||||||
|
except KeyError:
|
||||||
|
continue
|
||||||
return input_list
|
return input_list
|
||||||
|
|
||||||
|
|
||||||
@@ -688,6 +688,7 @@ def super_splitter(ins_str: str, substring: str, idx: int) -> str:
|
|||||||
try:
|
try:
|
||||||
return ins_str.split(substring)[idx]
|
return ins_str.split(substring)[idx]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
|
logger.error(f"Index of split {idx} not found.")
|
||||||
return ins_str
|
return ins_str
|
||||||
|
|
||||||
|
|
||||||
@@ -767,7 +768,6 @@ def under_development(func):
|
|||||||
Result(owner=func.__str__(), code=1, msg=error_msg,
|
Result(owner=func.__str__(), code=1, msg=error_msg,
|
||||||
status="warning"))
|
status="warning"))
|
||||||
return report
|
return report
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
@@ -856,7 +856,6 @@ def create_holidays_for_year(year: int | None = None) -> List[date]:
|
|||||||
offset = -d.weekday() # weekday == 0 means Monday
|
offset = -d.weekday() # weekday == 0 means Monday
|
||||||
output = d + timedelta(offset)
|
output = d + timedelta(offset)
|
||||||
return output.date()
|
return output.date()
|
||||||
|
|
||||||
if not year:
|
if not year:
|
||||||
year = date.today().year
|
year = date.today().year
|
||||||
# NOTE: Includes New Year's day for next year.
|
# NOTE: Includes New Year's day for next year.
|
||||||
@@ -886,7 +885,7 @@ def check_dictionary_inclusion_equality(listo: List[dict] | dict, dicto: dict) -
|
|||||||
Returns:
|
Returns:
|
||||||
bool: True if dicto is equal to any dictionary in the list.
|
bool: True if dicto is equal to any dictionary in the list.
|
||||||
"""
|
"""
|
||||||
logger.debug(f"Comparing: {listo} and {dicto}")
|
# logger.debug(f"Comparing: {listo} and {dicto}")
|
||||||
if isinstance(dicto, list) and isinstance(listo, list):
|
if isinstance(dicto, list) and isinstance(listo, list):
|
||||||
return listo == dicto
|
return listo == dicto
|
||||||
elif isinstance(dicto, dict) and isinstance(listo, dict):
|
elif isinstance(dicto, dict) and isinstance(listo, dict):
|
||||||
@@ -957,7 +956,6 @@ class Settings(BaseSettings, extra="allow"):
|
|||||||
settings_path = None
|
settings_path = None
|
||||||
if settings_path is None:
|
if settings_path is None:
|
||||||
# NOTE: Check user .config/submissions directory
|
# NOTE: Check user .config/submissions directory
|
||||||
# if CONFIGDIR.joinpath("config.yml").exists():
|
|
||||||
if cls.configdir.joinpath("config.yml").exists():
|
if cls.configdir.joinpath("config.yml").exists():
|
||||||
settings_path = cls.configdir.joinpath("config.yml")
|
settings_path = cls.configdir.joinpath("config.yml")
|
||||||
# NOTE: Check user .submissions directory
|
# NOTE: Check user .submissions directory
|
||||||
@@ -969,8 +967,6 @@ class Settings(BaseSettings, extra="allow"):
|
|||||||
settings_path = Path(sys._MEIPASS).joinpath("files", "config.yml")
|
settings_path = Path(sys._MEIPASS).joinpath("files", "config.yml")
|
||||||
else:
|
else:
|
||||||
settings_path = project_path.joinpath('src', 'config.yml')
|
settings_path = project_path.joinpath('src', 'config.yml')
|
||||||
# with open(settings_path, "r") as dset:
|
|
||||||
# default_settings = yaml.load(dset, Loader=yaml.Loader)
|
|
||||||
else:
|
else:
|
||||||
# NOTE: check if user defined path is directory
|
# NOTE: check if user defined path is directory
|
||||||
if settings_path.is_dir():
|
if settings_path.is_dir():
|
||||||
@@ -1285,3 +1281,4 @@ class Settings(BaseSettings, extra="allow"):
|
|||||||
|
|
||||||
|
|
||||||
ctx = Settings()
|
ctx = Settings()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user