feature/metafeeds: Support for canteen meta feeds and index feed (#2)
* feature/metafeeds: Restructured API, splitted menu and meta feed * feature/metafeeds: add field 'key' to Canteen * feature/metafeeds: added helper function for reverse urls * feature/metafeeds: added menu feed url to meta feed * feature/metafeeds: added missing test (added: testing meta feed rendering in retrievaltest) * feature/metafeeds: added feed index page * whitespace fix * feature/metafeeds: added alias urls * feature/metafeeds: moved meta feed default url * feature/metafeeds: moved index generation to views * feature/metafeeds: inlined builder instance creation * feature/metafeeds: removed unused 'menu' parameter * feature/metafeeds: replaced 'reverse' module with Flask's url_for * feature/metafeeds: removed unused import * feature/metafeeds: removed unused function parameters * feature/metafeeds: moved menu feed url generation to views.py * feature/metafeeds: cleanup debug prints removing debug prints that should never have been committed.
This commit is contained in:
@@ -2,4 +2,4 @@
|
|||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
Canteen = namedtuple('Canteen', ('name', 'street', 'city', 'id', 'chash'))
|
Canteen = namedtuple('Canteen', ('key', 'name', 'street', 'city', 'id', 'chash'))
|
||||||
|
|||||||
@@ -17,7 +17,8 @@ def _get_config(filename):
|
|||||||
|
|
||||||
def _parse_canteen(config, canteen_name):
|
def _parse_canteen(config, canteen_name):
|
||||||
get = partial(config.get, canteen_name)
|
get = partial(config.get, canteen_name)
|
||||||
return Canteen(name=get('name'),
|
return Canteen(key=canteen_name,
|
||||||
|
name=get('name'),
|
||||||
street=get('street'),
|
street=get('street'),
|
||||||
city=get('city'),
|
city=get('city'),
|
||||||
id=get('id'),
|
id=get('id'),
|
||||||
|
|||||||
+14
-9
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
from pyopenmensa.feed import LazyBuilder
|
from pyopenmensa.feed import LazyBuilder
|
||||||
|
|
||||||
|
|
||||||
PRICE_ROLE_MAPPING = {
|
PRICE_ROLE_MAPPING = {
|
||||||
'student': 'preis_s',
|
'student': 'preis_s',
|
||||||
'other': 'preis_g',
|
'other': 'preis_g',
|
||||||
@@ -48,18 +49,22 @@ def _process_day(builder, day):
|
|||||||
roles=None)
|
roles=None)
|
||||||
|
|
||||||
|
|
||||||
def _create_builder(canteen):
|
def render_menu(menu):
|
||||||
builder = LazyBuilder()
|
builder = LazyBuilder()
|
||||||
builder.name = canteen.name
|
|
||||||
builder.address = canteen.street
|
|
||||||
builder.city = canteen.city
|
|
||||||
return builder
|
|
||||||
|
|
||||||
|
|
||||||
def render(canteen, menu):
|
|
||||||
builder = _create_builder(canteen)
|
|
||||||
|
|
||||||
for day in _active_days(menu):
|
for day in _active_days(menu):
|
||||||
_process_day(builder, day)
|
_process_day(builder, day)
|
||||||
|
|
||||||
return builder.toXMLFeed()
|
return builder.toXMLFeed()
|
||||||
|
|
||||||
|
|
||||||
|
def render_meta(canteen, menu_feed_url):
|
||||||
|
builder = LazyBuilder()
|
||||||
|
|
||||||
|
builder.name = canteen.name
|
||||||
|
builder.address = canteen.street
|
||||||
|
builder.city = canteen.city
|
||||||
|
|
||||||
|
builder.define(name="full", priority="0", url=menu_feed_url, source=None, dayOfWeek="*", dayOfMonth="*", hour="8-18", minute="0", retry="30 1")
|
||||||
|
|
||||||
|
return builder.toXMLFeed()
|
||||||
|
|||||||
+49
-6
@@ -1,6 +1,9 @@
|
|||||||
# -*- encoding: utf-8 -*-
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
from flask import Flask, make_response
|
import os
|
||||||
|
import urlparse
|
||||||
|
|
||||||
|
from flask import Flask, jsonify, make_response, url_for
|
||||||
from werkzeug.contrib.cache import SimpleCache
|
from werkzeug.contrib.cache import SimpleCache
|
||||||
|
|
||||||
import feed
|
import feed
|
||||||
@@ -10,6 +13,16 @@ from canteen_api import MenuParams, download_menu
|
|||||||
CACHE_TIMEOUT = 45 * 60
|
CACHE_TIMEOUT = 45 * 60
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
app.url_map.strict_slashes = False
|
||||||
|
|
||||||
|
if 'BASE_URL' in os.environ:
|
||||||
|
base_url = urlparse.urlparse(os.environ.get('BASE_URL'))
|
||||||
|
if base_url.scheme:
|
||||||
|
app.config['PREFERRED_URL_SCHEME'] = base_url.scheme
|
||||||
|
if base_url.netloc:
|
||||||
|
app.config['SERVER_NAME'] = base_url.netloc
|
||||||
|
if base_url.path:
|
||||||
|
app.config['APPLICATION_ROOT'] = base_url.path
|
||||||
|
|
||||||
cache = SimpleCache()
|
cache = SimpleCache()
|
||||||
|
|
||||||
@@ -37,15 +50,37 @@ def get_menu(canteen, params):
|
|||||||
return menu
|
return menu
|
||||||
|
|
||||||
|
|
||||||
def canteen_feed_xml(canteen, menu):
|
def _canteen_feed_xml(xml):
|
||||||
xml = feed.render(canteen, menu)
|
|
||||||
response = make_response(xml)
|
response = make_response(xml)
|
||||||
response.mimetype = 'text/xml'
|
response.mimetype = 'text/xml'
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
@app.route('/canteen/<canteen_name>')
|
def canteen_menu_feed_xml(menu):
|
||||||
def canteen_feed(canteen_name):
|
xml = feed.render_menu(menu)
|
||||||
|
return _canteen_feed_xml(xml)
|
||||||
|
|
||||||
|
|
||||||
|
def canteen_meta_feed_xml(canteen):
|
||||||
|
menu_feed_url = url_for('canteen_menu_feed', canteen_name=canteen.key, _external=True)
|
||||||
|
xml = feed.render_meta(canteen, menu_feed_url)
|
||||||
|
return _canteen_feed_xml(xml)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/canteens/<canteen_name>')
|
||||||
|
@app.route('/canteens/<canteen_name>/meta')
|
||||||
|
def canteen_meta_feed(canteen_name):
|
||||||
|
config = read_canteen_config()
|
||||||
|
|
||||||
|
if canteen_name not in config:
|
||||||
|
return canteen_not_found(config, canteen_name)
|
||||||
|
|
||||||
|
canteen = config[canteen_name]
|
||||||
|
return canteen_meta_feed_xml(canteen)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/canteens/<canteen_name>/menu')
|
||||||
|
def canteen_menu_feed(canteen_name):
|
||||||
config = read_canteen_config()
|
config = read_canteen_config()
|
||||||
|
|
||||||
if canteen_name not in config:
|
if canteen_name not in config:
|
||||||
@@ -53,7 +88,15 @@ def canteen_feed(canteen_name):
|
|||||||
|
|
||||||
canteen = config[canteen_name]
|
canteen = config[canteen_name]
|
||||||
menu = get_menu_cached(canteen)
|
menu = get_menu_cached(canteen)
|
||||||
return canteen_feed_xml(canteen, menu)
|
return canteen_menu_feed_xml(menu)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/')
|
||||||
|
@app.route('/canteens')
|
||||||
|
def canteen_index():
|
||||||
|
config = read_canteen_config()
|
||||||
|
return jsonify({key: url_for('canteen_meta_feed', canteen_name=key, _external=True) for key in config})
|
||||||
|
|
||||||
|
|
||||||
@app.route('/health_check')
|
@app.route('/health_check')
|
||||||
def health_check():
|
def health_check():
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<openmensa version="2.1" xmlns="http://openmensa.org/open-mensa-v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://openmensa.org/open-mensa-v2 http://openmensa.org/open-mensa-v2.xsd">
|
<openmensa version="2.1" xmlns="http://openmensa.org/open-mensa-v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://openmensa.org/open-mensa-v2 http://openmensa.org/open-mensa-v2.xsd">
|
||||||
<canteen>
|
<canteen>
|
||||||
<name>Mensa Griebnitzsee</name>
|
|
||||||
<address>August-Bebel-Straße 69, Haus 6</address>
|
|
||||||
<city>14482 Potsdam</city>
|
|
||||||
<day date="2018-09-19">
|
<day date="2018-09-19">
|
||||||
<category name="Angebot 1">
|
<category name="Angebot 1">
|
||||||
<meal>
|
<meal>
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<openmensa version="2.1" xmlns="http://openmensa.org/open-mensa-v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://openmensa.org/open-mensa-v2 http://openmensa.org/open-mensa-v2.xsd">
|
||||||
|
<canteen>
|
||||||
|
<name>Mensa Griebnitzsee</name>
|
||||||
|
<address>August-Bebel-Straße 69, Haus 6</address>
|
||||||
|
<city>14482 Potsdam</city>
|
||||||
|
<feed name="full" priority="0">
|
||||||
|
<schedule dayOfMonth="*" dayOfWeek="*" hour="8-18" minute="0" retry="30 1"/>
|
||||||
|
<url>canteens/griebnitzsee/menu</url>
|
||||||
|
</feed>
|
||||||
|
</canteen>
|
||||||
|
</openmensa>
|
||||||
@@ -21,16 +21,32 @@ def _menu():
|
|||||||
return json.load(f)
|
return json.load(f)
|
||||||
|
|
||||||
|
|
||||||
def _expected_feed():
|
def _expected_meta_feed():
|
||||||
with io.open(_resource_path('output.xml'), encoding='utf-8') as f:
|
with io.open(_resource_path('meta_output.xml'), encoding='utf-8') as f:
|
||||||
return f.read()
|
return f.read()
|
||||||
|
|
||||||
|
|
||||||
def test_consistency():
|
def _expected_menu_feed():
|
||||||
|
with io.open(_resource_path('menu_output.xml'), encoding='utf-8') as f:
|
||||||
|
return f.read()
|
||||||
|
|
||||||
|
|
||||||
|
def test_meta_consistency():
|
||||||
|
canteen = _canteen()
|
||||||
|
menu = _menu()
|
||||||
|
menu_feed_url = "canteens/{}/menu".format(canteen.key)
|
||||||
|
|
||||||
|
actual = feed.render_meta(canteen, menu_feed_url)
|
||||||
|
|
||||||
|
expected = _expected_meta_feed()
|
||||||
|
assert expected == actual
|
||||||
|
|
||||||
|
|
||||||
|
def test_menu_consistency():
|
||||||
canteen = _canteen()
|
canteen = _canteen()
|
||||||
menu = _menu()
|
menu = _menu()
|
||||||
|
|
||||||
actual = feed.render(canteen, menu)
|
actual = feed.render_menu(menu)
|
||||||
|
|
||||||
expected = _expected_feed()
|
expected = _expected_menu_feed()
|
||||||
assert expected == actual
|
assert expected == actual
|
||||||
|
|||||||
@@ -27,4 +27,5 @@ requires_online_api = pytest.mark.skipif(
|
|||||||
@requires_online_api
|
@requires_online_api
|
||||||
def test_retrieval(canteen):
|
def test_retrieval(canteen):
|
||||||
menu = download_menu(MenuParams(canteen_id=canteen.id, chash=canteen.chash))
|
menu = download_menu(MenuParams(canteen_id=canteen.id, chash=canteen.chash))
|
||||||
feed.render(canteen, menu)
|
feed.render_meta(canteen, menu)
|
||||||
|
feed.render_menu(canteen, menu)
|
||||||
|
|||||||
Reference in New Issue
Block a user