Mid code cleanup
This commit is contained in:
@@ -11,7 +11,7 @@ from typing import Any, List
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from tools import report_result
|
from tools import report_result
|
||||||
|
|
||||||
# Load testing environment
|
# NOTE: Load testing environment
|
||||||
if 'pytest' in sys.modules:
|
if 'pytest' in sys.modules:
|
||||||
sys.path.append(Path(__file__).parents[4].absolute().joinpath("tests").__str__())
|
sys.path.append(Path(__file__).parents[4].absolute().joinpath("tests").__str__())
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@ class BaseClass(Base):
|
|||||||
"""
|
"""
|
||||||
Abstract class to pass ctx values to all SQLAlchemy objects.
|
Abstract class to pass ctx values to all SQLAlchemy objects.
|
||||||
"""
|
"""
|
||||||
__abstract__ = True #: Will not be added to DB
|
__abstract__ = True #: NOTE: Will not be added to DB
|
||||||
|
|
||||||
__table_args__ = {'extend_existing': True} #: Will only add new columns
|
__table_args__ = {'extend_existing': True} #: Will only add new columns
|
||||||
|
|
||||||
@@ -168,6 +168,7 @@ class BaseClass(Base):
|
|||||||
logger.error(f"Error message: {type(e)}")
|
logger.error(f"Error message: {type(e)}")
|
||||||
self.__database_session__.rollback()
|
self.__database_session__.rollback()
|
||||||
report.add_result(Result(msg=e, status="Critical"))
|
report.add_result(Result(msg=e, status="Critical"))
|
||||||
|
return report
|
||||||
|
|
||||||
|
|
||||||
class ConfigItem(BaseClass):
|
class ConfigItem(BaseClass):
|
||||||
@@ -202,5 +203,6 @@ from .organizations import *
|
|||||||
from .kits import *
|
from .kits import *
|
||||||
from .submissions import *
|
from .submissions import *
|
||||||
|
|
||||||
# NOTE: Add a creator to the submission for reagent association.
|
# NOTE: Add a creator to the submission for reagent association. Assigned here due to circular import constraints.
|
||||||
|
# https://docs.sqlalchemy.org/en/20/orm/extensions/associationproxy.html#sqlalchemy.ext.associationproxy.association_proxy.params.creator
|
||||||
BasicSubmission.reagents.creator = lambda reg: SubmissionReagentAssociation(reagent=reg)
|
BasicSubmission.reagents.creator = lambda reg: SubmissionReagentAssociation(reagent=reg)
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ class Control(BaseClass):
|
|||||||
}
|
}
|
||||||
return output
|
return output
|
||||||
|
|
||||||
def convert_by_mode(self, mode: Literal['kraken', 'matches', 'contains']) -> list[dict]:
|
def convert_by_mode(self, mode: Literal['kraken', 'matches', 'contains']) -> List[dict]:
|
||||||
"""
|
"""
|
||||||
split this instance into analysis types for controls graphs
|
split this instance into analysis types for controls graphs
|
||||||
|
|
||||||
@@ -169,7 +169,7 @@ class Control(BaseClass):
|
|||||||
mode (str): analysis type, 'contains', etc
|
mode (str): analysis type, 'contains', etc
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
list[dict]: list of records
|
List[dict]: list of records
|
||||||
"""
|
"""
|
||||||
output = []
|
output = []
|
||||||
# logger.debug("load json string for mode (i.e. contains, matches, kraken2)")
|
# logger.debug("load json string for mode (i.e. contains, matches, kraken2)")
|
||||||
|
|||||||
@@ -263,7 +263,6 @@ class KitType(BaseClass):
|
|||||||
for k, v in self.construct_xl_map_for_use(submission_type=submission_type):
|
for k, v in self.construct_xl_map_for_use(submission_type=submission_type):
|
||||||
# logger.debug(f"Value: {v}")
|
# logger.debug(f"Value: {v}")
|
||||||
try:
|
try:
|
||||||
# assoc = [item for item in self.kit_reagentrole_associations if item.reagent_role.name == k][0]
|
|
||||||
assoc = next(item for item in self.kit_reagentrole_associations if item.reagent_role.name == k)
|
assoc = next(item for item in self.kit_reagentrole_associations if item.reagent_role.name == k)
|
||||||
except StopIteration as e:
|
except StopIteration as e:
|
||||||
continue
|
continue
|
||||||
@@ -272,10 +271,8 @@ class KitType(BaseClass):
|
|||||||
base_dict['reagent roles'].append(v)
|
base_dict['reagent roles'].append(v)
|
||||||
for k, v in submission_type.construct_equipment_map():
|
for k, v in submission_type.construct_equipment_map():
|
||||||
try:
|
try:
|
||||||
# assoc = [item for item in submission_type.submissiontype_equipmentrole_associations if
|
|
||||||
# item.equipment_role.name == k][0]
|
|
||||||
assoc = next(item for item in submission_type.submissiontype_equipmentrole_associations if
|
assoc = next(item for item in submission_type.submissiontype_equipmentrole_associations if
|
||||||
item.equipment_role.name == k)
|
item.equipment_role.name == k)
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
continue
|
continue
|
||||||
for kk, vv in assoc.to_export_dict(kit_type=self).items():
|
for kk, vv in assoc.to_export_dict(kit_type=self).items():
|
||||||
@@ -292,7 +289,7 @@ class ReagentRole(BaseClass):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
id = Column(INTEGER, primary_key=True) #: primary key
|
id = Column(INTEGER, primary_key=True) #: primary key
|
||||||
name = Column(String(64)) #: name of reagent type
|
name = Column(String(64)) #: name of role reagent plays
|
||||||
instances = relationship("Reagent", back_populates="role",
|
instances = relationship("Reagent", back_populates="role",
|
||||||
secondary=reagentroles_reagents) #: concrete instances of this reagent type
|
secondary=reagentroles_reagents) #: concrete instances of this reagent type
|
||||||
eol_ext = Column(Interval()) #: extension of life interval
|
eol_ext = Column(Interval()) #: extension of life interval
|
||||||
@@ -747,15 +744,12 @@ class SubmissionType(BaseClass):
|
|||||||
Returns:
|
Returns:
|
||||||
dict: Map equipment locations in excel sheet
|
dict: Map equipment locations in excel sheet
|
||||||
"""
|
"""
|
||||||
# output = {}
|
|
||||||
# logger.debug("Iterating through equipment roles")
|
# logger.debug("Iterating through equipment roles")
|
||||||
for item in self.submissiontype_equipmentrole_associations:
|
for item in self.submissiontype_equipmentrole_associations:
|
||||||
emap = item.uses
|
emap = item.uses
|
||||||
if emap is None:
|
if emap is None:
|
||||||
emap = {}
|
emap = {}
|
||||||
# output[item.equipment_role.name] = emap
|
|
||||||
yield item.equipment_role.name, emap
|
yield item.equipment_role.name, emap
|
||||||
# return output
|
|
||||||
|
|
||||||
def construct_tips_map(self) -> Generator[str, dict]:
|
def construct_tips_map(self) -> Generator[str, dict]:
|
||||||
"""
|
"""
|
||||||
@@ -764,14 +758,11 @@ class SubmissionType(BaseClass):
|
|||||||
Returns:
|
Returns:
|
||||||
dict: Tip locations in the excel sheet.
|
dict: Tip locations in the excel sheet.
|
||||||
"""
|
"""
|
||||||
# output = {}
|
|
||||||
for item in self.submissiontype_tiprole_associations:
|
for item in self.submissiontype_tiprole_associations:
|
||||||
tmap = item.uses
|
tmap = item.uses
|
||||||
if tmap is None:
|
if tmap is None:
|
||||||
tmap = {}
|
tmap = {}
|
||||||
# output[item.tip_role.name] = tmap
|
|
||||||
yield item.tip_role.name, tmap
|
yield item.tip_role.name, tmap
|
||||||
# return output
|
|
||||||
|
|
||||||
def get_equipment(self, extraction_kit: str | KitType | None = None) -> List['PydEquipmentRole']:
|
def get_equipment(self, extraction_kit: str | KitType | None = None) -> List['PydEquipmentRole']:
|
||||||
"""
|
"""
|
||||||
@@ -1035,7 +1026,7 @@ class SubmissionTypeKitTypeAssociation(BaseClass):
|
|||||||
exclude = ['_sa_instance_state', 'submission_types_id', 'kits_id', 'submission_type', 'kit_type']
|
exclude = ['_sa_instance_state', 'submission_types_id', 'kits_id', 'submission_type', 'kit_type']
|
||||||
base_dict = {k: v for k, v in self.__dict__.items() if k not in exclude}
|
base_dict = {k: v for k, v in self.__dict__.items() if k not in exclude}
|
||||||
base_dict['kit_type'] = self.kit_type.to_export_dict(submission_type=self.submission_type)
|
base_dict['kit_type'] = self.kit_type.to_export_dict(submission_type=self.submission_type)
|
||||||
logger.debug(f"STKTA returning: {base_dict}")
|
# logger.debug(f"STKTA returning: {base_dict}")
|
||||||
return base_dict
|
return base_dict
|
||||||
|
|
||||||
|
|
||||||
@@ -1073,7 +1064,7 @@ class KitTypeReagentRoleAssociation(BaseClass):
|
|||||||
return f"<KitTypeReagentRoleAssociation({self.kit_type} & {self.reagent_role})>"
|
return f"<KitTypeReagentRoleAssociation({self.kit_type} & {self.reagent_role})>"
|
||||||
|
|
||||||
@validates('required')
|
@validates('required')
|
||||||
def validate_age(self, key, value):
|
def validate_required(self, key, value):
|
||||||
"""
|
"""
|
||||||
Ensures only 1 & 0 used in 'required'
|
Ensures only 1 & 0 used in 'required'
|
||||||
|
|
||||||
@@ -1243,7 +1234,6 @@ class SubmissionReagentAssociation(BaseClass):
|
|||||||
match submission:
|
match submission:
|
||||||
case BasicSubmission() | str():
|
case BasicSubmission() | str():
|
||||||
if isinstance(submission, str):
|
if isinstance(submission, str):
|
||||||
# submission = BasicSubmission.query(rsl_number=submission)
|
|
||||||
submission = BasicSubmission.query(rsl_plate_num=submission)
|
submission = BasicSubmission.query(rsl_plate_num=submission)
|
||||||
# logger.debug(f"Lookup SubmissionReagentAssociation by submission BasicSubmission {submission}")
|
# logger.debug(f"Lookup SubmissionReagentAssociation by submission BasicSubmission {submission}")
|
||||||
query = query.filter(cls.submission == submission)
|
query = query.filter(cls.submission == submission)
|
||||||
@@ -1424,7 +1414,7 @@ class Equipment(BaseClass):
|
|||||||
re.VERBOSE)
|
re.VERBOSE)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def assign_equipment(cls, equipment_role: EquipmentRole|str) -> List[Equipment]:
|
def assign_equipment(cls, equipment_role: EquipmentRole | str) -> List[Equipment]:
|
||||||
"""
|
"""
|
||||||
Creates a list of equipment from user input to be used in Submission Type creation
|
Creates a list of equipment from user input to be used in Submission Type creation
|
||||||
|
|
||||||
@@ -1581,10 +1571,11 @@ class EquipmentRole(BaseClass):
|
|||||||
Returns:
|
Returns:
|
||||||
dict: dictionary of Association and related reagent role
|
dict: dictionary of Association and related reagent role
|
||||||
"""
|
"""
|
||||||
base_dict = {}
|
return dict(role=self.name,
|
||||||
base_dict['role'] = self.name
|
processes=self.get_processes(submission_type=submission_type, extraction_kit=kit_type))
|
||||||
base_dict['processes'] = self.get_processes(submission_type=submission_type, extraction_kit=kit_type)
|
# base_dict['role'] = self.name
|
||||||
return base_dict
|
# base_dict['processes'] = self.get_processes(submission_type=submission_type, extraction_kit=kit_type)
|
||||||
|
# return base_dict
|
||||||
|
|
||||||
|
|
||||||
class SubmissionEquipmentAssociation(BaseClass):
|
class SubmissionEquipmentAssociation(BaseClass):
|
||||||
@@ -1621,6 +1612,7 @@ class SubmissionEquipmentAssociation(BaseClass):
|
|||||||
Returns:
|
Returns:
|
||||||
dict: This SubmissionEquipmentAssociation as a dictionary
|
dict: This SubmissionEquipmentAssociation as a dictionary
|
||||||
"""
|
"""
|
||||||
|
# TODO: Currently this will only fetch a single process, even if multiple are selectable.
|
||||||
try:
|
try:
|
||||||
process = self.process.name
|
process = self.process.name
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
@@ -1707,9 +1699,9 @@ class SubmissionTypeEquipmentRoleAssociation(BaseClass):
|
|||||||
super().save()
|
super().save()
|
||||||
|
|
||||||
def to_export_dict(self, kit_type: KitType):
|
def to_export_dict(self, kit_type: KitType):
|
||||||
base_dict = dict(static=self.static)
|
base_dict = {k: v for k, v in self.equipment_role.to_export_dict(submission_type=self.submission_type,
|
||||||
for k, v in self.equipment_role.to_export_dict(submission_type=self.submission_type, kit_type=kit_type).items():
|
kit_type=kit_type).items()}
|
||||||
base_dict[k] = v
|
base_dict['static'] = self.static
|
||||||
return base_dict
|
return base_dict
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ class BasicSubmission(BaseClass):
|
|||||||
str: Representation of this BasicSubmission
|
str: Representation of this BasicSubmission
|
||||||
"""
|
"""
|
||||||
submission_type = self.submission_type or "Basic"
|
submission_type = self.submission_type or "Basic"
|
||||||
return f"{submission_type}Submission({self.rsl_plate_num})"
|
return f"<{submission_type}Submission({self.rsl_plate_num})>"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def jsons(cls) -> List[str]:
|
def jsons(cls) -> List[str]:
|
||||||
@@ -231,6 +231,9 @@ class BasicSubmission(BaseClass):
|
|||||||
"""
|
"""
|
||||||
Gets the SubmissionType associated with this class
|
Gets the SubmissionType associated with this class
|
||||||
|
|
||||||
|
Args:
|
||||||
|
sub_type (str | SubmissionType, Optional): Identity of the submission type to retrieve. Defaults to None.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
SubmissionType: SubmissionType with name equal to this polymorphic identity
|
SubmissionType: SubmissionType with name equal to this polymorphic identity
|
||||||
"""
|
"""
|
||||||
@@ -421,8 +424,6 @@ class BasicSubmission(BaseClass):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Column count error: {e}")
|
logger.error(f"Column count error: {e}")
|
||||||
# NOTE: Get kit associated with this submission
|
# NOTE: Get kit associated with this submission
|
||||||
# assoc = [item for item in self.extraction_kit.kit_submissiontype_associations if
|
|
||||||
# item.submission_type == self.submission_type][0]
|
|
||||||
assoc = next((item for item in self.extraction_kit.kit_submissiontype_associations if item.submission_type == self.submission_type),
|
assoc = next((item for item in self.extraction_kit.kit_submissiontype_associations if item.submission_type == self.submission_type),
|
||||||
None)
|
None)
|
||||||
# logger.debug(f"Came up with association: {assoc}")
|
# logger.debug(f"Came up with association: {assoc}")
|
||||||
@@ -445,7 +446,7 @@ class BasicSubmission(BaseClass):
|
|||||||
Returns positve sample locations for plate
|
Returns positve sample locations for plate
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
list: list of htipick dictionaries for each sample
|
list: list of hitpick dictionaries for each sample
|
||||||
"""
|
"""
|
||||||
output_list = [assoc.to_hitpick() for assoc in self.submission_sample_associations]
|
output_list = [assoc.to_hitpick() for assoc in self.submission_sample_associations]
|
||||||
return output_list
|
return output_list
|
||||||
@@ -468,8 +469,7 @@ class BasicSubmission(BaseClass):
|
|||||||
for column in range(1, plate_columns + 1):
|
for column in range(1, plate_columns + 1):
|
||||||
for row in range(1, plate_rows + 1):
|
for row in range(1, plate_rows + 1):
|
||||||
try:
|
try:
|
||||||
# well = [item for item in sample_list if item['row'] == row and item['column'] == column][0]
|
well = next((item for item in sample_list if item['row'] == row and item['column'] == column), dict(name="", row=row, column=column, background_color="#ffffff"))
|
||||||
well = next(item for item in sample_list if item['row'] == row and item['column'] == column)
|
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
well = dict(name="", row=row, column=column, background_color="#ffffff")
|
well = dict(name="", row=row, column=column, background_color="#ffffff")
|
||||||
output_samples.append(well)
|
output_samples.append(well)
|
||||||
@@ -2788,16 +2788,17 @@ class SubmissionSampleAssociation(BaseClass):
|
|||||||
if isinstance(polymorphic_identity, dict):
|
if isinstance(polymorphic_identity, dict):
|
||||||
polymorphic_identity = polymorphic_identity['value']
|
polymorphic_identity = polymorphic_identity['value']
|
||||||
if polymorphic_identity is None:
|
if polymorphic_identity is None:
|
||||||
output = cls
|
model = cls
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
output = [item for item in cls.__subclasses__() if
|
# output = [item for item in cls.__subclasses__() if
|
||||||
item.__mapper_args__['polymorphic_identity'] == polymorphic_identity][0]
|
# item.__mapper_args__['polymorphic_identity'] == polymorphic_identity][0]
|
||||||
|
model = cls.__mapper__.polymorphic_map[polymorphic_identity].class_
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Could not get polymorph {polymorphic_identity} of {cls} due to {e}")
|
logger.error(f"Could not get polymorph {polymorphic_identity} of {cls} due to {e}")
|
||||||
output = cls
|
model = cls
|
||||||
# logger.debug(f"Using SubmissionSampleAssociation subclass: {output}")
|
# logger.debug(f"Using SubmissionSampleAssociation subclass: {output}")
|
||||||
return output
|
return model
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@setup_lookup
|
@setup_lookup
|
||||||
@@ -2986,7 +2987,7 @@ class WastewaterAssociation(SubmissionSampleAssociation):
|
|||||||
return sample
|
return sample
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def autoincrement_id(cls) -> int:
|
def autoincrement_id_local(cls) -> int:
|
||||||
"""
|
"""
|
||||||
Increments the association id automatically. Overrides parent
|
Increments the association id automatically. Overrides parent
|
||||||
|
|
||||||
@@ -2994,12 +2995,17 @@ class WastewaterAssociation(SubmissionSampleAssociation):
|
|||||||
int: incremented id
|
int: incremented id
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
parent = [base for base in cls.__bases__ if base.__name__ == "SubmissionSampleAssociation"][0]
|
parent = next((base for base in cls.__bases__ if base.__name__=="SubmissionSampleAssociation"),
|
||||||
|
SubmissionSampleAssociation)
|
||||||
return max([item.id for item in parent.query()]) + 1
|
return max([item.id for item in parent.query()]) + 1
|
||||||
except ValueError as e:
|
except StopIteration as e:
|
||||||
logger.error(f"Problem incrementing id: {e}")
|
logger.error(f"Problem incrementing id: {e}")
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def autoincrement_id(cls) -> int:
|
||||||
|
return super().autoincrement_id()
|
||||||
|
|
||||||
|
|
||||||
class WastewaterArticAssociation(SubmissionSampleAssociation):
|
class WastewaterArticAssociation(SubmissionSampleAssociation):
|
||||||
"""
|
"""
|
||||||
@@ -3040,8 +3046,9 @@ class WastewaterArticAssociation(SubmissionSampleAssociation):
|
|||||||
int: incremented id
|
int: incremented id
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
parent = [base for base in cls.__bases__ if base.__name__ == "SubmissionSampleAssociation"][0]
|
parent = next((base for base in cls.__bases__ if base.__name__ == "SubmissionSampleAssociation"),
|
||||||
|
SubmissionSampleAssociation)
|
||||||
return max([item.id for item in parent.query()]) + 1
|
return max([item.id for item in parent.query()]) + 1
|
||||||
except ValueError as e:
|
except StopIteration as e:
|
||||||
logger.error(f"Problem incrementing id: {e}")
|
logger.error(f"Problem incrementing id: {e}")
|
||||||
return 1
|
return 1
|
||||||
|
|||||||
@@ -547,23 +547,9 @@ class DocxWriter(object):
|
|||||||
if columns == 0:
|
if columns == 0:
|
||||||
columns = max([sample['column'] for sample in sample_list])
|
columns = max([sample['column'] for sample in sample_list])
|
||||||
for row in range(0, rows):
|
for row in range(0, rows):
|
||||||
# NOTE: Create a list with length equal to columns length
|
# NOTE: Create a list with length equal to columns length, padding with '' where necessary
|
||||||
# contents = [''] * columns
|
|
||||||
contents = [next((item['submitter_id'] for item in sample_list if item['row'] == row + 1 and
|
contents = [next((item['submitter_id'] for item in sample_list if item['row'] == row + 1 and
|
||||||
item['column'] == column + 1), '') for column in range(0, columns)]
|
item['column'] == column + 1), '') for column in range(0, columns)]
|
||||||
# for column in range(0, columns):
|
|
||||||
# contents[column] = next((item['submitter_id'] for item in sample_list if item['row'] == row + 1 and item['column'] == column), '')
|
|
||||||
# try:
|
|
||||||
# # ooi = [item for item in sample_list if item['row'] == row + 1 and item['column'] == column + 1][0]
|
|
||||||
# ooi = next(item for item in sample_list if item['row'] == row + 1 and item['column'] == column)
|
|
||||||
# except StopIteration:
|
|
||||||
# continue
|
|
||||||
# contents[column] = ooi['submitter_id']
|
|
||||||
# NOTE: Pad length of contents to reflect columns
|
|
||||||
# if len(contents) < columns:
|
|
||||||
# contents += [''] * (columns - len(contents))
|
|
||||||
# if not contents:
|
|
||||||
# contents = [''] * columns
|
|
||||||
yield contents
|
yield contents
|
||||||
|
|
||||||
def create_merged_template(self, *args) -> BytesIO:
|
def create_merged_template(self, *args) -> BytesIO:
|
||||||
|
|||||||
@@ -177,10 +177,10 @@ class SubmissionDetails(QDialog):
|
|||||||
writer = DocxWriter(base_dict=base_dict)
|
writer = DocxWriter(base_dict=base_dict)
|
||||||
fname = select_save_file(obj=self, default_name=base_dict['plate_number'], extension="docx")
|
fname = select_save_file(obj=self, default_name=base_dict['plate_number'], extension="docx")
|
||||||
writer.save(fname)
|
writer.save(fname)
|
||||||
try:
|
# try:
|
||||||
html_to_pdf(html=self.html, output_file=fname)
|
# html_to_pdf(html=self.html, output_file=fname)
|
||||||
except PermissionError as e:
|
# except PermissionError as e:
|
||||||
logger.error(f"Error saving pdf: {e}")
|
# logger.error(f"Error saving pdf: {e}")
|
||||||
|
|
||||||
|
|
||||||
class SubmissionComment(QDialog):
|
class SubmissionComment(QDialog):
|
||||||
|
|||||||
Reference in New Issue
Block a user