Bug fixes for omni gui objects.

This commit is contained in:
lwark
2025-04-16 13:47:07 -05:00
parent 58f5d361b3
commit 1a1f766890
6 changed files with 263 additions and 70 deletions

View File

@@ -457,12 +457,12 @@ class BaseClass(Base):
""" """
match input_date: match input_date:
case datetime() | date(): case datetime() | date():
output_date = input_date#.strftime("%Y-%m-%d %H:%M:%S") output_date = input_date
case int(): case int():
output_date = datetime.fromordinal( output_date = datetime.fromordinal(
datetime(1900, 1, 1).toordinal() + input_date - 2)#.date().strftime("%Y-%m-%d %H:%M:%S") datetime(1900, 1, 1).toordinal() + input_date - 2)
case _: case _:
output_date = parse(input_date)#.strftime("%Y-%m-%d %H:%M:%S") output_date = parse(input_date)
if eod: if eod:
addition_time = datetime.max.time() addition_time = datetime.max.time()
else: else:

View File

@@ -126,7 +126,13 @@ class KitType(BaseClass):
submission_type=ST)) #: Association proxy to SubmissionTypeKitTypeAssociation submission_type=ST)) #: Association proxy to SubmissionTypeKitTypeAssociation
@classproperty @classproperty
def aliases(cls): def aliases(cls) -> List[str]:
"""
Gets other names the sql object of this class might go by.
Returns:
List[str]: List of names
"""
return super().aliases + [cls.query_alias, "kit_types", "kit_type"] return super().aliases + [cls.query_alias, "kit_types", "kit_type"]
@hybrid_property @hybrid_property
@@ -1077,7 +1083,13 @@ class SubmissionType(BaseClass):
return self.processes return self.processes
@classproperty @classproperty
def aliases(cls): def aliases(cls) -> List[str]:
"""
Gets other names the sql object of this class might go by.
Returns:
List[str]: List of names
"""
return super().aliases + ["submission_types", "submission_type"] return super().aliases + ["submission_types", "submission_type"]
@classproperty @classproperty

View File

