Reimplementert confirm som meny; mer tegnkodingshakking.

Har nå mulighet for default-valg i confirm (default-en vises med stor
bokstav, som i '(Y/n)', og velges hvis man skriver en tom linje), og
confirm leser input på samme måte som alt annet (via Menu.input_str).

Har laget en funksjon safe_str som prøver å gjøre om et vilkårlig
objekt til noe Python kan printe uten å bli sur.  Tok i bruk denne i
raw_input-kallet i Menu.input_str (det viser seg at raw_input blir
muggen hvis den får et unicode-objekt som inneholder ikke-ASCII-tegn).
This commit is contained in:
Øystein Ingmar Skartsæterhagen 2010-05-11 19:23:52 +00:00
parent 29220ebe3d
commit c2342397eb
2 changed files with 91 additions and 52 deletions

View File

@ -20,56 +20,56 @@ def search_product(string, session):
Product.name.ilike('%'+string+'%'))).all() Product.name.ilike('%'+string+'%'))).all()
return product_list return product_list
def guess_data_type(string): # def guess_data_type(string):
if string.startswith('NTNU'): # if string.startswith('NTNU'):
return 'card' # return 'card'
if string.isdigit(): # if string.isdigit():
return 'bar_code' # return 'bar_code'
if string.isalpha() and string.islower(): # if string.isalpha() and string.islower():
return 'username' # return 'username'
return 'product_name' # return 'product_name'
def retrieve_user(string, session): # def retrieve_user(string, session):
# first = session.query(User).filter(or_(User.name==string, User.card==string)).first() # # first = session.query(User).filter(or_(User.name==string, User.card==string)).first()
search = search_user(string,session) # search = search_user(string,session)
if isinstance(search,User): # if isinstance(search,User):
print "Found user "+search.name # print "Found user "+search.name
return search # return search
else: # else:
if len(search) == 0: # if len(search) == 0:
print "No users found matching your search" # print "No users found matching your search"
return None # return None
if len(search) == 1: # if len(search) == 1:
print "Found one user: "+list[0].name # print "Found one user: "+list[0].name
if confirm(): # if confirm():
return list[0] # return list[0]
else: # else:
return None # return None
else: # else:
print "Found "+str(len(search))+" users:" # print "Found "+str(len(search))+" users:"
return select_from_list(search) # return select_from_list(search)
def confirm(prompt='Confirm? (y/n) '): # def confirm(prompt='Confirm? (y/n) '):
while True: # while True:
input = raw_input(prompt) # input = raw_input(prompt)
if input in ["y","yes"]: # if input in ["y","yes"]:
return True # return True
elif input in ["n","no"]: # elif input in ["n","no"]:
return False # return False
else: # else:
print "Nonsense!" # print "Nonsense!"
def select_from_list(list): # def select_from_list(list):
while True: # while True:
for i in range(len(list)): # for i in range(len(list)):
print i+1, " ) ", list[i].name # print i+1, " ) ", list[i].name
choice = raw_input("Select user :\n") # choice = raw_input("Select user :\n")
if choice in [str(x+1) for x in range(len(list))]: # if choice in [str(x+1) for x in range(len(list))]:
return list[int(choice)-1] # return list[int(choice)-1]
else: # else:
return None # return None
def argmax(d, all=False, value=None): def argmax(d, all=False, value=None):
maxarg = None maxarg = None
@ -85,3 +85,17 @@ def argmax(d, all=False, value=None):
if all: if all:
return filter(lambda k: d[k] == d[maxarg], d.keys()) return filter(lambda k: d[k] == d[maxarg], d.keys())
return maxarg return maxarg
def safe_str(obj):
'''
Ugly hack to avoid Python complaining about encodings.
Call this on any object to turn it into a string which is
(hopefully) safe for printing.
'''
if isinstance(obj, str):
return obj
if isinstance(obj, unicode):
return obj.encode('utf8')
else:
return safe_str(unicode(obj))

