Convert most strings to fstrings for readability

Some are kept as-is because they wouldn't be more readable, or do insanity that i cannot bother deciphering right now
This commit is contained in:
Robert Maikher 2018-08-23 13:15:45 +02:00
parent 068015a972
commit d5475b834f
9 changed files with 128 additions and 118 deletions

9
db.py
View File

@ -32,7 +32,7 @@ class User(Base):
self.credit = credit self.credit = credit
def __repr__(self): def __repr__(self):
return "<User('%s')>" % self.name return f"<User('{self.name}')>"
def __str__(self): def __str__(self):
return self.name return self.name
@ -63,8 +63,7 @@ class Product(Base):
self.hidden = hidden self.hidden = hidden
def __repr__(self): def __repr__(self):
return "<Product('%s', '%s', '%s', '%s', '%s')>" %\ return f"<Product('{self.name}', '{self.bar_code}', '{self.price}', '{self.stock}', '{self.hidden}')>"
(self.name, self.bar_code, self.price, self.stock, self.hidden)
def __str__(self): def __str__(self):
return self.name return self.name
@ -97,7 +96,7 @@ class PurchaseEntry(Base):
self.amount = amount self.amount = amount
def __repr__(self): def __repr__(self):
return "<PurchaseEntry('%s', '%s')>" % (self.product.name, self.amount) return f"<PurchaseEntry('{self.product.name}', '{self.amount}')>"
class Transaction(Base): class Transaction(Base):
@ -141,7 +140,7 @@ class Purchase(Base):
pass pass
def __repr__(self): def __repr__(self):
return "<Purchase(%d, %d, '%s')>" % (int(self.id), self.price, self.time.strftime('%c')) return f"<Purchase({int(self.id):d}, {self.price:d}, '{self.time.strftime('%c')}')>"
def is_complete(self): def is_complete(self):
return len(self.transactions) > 0 and len(self.entries) > 0 return len(self.transactions) > 0 and len(self.entries) > 0

View File

@ -5,30 +5,30 @@ import subprocess
import os import os
import signal import signal
def search_user(string, session, ignorethisflag=None): def search_user(str, session, ignorethisflag=None):
string = string.lower() str = str.lower()
exact_match = session.query(User).filter(or_(User.name==string, User.card==string, User.rfid==string)).first() exact_match = session.query(User).filter(or_(User.name == str, User.card == str, User.rfid == str)).first()
if exact_match: if exact_match:
return exact_match return exact_match
user_list = session.query(User).filter(or_(User.name.ilike('%'+string+'%'), user_list = session.query(User).filter(or_(User.name.ilike(f'%{str}%'),
User.card.ilike('%'+string+'%'), User.card.ilike(f'%{str}%'),
User.rfid.ilike('%'+string+'%'))).all() User.rfid.ilike(f'%{str}%'))).all()
return user_list return user_list
def search_product(string, session, find_hidden_products=True): def search_product(str, session, find_hidden_products=True):
if find_hidden_products: if find_hidden_products:
exact_match = session.query(Product).filter(or_(Product.bar_code==string, Product.name==string)).first() exact_match = session.query(Product).filter(or_(Product.bar_code == str, Product.name == str)).first()
else: else:
exact_match = session.query(Product).filter(or_(Product.bar_code==string, exact_match = session.query(Product).filter(or_(Product.bar_code == str,
and_(Product.name==string, Product.hidden == False))).first() and_(Product.name == str, Product.hidden == False))).first()
if exact_match: if exact_match:
return exact_match return exact_match
if find_hidden_products: if find_hidden_products:
product_list = session.query(Product).filter(or_(Product.bar_code.ilike('%'+string+'%'), product_list = session.query(Product).filter(or_(Product.bar_code.ilike(f'%{str}%'),
Product.name.ilike('%'+string+'%'))).all() Product.name.ilike(f'%{str}%'))).all()
else: else:
product_list = session.query(Product).filter(or_(Product.bar_code.ilike('%' + string + '%'), product_list = session.query(Product).filter(or_(Product.bar_code.ilike(f'%{str}%'),
and_(Product.name.ilike('%' + string + '%'), and_(Product.name.ilike(f'%{str}%'),
Product.hidden == False))).all() Product.hidden == False))).all()
return product_list return product_list

View File

@ -6,4 +6,4 @@ session=Session()
slabbedasker=session.query(User).filter(User.credit<0).all() slabbedasker=session.query(User).filter(User.credit<0).all()
for slubbert in slabbedasker: for slubbert in slabbedasker:
print("%s, %s" % (slubbert.name, slubbert.credit)) print(f"{slubbert.name}, {slubbert.credit}")

