Skip to content

Commit

Permalink
fix: post stats endpoint error
Browse files Browse the repository at this point in the history
refactor: added black formatter and bring back linting
  • Loading branch information
leehanchung committed Apr 30, 2020
1 parent d43c911 commit 7e27e87
Show file tree
Hide file tree
Showing 15 changed files with 207 additions and 346 deletions.
7 changes: 4 additions & 3 deletions .github/workflows/pythonapp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ jobs:
pip install pipenv
python -m pipenv install --dev --system
#===============================================#
# - name: STEP 4. Lint with pylint
# run: |
# pipenv run pylint --rcfile=.pylintrc api
- name: STEP 4. Lint with pylint
run: |
pipenv run black --line-length=80 api
pipenv run pylint --rcfile=.pylintrc api
#===============================================#
- name: STEP 5. Test with pytest
env:
Expand Down
9 changes: 4 additions & 5 deletions api/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
from api.config import DataReadingError, DataValidationError



_logger = get_logger(logger_name=__name__)


Expand Down Expand Up @@ -40,10 +39,10 @@ def create_app() -> FastAPI:
allow_headers=["*"],
)

app.add_exception_handler(DataReadingError,
data_reading_exception_handler)
app.add_exception_handler(DataValidationError,
data_validation_exception_handler)
app.add_exception_handler(DataReadingError, data_reading_exception_handler)
app.add_exception_handler(
DataValidationError, data_validation_exception_handler
)

_logger.info("FastAPI instance created")

Expand Down
23 changes: 14 additions & 9 deletions api/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ def get_logger(*, logger_name):
class DataReadingError(Exception):
"""DataReadingError exception used for sanity checking.
"""

def __init__(self, *args):
super(DataReadingError, self).__init__(*args)
if args:
Expand All @@ -74,6 +75,7 @@ def __str__(self):
class DataValidationError(Exception):
"""DataValidationError exception used for sanity checking.
"""

def __init__(self, *args):
super(DataValidationError, self).__init__(*args)
if args:
Expand All @@ -95,6 +97,7 @@ class Config:
"""
Base config for Staging API
"""

DEBUG = False
TESTING = False
CSRF_ENABLED = True
Expand All @@ -108,13 +111,17 @@ class Config:
COLLECTION_TWITTER = "twitter"

# JHU CSSE Daily Reports
BASE_URL = "https://raw.githubusercontent.com/CSSEGISandData/COVID-19/" \
"master/csse_covid_19_data/csse_covid_19_daily_reports/"
BASE_URL = (
"https://raw.githubusercontent.com/CSSEGISandData/COVID-19/"
"master/csse_covid_19_data/csse_covid_19_daily_reports/"
)

# JHU CSSE time series reports
TIME_URL = "https://raw.githubusercontent.com/CSSEGISandData/COVID-19/" \
"master/csse_covid_19_data/csse_covid_19_time_series/" \
"time_series_19-covid-Confirmed.csv"
TIME_URL = (
"https://raw.githubusercontent.com/CSSEGISandData/COVID-19/"
"master/csse_covid_19_data/csse_covid_19_time_series/"
"time_series_19-covid-Confirmed.csv"
)

# NEWS API
NEWS_API_KEY = config("NEWS_API_KEY")
Expand All @@ -124,7 +131,7 @@ class Config:

# CVTRACK
CVTRACK_URL = "https://covidtracking.com/api/us/daily"
CVTRACK_STATES_URL = "https://covidtracking.com/api/states"
CVTRACK_STATES_URL = "https://covidtracking.com/api/v1/states/daily.json"

TMP_URL = "https://coronavirus-19-api.herokuapp.com/countries/USA"

Expand All @@ -136,7 +143,6 @@ class Config:

DB_NAME = "covid"


INFO = dict(
{
"title": "ncov19.us API",
Expand All @@ -145,7 +151,7 @@ class Config:
"URL: https://github.com/ncov19-us/back-end | "
"[GNU GENERAL PUBLIC LICENSE]"
"(https://github.com/ncov19-us/back-end/blob/master/LICENSE)"
),
),
}
)

Expand All @@ -164,7 +170,6 @@ class DevelopmentConfig(Config):
DB_NAME = "covid-staging"



