Skip to content

Commit 23d9bc4

Browse files
Merge pull request #36 from NFDI4Chem/development
Development
2 parents ced1c62 + 41f50b7 commit 23d9bc4

File tree

6 files changed

+1316
-159
lines changed

6 files changed

+1316
-159
lines changed

app/main.py

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
1-
from fastapi import FastAPI
1+
import os
2+
from fastapi import FastAPI, status
23
from fastapi.responses import RedirectResponse
34
from fastapi_versioning import VersionedFastAPI
45

6+
from .routers import registration
57
from .routers import chem
68
from fastapi.middleware.cors import CORSMiddleware
79

810
from app.core import config, tasks
911

1012
from prometheus_fastapi_instrumentator import Instrumentator
13+
from app.schemas import HealthCheck
1114

1215
app = FastAPI(
1316
title=config.PROJECT_NAME,
@@ -24,16 +27,7 @@
2427
},
2528
)
2629

27-
origins = ["*"]
28-
29-
app.add_middleware(
30-
CORSMiddleware,
31-
allow_origins=origins,
32-
allow_credentials=True,
33-
allow_methods=["*"],
34-
allow_headers=["*"],
35-
)
36-
30+
app.include_router(registration.router)
3731
app.include_router(chem.router)
3832

3933
app.add_event_handler("startup", tasks.create_start_app_handler(app))
@@ -58,7 +52,49 @@
5852

5953
Instrumentator().instrument(app).expose(app)
6054

55+
origins = ["*"]
56+
57+
58+
@app.middleware("http")
59+
async def add_cors_headers(request, call_next):
60+
response = await call_next(request)
61+
response.headers["Access-Control-Allow-Origin"] = "*"
62+
response.headers["Access-Control-Allow-Credentials"] = "true"
63+
response.headers["Access-Control-Allow-Methods"] = "GET, POST, PUT, DELETE, OPTIONS"
64+
response.headers["Access-Control-Allow-Headers"] = "Content-Type, Authorization"
65+
return response
66+
67+
68+
app.add_middleware(
69+
CORSMiddleware,
70+
allow_origins=origins,
71+
allow_credentials=True,
72+
allow_methods=["*"],
73+
allow_headers=["*"],
74+
)
75+
6176

6277
@app.get("/", include_in_schema=False)
6378
async def root():
64-
return RedirectResponse(url="https://nfdi4chem.github.io/nmrkit")
79+
return RedirectResponse(url=os.getenv("HOMEPAGE_URL", "/latest/docs"))
80+
81+
82+
@app.get(
83+
"/health",
84+
tags=["healthcheck"],
85+
summary="Perform a Health Check",
86+
response_description="Return HTTP Status Code 200 (OK)",
87+
status_code=status.HTTP_200_OK,
88+
response_model=HealthCheck,
89+
)
90+
def get_health() -> HealthCheck:
91+
"""
92+
## Perform a Health Check
93+
Endpoint to perform a healthcheck on. This endpoint can primarily be used Docker
94+
to ensure a robust container orchestration and management is in place. Other
95+
services which rely on proper functioning of the API service will not deploy if this
96+
endpoint returns any other HTTP status code except 200 (OK).
97+
Returns:
98+
HealthCheck: Returns a JSON response with the health status
99+
"""
100+
return HealthCheck(status="OK")

app/routers/chem.py

Lines changed: 9 additions & 147 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,9 @@
1-
from typing import List, Annotated, Union
2-
from app.core.config import LWREG_CONFIG
1+
from typing import Annotated
32
from psycopg2.errors import UniqueViolation
43
from app.modules.cdkmodules import getCDKHOSECodes
5-
from fastapi import APIRouter, HTTPException, Body, status, Query
4+
from fastapi import APIRouter, HTTPException, status, Query
65
from app.modules.rdkitmodules import getRDKitHOSECodes
7-
from lwreg.utils import (
8-
initdb,
9-
bulk_register,
10-
query,
11-
retrieve,
12-
RegistrationFailureReasons,
13-
)
14-
from app import schemas
15-
from rdkit import Chem
16-
from io import BytesIO
6+
from app.schemas import HealthCheck
177

188
router = APIRouter(
199
prefix="/chem",
@@ -23,160 +13,32 @@
2313
)
2414

2515