@@ -1540,12 +1540,15 @@ class BacterialCulture(BasicSubmission):
return report return report
parser = ConcentrationParser(filepath=fname, submission=self) parser = ConcentrationParser(filepath=fname, submission=self)
conc_samples = [sample for sample in parser.samples] conc_samples = [sample for sample in parser.samples]
# logger.debug(f"Concentration samples: {pformat(conc_samples)}")
for sample in self.samples: for sample in self.samples:
logger.debug(f"Sample {sample.submitter_id}") # logger.debug(f"Sample {sample.submitter_id}")
# logger.debug(f"Match {item['submitter_id']}")
try: try:
# NOTE: Fix for ENs which have no rsl_number... # NOTE: Fix for ENs which have no rsl_number...
sample_dict = next(item for item in conc_samples if item['submitter_id'] == sample.submitter_id) sample_dict = next(item for item in conc_samples if str(item['submitter_id']).upper() == sample.submitter_id)
except StopIteration: except StopIteration:
logger.error(f"Couldn't find sample dict for {sample.submitter_id}")
continue continue
logger.debug(f"Sample {sample.submitter_id} conc. = {sample_dict['concentration']}") logger.debug(f"Sample {sample.submitter_id} conc. = {sample_dict['concentration']}")
if sample_dict['concentration']: if sample_dict['concentration']:
@@ -1734,12 +1737,10 @@ class Wastewater(BasicSubmission):
sample[f"ct_{sample['target'].lower()}"] = sample['ct'] if isinstance(sample['ct'], float) else 0.0 sample[f"ct_{sample['target'].lower()}"] = sample['ct'] if isinstance(sample['ct'], float) else 0.0
# NOTE: Set assessment # NOTE: Set assessment
# logger.debug(f"Sample assessemnt: {sample['assessment']}") # logger.debug(f"Sample assessemnt: {sample['assessment']}")
# sample[f"{sample['target'].lower()}_status"] = sample['assessment']
# NOTE: Get sample having other target # NOTE: Get sample having other target
other_targets = [s for s in samples if re.sub('-N\\d*$', '', s['sample']) == sample['sample']] other_targets = [s for s in samples if re.sub('-N\\d*$', '', s['sample']) == sample['sample']]
for s in other_targets: for s in other_targets:
sample[f"ct_{s['target'].lower()}"] = s['ct'] if isinstance(s['ct'], float) else 0.0 sample[f"ct_{s['target'].lower()}"] = s['ct'] if isinstance(s['ct'], float) else 0.0
# sample[f"{s['target'].lower()}_status"] = s['assessment']
try: try:
del sample['ct'] del sample['ct']
except KeyError: except KeyError:
@@ -2177,7 +2178,6 @@ class WastewaterArtic(BasicSubmission):
except AttributeError: except AttributeError:
plate_num = "1" plate_num = "1"
plate_num = plate_num.strip("-") plate_num = plate_num.strip("-")
# repeat_num = re.search(r"R(?P<repeat>\d)?$", "PBS20240426-2R").groups()[0]
try: try:
repeat_num = re.search(r"R(?P<repeat>\d)?$", processed).groups()[0] repeat_num = re.search(r"R(?P<repeat>\d)?$", processed).groups()[0]
except: except:
@@ -2663,16 +2663,6 @@ class BasicSample(BaseClass, LogMixin):
def delete(self): def delete(self):
raise AttributeError(f"Delete not implemented for {self.__class__}") raise AttributeError(f"Delete not implemented for {self.__class__}")
# @classmethod
# def get_searchables(cls) -> List[dict]:
# """
# Delivers a list of fields that can be used in fuzzy search.
#
# Returns:
# List[str]: List of fields.
# """
# return [dict(label="Submitter ID", field="submitter_id")]
@classmethod @classmethod
def samples_to_df(cls, sample_list: List[BasicSample], **kwargs) -> pd.DataFrame: def samples_to_df(cls, sample_list: List[BasicSample], **kwargs) -> pd.DataFrame:
""" """
@@ -2729,8 +2719,6 @@ class WastewaterSample(BasicSample):
Derivative wastewater sample Derivative wastewater sample
""" """
# searchables = BasicSample.searchables + ['ww_processing_num', 'ww_full_sample_id', 'rsl_number']
id = Column(INTEGER, ForeignKey('_basicsample.id'), primary_key=True) id = Column(INTEGER, ForeignKey('_basicsample.id'), primary_key=True)
ww_processing_num = Column(String(64)) #: wastewater processing number ww_processing_num = Column(String(64)) #: wastewater processing number
ww_full_sample_id = Column(String(64)) #: full id given by entrics ww_full_sample_id = Column(String(64)) #: full id given by entrics

View File

