Skip to content

Commit

Permalink
optimize annotation data to client
Browse files Browse the repository at this point in the history
  • Loading branch information
nleroy917 committed Dec 4, 2023
1 parent 860be2c commit dbf50a5
Show file tree
Hide file tree
Showing 13 changed files with 111 additions and 45 deletions.
2 changes: 1 addition & 1 deletion pephub/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
from platform import python_version
from fastapi import __version__ as fastapi_version
from pepdbagent import __version__ as pepdbagent_version
from pepdbagent.const import DEFAULT_TAG

from secrets import token_hex

Expand Down Expand Up @@ -131,3 +130,4 @@
CALLBACK_ENDPOINT = "/auth/callback"

DEFAULT_PEP_SCHEMA = "pep/2.1.0"
DEFAULT_TAG = "default"
8 changes: 4 additions & 4 deletions pephub/dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from typing import Union, List, Optional, Dict, Any
from datetime import datetime, timedelta

from fastapi import Depends, Header, Form
from fastapi import Depends, Header
from fastapi.exceptions import HTTPException
from fastapi.security import HTTPBearer
from pydantic import BaseModel
Expand All @@ -23,7 +23,7 @@
from qdrant_client.http.exceptions import ResponseHandlingException
from sentence_transformers import SentenceTransformer

