From 896978f1ab6759909c506d0bfcc57cdf21aee030 Mon Sep 17 00:00:00 2001 From: bt3gl Date: Sat, 26 Mar 2022 11:13:24 +0400 Subject: [PATCH] Add Location API project on FastAPI deplpyed in Vercel --- README.md | 5 ++++ fastapi-location-app/.gitignore | 4 +++ fastapi-location-app/.vercelignore | 5 ++++ fastapi-location-app/README.md | 34 ++++++++++++++++++++++ fastapi-location-app/api/__init__.py | 0 fastapi-location-app/api/api.py | 14 +++++++++ fastapi-location-app/api/methods.py | 35 +++++++++++++++++++++++ fastapi-location-app/api/routes.py | 17 +++++++++++ fastapi-location-app/main.py | 4 +++ fastapi-location-app/requirements-dev.txt | 1 + fastapi-location-app/requirements.txt | 4 +++ fastapi-location-app/vercel.json | 11 +++++++ 12 files changed, 134 insertions(+) create mode 100644 fastapi-location-app/.gitignore create mode 100644 fastapi-location-app/.vercelignore create mode 100644 fastapi-location-app/README.md create mode 100644 fastapi-location-app/api/__init__.py create mode 100644 fastapi-location-app/api/api.py create mode 100644 fastapi-location-app/api/methods.py create mode 100644 fastapi-location-app/api/routes.py create mode 100644 fastapi-location-app/main.py create mode 100644 fastapi-location-app/requirements-dev.txt create mode 100644 fastapi-location-app/requirements.txt create mode 100644 fastapi-location-app/vercel.json diff --git a/README.md b/README.md index 4ef960d..f664dfb 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,11 @@ # ✨🐍 [Scratch Space] Python: small projects and boilerplates +### APIs + +* [FastAPI Location API deployed in Vercel](github.com/bt3gl-labs/Scratch-Space-Python/tree/master/fastapi-location-api) + + ### Boilerplates * [CLI with Click](https://github.com/bt3gl-labs/Scratch-Space-Python/tree/master/boilerplates-click) diff --git a/fastapi-location-app/.gitignore b/fastapi-location-app/.gitignore new file mode 100644 index 0000000..6323082 --- /dev/null +++ b/fastapi-location-app/.gitignore @@ -0,0 +1,4 @@ +__pycache__ +.vercel +venv +.env \ No newline at end of file diff --git a/fastapi-location-app/.vercelignore b/fastapi-location-app/.vercelignore new file mode 100644 index 0000000..9180259 --- /dev/null +++ b/fastapi-location-app/.vercelignore @@ -0,0 +1,5 @@ +requirements-dev.txt +venv +main.py +README.md +.gitignore \ No newline at end of file diff --git a/fastapi-location-app/README.md b/fastapi-location-app/README.md new file mode 100644 index 0000000..c1749c3 --- /dev/null +++ b/fastapi-location-app/README.md @@ -0,0 +1,34 @@ +# Location API 🗺 + + +Location API deployed in Vercel and built with FastAPI. + +## Endpoint /location + +Input data: + +``` +{"city": "berlin"} +``` + +Response: + +``` +{"lat":52.5186925,"lon":13.3996024,"tzone":1} +``` + + +### Installing + +``` +virtualenv -p python3.9 venv +source venv/bin/activate +pipenv install +``` + +### Running + + +``` +python3 main.py +``` diff --git a/fastapi-location-app/api/__init__.py b/fastapi-location-app/api/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/fastapi-location-app/api/api.py b/fastapi-location-app/api/api.py new file mode 100644 index 0000000..6702af7 --- /dev/null +++ b/fastapi-location-app/api/api.py @@ -0,0 +1,14 @@ + +from .routes import router as LocationRouter +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/", tags=["Root"]) +async def read_root() -> dict: + return { + "message": "$CHOICES Timezone API ⏳✨. Try /docs to learn about this API" + } + +app.include_router(LocationRouter, prefix="/tzone") diff --git a/fastapi-location-app/api/methods.py b/fastapi-location-app/api/methods.py new file mode 100644 index 0000000..5a70ff6 --- /dev/null +++ b/fastapi-location-app/api/methods.py @@ -0,0 +1,35 @@ +import pytz +import datetime +from geopy.geocoders import Nominatim +from timezonefinder import TimezoneFinder + + +def _find_timezone(lat, lon) -> int: + obj = TimezoneFinder() + tzone = obj.timezone_at(lng=lon, lat=lat) + timezone = datetime.datetime.now(pytz.timezone(tzone)).strftime('%z') + try: + timezone = int(timezone[:-2]) + except: + print('Error formatting timezone {}'.format(timezone)) + return timezone + + +def get_location(data) -> dict: + try: + city = data['city'] + except: + print('Data is ill-formatted: {}'.format(data)) + + geolocator = Nominatim(user_agent="$choices") + location = geolocator.geocode(city) + + data = { + 'lat': location.latitude, + 'lon': location.longitude, + 'tzone': _find_timezone(location.latitude, location.longitude) + } + + return data + + diff --git a/fastapi-location-app/api/routes.py b/fastapi-location-app/api/routes.py new file mode 100644 index 0000000..dbbcb7c --- /dev/null +++ b/fastapi-location-app/api/routes.py @@ -0,0 +1,17 @@ +from pydantic import BaseModel +from fastapi import APIRouter +from .methods import get_location + + +router = APIRouter() + +class City(BaseModel): + city: str + + +@router.post("/") +def search_city(data: City) -> dict: + return get_location(data.dict()) + + + diff --git a/fastapi-location-app/main.py b/fastapi-location-app/main.py new file mode 100644 index 0000000..c9f72d1 --- /dev/null +++ b/fastapi-location-app/main.py @@ -0,0 +1,4 @@ +import uvicorn + +if __name__ == "__main__": + uvicorn.run("api.api:app", host="0.0.0.0", port=8000, reload=True) diff --git a/fastapi-location-app/requirements-dev.txt b/fastapi-location-app/requirements-dev.txt new file mode 100644 index 0000000..400ebf5 --- /dev/null +++ b/fastapi-location-app/requirements-dev.txt @@ -0,0 +1 @@ +uvicorn \ No newline at end of file diff --git a/fastapi-location-app/requirements.txt b/fastapi-location-app/requirements.txt new file mode 100644 index 0000000..e414903 --- /dev/null +++ b/fastapi-location-app/requirements.txt @@ -0,0 +1,4 @@ +timezonefinder==5.2.0 +pytz==2022.1 +pydantic +fastapi \ No newline at end of file diff --git a/fastapi-location-app/vercel.json b/fastapi-location-app/vercel.json new file mode 100644 index 0000000..fa20649 --- /dev/null +++ b/fastapi-location-app/vercel.json @@ -0,0 +1,11 @@ +{ + "routes": [ + {"src": "/(.*)", "dest": "api/api.py"} + ], + "functions": { + "api/api.py": { + "memory": 3008, + "maxDuration": 30 + } + } +} \ No newline at end of file