Skip to content

Commit

Permalink
feat(pep_0585):
Browse files Browse the repository at this point in the history
  • Loading branch information
henrikstranneheim committed Mar 8, 2024
1 parent 10225ca commit 05ac470
Show file tree
Hide file tree
Showing 11 changed files with 60 additions and 65 deletions.
11 changes: 5 additions & 6 deletions genotype_api/api/endpoints/analyses.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"""Routes for analysis"""

from pathlib import Path
from typing import List

from fastapi import APIRouter, Depends, status, Query, UploadFile, File
from fastapi.responses import JSONResponse
Expand Down Expand Up @@ -40,15 +39,15 @@ def read_analysis(
return get_analysis(session=session, analysis_id=analysis_id)


@router.get("/", response_model=List[AnalysisRead])
@router.get("/", response_model=list[AnalysisRead])
def read_analyses(
skip: int = 0,
limit: int = Query(default=100, lte=100),
session: Session = Depends(get_session),
current_user: User = Depends(get_active_user),
) -> List[Analysis]:
) -> list[Analysis]:
"""Return all analyses."""
analyses: List[Analysis] = session.exec(select(Analysis).offset(skip).limit(limit)).all()
analyses: list[Analysis] = session.exec(select(Analysis).offset(skip).limit(limit)).all()

return analyses

