Skip to content

Commit

Permalink
Merge pull request #3 from TranslatorSRI/stub
Browse files Browse the repository at this point in the history
Stub part 2
  • Loading branch information
maximusunc authored Jun 30, 2023
2 parents bf4ab6b + dac64b5 commit adf4459
Show file tree
Hide file tree
Showing 7 changed files with 152 additions and 99 deletions.
46 changes: 46 additions & 0 deletions .github/workflows/dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: 'Pull Request Feedback'

on:
pull_request:

jobs:
test:
name: Run pytest
runs-on: ubuntu-latest
steps:
- name: Checkout the repository
uses: actions/checkout@v2

# Cache docker layers for faster build
- uses: satackey/[email protected]
# Ignore the failure of a step and avoid terminating the job.
continue-on-error: true

- name: Build
run: docker build -t appraiser-testing -f Dockerfile.test .

- name: Run tests and get output
run: |
echo 'TEST_OUTPUT<<EOF' >> $GITHUB_ENV
echo "$(docker run appraiser-testing)" >> $GITHUB_ENV
echo 'EOF' >> $GITHUB_ENV
- name: Exit if there are any test failures
run: '[[ $TEST_OUTPUT != *FAILED* ]]'

verify-lock:
name: Verify lockfiles are up to date
runs-on: ubuntu-latest
steps:
- name: Checkout the repository
uses: actions/checkout@v2

- name: Verify lockfiles
run: python manage.py verify_locked

check-format:
name: Check that code matches Black formatter
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: psf/black@stable
21 changes: 21 additions & 0 deletions Dockerfile.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
FROM renciorg/renci-python-image:v0.0.1

# Add image info
LABEL org.opencontainers.image.source /github.com/TranslatorSRI/answer-appraiser

# set up requirements
WORKDIR /app

# Normal requirements
ADD requirements-lock.txt .
RUN pip install -r requirements-lock.txt

# Test requirements
ADD requirements-test-lock.txt .
RUN pip install -r requirements-test-lock.txt

# Copy in files
ADD . .

# set up default command
CMD pytest
8 changes: 5 additions & 3 deletions app/ordering_components.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,17 @@ def get_clinical_evidence(result, message, logger):
# TODO Calculate clinical evidence
return 0


def get_novelty(result, message, logger):
# TODO get novelty from novelty package
return 0



def get_ordering_components(message, logger):
logger.debug(f"Computing scores for {len(message['results'])} results")
for result in message.get("results") or []:
result["ordering_components"] = {
"confidence": get_confidence(result, message, logger),
"clinical_evidence": get_clinical_evidence(result, message, logger),
"novelty": get_novelty(result, message, logger)
}
"novelty": get_novelty(result, message, logger),
}
165 changes: 74 additions & 91 deletions app/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,7 @@
from starlette.middleware.cors import CORSMiddleware
from uuid import uuid4

from reasoner_pydantic import (
AsyncQuery,
AsyncQueryResponse,
Response,
Query
)
from reasoner_pydantic import AsyncQuery, AsyncQueryResponse, Response, Query

from .logger import setup_logger, get_logger
from .trapi import TRAPI
Expand Down Expand Up @@ -58,83 +53,64 @@

APP.add_middleware(
CORSMiddleware,
allow_origins=['*'],
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)

EXAMPLE = {
"message": {
"query_graph": {
"nodes": {
"n0": {"ids": ["MESH:D008687"]},
"n1": {"categories": ["biolink:Disease"]}
},
"edges": {
"n0n1": {
"subject": "n0",
"object": "n1",
"predicates": ["biolink:treats"]
}
}
},
"knowledge_graph": {
"nodes": {
"MESH:D008687": {
"categories": ["biolink:SmallMolecule"],
"name": "Metformin"
},
"MONDO:0005148": {
"categories": [
"biolink:Disease"
],
"name": "type 2 diabetes mellitus"
}
},
"edges": {
"n0n1": {
"subject": "MESH:D008687",
"object": "MONDO:0005148",
"predicate": "biolink:treats",
"sources": [
{
"resource_id": "infores:kp0",
"resource_role": "primary_knowledge_source"
}
]
}
}
},
"results": [
{
"node_bindings": {
"n0": [
{
"id": "MESH:D008687"
}
],
"n1": [
{
"id": "MONDO:0005148"
}
]
},
"analyses": [
{
"resource_id": "kp0",
"edge_bindings": {
"n0n1": [
{
"id": "n0n1"
}
]
}
}
]
}
]
}
"message": {
"query_graph": {
"nodes": {
"n0": {"ids": ["MESH:D008687"]},
"n1": {"categories": ["biolink:Disease"]},
},
"edges": {
"n0n1": {
"subject": "n0",
"object": "n1",
"predicates": ["biolink:treats"],
}
},
},
"knowledge_graph": {
"nodes": {
"MESH:D008687": {
"categories": ["biolink:SmallMolecule"],
"name": "Metformin",
},
"MONDO:0005148": {
"categories": ["biolink:Disease"],
"name": "type 2 diabetes mellitus",
},
},
"edges": {
"n0n1": {
"subject": "MESH:D008687",
"object": "MONDO:0005148",
"predicate": "biolink:treats",
"sources": [
{
"resource_id": "infores:kp0",
"resource_role": "primary_knowledge_source",
}
],
}
},
},
"results": [
{
"node_bindings": {
"n0": [{"id": "MESH:D008687"}],
"n1": [{"id": "MONDO:0005148"}],
},
"analyses": [
{"resource_id": "kp0", "edge_bindings": {"n0n1": [{"id": "n0n1"}]}}
],
}
],
}
}

