Skip to content

Commit

Permalink
chore: merge conflict, fix: zip codes for territories, fix: zip code …
Browse files Browse the repository at this point in the history
…error response message (#62)

* refactor: change Aaron to standard feat: adding basic test
- Changed APP to app according to Flask/FastAPI standard
- Changed config_ to _config. trailing space is for python default conflicts not import
- Adding basic tests for endpoints

* test: added test structures
- 	est_app.py: testing �pp.py app title, description, version
- 	est_config.py: tested ProductionConfig, DevelopmentConfig, config loader
- 	est_endpoints.py: tested root test

* test: added test structures
- 	est_app.py: testing �pp.py app title, description, version
- 	est_config.py: tested ProductionConfig, DevelopmentConfig, config loader
- 	est_endpoints.py: tested root test

* tests: add testing for custom error messages

* chore: updated README

* chore: fixed PR template

* chore: updated README

* chore: updated README

* tests: adds test cases for endpoints
- '/' done
- '/news' only testing for 422 and 405, no validation yet
- '/twitter': tested 422, 404, 405, and random data sample validation
- '/county': tested 404, 405, 422. no data return validation yet
- '/state': tested 405, 422.
- '/country': tested 405, 422.
- '/stats': tested 405, 422.

* style: fix for codefactor.
- 	est_config.py: keeping assert == True/False for code readability
- 	est_endpoints.py: keeping TODO as a reminder to fix endpoints.py

* style: changed config_ to �pp_config after technical discussion

* style: chore:
- added .pylintrc
- fixed all files for pylint
- added .github/workflow/pythonapp.yml
- added pipenv, pylint and pytest

* chore:
- streamlining pythonapp.yml
- triggers pythonapp.yml on all push and pull_request

* chore: updated pythonapp.yml

* chore: updated pythonapp.yml

* chore: updated pythonapp.yml, readme.md

* chore: updated pythonapp.yml

* chore: updated pythonapp.yml

* chore: updated pythonapp.yml

* chore: updated pythonapp.yml

* chore: updated pythonapp.yml

* chore: updated pythonapp.yml

* chore: updated pythonapp.yml

* chore: updated pythonapp.yml

* feat: rerouting root endpoint to postman

* feat: rerouting root endpoint to postman

* feat: added redirect to postman, added test

* fix: added uvloop

* feat: adding coverall

* feat: installed coveralls for coverall.io

* feat: installed coveralls for coverall.io

* feat: installed coveralls for coverall.io

* feat: installed coveralls for coverall.io attempt 6

* feat: installed coveralls for coverall.io attempt 8

* feat: installed coveralls for coverall.io attempt 9

* feat: settingup coverall attempt #11

* feat: coverall badge attempt #12

* feat: coverall added, feat: routing root to redoc

* fix: default config logic

* fix: default config logic

* Update LICENSE

* chore: updating README again  🤧 (#46)

* chore: updating READMEs

* chore: updating READMEs

* chore: updating READMEs (#48)

* fix: post county new_death nan error (#50)

* fix: /post county new_death nan error

* fix: /post county new_death nan error

* feat: test: (#52)

* feat: adding zip route

* feat: zip route #1

* feat: removed uszipcode, added zipcodes

* feat:
- feat: added zip endpoint to return county data given zip code
- test: added tests for the zip endpoint
- feat: modified github actions to trigger on push, and on pr to master/staging

* han: attempt to fix codefactor #1

* feat: zip endpoint
- added custom exception handlers
- mal-formed zip codes now return 422 instead of 404
- changed mal-formed zip codes test cases from 404 to 422

* fixed zip endpoint for nyc (#54)

* fix: benton, wa

* fix: github actions

* fix: github actions to pr only

* fix: combined -- counties and retargeted combined counties (#57)

* chore: updating master (#55)

* refactor: change Aaron to standard feat: adding basic test
- Changed APP to app according to Flask/FastAPI standard
- Changed config_ to _config. trailing space is for python default conflicts not import
- Adding basic tests for endpoints

* test: added test structures
- 	est_app.py: testing �pp.py app title, description, version
- 	est_config.py: tested ProductionConfig, DevelopmentConfig, config loader
- 	est_endpoints.py: tested root test

* test: added test structures
- 	est_app.py: testing �pp.py app title, description, version
- 	est_config.py: tested ProductionConfig, DevelopmentConfig, config loader
- 	est_endpoints.py: tested root test

* tests: add testing for custom error messages

* chore: updated README

* chore: fixed PR template

* chore: updated README

* chore: updated README

* tests: adds test cases for endpoints
- '/' done
- '/news' only testing for 422 and 405, no validation yet
- '/twitter': tested 422, 404, 405, and random data sample validation
- '/county': tested 404, 405, 422. no data return validation yet
- '/state': tested 405, 422.
- '/country': tested 405, 422.
- '/stats': tested 405, 422.

* style: fix for codefactor.
- 	est_config.py: keeping assert == True/False for code readability
- 	est_endpoints.py: keeping TODO as a reminder to fix endpoints.py

* style: changed config_ to �pp_config after technical discussion

* style: chore:
- added .pylintrc
- fixed all files for pylint
- added .github/workflow/pythonapp.yml
- added pipenv, pylint and pytest

* chore:
- streamlining pythonapp.yml
- triggers pythonapp.yml on all push and pull_request

* chore: updated pythonapp.yml

* chore: updated pythonapp.yml

* chore: updated pythonapp.yml, readme.md

* chore: updated pythonapp.yml

* chore: updated pythonapp.yml

* chore: updated pythonapp.yml

* chore: updated pythonapp.yml

* chore: updated pythonapp.yml

* chore: updated pythonapp.yml

* chore: updated pythonapp.yml

* chore: updated pythonapp.yml

* feat: rerouting root endpoint to postman

* feat: rerouting root endpoint to postman

* feat: added redirect to postman, added test

* fix: added uvloop

* feat: adding coverall

* feat: installed coveralls for coverall.io

* feat: installed coveralls for coverall.io

* feat: installed coveralls for coverall.io

* feat: installed coveralls for coverall.io attempt 6

* feat: installed coveralls for coverall.io attempt 8

* feat: installed coveralls for coverall.io attempt 9

* feat: settingup coverall attempt #11

* feat: coverall badge attempt #12

* feat: coverall added, feat: routing root to redoc

* fix: default config logic

* fix: default config logic

* Update LICENSE

* chore: updating README again  🤧 (#46)

* chore: updating READMEs

* chore: updating READMEs

* chore: updating READMEs (#48)

* fix: post county new_death nan error (#50)

* fix: /post county new_death nan error

* fix: /post county new_death nan error

* feat: test: (#52)

* feat: adding zip route

* feat: zip route #1

* feat: removed uszipcode, added zipcodes

* feat:
- feat: added zip endpoint to return county data given zip code
- test: added tests for the zip endpoint
- feat: modified github actions to trigger on push, and on pr to master/staging

* han: attempt to fix codefactor #1

* feat: zip endpoint
- added custom exception handlers
- mal-formed zip codes now return 422 instead of 404
- changed mal-formed zip codes test cases from 404 to 422

* fixed zip endpoint for nyc (#54)

Co-authored-by: leehanchung <[email protected]>
Co-authored-by: Hanchung Lee <[email protected]>

* fix: benton, wa

* fix: github actions

* fix: github actions to pr only

* fix: counties yo counties

* fix: merge confliictassz round 2

Co-authored-by: Harsh Desai <[email protected]>

* chore: updating master (#55) (#59)

* refactor: change Aaron to standard feat: adding basic test
- Changed APP to app according to Flask/FastAPI standard
- Changed config_ to _config. trailing space is for python default conflicts not import
- Adding basic tests for endpoints

* test: added test structures
- 	est_app.py: testing �pp.py app title, description, version
- 	est_config.py: tested ProductionConfig, DevelopmentConfig, config loader
- 	est_endpoints.py: tested root test

* test: added test structures
- 	est_app.py: testing �pp.py app title, description, version
- 	est_config.py: tested ProductionConfig, DevelopmentConfig, config loader
- 	est_endpoints.py: tested root test

* tests: add testing for custom error messages

* chore: updated README

* chore: fixed PR template

* chore: updated README

* chore: updated README

* tests: adds test cases for endpoints
- '/' done
- '/news' only testing for 422 and 405, no validation yet
- '/twitter': tested 422, 404, 405, and random data sample validation
- '/county': tested 404, 405, 422. no data return validation yet
- '/state': tested 405, 422.
- '/country': tested 405, 422.
- '/stats': tested 405, 422.

* style: fix for codefactor.
- 	est_config.py: keeping assert == True/False for code readability
- 	est_endpoints.py: keeping TODO as a reminder to fix endpoints.py

* style: changed config_ to �pp_config after technical discussion

* style: chore:
- added .pylintrc
- fixed all files for pylint
- added .github/workflow/pythonapp.yml
- added pipenv, pylint and pytest

* chore:
- streamlining pythonapp.yml
- triggers pythonapp.yml on all push and pull_request

* chore: updated pythonapp.yml

* chore: updated pythonapp.yml

* chore: updated pythonapp.yml, readme.md

* chore: updated pythonapp.yml

* chore: updated pythonapp.yml

* chore: updated pythonapp.yml

* chore: updated pythonapp.yml

* chore: updated pythonapp.yml

* chore: updated pythonapp.yml

* chore: updated pythonapp.yml

* chore: updated pythonapp.yml

* feat: rerouting root endpoint to postman

* feat: rerouting root endpoint to postman

* feat: added redirect to postman, added test

* fix: added uvloop

* feat: adding coverall

* feat: installed coveralls for coverall.io

* feat: installed coveralls for coverall.io

* feat: installed coveralls for coverall.io

* feat: installed coveralls for coverall.io attempt 6

* feat: installed coveralls for coverall.io attempt 8

* feat: installed coveralls for coverall.io attempt 9

* feat: settingup coverall attempt #11

* feat: coverall badge attempt #12

* feat: coverall added, feat: routing root to redoc

* fix: default config logic

* fix: default config logic

* Update LICENSE

* chore: updating README again  🤧 (#46)

* chore: updating READMEs

* chore: updating READMEs

* chore: updating READMEs (#48)

* fix: post county new_death nan error (#50)

* fix: /post county new_death nan error

* fix: /post county new_death nan error

* feat: test: (#52)

* feat: adding zip route

* feat: zip route #1

* feat: removed uszipcode, added zipcodes

* feat:
- feat: added zip endpoint to return county data given zip code
- test: added tests for the zip endpoint
- feat: modified github actions to trigger on push, and on pr to master/staging

* han: attempt to fix codefactor #1

* feat: zip endpoint
- added custom exception handlers
- mal-formed zip codes now return 422 instead of 404
- changed mal-formed zip codes test cases from 404 to 422

* fixed zip endpoint for nyc (#54)

Co-authored-by: leehanchung <[email protected]>
Co-authored-by: Hanchung Lee <[email protected]>

Co-authored-by: Harsh Desai <[email protected]>

* fix: zipcode fix for us districts and territories

* tests: unit test for US districts and all territories added

* chore: linting fixed

Co-authored-by: Harsh Desai <[email protected]>
  • Loading branch information
leehanchung and hurshd0 committed Apr 26, 2020
1 parent e11a5c3 commit 8661e05
Show file tree
Hide file tree
Showing 5 changed files with 315 additions and 343 deletions.
128 changes: 53 additions & 75 deletions api/endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,14 @@
from api.utils import read_country_data
from api.utils import read_county_stats
from api.utils import read_states

# from api.utils import read_county_stats_zip_ny
from api.config import DataReadingError

# Starts the FastAPI Router to be used by the FastAPI app.
router = APIRouter()
_logger = get_logger(logger_name=__name__)
tm = TwitterMongo(app_config.DB_NAME,
app_config.COLLECTION_TWITTER,
verbose=False)
tm = TwitterMongo(app_config.DB_NAME, app_config.COLLECTION_TWITTER, verbose=False)


###############################################################################
Expand All @@ -46,7 +45,7 @@ class RootOutput(BaseModel):
message: str


@router.get("/")#, response_model=RootOutput)
@router.get("/") # , response_model=RootOutput)
async def root() -> JSONResponse:
"""Root URL, redirect to ReDoc API doc
"""
Expand Down Expand Up @@ -78,9 +77,7 @@ class NewsOut(BaseModel):
message: List[News]


@router.get("/news",
response_model=NewsOut,
responses={404: {"model": Message}})
@router.get("/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,9 +95,7 @@ async def get_gnews() -> JSONResponse:
return json_data


@router.post("/news",
response_model=NewsOut,
responses={404: {"model": Message}})
@router.post("/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
results in JSON
Expand All @@ -114,8 +109,7 @@ 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 @@ -147,9 +141,9 @@ class TwitterOutput(BaseModel):
message: UserTweets


@router.get("/twitter",
response_model=TwitterOutput,
responses={404: {"model": Message}})
@router.get(
"/twitter", response_model=TwitterOutput, responses={404: {"model": Message}}
)
async def get_twitter() -> JSONResponse:
"""Fetch and return Twitter data from MongoDB connection."""
try:
Expand All @@ -164,23 +158,20 @@ async def get_twitter() -> JSONResponse:

json_data = {
"success": True,
"message": {"username": username,
"full_name": full_name,
"tweets": tweets},
"message": {"username": username, "full_name": full_name, "tweets": tweets},
}
del tweets
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}})
@router.post(
"/twitter", response_model=TwitterOutput, responses={404: {"model": Message}}
)
async def post_twitter(twyuser: TwitterInput) -> JSONResponse:
"""Fetch and return Twitter data from MongoDB connection."""
try:
Expand All @@ -193,17 +184,14 @@ async def post_twitter(twyuser: TwitterInput) -> JSONResponse:
tweets = sorted(tweets, key=lambda i: i["created_at"], reverse=True)
json_data = {
"success": True,
"message": {"username": username,
"full_name": full_name,
"tweets": tweets},
"message": {"username": username, "full_name": full_name, "tweets": tweets},
}

del tweets
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 @@ -237,9 +225,7 @@ class CountyOut(BaseModel):


@cached(cache=TTLCache(maxsize=1, ttl=3600))
@router.get("/county",
response_model=CountyOut,
responses={404: {"model": Message}})
@router.get("/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
with 404 if run into error.
Expand All @@ -252,15 +238,12 @@ async def get_county_data() -> JSONResponse:
gc.collect()
except Exception as ex:
_logger.warning(f"Endpoint: /county --- GET --- {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


@router.post("/county",
response_model=CountyOut,
responses={404: {"model": Message}})
@router.post("/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
with 404 if run into error.
Expand All @@ -272,8 +255,7 @@ 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 @@ -299,9 +281,7 @@ class StateOutput(BaseModel):


@cached(cache=TTLCache(maxsize=3, ttl=3600))
@router.post("/state",
response_model=StateOutput,
responses={404: {"model": Message}})
@router.post("/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
unattributed and out of state cases.
Expand All @@ -315,8 +295,7 @@ 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 All @@ -342,9 +321,9 @@ class CountryOutput(BaseModel):


@cached(cache=TTLCache(maxsize=3, ttl=3600))
@router.post("/country",
response_model=CountryOutput,
responses={404: {"model": Message}})
@router.post(
"/country", response_model=CountryOutput, responses={404: {"model": Message}}
)
async def get_country(country: CountryInput) -> JSONResponse:
"""Fetch country level data time series for a single country.
- Cached for 1 hour
Expand All @@ -355,11 +334,11 @@ 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


###############################################################################
#
# Stats Endpoints
Expand All @@ -383,9 +362,7 @@ class StatsOutput(BaseModel):
message: Stats


@router.get("/stats",
response_model=StatsOutput,
responses={404: {"model": Message}})
@router.get("/stats", response_model=StatsOutput, responses={404: {"model": Message}})
async def get_stats() -> JSONResponse:
"""Get overall tested, confirmed, and deaths stats from the database
and return it as a JSON string.
Expand All @@ -395,14 +372,11 @@ 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}})
@router.post("/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
and return it as a JSON string.
Expand All @@ -412,10 +386,10 @@ 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


###############################################################################
#
# ZIP Endpoint
Expand All @@ -424,6 +398,7 @@ async def post_stats(stats: StatsInput) -> JSONResponse:
class ZIPInput(BaseModel):
zip_code: str = "70030"


class ZIPStats(BaseModel):
county_name: str = "St. Charles"
state_name: str = "Louisiana"
Expand All @@ -436,45 +411,48 @@ class ZIPStats(BaseModel):
longitude: float
last_update: str = "2020-04-17 19:50 EDT"


class ZIPOutput(BaseModel):
success: bool
message: ZIPStats


@router.post("/zip",
response_model=ZIPOutput,
responses={404: {"model": Message}})
@router.post("/zip", response_model=ZIPOutput, responses={404: {"model": Message}})
def post_zip(zip_code: ZIPInput) -> JSONResponse:
"""Returns county stats for the zip code input.
"""

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}")

raise HTTPException(
status_code=422, detail=f"[Error] POST '/zip' {ex} {message}"
)

try:
county = zip_info['county'].rsplit(' ', 1)[0]
state = zip_info['state']
_logger.info(f"State: {state}, County: {county}")
county = zip_info["county"].rsplit(" ", 1)[0]
state = zip_info["state"]
city = zip_info["city"]
_logger.info(f"State: {state}, County: {county}, City: {city}")
if state == "NY":
nyc_counties = ["Bronx", "Kings", "Queens", "Richmond"]
if county in nyc_counties:
if county in nyc_counties:
county = "New York"
data = read_county_stats(state, county)[0]
else:
data = read_county_stats(state, county)[0]
elif state == "VI":
if city == "St Thomas":
county = "St. Thomas"
if city == "St John":
county = "St. John"
if city in ["Christiansted", "Frederiksted", "Kingshill"]:
county = "St. Croix"
data = read_county_stats(state, county)[0]
json_data = {"success": True, "message": data}
del data
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
Loading

0 comments on commit 8661e05

Please sign in to comment.