Expand All @@ -67,7 +66,7 @@ def delete_analysis(
return JSONResponse(f"Deleted analysis: {analysis_id}", status_code=status.HTTP_200_OK)


@router.post("/sequence", response_model=List[Analysis])
@router.post("/sequence", response_model=list[Analysis])
def upload_sequence_analysis(
file: UploadFile = File(...),
session: Session = Depends(get_session),
Expand All @@ -78,7 +77,7 @@ def upload_sequence_analysis(
file_name: Path = check_file(file_path=file.filename, extension=".vcf")
content = file.file.read().decode("utf-8")
sequence_analysis = SequenceAnalysis(vcf_file=content, source=str(file_name))
analyses: List[Analysis] = list(sequence_analysis.generate_analyses())
analyses: list[Analysis] = list(sequence_analysis.generate_analyses())
check_analyses_objects(session=session, analyses=analyses, analysis_type="sequence")
create_analyses_sample_objects(session=session, analyses=analyses)
for analysis in analyses:
Expand Down
10 changes: 5 additions & 5 deletions genotype_api/api/endpoints/plates.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from datetime import datetime
from io import BytesIO
from pathlib import Path
from typing import List, Optional, Literal
from typing import Optional, Literal

from fastapi import APIRouter, Depends, File, HTTPException, UploadFile, Query, status
from sqlalchemy import desc, asc
Expand Down Expand Up @@ -66,7 +66,7 @@ def upload_plate(
file_name=str(file_name),
include_key="-CG-",
)
analyses: List[Analysis] = list(excel_parser.generate_analyses())
analyses: list[Analysis] = list(excel_parser.generate_analyses())
check_analyses_objects(session=session, analyses=analyses, analysis_type="genotype")
create_analyses_sample_objects(session=session, analyses=analyses)
plate_obj = PlateCreate(plate_id=plate_id)
Expand Down Expand Up @@ -136,7 +136,7 @@ def read_plate(

@router.get(
"/",
response_model=List[PlateReadWithAnalysisDetail],
response_model=list[PlateReadWithAnalysisDetail],
response_model_exclude={"analyses"},
response_model_by_alias=False,
)
Expand All @@ -150,7 +150,7 @@ async def read_plates(
):
"""Display all plates"""
sort_func = desc if sort_order == "descend" else asc
plates: List[Plate] = session.exec(
plates: list[Plate] = session.exec(
select(Plate).order_by(sort_func(order_by)).offset(skip).limit(limit)
).all()

Expand All @@ -165,7 +165,7 @@ def delete_plate(
):
"""Delete plate."""
plate = session.get(Plate, plate_id)
analyses: List[Analysis] = get_analyses_from_plate(session=session, plate_id=plate_id)
analyses: list[Analysis] = get_analyses_from_plate(session=session, plate_id=plate_id)
analyse_ids = [analyse.id for analyse in analyses]
for analysis in analyses:
session.delete(analysis)
Expand Down
10 changes: 5 additions & 5 deletions genotype_api/api/endpoints/samples.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import List, Optional, Literal
from typing import Optional, Literal
from fastapi import APIRouter, Depends, Query
from fastapi.responses import JSONResponse
from datetime import timedelta, date
Expand Down Expand Up @@ -71,7 +71,7 @@ def read_sample(

@router.get(
"/",
response_model=List[SampleReadWithAnalysisDeep],
response_model=list[SampleReadWithAnalysisDeep],
response_model_by_alias=False,
response_model_exclude={
"analyses": {"__all__": {"genotypes": True, "source": True, "created_at": True}},
Expand All @@ -95,7 +95,7 @@ def read_samples(
status_missing: Optional[bool] = False,
session: Session = Depends(get_session),
current_user: User = Depends(get_active_user),
) -> List[Sample]:
) -> list[Sample]:
"""Returns a list of samples matching the provided filters."""
statement: SelectOfScalar = select(Sample).distinct().join(Analysis)
if sample_id:
Expand Down Expand Up @@ -182,7 +182,7 @@ def set_sample_status(
return sample


@router.get("/{sample_id}/match", response_model=List[MatchResult])
@router.get("/{sample_id}/match", response_model=list[MatchResult])
def match(
sample_id: str,
analysis_type: Literal["genotype", "sequence"],
Expand All @@ -191,7 +191,7 @@ def match(
date_max: Optional[date] = date.max,
session: Session = Depends(get_session),
current_user: User = Depends(get_active_user),
) -> List[MatchResult]:
) -> list[MatchResult]:
"""Match sample genotype against all other genotypes."""

all_genotypes: Analysis = session.query(Analysis).filter(
Expand Down
9 changes: 4 additions & 5 deletions genotype_api/api/endpoints/snps.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"""Routes for the snps"""

from genotype_api.database.models.models import SNP, User
from typing import List

from fastapi import APIRouter, Depends, HTTPException, Query, File, UploadFile
from genotype_api.database import get_session
Expand All @@ -16,23 +15,23 @@
router = APIRouter()


@router.get("/", response_model=List[SNP])
@router.get("/", response_model=list[SNP])
def read_snps(
skip: int = 0,
limit: int = Query(default=100, lte=100),
session: Session = Depends(get_session),
current_user: User = Depends(get_active_user),
) -> List[SNP]:
) -> list[SNP]:
return session.exec(select(SNP).offset(skip).limit(limit)).all()


@router.post("/", response_model=List[SNP])
@router.post("/", response_model=list[SNP])
async def upload_snps(
snps_file: UploadFile,
session: Session = Depends(get_session),
current_user: User = Depends(get_active_user),
):
db_snps: List[SNP] = session.exec(select(SNP)).all()
db_snps: list[SNP] = session.exec(select(SNP)).all()
if db_snps:
raise HTTPException(status_code=400, detail="SNPs already uploaded")
snps = []
Expand Down
10 changes: 4 additions & 6 deletions genotype_api/api/endpoints/users.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
"""Routes for users"""

from typing import List

from fastapi import APIRouter, Depends, HTTPException, Query
from pydantic import EmailStr
from starlette import status
Expand Down Expand Up @@ -67,14 +65,14 @@ def change_user_email(
return user


@router.get("/", response_model=List[UserRead])
@router.get("/", response_model=list[UserRead])
def read_users(
skip: int = 0,
limit: int = Query(default=100, lte=100),
session: Session = Depends(get_session),
current_user: User = Depends(get_active_user),
) -> List[User]:
users: List[User] = session.exec(select(User).offset(skip).limit(limit)).all()
) -> list[User]:
users: list[User] = session.exec(select(User).offset(skip).limit(limit)).all()
return users


Expand All @@ -84,7 +82,7 @@ def create_user(
session: Session = Depends(get_session),
current_user: User = Depends(get_active_user),
):
user_in_db: List[User] = session.exec(select(User).where(User.email == user.email)).all()
user_in_db: list[User] = session.exec(select(User).where(User.email == user.email)).all()
if user_in_db:
raise HTTPException(status_code=409, detail="Email already registered")
db_user = User.from_orm(user)
Expand Down
3 changes: 1 addition & 2 deletions genotype_api/database/crud/create.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import logging
from typing import List

from fastapi import HTTPException
from sqlmodel import Session
Expand Down Expand Up @@ -49,7 +48,7 @@ def create_sample(session: Session, sample: Sample) -> Sample:
return sample


def create_analyses_sample_objects(session: Session, analyses: List[Analysis]) -> List[Sample]:
def create_analyses_sample_objects(session: Session, analyses: list[Analysis]) -> list[Sample]:
"""creating samples in an analysis if not already in db."""
return [
create_sample(session=session, sample=Sample(id=analysis_obj.sample_id))
Expand Down
8 changes: 4 additions & 4 deletions genotype_api/database/crud/read.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import logging
from typing import List, Optional
list[, Optional

from sqlalchemy import func
from sqlmodel import Session, select
Expand All @@ -14,7 +14,7 @@
LOG = logging.getLogger(__name__)


def get_analyses_from_plate(plate_id: int, session: Session) -> List[Analysis]:
def get_analyses_from_plate(plate_id: int, session: Session) -> list[Analysis]:
statement = select(Analysis).where(Analysis.plate_id == plate_id)
return session.exec(statement).all()

Expand Down Expand Up @@ -91,13 +91,13 @@ def get_user_by_email(session: Session, email: str) -> Optional[User]:
return session.exec(statement).first()


def get_users(session: Session, skip: int = 0, limit: int = 100) -> List[User]:
def get_users(session: Session, skip: int = 0, limit: int = 100) -> list[User]:
statement = select(User).offset(skip).limit(limit)
return session.exec(statement).all()


def check_analyses_objects(
session: Session, analyses: List[Analysis], analysis_type: TYPES
session: Session, analyses: list[Analysis], analysis_type: TYPES
) -> None:
"""Raising 400 if any analysis in the list already exist in the database"""
for analysis_obj in analyses:
Expand Down
34 changes: 17 additions & 17 deletions genotype_api/database/models/models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from collections import Counter
from datetime import datetime
from typing import Optional, List, Dict, Tuple
from typing import Optional

from pydantic import constr, EmailStr, validator
from sqlalchemy import Index
Expand All @@ -25,7 +25,7 @@ class Genotype(GenotypeBase, table=True):
analysis: Optional["Analysis"] = Relationship(back_populates="genotypes")

@property
def alleles(self) -> List[str]:
def alleles(self) -> list[str]:
"""Return sorted because we are not dealing with phased data."""

return sorted([self.allele_1, self.allele_2])
Expand Down Expand Up @@ -59,10 +59,10 @@ class Analysis(AnalysisBase, table=True):
id: Optional[int] = Field(default=None, primary_key=True)

sample: Optional["Sample"] = Relationship(back_populates="analyses")
plate: Optional[List["Plate"]] = Relationship(back_populates="analyses")
genotypes: Optional[List["Genotype"]] = Relationship(back_populates="analysis")
plate: Optional[list["Plate"]] = Relationship(back_populates="analyses")
genotypes: Optional[list["Genotype"]] = Relationship(back_populates="analysis")

def check_no_calls(self) -> Dict[str, int]:
def check_no_calls(self) -> dict[str, int]:
"""Check that genotypes look ok."""
calls = ["known" if genotype.is_ok else "unknown" for genotype in self.genotypes]
return Counter(calls)
Expand Down Expand Up @@ -90,7 +90,7 @@ class Sample(SampleBase, table=True):
__tablename__ = "sample"
id: Optional[constr(max_length=32)] = Field(default=None, primary_key=True)

analyses: Optional[List["Analysis"]] = Relationship(back_populates="sample")
analyses: Optional[list["Analysis"]] = Relationship(back_populates="sample")

@property
def genotype_analysis(self) -> Optional[Analysis]:
Expand Down Expand Up @@ -146,7 +146,7 @@ class UserBase(SQLModel):
class User(UserBase, table=True):
__tablename__ = "user"
id: Optional[int] = Field(default=None, primary_key=True)
plates: Optional[List["Plate"]] = Relationship(back_populates="user")
plates: Optional[list["Plate"]] = Relationship(back_populates="user")


class UserRead(UserBase):
Expand All @@ -170,7 +170,7 @@ class Plate(PlateBase, table=True):
__tablename__ = "plate"
id: Optional[int] = Field(default=None, primary_key=True)
user: Optional["User"] = Relationship(back_populates="plates")
analyses: Optional[List["Analysis"]] = Relationship(back_populates="plate")
analyses: Optional[list["Analysis"]] = Relationship(back_populates="plate")


class PlateRead(PlateBase):
Expand All @@ -179,23 +179,23 @@ class PlateRead(PlateBase):


class PlateCreate(PlateBase):
analyses: Optional[List[Analysis]] = []
analyses: Optional[list[Analysis]] = []


class UserReadWithPlates(UserRead):
plates: Optional[List[Plate]] = []
plates: Optional[list[Plate]] = []


class SampleReadWithAnalysis(SampleRead):
analyses: Optional[List[AnalysisRead]] = []
analyses: Optional[list[AnalysisRead]] = []


class AnalysisReadWithGenotype(AnalysisRead):
genotypes: Optional[List[Genotype]] = []
genotypes: Optional[list[Genotype]] = []


class SampleReadWithAnalysisDeep(SampleRead):
analyses: Optional[List[AnalysisReadWithGenotype]] = []
analyses: Optional[list[AnalysisReadWithGenotype]] = []
detail: Optional[SampleDetail]

@validator("detail")
Expand Down Expand Up @@ -224,7 +224,7 @@ class AnalysisReadWithSample(AnalysisRead):
sample: Optional[SampleSlim]


def compare_genotypes(genotype_1: Genotype, genotype_2: Genotype) -> Tuple[str, str]:
def compare_genotypes(genotype_1: Genotype, genotype_2: Genotype) -> tuple[str, str]:
"""Compare two genotypes if they have the same alleles."""

if "0" in genotype_1.alleles or "0" in genotype_2.alleles:
Expand All @@ -240,11 +240,11 @@ class AnalysisReadWithSampleDeep(AnalysisRead):


class PlateReadWithAnalyses(PlateRead):
analyses: Optional[List[AnalysisReadWithSample]] = []
analyses: Optional[list[AnalysisReadWithSample]] = []


class PlateReadWithAnalysisDetail(PlateRead):
analyses: Optional[List[AnalysisReadWithSample]] = []
analyses: Optional[list[AnalysisReadWithSample]] = []
detail: Optional[PlateStatusCounts]

@validator("detail")
Expand All @@ -260,7 +260,7 @@ class Config:


class PlateReadWithAnalysisDetailSingle(PlateRead):
analyses: Optional[List[AnalysisReadWithSample]] = []
analyses: Optional[list[AnalysisReadWithSample]] = []
detail: Optional[PlateStatusCounts]

@validator("detail")
Expand Down
Loading

0 comments on commit 05ac470

Please sign in to comment.