Skip to content

Commit f651503

Browse files
author
ExpDev07
committed
caching
1 parent 840f430 commit f651503

File tree

5 files changed

+136
-64
lines changed

5 files changed

+136
-64
lines changed

Pipfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ python-dotenv = "*"
1212
requests = "*"
1313
gunicorn = "*"
1414
flask-cors = "*"
15+
geopy = "*"
16+
cachetools = "*"
1517

1618
[requires]
1719
python_version = "3.8"

Pipfile.lock

Lines changed: 33 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from flask import Flask
22
from flask_cors import CORS
3-
from .settings import *
3+
from app.settings import *
4+
from app.location import get_locations
45

56
# Create the flask application.
67
app = Flask(__name__)

app/location.py

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import requests
2+
from datetime import datetime
3+
from cachetools import cached, TTLCache
4+
from geopy.geocoders import Nominatim
5+
from app.settings import *
6+
7+
class Location(object):
8+
"""A location with data about the coronavirus."""
9+
10+
def __init__(self, last_updated, country, province, coordinates, confirmed, deaths, recovered):
11+
self.last_updated = last_updated
12+
self.country = country
13+
self.province = province
14+
self.coordinates = coordinates
15+
self.confirmed = confirmed
16+
self.deaths = deaths
17+
self.recovered = recovered
18+
19+
def serialize(self):
20+
"""Serializes the location."""
21+
return {
22+
'last_updated': self.last_updated,
23+
'country': self.country,
24+
'province': self.province,
25+
'coordinates': self.coordinates,
26+
'confirmed': self.confirmed,
27+
'deaths': self.deaths,
28+
'recovered': self.recovered,
29+
}
30+
31+
import pprint
32+
33+
@cached(cache=TTLCache(maxsize=100, ttl=1800))
34+
def get_locations():
35+
"""Gets all the locations."""
36+
37+
# Request latest data and parse the json.
38+
response = requests.get('https://sheets.googleapis.com/v4/spreadsheets/' + SPREADSHEET_ID + '/values/A:F?key=' + GOOGLE_API_KEY).json()
39+
40+
# Extract the values and remove header.
41+
items = response['values']
42+
items.pop(0)
43+
44+
# The locations.
45+
locations = [];
46+
47+
# Go through all the items and make a location for them all.
48+
for item in items:
49+
locations.append(Location(
50+
# Date when location was last updated.
51+
last_updated = datetime.strptime(item[2], '%m/%d/%y %H:%M'),
52+
53+
# Country and province.
54+
country = item[1],
55+
province = item[0],
56+
57+
# Coordinates.
58+
coordinates = get_coordinates(item[0] or item[1]),
59+
60+
# Statistics.
61+
confirmed = int(item[3]),
62+
deaths = int(item[4]),
63+
recovered = int(item[5]),
64+
))
65+
66+
# Return the locations!
67+
return locations
68+
69+
# Create the geo locator.
70+
geolocator = Nominatim(user_agent='coronavirus-tracker-api', timeout=50)
71+
72+
@cached(cache={})
73+
def get_coordinates(query):
74+
"""Gets the coordinates from the query provided."""
75+
76+
# Geo-code the query.
77+
geo_location = geolocator.geocode(query)
78+
79+
# Make sure to return empty if we cannot geo-locate.
80+
if not geo_location:
81+
print('Could not geo-code ' + query)
82+
return None
83+
84+
# Return the coordinates.
85+
print('Successfully geo-coded ' + query + '!')
86+
return {
87+
'latitude': geo_location.latitude,
88+
'longitude': geo_location.longitude,
89+
}
90+
91+

app/routes/latest.py

Lines changed: 8 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
import requests
22
import functools
3-
from datetime import datetime
3+
from flask import jsonify
44
from app import app
5-
from ..settings import *
5+
from app.location import get_locations
66

77
@app.route('/latest')
88
def latest():
9-
# Fetch the latest data.
10-
data = fetch()
9+
# Get all the locations.
10+
locations = list(map(lambda loc: loc.serialize(), get_locations()))
1111

1212
# Make some simple statistic calculations.
13-
confirmed = sum(map(lambda value: value['confirmed'], data))
14-
deaths = sum(map(lambda value: value['deaths'], data))
15-
recovered = sum(map(lambda value: value['recovered'], data))
13+
confirmed = sum(map(lambda loc: loc['confirmed'], locations))
14+
deaths = sum(map(lambda loc: loc['deaths'], locations))
15+
recovered = sum(map(lambda loc: loc['recovered'], locations))
1616

1717
# Return the stats and data as json.
1818
return {
@@ -22,50 +22,5 @@ def latest():
2222
'recovered': recovered,
2323

2424
# Data
25-
'data': data
26-
}
27-
28-
def fetch():
29-
"""
30-
Fetches the latest data.
31-
"""
32-
33-
# Request latest data and parse the json
34-
response = requests.get('https://sheets.googleapis.com/v4/spreadsheets/' + SPREADSHEET_ID + '/values/A:F?key=' + GOOGLE_API_KEY).json()
35-
36-
# Extract the values and remove header
37-
items = response['values']
38-
items.pop(0)
39-
40-
# Normalize the values
41-
return normalizeItems(items)
42-
43-
def normalizeItems(items):
44-
"""
45-
Normalizes the items into a format that can be returned.
46-
"""
47-
48-
# The list of items normalized.
49-
normalized = []
50-
51-
# Normalize each item and add them to the list.
52-
for item in items:
53-
normalized.append(normalize(item))
54-
55-
# Return the normalized items.
56-
return normalized
57-
58-
def normalize(item):
59-
"""
60-
Normalizes the provided item.
61-
"""
62-
63-
# Return the normalized item.
64-
return {
65-
'province': item[0],
66-
'country': item[1],
67-
'last_updated': datetime.strptime(item[2], '%m/%d/%y %H:%M'),
68-
'confirmed': int(item[3]),
69-
'deaths': int(item[4]),
70-
'recovered': int(item[5]),
25+
'locations': locations,
7126
}

0 commit comments

Comments
 (0)