From 5adf85ab65ef7d083a351020877399a487d825b194b4911de24101291ff1e7b2 Mon Sep 17 00:00:00 2001 From: Kai Fabian Date: Mon, 22 Oct 2018 09:16:14 +0200 Subject: [PATCH] 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. --- stw_potsdam/canteen.py | 2 +- stw_potsdam/config.py | 3 +- stw_potsdam/feed.py | 23 +++++--- stw_potsdam/views.py | 55 +++++++++++++++++-- .../resources/{output.xml => menu_output.xml} | 3 - tests/resources/meta_output.xml | 12 ++++ tests/test_consistency.py | 26 +++++++-- tests/test_retrieval.py | 3 +- 8 files changed, 101 insertions(+), 26 deletions(-) rename tests/resources/{output.xml => menu_output.xml} (99%) create mode 100644 tests/resources/meta_output.xml diff --git a/stw_potsdam/canteen.py b/stw_potsdam/canteen.py index c656f5f..e716e0c 100644 --- a/stw_potsdam/canteen.py +++ b/stw_potsdam/canteen.py @@ -2,4 +2,4 @@ from collections import namedtuple -Canteen = namedtuple('Canteen', ('name', 'street', 'city', 'id', 'chash')) +Canteen = namedtuple('Canteen', ('key', 'name', 'street', 'city', 'id', 'chash')) diff --git a/stw_potsdam/config.py b/stw_potsdam/config.py index eacf207..8dd3fef 100644 --- a/stw_potsdam/config.py +++ b/stw_potsdam/config.py @@ -17,7 +17,8 @@ def _get_config(filename): def _parse_canteen(config, canteen_name): get = partial(config.get, canteen_name) - return Canteen(name=get('name'), + return Canteen(key=canteen_name, + name=get('name'), street=get('street'), city=get('city'), id=get('id'), diff --git a/stw_potsdam/feed.py b/stw_potsdam/feed.py index 2bd2d69..443ba46 100644 --- a/stw_potsdam/feed.py +++ b/stw_potsdam/feed.py @@ -2,6 +2,7 @@ from pyopenmensa.feed import LazyBuilder + PRICE_ROLE_MAPPING = { 'student': 'preis_s', 'other': 'preis_g', @@ -48,18 +49,22 @@ def _process_day(builder, day): roles=None) -def _create_builder(canteen): +def render_menu(menu): 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): _process_day(builder, day) 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() diff --git a/stw_potsdam/views.py b/stw_potsdam/views.py index 081f314..4152676 100644 --- a/stw_potsdam/views.py +++ b/stw_potsdam/views.py @@ -1,6 +1,9 @@ # -*- 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 import feed @@ -10,6 +13,16 @@ from canteen_api import MenuParams, download_menu CACHE_TIMEOUT = 45 * 60 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() @@ -37,15 +50,37 @@ def get_menu(canteen, params): return menu -def canteen_feed_xml(canteen, menu): - xml = feed.render(canteen, menu) +def _canteen_feed_xml(xml): response = make_response(xml) response.mimetype = 'text/xml' return response -@app.route('/canteen/') -def canteen_feed(canteen_name): +def canteen_menu_feed_xml(menu): + 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/') +@app.route('/canteens//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//menu') +def canteen_menu_feed(canteen_name): config = read_canteen_config() if canteen_name not in config: @@ -53,7 +88,15 @@ def canteen_feed(canteen_name): canteen = config[canteen_name] 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') def health_check(): diff --git a/tests/resources/output.xml b/tests/resources/menu_output.xml similarity index 99% rename from tests/resources/output.xml rename to tests/resources/menu_output.xml index a0681cd..5a776fe 100644 --- a/tests/resources/output.xml +++ b/tests/resources/menu_output.xml @@ -1,9 +1,6 @@ - Mensa Griebnitzsee -
August-Bebel-Straße 69, Haus 6
- 14482 Potsdam diff --git a/tests/resources/meta_output.xml b/tests/resources/meta_output.xml new file mode 100644 index 0000000..ba6438a --- /dev/null +++ b/tests/resources/meta_output.xml @@ -0,0 +1,12 @@ + + + + Mensa Griebnitzsee +
August-Bebel-Straße 69, Haus 6
+ 14482 Potsdam + + + canteens/griebnitzsee/menu + +
+
diff --git a/tests/test_consistency.py b/tests/test_consistency.py index 1af2579..9d0c21b 100644 --- a/tests/test_consistency.py +++ b/tests/test_consistency.py @@ -21,16 +21,32 @@ def _menu(): return json.load(f) -def _expected_feed(): - with io.open(_resource_path('output.xml'), encoding='utf-8') as f: +def _expected_meta_feed(): + with io.open(_resource_path('meta_output.xml'), encoding='utf-8') as f: 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() menu = _menu() - actual = feed.render(canteen, menu) + actual = feed.render_menu(menu) - expected = _expected_feed() + expected = _expected_menu_feed() assert expected == actual diff --git a/tests/test_retrieval.py b/tests/test_retrieval.py index 58b6726..2f0d183 100644 --- a/tests/test_retrieval.py +++ b/tests/test_retrieval.py @@ -27,4 +27,5 @@ requires_online_api = pytest.mark.skipif( @requires_online_api def test_retrieval(canteen): 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)