PEP-8 compliance for text-based

This commit is contained in:
Christoffer Viken 2017-02-10 17:09:22 +00:00
parent ba8f80e4aa
commit 4d254c612f
1 changed files with 228 additions and 223 deletions

View File

@ -1,17 +1,17 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sqlalchemy
from sqlalchemy import distinct
from sqlalchemy.sql import func
from sqlalchemy import desc
import re, sys, os, traceback, signal, readline
from select import select
import os
from helpers import *
import random
import re
import sys
import traceback
from select import select
import sqlalchemy
from helpers import *
from sqlalchemy import desc
from sqlalchemy.sql import func
from statistikkHelpers import statisticsTextOnly
from math import ceil
random.seed()
exit_commands = ['exit', 'abort', 'quit', 'bye', 'eat flaming death', 'q']
@ -25,13 +25,14 @@ restart_commands = ['restart']
class ExitMenu(Exception):
pass
class Menu():
def __init__(self, name, items=[], prompt='> ',
class Menu(object):
def __init__(self, name, items=None, prompt='> ',
return_index=True,
exit_msg=None, exit_confirm_msg=None, exit_disallowed_msg=None,
help_text=None, uses_db=False):
self.name = name
self.items = items
self.items = items if items is not None else []
self.prompt = prompt
self.return_index = return_index
self.exit_msg = exit_msg
@ -44,10 +45,10 @@ class Menu():
self.session = None
def exit_menu(self):
if self.exit_disallowed_msg != None:
if self.exit_disallowed_msg is not None:
print self.exit_disallowed_msg
return
if self.exit_confirm_msg != None:
if self.exit_confirm_msg is not None:
if not self.confirm(self.exit_confirm_msg, default=True):
return
raise ExitMenu()
@ -58,7 +59,7 @@ class Menu():
def set_context(self, string, display=True):
self.context = string
if self.context != None and display:
if self.context is not None and display:
print self.context
def add_to_context(self, string):
@ -66,14 +67,14 @@ class Menu():
def printc(self, string):
print string
if self.context == None:
if self.context is None:
self.context = string
else:
self.context += '\n' + string
def show_context(self):
print self.header_format % self.name
if self.context != None:
if self.context is not None:
print self.context
def item_is_submenu(self, i):
@ -96,20 +97,20 @@ class Menu():
def input_str(self, prompt=None, regex=None, length_range=(None, None),
empty_string_is_none=False, timeout=None):
if prompt == None:
if prompt is None:
prompt = self.prompt
if regex != None:
if regex is not None:
while True:
result = self.input_str(prompt, length_range=length_range,
empty_string_is_none=empty_string_is_none)
if result == None or re.match(regex+'$', result):
if result is None or re.match(regex + '$', result):
return result
else:
print 'Value must match regular expression "%s"' % regex
if length_range != (None, None):
while True:
result = self.input_str(prompt, empty_string_is_none=empty_string_is_none)
if result == None:
if result is None:
length = 0
else:
length = len(result)
@ -125,7 +126,8 @@ class Menu():
return result
while True:
try:
result = None
# result = None
# It is replaced either way
if timeout:
# assuming line buffering
sys.stdout.write(safe_str(prompt))
@ -166,18 +168,18 @@ class Menu():
return None
return result
def special_input_choice(self, str):
'''
def special_input_choice(self, in_str):
"""
Handle choices which are not simply menu items.
Override this in subclasses to implement magic menu
choices. Return True if str was some valid magic menu
choice, False otherwise.
'''
"""
return False
def input_choice(self, number_of_choices, prompt=None):
if prompt == None:
if prompt is None:
prompt = self.prompt
while True:
result = self.input_str(prompt)
@ -198,18 +200,18 @@ class Menu():
else:
if result.isdigit():
choice = int(result)
if (choice == 0 and 10 <= number_of_choices):
if choice == 0 and 10 <= number_of_choices:
return 10
if (choice > 0 and choice <= number_of_choices):
if choice > 0 and choice <= number_of_choices:
return choice
if not self.special_input_choice(result):
self.invalid_menu_choice(result)
def invalid_menu_choice(self, str):
def invalid_menu_choice(self, in_str):
print 'Please enter a valid choice.'
def input_int(self, prompt=None, allowed_range=(None, None), null_allowed=False, default=None):
if prompt == None:
if prompt is None:
prompt = self.prompt
if default is not None:
prompt += ("[%s] " % default)
@ -237,7 +239,7 @@ class Menu():
def input_user(self, prompt=None):
user = None
while user == None:
while user is None:
user = self.retrieve_user(self.input_str(prompt))
return user
@ -246,7 +248,7 @@ class Menu():
def input_product(self, prompt=None):
product = None
while product == None:
while product is None:
product = self.retrieve_product(self.input_str(prompt))
return product
@ -256,7 +258,7 @@ class Menu():
def input_thing(self, prompt=None, permitted_things=('user', 'product'),
add_nonexisting=(), empty_input_permitted=False, find_hidden_products=True):
result = None
while result == None:
while result is None:
search_str = self.input_str(prompt)
if search_str == '' and empty_input_permitted:
return None
@ -266,7 +268,8 @@ class Menu():
def input_multiple(self, prompt=None, permitted_things=('user', 'product'),
add_nonexisting=(), empty_input_permitted=False, find_hidden_products=True):
result = None
while result == None:
num = 0
while result is None:
search_str = self.input_str(prompt)
search_lst = search_str.split(" ")
if search_str == '' and empty_input_permitted:
@ -275,17 +278,17 @@ class Menu():
result = self.search_for_thing(search_str, permitted_things, add_nonexisting, find_hidden_products)
num = 1
if (result == None) and (len(search_lst) > 1):
if (result is None) and (len(search_lst) > 1):
print 'Interpreting input as "<number> <product>"'
try:
num = int(search_lst[0])
result = self.search_for_thing(" ".join(search_lst[1:]), permitted_things,add_nonexisting, find_hidden_products)
result = self.search_for_thing(" ".join(search_lst[1:]), permitted_things, add_nonexisting,
find_hidden_products)
# Her kan det legges inn en except ValueError,
# men da blir det fort mye plaging av brukeren
except Exception as e:
print(e)
return (result,num)
return result, num
def search_for_thing(self, search_str, permitted_things=('user', 'product'),
add_nonexisting=(), find_hidden_products=True):
@ -297,18 +300,18 @@ class Menu():
results[thing] = search_fun[thing](search_str, self.session, find_hidden_products)
result_values[thing] = self.search_result_value(results[thing])
selected_thing = argmax(result_values)
if results[selected_thing] == []:
if not results[selected_thing]:
thing_for_type = {'card': 'user', 'username': 'user',
'bar_code': 'product', 'rfid': 'rfid'}
type_guess = guess_data_type(search_str)
if type_guess != None and thing_for_type[type_guess] in add_nonexisting:
if type_guess is not None and thing_for_type[type_guess] in add_nonexisting:
return self.search_add(search_str)
# print 'No match found for "%s".' % search_str
return None
return self.search_ui2(search_str, results[selected_thing], selected_thing)
def search_result_value(self, result):
if result == None:
if result is None:
return 0
if not isinstance(result, list):
return 3
@ -349,7 +352,6 @@ class Menu():
print '"%s" looks like the bar code for a product, but no such product exists.' % string
return None
def search_ui(self, search_fun, search_str, thing):
result = search_fun(search_str, self.session)
return self.search_ui2(search_str, result, thing)
@ -379,13 +381,11 @@ class Menu():
return_index=False)
return selector.execute()
def confirm(self, prompt, default=None, timeout=None):
return ConfirmMenu(prompt, default, timeout).execute()
def print_header(self):
print
print ""
print self.header_format % self.name
def pause(self):
@ -416,10 +416,10 @@ it by putting money in the box and using the "Adjust credit" menu.
'''
def local_help(self):
if self.help_text == None:
if self.help_text is None:
print 'no help here'
else:
print
print ''
print 'Help for %s:' % (self.header_format % self.name)
print self.help_text
@ -433,11 +433,11 @@ it by putting money in the box and using the "Adjust credit" menu.
self.at_exit()
return None
finally:
if self.session != None:
if self.session is not None:
self.session.close()
self.session = None
def _execute(self):
def _execute(self, **kwargs):
line_format = '%' + str(len(str(len(self.items)))) + 'd ) %s'
while True:
self.print_header()
@ -456,10 +456,10 @@ it by putting money in the box and using the "Adjust credit" menu.
class Selector(Menu):
def __init__(self, name, items=[], prompt='select> ',
return_index=True,
exit_msg=None, exit_confirm_msg=None,
def __init__(self, name, items=None, prompt='select> ', return_index=True, exit_msg=None, exit_confirm_msg=None,
help_text=None):
if items is None:
items = []
Menu.__init__(self, name, items, prompt, return_index, exit_msg)
self.header_format = '%s'
@ -467,11 +467,11 @@ class Selector(Menu):
print self.header_format % self.name
def local_help(self):
if self.help_text == None:
if self.help_text is None:
print 'This is a selection menu. Enter one of the listed numbers, or'
print '\'exit\' to go out and do something else.'
else:
print
print ''
print 'Help for selector (%s):' % self.name
print self.help_text
@ -492,7 +492,7 @@ class ConfirmMenu(Menu):
return True
elif result in ['n', 'no']:
return False
elif self.default != None and result == '':
elif self.default is not None and result == '':
return self.default
else:
print 'Please answer yes or no'
@ -506,7 +506,7 @@ class MessageMenu(Menu):
def _execute(self):
self.print_header()
print
print ''
print self.message
if self.pause_after_message:
self.pause()
@ -608,7 +608,6 @@ class FAQMenu(Menu):
''')]
class TransferMenu(Menu):
def __init__(self):
Menu.__init__(self, 'Transfer credit between users',
@ -676,7 +675,7 @@ user, then rfid (write an empty line to remove the card number or rfid).
user = self.input_user('User> ')
self.printc('Editing user %s' % user.name)
card_str = '"%s"' % user.card
if user.card == None:
if user.card is None:
card_str = 'empty'
user.card = self.input_str('Card number (currently %s)> ' % card_str,
User.card_re, (0, 10),
@ -685,7 +684,7 @@ user, then rfid (write an empty line to remove the card number or rfid).
user.card = user.card.lower()
rfid_str = '"%s"' % user.rfid
if user.rfid == None:
if user.rfid is None:
rfid_str = 'empty'
user.rfid = self.input_str('RFID (currently %s)> ' % rfid_str,
User.rfid_re, (0, 10),
@ -749,7 +748,7 @@ class EditProductMenu(Menu):
print 'Could not store product %s: %s' % (product.name, e)
self.pause()
return
elif what == None:
elif what is None:
print 'Edit aborted'
return
else:
@ -768,7 +767,8 @@ class ShowUserMenu(Menu):
print 'RFID: %s' % user.rfid
print 'Credit: %s kr' % user.credit
selector = Selector('What do you want to know about %s?' % user.name,
items=[('transactions', 'Recent transactions (List of last ' + str(conf.user_recent_transaction_limit) + ')'),
items=[('transactions', 'Recent transactions (List of last ' + str(
conf.user_recent_transaction_limit) + ')'),
('products', 'Which products %s has bought, and how many' % user.name),
('transactions-all', 'Everything (List of all transactions)')])
what = selector.execute()
@ -832,7 +832,7 @@ class ShowUserMenu(Menu):
products.append((product, count))
num_products = len(products)
if num_products == 0:
print('No products purchased yet')
print 'No products purchased yet'
else:
text = ''
text += 'Products purchased:\n'
@ -877,6 +877,7 @@ addition, and you can type 'what' at any time to redisplay it.
When finished, write an empty line to confirm the purchase.
'''
def credit_check(self, user):
"""
@ -893,7 +894,7 @@ When finished, write an empty line to confirm the purchase.
print "***********************************************************************"
print "***********************************************************************"
print
print ""
print "$$\ $$\ $$$$$$\ $$$$$$$\ $$\ $$\ $$$$$$\ $$\ $$\ $$$$$$\\"
print "$$ | $\ $$ |$$ __$$\ $$ __$$\ $$$\ $$ |\_$$ _|$$$\ $$ |$$ __$$\\"
print "$$ |$$$\ $$ |$$ / $$ |$$ | $$ |$$$$\ $$ | $$ | $$$$\ $$ |$$ / \__|"
@ -902,14 +903,14 @@ When finished, write an empty line to confirm the purchase.
print "$$$ / \$$$ |$$ | $$ |$$ | $$ |$$ |\$$$ | $$ | $$ |\$$$ |$$ | $$ |"
print "$$ / \$$ |$$ | $$ |$$ | $$ |$$ | \$$ |$$$$$$\ $$ | \$$ |\$$$$$$ |"
print "\__/ \__|\__| \__|\__| \__|\__| \__|\______|\__| \__| \______/"
print
print ""
print "***********************************************************************"
print "***********************************************************************"
print
print ""
print "USER %s HAS LOWER CREDIT THAN %d." % (user.name, conf.low_credit_warning_limit)
print "THIS PURCHASE WILL CHARGE YOUR CREDIT TWICE AS MUCH."
print "CONSIDER PUTTING MONEY IN THE BOX TO AVOID THIS."
print
print ""
print "Do you want to continue with this purchase?"
if timeout:
@ -918,7 +919,6 @@ When finished, write an empty line to confirm the purchase.
else:
return self.confirm(prompt=">", default=True)
def add_thing_to_purchase(self, thing):
if isinstance(thing, User):
if thing.is_anonymous():
@ -938,18 +938,20 @@ When finished, write an empty line to confirm the purchase.
PurchaseEntry(self.purchase, thing, 1)
return True
def _execute(self, initialContents=[]):
def _execute(self, initial_contents=None):
self.print_header()
self.purchase = Purchase()
self.exit_confirm_msg = None
self.superfast_mode = False
for thing in initialContents:
if initial_contents is None:
initial_contents = []
for thing in initial_contents:
self.add_thing_to_purchase(thing)
isproduct = lambda t: isinstance(t, Product)
if len(initialContents) > 0 and all(map(isproduct, initialContents)):
if len(initial_contents) > 0 and all(map(isproduct, initial_contents)):
self.superfast_mode = True
print '***********************************************'
print '****** Buy menu is in SUPERFASTmode[tm]! ******'
@ -972,7 +974,7 @@ When finished, write an empty line to confirm the purchase.
find_hidden_products=False)
# Possibly exit from the menu:
if thing == None:
if thing is None:
if not self.complete_input():
if self.confirm('Not enough information entered. Abort purchase?',
default=True):
@ -1006,8 +1008,8 @@ When finished, write an empty line to confirm the purchase.
if not t.user.is_anonymous():
print 'User %s\'s credit is now %d kr' % (t.user.name, t.user.credit)
if t.user.credit < conf.low_credit_warning_limit:
print ('USER %s HAS LOWER CREDIT THAN %d, AND SHOULD CONSIDER PUTTING SOME MONEY IN THE BOX.'
% (t.user.name, conf.low_credit_warning_limit))
print 'USER %s HAS LOWER CREDIT THAN %d, AND SHOULD CONSIDER PUTTING SOME MONEY IN THE BOX.'\
% (t.user.name, conf.low_credit_warning_limit)
# skriver til log
# print Product.price
# with open("dibbler-out.txt", "a") as f:
@ -1029,7 +1031,8 @@ When finished, write an empty line to confirm the purchase.
if len(transactions) == 0:
string += '(empty)'
else:
string += ', '.join(map(lambda t: t.user.name + ("*" if t.user.credit < conf.user_recent_transaction_limit else ""),
string += ', '.join(
map(lambda t: t.user.name + ("*" if t.user.credit < conf.user_recent_transaction_limit else ""),
transactions))
string += '\n products: '
if len(entries) == 0:
@ -1045,15 +1048,17 @@ When finished, write an empty line to confirm the purchase.
string += '\n total price: %d kr' % self.purchase.price
if any(t.penalty > 1 for t in transactions):
string += '\n *total with penalty: %d kr' % sum(self.purchase.price_per_transaction() * t.penalty for t in transactions)
string += '\n *total with penalty: %d kr' % sum(
self.purchase.price_per_transaction() * t.penalty for t in transactions)
return string
def print_purchase(self):
info = self.format_purchase()
if info != None:
if info is not None:
self.set_context(info)
class AdjustStockMenu(Menu):
def __init__(self):
Menu.__init__(self, 'Adjust stock', uses_db=True)
@ -1062,7 +1067,6 @@ class AdjustStockMenu(Menu):
self.print_header()
product = self.input_product('Product> ')
print 'The stock of this product is: %d ' % (product.stock)
print 'Write the number of products you have added to the stock'
print 'Alternatively, correct the stock for any mistakes'
@ -1109,7 +1113,6 @@ class CleanupStockMenu(Menu):
if oldstock != product.stock:
changed_products.append((product, oldstock))
try:
self.session.commit()
print 'New stocks are now stored.'
@ -1123,7 +1126,6 @@ class CleanupStockMenu(Menu):
print p[0].name, ".", p[1], "->", p[0].stock
class AdjustCreditMenu(Menu): # reimplements ChargeMenu; these should be combined to one
def __init__(self):
Menu.__init__(self, 'Adjust credit', uses_db=True)
@ -1205,7 +1207,7 @@ class ProductPopularityMenu(Menu):
self.session.query(Product, sub.c.purchase_count) \
.outerjoin((sub, Product.product_id == sub.c.product_id)) \
.order_by(desc(sub.c.purchase_count)) \
.filter(sub.c.purchase_count != None) \
.filter(sub.c.purchase_count is not None) \
.all()
line_format = '%10s | %-' + str(Product.name_length) + 's\n'
text += line_format % ('items sold', 'product')
@ -1214,6 +1216,7 @@ class ProductPopularityMenu(Menu):
text += line_format % (number, product.name)
less(text)
class ProductRevenueMenu(Menu):
def __init__(self):
Menu.__init__(self, 'Products by revenue', uses_db=True)
@ -1230,7 +1233,7 @@ class ProductRevenueMenu(Menu):
self.session.query(Product, sub.c.purchase_count) \
.outerjoin((sub, Product.product_id == sub.c.product_id)) \
.order_by(desc(sub.c.purchase_count * Product.price)) \
.filter(sub.c.purchase_count != None) \
.filter(sub.c.purchase_count is not None) \
.all()
line_format = '%7s | %10s | %5s | %-' + str(Product.name_length) + 's\n'
text += line_format % ('revenue', 'items sold', 'price', 'product')
@ -1239,6 +1242,7 @@ class ProductRevenueMenu(Menu):
text += line_format % (number * product.price, number, product.price, product.name)
less(text)
class BalanceMenu(Menu):
def __init__(self):
Menu.__init__(self, 'Total balance of PVVVV', uses_db=True)
@ -1246,7 +1250,7 @@ class BalanceMenu(Menu):
def _execute(self):
self.print_header()
text = ''
total_value = 0;
total_value = 0
product_list = self.session.query(Product).all()
for p in product_list:
total_value += p.stock * p.price
@ -1261,12 +1265,16 @@ class BalanceMenu(Menu):
text += 24 * '-' + '\n'
text += line_format % ('Total balance', total_balance)
less(text)
class LoggedStatisticsMenu(Menu):
def __init__(self):
Menu.__init__(self, 'Statistics from log', uses_db=True)
def _execute(self):
statisticsTextOnly()
def restart():
# Does not work if the script is not executable, or if it was
# started by searching $PATH.
@ -1280,21 +1288,19 @@ if not conf.stop_allowed:
signal.signal(signal.SIGTSTP, signal.SIG_IGN)
class MainMenu(Menu):
def special_input_choice(self, str):
def special_input_choice(self, in_str):
buy_menu = BuyMenu(Session())
thing = buy_menu.search_for_thing(str)
thing = buy_menu.search_for_thing(in_str)
if thing:
buy_menu.execute(initialContents=[thing])
print
self.show_context()
print self.show_context()
return True
return False
def invalid_menu_choice(self, str):
print
self.show_context()
def invalid_menu_choice(self, in_str):
print self.show_context()
class AddStockMenu(Menu):
def __init__(self):
@ -1322,14 +1328,16 @@ much money you're due in credits for the purchase when prompted.
thing_price = 0
# Read in a 'thing' (product or user):
line = self.input_multiple(add_nonexisting=('user','product'), empty_input_permitted=True, find_hidden_products=False)
line = self.input_multiple(add_nonexisting=('user', 'product'), empty_input_permitted=True,
find_hidden_products=False)
if line:
(thing, amount) = line
if isinstance(thing, Product):
self.printc("%d of %s registered" % (amount, thing.name))
thing_price = self.input_int('What did you pay a piece? ', (1,100000), default=thing.price) * amount
thing_price = self.input_int('What did you pay a piece? ', (1, 100000),
default=thing.price) * amount
self.price += thing_price
# once we get something in the
@ -1372,7 +1380,6 @@ much money you're due in credits for the purchase when prompted.
print('%' + str(-Product.name_length) + 's %5i') % (product.name, self.products[product][0])
print(6 + Product.name_length) * '-'
def add_thing_to_pending(self, thing, amount, price):
if isinstance(thing, User):
if self.user:
@ -1414,8 +1421,6 @@ much money you're due in credits for the purchase when prompted.
print 'Could not perform transaction: %s' % e
main = MainMenu('Dibbler main menu',
items=[BuyMenu(),
ProductListMenu(),
@ -1447,11 +1452,11 @@ while True:
try:
main.execute()
except KeyboardInterrupt:
print
print ''
print 'Interrupted.'
except:
print 'Something went wrong.'
print '%s: %s' % sys.exc_info()[0:2]
print '%s: %s' % sys.exc_info()[0], sys.exc_info()[1]
if conf.show_tracebacks:
traceback.print_tb(sys.exc_info()[2])
else: