From 0c2626ee5baa696bc62b702b268a85d29cd96c84 Mon Sep 17 00:00:00 2001 From: Anna Wiggins Date: Thu, 28 Jan 2016 11:52:09 -0500 Subject: [PATCH] Fix the bug where leaving the program open makes us always fail due to being logged out. Also, some major refactoring to make the gui code cleaner. --- actions.py | 18 ++++++ gui.py | 146 ++++++++++++++++++++++++++++++++++++++++++++++++ update_inara.py | 81 ++++++--------------------- utils.py | 80 ++++---------------------- 4 files changed, 191 insertions(+), 134 deletions(-) create mode 100644 actions.py create mode 100644 gui.py diff --git a/actions.py b/actions.py new file mode 100644 index 0000000..1fb6ee6 --- /dev/null +++ b/actions.py @@ -0,0 +1,18 @@ +""" +This module mostly serves as a shim between the elite_api library and the rest of our program. +""" + +from elite_api import companion +from elite_api.inara import InaraSession + + +def do_logins(settings): + inara_session = InaraSession(settings.get('inara', 'username'), settings.get('inara', 'password')) + companion.login(settings.get('ed_companion', 'username'), settings.get('ed_companion', 'password')) + return inara_session + + +def update_inara(inara_session): + data = companion.get_data() + inara_session.update_credits(data['commander']['credits']) + inara_session.update_location(data['lastSystem']['name']) diff --git a/gui.py b/gui.py new file mode 100644 index 0000000..2c0159d --- /dev/null +++ b/gui.py @@ -0,0 +1,146 @@ +import actions +from datetime import datetime +import Tkinter as tk +import tkSimpleDialog, tkMessageBox +import utils + +class UpdateWindow(object): + def __init__(self, parent, settings): + self.parent = parent + if settings is not None: + self.settings = settings + else: + self.settings = utils.update_settings(self._render_config_dialog, self.settings) + self.frame = tk.Frame(parent) + self.frame.pack(expand=True, fill=tk.BOTH) + + self.message = tk.StringVar() + self.message.set("Click Update to update!") + message_label = tk.Label(self.frame, textvariable=self.message) + message_label.grid(columnspan=2, padx=20, pady=20) + + self.update_button = tk.Button(self.frame, text="Update", height=2, width=4, + command=self._update_inara) + self.update_button.grid(row=1, column=0, pady=10) + + config_button = tk.Button(self.frame, text="Config", height=1, width=2, + command=self._update_settings) + config_button.grid(row=1, column=1, sticky=tk.E+tk.S, padx=5, pady=5) + + self._try_login() + + def _update_inara(self, second_try=False): + self.message.set("Updating, please wait...") + self.parent.update() + try: + actions.update_inara(self.session) + self.message.set("Update successful! (Last update: %s)" % + datetime.now().isoformat(' ')[:16]) + except: + if second_try: + self.message.set("Error updating! Double-check your config,\nor try again later.") + else: + # We don't use self._try_login() here because we don't want to disable the update button in this case. + self.session = actions.do_logins(self.settings) + self._update_inara(True) + + def _update_settings(self): + self.settings = utils.update_settings(self._render_config_dialog, self.settings) + self._try_login() + + def _try_login(self): + try: + self.session = actions.do_logins(self.settings) + self.update_button['state'] = tk.NORMAL + except: + self.update_button['state'] = tk.DISABLED + self.message.set("Error logging in. Double-check your config!") + + def _render_config_dialog(self, settings): + dialog = ConfigDialog(self.frame, settings) + + +class ShipFrame(tk.Frame): + INSURANCE = {'0': .05, '1': .04, '2': .02} + + def __init__(self, parent, *args, **kwargs): + tk.Frame.__init__(self, parent, *args, **kwargs) + self.ship_data = [] + name_header = tk.Label(self, text="Ship Name") + name_header.grid() + rebuy_header = tk.Label(self, text="Rebuy") + name_header.grid(column=1) + value_header = tk.Label(self, text="Value") + name_header.grid(column=2) + + def add_ship(self, data): + """ + 'data' should contain the following keys: name, id, rebuy, insurance, date, main, star, description, config, image. + Some of these are probably blank, but we need to propagate all of them to the Inara form eventually. + """ + if not self._validate_data(data): + return False + label = tk.Label(self, text="%s:" % data['name']) + label.grid() + entry = tk.Entry(self, text=value) + entry.grid(column=1) + + ship_value = int(data['rebuy']) / INSURANCE[data['insurance']] + value_label = tk.Label(self, text=str(ship_value)) + value_label.grid(column=2) + + data['rebuy_entry'] = entry + self.ship_data.append(data) + + def _validate_date(self, data): + return all(key in data.keys() for key in + ('name', 'id', 'rebuy', 'insurance', 'date', 'main', 'star', 'description', 'config', 'image')) + + + +class ConfigDialog(tkSimpleDialog.Dialog): + def __init__(self, parent, settings, title="Authentication Data"): + self.settings = settings + self.entries = [] + self.data = [] + tkSimpleDialog.Dialog.__init__(self, parent, title) + + def body(self, parent): + i = 0 + values = [] + + for section, value in (('ed_companion', 'username'), + ('ed_companion', 'password'), + ('inara', 'username'), + ('inara', 'password')): + if self.settings.has_option(section, value): + values.append(self.settings.get(section, value)) + else: + values.append("") + + for field in ("Elite Username (email address):", + "Elite Password:", + "Inara Username:", + "Inara Password:"): + label = tk.Label(parent, text=field) + label.grid(row=i, column=0, sticky=tk.W) + entry = tk.Entry(parent, width=30) + entry.insert(0, values[i]) + entry.grid(row=i, column=1, sticky=tk.E) + self.entries.append(entry) + i += 1 + return self.entries[0] + + def validate(self): + for entry in self.entries: + if entry.get().strip() == "": + tkMessageBox.showwarning("Missing Data", + "You must provide a value for every field.") + return False + return True + + def apply(self): + self.settings.set('ed_companion', 'username', self.entries[0].get().strip()) + self.settings.set('ed_companion', 'password', self.entries[1].get().strip()) + self.settings.set('inara', 'username', self.entries[2].get().strip()) + self.settings.set('inara', 'password', self.entries[3].get().strip()) diff --git a/update_inara.py b/update_inara.py index 0af4eda..954a15e 100755 --- a/update_inara.py +++ b/update_inara.py @@ -1,9 +1,8 @@ #!/usr/bin/python +import actions import argparse -from datetime import datetime -from elite_api import companion -from elite_api.inara import InaraSession +import gui import Tkinter as tk import utils @@ -12,63 +11,12 @@ arg_parser.add_argument("--no-gui", help="Just update and report to the command line.", action="store_false", dest="gui") - -def do_logins(settings): - inara_session = InaraSession(settings.get('inara', 'username'), settings.get('inara', 'password')) - companion.login(settings.get('ed_companion', 'username'), settings.get('ed_companion', 'password')) - return inara_session - - -def update_inara(inara_session): - data = companion.get_data() - inara_session.update_credits(data['commander']['credits']) - inara_session.update_location(data['lastSystem']['name']) - - -class UpdateWindow(object): - def __init__(self, parent, settings): - self.parent = parent - self.settings = settings - self.frame = tk.Frame(parent) - self.frame.pack(expand=True, fill=tk.BOTH) - - self.message = tk.StringVar() - self.message.set("Click Update to update!") - message_label = tk.Label(self.frame, textvariable=self.message) - message_label.grid(columnspan=2, padx=20, pady=20) - - self.update_button = tk.Button(self.frame, text="Update", height=2, width=4, - command=self._update_inara) - self.update_button.grid(row=1, column=0, pady=10) - - config_button = tk.Button(self.frame, text="Config", height=1, width=2, - command=self._update_settings) - config_button.grid(row=1, column=1, sticky=tk.E+tk.S, padx=5, pady=5) - - self._try_login() - - def _update_inara(self): - self.message.set("Updating, please wait...") - self.parent.update() - try: - update_inara(self.session) - self.message.set("Update successful! (Last update: %s)" % - datetime.now().isoformat(' ')[:16]) - except: - self.message.set("Error updating! Double-check your config,\nor try again later.") - - def _update_settings(self): - self.settings = utils.update_settings(True, self.parent, self.settings) - self._try_login() - - def _try_login(self): - try: - self.session = do_logins(self.settings) - self.update_button['state'] = tk.NORMAL - except: - self.update_button['state'] = tk.DISABLED - self.message.set("Error logging in. Double-check your config!") - +def _settings_prompt_cli(settings): + settings.set('ed_companion', 'username', raw_input("Elite Username (email address): ")) + settings.set('ed_companion', 'password', raw_input("Elite Password: ")) + settings.set('inara', 'username', raw_input("Inara Username: ")) + settings.set('inara', 'password', raw_input("Inara Password: ")) + print "To change these settings later, edit " + filename def main(): args = arg_parser.parse_args() @@ -76,13 +24,16 @@ def main(): if args.gui: root = tk.Tk() root.wm_title("Inara Updater") - settings = utils.get_settings(True, root) - app = UpdateWindow(root, settings) + settings = utils.get_settings() + app = gui.UpdateWindow(root, settings) root.mainloop() + else: - settings = utils.get_settings(False) - inara_session = do_logins(settings) - update_inara(inara_session) + settings = utils.get_settings() + if settings is None: + util.update_settings(_settings_prompt_cli, settings) + inara_session = actions.do_logins(settings) + actions.update_inara(inara_session) print("Inara updated!") if __name__ == '__main__': diff --git a/utils.py b/utils.py index b0c72a5..d127479 100644 --- a/utils.py +++ b/utils.py @@ -1,7 +1,5 @@ from ConfigParser import ConfigParser import os -import Tkinter as tk -import tkSimpleDialog, tkMessageBox import platform def get_config_dir(make=False): @@ -15,91 +13,35 @@ def get_config_dir(make=False): def get_settings(use_gui=True, parent=None): """ Try to read the settings from file into ConfigParser object. - If the config file isn't found, initialize it. + If the config file isn't found, return None. """ filename = os.path.join(get_config_dir(), 'settings.conf') settings = ConfigParser() if os.path.isfile(filename): settings.read(filename) + return settings else: try: os.makedirs(get_config_dir()) except: pass + return None - settings = update_settings(use_gui, parent) - - return settings - - -def update_settings(gui=True, parent=None, settings=None): +def update_settings(config_func, settings=None): + """ + This function will initialize settings if it is None, call the passed function + with the settings object as a parameter, then write the settings to the config + file. + """ if settings is None: settings = ConfigParser() settings.add_section('ed_companion') settings.add_section('inara') - if gui: - dialog = ConfigDialog(parent, settings) - else: - _settings_prompt_cli(settings) - print "To change these settings later, edit " + filename + config_func(settings) + with open(os.path.join(get_config_dir(), 'settings.conf'), 'wb') as f: settings.write(f) return settings - - -def _settings_prompt_cli(settings): - settings.set('ed_companion', 'username', raw_input("Elite Username (email address): ")) - settings.set('ed_companion', 'password', raw_input("Elite Password: ")) - settings.set('inara', 'username', raw_input("Inara Username: ")) - settings.set('inara', 'password', raw_input("Inara Password: ")) - - -class ConfigDialog(tkSimpleDialog.Dialog): - def __init__(self, parent, settings, title="Authentication Data"): - self.settings = settings - self.entries = [] - self.data = [] - tkSimpleDialog.Dialog.__init__(self, parent, title) - - def body(self, parent): - i = 0 - values = [] - - for section, value in (('ed_companion', 'username'), - ('ed_companion', 'password'), - ('inara', 'username'), - ('inara', 'password')): - if self.settings.has_option(section, value): - values.append(self.settings.get(section, value)) - else: - values.append("") - - for field in ("Elite Username (email address):", - "Elite Password:", - "Inara Username:", - "Inara Password:"): - label = tk.Label(parent, text=field) - label.grid(row=i, column=0, sticky=tk.W) - entry = tk.Entry(parent, width=30) - entry.insert(0, values[i]) - entry.grid(row=i, column=1, sticky=tk.E) - self.entries.append(entry) - i += 1 - return self.entries[0] - - def validate(self): - for entry in self.entries: - if entry.get().strip() == "": - tkMessageBox.showwarning("Missing Data", - "You must provide a value for every field.") - return False - return True - - def apply(self): - self.settings.set('ed_companion', 'username', self.entries[0].get().strip()) - self.settings.set('ed_companion', 'password', self.entries[1].get().strip()) - self.settings.set('inara', 'username', self.entries[2].get().strip()) - self.settings.set('inara', 'password', self.entries[3].get().strip())