Skip to content

Commit

Permalink
refactor user and snp endpoints (#108) (patch)
Browse files Browse the repository at this point in the history
Refactor user and SNP endpoints
  • Loading branch information
ChrOertlin authored Mar 19, 2024
1 parent 13ab34b commit a45dabe
Show file tree
Hide file tree
Showing 11 changed files with 101 additions and 49 deletions.
2 changes: 1 addition & 1 deletion genotype_api/api/endpoints/samples.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
from genotype_api.database.session_handler import get_session
from genotype_api.models import MatchResult, SampleDetail
from genotype_api.security import get_active_user
from genotype_api.service.match_genotype_service.match_genotype import MatchGenotypeService
from genotype_api.services.match_genotype_service.match_genotype import MatchGenotypeService

SelectOfScalar.inherit_cache = True
Select.inherit_cache = True
Expand Down
30 changes: 12 additions & 18 deletions genotype_api/api/endpoints/snps.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
"""Routes for the snps"""

from fastapi import APIRouter, Depends, HTTPException, Query, UploadFile
from sqlmodel import Session, delete, select
from sqlmodel import Session
from sqlmodel.sql.expression import Select, SelectOfScalar

from genotype_api.database.crud.create import create_snps
from genotype_api.database.crud.read import get_snps, get_snps_by_limit_and_skip
from genotype_api.database.models import SNP, User
from genotype_api.database.crud import delete
from genotype_api.database.session_handler import get_session
from genotype_api.security import get_active_user
from genotype_api.services.snp_reader.snp_reader import SNPReaderService

SelectOfScalar.inherit_cache = True
Select.inherit_cache = True
Expand All @@ -21,7 +25,7 @@ def read_snps(
session: Session = Depends(get_session),
current_user: User = Depends(get_active_user),
) -> list[SNP]:
return session.exec(select(SNP).offset(skip).limit(limit)).all()
return get_snps_by_limit_and_skip(session=session, skip=skip, limit=limit)


@router.post("/", response_model=list[SNP])
Expand All @@ -30,21 +34,12 @@ async def upload_snps(
session: Session = Depends(get_session),
current_user: User = Depends(get_active_user),
):
db_snps: list[SNP] = session.exec(select(SNP)).all()
if db_snps:
existing_snps: list[SNP] = get_snps(session)
if existing_snps:
raise HTTPException(status_code=400, detail="SNPs already uploaded")
snps = []
content = await snps_file.read()

header = ["id", "ref", "chrom", "pos"]
for line in content.decode().split("\n"):
if len(line) <= 10:
continue
snp = SNP(**dict(zip(header, line.split())))
session.add(snp)
snps.append(snp)
session.commit()
return snps
snps: list[SNP] = SNPReaderService.read_snps_from_file(snps_file)
new_snps: list[snps] = create_snps(session=session, snps=snps)
return new_snps


@router.delete("/")
Expand All @@ -54,6 +49,5 @@ def delete_snps(
):
"""Delete all SNPs"""

result = session.exec(delete(SNP))
session.commit()
result = delete.delete_snps(session)
return {"message": f"all snps deleted ({result.rowcount} snps)"}
30 changes: 14 additions & 16 deletions genotype_api/api/endpoints/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@
from starlette import status
from starlette.responses import JSONResponse

from genotype_api.database.crud.read import get_user
from genotype_api.database.crud.read import (
get_user,
get_user_by_email,
get_users_with_skip_and_limit,
)
from genotype_api.database.crud.update import update_user_email
from genotype_api.database.crud import delete, create
from genotype_api.database.models import User
from genotype_api.dto.dto import UserRead, UserCreate, UserReadWithPlates
from genotype_api.database.session_handler import get_session
Expand Down Expand Up @@ -43,8 +49,7 @@ def delete_user(
status_code=status.HTTP_406_NOT_ACCEPTABLE,
detail="User previously signed plates, please archive instead",
)
session.delete(user)
session.commit()
delete.delete_user(session=session, user=user)
return JSONResponse(content="User deleted successfully", status_code=status.HTTP_200_OK)


Expand All @@ -58,10 +63,7 @@ def change_user_email(
user: User = get_user(session=session, user_id=user_id)
if not user:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="User not found")
user.email = email
session.add(user)
session.commit()
session.refresh(user)
user: User = update_user_email(session=session, user=user, email=email)
return user


Expand All @@ -72,8 +74,7 @@ def read_users(
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()
return users
return get_users_with_skip_and_limit(session=session, skip=skip, limit=limit)


@router.post("/", response_model=User)
Expand All @@ -82,11 +83,8 @@ 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()
if user_in_db:
existing_user: User = get_user_by_email(session=session, email=user.email)
if existing_user:
raise HTTPException(status_code=409, detail="Email already registered")
db_user = User.from_orm(user)
session.add(db_user)
session.commit()
session.refresh(db_user)
return db_user
new_user: User = create.create_user(session=session, user=user)
return new_user
19 changes: 12 additions & 7 deletions genotype_api/database/crud/create.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from sqlmodel import Session
from sqlmodel.sql.expression import Select, SelectOfScalar

from genotype_api.database.models import Analysis, Plate, Sample, User
from genotype_api.database.models import Analysis, Plate, Sample, User, SNP
from genotype_api.dto.dto import UserCreate, PlateCreate

SelectOfScalar.inherit_cache = True
Expand Down Expand Up @@ -51,10 +51,15 @@ def create_analyses_sample_objects(session: Session, analyses: list[Analysis]) -
]


def create_user(db: Session, user: UserCreate):
fake_hashed_password = user.password + "notreallyhashed"
db_user = User(email=user.email, hashed_password=fake_hashed_password)
db.add(db_user)
db.commit()
db.refresh(db_user)
def create_user(session: Session, user: UserCreate):
db_user = User.from_orm(user)
session.add(db_user)
session.commit()
session.refresh(db_user)
return db_user


def create_snps(session: Session, snps: list[SNP]) -> list[SNP]:
session.add_all(snps)
session.commit()
return snps
14 changes: 13 additions & 1 deletion genotype_api/database/crud/delete.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import logging

from sqlalchemy import delete
from sqlmodel import Session
from sqlmodel.sql.expression import Select, SelectOfScalar

from genotype_api.database.models import Analysis, Plate, Sample
from genotype_api.database.models import Analysis, Plate, Sample, User, SNP

SelectOfScalar.inherit_cache = True
Select.inherit_cache = True
Expand All @@ -24,3 +25,14 @@ def delete_plate(session: Session, plate: Plate) -> None:
def delete_sample(session: Session, sample: Sample) -> None:
session.delete(sample)
session.commit()


def delete_user(session: Session, user: User) -> None:
session.delete(user)
session.commit()


def delete_snps(session) -> any:
result = session.exec(delete(SNP))
session.commit()
return result
13 changes: 13 additions & 0 deletions genotype_api/database/crud/read.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
Plate,
Sample,
User,
SNP,
)
from genotype_api.dto.dto import PlateReadWithAnalysisDetailSingle