View File

@ -64,7 +64,7 @@ if __name__ == '__main__':
print('Interrupted.') print('Interrupted.')
except: except:
print('Something went wrong.') print('Something went wrong.')
print('%s: %s' % (sys.exc_info()[0], sys.exc_info()[1])) print(f'{sys.exc_info()[0]}: {sys.exc_info()[1]}')
if conf.show_tracebacks: if conf.show_tracebacks:
traceback.print_tb(sys.exc_info()[2]) traceback.print_tb(sys.exc_info()[2])
else: else:

View File

@ -41,7 +41,7 @@ much money you're due in credits for the purchase when prompted.\n'''
(thing, amount) = line (thing, amount) = line
if isinstance(thing, Product): if isinstance(thing, Product):
self.printc("%d of %s registered" % (amount, thing.name)) self.printc(f"{amount:d} of {thing.name} registered")
thing_price = self.input_int('What did you pay a piece? ', (1, 100000), thing_price = self.input_int('What did you pay a piece? ', (1, 100000),
default=thing.price) * amount default=thing.price) * amount
self.price += thing_price self.price += thing_price
@ -65,6 +65,7 @@ much money you're due in credits for the purchase when prompted.\n'''
def complete_input(self): def complete_input(self):
return bool(self.users) and len(self.products) and self.price return bool(self.users) and len(self.products) and self.price
# TODO: Rewrite this madness
def print_info(self): def print_info(self):
print((6 + Product.name_length) * '-') print((6 + Product.name_length) * '-')
if self.price: if self.price:
@ -72,7 +73,7 @@ much money you're due in credits for the purchase when prompted.\n'''
if self.users: if self.users:
print("Users to credit:") print("Users to credit:")
for user in self.users: for user in self.users:
print(" %s" % str(user.name)) print(f" {str(user.name)}")
print("\n{{0:s}}{{1:>{0}s}}".format(Product.name_length-1).format("Product", "Amount")) print("\n{{0:s}}{{1:>{0}s}}".format(Product.name_length-1).format("Product", "Amount"))
print((6 + Product.name_length) * '-') print((6 + Product.name_length) * '-')
if len(self.products): if len(self.products):
@ -94,6 +95,7 @@ much money you're due in credits for the purchase when prompted.\n'''
print('Did you pay a different price?') print('Did you pay a different price?')
if self.confirm('>', default=False): if self.confirm('>', default=False):
price = self.input_int('How much did you pay?', default=self.price) price = self.input_int('How much did you pay?', default=self.price)
# TODO: Loop until we get a valid answer instead of assuming default
if price > self.price: if price > self.price:
print('Illegal action, total can not be higher than your total.') print('Illegal action, total can not be higher than your total.')
else: else:
@ -109,9 +111,9 @@ much money you're due in credits for the purchase when prompted.\n'''
product.price = int(ceil(float(value) / (max(product.stock, 0) + self.products[product][0]))) product.price = int(ceil(float(value) / (max(product.stock, 0) + self.products[product][0])))
product.stock = max(self.products[product][0], product.stock + self.products[product][0]) product.stock = max(self.products[product][0], product.stock + self.products[product][0])
product.hidden = False product.hidden = False
print("New stock for %s: %d" % (product.name, product.stock), \ print(f"New stock for {product.name}: {product.stock:d}",
("- New price: " + str(product.price) if old_price != product.price else ""), \ f"- New price: {product.price}" if old_price != product.price else "",
("- Removed hidden status" if old_hidden != product.hidden else "")) "- Removed hidden status" if old_hidden != product.hidden else "")
purchase = Purchase() purchase = Purchase()
for user in self.users: for user in self.users:
@ -127,6 +129,6 @@ much money you're due in credits for the purchase when prompted.\n'''
print("Success! Transaction performed:") print("Success! Transaction performed:")
# self.print_info() # self.print_info()
for user in self.users: for user in self.users:
print("User %s's credit is now %i" % (user.name, user.credit)) print(f"User {user.name}'s credit is now {user.credit:d}")
except sqlalchemy.exc.SQLAlchemyError as e: except sqlalchemy.exc.SQLAlchemyError as e:
print('Could not perform transaction: %s' % e) print(f'Could not perform transaction: {e}')

View File

