Switching to save instance
This commit is contained in:
@@ -6,11 +6,14 @@ import sys, logging
|
|||||||
from pandas import DataFrame
|
from pandas import DataFrame
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
from sqlalchemy import Column, INTEGER, String, JSON
|
from sqlalchemy import Column, INTEGER, String, JSON
|
||||||
from sqlalchemy.orm import DeclarativeMeta, declarative_base, Query, Session, InstrumentedAttribute
|
from sqlalchemy.orm import DeclarativeMeta, declarative_base, Query, Session, InstrumentedAttribute, ColumnProperty
|
||||||
from sqlalchemy.ext.declarative import declared_attr
|
from sqlalchemy.ext.declarative import declared_attr
|
||||||
from sqlalchemy.exc import ArgumentError, InvalidRequestError
|
from sqlalchemy.exc import ArgumentError, InvalidRequestError
|
||||||
from typing import Any, List
|
from typing import Any, List
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
from sqlalchemy.orm.relationships import _RelationshipDeclared
|
||||||
|
|
||||||
from tools import report_result, list_sort_dict
|
from tools import report_result, list_sort_dict
|
||||||
|
|
||||||
# NOTE: Load testing environment
|
# NOTE: Load testing environment
|
||||||
@@ -48,7 +51,7 @@ class BaseClass(Base):
|
|||||||
__table_args__ = {'extend_existing': True} #: Will only add new columns
|
__table_args__ = {'extend_existing': True} #: Will only add new columns
|
||||||
|
|
||||||
singles = ['id']
|
singles = ['id']
|
||||||
omni_removes = ['submissions', "omnigui_class_dict", "omnigui_instance_dict"]
|
omni_removes = ["id", 'submissions', "omnigui_class_dict", "omnigui_instance_dict"]
|
||||||
omni_sort = ["name"]
|
omni_sort = ["name"]
|
||||||
|
|
||||||
@classproperty
|
@classproperty
|
||||||
@@ -198,7 +201,7 @@ class BaseClass(Base):
|
|||||||
try:
|
try:
|
||||||
records = [obj.to_sub_dict(**kwargs) for obj in objects]
|
records = [obj.to_sub_dict(**kwargs) for obj in objects]
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
records = [{k:v['instance_attr'] for k, v in obj.omnigui_instance_dict.items()} for obj in objects]
|
records = [{k: v['instance_attr'] for k, v in obj.omnigui_instance_dict.items()} for obj in objects]
|
||||||
return DataFrame.from_records(records)
|
return DataFrame.from_records(records)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -324,36 +327,76 @@ class BaseClass(Base):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def relevant_relationships(cls, relationship_instance):
|
def relevant_relationships(cls, relationship_instance):
|
||||||
query_kwargs = {relationship_instance.query_alias:relationship_instance}
|
query_kwargs = {relationship_instance.query_alias: relationship_instance}
|
||||||
return cls.query(**query_kwargs)
|
return cls.query(**query_kwargs)
|
||||||
|
|
||||||
|
def check_all_attributes(self, attributes: dict):
|
||||||
|
logger.debug(f"Incoming attributes: {attributes}")
|
||||||
|
for key, value in attributes.items():
|
||||||
|
# print(getattr(self.__class__, key).property)
|
||||||
|
if value.lower() == "none":
|
||||||
|
value = None
|
||||||
|
self_value = getattr(self, key)
|
||||||
|
class_attr = getattr(self.__class__, key)
|
||||||
|
match class_attr.property:
|
||||||
|
case ColumnProperty():
|
||||||
|
match class_attr.type:
|
||||||
|
case INTEGER():
|
||||||
|
if value.lower() == "true":
|
||||||
|
value = 1
|
||||||
|
elif value.lower() == "false":
|
||||||
|
value = 0
|
||||||
|
else:
|
||||||
|
value = int(value)
|
||||||
|
case FLOAT():
|
||||||
|
value = float(value)
|
||||||
|
case _RelationshipDeclared():
|
||||||
|
try:
|
||||||
|
self_value = self_value.name
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
if class_attr.property.uselist:
|
||||||
|
self_value = self_value.__str__()
|
||||||
|
logger.debug(f"Checking self_value {self_value} of type {type(self_value)} against attribute {value} of type {type(value)}")
|
||||||
|
if self_value != value:
|
||||||
|
output = False
|
||||||
|
logger.debug(f"Value {key} is False, returning.")
|
||||||
|
return output
|
||||||
|
return True
|
||||||
|
|
||||||
def __setattr__(self, key, value):
|
def __setattr__(self, key, value):
|
||||||
|
logger.debug(f"Attempting to set {key} to {pformat(value)}")
|
||||||
try:
|
try:
|
||||||
field_type = getattr(self.__class__, key)
|
field_type = getattr(self.__class__, key)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
return super().__setattr__(key, value)
|
return super().__setattr__(key, value)
|
||||||
try:
|
if isinstance(field_type, InstrumentedAttribute):
|
||||||
check = field_type.property.uselist
|
logger.debug(f"{key} is an InstrumentedAttribute.")
|
||||||
except AttributeError:
|
match field_type.property:
|
||||||
check = False
|
case ColumnProperty():
|
||||||
if check:
|
logger.debug(f"Setting ColumnProperty to {value}")
|
||||||
logger.debug(f"Setting with uselist")
|
return super().__setattr__(key, value)
|
||||||
if self.__getattribute__(key) is not None:
|
case _RelationshipDeclared():
|
||||||
if isinstance(value, list):
|
logger.debug(f"Setting _RelationshipDeclared to {value}")
|
||||||
value = self.__getattribute__(key) + value
|
if field_type.property.uselist:
|
||||||
else:
|
logger.debug(f"Setting with uselist")
|
||||||
value = self.__getattribute__(key) + [value]
|
if self.__getattribute__(key) is not None:
|
||||||
else:
|
if isinstance(value, list):
|
||||||
value = [value]
|
value = self.__getattribute__(key) + value
|
||||||
|
else:
|
||||||
|
value = self.__getattribute__(key) + [value]
|
||||||
|
else:
|
||||||
|
value = [value]
|
||||||
|
return super().__setattr__(key, value)
|
||||||
|
else:
|
||||||
|
if isinstance(value, list):
|
||||||
|
if len(value) == 1:
|
||||||
|
value = value[0]
|
||||||
|
else:
|
||||||
|
raise ValueError("Object is too long to parse a single value.")
|
||||||
|
return super().__setattr__(key, value)
|
||||||
else:
|
else:
|
||||||
if isinstance(value, list):
|
super().__setattr__(key, value)
|
||||||
if len(value) == 1:
|
|
||||||
value = value[0]
|
|
||||||
else:
|
|
||||||
raise ValueError("Object is too long to parse a single value.")
|
|
||||||
return super().__setattr__(key, value)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class ConfigItem(BaseClass):
|
class ConfigItem(BaseClass):
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ from sqlalchemy.ext.associationproxy import association_proxy
|
|||||||
from sqlalchemy.ext.hybrid import hybrid_property
|
from sqlalchemy.ext.hybrid import hybrid_property
|
||||||
from datetime import date, datetime, timedelta
|
from datetime import date, datetime, timedelta
|
||||||
from tools import check_authorization, setup_lookup, Report, Result, check_regex_match, yaml_regex_creator, timezone
|
from tools import check_authorization, setup_lookup, Report, Result, check_regex_match, yaml_regex_creator, timezone
|
||||||
from typing import List, Literal, Generator, Any, Tuple
|
from typing import List, Literal, Generator, Any, Tuple, Dict, AnyStr
|
||||||
from pandas import ExcelFile
|
from pandas import ExcelFile
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from . import Base, BaseClass, Organization, LogMixin
|
from . import Base, BaseClass, Organization, LogMixin
|
||||||
@@ -861,7 +861,7 @@ class SubmissionType(BaseClass):
|
|||||||
|
|
||||||
@classproperty
|
@classproperty
|
||||||
def omni_removes(cls):
|
def omni_removes(cls):
|
||||||
return super().omni_removes + ["template_file", "defaults", "instances"]
|
return super().omni_removes + ["defaults", "instances"]
|
||||||
|
|
||||||
@classproperty
|
@classproperty
|
||||||
def basic_template(cls) -> bytes:
|
def basic_template(cls) -> bytes:
|
||||||
@@ -1167,7 +1167,10 @@ class SubmissionTypeKitTypeAssociation(BaseClass):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
return f"{self.submission_type.name} -> {self.kit_type.name}"
|
try:
|
||||||
|
return f"{self.submission_type.name} -> {self.kit_type.name}"
|
||||||
|
except AttributeError:
|
||||||
|
return "Blank SubmissionTypeKitTypeAssociation"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@setup_lookup
|
@setup_lookup
|
||||||
@@ -1378,6 +1381,16 @@ class KitTypeReagentRoleAssociation(BaseClass):
|
|||||||
dicto['required']['instance_attr'] = bool(dicto['required']['instance_attr'])
|
dicto['required']['instance_attr'] = bool(dicto['required']['instance_attr'])
|
||||||
return dicto
|
return dicto
|
||||||
|
|
||||||
|
@classproperty
|
||||||
|
def json_edit_fields(cls) -> dict:
|
||||||
|
dicto = dict(
|
||||||
|
sheet="str",
|
||||||
|
expiry=dict(column="int", row="int"),
|
||||||
|
lot=dict(column="int", row="int"),
|
||||||
|
name=dict(column="int", row="int")
|
||||||
|
)
|
||||||
|
return dicto
|
||||||
|
|
||||||
|
|
||||||
class SubmissionReagentAssociation(BaseClass):
|
class SubmissionReagentAssociation(BaseClass):
|
||||||
"""
|
"""
|
||||||
@@ -1932,7 +1945,6 @@ class Process(BaseClass):
|
|||||||
if value not in field:
|
if value not in field:
|
||||||
field.append(value)
|
field.append(value)
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@setup_lookup
|
@setup_lookup
|
||||||
def query(cls,
|
def query(cls,
|
||||||
|
|||||||
@@ -230,7 +230,7 @@ class App(QMainWindow):
|
|||||||
self.table_widget.sub_wid.setData(page=self.table_widget.pager.page_anchor, page_size=page_size)
|
self.table_widget.sub_wid.setData(page=self.table_widget.pager.page_anchor, page_size=page_size)
|
||||||
|
|
||||||
def manage_orgs(self):
|
def manage_orgs(self):
|
||||||
dlg = ManagerWindow(parent=self, object_type=Organization, extras=[])
|
dlg = ManagerWindow(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()
|
||||||
new_org.save()
|
new_org.save()
|
||||||
@@ -238,9 +238,11 @@ class App(QMainWindow):
|
|||||||
|
|
||||||
@under_development
|
@under_development
|
||||||
def manage_kits(self, *args, **kwargs):
|
def manage_kits(self, *args, **kwargs):
|
||||||
dlg = ManagerWindow(parent=self, object_type=KitType, extras=[])
|
dlg = ManagerWindow(parent=self, object_type=KitType, extras=[], add_edit='edit', managers=set())
|
||||||
if dlg.exec():
|
if dlg.exec():
|
||||||
print(dlg.parse_form())
|
output = dlg.parse_form()
|
||||||
|
assert isinstance(output, KitType)
|
||||||
|
output.save()
|
||||||
|
|
||||||
class AddSubForm(QWidget):
|
class AddSubForm(QWidget):
|
||||||
|
|
||||||
|
|||||||
@@ -1,27 +1,23 @@
|
|||||||
"""
|
"""
|
||||||
Provides a screen for managing all attributes of a database object.
|
Provides a screen for managing all attributes of a database object.
|
||||||
"""
|
"""
|
||||||
from copy import deepcopy
|
import json, logging
|
||||||
from pprint import pformat
|
from pprint import pformat
|
||||||
from typing import Any, List
|
from typing import Any, List, Literal
|
||||||
from PyQt6.QtCore import QSortFilterProxyModel, Qt
|
from PyQt6.QtCore import QSortFilterProxyModel, Qt
|
||||||
from PyQt6.QtGui import QAction, QCursor
|
from PyQt6.QtGui import QAction, QCursor
|
||||||
from PyQt6.QtWidgets import (
|
from PyQt6.QtWidgets import (
|
||||||
QLabel, QDialog,
|
QLabel, QDialog,
|
||||||
QTableView, QWidget, QLineEdit, QGridLayout, QComboBox, QPushButton, QDialogButtonBox, QDateEdit, QMenu,
|
QTableView, QWidget, QLineEdit, QGridLayout, QComboBox, QPushButton, QDialogButtonBox, QDateEdit, QMenu,
|
||||||
QDoubleSpinBox, QSpinBox, QCheckBox
|
QDoubleSpinBox, QSpinBox, QCheckBox, QTextEdit, QVBoxLayout, QHBoxLayout
|
||||||
)
|
)
|
||||||
from sqlalchemy import String, TIMESTAMP, FLOAT, INTEGER, JSON, BLOB
|
from sqlalchemy import String, TIMESTAMP, FLOAT, INTEGER, JSON, BLOB
|
||||||
from sqlalchemy.orm import InstrumentedAttribute
|
from sqlalchemy.orm import InstrumentedAttribute
|
||||||
from sqlalchemy.orm.collections import InstrumentedList
|
|
||||||
from sqlalchemy.orm.properties import ColumnProperty
|
from sqlalchemy.orm.properties import ColumnProperty
|
||||||
from sqlalchemy.orm.relationships import _RelationshipDeclared
|
from sqlalchemy.orm.relationships import _RelationshipDeclared
|
||||||
from pandas import DataFrame
|
from pandas import DataFrame
|
||||||
from backend import db
|
from backend import db
|
||||||
import logging
|
|
||||||
|
|
||||||
from tools import check_object_in_managers
|
from tools import check_object_in_managers
|
||||||
from .omni_add_edit import AddEdit
|
|
||||||
from .omni_search import SearchBox
|
from .omni_search import SearchBox
|
||||||
from frontend.widgets.submission_table import pandasModel
|
from frontend.widgets.submission_table import pandasModel
|
||||||
|
|
||||||
@@ -33,11 +29,16 @@ class ManagerWindow(QDialog):
|
|||||||
Initially this is a window to manage Organization Contacts, but hope to abstract it more later.
|
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], managers: set = set(), **kwargs):
|
def __init__(self, parent,
|
||||||
|
object_type: Any,
|
||||||
|
extras: List[str],
|
||||||
|
managers: set = set(),
|
||||||
|
add_edit: Literal['add', 'edit'] = 'edit',
|
||||||
|
**kwargs):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.object_type = self.original_type = object_type
|
self.object_type = self.original_type = object_type
|
||||||
|
self.add_edit = add_edit
|
||||||
self.instance = None
|
self.instance = None
|
||||||
# self.managers = deepcopy(managers)
|
|
||||||
self.managers = managers
|
self.managers = managers
|
||||||
try:
|
try:
|
||||||
self.managers.add(self.parent().instance)
|
self.managers.add(self.parent().instance)
|
||||||
@@ -63,9 +64,12 @@ class ManagerWindow(QDialog):
|
|||||||
self.layout.addWidget(self.sub_class, 0, 0)
|
self.layout.addWidget(self.sub_class, 0, 0)
|
||||||
else:
|
else:
|
||||||
self.sub_class = None
|
self.sub_class = None
|
||||||
self.options = QComboBox(self)
|
if self.add_edit == "edit":
|
||||||
self.options.setObjectName("options")
|
self.options = QComboBox(self)
|
||||||
self.update_options()
|
self.options.setObjectName("options")
|
||||||
|
self.update_options()
|
||||||
|
else:
|
||||||
|
self.update_data(initial=True)
|
||||||
self.setLayout(self.layout)
|
self.setLayout(self.layout)
|
||||||
self.setWindowTitle(f"Manage {self.object_type.__name__} - Managers: {self.managers}")
|
self.setWindowTitle(f"Manage {self.object_type.__name__} - Managers: {self.managers}")
|
||||||
|
|
||||||
@@ -96,15 +100,15 @@ class ManagerWindow(QDialog):
|
|||||||
self.options.setEditable(False)
|
self.options.setEditable(False)
|
||||||
self.options.setMinimumWidth(self.minimumWidth())
|
self.options.setMinimumWidth(self.minimumWidth())
|
||||||
self.layout.addWidget(self.options, 1, 0, 1, 1)
|
self.layout.addWidget(self.options, 1, 0, 1, 1)
|
||||||
if len(options) > 0:
|
# if len(options) > 0:
|
||||||
self.add_button = QPushButton("Add New")
|
self.add_button = QPushButton("Add New")
|
||||||
self.layout.addWidget(self.add_button, 1, 1, 1, 1)
|
self.layout.addWidget(self.add_button, 1, 1, 1, 1)
|
||||||
self.add_button.clicked.connect(self.add_new)
|
self.add_button.clicked.connect(self.add_new)
|
||||||
self.options.currentTextChanged.connect(self.update_data)
|
self.options.currentTextChanged.connect(self.update_data)
|
||||||
# logger.debug(f"Instance: {self.instance}")
|
# logger.debug(f"Instance: {self.instance}")
|
||||||
self.update_data()
|
self.update_data()
|
||||||
|
|
||||||
def update_data(self) -> None:
|
def update_data(self, initial:bool=False) -> None:
|
||||||
"""
|
"""
|
||||||
Performs updating of widgets on first run and after options change.
|
Performs updating of widgets on first run and after options change.
|
||||||
|
|
||||||
@@ -119,15 +123,19 @@ class ManagerWindow(QDialog):
|
|||||||
item.setParent(None)
|
item.setParent(None)
|
||||||
# logger.debug(f"Current options text lower: {self.options.currentText().lower()}")
|
# logger.debug(f"Current options text lower: {self.options.currentText().lower()}")
|
||||||
# NOTE: Find the instance this manager will update
|
# NOTE: Find the instance this manager will update
|
||||||
if "blank" not in self.options.currentText().lower() and self.options.currentText() != "":
|
# try:
|
||||||
|
# check = "blank" not in self.options.currentText().lower() and self.options.currentText() != ""
|
||||||
|
# except AttributeError:
|
||||||
|
# check = False
|
||||||
|
# if check:
|
||||||
|
if self.add_edit == "edit" and initial:
|
||||||
# logger.debug(f"Querying with {self.options.currentText()}")
|
# logger.debug(f"Querying with {self.options.currentText()}")
|
||||||
self.instance = self.object_type.query(name=self.options.currentText(), limit=1)
|
self.instance = self.object_type.query(name=self.options.currentText(), limit=1)
|
||||||
# logger.debug(f"Instance: {self.instance}")
|
# logger.debug(f"Instance: {self.instance}")
|
||||||
if not self.instance:
|
if not self.instance:
|
||||||
self.instance = self.object_type()
|
self.instance = self.object_type()
|
||||||
# logger.debug(f"self.instance: {self.instance}")
|
# logger.debug(f"self.instance: {self.instance}")
|
||||||
fields = {k: v for k, v in self.instance.omnigui_instance_dict.items() if
|
fields = self.instance.omnigui_instance_dict
|
||||||
isinstance(v['class_attr'], InstrumentedAttribute) and k != "id"}
|
|
||||||
for key, field in fields.items():
|
for key, field in fields.items():
|
||||||
try:
|
try:
|
||||||
value = getattr(self.instance, key)
|
value = getattr(self.instance, key)
|
||||||
@@ -154,11 +162,6 @@ class ManagerWindow(QDialog):
|
|||||||
# NOTE: Add OK|Cancel to bottom of dialog.
|
# NOTE: Add OK|Cancel to bottom of dialog.
|
||||||
self.layout.addWidget(self.buttonBox, self.layout.rowCount(), 0, 1, 2)
|
self.layout.addWidget(self.buttonBox, self.layout.rowCount(), 0, 1, 2)
|
||||||
|
|
||||||
|
|
||||||
def add_new_relation(self, field: str):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def parse_form(self) -> Any:
|
def parse_form(self) -> Any:
|
||||||
"""
|
"""
|
||||||
Returns the instance associated with this window.
|
Returns the instance associated with this window.
|
||||||
@@ -182,18 +185,48 @@ class ManagerWindow(QDialog):
|
|||||||
return self.instance
|
return self.instance
|
||||||
|
|
||||||
def add_new(self):
|
def add_new(self):
|
||||||
# dlg = AddEdit(parent=self, instance=self.object_type(), managers=self.managers)
|
|
||||||
# if dlg.exec():
|
|
||||||
# new_pyd = dlg.parse_form()
|
|
||||||
# new_instance = new_pyd.to_sql()
|
|
||||||
# # new_instance.save()
|
|
||||||
# logger.debug(f"New instance: {new_instance}")
|
|
||||||
# self.instance = new_instance
|
|
||||||
# self.update_options()
|
|
||||||
new_instance = self.object_type()
|
new_instance = self.object_type()
|
||||||
self.instance = new_instance
|
self.instance = new_instance
|
||||||
self.update_options()
|
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):
|
class EditProperty(QWidget):
|
||||||
|
|
||||||
@@ -203,7 +236,7 @@ class EditProperty(QWidget):
|
|||||||
self.layout = QGridLayout()
|
self.layout = QGridLayout()
|
||||||
self.layout.addWidget(self.label, 0, 0, 1, 1)
|
self.layout.addWidget(self.label, 0, 0, 1, 1)
|
||||||
self.setObjectName(key)
|
self.setObjectName(key)
|
||||||
# logger.debug(f"Column type: {column_type}")
|
logger.debug(f"Column type for {key}: {column_type['class_attr'].property.expression.type}")
|
||||||
match column_type['class_attr'].property.expression.type:
|
match column_type['class_attr'].property.expression.type:
|
||||||
case String():
|
case String():
|
||||||
self.widget = QLineEdit(self)
|
self.widget = QLineEdit(self)
|
||||||
@@ -214,12 +247,13 @@ class EditProperty(QWidget):
|
|||||||
self.widget.setChecked(value)
|
self.widget.setChecked(value)
|
||||||
else:
|
else:
|
||||||
if value is None:
|
if value is None:
|
||||||
value = 1
|
value = 0
|
||||||
self.widget = QSpinBox()
|
self.widget = QSpinBox()
|
||||||
|
self.widget.setMaximum(999)
|
||||||
self.widget.setValue(value)
|
self.widget.setValue(value)
|
||||||
case FLOAT():
|
case FLOAT():
|
||||||
if not value:
|
if not value:
|
||||||
value = 1.0
|
value = 0.0
|
||||||
self.widget = QDoubleSpinBox()
|
self.widget = QDoubleSpinBox()
|
||||||
self.widget.setMaximum(999.99)
|
self.widget.setMaximum(999.99)
|
||||||
self.widget.setValue(value)
|
self.widget.setValue(value)
|
||||||
@@ -227,7 +261,9 @@ class EditProperty(QWidget):
|
|||||||
self.widget = QDateEdit(self)
|
self.widget = QDateEdit(self)
|
||||||
self.widget.setDate(value)
|
self.widget.setDate(value)
|
||||||
case JSON():
|
case JSON():
|
||||||
self.widget = QLabel("JSON Under construction")
|
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():
|
case BLOB():
|
||||||
self.widget = QLabel("BLOB Under construction")
|
self.widget = QLabel("BLOB Under construction")
|
||||||
case _:
|
case _:
|
||||||
@@ -259,37 +295,54 @@ class EditRelationship(QWidget):
|
|||||||
# logger.debug(f"Edit relationship entity: {self.entity}")
|
# logger.debug(f"Edit relationship entity: {self.entity}")
|
||||||
self.label = QLabel(key.title().replace("_", " "))
|
self.label = QLabel(key.title().replace("_", " "))
|
||||||
self.setObjectName(key) #: key is the name of the relationship this represents
|
self.setObjectName(key) #: key is the name of the relationship this represents
|
||||||
self.relationship = getattr(self.parent().instance.__class__, key)
|
self.relationship = getattr(self.parent().instance.__class__, key) #: relationship object for type differentiation
|
||||||
# logger.debug(f"self.relationship: {self.relationship}")
|
# logger.debug(f"self.relationship: {self.relationship}")
|
||||||
# logger.debug(f"Relationship uses list: {self.relationship.property.uselist}")
|
# logger.debug(f"Relationship uses list: {self.relationship.property.uselist}")
|
||||||
self.data = value
|
# NOTE: value is a database object in this case.
|
||||||
|
|
||||||
# logger.debug(f"Data for edit relationship: {self.data}")
|
# logger.debug(f"Data for edit relationship: {self.data}")
|
||||||
self.widget = QTableView()
|
self.widget = QTableView()
|
||||||
self.set_data()
|
|
||||||
self.add_button = QPushButton("Add New")
|
self.add_button = QPushButton("Add New")
|
||||||
self.add_button.clicked.connect(self.add_new)
|
self.add_button.clicked.connect(self.add_new)
|
||||||
self.existing_button = QPushButton("Add Existing")
|
self.existing_button = QPushButton("Add Existing")
|
||||||
self.existing_button.clicked.connect(self.add_existing)
|
self.existing_button.clicked.connect(self.add_existing)
|
||||||
# self.existing_button.setEnabled(self.entity.level == 1)
|
# self.existing_button.setEnabled(self.entity.level == 1)
|
||||||
if not self.relationship.property.uselist and len(self.data) >= 1:
|
if not isinstance(value, list):
|
||||||
self.add_button.setEnabled(False)
|
if value is not None:
|
||||||
self.existing_button.setEnabled(False)
|
value = [value]
|
||||||
checked_manager = check_object_in_managers(self.parent().managers, self.objectName())
|
else:
|
||||||
logger.debug(f"Checked manager for check: {checked_manager}")
|
value = []
|
||||||
|
self.data = value
|
||||||
|
# self.update_buttons()
|
||||||
|
checked_manager, is_primary = check_object_in_managers(self.parent().managers, self.objectName())
|
||||||
if checked_manager:
|
if checked_manager:
|
||||||
self.widget.setEnabled(False)
|
logger.debug(f"Checked manager for {self.objectName()}: {checked_manager}")
|
||||||
self.add_button.setEnabled(False)
|
if checked_manager is not None and not self.data:
|
||||||
self.existing_button.setEnabled(False)
|
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 = QGridLayout()
|
||||||
self.layout.addWidget(self.label, 0, 0, 1, 5)
|
self.layout.addWidget(self.label, 0, 0, 1, 5)
|
||||||
self.layout.addWidget(self.widget, 1, 0, 1, 8)
|
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.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.layout.addWidget(self.existing_button, 0, 7, 1, 1, alignment=Qt.AlignmentFlag.AlignRight)
|
||||||
self.setLayout(self.layout)
|
self.setLayout(self.layout)
|
||||||
# self.set_data()
|
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):
|
def parse_row(self, x):
|
||||||
context = {item: x.sibling(x.row(), self.data.columns.get_loc(item)).data() for item in self.data.columns}
|
context = {item: x.sibling(x.row(), self.df.columns.get_loc(item)).data() for item in self.df.columns}
|
||||||
try:
|
try:
|
||||||
object = self.entity.query(**context)
|
object = self.entity.query(**context)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
@@ -303,9 +356,10 @@ class EditRelationship(QWidget):
|
|||||||
instance = self.entity()
|
instance = self.entity()
|
||||||
managers = self.parent().managers
|
managers = self.parent().managers
|
||||||
# logger.debug(f"Managers going into add new: {managers}")
|
# logger.debug(f"Managers going into add new: {managers}")
|
||||||
dlg = ManagerWindow(self.parent(), object_type=instance.__class__, extras=[], managers=managers)
|
dlg = ManagerWindow(self.parent(), object_type=instance.__class__, extras=[], managers=managers, add_edit="add")
|
||||||
if dlg.exec():
|
if dlg.exec():
|
||||||
new_instance = dlg.parse_form()
|
new_instance = dlg.parse_form()
|
||||||
|
self.parent().__setattr__(self.objectName(), new_instance)
|
||||||
# logger.debug(f"New instance before transformation attempt: {new_instance}")
|
# logger.debug(f"New instance before transformation attempt: {new_instance}")
|
||||||
# try:
|
# try:
|
||||||
# new_instance = new_instance.to_sql()
|
# new_instance = new_instance.to_sql()
|
||||||
@@ -326,19 +380,9 @@ class EditRelationship(QWidget):
|
|||||||
for row in rows:
|
for row in rows:
|
||||||
# logger.debug(f"Querying with {row}")
|
# logger.debug(f"Querying with {row}")
|
||||||
instance = self.entity.query(**row)
|
instance = self.entity.query(**row)
|
||||||
# logger.debug(f"Queried instance: {instance}")
|
|
||||||
# logger.debug(f"Checking field type: {self.objectName()}")
|
|
||||||
# addition = getattr(self.parent().instance, self.objectName())
|
|
||||||
# logger.debug(f"Instance object: {addition}")
|
|
||||||
# NOTE: Saving currently disabled
|
|
||||||
# if self.relationship.property.uselist:
|
|
||||||
# addition.append(instance)
|
|
||||||
# else:
|
|
||||||
# addition = instance
|
|
||||||
setattr(self.parent().instance, self.objectName(), instance)
|
setattr(self.parent().instance, self.objectName(), instance)
|
||||||
# self.parent().instance.save()
|
# self.parent().instance.save()
|
||||||
self.parent().update_data()
|
self.parent().update_data()
|
||||||
# yield instance
|
|
||||||
|
|
||||||
def set_choices(self) -> None:
|
def set_choices(self) -> None:
|
||||||
pass
|
pass
|
||||||
@@ -347,19 +391,7 @@ class EditRelationship(QWidget):
|
|||||||
"""
|
"""
|
||||||
sets data in model
|
sets data in model
|
||||||
"""
|
"""
|
||||||
# logger.debug(self.data)
|
logger.debug(f"Self.data: {self.data}")
|
||||||
if not isinstance(self.data, list):
|
|
||||||
if self.data is not None:
|
|
||||||
self.data = [self.data]
|
|
||||||
else:
|
|
||||||
self.data = []
|
|
||||||
checked_manager = check_object_in_managers(self.parent().managers, self.objectName())
|
|
||||||
# logger.debug(f"Returned checked_manager: {checked_manager}")
|
|
||||||
if checked_manager is not None:
|
|
||||||
if not self.data:
|
|
||||||
self.data = [checked_manager]
|
|
||||||
# setattr(self.parent().instance, self.objectName(), checked_manager)
|
|
||||||
# logger.debug(f"Data: {self.data}")
|
|
||||||
try:
|
try:
|
||||||
records = [{k: v['instance_attr'] for k, v in item.omnigui_instance_dict.items()} for item in self.data]
|
records = [{k: v['instance_attr'] for k, v in item.omnigui_instance_dict.items()} for item in self.data]
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
@@ -382,6 +414,7 @@ class EditRelationship(QWidget):
|
|||||||
self.widget.resizeRowsToContents()
|
self.widget.resizeRowsToContents()
|
||||||
self.widget.setSortingEnabled(True)
|
self.widget.setSortingEnabled(True)
|
||||||
self.widget.doubleClicked.connect(self.parse_row)
|
self.widget.doubleClicked.connect(self.parse_row)
|
||||||
|
self.update_buttons()
|
||||||
|
|
||||||
def contextMenuEvent(self, event):
|
def contextMenuEvent(self, event):
|
||||||
"""
|
"""
|
||||||
@@ -390,7 +423,7 @@ class EditRelationship(QWidget):
|
|||||||
Args:
|
Args:
|
||||||
event (_type_): the item of interest
|
event (_type_): the item of interest
|
||||||
"""
|
"""
|
||||||
print(self.widget.isEnabled())
|
# print(self.widget.isEnabled())
|
||||||
if not self.widget.isEnabled():
|
if not self.widget.isEnabled():
|
||||||
logger.warning(f"{self.objectName()} is disabled.")
|
logger.warning(f"{self.objectName()} is disabled.")
|
||||||
return
|
return
|
||||||
@@ -398,24 +431,184 @@ class EditRelationship(QWidget):
|
|||||||
# NOTE: the overly complicated {column_name: row_value} dictionary construction
|
# 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
|
row_data = {self.df.columns[column]: self.widget.model().index(id.row(), column).data() for column in
|
||||||
range(self.widget.model().columnCount())}
|
range(self.widget.model().columnCount())}
|
||||||
object = self.entity.query(**row_data)
|
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):
|
if isinstance(object, list):
|
||||||
object = object[0]
|
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)
|
# logger.debug(object)
|
||||||
self.menu = QMenu(self)
|
self.menu = QMenu(self)
|
||||||
try:
|
try:
|
||||||
action = QAction(f"Remove {object.name}", self)
|
remove_action = QAction(f"Remove {object.name}", self)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
action = QAction(f"Remove object", self)
|
remove_action = QAction(f"Remove object", self)
|
||||||
action.triggered.connect(lambda: self.remove_item(object=object))
|
remove_action.triggered.connect(lambda: self.remove_item(object=object))
|
||||||
self.menu.addAction(action)
|
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())
|
self.menu.popup(QCursor.pos())
|
||||||
|
|
||||||
def remove_item(self, object):
|
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())
|
editor = getattr(self.parent().instance, self.objectName().lower())
|
||||||
editor.remove(object)
|
logger.debug(f"Editor: {editor}")
|
||||||
self.parent().instance.save()
|
if object in self.parent().managers:
|
||||||
self.parent().update_data()
|
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.parent().update_data()
|
||||||
|
self.set_data()
|
||||||
|
|
||||||
def parse_form(self):
|
def parse_form(self):
|
||||||
return dict(field=self.objectName(), value=self.data)
|
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.object_type
|
||||||
|
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)}")
|
||||||
|
# output[key] = value
|
||||||
|
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)
|
||||||
|
|||||||
@@ -175,6 +175,7 @@ class SubmissionDetails(QDialog):
|
|||||||
template_path = Path(self.template.environment.loader.__getattribute__("searchpath")[0])
|
template_path = Path(self.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:
|
||||||
css = f.read()
|
css = f.read()
|
||||||
|
# logger.debug(f"Base dictionary of submission {self.rsl_plate_num}: {pformat(self.base_dict)}")
|
||||||
self.html = self.template.render(sub=self.base_dict, permission=is_power_user(), css=css)
|
self.html = self.template.render(sub=self.base_dict, permission=is_power_user(), css=css)
|
||||||
self.webview.setHtml(self.html)
|
self.webview.setHtml(self.html)
|
||||||
|
|
||||||
|
|||||||
@@ -148,6 +148,7 @@ def check_key_or_attr(key: str, interest: dict | object, check_none: bool = Fals
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def check_not_nan(cell_contents) -> bool:
|
def check_not_nan(cell_contents) -> bool:
|
||||||
"""
|
"""
|
||||||
Check to ensure excel sheet cell contents are not blank.
|
Check to ensure excel sheet cell contents are not blank.
|
||||||
@@ -816,22 +817,22 @@ def setup_lookup(func):
|
|||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
def check_object_in_managers(managers: list, object_name: object):
|
def check_object_in_managers(managers: list, object_name: object) -> Tuple[Any, bool]:
|
||||||
for manager in managers:
|
for manager in managers:
|
||||||
logger.debug(f"Manager: {manager}, Key: {object_name}")
|
logger.debug(f"Manager: {manager}, aliases: {manager.aliases}, Key: {object_name}")
|
||||||
if object_name in manager.aliases:
|
if object_name in manager.aliases:
|
||||||
return manager
|
return manager, True
|
||||||
relationships = [getattr(manager.__class__, item) for item in dir(manager.__class__)
|
relationships = [getattr(manager.__class__, item) for item in dir(manager.__class__)
|
||||||
if isinstance(getattr(manager.__class__, item), InstrumentedAttribute)]
|
if isinstance(getattr(manager.__class__, item), InstrumentedAttribute)]
|
||||||
relationships = [item for item in relationships if isinstance(item.property, _RelationshipDeclared)]
|
relationships = [item for item in relationships if isinstance(item.property, _RelationshipDeclared)]
|
||||||
for relationship in relationships:
|
for relationship in relationships:
|
||||||
if relationship.key == object_name:
|
if relationship.key == object_name and "association" not in relationship.key:
|
||||||
logger.debug(f"Checking {relationship.key}")
|
logger.debug(f"Checking {relationship.key}")
|
||||||
try:
|
try:
|
||||||
rel_obj = getattr(manager, relationship.key)
|
rel_obj = getattr(manager, relationship.key)
|
||||||
if rel_obj is not None:
|
if rel_obj is not None:
|
||||||
logger.debug(f"Returning {rel_obj}")
|
logger.debug(f"Returning {rel_obj}")
|
||||||
return rel_obj
|
return rel_obj, False
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
if "association" in relationship.key:
|
if "association" in relationship.key:
|
||||||
@@ -841,10 +842,10 @@ def check_object_in_managers(managers: list, object_name: object):
|
|||||||
if getattr(item, object_name) is not None), None)
|
if getattr(item, object_name) is not None), None)
|
||||||
if rel_obj is not None:
|
if rel_obj is not None:
|
||||||
logger.debug(f"Returning {rel_obj}")
|
logger.debug(f"Returning {rel_obj}")
|
||||||
return rel_obj
|
return rel_obj, False
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
return None
|
return None, None
|
||||||
|
|
||||||
|
|
||||||
def get_application_from_parent(widget):
|
def get_application_from_parent(widget):
|
||||||
@@ -1163,6 +1164,7 @@ def is_list_etc(object):
|
|||||||
check = False
|
check = False
|
||||||
return check
|
return check
|
||||||
|
|
||||||
|
|
||||||
def create_holidays_for_year(year: int | None = None) -> List[date]:
|
def create_holidays_for_year(year: int | None = None) -> List[date]:
|
||||||
def find_nth_monday(year, month, occurence: int | None = None, day: int | None = None):
|
def find_nth_monday(year, month, occurence: int | None = None, day: int | None = None):
|
||||||
if not occurence:
|
if not occurence:
|
||||||
|
|||||||
Reference in New Issue
Block a user