From 80d77117e1bf3f309f51ea9ac7efa607e2203052 Mon Sep 17 00:00:00 2001 From: Landon Wark Date: Fri, 13 Oct 2023 09:26:12 -0500 Subject: [PATCH] Pre-refactor --- TODO.md | 1 + .../backend/db/functions/constructions.py | 13 +++++----- src/submissions/backend/db/functions/misc.py | 1 - .../backend/db/models/submissions.py | 13 ++++++++++ src/submissions/backend/pydant/__init__.py | 4 +-- src/submissions/tools/__init__.py | 25 +++++++++++++------ 6 files changed, 41 insertions(+), 16 deletions(-) diff --git a/TODO.md b/TODO.md index c287f8d..2f22789 100644 --- a/TODO.md +++ b/TODO.md @@ -1,3 +1,4 @@ +- [x] Change 'check_is_power_user' to decorator. - [x] Drag and drop files into submission form area? - [ ] Get info for controls into their sample hitpicks. - [x] Move submission-type specific parser functions into class methods in their respective models. diff --git a/src/submissions/backend/db/functions/constructions.py b/src/submissions/backend/db/functions/constructions.py index 78ab32f..01410a7 100644 --- a/src/submissions/backend/db/functions/constructions.py +++ b/src/submissions/backend/db/functions/constructions.py @@ -2,7 +2,7 @@ Used to construct models from input dictionaries. ''' from getpass import getuser -from tools import Settings, RSLNamer, check_regex_match +from tools import Settings, RSLNamer, check_regex_match, check_authorization, massage_common_reagents from .. import models from .lookups import * import logging @@ -190,6 +190,7 @@ def construct_samples(ctx:Settings, instance:models.BasicSubmission, samples:Lis continue return instance +@check_authorization def construct_kit_from_yaml(ctx:Settings, kit_dict:dict) -> dict: """ Create and store a new kit in the database based on a .yml file @@ -197,16 +198,16 @@ def construct_kit_from_yaml(ctx:Settings, kit_dict:dict) -> dict: Args: ctx (Settings): Context object passed down from frontend - exp (dict): Experiment dictionary created from yaml file + kit_dict (dict): Experiment dictionary created from yaml file Returns: dict: a dictionary containing results of db addition """ - from tools import check_is_power_user, massage_common_reagents + # from tools import check_is_power_user, massage_common_reagents # Don't want just anyone adding kits - if not check_is_power_user(ctx=ctx): - logger.debug(f"{getuser()} does not have permission to add kits.") - return {'code':1, 'message':"This user does not have permission to add kits.", "status":"warning"} + # if not check_is_power_user(ctx=ctx): + # logger.debug(f"{getuser()} does not have permission to add kits.") + # return {'code':1, 'message':"This user does not have permission to add kits.", "status":"warning"} submission_type = lookup_submission_type(ctx=ctx, name=kit_dict['used_for']) logger.debug(f"Looked up submission type: {kit_dict['used_for']} and got {submission_type}") kit = models.KitType(name=kit_dict["kit_name"]) diff --git a/src/submissions/backend/db/functions/misc.py b/src/submissions/backend/db/functions/misc.py index 1a68a24..8880f30 100644 --- a/src/submissions/backend/db/functions/misc.py +++ b/src/submissions/backend/db/functions/misc.py @@ -258,4 +258,3 @@ def get_polymorphic_subclass(base:object, polymorphic_identity:str|None=None): logger.error(f"Could not get polymorph {polymorphic_identity} of {base} due to {e}") return base - \ No newline at end of file diff --git a/src/submissions/backend/db/models/submissions.py b/src/submissions/backend/db/models/submissions.py index e6db1eb..efbda37 100644 --- a/src/submissions/backend/db/models/submissions.py +++ b/src/submissions/backend/db/models/submissions.py @@ -294,6 +294,19 @@ class BasicSubmission(Base): Workbook: updated workbook """ return input_excel + + @classmethod + def enforce_naming_schema(cls, input_str:str) -> str: + """ + Used to ensure proper custom naming of submission. + + Args: + input_str (str): name parsed by default parser + + Returns: + str: custom parser output. + """ + return input_str # Below are the custom submission types diff --git a/src/submissions/backend/pydant/__init__.py b/src/submissions/backend/pydant/__init__.py index bbb4c1f..588767a 100644 --- a/src/submissions/backend/pydant/__init__.py +++ b/src/submissions/backend/pydant/__init__.py @@ -2,7 +2,7 @@ Contains pydantic models and accompanying validators ''' import uuid -from pydantic import BaseModel, field_validator, Extra, Field +from pydantic import BaseModel, field_validator, Field from datetime import date, datetime from dateutil.parser import parse from dateutil.parser._parser import ParserError @@ -74,7 +74,7 @@ class PydReagent(BaseModel): -class PydSubmission(BaseModel, extra=Extra.allow): +class PydSubmission(BaseModel, extra='allow'): ctx: Settings filepath: Path submission_type: dict|None diff --git a/src/submissions/tools/__init__.py b/src/submissions/tools/__init__.py index d43f450..b16c283 100644 --- a/src/submissions/tools/__init__.py +++ b/src/submissions/tools/__init__.py @@ -6,7 +6,6 @@ import re import numpy as np import logging import pandas as pd -from datetime import datetime from jinja2 import Environment, FileSystemLoader import yaml import sys, os, stat, platform, getpass @@ -18,6 +17,7 @@ from sqlalchemy import create_engine from pydantic import field_validator from pydantic_settings import BaseSettings, SettingsConfigDict from typing import Any, Tuple +from datetime import datetime logger = logging.getLogger(f"submissions.{__name__}") @@ -133,18 +133,21 @@ def massage_common_reagents(reagent_name:str): reagent_name = "molecular_grade_water" reagent_name = reagent_name.replace("ยต", "u") return reagent_name - + class RSLNamer(object): """ Object that will enforce proper formatting on RSL plate names. """ def __init__(self, ctx, instr:str, sub_type:str|None=None): + from backend.db.functions import get_polymorphic_subclass + from backend.db.models import BasicSubmission self.ctx = ctx self.submission_type = sub_type self.retrieve_rsl_number(in_str=instr) if self.submission_type != None: - parser = getattr(self, f"enforce_{self.submission_type.replace(' ', '_').lower()}") - parser() + custom_enforcer = get_polymorphic_subclass(BasicSubmission, self.submission_type).enforce_naming_schema + # parser = getattr(self, f"enforce_{self.submission_type.replace(' ', '_').lower()}") + # parser() self.parsed_name = self.parsed_name.replace("_", "-") def retrieve_rsl_number(self, in_str:str|Path): @@ -220,8 +223,6 @@ class RSLNamer(object): repeat = "" self.parsed_name = re.sub(r"(-\dR)\d?", rf"\1 {repeat}", self.parsed_name).replace(" ", "") - - def enforce_bacterial_culture(self): """ Uses regex to enforce proper formatting of bacterial culture samples @@ -588,6 +589,7 @@ def jinja_template_loading(): def check_is_power_user(ctx:Settings) -> bool: """ Check to ensure current user is in power users list. + NOTE: Depreciated in favour of 'check_authorization' below. Args: ctx (dict): settings passed down from gui. @@ -604,6 +606,16 @@ def check_is_power_user(ctx:Settings) -> bool: check = False return check +def check_authorization(func): + def wrapper(*args, **kwargs): + logger.debug(f"Checking authorization") + if getpass.getuser() in kwargs['ctx'].power_users: + return func(*args, **kwargs) + else: + logger.error(f"User {getpass.getuser()} is not authorized for this function.") + return dict(code=1, message="This user does not have permission for this function.", status="warning") + return wrapper + def check_if_app(ctx:Settings=None) -> bool: """ Checks if the program is running from pyinstaller compiled @@ -636,4 +648,3 @@ def convert_well_to_row_column(input_str:str) -> Tuple[int, int]: except IndexError: return None, None return row, column -