@ -49,7 +49,7 @@ When finished, write an empty line to confirm the purchase.\n'''
print("***********************************************************************") print("***********************************************************************")
print("***********************************************************************") print("***********************************************************************")
print("") print("")
print("USER %s HAS LOWER CREDIT THAN %d." % (user.name, conf.low_credit_warning_limit)) print(f"USER {user.name} HAS LOWER CREDIT THAN {conf.low_credit_warning_limit:d}.")
print("THIS PURCHASE WILL CHARGE YOUR CREDIT TWICE AS MUCH.") print("THIS PURCHASE WILL CHARGE YOUR CREDIT TWICE AS MUCH.")
print("CONSIDER PUTTING MONEY IN THE BOX TO AVOID THIS.") print("CONSIDER PUTTING MONEY IN THE BOX TO AVOID THIS.")
print("") print("")
@ -149,16 +149,16 @@ When finished, write an empty line to confirm the purchase.\n'''
try: try:
self.session.commit() self.session.commit()
except sqlalchemy.exc.SQLAlchemyError as e: except sqlalchemy.exc.SQLAlchemyError as e:
print('Could not store purchase: %s' % e) print(f'Could not store purchase: {e}')
else: else:
print('Purchase stored.') print('Purchase stored.')
self.print_purchase() self.print_purchase()
for t in self.purchase.transactions: for t in self.purchase.transactions:
if not t.user.is_anonymous(): if not t.user.is_anonymous():
print('User %s\'s credit is now %d kr' % (t.user.name, t.user.credit)) print(f"User {t.user.name}'s credit is now {t.user.credit:d} kr")
if t.user.credit < conf.low_credit_warning_limit: 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.' \ print(f'USER {t.user.name} HAS LOWER CREDIT THAN {conf.low_credit_warning_limit:d},',
% (t.user.name, conf.low_credit_warning_limit)) 'AND SHOULD CONSIDER PUTTING SOME MONEY IN THE BOX.')
return True return True
@ -183,15 +183,17 @@ When finished, write an empty line to confirm the purchase.\n'''
string += '(empty)' string += '(empty)'
else: else:
string += "\n " string += "\n "
string += '\n '.join(['%dx %s (%d kr)' % (e.amount, e.product.name, e.product.price) for e in entries]) string += '\n '.join([f'{e.amount:d}x {e.product.name} ({e.product.price:d} kr)' for e in entries])
if len(transactions) > 1: if len(transactions) > 1:
string += '\n price per person: %d kr' % self.purchase.price_per_transaction() string += f'\n price per person: {self.purchase.price_per_transaction():d} kr'
if any(t.penalty > 1 for t in transactions): if any(t.penalty > 1 for t in transactions):
string += ' *(%d kr)' % (self.purchase.price_per_transaction() * 2) # TODO: Use penalty multiplier instead of 2
string += f' *({self.purchase.price_per_transaction() * 2:d} kr)'
string += '\n total price: %d kr' % self.purchase.price string += f'\n total price: {self.purchase.price:d} kr'
if any(t.penalty > 1 for t in transactions): if any(t.penalty > 1 for t in transactions):
# TODO: Rewrite?
string += '\n *total with penalty: %d kr' % sum( string += '\n *total with penalty: %d kr' % sum(
self.purchase.price_per_transaction() * t.penalty for t in transactions) self.purchase.price_per_transaction() * t.penalty for t in transactions)

View File

@ -19,9 +19,9 @@ class AddUserMenu(Menu):
self.session.add(user) self.session.add(user)
try: try:
self.session.commit() self.session.commit()
print('User %s stored' % username) print(f'User {username} stored')
except sqlalchemy.exc.IntegrityError as e: except sqlalchemy.exc.IntegrityError as e:
print('Could not store user %s: %s' % (username, e)) print(f'Could not store user {username}: {e}')
self.pause() self.pause()
@ -38,27 +38,29 @@ user, then rfid (write an empty line to remove the card number or rfid).
def _execute(self): def _execute(self):
self.print_header() self.print_header()
user = self.input_user('User> ') user = self.input_user('User> ')
self.printc('Editing user %s' % user.name) self.printc(f'Editing user {user.name}')
card_str = '"%s"' % user.card card_str = f'"{user.card}"'
if user.card is None: if user.card is None:
card_str = 'empty' card_str = 'empty'
# TODO: Inconsistent with other defaulted strings. Redo.
user.card = self.input_str('Card number (currently %s)> ' % card_str, user.card = self.input_str('Card number (currently %s)> ' % card_str,
User.card_re, (0, 10), User.card_re, (0, 10),
empty_string_is_none=True) empty_string_is_none=True)
if user.card: if user.card:
user.card = user.card.lower() user.card = user.card.lower()
rfid_str = '"%s"' % user.rfid rfid_str = f'"{user.rfid}"'
if user.rfid is None: if user.rfid is None:
rfid_str = 'empty' rfid_str = 'empty'
user.rfid = self.input_str('RFID (currently %s)> ' % rfid_str, # TODO: Inconsistent with other defaulted strings. Redo.
user.rfid = self.input_str(f'RFID (currently {rfid_str})> ',
User.rfid_re, (0, 10), User.rfid_re, (0, 10),
empty_string_is_none=True) empty_string_is_none=True)
try: try:
self.session.commit() self.session.commit()
print('User %s stored' % user.name) print(f'User {user.name} stored')
except sqlalchemy.exc.SQLAlchemyError as e: except sqlalchemy.exc.SQLAlchemyError as e:
print('Could not store user %s: %s' % (user.name, e)) print(f'Could not store user {user.name}: {e}')
self.pause() self.pause()
@ -75,9 +77,9 @@ class AddProductMenu(Menu):
self.session.add(product) self.session.add(product)
try: try:
self.session.commit() self.session.commit()
print('Product %s stored' % name) print(f'Product {name} stored')
except sqlalchemy.exc.SQLAlchemyError as e: except sqlalchemy.exc.SQLAlchemyError as e:
print('Could not store product %s: %s' % (name, e)) print(f'Could not store product {name}: {e}')
self.pause() self.pause()
@ -88,9 +90,9 @@ class EditProductMenu(Menu):
def _execute(self): def _execute(self):
self.print_header() self.print_header()
product = self.input_product('Product> ') product = self.input_product('Product> ')
self.printc('Editing product %s' % product.name) self.printc(f'Editing product {product.name}')
while True: while True:
selector = Selector('Do what with %s?' % product.name, selector = Selector(f'Do what with {product.name}?',
items=[('name', 'Edit name'), items=[('name', 'Edit name'),
('price', 'Edit price'), ('price', 'Edit price'),
('barcode', 'Edit barcode'), ('barcode', 'Edit barcode'),
@ -98,19 +100,19 @@ class EditProductMenu(Menu):
('store', 'Store')]) ('store', 'Store')])
what = selector.execute() what = selector.execute()
if what == 'name': if what == 'name':
product.name = self.input_str('Name[%s]> ' % product.name, Product.name_re, (1, product.name_length)) product.name = self.input_str(f'Name[{product.name}]> ', Product.name_re, (1, product.name_length))
elif what == 'price': elif what == 'price':
product.price = self.input_int('Price[%s]> ' % product.price, (1, 100000)) product.price = self.input_int(f'Price[{product.price}]> ', (1, 100000))
elif what == 'barcode': elif what == 'barcode':
product.bar_code = self.input_str('Bar code[%s]> ' % product.bar_code, Product.bar_code_re, (8, 13)) product.bar_code = self.input_str(f'Bar code[{product.bar_code}]> ', Product.bar_code_re, (8, 13))
elif what == 'hidden': elif what == 'hidden':
product.hidden = self.confirm('Hidden[%s]' % ("Y" if product.hidden else "N"), False) product.hidden = self.confirm('Hidden[%s]' % ("Y" if product.hidden else "N"), False)
elif what == 'store': elif what == 'store':
try: try:
self.session.commit() self.session.commit()
print('Product %s stored' % product.name) print(f'Product {product.name} stored')
except sqlalchemy.exc.SQLAlchemyError as e: except sqlalchemy.exc.SQLAlchemyError as e:
print('Could not store product %s: %s' % (product.name, e)) print(f'Could not store product {product.name}: {e}')
self.pause() self.pause()
return return
elif what is None: elif what is None:
@ -128,25 +130,26 @@ class AdjustStockMenu(Menu):
self.print_header() self.print_header()
product = self.input_product('Product> ') product = self.input_product('Product> ')
print('The stock of this product is: %d ' % product.stock) print(f'The stock of this product is: {product.stock:d} ')
print('Write the number of products you have added to the stock') print('Write the number of products you have added to the stock')
print('Alternatively, correct the stock for any mistakes') print('Alternatively, correct the stock for any mistakes')
add_stock = self.input_int('Added stock> ', (-1000, 1000)) add_stock = self.input_int('Added stock> ', (-1000, 1000))
print('You added %d to the stock of %s' % (add_stock, product)) # TODO: Print something else when adding negative stock?
print(f'You added {add_stock:d} to the stock of {product}')
product.stock += add_stock product.stock += add_stock
print('The stock is now %d' % product.stock) print(f'The stock is now {product.stock:d}')
try: try:
self.session.commit() self.session.commit()
print('Stock is now stored') print('Stock is now stored')
self.pause() self.pause()
except sqlalchemy.exc.SQLAlchemyError as e: except sqlalchemy.exc.SQLAlchemyError as e:
print('Could not store stock: %s' % e) print(f'Could not store stock: {e}')
self.pause() self.pause()
return return
print('The stock is now %d' % product.stock) print(f'The stock is now {product.stock:d}')
class CleanupStockMenu(Menu): class CleanupStockMenu(Menu):
@ -179,7 +182,7 @@ class CleanupStockMenu(Menu):
print('New stocks are now stored.') print('New stocks are now stored.')
self.pause() self.pause()
except sqlalchemy.exc.SQLAlchemyError as e: except sqlalchemy.exc.SQLAlchemyError as e:
print('Could not store stock: %s' % e) print(f'Could not store stock: {e}')
self.pause() self.pause()
return return

View File

@ -87,6 +87,7 @@ class Menu(object):
return i return i
return self.items[i] return self.items[i]
# TODO: Allow default
def input_str(self, prompt=None, regex=None, length_range=(None, None), def input_str(self, prompt=None, regex=None, length_range=(None, None),
empty_string_is_none=False, timeout=None): empty_string_is_none=False, timeout=None):
if prompt is None: if prompt is None:
@ -98,7 +99,7 @@ class Menu(object):
if result is None or re.match(regex + '$', result): if result is None or re.match(regex + '$', result):
return result return result
else: else:
print('Value must match regular expression "%s"' % regex) print(f'Value must match regular expression "{regex}"')
if length_range != (None, None): if length_range != (None, None):
while True: while True:
result = self.input_str(prompt, empty_string_is_none=empty_string_is_none) result = self.input_str(prompt, empty_string_is_none=empty_string_is_none)
@ -109,11 +110,11 @@ class Menu(object):
if ((length_range[0] and length < length_range[0]) or if ((length_range[0] and length < length_range[0]) or
(length_range[1] and length > length_range[1])): (length_range[1] and length > length_range[1])):
if length_range[0] and length_range[1]: if length_range[0] and length_range[1]:
print('Value must have length in range [%d,%d]' % length_range) print(f'Value must have length in range [{length_range[0]:d}, {length_range[1]:d}]')
elif length_range[0]: elif length_range[0]:
print('Value must have length at least %d' % length_range[0]) print(f'Value must have length at least {length_range[0]:d}')
else: else:
print('Value must have length at most %d' % length_range[1]) print(f'Value must have length at most {length_range[1]:d}')
else: else:
return result return result
while True: while True:
@ -129,9 +130,9 @@ class Menu(object):
# timeout occurred, simulate empty line # timeout occurred, simulate empty line
result = '' result = ''
else: else:
result = str(input(), conf.input_encoding).strip() result = input().strip()
else: else:
result = str(input(safe_str(prompt)), conf.input_encoding).strip() result = input(safe_str(prompt)).strip()
except EOFError: except EOFError:
print('quit') print('quit')
self.exit_menu() self.exit_menu()
@ -210,7 +211,7 @@ class Menu(object):
if prompt is None: if prompt is None:
prompt = self.prompt prompt = self.prompt
if default is not None: if default is not None:
prompt += ("[%s] " % default) prompt += (f"[{default}] ")
while True: while True:
result = self.input_str(prompt) result = self.input_str(prompt)
if result == '': if result == '':
@ -223,11 +224,11 @@ class Menu(object):
if ((allowed_range[0] and value < allowed_range[0]) or if ((allowed_range[0] and value < allowed_range[0]) or
(allowed_range[1] and value > allowed_range[1])): (allowed_range[1] and value > allowed_range[1])):
if allowed_range[0] and allowed_range[1]: if allowed_range[0] and allowed_range[1]:
print('Value must be in range [%d,%d]' % allowed_range) print(f'Value must be in range [{allowed_range[0]:d}, {allowed_range[1]:d}]')
elif allowed_range[0]: elif allowed_range[0]:
print('Value must be at least %d' % allowed_range[0]) print(f'Value must be at least {allowed_range[0]:d}')
else: else:
print('Value must be at most %d' % allowed_range[1]) print(f'Value must be at most {allowed_range[1]:d}')
else: else:
return value return value
except ValueError: except ValueError:
@ -302,7 +303,7 @@ class Menu(object):
type_guess = guess_data_type(search_str) type_guess = guess_data_type(search_str)
if type_guess is not None and thing_for_type[type_guess] in add_non_existing: if type_guess is not None and thing_for_type[type_guess] in add_non_existing:
return self.search_add(search_str) return self.search_add(search_str)
# print 'No match found for "%s".' % search_str # print('No match found for "%s".' % search_str)
return None return None
return self.search_ui2(search_str, results[selected_thing], selected_thing) return self.search_ui2(search_str, results[selected_thing], selected_thing)
@ -321,16 +322,16 @@ class Menu(object):
def search_add(self, string): def search_add(self, string):
type_guess = guess_data_type(string) type_guess = guess_data_type(string)
if type_guess == 'username': if type_guess == 'username':
print('"%s" looks like a username, but no such user exists.' % string) print(f'"{string}" looks like a username, but no such user exists.')
if self.confirm('Create user %s?' % string): if self.confirm(f'Create user {string}?'):
user = User(string, None) user = User(string, None)
self.session.add(user) self.session.add(user)
return user return user
return None return None
if type_guess == 'card': if type_guess == 'card':
selector = Selector('"%s" looks like a card number, but no user with that card number exists.' % string, selector = Selector(f'"{string}" looks like a card number, but no user with that card number exists.',
[('create', 'Create user with card number %s' % string), [('create', f'Create user with card number {string}'),
('set', 'Set card number of an existing user to %s' % string)]) ('set', f'Set card number of an existing user to {string}')])
selection = selector.execute() selection = selector.execute()
if selection == 'create': if selection == 'create':
username = self.input_str('Username for new user (should be same as PVV username)> ', username = self.input_str('Username for new user (should be same as PVV username)> ',
@ -342,7 +343,7 @@ class Menu(object):
user = self.input_user('User to set card number for> ') user = self.input_user('User to set card number for> ')
old_card = user.card old_card = user.card
user.card = string user.card = string
print('Card number of %s set to %s (was %s)' % (user.name, string, old_card)) print(f'Card number of {user.name} set to {string} (was {old_card})')
return user return user
return None return None
if type_guess == 'bar_code': if type_guess == 'bar_code':
@ -357,22 +358,19 @@ class Menu(object):
if not isinstance(result, list): if not isinstance(result, list):
return result return result
if len(result) == 0: if len(result) == 0:
print('No %ss matching "%s"' % (thing, search_str)) print(f'No {thing}s matching "{search_str}"')
return None return None
if len(result) == 1: if len(result) == 1:
msg = 'One %s matching "%s": %s. Use this?' % \ msg = f'One {thing} matching "{search_str}": {str(result[0])}. Use this?'
(thing, search_str, str(result[0]))
if self.confirm(msg, default=True): if self.confirm(msg, default=True):
return result[0] return result[0]
return None return None
limit = 9 limit = 9
if len(result) > limit: if len(result) > limit:
select_header = '%d %ss matching "%s"; showing first %d' % \ select_header = f'{len(result):d} {thing}s matching "{search_str}"; showing first {limit:d}'
(len(result), thing, search_str, limit)
select_items = result[:limit] select_items = result[:limit]
else: else:
select_header = '%d %ss matching "%s"' % \ select_header = f'{len(result):d} {thing}s matching "{search_str}"'
(len(result), thing, search_str)
select_items = result select_items = result
selector = Selector(select_header, items=select_items, selector = Selector(select_header, items=select_items,
return_index=False) return_index=False)
@ -419,7 +417,8 @@ class Menu(object):
print('no help here') print('no help here')
else: else:
print('') print('')
print('Help for %s:' % (self.header_format % self.name)) print('Help for %s:' % (self.header_format
% self.name))
print(self.help_text) print(self.help_text)
def execute(self, **kwargs): def execute(self, **kwargs):
@ -437,6 +436,7 @@ class Menu(object):
self.session = None self.session = None
def _execute(self, **kwargs): def _execute(self, **kwargs):
# TODO: This is a very awkward line. Is there a better way of doing this?
line_format = '%' + str(len(str(len(self.items)))) + 'd ) %s' line_format = '%' + str(len(str(len(self.items)))) + 'd ) %s'
while True: while True:
self.print_header() self.print_header()
@ -478,7 +478,7 @@ class ConfirmMenu(Menu):
def _execute(self): def _execute(self):
options = {True: '[y]/n', False: 'y/[n]', None: 'y/n'}[self.default] options = {True: '[y]/n', False: 'y/[n]', None: 'y/n'}[self.default]
while True: while True:
result = self.input_str('%s (%s) ' % (self.prompt, options), timeout=self.timeout) result = self.input_str(f'{self.prompt} ({options}) ', timeout=self.timeout)
result = result.lower().strip() result = result.lower().strip()
if result in ['y', 'yes']: if result in ['y', 'yes']:
return True return True
@ -507,5 +507,5 @@ class Selector(Menu):
print('\'exit\' to go out and do something else.') print('\'exit\' to go out and do something else.')
else: else:
print('') print('')
print('Help for selector (%s):' % self.name) print(f'Help for selector ({self.name}):')
print(self.help_text) print(self.help_text)

View File

@ -13,30 +13,30 @@ class TransferMenu(Menu):
def _execute(self): def _execute(self):
self.print_header() self.print_header()
amount = self.input_int('Transfer amount> ', (1, 100000)) amount = self.input_int('Transfer amount> ', (1, 100000))
self.set_context('Transfering %d kr' % amount, display=False) self.set_context(f'Transferring {amount:d} kr', display=False)
user1 = self.input_user('From user> ') user1 = self.input_user('From user> ')
self.add_to_context(' from ' + user1.name) self.add_to_context(f' from {user1.name}')
user2 = self.input_user('To user> ') user2 = self.input_user('To user> ')
self.add_to_context(' to ' + user2.name) self.add_to_context(f' to {user2.name}')
comment = self.input_str('Comment> ') comment = self.input_str('Comment> ')
self.add_to_context(' (comment) ' + user2.name) self.add_to_context(f' (comment) {user2.name}')
t1 = Transaction(user1, amount, t1 = Transaction(user1, amount,
'transfer to ' + user2.name + ' "' + comment + '"') f'transfer to {user2.name} "{comment}"')
t2 = Transaction(user2, -amount, t2 = Transaction(user2, -amount,
'transfer from ' + user1.name + ' "' + comment + '"') f'transfer from {user1.name} "{comment}"')
t1.perform_transaction() t1.perform_transaction()
t2.perform_transaction() t2.perform_transaction()
self.session.add(t1) self.session.add(t1)
self.session.add(t2) self.session.add(t2)
try: try:
self.session.commit() self.session.commit()
print('Transfered %d kr from %s to %s' % (amount, user1, user2)) print(f"Transferred {amount:d} kr from {user1} to {user2}")
print('User %s\'s credit is now %d kr' % (user1, user1.credit)) print(f"User {user1}'s credit is now {user1.credit:d} kr")
print('User %s\'s credit is now %d kr' % (user2, user2.credit)) print(f"User {user2}'s credit is now {user2.credit:d} kr")
print('Comment: %s' % comment) print(f"Comment: {comment}")
except sqlalchemy.exc.SQLAlchemyError as e: except sqlalchemy.exc.SQLAlchemyError as e:
print('Could not perform transfer: %s' % e) print(f'Could not perform transfer: {e}')
# self.pause() # self.pause()
@ -47,14 +47,14 @@ class ShowUserMenu(Menu):
def _execute(self): def _execute(self):
self.print_header() self.print_header()
user = self.input_user('User name, card number or RFID> ') user = self.input_user('User name, card number or RFID> ')
print('User name: %s' % user.name) print(f'User name: {user.name}')
print('Card number: %s' % user.card) print(f'Card number: {user.card}')
print('RFID: %s' % user.rfid) print(f'RFID: {user.rfid}')
print('Credit: %s kr' % user.credit) print(f'Credit: {user.credit} kr')
selector = Selector('What do you want to know about %s?' % user.name, selector = Selector(f'What do you want to know about {user.name}?',
items=[('transactions', 'Recent transactions (List of last ' + str( items=[('transactions', 'Recent transactions (List of last ' + str(
conf.user_recent_transaction_limit) + ')'), conf.user_recent_transaction_limit) + ')'),
('products', 'Which products %s has bought, and how many' % user.name), ('products', f'Which products {user.name} has bought, and how many'),
('transactions-all', 'Everything (List of all transactions)')]) ('transactions-all', 'Everything (List of all transactions)')])
what = selector.execute() what = selector.execute()
if what == 'transactions': if what == 'transactions':
@ -66,21 +66,24 @@ class ShowUserMenu(Menu):
else: else:
print('What what?') print('What what?')
# TODO: This is almost identical to the print_transactions function. Reimplement using that one?
@staticmethod @staticmethod
def print_all_transactions(user): def print_all_transactions(user):
num_trans = len(user.transactions) num_trans = len(user.transactions)
string = '%s\'s transactions (%d):\n' % (user.name, num_trans) string = f"{user.name}'s transactions ({num_trans:d}):\n"
for t in user.transactions[::-1]: for t in user.transactions[::-1]:
string += ' * %s: %s %d kr, ' % \ string += ' * %s: %s %d kr, ' % \
(t.time.strftime('%Y-%m-%d %H:%M'), (t.time.strftime('%Y-%m-%d %H:%M'),
{True: 'in', False: 'out'}[t.amount < 0], 'in' if t.amount < 0 else 'out',
abs(t.amount)) abs(t.amount))
if t.purchase: if t.purchase:
# TODO: Print purchased amount, not just product names
# TODO: Print something other than "purchase" when user put products into dibbler?
string += 'purchase (' string += 'purchase ('
string += ', '.join([e.product.name for e in t.purchase.entries]) string += ', '.join([e.product.name for e in t.purchase.entries])
string += ')' string += ')'
if t.penalty > 1: if t.penalty > 1:
string += ' * %dx penalty applied' % t.penalty string += f' * {t.penalty:d}x penalty applied'
else: else:
string += t.description string += t.description
string += '\n' string += '\n'
@ -90,20 +93,20 @@ class ShowUserMenu(Menu):
def print_transactions(user, limit=10): def print_transactions(user, limit=10):
num_trans = len(user.transactions) num_trans = len(user.transactions)
if num_trans <= limit: if num_trans <= limit:
string = '%s\'s transactions (%d):\n' % (user.name, num_trans) string = f"{user.name}'s transactions ({num_trans:d}):\n"
else: else:
string = '%s\'s transactions (%d, showing only last %d):\n' % (user.name, num_trans, limit) string = f"{user.name}'s transactions ({num_trans:d}, showing only last {limit:d}):\n"
for t in user.transactions[-1:-limit - 1:-1]: for t in user.transactions[-1:-limit - 1:-1]:
string += ' * %s: %s %d kr, ' % \ string += ' * %s: %s %d kr, ' % \
(t.time.strftime('%Y-%m-%d %H:%M'), (t.time.strftime('%Y-%m-%d %H:%M'),
{True: 'in', False: 'out'}[t.amount < 0], 'in' if t.amount < 0 else 'out',
abs(t.amount)) abs(t.amount))
if t.purchase: if t.purchase:
string += 'purchase (' string += 'purchase ('
string += ', '.join([e.product.name for e in t.purchase.entries]) string += ', '.join([e.product.name for e in t.purchase.entries])
string += ')' string += ')'
if t.penalty > 1: if t.penalty > 1:
string += ' * %dx penalty applied' % t.penalty string += f' * {t.penalty:d}x penalty applied'
else: else:
string += t.description string += t.description
string += '\n' string += '\n'
@ -124,7 +127,7 @@ class ShowUserMenu(Menu):
text = '' text = ''
text += 'Products purchased:\n' text += 'Products purchased:\n'
for product, count in products: for product, count in products:
text += '{0:<47} {1:>3}\n'.format(product.name, count) text += f'{product.name:<47} {count:>3}\n'
less(text) less(text)
@ -148,16 +151,17 @@ class UserListMenu(Menu):
text += line_format % ('total credit', total_credit) text += line_format % ('total credit', total_credit)
less(text) less(text)
# reimplements ChargeMenu
class AdjustCreditMenu(Menu): # reimplements ChargeMenu; these should be combined to one # TODO: these should be combined to one
class AdjustCreditMenu(Menu):
def __init__(self): def __init__(self):
Menu.__init__(self, 'Adjust credit', uses_db=True) Menu.__init__(self, 'Adjust credit', uses_db=True)
def _execute(self): def _execute(self):
self.print_header() self.print_header()
user = self.input_user('User> ') user = self.input_user('User> ')
print('User %s\'s credit is %d kr' % (user.name, user.credit)) print(f"User {user.name}'s credit is {user.credit:d} kr")
self.set_context('Adjusting credit for user %s' % user.name, display=False) self.set_context(f'Adjusting credit for user {user.name}', display=False)
print('(Note on sign convention: Enter a positive amount here if you have') print('(Note on sign convention: Enter a positive amount here if you have')
print('added money to the PVVVV money box, a negative amount if you have') print('added money to the PVVVV money box, a negative amount if you have')
print('taken money from it)') print('taken money from it)')
@ -173,9 +177,9 @@ class AdjustCreditMenu(Menu): # reimplements ChargeMenu; these should be combin
self.session.add(transaction) self.session.add(transaction)
try: try:
self.session.commit() self.session.commit()
print('User %s\'s credit is now %d kr' % (user.name, user.credit)) print(f"User {user.name}'s credit is now {user.credit:d} kr")
except sqlalchemy.exc.SQLAlchemyError as e: except sqlalchemy.exc.SQLAlchemyError as e:
print('Could not store transaction: %s' % e) print(f'Could not store transaction: {e}')
# self.pause() # self.pause()