feat(validation): add SQLModel database models and fix relationships
This commit is contained in:
26
src/macro_lactone_toolkit/validation/database.py
Normal file
26
src/macro_lactone_toolkit/validation/database.py
Normal file
@@ -0,0 +1,26 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from contextlib import contextmanager
|
||||
from pathlib import Path
|
||||
|
||||
from sqlmodel import Session, SQLModel, create_engine
|
||||
|
||||
|
||||
def get_engine(db_path: str | Path):
|
||||
"""Create SQLite engine."""
|
||||
db_path = Path(db_path)
|
||||
db_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
url = f"sqlite:///{db_path}"
|
||||
return create_engine(url, echo=False)
|
||||
|
||||
|
||||
@contextmanager
|
||||
def get_session(engine):
|
||||
"""Context manager for database sessions."""
|
||||
with Session(engine) as session:
|
||||
yield session
|
||||
|
||||
|
||||
def init_database(engine):
|
||||
"""Create all tables."""
|
||||
SQLModel.metadata.create_all(engine)
|
||||
@@ -1,25 +1,26 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
from enum import Enum
|
||||
from typing import List, Optional
|
||||
|
||||
from sqlmodel import Field, Relationship, SQLModel
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
from sqlmodel import Field, SQLModel
|
||||
|
||||
|
||||
class ClassificationType(str, Enum):
|
||||
class ClassificationType:
|
||||
STANDARD = "standard_macrolactone"
|
||||
NON_STANDARD = "non_standard_macrocycle"
|
||||
NOT_MACROLACTONE = "not_macrolactone"
|
||||
|
||||
|
||||
class ProcessingStatus(str, Enum):
|
||||
class ProcessingStatus:
|
||||
PENDING = "pending"
|
||||
SUCCESS = "success"
|
||||
FAILED = "failed"
|
||||
SKIPPED = "skipped"
|
||||
|
||||
|
||||
# Define all tables without relationships first
|
||||
class ParentMolecule(SQLModel, table=True):
|
||||
"""Original molecule information."""
|
||||
|
||||
@@ -29,11 +30,11 @@ class ParentMolecule(SQLModel, table=True):
|
||||
source_id: str = Field(index=True)
|
||||
molecule_name: Optional[str] = None
|
||||
smiles: str = Field(index=True)
|
||||
classification: ClassificationType = Field(index=True)
|
||||
classification: str = Field(index=True)
|
||||
ring_size: Optional[int] = Field(default=None, index=True)
|
||||
primary_reason_code: Optional[str] = None
|
||||
primary_reason_message: Optional[str] = None
|
||||
processing_status: ProcessingStatus = Field(default=ProcessingStatus.PENDING)
|
||||
processing_status: str = Field(default=ProcessingStatus.PENDING)
|
||||
error_message: Optional[str] = None
|
||||
num_sidechains: Optional[int] = None
|
||||
cleavage_positions: Optional[str] = None
|
||||
@@ -41,9 +42,6 @@ class ParentMolecule(SQLModel, table=True):
|
||||
created_at: datetime = Field(default_factory=datetime.utcnow)
|
||||
processed_at: Optional[datetime] = None
|
||||
|
||||
fragments: List["SideChainFragment"] = Relationship(back_populates="parent")
|
||||
numbering: Optional["RingNumbering"] = Relationship(back_populates="parent")
|
||||
|
||||
|
||||
class RingNumbering(SQLModel, table=True):
|
||||
"""Ring numbering details."""
|
||||
@@ -58,8 +56,6 @@ class RingNumbering(SQLModel, table=True):
|
||||
position_to_atom: str
|
||||
atom_to_position: str
|
||||
|
||||
parent: Optional[ParentMolecule] = Relationship(back_populates="numbering")
|
||||
|
||||
|
||||
class SideChainFragment(SQLModel, table=True):
|
||||
"""Side chain fragments from cleavage."""
|
||||
@@ -81,8 +77,6 @@ class SideChainFragment(SQLModel, table=True):
|
||||
original_bond_type: str
|
||||
image_path: Optional[str] = None
|
||||
|
||||
parent: Optional[ParentMolecule] = Relationship(back_populates="fragments")
|
||||
|
||||
|
||||
class ValidationResult(SQLModel, table=True):
|
||||
"""Manual validation records."""
|
||||
|
||||
Reference in New Issue
Block a user