diff --git a/db.py b/db.py index 1255d96..6e61eec 100644 --- a/db.py +++ b/db.py @@ -32,7 +32,7 @@ class User(Base): self.credit = credit def __repr__(self): - return "" % self.name + return f"" def __str__(self): return self.name @@ -63,8 +63,7 @@ class Product(Base): self.hidden = hidden def __repr__(self): - return "" %\ - (self.name, self.bar_code, self.price, self.stock, self.hidden) + return f"" def __str__(self): return self.name @@ -97,7 +96,7 @@ class PurchaseEntry(Base): self.amount = amount def __repr__(self): - return "" % (self.product.name, self.amount) + return f"" class Transaction(Base): @@ -141,7 +140,7 @@ class Purchase(Base): pass def __repr__(self): - return "" % (int(self.id), self.price, self.time.strftime('%c')) + return f"" def is_complete(self): return len(self.transactions) > 0 and len(self.entries) > 0 diff --git a/helpers.py b/helpers.py index 4d30d59..0783fcc 100644 --- a/helpers.py +++ b/helpers.py @@ -5,30 +5,30 @@ import subprocess import os import signal -def search_user(string, session, ignorethisflag=None): - string = string.lower() - exact_match = session.query(User).filter(or_(User.name==string, User.card==string, User.rfid==string)).first() +def search_user(str, session, ignorethisflag=None): + str = str.lower() + exact_match = session.query(User).filter(or_(User.name == str, User.card == str, User.rfid == str)).first() if exact_match: return exact_match - user_list = session.query(User).filter(or_(User.name.ilike('%'+string+'%'), - User.card.ilike('%'+string+'%'), - User.rfid.ilike('%'+string+'%'))).all() + user_list = session.query(User).filter(or_(User.name.ilike(f'%{str}%'), + User.card.ilike(f'%{str}%'), + User.rfid.ilike(f'%{str}%'))).all() 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: - 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: - exact_match = session.query(Product).filter(or_(Product.bar_code==string, - and_(Product.name==string, Product.hidden == False))).first() + exact_match = session.query(Product).filter(or_(Product.bar_code == str, + and_(Product.name == str, Product.hidden == False))).first() if exact_match: return exact_match if find_hidden_products: - product_list = session.query(Product).filter(or_(Product.bar_code.ilike('%'+string+'%'), - Product.name.ilike('%'+string+'%'))).all() + product_list = session.query(Product).filter(or_(Product.bar_code.ilike(f'%{str}%'), + Product.name.ilike(f'%{str}%'))).all() else: - product_list = session.query(Product).filter(or_(Product.bar_code.ilike('%' + string + '%'), - and_(Product.name.ilike('%' + string + '%'), + product_list = session.query(Product).filter(or_(Product.bar_code.ilike(f'%{str}%'), + and_(Product.name.ilike(f'%{str}%'), Product.hidden == False))).all() return product_list diff --git a/slabbedasker.py b/slabbedasker.py index e008126..c0172bc 100755 --- a/slabbedasker.py +++ b/slabbedasker.py @@ -6,4 +6,4 @@ session=Session() slabbedasker=session.query(User).filter(User.credit<0).all() for slubbert in slabbedasker: - print("%s, %s" % (slubbert.name, slubbert.credit)) + print(f"{slubbert.name}, {slubbert.credit}") diff --git a/text_based.py b/text_based.py index 1a3c56a..a392336 100755 --- a/text_based.py +++ b/text_based.py @@ -64,7 +64,7 @@ if __name__ == '__main__': print('Interrupted.') except: 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: traceback.print_tb(sys.exc_info()[2]) else: diff --git a/text_interface/addstock.py b/text_interface/addstock.py index e31b31a..19b9c95 100644 --- a/text_interface/addstock.py +++ b/text_interface/addstock.py @@ -41,7 +41,7 @@ much money you're due in credits for the purchase when prompted.\n''' (thing, amount) = line 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), default=thing.price) * amount 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): return bool(self.users) and len(self.products) and self.price + # TODO: Rewrite this madness def print_info(self): print((6 + Product.name_length) * '-') if self.price: @@ -72,7 +73,7 @@ much money you're due in credits for the purchase when prompted.\n''' if self.users: print("Users to credit:") 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((6 + Product.name_length) * '-') 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?') if self.confirm('>', default=False): 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: print('Illegal action, total can not be higher than your total.') 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.stock = max(self.products[product][0], product.stock + self.products[product][0]) product.hidden = False - print("New stock for %s: %d" % (product.name, product.stock), \ - ("- New price: " + str(product.price) if old_price != product.price else ""), \ - ("- Removed hidden status" if old_hidden != product.hidden else "")) + print(f"New stock for {product.name}: {product.stock:d}", + f"- New price: {product.price}" if old_price != product.price else "", + "- Removed hidden status" if old_hidden != product.hidden else "") purchase = Purchase() 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:") # self.print_info() 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: - print('Could not perform transaction: %s' % e) + print(f'Could not perform transaction: {e}') diff --git a/text_interface/buymenu.py b/text_interface/buymenu.py index 4fa979d..1f0fa24 100644 --- a/text_interface/buymenu.py +++ b/text_interface/buymenu.py @@ -49,7 +49,7 @@ When finished, write an empty line to confirm the purchase.\n''' 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("CONSIDER PUTTING MONEY IN THE BOX TO AVOID THIS.") print("") @@ -149,16 +149,16 @@ When finished, write an empty line to confirm the purchase.\n''' try: self.session.commit() except sqlalchemy.exc.SQLAlchemyError as e: - print('Could not store purchase: %s' % e) + print(f'Could not store purchase: {e}') else: print('Purchase stored.') self.print_purchase() for t in self.purchase.transactions: 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: - 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(f'USER {t.user.name} HAS LOWER CREDIT THAN {conf.low_credit_warning_limit:d},', + 'AND SHOULD CONSIDER PUTTING SOME MONEY IN THE BOX.') return True @@ -183,15 +183,17 @@ When finished, write an empty line to confirm the purchase.\n''' string += '(empty)' else: 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: - 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): - 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): + # TODO: Rewrite? string += '\n *total with penalty: %d kr' % sum( self.purchase.price_per_transaction() * t.penalty for t in transactions) diff --git a/text_interface/editing.py b/text_interface/editing.py index b325ab7..89fa7e8 100644 --- a/text_interface/editing.py +++ b/text_interface/editing.py @@ -19,9 +19,9 @@ class AddUserMenu(Menu): self.session.add(user) try: self.session.commit() - print('User %s stored' % username) + print(f'User {username} stored') 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() @@ -38,27 +38,29 @@ user, then rfid (write an empty line to remove the card number or rfid). def _execute(self): self.print_header() user = self.input_user('User> ') - self.printc('Editing user %s' % user.name) - card_str = '"%s"' % user.card + self.printc(f'Editing user {user.name}') + card_str = f'"{user.card}"' if user.card is None: card_str = 'empty' + # TODO: Inconsistent with other defaulted strings. Redo. user.card = self.input_str('Card number (currently %s)> ' % card_str, User.card_re, (0, 10), empty_string_is_none=True) if user.card: user.card = user.card.lower() - rfid_str = '"%s"' % user.rfid + rfid_str = f'"{user.rfid}"' if user.rfid is None: 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), empty_string_is_none=True) try: self.session.commit() - print('User %s stored' % user.name) + print(f'User {user.name} stored') 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() @@ -75,9 +77,9 @@ class AddProductMenu(Menu): self.session.add(product) try: self.session.commit() - print('Product %s stored' % name) + print(f'Product {name} stored') 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() @@ -88,9 +90,9 @@ class EditProductMenu(Menu): def _execute(self): self.print_header() product = self.input_product('Product> ') - self.printc('Editing product %s' % product.name) + self.printc(f'Editing product {product.name}') while True: - selector = Selector('Do what with %s?' % product.name, + selector = Selector(f'Do what with {product.name}?', items=[('name', 'Edit name'), ('price', 'Edit price'), ('barcode', 'Edit barcode'), @@ -98,19 +100,19 @@ class EditProductMenu(Menu): ('store', 'Store')]) what = selector.execute() 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': - 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': - 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': product.hidden = self.confirm('Hidden[%s]' % ("Y" if product.hidden else "N"), False) elif what == 'store': try: self.session.commit() - print('Product %s stored' % product.name) + print(f'Product {product.name} stored') 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() return elif what is None: @@ -128,25 +130,26 @@ class AdjustStockMenu(Menu): self.print_header() 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('Alternatively, correct the stock for any mistakes') 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 - print('The stock is now %d' % product.stock) + print(f'The stock is now {product.stock:d}') try: self.session.commit() print('Stock is now stored') self.pause() except sqlalchemy.exc.SQLAlchemyError as e: - print('Could not store stock: %s' % e) + print(f'Could not store stock: {e}') self.pause() return - print('The stock is now %d' % product.stock) + print(f'The stock is now {product.stock:d}') class CleanupStockMenu(Menu): @@ -179,7 +182,7 @@ class CleanupStockMenu(Menu): print('New stocks are now stored.') self.pause() except sqlalchemy.exc.SQLAlchemyError as e: - print('Could not store stock: %s' % e) + print(f'Could not store stock: {e}') self.pause() return diff --git a/text_interface/helpermenus.py b/text_interface/helpermenus.py index 23de252..04aaccd 100644 --- a/text_interface/helpermenus.py +++ b/text_interface/helpermenus.py @@ -87,6 +87,7 @@ class Menu(object): return i return self.items[i] + # TODO: Allow default def input_str(self, prompt=None, regex=None, length_range=(None, None), empty_string_is_none=False, timeout=None): if prompt is None: @@ -98,7 +99,7 @@ class Menu(object): if result is None or re.match(regex + '$', result): return result else: - print('Value must match regular expression "%s"' % regex) + print(f'Value must match regular expression "{regex}"') if length_range != (None, None): while True: 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 (length_range[1] and length > 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]: - print('Value must have length at least %d' % length_range[0]) + print(f'Value must have length at least {length_range[0]:d}') 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: return result while True: @@ -129,9 +130,9 @@ class Menu(object): # timeout occurred, simulate empty line result = '' else: - result = str(input(), conf.input_encoding).strip() + result = input().strip() else: - result = str(input(safe_str(prompt)), conf.input_encoding).strip() + result = input(safe_str(prompt)).strip() except EOFError: print('quit') self.exit_menu() @@ -210,7 +211,7 @@ class Menu(object): if prompt is None: prompt = self.prompt if default is not None: - prompt += ("[%s] " % default) + prompt += (f"[{default}] ") while True: result = self.input_str(prompt) if result == '': @@ -223,11 +224,11 @@ class Menu(object): if ((allowed_range[0] and value < allowed_range[0]) or (allowed_range[1] and value > 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]: - print('Value must be at least %d' % allowed_range[0]) + print(f'Value must be at least {allowed_range[0]:d}') else: - print('Value must be at most %d' % allowed_range[1]) + print(f'Value must be at most {allowed_range[1]:d}') else: return value except ValueError: @@ -302,7 +303,7 @@ class Menu(object): type_guess = guess_data_type(search_str) if type_guess is not None and thing_for_type[type_guess] in add_non_existing: 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 self.search_ui2(search_str, results[selected_thing], selected_thing) @@ -321,16 +322,16 @@ class Menu(object): def search_add(self, string): type_guess = guess_data_type(string) if type_guess == 'username': - print('"%s" looks like a username, but no such user exists.' % string) - if self.confirm('Create user %s?' % string): + print(f'"{string}" looks like a username, but no such user exists.') + if self.confirm(f'Create user {string}?'): user = User(string, None) self.session.add(user) return user return None if type_guess == 'card': - selector = Selector('"%s" looks like a card number, but no user with that card number exists.' % string, - [('create', 'Create user with card number %s' % string), - ('set', 'Set card number of an existing user to %s' % string)]) + selector = Selector(f'"{string}" looks like a card number, but no user with that card number exists.', + [('create', f'Create user with card number {string}'), + ('set', f'Set card number of an existing user to {string}')]) selection = selector.execute() if selection == 'create': 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> ') old_card = user.card 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 None if type_guess == 'bar_code': @@ -357,22 +358,19 @@ class Menu(object): if not isinstance(result, list): return result if len(result) == 0: - print('No %ss matching "%s"' % (thing, search_str)) + print(f'No {thing}s matching "{search_str}"') return None if len(result) == 1: - msg = 'One %s matching "%s": %s. Use this?' % \ - (thing, search_str, str(result[0])) + msg = f'One {thing} matching "{search_str}": {str(result[0])}. Use this?' if self.confirm(msg, default=True): return result[0] return None limit = 9 if len(result) > limit: - select_header = '%d %ss matching "%s"; showing first %d' % \ - (len(result), thing, search_str, limit) + select_header = f'{len(result):d} {thing}s matching "{search_str}"; showing first {limit:d}' select_items = result[:limit] else: - select_header = '%d %ss matching "%s"' % \ - (len(result), thing, search_str) + select_header = f'{len(result):d} {thing}s matching "{search_str}"' select_items = result selector = Selector(select_header, items=select_items, return_index=False) @@ -419,7 +417,8 @@ class Menu(object): print('no help here') else: print('') - print('Help for %s:' % (self.header_format % self.name)) + print('Help for %s:' % (self.header_format + % self.name)) print(self.help_text) def execute(self, **kwargs): @@ -437,6 +436,7 @@ class Menu(object): self.session = None 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' while True: self.print_header() @@ -478,7 +478,7 @@ class ConfirmMenu(Menu): 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), timeout=self.timeout) + result = self.input_str(f'{self.prompt} ({options}) ', timeout=self.timeout) result = result.lower().strip() if result in ['y', 'yes']: return True @@ -507,5 +507,5 @@ class Selector(Menu): print('\'exit\' to go out and do something else.') else: print('') - print('Help for selector (%s):' % self.name) + print(f'Help for selector ({self.name}):') print(self.help_text) diff --git a/text_interface/miscmenus.py b/text_interface/miscmenus.py index 744f395..d8523c6 100644 --- a/text_interface/miscmenus.py +++ b/text_interface/miscmenus.py @@ -13,30 +13,30 @@ class TransferMenu(Menu): def _execute(self): self.print_header() 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> ') - self.add_to_context(' from ' + user1.name) + self.add_to_context(f' from {user1.name}') 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> ') - self.add_to_context(' (comment) ' + user2.name) + self.add_to_context(f' (comment) {user2.name}') t1 = Transaction(user1, amount, - 'transfer to ' + user2.name + ' "' + comment + '"') + f'transfer to {user2.name} "{comment}"') t2 = Transaction(user2, -amount, - 'transfer from ' + user1.name + ' "' + comment + '"') + f'transfer from {user1.name} "{comment}"') t1.perform_transaction() t2.perform_transaction() self.session.add(t1) self.session.add(t2) try: self.session.commit() - print('Transfered %d kr from %s to %s' % (amount, user1, user2)) - print('User %s\'s credit is now %d kr' % (user1, user1.credit)) - print('User %s\'s credit is now %d kr' % (user2, user2.credit)) - print('Comment: %s' % comment) + print(f"Transferred {amount:d} kr from {user1} to {user2}") + print(f"User {user1}'s credit is now {user1.credit:d} kr") + print(f"User {user2}'s credit is now {user2.credit:d} kr") + print(f"Comment: {comment}") except sqlalchemy.exc.SQLAlchemyError as e: - print('Could not perform transfer: %s' % e) + print(f'Could not perform transfer: {e}') # self.pause() @@ -47,14 +47,14 @@ class ShowUserMenu(Menu): def _execute(self): self.print_header() user = self.input_user('User name, card number or RFID> ') - print('User name: %s' % user.name) - print('Card number: %s' % user.card) - print('RFID: %s' % user.rfid) - print('Credit: %s kr' % user.credit) - selector = Selector('What do you want to know about %s?' % user.name, + print(f'User name: {user.name}') + print(f'Card number: {user.card}') + print(f'RFID: {user.rfid}') + print(f'Credit: {user.credit} kr') + selector = Selector(f'What do you want to know about {user.name}?', items=[('transactions', 'Recent transactions (List of last ' + str( 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)')]) what = selector.execute() if what == 'transactions': @@ -66,21 +66,24 @@ class ShowUserMenu(Menu): else: print('What what?') + # TODO: This is almost identical to the print_transactions function. Reimplement using that one? @staticmethod def print_all_transactions(user): 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]: string += ' * %s: %s %d kr, ' % \ (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)) 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 += ', '.join([e.product.name for e in t.purchase.entries]) string += ')' if t.penalty > 1: - string += ' * %dx penalty applied' % t.penalty + string += f' * {t.penalty:d}x penalty applied' else: string += t.description string += '\n' @@ -90,20 +93,20 @@ class ShowUserMenu(Menu): def print_transactions(user, limit=10): num_trans = len(user.transactions) 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: - 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]: string += ' * %s: %s %d kr, ' % \ (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)) if t.purchase: string += 'purchase (' string += ', '.join([e.product.name for e in t.purchase.entries]) string += ')' if t.penalty > 1: - string += ' * %dx penalty applied' % t.penalty + string += f' * {t.penalty:d}x penalty applied' else: string += t.description string += '\n' @@ -124,7 +127,7 @@ class ShowUserMenu(Menu): text = '' text += 'Products purchased:\n' 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) @@ -148,16 +151,17 @@ class UserListMenu(Menu): text += line_format % ('total credit', total_credit) less(text) - -class AdjustCreditMenu(Menu): # reimplements ChargeMenu; these should be combined to one +# reimplements ChargeMenu +# TODO: these should be combined to one +class AdjustCreditMenu(Menu): def __init__(self): Menu.__init__(self, 'Adjust credit', uses_db=True) def _execute(self): self.print_header() user = self.input_user('User> ') - print('User %s\'s credit is %d kr' % (user.name, user.credit)) - self.set_context('Adjusting credit for user %s' % user.name, display=False) + print(f"User {user.name}'s credit is {user.credit:d} kr") + 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('added money to the PVVVV money box, a negative amount if you have') print('taken money from it)') @@ -173,9 +177,9 @@ class AdjustCreditMenu(Menu): # reimplements ChargeMenu; these should be combin self.session.add(transaction) try: 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: - print('Could not store transaction: %s' % e) + print(f'Could not store transaction: {e}') # self.pause()