Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion app/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
from app.modules.examples.yaml_example import YamlExampleHandler
from app.modules.training.pipeline_training import PipelineTrainigHandler
from app.modules.training.http_training import HttpTrainingHandler
from app.modules.training.datastore_training import DatastoreTrainingHandler
from app.modules.cityinfo.cityinfo import CityInfoBuildHandler , CityInfoViewHandler

def handlers():
return [
Expand All @@ -18,5 +20,8 @@ def handlers():
(r'/examples/datastore/([^\/]+)/([^\/]+)', DatastoreExampleHandler),
(r'/examples/yaml', YamlExampleHandler),
(r'/training/pipeline/(\d+)', PipelineTrainigHandler),
(r'/training/http/([\d\.]+)/([\d\.]+)', HttpTrainingHandler),
(r'/training/http/([-?\d\.]+)/([-?\d\.]+)', HttpTrainingHandler),
(r'/training/datastore', DatastoreTrainingHandler),
(r'/cityinfo/build', CityInfoBuildHandler),
(r'/cityinfo/view', CityInfoViewHandler),
]
1 change: 1 addition & 0 deletions app/modules/cityinfo/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# __init__.py needed to create "package" for this directory
75 changes: 75 additions & 0 deletions app/modules/cityinfo/city_extras.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import requests
import logging
import os
from google.appengine.ext import ndb
from requests_toolbelt.adapters import appengine
from app.modules.common.kinds import CityInfo

# https://toolbelt.readthedocs.io/en/latest/adapters.html#appengineadapter
appengine.monkeypatch(validate_certificate=False)

def CityWikiInfo(lat , lon):
# wikipedia base api url
API_HOST = "https://en.wikipedia.org/w/api.php?"

# add given lat long to api url
apiUrl = "%sformat=json&action=query&prop=extracts&exintro=1&explaintext=1&exlimit=20&generator=geosearch&ggsradius=10000&ggslimit=100&ggscoord=%s%s%s" % (API_HOST, lat,"|", lon)

logging.info(apiUrl)

template_vars = {}

try:
# make the api call
request = requests.get(apiUrl)
data = request.json()

# check if there is data returned
if 'query' in data :

for idx , page in data['query']['pages'].items():
# get the 0 indexd page (first page data)
if page['index'] == 0:
return page['extract']

else:
# if there is no data returned show user
logging.error(e)
except requests.exceptions.RequestException as e:
logging.error(e)

return None

def CityWeatherTemp(lat , lon):
API_HOST = "http://api.openweathermap.org"
API_KEY = os.environ.get("HTTP_EXAMPLE_API_KEY")

if API_KEY:
try:
apiUrl = "%s/data/2.5/forecast?appid=%s&mode=json&units=metric&lat=%s&lon=%s" % (API_HOST, API_KEY, lat, lon)
request = requests.get(apiUrl)
data = request.json()
return data['list'][0]['main']['temp']
except requests.exceptions.RequestException as e:
logging.error(e)

return None

def StoreCitiesInfo(cities):
for city in cities:
entity_key = ndb.Key('CityInfo', city['Location'])
entity = entity_key.get()

if entity is None:
entity = CityInfo(
Location=city['Location'],
Info=city['Info'],
Temp=city['Temp']
)
entity.key = ndb.Key('CityInfo', city['Location'])
entity.put()

else:
entity.Info = city['Info']
entity.Temp = city['Temp']
entity.put()
16 changes: 16 additions & 0 deletions app/modules/cityinfo/city_info.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<html>
<body>
<h1>Cities Information</h1>
<dl>
{% for city in cities %}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a condition to be displayed if we don't have data on any cities.

<dt><p>{{ city.Location }}</p></dt>
<dd><p>Temp : {{ city.Temp }}</p></dd>
<dd><p>Last Updated : {{ city.LastUpdated }}</p></dd>
<dd><p>Info : {{ city.Info }}</p></dd>
{% endfor %}
{% if not cities %}
No cities found
{% endif %}
</dl>
</body>
</html>
24 changes: 24 additions & 0 deletions app/modules/cityinfo/cityinfo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import webapp2
import logging
import os
from google.appengine.ext.webapp import template
from app.modules.common.city_info import CityInfoRootPipeline
from app.modules.common.kinds import CityInfo

class CityInfoBuildHandler(webapp2.RequestHandler):
def get(self):
logging.info("CityInfoBuildHandler")
CitiesUpdate = CityInfoRootPipeline()
CitiesUpdate.start()

class CityInfoViewHandler(webapp2.RequestHandler):
def get(self):
logging.info("CityInfoViewHandler")

# get cities
cities = CityInfo.query().fetch(20)

template_path = os.path.join(os.path.dirname(__file__), 'city_info.html')
self.response.write(template.render(template_path, {
'cities': cities,
}))
18 changes: 18 additions & 0 deletions app/modules/cityinfo/cityinfo.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
cities:
-
name: London
lat: 51.507222
lon: -0.1275
-
name: Cairo
lat: 30.044444
lon: 31.235833
-
name: Beijing
lat: 39.916667
lon: 116.383333

-
name: Paris
lat: 48.8588376
lon: 2.2768489
56 changes: 56 additions & 0 deletions app/modules/common/city_info.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import webapp2
import logging
import pipeline
import app.modules.cityinfo.city_extras as CityExtras
import app.modules.common.util as Utils

class CityInfoRootPipeline(pipeline.Pipeline):