from .routers.models import AnnotationModel, NamespaceList, Namespace, ForkRequest
from .routers.models import AnnotationModel, Namespace, ForkRequest
from .const import (
DEFAULT_POSTGRES_HOST,
DEFAULT_POSTGRES_PASSWORD,
Expand Down Expand Up @@ -314,13 +314,13 @@ def verify_user_can_write_project(
if session_info is None:
raise HTTPException(
401,
f"Please authenticate before editing project.",
"Please authenticate before editing project.",
)
# AUTHORIZATION REQUIRED
if session_info["login"] != namespace and namespace not in orgs:
raise HTTPException(
403,
f"The current authenticated user does not have permission to edit this project.",
"The current authenticated user does not have permission to edit this project.",
)


Expand Down
11 changes: 3 additions & 8 deletions pephub/main.py
Original file line number Diff line number Diff line change
@@ -1,38 +1,33 @@
import logging
import sys
import uvicorn
import coloredlogs

from fastapi import FastAPI
from fastapi.middleware import Middleware
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles

from ._version import __version__ as server_v
from .const import PKG_NAME, TAGS_METADATA, SPA_PATH
from .helpers import build_parser
from .routers.api.v1.base import api as api_base
from .routers.api.v1.namespace import namespace as api_namespace
from .routers.api.v1.project import project as api_project
from .routers.api.v1.user import user as api_user
from .routers.api.v1.search import search as api_search
from .routers.auth.base import auth as auth_router
from .routers.eido.eido import router as eido_router
from .middleware import SPA, EnvironmentMiddleware
from .const import LOG_LEVEL_MAP
from .middleware import SPA

_LOGGER_PEPDBAGENT = logging.getLogger("pepdbagent")
coloredlogs.install(
logger=_LOGGER_PEPDBAGENT,
level=logging.WARNING,
level=logging.INFO,
datefmt="%b %d %Y %H:%M:%S",
fmt="[%(levelname)s] [%(asctime)s] [PEPDBAGENT] %(message)s",
)

_LOGGER_PEPPY = logging.getLogger("peppy")
coloredlogs.install(
logger=_LOGGER_PEPPY,
level=logging.WARNING,
level=logging.INFO,
datefmt="%b %d %Y %H:%M:%S",
fmt="[%(levelname)s] [%(asctime)s] [PEPPY] %(message)s",
)
Expand Down
1 change: 0 additions & 1 deletion pephub/routers/api/v1/base.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from fastapi import APIRouter

from ....dependencies import *
from ....const import ALL_VERSIONS


Expand Down
22 changes: 18 additions & 4 deletions pephub/routers/api/v1/namespace.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,31 @@
import tempfile
import shutil
import json
from typing import List, Optional, Union

from fastapi import APIRouter, File, UploadFile, Request, Depends, Form, Body
import peppy

from fastapi import APIRouter, File, UploadFile, Request, Depends, Form
from fastapi.responses import JSONResponse
from peppy import Project
from peppy.const import DESC_KEY, NAME_KEY
from pepdbagent import PEPDatabaseAgent
from pepdbagent.exceptions import ProjectUniqueNameError
from pepdbagent.const import DEFAULT_LIMIT_INFO
from pepdbagent.models import ListOfNamespaceInfo
from typing import Literal
from typing_extensions import Annotated

from ....dependencies import *
from ...models import Namespace
from ....dependencies import (
get_db,
get_namespace_info,
get_user_from_session_info,
read_authorization_header,
get_organizations_from_session_info,
get_namespace_access_list,
verify_user_can_write_namespace,
)
from ....helpers import parse_user_file_upload, split_upload_files_on_init_file
from ....const import (
DEFAULT_TAG,
Expand Down Expand Up @@ -292,7 +306,7 @@ async def upload_raw_pep(
except Exception as e:
return JSONResponse(
content={
"message": f"Incorrect raw project was provided. Couldn't initiate peppy object.",
"message": "Incorrect raw project was provided. Couldn't initiate peppy object.",
"error": f"{e}",
"status_code": 417,
},
Expand All @@ -313,7 +327,7 @@ async def upload_raw_pep(
return JSONResponse(
content={
"message": f"Project '{namespace}/{p_project.name}:{tag}' already exists in namespace",
"error": f"Set overwrite=True to overwrite or update project",
"error": "Set overwrite=True to overwrite or update project",
"status_code": 409,
},
status_code=409,
Expand Down
30 changes: 20 additions & 10 deletions pephub/routers/api/v1/project.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import eido
import yaml
import pandas as pd
from io import StringIO
from typing import Callable, Literal, Union
from fastapi import APIRouter
import peppy
from typing import Callable, Literal, Union, Optional
from fastapi import APIRouter, Depends
from fastapi.exceptions import HTTPException
from fastapi.responses import JSONResponse, PlainTextResponse
from peppy import Project
from peppy.const import (
Expand All @@ -13,11 +14,20 @@
SUBSAMPLE_RAW_LIST_KEY,
)

from ...models import ProjectOptional, ProjectRawModel
from ...models import ProjectOptional, ProjectRawModel, AnnotationModel, ForkRequest
from ....helpers import zip_conv_result, get_project_sample_names, zip_pep
from ....dependencies import *
from ....dependencies import (
get_db,
get_project,
get_project_annotation,
get_namespace_access_list,
verify_user_can_fork,
verify_user_can_read_project,
DEFAULT_TAG,
)
from ....const import SAMPLE_CONVERSION_FUNCTIONS, VALID_UPDATE_KEYS

from pepdbagent import PEPDatabaseAgent
from pepdbagent.exceptions import ProjectUniqueNameError

from dotenv import load_dotenv
Expand Down Expand Up @@ -51,7 +61,7 @@ async def get_a_pep(
try:
raw_project = ProjectRawModel(**proj)
except Exception:
raise HTTPException(500, f"Unexpected project error!")
raise HTTPException(500, "Unexpected project error!")
return raw_project.dict(by_alias=False)
samples = [s.to_dict() for s in proj.samples]
sample_table_index = proj.sample_table_index
Expand Down Expand Up @@ -160,10 +170,10 @@ async def update_a_pep(
eido.validate_project(
new_project, "http://schema.databio.org/pep/2.1.0.yaml"
)
except Exception as e:
except Exception as _:
raise HTTPException(
status_code=400,
detail=f"",
detail="Could not validate PEP. Please check your PEP and try again.",
)

# if we get through all samples, then update project in the database
Expand Down Expand Up @@ -308,7 +318,7 @@ async def get_pep_samples(


@project.get("/config", summary="Get project configuration file")
async def get_pep_samples(
async def get_pep_config(
proj: Union[peppy.Project, dict] = Depends(get_project),
format: Optional[Literal["JSON", "String"]] = "JSON",
raw: Optional[bool] = False,
Expand Down Expand Up @@ -510,7 +520,7 @@ async def fork_pep_to_namespace(


@project.get("/annotation")
async def get_subsamples(
async def get_project_annotation(
proj_annotation: AnnotationModel = Depends(get_project_annotation),
):
"""
Expand Down
20 changes: 13 additions & 7 deletions pephub/routers/api/v1/search.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
from enum import Enum
from fastapi import APIRouter, __version__ as fastapi_version
from typing import List

from fastapi import APIRouter, Depends
from fastapi.responses import JSONResponse
from peppy import __version__ as peppy_version
from platform import python_version
from pepdbagent import PEPDatabaseAgent

from ...._version import __version__ as pephub_version
from ....dependencies import *
from sentence_transformers import SentenceTransformer
from qdrant_client import QdrantClient

from ....dependencies import (
get_db,
get_qdrant,
get_sentence_transformer,
get_namespace_access_list,
)
from ...models import SearchQuery
from ....const import DEFAULT_QDRANT_COLLECTION_NAME, ALL_VERSIONS
from ....const import DEFAULT_QDRANT_COLLECTION_NAME


from dotenv import load_dotenv
Expand Down
11 changes: 8 additions & 3 deletions pephub/routers/api/v1/user.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
from fastapi import APIRouter, Request
from fastapi import APIRouter, Request, Depends
from fastapi.templating import Jinja2Templates
from fastapi.responses import RedirectResponse, JSONResponse
from platform import python_version

from pepdbagent import PEPDatabaseAgent

from ...._version import __version__ as pephub_version
from ....dependencies import *
from ....dependencies import (
get_db,
read_authorization_header,
)
from ....const import BASE_TEMPLATES_PATH

user = APIRouter(prefix="/api/v1/me", tags=["profile"])
Expand Down Expand Up @@ -36,7 +41,7 @@ def profile_data(


@user.get("/data")
def profile_data(
def profile_data2(
request: Request,
session_info=Depends(read_authorization_header),
agent: PEPDatabaseAgent = Depends(get_db),
Expand Down
8 changes: 5 additions & 3 deletions pephub/routers/eido/eido.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@
import shutil
import yaml

from fastapi import UploadFile, Form, APIRouter
from fastapi import UploadFile, Form, APIRouter, Depends
from fastapi.exceptions import HTTPException
from starlette.requests import Request
from starlette.responses import JSONResponse
from typing import List, Tuple
from typing import List, Tuple, Optional
from pepdbagent import PEPDatabaseAgent
from pepdbagent.utils import registry_path_converter

from ...helpers import parse_user_file_upload, split_upload_files_on_init_file
from ...dependencies import *
from ...dependencies import get_db, DEFAULT_TAG


schemas_url = "https://schema.databio.org/list.json"
Expand Down
2 changes: 1 addition & 1 deletion requirements/requirements-all.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ tqdm
uvicorn
python-dotenv
pepdbagent>=0.6.0
peppy>=0.40.0a4
peppy>=0.40.0a5
qdrant-client
requests
aiofiles
Expand Down
16 changes: 15 additions & 1 deletion web/src/api/project.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import axios from 'axios';

import { Project, ProjectConfigResponse, Sample } from '../../types';
import { Project, ProjectAnnotation, ProjectConfigResponse, Sample } from '../../types';

const API_HOST = import.meta.env.VITE_API_HOST || '';
const API_BASE = `${API_HOST}/api/v1`;
Expand Down Expand Up @@ -43,6 +43,20 @@ export const getProject = (
}
};

export const getProjectAnnotation = (
namespace: string,
projectName: string,
tag: string = 'default',
token: string | null = null,
) => {
const url = `${API_BASE}/projects/${namespace}/${projectName}/annotation?tag=${tag}`;
if (!token) {
return axios.get<ProjectAnnotation>(url).then((res) => res.data);
} else {
return axios.get<ProjectAnnotation>(url, { headers: { Authorization: `Bearer ${token}` } }).then((res) => res.data);
}
};

export const getSampleTable = (
namespace: string,
projectName: string,
Expand Down
17 changes: 17 additions & 0 deletions web/src/hooks/queries/useProjectAnnotation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { useQuery } from '@tanstack/react-query';

import { getProjectAnnotation } from '../../api/project';

export const useProjectAnnotation = (
namespace: string | undefined,
project: string | undefined,
tag: string | undefined,
token: string | null,
) => {
const query = useQuery({
queryKey: [namespace, project, tag, 'annotation'],
queryFn: () => getProjectAnnotation(namespace || '', project || '', tag, token),
enabled: namespace !== undefined || project !== undefined,
});
return query;
};
8 changes: 6 additions & 2 deletions web/src/pages/Project.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { useConfigMutation } from '../hooks/mutations/useConfigMutation';
import { useSampleTableMutation } from '../hooks/mutations/useSampleTableMutation';
import { useSubsampleTableMutation } from '../hooks/mutations/useSubsampleTableMutation';
import { useTotalProjectChangeMutation } from '../hooks/mutations/useTotalProjectChangeMutation';
import { useProject } from '../hooks/queries/useProject';
import { useProjectAnnotation } from '../hooks/queries/useProjectAnnotation';
import { useProjectConfig } from '../hooks/queries/useProjectConfig';
import { useSampleTable } from '../hooks/queries/useSampleTable';
import { useSubsampleTable } from '../hooks/queries/useSubsampleTable';
Expand Down Expand Up @@ -65,7 +65,11 @@ export const ProjectPage: FC = () => {
const fork = searchParams.get('fork');

// fetch data
const { data: projectInfo, isLoading: projectInfoIsLoading, error } = useProject(namespace, project || '', tag, jwt);
const {
data: projectInfo,
isLoading: projectInfoIsLoading,
error,
} = useProjectAnnotation(namespace, project || '', tag, jwt);
const { data: projectSamples } = useSampleTable(namespace, project, tag, jwt);
const { data: projectSubsamples } = useSubsampleTable(namespace, project, tag, jwt);
const { data: projectConfig, isLoading: projectConfigIsLoading } = useProjectConfig(
Expand Down

0 comments on commit dbf50a5

Please sign in to comment.