16+
@router.get("/", include_in_schema=False)
2617
@router.get(
2718
"/health",
2819
tags=["healthcheck"],
2920
summary="Perform a Health Check on Chem Module",
30-
response_description="Returns HTTP Status Code 200 (OK)",
21+
response_description="Return HTTP Status Code 200 (OK)",
3122
status_code=status.HTTP_200_OK,
32-
response_model=schemas.HealthCheck,
3323
include_in_schema=False,
24+
response_model=HealthCheck,
3425
)
35-
def get_health() -> schemas.HealthCheck:
26+
def get_health() -> HealthCheck:
3627
"""
3728
## Perform a Health Check
3829
Endpoint to perform a healthcheck on. This endpoint can primarily be used Docker
3930
to ensure a robust container orchestration and management is in place. Other
4031
services which rely on proper functioning of the API service will not deploy if this
4132
endpoint returns any other HTTP status code except 200 (OK).
42-
4333
Returns:
4434
HealthCheck: Returns a JSON response with the health status
4535
"""
46-
return schemas.HealthCheck(status="OK")
47-
48-
49-
@router.post(
50-
"/init",
51-
tags=["chem"],
52-
summary="Initializes the registration database",
53-
response_description="Returns boolean indicating the success of the initialisation",
54-
status_code=status.HTTP_200_OK,
55-
response_model=Union[bool, None],
56-
)
57-
async def initialise_database(confirm: Annotated[bool, Body(embed=True)] = False):
58-
"""
59-
## Initializes the registration database
60-
61-
NOTE: This call destroys any existing information in the registration database
62-
63-
Arguments:
64-
65-
confirm -- if set to False we immediately return
66-
"""
67-
return initdb(config=LWREG_CONFIG, confirm=confirm)
68-
69-
70-
@router.post(
71-
"/register",
72-
tags=["chem"],
73-
summary="Registers new molecules",
74-
response_description="Returns the new registry number(s) (molregno). If all entries are duplicates exception is raised",
75-
status_code=status.HTTP_200_OK,
76-
response_model=List[str | int],
77-
)
78-
async def register_compounds(
79-
data: Annotated[
80-
str,
81-
Body(embed=False, media_type="text/plain"),
82-
] = "CCCC"
83-
):
84-
"""
85-
## Registers new molecules, assuming it doesn't already exist,
86-
and returns the new registry number(s) (molregno). If all entries
87-
are duplicates exception is raised
88-
89-
#### Only one of the molecule format objects should be provided
90-
91-
molblock -- MOL or SDF block
92-
smiles -- smiles
93-
"""
94-
try:
95-
if "$$$$" in data:
96-
molStream = BytesIO(data.encode("utf8"))
97-
mols = [m for m in Chem.ForwardSDMolSupplier(molStream)]
98-
else:
99-
smiles = data.splitlines()
100-
mols = [Chem.MolFromSmiles(smi) for smi in smiles]
101-
if len(mols) > 0:
102-
db_responses = bulk_register(mols=mols, config=LWREG_CONFIG)
103-
reg_responses = []
104-
ops_total_failure = True
105-
for res in db_responses:
106-
if res == RegistrationFailureReasons.PARSE_FAILURE:
107-
reg_responses.append("PARSE_FAILURE")
108-
elif res == RegistrationFailureReasons.DUPLICATE:
109-
reg_responses.append("DUPLICATE")
110-
else:
111-
ops_total_failure = False
112-
reg_responses.append(res)
113-
if ops_total_failure:
114-
raise
115-
else:
116-
return reg_responses
117-
else:
118-
raise
119-
except Exception as e:
120-
raise HTTPException(
121-
status_code=422,
122-
detail="Registration failed: ALL_DUPLICATE_ENTRIES " + e.message,
123-
)
124-
125-
126-
@router.get(
127-
"/query",
128-
tags=["chem"],
129-
summary="Queries to see if a molecule has already been registered",
130-
response_model=List[int],
131-
response_description="Returns the corresponding registry numbers (molregnos)",
132-
status_code=status.HTTP_200_OK,
133-
)
134-
async def query_compounds(smi: str):
135-
"""
136-
## Queries to see if a molecule has already been registered
137-
138-
Returns:
139-
Corresponding registry numbers (molregnos)
140-
"""
141-
try:
142-
res = query(smiles=smi, config=LWREG_CONFIG)
143-
return res
144-
except Exception as e:
145-
raise HTTPException(
146-
status_code=500,
147-
detail="Internal Server Error" + e.message,
148-
)
149-
150-
151-
@router.post(
152-
"/retrieve",
153-
tags=["chem"],
154-
summary="Retrieves entries based on the list of ids provided",
155-
response_model=tuple(),
156-
response_description="Returns HTTP Status Code 200 (OK)",
157-
status_code=status.HTTP_200_OK,
158-
)
159-
async def retrieve_compounds(ids: List[int]):
160-
"""
161-
## Retrieves entries based on the ids provided
162-
163-
Returns:
164-
Molecule data for one or more registry ids (molregnos).
165-
The return value is a tuple of (molregno, data, format) 3-tuples
166-
"""
167-
try:
168-
res = retrieve(ids=ids, config=LWREG_CONFIG)
169-
return res
170-
except Exception as e:
171-
raise HTTPException(
172-
status_code=500,
173-
detail="Internal Server Error" + e.message,
174-
)
36+
return HealthCheck(status="OK")
17537

17638

17739
@router.get(
17840
"/hosecode",
179-
tags=["chem"],
41+
tags=["registration"],
18042
summary="Generates HOSE codes of molecule",
18143
response_model=list[str],
18244
response_description="Returns an array of hose codes generated",

0 commit comments

Comments
 (0)