def get_config():
"""Set default config to ProductionConfig unless STAGING environment
is set to false on Linux `export STAGING=False` or Windows Powershell
Expand Down
88 changes: 43 additions & 45 deletions api/endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,10 @@
router = APIRouter()
_logger = get_logger(logger_name=__name__)
tm = TwitterMongo(
app_config.DB_NAME,
app_config.COLLECTION_TWITTER,
verbose=False,
app_config.DB_NAME, app_config.COLLECTION_TWITTER, verbose=False,
)



###############################################################################
#
# Root Endpoint
Expand Down Expand Up @@ -83,9 +80,7 @@ class NewsOut(BaseModel):


@router.get(
"/news",
response_model=NewsOut,
responses={404: {"model": Message}},
"/news", response_model=NewsOut, responses={404: {"model": Message}},
)
async def get_gnews() -> JSONResponse:
"""Fetch US news from Google News API and return the results in JSON
Expand All @@ -98,17 +93,14 @@ async def get_gnews() -> JSONResponse:
except DataReadingError as ex:
_logger.warning(f"Endpoint: /news --- GET --- {ex}")
return JSONResponse(
status_code=404,
content={"message": f"[Error] get /News API: {ex}"}
status_code=404, content={"message": f"[Error] get /News API: {ex}"}
)

return json_data


@router.post(
"/news",
response_model=NewsOut,
responses={404: {"model": Message}},
"/news", response_model=NewsOut, responses={404: {"model": Message}},
)
async def post_gnews(news: NewsInput) -> JSONResponse:
"""Fetch specific state and topic news from Google News API and return the
Expand All @@ -123,7 +115,8 @@ async def post_gnews(news: NewsInput) -> JSONResponse:
except DataReadingError as ex:
_logger.warning(f"Endpoint: /news --- POST --- {ex}")
return JSONResponse(
status_code=404, content={"message": f"[Error] post /News API: {ex}"}
status_code=404,
content={"message": f"[Error] post /News API: {ex}"},
)

return json_data
Expand Down Expand Up @@ -158,7 +151,7 @@ class TwitterOutput(BaseModel):
@router.get(
"/twitter",
response_model=TwitterOutput,
responses={404: {"model": Message}}
responses={404: {"model": Message}},
)
async def get_twitter() -> JSONResponse:
"""Fetch and return Twitter data from MongoDB connection."""
Expand All @@ -184,15 +177,17 @@ async def get_twitter() -> JSONResponse:
gc.collect()
except Exception as ex:
_logger.warning(f"Endpoint: /twitter --- GET --- {ex}")
raise HTTPException(status_code=404, detail=f"[Error] get /twitter API: {ex}")
raise HTTPException(
status_code=404, detail=f"[Error] get /twitter API: {ex}"
)

return json_data


@router.post(
"/twitter",
response_model=TwitterOutput,
responses={404: {"model": Message}}
responses={404: {"model": Message}},
)
async def post_twitter(twyuser: TwitterInput) -> JSONResponse:
"""Fetch and return Twitter data from MongoDB connection."""
Expand All @@ -216,7 +211,9 @@ async def post_twitter(twyuser: TwitterInput) -> JSONResponse:
gc.collect()
except Exception as ex:
_logger.warning(f"Endpoint: /twitter --- POST --- {ex}")
raise HTTPException(status_code=404, detail=f"[Error] post /twitter API: {ex}")
raise HTTPException(
status_code=404, detail=f"[Error] post /twitter API: {ex}"
)

return json_data

Expand Down Expand Up @@ -251,9 +248,7 @@ class CountyOut(BaseModel):

@cached(cache=TTLCache(maxsize=1, ttl=3600))
@router.get(
"/county",
response_model=CountyOut,
responses={404: {"model": Message}}
"/county", response_model=CountyOut, responses={404: {"model": Message}}
)
async def get_county_data() -> JSONResponse:
"""Get all US county data and return it as a big fat json string. Respond
Expand All @@ -268,15 +263,13 @@ async def get_county_data() -> JSONResponse:
except Exception as ex:
_logger.warning(f"Endpoint: /county --- GET --- {ex}")
raise HTTPException(
status_code=404,
detail=f"[Error] get '/county' API: {ex}")
status_code=404, detail=f"[Error] get '/county' API: {ex}"
)
return json_data


@router.post(
"/county",
response_model=CountyOut,
responses={404: {"model": Message}}
"/county", response_model=CountyOut, responses={404: {"model": Message}}
)
def post_county(county: CountyInput) -> JSONResponse:
"""Get all US county data and return it as a big fat json string. Respond
Expand All @@ -289,7 +282,9 @@ def post_county(county: CountyInput) -> JSONResponse:
gc.collect()
except Exception as ex:
_logger.warning(f"Endpoint: /county --- POST --- {ex}")
raise HTTPException(status_code=404, detail=f"[Error] get '/county' API: {ex}")
raise HTTPException(
status_code=404, detail=f"[Error] get '/county' API: {ex}"
)

return json_data

Expand All @@ -316,9 +311,7 @@ class StateOutput(BaseModel):

@cached(cache=TTLCache(maxsize=3, ttl=3600))
@router.post(
"/state",
response_model=StateOutput,
responses={404: {"model": Message}}
"/state", response_model=StateOutput, responses={404: {"model": Message}}
)
async def post_state(state: StateInput) -> JSONResponse:
"""Fetch state level data time series for a single state, ignoring the
Expand All @@ -333,7 +326,9 @@ async def post_state(state: StateInput) -> JSONResponse:
gc.collect()
except Exception as ex:
_logger.warning(f"Endpoint: /state --- POST --- {ex}")
raise HTTPException(status_code=404, detail=f"[Error] get /country API: {ex}")
raise HTTPException(
status_code=404, detail=f"[Error] get /country API: {ex}"
)

return json_data

Expand Down Expand Up @@ -374,7 +369,9 @@ async def get_country(country: CountryInput) -> JSONResponse:
json_data = {"success": True, "message": data}
except Exception as ex:
_logger.warning(f"Endpoint: /country --- GET --- {ex}")
raise HTTPException(status_code=404, detail=f"[Error] get /country API: {ex}")
raise HTTPException(
status_code=404, detail=f"[Error] get /country API: {ex}"
)

return json_data

Expand Down Expand Up @@ -403,9 +400,7 @@ class StatsOutput(BaseModel):


@router.get(
"/stats",
response_model=StatsOutput,
responses={404: {"model": Message}}
"/stats", response_model=StatsOutput, responses={404: {"model": Message}}
)
async def get_stats() -> JSONResponse:
"""Get overall tested, confirmed, and deaths stats from the database
Expand All @@ -416,14 +411,14 @@ async def get_stats() -> JSONResponse:
json_data = {"success": True, "message": data}
except Exception as ex:
_logger.warning(f"Endpoint: /stats --- GET --- {ex}")
raise HTTPException(status_code=404, detail=f"[Error] get /stats API: {ex}")
raise HTTPException(
status_code=404, detail=f"[Error] get /stats API: {ex}"
)
return json_data


@router.post(
"/stats",
response_model=StatsOutput,
responses={404: {"model": Message}}
"/stats", response_model=StatsOutput, responses={404: {"model": Message}}
)
async def post_stats(stats: StatsInput) -> JSONResponse:
"""Get overall tested, confirmed, and deaths stats from the database
Expand All @@ -434,7 +429,9 @@ async def post_stats(stats: StatsInput) -> JSONResponse:
json_data = {"success": True, "message": data}
except Exception as ex:
_logger.warning(f"Endpoint: /stats --- POST --- {ex}")
raise HTTPException(status_code=404, detail=f"[Error] post /stats API: {ex}")
raise HTTPException(
status_code=404, detail=f"[Error] post /stats API: {ex}"
)
return json_data


Expand Down Expand Up @@ -466,9 +463,7 @@ class ZIPOutput(BaseModel):


@router.post(
"/zip",
response_model=ZIPOutput,
responses={404: {"model": Message}}
"/zip", response_model=ZIPOutput, responses={404: {"model": Message}}
)
def post_zip(zip_code: ZIPInput) -> JSONResponse:
"""Returns county stats for the zip code input.
Expand All @@ -477,8 +472,9 @@ def post_zip(zip_code: ZIPInput) -> JSONResponse:
try:
zip_info = zipcodes.matching(zip_code.zip_code)[0]
except Exception as ex:
message = (f"ZIP code {zip_code.zip_code}"
" not found in US Zipcode database.")
message = (
f"ZIP code {zip_code.zip_code}" " not found in US Zipcode database."
)
_logger.warning(f"Endpoint: /zip --- POST --- {ex} {message}")
raise HTTPException(
status_code=422, detail=f"[Error] POST '/zip' {ex} {message}"
Expand Down Expand Up @@ -506,6 +502,8 @@ def post_zip(zip_code: ZIPInput) -> JSONResponse:
gc.collect()
except Exception as ex:
_logger.warning(f"Endpoint: /zip --- POST --- {ex}")
raise HTTPException(status_code=404, detail=f"[Error] get '/zip' API: {ex}")
raise HTTPException(
status_code=404, detail=f"[Error] get '/zip' API: {ex}"
)

return json_data
10 changes: 4 additions & 6 deletions api/exception_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@


async def data_reading_exception_handler(
request: Request,
exc: DataReadingError,
) -> JSONResponse:
request: Request, exc: DataReadingError,
) -> JSONResponse:

return JSONResponse(
status_code=422,
Expand All @@ -16,9 +15,8 @@ async def data_reading_exception_handler(


async def data_validation_exception_handler(
request: Request,
exc: DataValidationError,
) -> JSONResponse:
request: Request, exc: DataValidationError,
) -> JSONResponse:
# this will hang, so just print out method directly for info
# body = await request.body()
return JSONResponse(
Expand Down
2 changes: 1 addition & 1 deletion api/tests/test_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ def test_app_headers(test_app=app):
"[GNU GENERAL PUBLIC LICENSE]"
"(https://github.com/ncov19-us/back-end/blob/master/LICENSE)"
)
assert version == f'{api.__version__}'
assert version == f"{api.__version__}"
Loading

0 comments on commit 7e27e87

Please sign in to comment.