Post code-cleanup, moments before disaster.
This commit is contained in:
@@ -56,6 +56,12 @@ class BaseClass(Base):
|
||||
omni_inheritable = []
|
||||
searchables = []
|
||||
|
||||
def __repr__(self) -> str:
|
||||
try:
|
||||
return f"<{self.__class__.__name__}({self.name})>"
|
||||
except AttributeError:
|
||||
return f"<{self.__class__.__name__}({self.__name__})>"
|
||||
|
||||
# @classproperty
|
||||
# def skip_on_edit(cls):
|
||||
# if "association" in cls.__name__.lower() or cls.__name__.lower() == "discount":
|
||||
@@ -444,6 +450,9 @@ class BaseClass(Base):
|
||||
else:
|
||||
return super().__setattr__(key, value)
|
||||
|
||||
def delete(self):
|
||||
logger.error(f"Delete has not been implemented for {self.__class__.__name__}")
|
||||
|
||||
|
||||
class ConfigItem(BaseClass):
|
||||
"""
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
All control related models.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import itertools
|
||||
from pprint import pformat
|
||||
from PyQt6.QtWidgets import QWidget, QCheckBox, QLabel
|
||||
from pandas import DataFrame
|
||||
@@ -16,7 +18,6 @@ from typing import List, Literal, Tuple, Generator
|
||||
from dateutil.parser import parse
|
||||
from re import Pattern
|
||||
|
||||
|
||||
logger = logging.getLogger(f"submissions.{__name__}")
|
||||
|
||||
|
||||
@@ -29,8 +30,8 @@ class ControlType(BaseClass):
|
||||
targets = Column(JSON) #: organisms checked for
|
||||
instances = relationship("Control", back_populates="controltype") #: control samples created of this type.
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"<ControlType({self.name})>"
|
||||
# def __repr__(self) -> str:
|
||||
# return f"<ControlType({self.name})>"
|
||||
|
||||
@classmethod
|
||||
@setup_lookup
|
||||
@@ -88,7 +89,7 @@ class ControlType(BaseClass):
|
||||
|
||||
Returns:
|
||||
Control: Associated Control class
|
||||
"""
|
||||
"""
|
||||
return Control.find_polymorphic_subclass(polymorphic_identity=self.name)
|
||||
|
||||
@classmethod
|
||||
@@ -103,7 +104,7 @@ class ControlType(BaseClass):
|
||||
return (k for k, v in ct.items() if v)
|
||||
|
||||
@classmethod
|
||||
def build_positive_regex(cls, control_type:str) -> Pattern:
|
||||
def build_positive_regex(cls, control_type: str) -> Pattern:
|
||||
"""
|
||||
Creates a re.Pattern that will look for positive control types
|
||||
|
||||
@@ -305,10 +306,10 @@ class PCRControl(Control):
|
||||
id = Column(INTEGER, ForeignKey('_control.id'), primary_key=True)
|
||||
subtype = Column(String(16)) #: PC or NC
|
||||
target = Column(String(16)) #: N1, N2, etc.
|
||||
ct = Column(FLOAT) #: PCR result
|
||||
ct = Column(FLOAT) #: PCR result
|
||||
reagent_lot = Column(String(64), ForeignKey("_reagent.lot", ondelete="SET NULL",
|
||||
name="fk_reagent_lot"))
|
||||
reagent = relationship("Reagent", foreign_keys=reagent_lot) #: reagent used for this control
|
||||
reagent = relationship("Reagent", foreign_keys=reagent_lot) #: reagent used for this control
|
||||
|
||||
__mapper_args__ = dict(polymorphic_identity="PCR Control",
|
||||
polymorphic_load="inline",
|
||||
@@ -320,7 +321,7 @@ class PCRControl(Control):
|
||||
|
||||
Returns:
|
||||
dict: Output dict of name, ct, subtype, target, reagent_lot and submitted_date
|
||||
"""
|
||||
"""
|
||||
return dict(
|
||||
name=self.name,
|
||||
ct=self.ct,
|
||||
@@ -343,7 +344,7 @@ class PCRControl(Control):
|
||||
|
||||
Returns:
|
||||
Tuple[Report, "PCRFigure"]: Report of status and resulting figure.
|
||||
"""
|
||||
"""
|
||||
from frontend.visualizations.pcr_charts import PCRFigure
|
||||
parent.mode_typer.clear()
|
||||
parent.mode_typer.setEnabled(False)
|
||||
@@ -352,6 +353,7 @@ class PCRControl(Control):
|
||||
end_date=chart_settings['end_date'])
|
||||
data = [control.to_sub_dict() for control in controls]
|
||||
df = DataFrame.from_records(data)
|
||||
# NOTE: Get all PCR controls with ct over 0
|
||||
try:
|
||||
df = df[df.ct > 0.0]
|
||||
except AttributeError:
|
||||
@@ -361,11 +363,11 @@ class PCRControl(Control):
|
||||
|
||||
def to_pydantic(self):
|
||||
from backend.validators import PydPCRControl
|
||||
return PydPCRControl(**self.to_sub_dict(), controltype_name=self.controltype_name, submission_id=self.submission_id)
|
||||
return PydPCRControl(**self.to_sub_dict(), controltype_name=self.controltype_name,
|
||||
submission_id=self.submission_id)
|
||||
|
||||
|
||||
class IridaControl(Control):
|
||||
|
||||
subtyping_allowed = ['kraken']
|
||||
|
||||
id = Column(INTEGER, ForeignKey('_control.id'), primary_key=True)
|
||||
@@ -379,11 +381,19 @@ class IridaControl(Control):
|
||||
sample = relationship("BacterialCultureSample", back_populates="control") #: This control's submission sample
|
||||
sample_id = Column(INTEGER,
|
||||
ForeignKey("_basicsample.id", ondelete="SET NULL", name="cont_BCS_id")) #: sample id key
|
||||
|
||||
|
||||
__mapper_args__ = dict(polymorphic_identity="Irida Control",
|
||||
polymorphic_load="inline",
|
||||
inherit_condition=(id == Control.id))
|
||||
|
||||
@property
|
||||
def targets(self):
|
||||
if self.controltype.targets:
|
||||
return list(itertools.chain.from_iterable([value for key, value in self.controltype.targets.items()
|
||||
if key == self.subtype]))
|
||||
else:
|
||||
return ["None"]
|
||||
|
||||
@validates("subtype")
|
||||
def enforce_subtype_literals(self, key: str, value: str) -> str:
|
||||
"""
|
||||
@@ -398,7 +408,7 @@ class IridaControl(Control):
|
||||
|
||||
Returns:
|
||||
str: Validated string.
|
||||
"""
|
||||
"""
|
||||
acceptables = ['ATCC49226', 'ATCC49619', 'EN-NOS', "EN-SSTI", "MCS-NOS", "MCS-SSTI", "SN-NOS", "SN-SSTI"]
|
||||
if value.upper() not in acceptables:
|
||||
raise KeyError(f"Sub-type must be in {acceptables}")
|
||||
@@ -416,19 +426,15 @@ class IridaControl(Control):
|
||||
except TypeError:
|
||||
kraken = {}
|
||||
kraken_cnt_total = sum([item['kraken_count'] for item in kraken.values()])
|
||||
new_kraken = [dict(name=item, kraken_count=kraken[item]['kraken_count'],
|
||||
kraken_percent=f"{kraken[item]['kraken_count'] / kraken_cnt_total:0.2%}",
|
||||
target=item in self.controltype.targets)
|
||||
for item in kraken]
|
||||
new_kraken = [dict(name=key, kraken_count=value['kraken_count'],
|
||||
kraken_percent=f"{value['kraken_count'] / kraken_cnt_total:0.2%}",
|
||||
target=key in self.controltype.targets)
|
||||
for key, value in kraken.items()]
|
||||
new_kraken = sorted(new_kraken, key=itemgetter('kraken_count'), reverse=True)
|
||||
if self.controltype.targets:
|
||||
targets = self.controltype.targets
|
||||
else:
|
||||
targets = ["None"]
|
||||
output = dict(
|
||||
name=self.name,
|
||||
type=self.controltype.name,
|
||||
targets=", ".join(targets),
|
||||
targets=", ".join(self.targets),
|
||||
kraken=new_kraken[0:10]
|
||||
)
|
||||
return output
|
||||
@@ -521,7 +527,7 @@ class IridaControl(Control):
|
||||
|
||||
Returns:
|
||||
Tuple[Report, "IridaFigure"]: Report of status and resulting figure.
|
||||
"""
|
||||
"""
|
||||
from frontend.visualizations import IridaFigure
|
||||
try:
|
||||
checker = parent.findChild(QCheckBox, name="irida_check")
|
||||
|
||||
@@ -16,7 +16,6 @@ from pandas import ExcelFile
|
||||
from pathlib import Path
|
||||
from . import Base, BaseClass, Organization, LogMixin
|
||||
from io import BytesIO
|
||||
from inspect import getouterframes, currentframe
|
||||
|
||||
logger = logging.getLogger(f'submissions.{__name__}')
|
||||
|
||||
@@ -98,7 +97,6 @@ class KitType(BaseClass):
|
||||
Base of kits used in submission processing
|
||||
"""
|
||||
|
||||
# query_alias = "kit_type"
|
||||
omni_sort = BaseClass.omni_sort + ["kit_submissiontype_associations", "kit_reagentrole_associations", "processes"]
|
||||
|
||||
id = Column(INTEGER, primary_key=True) #: primary key
|
||||
@@ -128,13 +126,6 @@ class KitType(BaseClass):
|
||||
creator=lambda ST: SubmissionTypeKitTypeAssociation(
|
||||
submission_type=ST)) #: Association proxy to SubmissionTypeKitTypeAssociation
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""
|
||||
Returns:
|
||||
str: A representation of the object.
|
||||
"""
|
||||
return f"<KitType({self.name})>"
|
||||
|
||||
@classproperty
|
||||
def aliases(cls):
|
||||
return super().aliases + [cls.query_alias, "kit_types", "kit_type"]
|
||||
@@ -187,9 +178,7 @@ class KitType(BaseClass):
|
||||
# NOTE: Account for submission_type variable type.
|
||||
match submission_type:
|
||||
case str():
|
||||
# assocs = [item for item in self.kit_reagentrole_associations if
|
||||
# item.submission_type.name == submission_type]
|
||||
logger.debug(f"Query for {submission_type}")
|
||||
# logger.debug(f"Query for {submission_type}")
|
||||
submission_type = SubmissionType.query(name=submission_type)
|
||||
case SubmissionType():
|
||||
pass
|
||||
@@ -213,18 +202,12 @@ class KitType(BaseClass):
|
||||
)
|
||||
if dlg.exec():
|
||||
dlg_result = dlg.parse_form()
|
||||
logger.debug(f"Dialog result: {dlg_result}")
|
||||
# logger.debug(f"Dialog result: {dlg_result}")
|
||||
new_kit = self.__class__.query(name=dlg_result)
|
||||
logger.debug(f"Query result: {new_kit}")
|
||||
# return new_kit.construct_xl_map_for_use(submission_type=submission_type)
|
||||
# logger.debug(f"Query result: {new_kit}")
|
||||
else:
|
||||
return None, new_kit
|
||||
assocs = [item for item in new_kit.kit_reagentrole_associations if item.submission_type == submission_type]
|
||||
# for assoc in assocs:
|
||||
# try:
|
||||
# yield assoc.reagent_role.name, assoc.uses
|
||||
# except TypeError:
|
||||
# continue
|
||||
output = {assoc.reagent_role.name: assoc.uses for assoc in assocs}
|
||||
# logger.debug(f"Output: {output}")
|
||||
return output, new_kit
|
||||
@@ -232,7 +215,6 @@ class KitType(BaseClass):
|
||||
@classmethod
|
||||
def query_or_create(cls, **kwargs) -> Tuple[KitType, bool]:
|
||||
from backend.validators.pydant import PydKitType
|
||||
from backend.validators.omni_gui_objects import BaseOmni
|
||||
new = False
|
||||
disallowed = ['expiry']
|
||||
sanitized_kwargs = {k: v for k, v in kwargs.items() if k not in disallowed}
|
||||
@@ -248,7 +230,7 @@ class KitType(BaseClass):
|
||||
@setup_lookup
|
||||
def query(cls,
|
||||
name: str = None,
|
||||
used_for: str | SubmissionType | None = None,
|
||||
submissiontype: str | SubmissionType | None = None,
|
||||
id: int | None = None,
|
||||
limit: int = 0,
|
||||
**kwargs
|
||||
@@ -266,11 +248,11 @@ class KitType(BaseClass):
|
||||
KitType|List[KitType]: KitType(s) of interest.
|
||||
"""
|
||||
query: Query = cls.__database_session__.query(cls)
|
||||
match used_for:
|
||||
match submissiontype:
|
||||
case str():
|
||||
query = query.filter(cls.used_for.any(name=used_for))
|
||||
query = query.filter(cls.submissiontype.any(name=submissiontype))
|
||||
case SubmissionType():
|
||||
query = query.filter(cls.used_for.contains(used_for))
|
||||
query = query.filter(cls.submissiontype.contains(submissiontype))
|
||||
case _:
|
||||
pass
|
||||
match name:
|
||||
@@ -399,9 +381,6 @@ class KitType(BaseClass):
|
||||
|
||||
def to_omni(self, expand: bool = False) -> "OmniKitType":
|
||||
from backend.validators.omni_gui_objects import OmniKitType
|
||||
# logger.debug(f"self.name: {self.name}")
|
||||
# level = len(getouterframes(currentframe()))
|
||||
# logger.warning(f"Function level is {level}")
|
||||
if expand:
|
||||
processes = [item.to_omni() for item in self.processes]
|
||||
kit_reagentrole_associations = [item.to_omni() for item in self.kit_reagentrole_associations]
|
||||
@@ -425,6 +404,8 @@ class ReagentRole(BaseClass):
|
||||
Base of reagent type abstract
|
||||
"""
|
||||
|
||||
skip_on_edit = False
|
||||
|
||||
id = Column(INTEGER, primary_key=True) #: primary key
|
||||
name = Column(String(64)) #: name of role reagent plays
|
||||
instances = relationship("Reagent", back_populates="role",
|
||||
@@ -442,13 +423,6 @@ class ReagentRole(BaseClass):
|
||||
creator=lambda kit: KitTypeReagentRoleAssociation(
|
||||
kit_type=kit)) #: Association proxy to KitTypeReagentRoleAssociation
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""
|
||||
Returns:
|
||||
str: Representation of object
|
||||
"""
|
||||
return f"<ReagentRole({self.name})>"
|
||||
|
||||
@classmethod
|
||||
def query_or_create(cls, **kwargs) -> Tuple[ReagentRole, bool]:
|
||||
new = False
|
||||
@@ -603,7 +577,6 @@ class Reagent(BaseClass, LogMixin):
|
||||
Returns:
|
||||
dict: representation of the reagent's attributes
|
||||
"""
|
||||
|
||||
if extraction_kit is not None:
|
||||
# NOTE: Get the intersection of this reagent's ReagentType and all ReagentTypes in KitType
|
||||
reagent_role = next((item for item in set(self.role).intersection(extraction_kit.reagent_roles)),
|
||||
@@ -713,8 +686,6 @@ class Reagent(BaseClass, LogMixin):
|
||||
limit = 1
|
||||
case _:
|
||||
pass
|
||||
# if not role and "reagentrole" in kwargs.keys():
|
||||
# role = kwargs['reagentrole']
|
||||
match role:
|
||||
case str():
|
||||
query = query.join(cls.role).filter(ReagentRole.name == role)
|
||||
@@ -772,6 +743,7 @@ class Reagent(BaseClass, LogMixin):
|
||||
@check_authorization
|
||||
def edit_from_search(self, obj, **kwargs):
|
||||
from frontend.widgets.omni_add_edit import AddEdit
|
||||
# logger.debug(f"Calling edit_from_search for {self.name}")
|
||||
dlg = AddEdit(parent=None, instance=self)
|
||||
if dlg.exec():
|
||||
pyd = dlg.parse_form()
|
||||
@@ -1377,20 +1349,6 @@ class SubmissionType(BaseClass):
|
||||
|
||||
def to_omni(self, expand: bool = False):
|
||||
from backend.validators.omni_gui_objects import OmniSubmissionType
|
||||
# level = len(getouterframes(currentframe()))
|
||||
# logger.warning(f"Function level is {level}")
|
||||
# try:
|
||||
# info_map = self.submission_type.info_map
|
||||
# except AttributeError:
|
||||
# info_map = {}
|
||||
# try:
|
||||
# defaults = self.submission_type.defaults
|
||||
# except AttributeError:
|
||||
# defaults = {}
|
||||
# try:
|
||||
# sample_map = self.submission_type.sample_map
|
||||
# except AttributeError:
|
||||
# sample_map = {}
|
||||
try:
|
||||
template_file = self.template_file
|
||||
except AttributeError:
|
||||
@@ -1555,8 +1513,6 @@ class SubmissionTypeKitTypeAssociation(BaseClass):
|
||||
|
||||
def to_omni(self, expand: bool = False):
|
||||
from backend.validators.omni_gui_objects import OmniSubmissionTypeKitTypeAssociation
|
||||
# level = len(getouterframes(currentframe()))
|
||||
# logger.warning(f"Function level is {level}")
|
||||
if expand:
|
||||
try:
|
||||
submissiontype = self.submission_type.to_omni()
|
||||
@@ -1569,10 +1525,6 @@ class SubmissionTypeKitTypeAssociation(BaseClass):
|
||||
else:
|
||||
submissiontype = self.submission_type.name
|
||||
kittype = self.kit_type.name
|
||||
# try:
|
||||
# processes = [item.to_omni() for item in self.submission_type.processes]
|
||||
# except AttributeError:
|
||||
# processes = []
|
||||
return OmniSubmissionTypeKitTypeAssociation(
|
||||
instance_object=self,
|
||||
submissiontype=submissiontype,
|
||||
@@ -1580,7 +1532,6 @@ class SubmissionTypeKitTypeAssociation(BaseClass):
|
||||
mutable_cost_column=self.mutable_cost_column,
|
||||
mutable_cost_sample=self.mutable_cost_sample,
|
||||
constant_cost=self.constant_cost
|
||||
# processes=processes,
|
||||
)
|
||||
|
||||
|
||||
@@ -1719,7 +1670,6 @@ class KitTypeReagentRoleAssociation(BaseClass):
|
||||
pass
|
||||
setattr(instance, k, v)
|
||||
logger.info(f"Instance from query or create: {instance.__dict__}\nis new: {new}")
|
||||
# sys.exit()
|
||||
return instance, new
|
||||
|
||||
@classmethod
|
||||
@@ -1854,6 +1804,8 @@ class SubmissionReagentAssociation(BaseClass):
|
||||
DOC: https://docs.sqlalchemy.org/en/14/orm/extensions/associationproxy.html
|
||||
"""
|
||||
|
||||
skip_on_edit = True
|
||||
|
||||
reagent_id = Column(INTEGER, ForeignKey("_reagent.id"), primary_key=True) #: id of associated reagent
|
||||
submission_id = Column(INTEGER, ForeignKey("_basicsubmission.id"), primary_key=True) #: id of associated submission
|
||||
comments = Column(String(1024)) #: Comments about reagents
|
||||
@@ -1869,10 +1821,10 @@ class SubmissionReagentAssociation(BaseClass):
|
||||
str: Representation of this SubmissionReagentAssociation
|
||||
"""
|
||||
try:
|
||||
return f"<{self.submission.rsl_plate_num} & {self.reagent.lot}>"
|
||||
return f"<SubmissionReagentAssociation({self.submission.rsl_plate_num} & {self.reagent.lot})>"
|
||||
except AttributeError:
|
||||
logger.error(f"Reagent {self.reagent.lot} submission association {self.reagent_id} has no submissions!")
|
||||
return f"<Unknown Submission & {self.reagent.lot}>"
|
||||
return f"<SubmissionReagentAssociation(Unknown Submission & {self.reagent.lot})>"
|
||||
|
||||
def __init__(self, reagent=None, submission=None):
|
||||
if isinstance(reagent, list):
|
||||
@@ -1963,12 +1915,12 @@ class Equipment(BaseClass, LogMixin):
|
||||
submissions = association_proxy("equipment_submission_associations",
|
||||
"submission") #: proxy to equipment_submission_associations.submission
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""
|
||||
Returns:
|
||||
str: representation of this Equipment
|
||||
"""
|
||||
return f"<Equipment({self.name})>"
|
||||
# def __repr__(self) -> str:
|
||||
# """
|
||||
# Returns:
|
||||
# str: representation of this Equipment
|
||||
# """
|
||||
# return f"<Equipment({self.name})>"
|
||||
|
||||
def to_dict(self, processes: bool = False) -> dict:
|
||||
"""
|
||||
@@ -1987,7 +1939,7 @@ class Equipment(BaseClass, LogMixin):
|
||||
|
||||
def get_processes(self, submission_type: str | SubmissionType | None = None,
|
||||
extraction_kit: str | KitType | None = None,
|
||||
equipment_role: str | EquipmentRole | None = None) -> List[str]:
|
||||
equipment_role: str | EquipmentRole | None = None) -> Generator[Process, None, None]:
|
||||
"""
|
||||
Get all processes associated with this Equipment for a given SubmissionType
|
||||
|
||||
@@ -2133,12 +2085,12 @@ class EquipmentRole(BaseClass):
|
||||
submission_types = association_proxy("equipmentrole_submissiontype_associations",
|
||||
"submission_type") #: proxy to equipmentrole_submissiontype_associations.submission_type
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""
|
||||
Returns:
|
||||
str: Representation of this EquipmentRole
|
||||
"""
|
||||
return f"<EquipmentRole({self.name})>"
|
||||
# def __repr__(self) -> str:
|
||||
# """
|
||||
# Returns:
|
||||
# str: Representation of this EquipmentRole
|
||||
# """
|
||||
# return f"<EquipmentRole({self.name})>"
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
"""
|
||||
@@ -2395,7 +2347,6 @@ class Process(BaseClass):
|
||||
|
||||
id = Column(INTEGER, primary_key=True) #: Process id, primary key
|
||||
name = Column(String(64), unique=True) #: Process name
|
||||
# version = Column(String(32))
|
||||
submission_types = relationship("SubmissionType", back_populates='processes',
|
||||
secondary=submissiontypes_processes) #: relation to SubmissionType
|
||||
equipment = relationship("Equipment", back_populates='processes',
|
||||
@@ -2410,12 +2361,12 @@ class Process(BaseClass):
|
||||
secondary=process_tiprole) #: relation to KitType
|
||||
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""
|
||||
Returns:
|
||||
str: Representation of this Process
|
||||
"""
|
||||
return f"<Process({self.name})>"
|
||||
# def __repr__(self) -> str:
|
||||
# """
|
||||
# Returns:
|
||||
# str: Representation of this Process
|
||||
# """
|
||||
# return f"<Process({self.name})>"
|
||||
|
||||
def set_attribute(self, key, value):
|
||||
match key:
|
||||
@@ -2506,13 +2457,20 @@ class Process(BaseClass):
|
||||
|
||||
def to_omni(self, expand: bool = False):
|
||||
from backend.validators.omni_gui_objects import OmniProcess
|
||||
if expand:
|
||||
submission_types = [item.to_omni() for item in self.submission_types]
|
||||
equipment_roles = [item.to_omni() for item in self.equipment_roles]
|
||||
tip_roles = [item.to_omni() for item in self.tip_roles]
|
||||
else:
|
||||
submission_types = [item.name for item in self.submission_types]
|
||||
equipment_roles = [item.name for item in self.equipment_roles]
|
||||
tip_roles = [item.name for item in self.tip_roles]
|
||||
return OmniProcess(
|
||||
instance_object=self,
|
||||
name=self.name,
|
||||
# version=self.version,
|
||||
submission_types=[item.to_omni() for item in self.submission_types],
|
||||
equipment_roles=[item.to_omni() for item in self.equipment_roles],
|
||||
tip_roles=[item.to_omni() for item in self.tip_roles]
|
||||
submission_types=submission_types,
|
||||
equipment_roles=equipment_roles,
|
||||
tip_roles=tip_roles
|
||||
)
|
||||
|
||||
|
||||
@@ -2538,8 +2496,8 @@ class TipRole(BaseClass):
|
||||
def tips(self):
|
||||
return self.instances
|
||||
|
||||
def __repr__(self):
|
||||
return f"<TipRole({self.name})>"
|
||||
# def __repr__(self):
|
||||
# return f"<TipRole({self.name})>"
|
||||
|
||||
@classmethod
|
||||
def query_or_create(cls, **kwargs) -> Tuple[TipRole, bool]:
|
||||
@@ -2573,10 +2531,14 @@ class TipRole(BaseClass):
|
||||
|
||||
def to_omni(self, expand: bool = False):
|
||||
from backend.validators.omni_gui_objects import OmniTipRole
|
||||
if expand:
|
||||
tips = [item.to_omni() for item in self.tips]
|
||||
else:
|
||||
tips = [item.name for item in self.tips]
|
||||
return OmniTipRole(
|
||||
instance_object=self,
|
||||
name=self.name,
|
||||
tips=[item.to_omni() for item in self.tips]
|
||||
tips=tips
|
||||
)
|
||||
|
||||
|
||||
@@ -2605,8 +2567,8 @@ class Tips(BaseClass, LogMixin):
|
||||
def tiprole(self):
|
||||
return self.role
|
||||
|
||||
def __repr__(self):
|
||||
return f"<Tips({self.name})>"
|
||||
# def __repr__(self):
|
||||
# return f"<Tips({self.name})>"
|
||||
|
||||
@classmethod
|
||||
def query_or_create(cls, **kwargs) -> Tuple[Tips, bool]:
|
||||
|
||||
@@ -29,8 +29,6 @@ class Organization(BaseClass):
|
||||
Base of organization
|
||||
"""
|
||||
|
||||
|
||||
|
||||
id = Column(INTEGER, primary_key=True) #: primary key
|
||||
name = Column(String(64)) #: organization name
|
||||
submissions = relationship("BasicSubmission",
|
||||
@@ -43,8 +41,8 @@ class Organization(BaseClass):
|
||||
def contact(self):
|
||||
return self.contacts
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"<Organization({self.name})>"
|
||||
# def __repr__(self) -> str:
|
||||
# return f"<Organization({self.name})>"
|
||||
|
||||
@classmethod
|
||||
@setup_lookup
|
||||
@@ -139,8 +137,8 @@ class Contact(BaseClass):
|
||||
secondary=orgs_contacts) #: relationship to joined organization
|
||||
submissions = relationship("BasicSubmission", back_populates="contact") #: submissions this contact has submitted
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"<Contact({self.name})>"
|
||||
# def __repr__(self) -> str:
|
||||
# return f"<Contact({self.name})>"
|
||||
|
||||
@classproperty
|
||||
def searchables(cls):
|
||||
|
||||
@@ -402,7 +402,6 @@ class BasicSubmission(BaseClass, LogMixin):
|
||||
columns = set([assoc.column for assoc in self.submission_sample_associations])
|
||||
return len(columns)
|
||||
|
||||
|
||||
def calculate_base_cost(self) -> None:
|
||||
"""
|
||||
Calculates cost of the plate
|
||||
@@ -733,7 +732,7 @@ class BasicSubmission(BaseClass, LogMixin):
|
||||
|
||||
@classmethod
|
||||
def find_polymorphic_subclass(cls, polymorphic_identity: str | SubmissionType | None = None,
|
||||
attrs: dict | None = None):
|
||||
attrs: dict | None = None) -> BasicSubmission:
|
||||
"""
|
||||
Find subclass based on polymorphic identity or relevant attributes.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user