View File

@ -35,7 +35,7 @@ class Menu():
print self.exit_disallowed_msg print self.exit_disallowed_msg
return return
if self.exit_confirm_msg != None: if self.exit_confirm_msg != None:
if not confirm(self.exit_confirm_msg): if not self.confirm(self.exit_confirm_msg):
return return
raise ExitMenu() raise ExitMenu()
@ -105,7 +105,7 @@ class Menu():
prompt = self.prompt prompt = self.prompt
while True: while True:
try: try:
result = raw_input(prompt) result = raw_input(safe_str(prompt))
except EOFError: except EOFError:
print 'quit' print 'quit'
self.exit_menu() self.exit_menu()
@ -193,6 +193,9 @@ class Menu():
return 2 return 2
return 1 return 1
def confirm(self, prompt, default=None):
return ConfirmMenu(prompt, default).execute()
def print_header(self): def print_header(self):
print print
print self.header_format % self.name print self.header_format % self.name
@ -248,6 +251,7 @@ product name or barcode.
else: else:
return self.item_value(item_i) return self.item_value(item_i)
class Selector(Menu): class Selector(Menu):
def __init__(self, name, items=[], prompt='select> ', def __init__(self, name, items=[], prompt='select> ',
return_index=True, return_index=True,
@ -269,6 +273,26 @@ class Selector(Menu):
print self.help_text print self.help_text
class ConfirmMenu(Menu):
def __init__(self, prompt='confirm?', default=None):
Menu.__init__(self, 'question', prompt=prompt,
exit_disallowed_msg='Please answer yes or no')
self.default=default
def _execute(self):
options = {True: 'Y/n', False: 'y/N', None: 'y/n'}[self.default]
while True:
result = self.input_str('%s (%s) ' % (self.prompt, options))
if result in ['y','yes']:
return True
if result in ['n','no']:
return False
if self.default != None and result == '':
return self.default
print 'Please answer yes or no'
# class ChargeMenu(Menu): # class ChargeMenu(Menu):
# def __init__(self): # def __init__(self):
# self.name = "Add credits to a user account" # self.name = "Add credits to a user account"
@ -479,7 +503,8 @@ When finished, write an empty line to confirm the purchase.
thing = self.input_thing(empty_input_permitted=True) thing = self.input_thing(empty_input_permitted=True)
if thing == None: if thing == None:
if not self.complete_input(): if not self.complete_input():
if confirm('Not enough information entered. Abort purchase? (y/n) '): if self.confirm('Not enough information entered. Abort purchase?',
default=True):
return False return False
continue continue
break break
@ -607,9 +632,9 @@ def search_ui2(search_str, result, thing, session):
print 'No %ss matching "%s"' % (thing, search_str) print 'No %ss matching "%s"' % (thing, search_str)
return None return None
if len(result) == 1: if len(result) == 1:
msg = 'One %s matching "%s": %s. Use this? (y/n) ' %\ msg = 'One %s matching "%s": %s. Use this?' %\
(thing, search_str, result[0]) (thing, search_str, unicode(result[0]))
if confirm(msg): if ConfirmMenu(msg, default=True).execute():
return result[0] return result[0]
return None return None
limit = 9 limit = 9
@ -640,7 +665,7 @@ main = Menu('Dibbler main menu',
AddProductMenu(), EditProductMenu()]) AddProductMenu(), EditProductMenu()])
], ],
exit_msg='happy happy joy joy', exit_msg='happy happy joy joy',
exit_confirm_msg='Really quit Dibbler? (y/n) ') exit_confirm_msg='Really quit Dibbler?')
if not conf.quit_allowed: if not conf.quit_allowed:
main.exit_disallowed_msg = 'You can check out any time you like, but you can never leave.' main.exit_disallowed_msg = 'You can check out any time you like, but you can never leave.'
while True: while True: