Ui interface updates.

This commit is contained in:
lwark
2025-07-04 12:31:55 -05:00
parent 51b193b4db
commit 0472afd9a5
11 changed files with 157 additions and 107 deletions

View File

@@ -13,6 +13,7 @@ from sqlalchemy import Column, INTEGER, String, JSON
from sqlalchemy.ext.associationproxy import AssociationProxy
from sqlalchemy.orm import DeclarativeMeta, declarative_base, Query, Session, InstrumentedAttribute, ColumnProperty
from sqlalchemy.ext.declarative import declared_attr
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.exc import ArgumentError
from typing import Any, List, ClassVar
from pathlib import Path
@@ -237,10 +238,10 @@ class BaseClass(Base):
@classmethod
def query_or_create(cls, **kwargs) -> Tuple[Any, bool]:
new = False
allowed = [k for k, v in cls.__dict__.items() if isinstance(v, InstrumentedAttribute)]
allowed = [k for k, v in cls.__dict__.items() if isinstance(v, InstrumentedAttribute) or isinstance(v, hybrid_property)]
# and not isinstance(v.property, _RelationshipDeclared)]
sanitized_kwargs = {k: v for k, v in kwargs.items() if k in allowed}
# logger.debug(f"Sanitized kwargs: {sanitized_kwargs}")
logger.debug(f"Sanitized kwargs: {sanitized_kwargs}")
instance = cls.query(**sanitized_kwargs)
if not instance or isinstance(instance, list):
instance = cls()
@@ -273,7 +274,7 @@ class BaseClass(Base):
return cls.execute_query(**kwargs)
@classmethod
def execute_query(cls, query: Query = None, model=None, limit: int = 0, **kwargs) -> Any | List[Any]:
def execute_query(cls, query: Query = None, model=None, limit: int = 0, offset:int|None=None, **kwargs) -> Any | List[Any]:
"""
Execute sqlalchemy query with relevant defaults.
@@ -291,22 +292,32 @@ class BaseClass(Base):
# logger.debug(f"Model: {model}")
if query is None:
query: Query = cls.__database_session__.query(cls)
else:
logger.debug(f"Incoming query: {query}")
singles = cls.get_default_info('singles')
for k, v in kwargs.items():
logger.info(f"Using key: {k} with value: {v}")
logger.info(f"Using key: {k} with value: {v} against {cls}")
try:
attr = getattr(cls, k)
# NOTE: account for attrs that use list.
if attr.property.uselist:
query = query.filter(attr.contains(v))
else:
query = query.filter(attr == v)
except (ArgumentError, AttributeError) as e:
logger.error(f"Attribute {k} unavailable due to:\n\t{e}\nSkipping.")
logger.error(f"Attribute {k} unavailable due to:\n\t{e}\n.")
continue
# NOTE: account for attrs that use list.
try:
check = attr.property.uselist
except AttributeError:
check = False
if check:
logger.debug("Got uselist")
query = query.filter(attr.contains(v))
else:
logger.debug("Single item.")
query = query.filter(attr == v)
if k in singles:
logger.warning(f"{k} is in singles. Returning only one value.")
limit = 1
if offset:
query.offset(offset)
with query.session.no_autoflush:
match limit:
case 0:
@@ -476,13 +487,13 @@ class BaseClass(Base):
# logger.debug(f"Attempting to set: {key} to {value}")
if key.startswith("_"):
return super().__setattr__(key, value)
try:
check = not hasattr(self, key)
except:
return
# try:
check = not hasattr(self, key)
# except:
# return
if check:
try:
json.dumps(value)
value = json.dumps(value)
except TypeError:
value = str(value)
self._misc_info.update({key: value})
@@ -612,6 +623,7 @@ class BaseClass(Base):
if dlg.exec():
pass
class LogMixin(Base):
tracking_exclusion: ClassVar = ['artic_technician', 'clientsubmissionsampleassociation',
'submission_reagent_associations', 'submission_equipment_associations',

View File

@@ -149,12 +149,14 @@ class ClientSubmission(BaseClass, LogMixin):
pass
# query = query.order_by(cls.submitted_date.desc())
# NOTE: Split query results into pages of size {page_size}
if page_size > 0:
query = query.limit(page_size)
if page_size > 0 and limit == 0:
limit = page_size
page = page - 1
if page is not None:
query = query.offset(page * page_size)
return cls.execute_query(query=query, limit=limit, **kwargs)
offset = page * page_size
else:
offset = None
return cls.execute_query(query=query, limit=limit, offset=offset, **kwargs)
@classmethod
def submissions_to_df(cls, submissiontype: str | None = None, limit: int = 0,
@@ -269,7 +271,9 @@ class ClientSubmission(BaseClass, LogMixin):
try:
assert isinstance(sample, Sample)
except AssertionError:
logger.warning(f"Converting {sample} to sql.")
sample = sample.to_sql()
logger.debug(sample.__dict__)
try:
row = sample._misc_info['row']
except (KeyError, AttributeError):
@@ -278,10 +282,12 @@ class ClientSubmission(BaseClass, LogMixin):
column = sample._misc_info['column']
except KeyError:
column = 0
logger.debug(f"Sample: {sample}")
submission_rank = sample._misc_info['submission_rank']
assoc = ClientSubmissionSampleAssociation(
sample=sample,
submission=self,
submission_rank=sample._misc_info['submission_rank'],
submission_rank=submission_rank,
row=row,
column=column
)
@@ -310,8 +316,9 @@ class ClientSubmission(BaseClass, LogMixin):
for sample in active_samples:
sample = sample.to_sql()
logger.debug(f"Sample: {sample.id}")
assoc = run.add_sample(sample)
assoc.save()
if sample not in run.sample:
assoc = run.add_sample(sample)
assoc.save()
else:
logger.warning("Run cancelled.")
obj.set_data()