From 3d4cb8555196a08347e373b6e542f80159155261 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20P=C3=A9rez-Cerezo?= Date: Mon, 3 Sep 2018 09:18:28 +0200 Subject: Cleanup, bump version to 0.4 This version breaks backend compatibility with 0.3.x; it turns the old list-based format into an OrderedDict-based format, sorted by category. This makes the renderers cleaner and easier to write. --- bin/mensa | 2 +- mensa/backends/base.py | 43 --------------------------------- mensa/backends/mathemensa.py | 6 +++-- mensa/backends/satyam.py | 7 +++--- mensa/backends/singh.py | 10 ++++---- mensa/backends/studentenwerk.py | 20 +++++++++------- mensa/base.py | 15 +----------- mensa/frontends/html.py | 53 +++++++++++++++++++---------------------- mensa/frontends/plain-text.py | 32 +++++++++++-------------- mensa/logic.py | 5 ++-- setup.py | 2 +- 11 files changed, 68 insertions(+), 127 deletions(-) delete mode 100644 mensa/backends/base.py diff --git a/bin/mensa b/bin/mensa index 48ecac8..3648607 100755 --- a/bin/mensa +++ b/bin/mensa @@ -69,5 +69,5 @@ restlist = None if args.rest : restlist = args.rest -foodl = logic.get_food(restlist, no_parallel=args.no_parallel, pos=args.pos, rad=args.rad) +foodl = logic.get_food(restlist, no_parallel=args.no_parallel, pos=args.pos, rad=args.rad, only_student_prices=args.student) logic.render(foodl, form, only_veggie=veggie, only_student_prices=args.student, pos=args.pos, dist=args.dist) diff --git a/mensa/backends/base.py b/mensa/backends/base.py deleted file mode 100644 index 6c57336..0000000 --- a/mensa/backends/base.py +++ /dev/null @@ -1,43 +0,0 @@ -# Common classes and methods. - -class Food : - def __init__(self,name, price="", category="Essen", veggie=False, desc=None, ingredients={}) : - self.name = name - self.price = price - self.category = category - self.veggie = veggie - self.desc=desc - self.ingredients=ingredients - -def formt (food) : - cat = [] - vegkeys = [ "", "Vegetarian", "Vegan" ] - r = "" - food.sort(key=lambda foo: foo.category) - for i in food: - if not i.category in cat : - cat.append(i.category) - if not i.category == None : - r=r+ i.category+"\n" - r=r+"\t" + i.name.ljust(80) + "\t"+ i.price.ljust(20) + vegkeys[i.veggie]+"\n" - if i.desc : - r = r+"\t "+i.desc+"\n" - return r - -foodsources = {} - -class Restaurant(object): - def __init__(self, name, human_name, module, optional_args=[], obligatory_args=()): - self.name = name - self.human_name = human_name - self.module = module - self.optional_args = optional_args - self.obligatory_args = obligatory_args - - def get_food(**opt_args) : - self.module.get_food_items(*obligatory_args, **optional_args) - - -def register_restaurant(restaurant): - global foodsources - foodsources[restaurant.name] = (restaurant) diff --git a/mensa/backends/mathemensa.py b/mensa/backends/mathemensa.py index 559956d..6fa93ce 100644 --- a/mensa/backends/mathemensa.py +++ b/mensa/backends/mathemensa.py @@ -10,7 +10,7 @@ import html5lib import datetime from mensa.base import * from yapsy.IPlugin import IPlugin - +from collections import OrderedDict class Mathemensa(IPlugin) : def register_restaurants(self) : r = Restaurant("Mathekantine", "Mathekantine", self, "dummy", pos=(52.51388,13.3235066)) @@ -46,4 +46,6 @@ class Mathemensa(IPlugin) : if "(v)" in name or "Gemüseplatte" in name : veg = 1 fl.append(Food(name, price, "Menü", veg)) - return fl + d = OrderedDict() + d["Menü"] = fl + return d diff --git a/mensa/backends/satyam.py b/mensa/backends/satyam.py index bf18dc5..6d28209 100644 --- a/mensa/backends/satyam.py +++ b/mensa/backends/satyam.py @@ -6,6 +6,7 @@ from mensa.base import * import re import sys from yapsy.IPlugin import IPlugin +from collections import OrderedDict class Satyam(IPlugin): def register_restaurants(self) : @@ -30,9 +31,9 @@ class Satyam(IPlugin): name = name.replace("\\n", "") name = " ".join(name.split()) name = name.replace(price, "") - - return [Food("Mittagstisch Express", price, "Mittagstisch", 2, name[3:-1])] - + k = OrderedDict() + k["Mittagstisch"] = [Food("Mittagstisch Express", price, "Mittagstisch", 2, name[3:-1])] + return k # if __name__ == "__main__": # food = get_food_items() diff --git a/mensa/backends/singh.py b/mensa/backends/singh.py index 393b5da..3e76190 100644 --- a/mensa/backends/singh.py +++ b/mensa/backends/singh.py @@ -7,6 +7,7 @@ import sys import datetime from mensa.base import * from yapsy.IPlugin import IPlugin +from collections import OrderedDict class Signh(IPlugin) : def register_restaurants(self) : @@ -27,7 +28,7 @@ class Signh(IPlugin) : the_page = response.read() document = html5lib.parse(the_page, treebuilder="lxml") groupsel = CSSSelector('.menu-list__items') - myorder=[0,3,1,4,2] + myorder=[0,3,1,4,2] # Weird order for weekdays, due to page layout. mylist = [ groupsel(document)[i] for i in myorder] i = mylist[weekday] fl = [] @@ -48,9 +49,8 @@ class Signh(IPlugin) : veg = 2 fl.append(Food(name, price, "Essen", veg, desc)) sys.stderr = s - return fl + k = OrderedDict() + k["Essen"] = fl + return k -if __name__ == "__main__": - food = get_food_items() - print(formt(food)) diff --git a/mensa/backends/studentenwerk.py b/mensa/backends/studentenwerk.py index 89c45eb..b1f00fd 100644 --- a/mensa/backends/studentenwerk.py +++ b/mensa/backends/studentenwerk.py @@ -9,7 +9,7 @@ from mensa.base import * from yapsy.IPlugin import IPlugin import multiprocessing import datetime - +from collections import OrderedDict from yapsy import NormalizePluginNameForModuleName as normalize mensenliste = {"TU Hardenbergstraße" : ["mensa-tu-hardenbergstra%C3%9Fe", (52.5097684, 13.3259478)], @@ -43,18 +43,20 @@ class Studentenwerk(IPlugin) : for h,n in mensenliste.items() : r = Restaurant(normalize(h), h, self, "dummy", [n[0]], pos=n[1]) register_restaurant(r) - def get_food_items(self, mensa="mensa-tu-hardenbergstra%C3%9Fe", ignore_nudelauswahl=False) : + def get_food_items(self, mensa="mensa-tu-hardenbergstra%C3%9Fe", ignore_nudelauswahl=False, **options) : document = self.fetch_page(mensa) groupsel = CSSSelector('.splGroupWrapper') groups = [e for e in groupsel(document)] - fl = [] - for i in groups : + fl = OrderedDict() + for group in groups : try: - name = CSSSelector('.splGroup')(i)[0].text + category = CSSSelector('.splGroup')(group)[0].text except: - raise NoMenuError from None + raise NoMenuError from None + if not category in fl : + fl[category] = [] sel = CSSSelector('.splMeal') - meals = [e for e in sel(i)] + meals = [e for e in sel(group)] for m in meals : namesel = CSSSelector('.bold') nm = namesel(m)[0].text @@ -68,7 +70,9 @@ class Studentenwerk(IPlugin) : elif "1.png" in pricesel(m)[0][1].attrib["src"] : veg = 1 price = pricesel(m)[-1].text.strip() - fl.append(Food(nm, price, name, veg)) + if "only_student_prices" in options and options["only_student_prices"] : + price = only_student_prices(price) + fl[category].append(Food(nm, price, category, veg)) return fl def get_opening_hours(self, mensa) : #### Rudiment of a function for getting opening hours. Does NOT work yet due to unknown issues. diff --git a/mensa/base.py b/mensa/base.py index 8db5b8c..678fa09 100644 --- a/mensa/base.py +++ b/mensa/base.py @@ -22,20 +22,6 @@ class Renderer(object) : def render(self, foods, **options) : self.module.render(foods, **options) -def formt (food) : - cat = [] - vegkeys = [ "", "Vegetarian", "Vegan" ] - r = "" - food.sort(key=lambda foo: foo.category) - for i in food: - if not i.category in cat : - cat.append(i.category) - if not i.category == None : - r=r+ i.category+"\n" - r=r+"\t" + i.name.ljust(80) + "\t"+ i.price.ljust(20) + vegkeys[i.veggie]+"\n" - if i.desc : - r = r+"\t "+i.desc+"\n" - return r from math import acos, radians, pi, cos, sin def dist(pos1, pos2) : # gives a rough estimate of the distance Accuracy: +/- cos(angle @@ -67,6 +53,7 @@ class Restaurant(object): def get_food(self,**opt_args) : return self.module.get_food_items(*self.obligatory_args, **opt_args) + def register_restaurant(restaurant): global foodsources foodsources[restaurant.name] = restaurant diff --git a/mensa/frontends/html.py b/mensa/frontends/html.py index c23d27c..f3bf065 100644 --- a/mensa/frontends/html.py +++ b/mensa/frontends/html.py @@ -3,38 +3,33 @@ from yapsy.IPlugin import IPlugin from xml.sax.saxutils import escape as esc class HTMLRenderer(IPlugin) : + def format_line(self, item) : + vegkeys = [ "", "Vegetarian", "Vegan" ] + if self.options.get("only_veggie",0) > item.veggie : + return "" + if item.desc : + desc = "
"+esc(item.desc)+"
\n" + else : + desc = "" + return"
  • " + esc(item.name) + ""+ esc(item.price) + ""+ esc(vegkeys[item.veggie])+"\n"+ desc + + def format_category(self, category, items) : + return "

    %s

    " % (esc(category), "".join([self.format_line(i) for i in items])) + def format_restaurant(self, restaurant, food) : + if not food : + return "" + st = "

    %s

    \n" % esc(restaurant.human_name) + dist = "" + if "pos" in self.options and restaurant.pos and self.options.get("dist") : + dist = "
    Distance: %.2f km
    \n" % base.dist(options["pos"], restaurant.pos) + body = "\n".join([self.format_category(cat, it) for cat,it in food.items()]) + return st+dist+body+"
    " def render (self, foods, **options) : ## Expects list of tuples with (Restaurant, Foodlist) - r = "" - vegkeys = [ "", "Vegetarian", "Vegan" ] - for restaurant, food in foods : - cat = [] - if not food : - continue - r = r+"

    "+esc(restaurant.human_name)+"

    "+"\n"#+base.formt(food) - if "pos" in options and restaurant.pos and "dist" in options : - ## display distance to restaurant - r=r+"
    Distance: %.2f km
    \n" % base.dist(options["pos"], restaurant.pos) + self.options = options + + r = "\n".join([self.format_restaurant(restaurant, food) for restaurant, food in foods ]) - food.sort(key=lambda foo: foo.category) - for i in food: - if options["only_student_prices"] : - price = base.only_student_prices(i.price) - else: - price = i.price - if options["only_veggie"] and options["only_veggie"] > i.veggie : - continue - if not i.category in cat : - if cat : - r = r + "" - cat.append(i.category) - if not i.category == None : - r=r+ "

    "+esc(i.category)+"

      \n" - r=r+"
    • " + esc(i.name) + ""+ esc(price) + ""+ esc(vegkeys[i.veggie])+"\n" - if i.desc : - r = r+"
      "+esc(i.desc)+"
      \n" - r = r+"
    " - r = r print(r) def register_renderer(self) : diff --git a/mensa/frontends/plain-text.py b/mensa/frontends/plain-text.py index 36b2a34..8f3f736 100644 --- a/mensa/frontends/plain-text.py +++ b/mensa/frontends/plain-text.py @@ -1,33 +1,29 @@ from mensa import base from yapsy.IPlugin import IPlugin class TextRenderer(IPlugin) : + def render_line(self, item) : + vegkeys = [ "", "Vegetarian", "Vegan" ] + if self.options.get("only_veggie",0) > item.veggie : + return "" + desc = "" + if item.desc : + desc = "\t "+item.desc+"\n" + return "\t" + item.name.ljust(80) + "\t"+ item.price.ljust(20) + vegkeys[item.veggie]+"\n"+desc + def render (self, foods, **options) : + self.options = options ## Expects list of tuples with (Restaurant, Foodlist) r = "" - vegkeys = [ "", "Vegetarian", "Vegan" ] for restaurant, food in foods : cat = [] if not food : continue - r = r+"*"*20+restaurant.human_name+"*"*20+"\n"#+base.formt(food) - if "pos" in options and restaurant.pos and "dist" in options : + r = r+"*"*20+restaurant.human_name+"*"*20+"\n" + if "pos" in options and restaurant.pos and options.get("dist") : ## display distance to restaurant r=r+"Distance: %.2f km\n" % base.dist(options["pos"], restaurant.pos) - food.sort(key=lambda foo: foo.category) - for i in food: - if options["only_student_prices"] : - price = base.only_student_prices(i.price) - else: - price = i.price - if options["only_veggie"] and options["only_veggie"] > i.veggie : - continue - if not i.category in cat : - cat.append(i.category) - if not i.category == None : - r=r+ i.category+"\n" - r=r+"\t" + i.name.ljust(80) + "\t"+ price.ljust(20) + vegkeys[i.veggie]+"\n" - if i.desc : - r = r+"\t "+i.desc+"\n" + + r= r + "".join([category+"\n" + "".join([self.render_line(i) for i in items]) for category,items in food.items()]) print(r) def register_renderer(self) : diff --git a/mensa/logic.py b/mensa/logic.py index 1ae6a96..3089e36 100755 --- a/mensa/logic.py +++ b/mensa/logic.py @@ -4,7 +4,6 @@ from mensa import base import urllib.error import os import sys -from math import acos, radians, pi, cos, sin from yapsy.PluginManager import PluginManager try: import multiprocessing @@ -44,11 +43,11 @@ def get_food(restlist=False, no_parallel=False,**options) : r = [] for k,i in sources : r.append(i) - foodl = get_food_parallel(r, ignore_nudelauswahl=True) + foodl = get_food_parallel(r, ignore_nudelauswahl=True, **options) else : for k,i in sources : try : - food = i.get_food(ignore_nudelauswahl=True) + food = i.get_food(ignore_nudelauswahl=True, **options) foodl.append((i, food)) # print("*"*20+i.human_name+"*"*20+"\n"+base.formt(food)) except base.NoMenuError: diff --git a/setup.py b/setup.py index d461b64..b1c60c1 100644 --- a/setup.py +++ b/setup.py @@ -10,7 +10,7 @@ def read(fname): setup( name = "mensa", - version = "0.3.2", + version = "0.4", author = "Gabriel Pérez-Cerezo", author_email = "gabriel@gpcf.eu", description = ("A program that fetches menus from various restaurants. Pre-installed by default are various cafeterias around TU Berlin."), -- cgit v1.2.3