Expand Down Expand Up @@ -173,6 +174,10 @@ def get_users(session: Session, skip: int = 0, limit: int = 100) -> list[User]:
return session.exec(statement).all()


def get_users_with_skip_and_limit(session: Session, skip: int, limit: int) -> list[User]:
return session.exec(select(User).offset(skip).limit(limit)).all()


def check_analyses_objects(
session: Session, analyses: list[Analysis], analysis_type: TYPES
) -> None:
Expand All @@ -185,3 +190,11 @@ def check_analyses_objects(
)
if db_analysis:
session.delete(db_analysis)


def get_snps(session) -> list[SNP]:
return session.exec(select(SNP)).all()


def get_snps_by_limit_and_skip(session: Session, skip: int, limit: int) -> list[SNP]:
return session.exec(select(SNP).offset(skip).limit(limit)).all()
13 changes: 11 additions & 2 deletions genotype_api/database/crud/update.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import types

from pydantic import EmailStr
from sqlmodel import Session

from genotype_api.constants import TYPES
from genotype_api.database.crud.read import get_sample
from genotype_api.database.filter_models.plate_models import PlateSignOff
from genotype_api.database.filter_models.sample_models import SampleSexesUpdate
from genotype_api.database.models import Sample, Plate
from genotype_api.database.models import Sample, Plate, User
from sqlmodel.sql.expression import Select, SelectOfScalar

from genotype_api.service.match_genotype_service.match_genotype import MatchGenotypeService
from genotype_api.services.match_genotype_service.match_genotype import MatchGenotypeService

SelectOfScalar.inherit_cache = True
Select.inherit_cache = True
Expand Down Expand Up @@ -74,3 +75,11 @@ def update_sample_sex(session: Session, sexes_update: SampleSexesUpdate) -> Samp
session.refresh(sample)
sample: Sample = refresh_sample_status(session=session, sample=sample)
return sample


def update_user_email(session: Session, user: User, email: EmailStr) -> User:
user.email = email
session.add(user)
session.commit()
session.refresh(user)
return user
2 changes: 1 addition & 1 deletion genotype_api/dto/dto.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import genotype_api.database.models
from genotype_api.database import models
from genotype_api.models import SampleDetail, PlateStatusCounts
from genotype_api.service.match_genotype_service.utils import check_snps, check_sex
from genotype_api.services.match_genotype_service.utils import check_snps, check_sex


class GenotypeRead(models.GenotypeBase):
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
"""Module for the match genotype service."""
"""Module for the match genotype services."""

from collections import Counter

from genotype_api.database.models import Analysis, Sample
from genotype_api.models import MatchResult, MatchCounts, SampleDetail
from genotype_api.service.match_genotype_service.utils import (
from genotype_api.services.match_genotype_service.utils import (
compare_genotypes,
check_snps,
check_sex,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Utils functions for the match genotype service."""
"""Utils functions for the match genotype services."""

from collections import Counter

Expand Down
21 changes: 21 additions & 0 deletions genotype_api/services/snp_reader/snp_reader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
"""This module holds the SNP reader server."""

from fastapi.datastructures import UploadFile

from genotype_api.database.models import SNP

SNP_HEADER = ["id", "ref", "chrom", "pos"]


class SNPReaderService:
@staticmethod
def read_snps_from_file(snps_file: UploadFile) -> list[SNP]:
snps: list[SNP] = []
content = snps_file.read()
header = SNP_HEADER
for line in content.decode().split("\n"):
if len(line) <= 10:
continue
snp = SNP(**dict(zip(header, line.split())))
snps.append(snp)
return snps

0 comments on commit a45dabe

Please sign in to comment.