Various bug fixes and streamlining.
This commit is contained in:
@@ -26,7 +26,7 @@ class RSLNamer(object):
|
||||
if self.submission_type is None:
|
||||
# logger.debug("Creating submission type because none exists")
|
||||
self.submission_type = self.retrieve_submission_type(filename=filename)
|
||||
logger.debug(f"got submission type: {self.submission_type}")
|
||||
logger.info(f"got submission type: {self.submission_type}")
|
||||
if self.submission_type is not None:
|
||||
# logger.debug("Retrieving BasicSubmission subclass")
|
||||
self.sub_object = BasicSubmission.find_polymorphic_subclass(polymorphic_identity=self.submission_type)
|
||||
@@ -48,36 +48,41 @@ class RSLNamer(object):
|
||||
Returns:
|
||||
str: parsed submission type
|
||||
"""
|
||||
def st_from_path(filename:Path) -> str:
|
||||
logger.debug(f"Using path method for {filename}.")
|
||||
if filename.exists():
|
||||
wb = load_workbook(filename)
|
||||
try:
|
||||
# NOTE: Gets first category in the metadata.
|
||||
submission_type = next(item.strip().title() for item in wb.properties.category.split(";"))
|
||||
except (StopIteration, AttributeError):
|
||||
sts = {item.name: item.get_template_file_sheets() for item in SubmissionType.query()}
|
||||
try:
|
||||
submission_type = next(k.title() for k,v in sts.items() if wb.sheetnames==v)
|
||||
except StopIteration:
|
||||
# NOTE: On failure recurse using filename as string for string method
|
||||
submission_type = cls.retrieve_submission_type(filename=filename.stem.__str__())
|
||||
else:
|
||||
submission_type = cls.retrieve_submission_type(filename=filename.stem.__str__())
|
||||
return submission_type
|
||||
def st_from_str(filename:str) -> str:
|
||||
regex = BasicSubmission.construct_regex()
|
||||
logger.debug(f"Using string method for {filename}.")
|
||||
logger.debug(f"Using regex: {regex}")
|
||||
m = regex.search(filename)
|
||||
print(m)
|
||||
try:
|
||||
submission_type = m.lastgroup
|
||||
logger.debug(f"Got submission type: {submission_type}")
|
||||
except AttributeError as e:
|
||||
submission_type = None
|
||||
logger.critical(f"No submission type found or submission type found!: {e}")
|
||||
return submission_type
|
||||
match filename:
|
||||
case Path():
|
||||
logger.debug(f"Using path method for {filename}.")
|
||||
if filename.exists():
|
||||
wb = load_workbook(filename)
|
||||
try:
|
||||
submission_type = [item.strip().title() for item in wb.properties.category.split(";")][0]
|
||||
except AttributeError:
|
||||
try:
|
||||
sts = {item.name: item.get_template_file_sheets() for item in SubmissionType.query()}
|
||||
for k, v in sts.items():
|
||||
# This gets the *first* submission type that matches the sheet names in the workbook
|
||||
if wb.sheetnames == v:
|
||||
submission_type = k.title()
|
||||
break
|
||||
except:
|
||||
# On failure recurse using filename as string for string method
|
||||
submission_type = cls.retrieve_submission_type(filename=filename.stem.__str__())
|
||||
else:
|
||||
submission_type = cls.retrieve_submission_type(filename=filename.stem.__str__())
|
||||
submission_type = st_from_path(filename=filename)
|
||||
case str():
|
||||
regex = BasicSubmission.construct_regex()
|
||||
logger.debug(f"Using string method for {filename}.")
|
||||
logger.debug(f"Using regex: {regex}")
|
||||
m = regex.search(filename)
|
||||
try:
|
||||
submission_type = m.lastgroup
|
||||
logger.debug(f"Got submission type: {submission_type}")
|
||||
except AttributeError as e:
|
||||
logger.critical(f"No submission type found or submission type found!: {e}")
|
||||
submission_type = st_from_str(filename=filename)
|
||||
case _:
|
||||
submission_type = None
|
||||
try:
|
||||
@@ -93,6 +98,7 @@ class RSLNamer(object):
|
||||
message="Please select submission type from list below.", obj_type=SubmissionType)
|
||||
if dlg.exec():
|
||||
submission_type = dlg.parse_form()
|
||||
print(submission_type)
|
||||
submission_type = submission_type.replace("_", " ")
|
||||
return submission_type
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ from datetime import date, datetime, timedelta
|
||||
from dateutil.parser import parse
|
||||
from dateutil.parser import ParserError
|
||||
from typing import List, Tuple, Literal
|
||||
from types import GeneratorType
|
||||
from . import RSLNamer
|
||||
from pathlib import Path
|
||||
from tools import check_not_nan, convert_nans_to_nones, Report, Result
|
||||
@@ -49,7 +48,6 @@ class PydReagent(BaseModel):
|
||||
def rescue_type_with_lookup(cls, value, values):
|
||||
if value is None and values.data['lot'] is not None:
|
||||
try:
|
||||
# return lookup_reagents(ctx=values.data['ctx'], lot_number=values.data['lot']).name
|
||||
return Reagent.query(lot_number=values.data['lot'].name)
|
||||
except AttributeError:
|
||||
return value
|
||||
@@ -222,7 +220,8 @@ class PydSample(BaseModel, extra='allow'):
|
||||
fields = list(self.model_fields.keys()) + list(self.model_extra.keys())
|
||||
return {k: getattr(self, k) for k in fields}
|
||||
|
||||
def toSQL(self, submission: BasicSubmission | str = None) -> Tuple[BasicSample, Result]:
|
||||
def toSQL(self, submission: BasicSubmission | str = None) -> Tuple[
|
||||
BasicSample, List[SubmissionSampleAssociation], Result | None]:
|
||||
"""
|
||||
Converts this instance into a backend.db.models.submissions.Sample object
|
||||
|
||||
@@ -238,6 +237,7 @@ class PydSample(BaseModel, extra='allow'):
|
||||
instance = BasicSample.query_or_create(sample_type=self.sample_type, submitter_id=self.submitter_id)
|
||||
for key, value in self.__dict__.items():
|
||||
match key:
|
||||
# NOTE: row, column go in the association
|
||||
case "row" | "column":
|
||||
continue
|
||||
case _:
|
||||
@@ -259,7 +259,6 @@ class PydSample(BaseModel, extra='allow'):
|
||||
**self.model_extra)
|
||||
# logger.debug(f"Using submission_sample_association: {association}")
|
||||
try:
|
||||
# instance.sample_submission_associations.append(association)
|
||||
out_associations.append(association)
|
||||
except IntegrityError as e:
|
||||
logger.error(f"Could not attach submission sample association due to: {e}")
|
||||
@@ -316,10 +315,10 @@ class PydEquipment(BaseModel, extra='ignore'):
|
||||
def make_empty_list(cls, value):
|
||||
# logger.debug(f"Pydantic value: {value}")
|
||||
value = convert_nans_to_nones(value)
|
||||
if value is None:
|
||||
value = ['']
|
||||
if len(value) == 0:
|
||||
if not value:
|
||||
value = ['']
|
||||
# if len(value) == 0:
|
||||
# value = ['']
|
||||
try:
|
||||
value = [item.strip() for item in value]
|
||||
except AttributeError:
|
||||
@@ -337,7 +336,7 @@ class PydEquipment(BaseModel, extra='ignore'):
|
||||
Tuple[Equipment, SubmissionEquipmentAssociation]: SQL objects
|
||||
"""
|
||||
if isinstance(submission, str):
|
||||
logger.info(f"Got string, querying {submission}")
|
||||
# logger.debug(f"Got string, querying {submission}")
|
||||
submission = BasicSubmission.query(rsl_number=submission)
|
||||
equipment = Equipment.query(asset_number=self.asset_number)
|
||||
if equipment is None:
|
||||
@@ -347,7 +346,7 @@ class PydEquipment(BaseModel, extra='ignore'):
|
||||
# NOTE: Need to make sure the same association is not added to the submission
|
||||
try:
|
||||
assoc = SubmissionEquipmentAssociation.query(equipment_id=equipment.id, submission_id=submission.id,
|
||||
role=self.role, limit=1)
|
||||
role=self.role, limit=1)
|
||||
except TypeError as e:
|
||||
logger.error(f"Couldn't get association due to {e}, returning...")
|
||||
return equipment, None
|
||||
@@ -400,7 +399,7 @@ class PydSubmission(BaseModel, extra='allow'):
|
||||
equipment: List[PydEquipment] | None = []
|
||||
cost_centre: dict | None = Field(default=dict(value=None, missing=True), validate_default=True)
|
||||
contact: dict | None = Field(default=dict(value=None, missing=True), validate_default=True)
|
||||
tips: List[PydTips] | None =[]
|
||||
tips: List[PydTips] | None = []
|
||||
|
||||
@field_validator("tips", mode="before")
|
||||
@classmethod
|
||||
@@ -409,7 +408,7 @@ class PydSubmission(BaseModel, extra='allow'):
|
||||
if isinstance(value, dict):
|
||||
value = value['value']
|
||||
if isinstance(value, Generator):
|
||||
logger.debug("We have a generator")
|
||||
# logger.debug("We have a generator")
|
||||
return [PydTips(**tips) for tips in value]
|
||||
if not value:
|
||||
return []
|
||||
@@ -466,7 +465,7 @@ class PydSubmission(BaseModel, extra='allow'):
|
||||
return dict(value=datetime.fromordinal(datetime(1900, 1, 1).toordinal() + value['value'] - 2).date(),
|
||||
missing=True)
|
||||
case str():
|
||||
string = re.sub(r"(_|-)\d$", "", value['value'])
|
||||
string = re.sub(r"(_|-)\d(R\d)?$", "", value['value'])
|
||||
try:
|
||||
output = dict(value=parse(string).date(), missing=True)
|
||||
except ParserError as e:
|
||||
@@ -568,6 +567,7 @@ class PydSubmission(BaseModel, extra='allow'):
|
||||
else:
|
||||
raise ValueError(f"No extraction kit found.")
|
||||
if value is None:
|
||||
# NOTE: Kit selection is done in the parser, so should not be necessary here.
|
||||
return dict(value=None, missing=True)
|
||||
return value
|
||||
|
||||
@@ -575,7 +575,7 @@ class PydSubmission(BaseModel, extra='allow'):
|
||||
@classmethod
|
||||
def make_submission_type(cls, value, values):
|
||||
if not isinstance(value, dict):
|
||||
value = {"value": value}
|
||||
value = dict(value=value)
|
||||
if check_not_nan(value['value']):
|
||||
value = value['value'].title()
|
||||
return dict(value=value, missing=False)
|
||||
@@ -593,6 +593,8 @@ class PydSubmission(BaseModel, extra='allow'):
|
||||
@field_validator("submission_category")
|
||||
@classmethod
|
||||
def rescue_category(cls, value, values):
|
||||
if isinstance(value['value'], str):
|
||||
value['value'] = value['value'].title()
|
||||
if value['value'] not in ["Research", "Diagnostic", "Surveillance", "Validation"]:
|
||||
value['value'] = values.data['submission_type']['value']
|
||||
return value
|
||||
@@ -600,18 +602,16 @@ class PydSubmission(BaseModel, extra='allow'):
|
||||
@field_validator("reagents", mode="before")
|
||||
@classmethod
|
||||
def expand_reagents(cls, value):
|
||||
# print(f"\n{type(value)}\n")
|
||||
if isinstance(value, Generator):
|
||||
logger.debug("We have a generator")
|
||||
# logger.debug("We have a generator")
|
||||
return [PydReagent(**reagent) for reagent in value]
|
||||
return value
|
||||
|
||||
@field_validator("samples", mode="before")
|
||||
@classmethod
|
||||
def expand_samples(cls, value):
|
||||
# print(f"\n{type(value)}\n")
|
||||
if isinstance(value, Generator):
|
||||
logger.debug("We have a generator")
|
||||
# logger.debug("We have a generator")
|
||||
return [PydSample(**sample) for sample in value]
|
||||
return value
|
||||
|
||||
@@ -619,11 +619,10 @@ class PydSubmission(BaseModel, extra='allow'):
|
||||
@classmethod
|
||||
def assign_ids(cls, value):
|
||||
starting_id = SubmissionSampleAssociation.autoincrement_id()
|
||||
output = []
|
||||
for iii, sample in enumerate(value, start=starting_id):
|
||||
# NOTE: Why is this a list? Answer: to zip with the lists of rows and columns in case of multiple of the same sample.
|
||||
sample.assoc_id = [iii]
|
||||
output.append(sample)
|
||||
return output
|
||||
return value
|
||||
|
||||
@field_validator("cost_centre", mode="before")
|
||||
@classmethod
|
||||
@@ -672,7 +671,7 @@ class PydSubmission(BaseModel, extra='allow'):
|
||||
else:
|
||||
return value
|
||||
|
||||
def __init__(self, run_custom:bool=False, **data):
|
||||
def __init__(self, run_custom: bool = False, **data):
|
||||
super().__init__(**data)
|
||||
# NOTE: this could also be done with default_factory
|
||||
logger.debug(data)
|
||||
@@ -682,7 +681,6 @@ class PydSubmission(BaseModel, extra='allow'):
|
||||
if run_custom:
|
||||
self.submission_object.custom_validation(pyd=self)
|
||||
|
||||
|
||||
def set_attribute(self, key: str, value):
|
||||
"""
|
||||
Better handling of attribute setting.
|
||||
@@ -742,7 +740,7 @@ class PydSubmission(BaseModel, extra='allow'):
|
||||
output = {k: self.filter_field(k) for k in fields}
|
||||
return output
|
||||
|
||||
def filter_field(self, key:str):
|
||||
def filter_field(self, key: str):
|
||||
item = getattr(self, key)
|
||||
# logger.debug(f"Attempting deconstruction of {key}: {item} with type {type(item)}")
|
||||
match item:
|
||||
@@ -796,8 +794,6 @@ class PydSubmission(BaseModel, extra='allow'):
|
||||
continue
|
||||
# logger.debug(f"Setting {key} to {value}")
|
||||
match key:
|
||||
# case "custom":
|
||||
# instance.custom = value
|
||||
case "reagents":
|
||||
if report.results[0].code == 1:
|
||||
instance.submission_reagent_associations = []
|
||||
@@ -833,7 +829,6 @@ class PydSubmission(BaseModel, extra='allow'):
|
||||
except AttributeError:
|
||||
continue
|
||||
if association is not None and association not in instance.submission_tips_associations:
|
||||
# association.save()
|
||||
instance.submission_tips_associations.append(association)
|
||||
case item if item in instance.jsons():
|
||||
# logger.debug(f"{item} is a json.")
|
||||
@@ -877,16 +872,9 @@ class PydSubmission(BaseModel, extra='allow'):
|
||||
instance.run_cost = instance.run_cost - sum(discounts)
|
||||
except Exception as e:
|
||||
logger.error(f"An unknown exception occurred when calculating discounts: {e}")
|
||||
# We need to make sure there's a proper rsl plate number
|
||||
# logger.debug(f"We've got a total cost of {instance.run_cost}")
|
||||
# try:
|
||||
# logger.debug(f"Constructed instance: {instance}")
|
||||
# except AttributeError as e:
|
||||
# logger.debug(f"Something went wrong constructing instance {self.rsl_plate_num}: {e}")
|
||||
# logger.debug(f"Constructed submissions message: {msg}")
|
||||
return instance, report
|
||||
|
||||
def to_form(self, parent: QWidget, disable:list|None=None):
|
||||
def to_form(self, parent: QWidget, disable: list | None = None):
|
||||
"""
|
||||
Converts this instance into a frontend.widgets.submission_widget.SubmissionFormWidget
|
||||
|
||||
@@ -1014,7 +1002,6 @@ class PydOrganization(BaseModel):
|
||||
value = [item.to_sql() for item in getattr(self, field)]
|
||||
case _:
|
||||
value = getattr(self, field)
|
||||
# instance.set_attribute(name=field, value=value)
|
||||
instance.__setattr__(name=field, value=value)
|
||||
return instance
|
||||
|
||||
|
||||
Reference in New Issue
Block a user