ASYNC_EXAMPLE = {
Expand All @@ -148,18 +124,19 @@ async def async_appraise(message, callback, logger: logging.Logger):
get_ordering_components(message, logger)
except Exception:
logger.error(f"Something went wrong while appraising: {traceback.format_exc()}")
try:
try:
logger.info(f"Posting to callback {callback}")
async with httpx.AsyncClient(timeout=httpx.Timeout(timeout=600.0)) as client:
res = await client.post(callback, json=message)
logger.info(f"Posted to {callback} with code {res.status_code}")
except Exception as e:
logger.error(f"Unable to post to callback {callback}.")


@APP.post("/async_get_appraisal", response_model=AsyncQueryResponse)
async def get_appraisal(
background_tasks: BackgroundTasks,
query: AsyncQuery = Body(..., example=ASYNC_EXAMPLE)
query: AsyncQuery = Body(..., example=ASYNC_EXAMPLE),
):
"""Appraise Answers"""
qid = str(uuid4())[:8]
Expand All @@ -169,28 +146,34 @@ async def get_appraisal(
message = query_dict["message"]
if not message.get("results"):
logger.warning("No results given.")
return JSONResponse(content={"status": "Rejected",
"description": "No Results.",
"job_id": qid}, status_code=400)
return JSONResponse(
content={"status": "Rejected", "description": "No Results.", "job_id": qid},
status_code=400,
)
callback = query_dict["callback"]
background_tasks.add_task(async_appraise, message, callback, logger)
return JSONResponse(content={"status": "Accepted",
"description": f"Appraising answers. Will send response to {callback}",
"job_id": qid}, status_code=200)
return JSONResponse(
content={
"status": "Accepted",
"description": f"Appraising answers. Will send response to {callback}",
"job_id": qid,
},
status_code=200,
)


@APP.post("/get_appraisal", response_model=Response)
async def sync_get_appraisal(
query: Query = Body(..., example=EXAMPLE)
):
async def sync_get_appraisal(query: Query = Body(..., example=EXAMPLE)):
qid = str(uuid4())[:8]
query_dict = query.dict()
log_level = query_dict.get("log_level") or "WARNING"
logger = get_logger(qid, log_level)
message = query_dict["message"]
if not message.get("results"):
return JSONResponse(content={"status": "Rejected",
"description": "No Results.",
"job_id": qid}, status_code=400)
return JSONResponse(
content={"status": "Rejected", "description": "No Results.", "job_id": qid},
status_code=400,
)
try:
get_ordering_components(message, logger)
except Exception:
Expand Down
4 changes: 2 additions & 2 deletions app/trapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,10 @@ def openapi(self) -> Dict[str, Any]:
"externalDocs": {
"description": "The values for version are restricted according to the regex in this external JSON schema. See schema and examples at url",
"url": "https://github.com/NCATSTranslator/translator_extensions/blob/production/x-trapi/",
}
},
}
openapi_schema["info"]["contact"] = self.contact
openapi_schema["info"]["termsOfService"] = self.terms_of_service

self.openapi_schema = openapi_schema
return self.openapi_schema
return self.openapi_schema
4 changes: 2 additions & 2 deletions manage.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ def test(extra_args):
and then exits.
"""
command = """\
docker build -t workflow-runner-testing -f Dockerfile.test .
docker run -it workflow-runner-testing\
docker build -t appraiser-testing -f Dockerfile.test .
docker run -it appraiser-testing\
"""
run_command(command + extra_args)

Expand Down
3 changes: 2 additions & 1 deletion tests/test_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@

testclient = TestClient(APP)


def test_sync_get_appraisal_400():
"""Test calling /query endpoint."""
response = testclient.post(
"/sync_get_appraisal",
json={"message": {}},
)
response_json = response.json()
assert response_json["status"] == "Rejected"
assert response_json["status"] == "Rejected"

0 comments on commit adf4459

Please sign in to comment.