def run(self):
logging.info("CityInfoRootPipeline")

# Read cityinfo.yaml file
data = Utils.ReadYamlFile('../cityinfo/cityinfo.yaml')
cities = []

for city in data['cities'] :
cityInfo = yield CityInfoFetchPipeline(city)
cities.append(cityInfo)

yield CityInfoPersistPipeline(*cities)

class CityInfoFetchPipeline(pipeline.Pipeline):

def run(self, city):
logging.info("CityInfoFetchPipeline")

cityinfo = yield CityInfoInfoPipeline(city['lat'] , city['lon'] )
citytemp = yield CityInfoWeatherPipeline(city['lat'] , city['lon'])

yield CityInfoReturn(city['name'], cityinfo,citytemp)

class CityInfoInfoPipeline(pipeline.Pipeline):

def run(self, lat , lon):
logging.info("CityInfoInfoPipeline")
return CityExtras.CityWikiInfo(lat , lon)

class CityInfoWeatherPipeline(pipeline.Pipeline):

def run(self , lat , lon):
logging.info("CityInfoWeatherPipeline")
return CityExtras.CityWeatherTemp(lat , lon)

class CityInfoPersistPipeline(pipeline.Pipeline):

def run(self, *args):
logging.info("CityInfoPersistPipeline")

CityExtras.StoreCitiesInfo(args)

class CityInfoReturn(pipeline.Pipeline):

def run(self, cityname,cityInfo , cityTemp):
logging.info("CityInfoReturn")

return {'Location' : cityname ,'Info' : cityInfo , 'Temp' : cityTemp }
12 changes: 12 additions & 0 deletions app/modules/common/kinds.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import webapp2
import logging
from google.appengine.ext import ndb

class Example(ndb.Model):
value = ndb.StringProperty()

class CityInfo(ndb.Model):
Location = ndb.StringProperty()
Info = ndb.TextProperty()
Temp = ndb.FloatProperty()
LastUpdated = ndb.DateTimeProperty(auto_now=True)
3 changes: 2 additions & 1 deletion app/modules/common/squares.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,5 @@ def run(self, number):
class LogResult(pipeline.Pipeline):

def run(self, number):
logging.info('All done! Value is %s', number)
logging.info('All done! Value is %s', number)

10 changes: 10 additions & 0 deletions app/modules/common/util.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import os
import yaml

def ReadYamlFile(fileLocation):
data = {}
yaml_path = os.path.join(os.path.dirname(__file__), fileLocation)
with open(yaml_path, 'r') as stream:
data = yaml.load(stream)

return data
4 changes: 3 additions & 1 deletion app/modules/home.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ <h1>Home</h1>
<li><a href="/examples/datastore/key">Datastore example (load)</a></li>
<li><a href="/examples/yaml">Yaml example</a></li>
<li><a href="/training/pipeline/5">Pipeline training</a></li>
<li><a href="/training/http/30.05/31.25">Http training </a></li>
<li><a href="/training/http/30.05/31.25">Http training</a></li>
<li><a href="/training/datastore">Datastore training</a></li>
<li><a href="/cityinfo/view">City info view</a></li>
</ul>
<p>Logged in as : {{user_name}}</p>
</body>
Expand Down
11 changes: 11 additions & 0 deletions app/modules/training/datastore_training.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<html>
<body>
<h1>Datastore Training</h1>
<dl>
{% for entity in entities %}
<dt><p>{{ entity.key }}</p></dt>
<dd><p>{{ entity.value }}</p></dd>
{% endfor %}
</dl>
</body>
</html>
24 changes: 24 additions & 0 deletions app/modules/training/datastore_training.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import webapp2
import logging
import os
from google.appengine.ext import ndb
from google.appengine.ext.webapp import template
from app.modules.common.kinds import Example

class DatastoreTrainingHandler(webapp2.RequestHandler):
def get(self):
logging.info("DatastoreTrainingHandler")

# get entities
entities_for_example_kind = Example.query().fetch(20)

# make a list of key value pairs
entities = []
for entity in entities_for_example_kind:
entities.append({'key':entity.key.string_id() , 'value':entity.value})

template_path = os.path.join(os.path.dirname(__file__), 'datastore_training.html')
self.response.write(template.render(template_path, {
'entities': entities,
}))

2 changes: 1 addition & 1 deletion app/modules/training/http_training.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def get(self, lat = None, lon = None):

# wikipedia base api url
API_HOST = "https://en.wikipedia.org/w/api.php?"

# add given lat long to api url
apiUrl = "%sformat=json&action=query&prop=extracts&exintro=1&explaintext=1&exlimit=20&generator=geosearch&ggsradius=10000&ggslimit=100&ggscoord=%s%s%s" % (API_HOST, lat,"|", lon)

Expand Down
4 changes: 4 additions & 0 deletions cron.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
cron:
- description: "City info build hourly"
url: /cityinfo/build
schedule: every 1 hours
2 changes: 1 addition & 1 deletion deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ if [ -z "$APPENGINE_PROJECT_ID" ]
then
echo "You must obtain an AppEngine PROJECT_ID [https://console.cloud.google.com/appengine] and place it in .env before running this!"
else
gcloud app deploy app-deploy.yaml --project $APPENGINE_PROJECT_ID --version 1 --promote
gcloud app deploy app-deploy.yaml cron.yaml --project $APPENGINE_PROJECT_ID --version 1 --promote
fi