@@ -24,10 +24,25 @@ class BaseOmni(BaseModel):
return f"<{self.__class__.__name__}({self.__repr_name__})>" return f"<{self.__class__.__name__}({self.__repr_name__})>"
@classproperty @classproperty
def aliases(cls): def aliases(cls) -> List[str]:
"""
Gets other names the sql object of this class might go by.
Returns:
List[str]: List of names
"""
return cls.class_object.aliases return cls.class_object.aliases
def check_all_attributes(self, attributes: dict) -> bool: def check_all_attributes(self, attributes: dict) -> bool:
"""
Compares this pobject to dictionary of attributes to determine equality.
Args:
attributes (dict):
Returns:
bool: result
"""
# logger.debug(f"Incoming attributes: {attributes}") # logger.debug(f"Incoming attributes: {attributes}")
attributes = {k : v for k, v in attributes.items() if k in self.list_searchables.keys()} attributes = {k : v for k, v in attributes.items() if k in self.list_searchables.keys()}
for key, value in attributes.items(): for key, value in attributes.items():
@@ -47,7 +62,14 @@ class BaseOmni(BaseModel):
# logger.debug("Everything checks out, these are the same object.") # logger.debug("Everything checks out, these are the same object.")
return True return True
def __setattr__(self, key, value): def __setattr__(self, key: str, value: Any):
"""
Overrides built in dunder method
Args:
key (str):
value (Any):
"""
try: try:
class_value = getattr(self.class_object, key) class_value = getattr(self.class_object, key)
except AttributeError: except AttributeError:
@@ -151,12 +173,22 @@ class OmniSubmissionType(BaseOmni):
super().__init__(**data) super().__init__(**data)
self.instance_object = instance_object self.instance_object = instance_object
def to_dataframe_dict(self): @property
def dataframe_dict(self) -> dict:
"""
Dictionary of gui relevant values.
Returns:
dict: result
"""
return dict( return dict(
name=self.name name=self.name
) )
def to_sql(self): def to_sql(self):
"""
Convert this object to an instance of its class object.
"""
instance, new = self.class_object.query_or_create(name=self.name) instance, new = self.class_object.query_or_create(name=self.name)
instance.info_map = self.info_map instance.info_map = self.info_map
instance.defaults = self.defaults instance.defaults = self.defaults
@@ -191,12 +223,23 @@ class OmniReagentRole(BaseOmni):
super().__init__(**data) super().__init__(**data)
self.instance_object = instance_object self.instance_object = instance_object
def to_dataframe_dict(self): @property
def dataframe_dict(self) -> dict:
"""
Dictionary of gui relevant values.
Returns:
dict: result
"""
return dict( return dict(
name=self.name name=self.name
) )
def to_sql(self): def to_sql(self):
"""
Convert this object to an instance of its class object.
"""
instance, new = self.class_object.query_or_create(name=self.name) instance, new = self.class_object.query_or_create(name=self.name)
if new: if new:
instance.eol_ext = self.eol_ext instance.eol_ext = self.eol_ext
@@ -252,7 +295,14 @@ class OmniSubmissionTypeKitTypeAssociation(BaseOmni):
super().__init__(**data) super().__init__(**data)
self.instance_object = instance_object self.instance_object = instance_object
def to_dataframe_dict(self): @property
def dataframe_dict(self) -> dict:
"""
Dictionary of gui relevant values.
Returns:
dict: result
"""
if isinstance(self.submissiontype, OmniSubmissionType): if isinstance(self.submissiontype, OmniSubmissionType):
submissiontype = self.submissiontype.name submissiontype = self.submissiontype.name
else: else:
@@ -270,6 +320,10 @@ class OmniSubmissionTypeKitTypeAssociation(BaseOmni):
) )
def to_sql(self): def to_sql(self):
"""
Convert this object to an instance of its class object.
"""
# logger.debug(f"Self kittype: {self.submissiontype}") # logger.debug(f"Self kittype: {self.submissiontype}")
if issubclass(self.submissiontype.__class__, BaseOmni): if issubclass(self.submissiontype.__class__, BaseOmni):
submissiontype = SubmissionType.query(name=self.submissiontype.name) submissiontype = SubmissionType.query(name=self.submissiontype.name)
@@ -288,7 +342,13 @@ class OmniSubmissionTypeKitTypeAssociation(BaseOmni):
return instance return instance
@property @property
def list_searchables(self): def list_searchables(self) -> dict:
"""
Provides attributes for checking this object against a dictionary.
Returns:
dict: result
"""
if isinstance(self.kittype, OmniKitType): if isinstance(self.kittype, OmniKitType):
kit = self.kittype.name kit = self.kittype.name
else: else:
@@ -334,7 +394,14 @@ class OmniKitTypeReagentRoleAssociation(BaseOmni):
super().__init__(**data) super().__init__(**data)
self.instance_object = instance_object self.instance_object = instance_object
def to_dataframe_dict(self): @property
def dataframe_dict(self) -> dict:
"""
Dictionary of gui relevant values.
Returns:
dict: result
"""
if isinstance(self.submission_type, OmniSubmissionType): if isinstance(self.submission_type, OmniSubmissionType):
submission_type = self.submission_type.name submission_type = self.submission_type.name
else: else:
@@ -349,12 +416,16 @@ class OmniKitTypeReagentRoleAssociation(BaseOmni):
else: else:
reagent_role = self.reagent_role reagent_role = self.reagent_role
return dict( return dict(
reagent_role=reagent_role, reagentrole=reagent_role,
submission_type=submission_type, submissiontype=submission_type,
kit_type=kit_type kittype=kit_type
) )
def to_sql(self): def to_sql(self):
"""
Convert this object to an instance of its class object.
"""
if isinstance(self.reagent_role, OmniReagentRole): if isinstance(self.reagent_role, OmniReagentRole):
reagent_role = self.reagent_role.name reagent_role = self.reagent_role.name
else: else:
@@ -387,7 +458,13 @@ class OmniKitTypeReagentRoleAssociation(BaseOmni):
return instance return instance
@property @property
def list_searchables(self): def list_searchables(self) -> dict:
"""
Provides attributes for checking this object against a dictionary.
Returns:
dict: result
"""
if isinstance(self.kit_type, OmniKitType): if isinstance(self.kit_type, OmniKitType):
kit = self.kit_type.name kit = self.kit_type.name
else: else:
@@ -420,12 +497,23 @@ class OmniEquipmentRole(BaseOmni):
super().__init__(**data) super().__init__(**data)
self.instance_object = instance_object self.instance_object = instance_object
def to_dataframe_dict(self): @property
def dataframe_dict(self) -> dict:
"""
Dictionary of gui relevant values.
Returns:
dict: result
"""
return dict( return dict(
name=self.name name=self.name
) )
def to_sql(self): def to_sql(self):
"""
Convert this object to an instance of its class object.
"""
instance, new = self.class_object.query_or_create(name=self.name) instance, new = self.class_object.query_or_create(name=self.name)
return instance return instance
@@ -447,12 +535,23 @@ class OmniTips(BaseOmni):
super().__init__(**data) super().__init__(**data)
self.instance_object = instance_object self.instance_object = instance_object
def to_dataframe_dict(self): @property
def dataframe_dict(self) -> dict:
"""
Dictionary of gui relevant values.
Returns:
dict: result
"""
return dict( return dict(
name=self.name name=self.name
) )
def to_sql(self): def to_sql(self):
"""
Convert this object to an instance of its class object.
"""
instance, new = self.class_object.query_or_create(name=self.name) instance, new = self.class_object.query_or_create(name=self.name)
return instance return instance
@@ -475,13 +574,24 @@ class OmniTipRole(BaseOmni):
super().__init__(**data) super().__init__(**data)
self.instance_object = instance_object self.instance_object = instance_object
def to_dataframe_dict(self): @property
def dataframe_dict(self) -> dict:
"""
Dictionary of gui relevant values.
Returns:
dict: result
"""
return dict( return dict(
name=self.name, name=self.name,
tips=[item.name for item in self.tips] tips=[item.name for item in self.tips]
) )
def to_sql(self): def to_sql(self):
"""
Convert this object to an instance of its class object.
"""
instance, new = self.class_object.query_or_create(name=self.name) instance, new = self.class_object.query_or_create(name=self.name)
for tips in self.tips: for tips in self.tips:
tips.to_sql() tips.to_sql()
@@ -504,10 +614,17 @@ class OmniProcess(BaseOmni):
super().__init__(**data) super().__init__(**data)
self.instance_object = instance_object self.instance_object = instance_object
def to_dataframe_dict(self): @property
submissiontypes = [item.name for item in self.submission_types] def dataframe_dict(self) -> dict:
"""
Dictionary of gui relevant values.
Returns:
dict: result
"""
submissiontypes = [item if isinstance(item, str) else item.name for item in self.submission_types]
logger.debug(f"Submission Types: {submissiontypes}") logger.debug(f"Submission Types: {submissiontypes}")
equipmentroles = [item.name for item in self.equipment_roles] equipmentroles = [item if isinstance(item, str) else item.name for item in self.equipment_roles]
logger.debug(f"Equipment Roles: {equipmentroles}") logger.debug(f"Equipment Roles: {equipmentroles}")
return dict( return dict(
name=self.name, name=self.name,
@@ -523,6 +640,10 @@ class OmniProcess(BaseOmni):
return value return value
def to_sql(self): def to_sql(self):
"""
Convert this object to an instance of its class object.
"""
instance, new = self.class_object.query_or_create(name=self.name) instance, new = self.class_object.query_or_create(name=self.name)
for st in self.submission_types: for st in self.submission_types:
try: try:
@@ -548,7 +669,13 @@ class OmniProcess(BaseOmni):
return instance return instance
@property @property
def list_searchables(self): def list_searchables(self) -> dict:
"""
Provides attributes for checking this object against a dictionary.
Returns:
dict: result
"""
return dict(name=self.name) return dict(name=self.name)
@@ -572,17 +699,24 @@ class OmniKitType(BaseOmni):
super().__init__(**data) super().__init__(**data)
self.instance_object = instance_object self.instance_object = instance_object
def to_dataframe_dict(self): @property
def dataframe_dict(self) -> dict:
"""
Dictionary of gui relevant values.
Returns:
dict: result
"""
return dict( return dict(
name=self.name name=self.name
) )
def to_sql(self) -> KitType: def to_sql(self) -> KitType:
"""
Convert this object to an instance of its class object.
"""
kit, is_new = KitType.query_or_create(name=self.name) kit, is_new = KitType.query_or_create(name=self.name)
# if is_new:
# logger.debug(f"New kit made: {kit}")
# else:
# logger.debug(f"Kit retrieved: {kit}")
new_rr = [] new_rr = []
for rr_assoc in self.kit_reagentrole_associations: for rr_assoc in self.kit_reagentrole_associations:
new_assoc = rr_assoc.to_sql() new_assoc = rr_assoc.to_sql()
@@ -603,9 +737,6 @@ class OmniKitType(BaseOmni):
if new_process not in new_processes: if new_process not in new_processes:
new_processes.append(new_process) new_processes.append(new_process)
kit.processes = new_processes kit.processes = new_processes
# logger.debug(f"Kit: {pformat(kit.__dict__)}")
# for item in kit.kit_reagentrole_associations:
# logger.debug(f"KTRRassoc: {item.__dict__}")
return kit return kit
@@ -622,7 +753,14 @@ class OmniOrganization(BaseOmni):
super().__init__(**data) super().__init__(**data)
self.instance_object = instance_object self.instance_object = instance_object
def to_dataframe_dict(self): @property
def dataframe_dict(self) -> dict:
"""
Dictionary of gui relevant values.
Returns:
dict: result
"""
return dict( return dict(
name=self.name, name=self.name,
cost_centre=self.cost_centre, cost_centre=self.cost_centre,
@@ -639,14 +777,27 @@ class OmniContact(BaseOmni):
phone: str = Field(default="", description="property") phone: str = Field(default="", description="property")
@property @property
def list_searchables(self): def list_searchables(self) -> dict:
"""
Provides attributes for checking this object against a dictionary.
Returns:
dict: result
"""
return dict(name=self.name, email=self.email) return dict(name=self.name, email=self.email)
def __init__(self, instance_object: Any, **data): def __init__(self, instance_object: Any, **data):
super().__init__(**data) super().__init__(**data)
self.instance_object = instance_object self.instance_object = instance_object
def to_dataframe_dict(self): @property
def dataframe_dict(self) -> dict:
"""
Dictionary of gui relevant values.
Returns:
dict: result
"""
return dict( return dict(
name=self.name, name=self.name,
email=self.email, email=self.email,
@@ -654,9 +805,9 @@ class OmniContact(BaseOmni):
) )
def to_sql(self): def to_sql(self):
"""
Convert this object to an instance of its class object.
"""
contact, is_new = Contact.query_or_create(name=self.name, email=self.email, phone=self.phone) contact, is_new = Contact.query_or_create(name=self.name, email=self.email, phone=self.phone)
# if is_new:
# logger.debug(f"New contact made: {contact}")
# else:
# logger.debug(f"Contact retrieved: {contact}")
return contact return contact

View File

@@ -4,6 +4,8 @@ Contains all operations for creating charts, graphs and visual effects.
from datetime import timedelta, date from datetime import timedelta, date
from pathlib import Path from pathlib import Path
from typing import Generator from typing import Generator
import plotly
from PyQt6.QtWidgets import QWidget from PyQt6.QtWidgets import QWidget
import pandas as pd, logging import pandas as pd, logging
from plotly.graph_objects import Figure from plotly.graph_objects import Figure
@@ -126,8 +128,8 @@ class CustomFigure(Figure):
html = f'<html><body>' html = f'<html><body>'
if self is not None: if self is not None:
# NOTE: Just cannot get this load from string to freaking work. # NOTE: Just cannot get this load from string to freaking work.
html += self.to_html(include_plotlyjs='cdn', full_html=False) # html += self.to_html(include_plotlyjs='cdn', full_html=False)
# html += plotly.offline.plot(self, output_type='div', include_plotlyjs=True) html += plotly.offline.plot(self, output_type='div', include_plotlyjs="cdn")
else: else:
html += "<h1>No data was retrieved for the given parameters.</h1>" html += "<h1>No data was retrieved for the given parameters.</h1>"
html += '</body></html>' html += '</body></html>'

View File

@@ -6,7 +6,7 @@ from json.decoder import JSONDecodeError
from datetime import datetime, timedelta from datetime import datetime, timedelta
from pprint import pformat from pprint import pformat
from typing import Any, List, Literal from typing import Any, List, Literal
from PyQt6.QtCore import QSortFilterProxyModel, Qt from PyQt6.QtCore import QSortFilterProxyModel, Qt, QModelIndex
from PyQt6.QtGui import QAction, QCursor from PyQt6.QtGui import QAction, QCursor
from PyQt6.QtWidgets import ( from PyQt6.QtWidgets import (
QLabel, QDialog, QLabel, QDialog,
@@ -114,7 +114,16 @@ class ManagerWindow(QDialog):
# logger.debug(f"Instance: {self.instance}") # logger.debug(f"Instance: {self.instance}")
self.update_data() self.update_data()
def update_instance(self, initial: bool = False): def update_instance(self, initial: bool = False) -> None:
"""
Gets the proper instance of this object's class object.
Args:
initial (bool): Whether this is the initial creation of this object.
Returns:
None
"""
if self.add_edit == "edit" or initial: if self.add_edit == "edit" or initial:
try: try:
# logger.debug(f"Querying with {self.options.currentText()}") # logger.debug(f"Querying with {self.options.currentText()}")
@@ -146,6 +155,7 @@ class ManagerWindow(QDialog):
[item for item in self.findChildren(QDialogButtonBox)] [item for item in self.findChildren(QDialogButtonBox)]
for item in deletes: for item in deletes:
item.setParent(None) item.setParent(None)
logger.debug(f"Self.omni_object: {self.omni_object}")
fields = self.omni_object.__class__.model_fields fields = self.omni_object.__class__.model_fields
for key, info in fields.items(): for key, info in fields.items():
# logger.debug(f"Attempting to set {key}, {info} widget") # logger.debug(f"Attempting to set {key}, {info} widget")
@@ -193,14 +203,22 @@ class ManagerWindow(QDialog):
# logger.debug(f"Instance coming from parsed form: {self.omni_object.__dict__}") # logger.debug(f"Instance coming from parsed form: {self.omni_object.__dict__}")
return self.omni_object return self.omni_object
def add_new(self): def add_new(self) -> None:
"""
Creates a new instance of this object's class object.
Returns:
None
"""
new_instance = self.class_object() new_instance = self.class_object()
self.instance = new_instance self.instance = new_instance
self.update_options() self.update_options()
class EditProperty(QWidget): class EditProperty(QWidget):
"""
Class to manage info items of SQL objects.
"""
def __init__(self, parent: ManagerWindow, key: str, column_type: Any, value): def __init__(self, parent: ManagerWindow, key: str, column_type: Any, value):
super().__init__(parent) super().__init__(parent)
self.label = QLabel(key.title().replace("_", " ")) self.label = QLabel(key.title().replace("_", " "))
@@ -245,7 +263,13 @@ class EditProperty(QWidget):
self.layout.addWidget(self.widget, 0, 1, 1, 3) self.layout.addWidget(self.widget, 0, 1, 1, 3)
self.setLayout(self.layout) self.setLayout(self.layout)
def parse_form(self): def parse_form(self) -> dict:
"""
Gets values from this EditProperty form.
Returns:
dict: Dictionary of values.
"""
# logger.debug(f"Parsing widget {self.objectName()}: {type(self.widget)}") # logger.debug(f"Parsing widget {self.objectName()}: {type(self.widget)}")
match self.widget: match self.widget:
case QLineEdit(): case QLineEdit():
@@ -269,7 +293,7 @@ class EditRelationship(QWidget):
from backend.db import models from backend.db import models
super().__init__(parent) super().__init__(parent)
self.class_object = getattr(models, class_object) self.class_object = getattr(models, class_object)
logger.debug(f"Attempt value: {value}") # logger.debug(f"Attempt value: {value}")
# logger.debug(f"Class object: {self.class_object}") # logger.debug(f"Class object: {self.class_object}")
self.setParent(parent) self.setParent(parent)
# logger.debug(f"Edit relationship class_object: {self.class_object}") # logger.debug(f"Edit relationship class_object: {self.class_object}")
@@ -317,7 +341,13 @@ class EditRelationship(QWidget):
self.setLayout(self.layout) self.setLayout(self.layout)
self.set_data() self.set_data()
def update_buttons(self): def update_buttons(self) -> None:
"""
Enables/disables buttons based on whether property is a list and has data.
Returns:
None
"""
if not self.relationship.property.uselist and len(self.data) >= 1: 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)}") # logger.debug(f"Property {self.relationship} doesn't use list and data is of length: {len(self.data)}")
self.add_button.setEnabled(False) self.add_button.setEnabled(False)
@@ -326,14 +356,23 @@ class EditRelationship(QWidget):
self.add_button.setEnabled(True) self.add_button.setEnabled(True)
self.existing_button.setEnabled(True) self.existing_button.setEnabled(True)
def parse_row(self, x): def parse_row(self, x: QModelIndex) -> None:
"""
Args:
x ():
Returns:
"""
context = {item: x.sibling(x.row(), self.df.columns.get_loc(item)).data() for item in self.df.columns} context = {item: x.sibling(x.row(), self.df.columns.get_loc(item)).data() for item in self.df.columns}
# logger.debug(f"Context: {pformat(context)}")
try: try:
object = self.class_object.query(**context) object = self.class_object.query(**context)
except KeyError: except KeyError:
object = None object = None
self.widget.doubleClicked.disconnect() self.widget.doubleClicked.disconnect()
self.add_edit(instance=object) self.add_new(instance=object)
def add_new(self, instance: Any = None, add_edit: Literal["add", "edit"] = "add", index: int | None = None): def add_new(self, instance: Any = None, add_edit: Literal["add", "edit"] = "add", index: int | None = None):
if add_edit == "edit": if add_edit == "edit":
@@ -388,12 +427,13 @@ 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.dataframe_dict for item in self.data]
except AttributeError: except AttributeError as e:
logger.error(e)
records = [] records = []
# logger.debug(f"Records: {records}") logger.debug(f"Records: {records}")
self.df = DataFrame.from_records(records) self.df = DataFrame.from_records(records)
try: try:
self.columns_of_interest = [dict(name=item, column=self.df.columns.get_loc(item)) for item in self.extras] self.columns_of_interest = [dict(name=item, column=self.df.columns.get_loc(item)) for item in self.extras]