diff --git a/README.md b/README.md index 99598e0..8e452b1 100644 --- a/README.md +++ b/README.md @@ -55,35 +55,64 @@ It is tested with Ubuntu / Windows Subsystem for Linux, Windows. ## Creating an executable for the GUI -Install pyinstaller if not already installed with `pip install pyinstaller`. +Install *pyinstaller* with `pip install pyinstaller`. -Run: `pyinstaller --onefile --noconsole ui.py`. +To create an executable file named *epson_print_conf.exe* from *ui.py*, run the following: -Run the exe file created in the *dist/* folder. +```bash +pyinstaller --onefile ui.py --name epson_print_conf --hidden-import babel.numbers --windowed +``` + +Then run the *epson_print_conf.exe* file created in the *dist/* folder, which has the same options of `ui.py`. + +The package includes another file named *gui.py*, which also automatically loads the configuration file *printer_conf.pickle*, merging it with the program configuration. In this case, the *epson_print_conf.spec* file helps creating an executable with *pyinstaller*. + +Run the following to build the executable: + +```bash +pip install pyinstaller # if not yet installed +curl -o devices.xml https://codeberg.org/attachments/147f41a3-a6ea-45f6-8c2a-25bac4495a1d +python3 parse_devices.py -a 192.168.178.29 -s XP-205 -p printer_conf.pickle # use your default IP address and printer model as default settings for the GUI +pyinstaller epson_print_conf.spec +``` + +Run the *epson_print_conf.exe* file created in the *dist/* folder. This executable program does not have options, embeds the *printer_conf.pickle* file and starts with the default IP address and printer model defined in the build phase. ## Usage -Running the GUI: +### Running the GUI with Python ``` python ui.py ``` -Using the command-line tool: +GUI usage: ``` -usage: epson_print_conf.py [-h] -m MODEL -a HOSTNAME [-p PORT] [-i] [-q QUERY_NAME] [--reset_waste_ink] [-d] - [--write-first-ti-received-time YEAR MONTH DAY] [--write-poweroff-timer MINUTES] - [--dry-run] [-R ADDRESS_SET] [-W ADDRESS_VALUE_SET] - [-e FIRST_ADDRESS LAST_ADDRESS] [--detect-key] [-S SEQUENCE_STRING] [-t TIMEOUT] - [-r RETRIES] [-c CONFIG_FILE] [--simdata SIMDATA_FILE] +ui.py [-h] [-P PICKLE_FILE] [-O] + +optional arguments: + -h, --help show this help message and exit + -P PICKLE_FILE, --pickle PICKLE_FILE + Save a pickle archive for subsequent load by ui.py and epson_print_conf.py + -O, --override Override the default configuration with the one of the pickle file instead of merging + +epson_print_conf GUI +``` + +### Using the command-line tool + +``` +epson_print_conf.py [-h] -m MODEL -a HOSTNAME [-p PORT] [-i] [-q QUERY_NAME] [--reset_waste_ink] [-d] [--write-first-ti-received-time YEAR MONTH DAY] + [--write-poweroff-timer MINUTES] [--dry-run] [-R ADDRESS_SET] [-W ADDRESS_VALUE_SET] [-e FIRST_ADDRESS LAST_ADDRESS] [--detect-key] + [-S SEQUENCE_STRING] [-t TIMEOUT] [-r RETRIES] [-c CONFIG_FILE] [--simdata SIMDATA_FILE] [-P PICKLE_FILE] [-O] optional arguments: -h, --help show this help message and exit -m MODEL, --model MODEL Printer model. Example: -m XP-205 (use ? to print all supported models) -a HOSTNAME, --address HOSTNAME - Printer host name or IP address. (Example: -m 192.168.1.87) + Printer host name or IP address. (Example: -a 192.168.1.87) -p PORT, --port PORT Printer port (default is 161) -i, --info Print all available information and statistics (default option) -q QUERY_NAME, --query QUERY_NAME @@ -98,8 +127,7 @@ optional arguments: -R ADDRESS_SET, --read-eeprom ADDRESS_SET Read the values of a list of printer EEPROM addreses. Format is: address [, ...] -W ADDRESS_VALUE_SET, --write-eeprom ADDRESS_VALUE_SET - Write related values to a list of printer EEPROM addresses. Format is: address: value - [, ...] + Write related values to a list of printer EEPROM addresses. Format is: address: value [, ...] -e FIRST_ADDRESS LAST_ADDRESS, --eeprom-dump FIRST_ADDRESS LAST_ADDRESS Dump EEPROM --detect-key Detect the read_key via brute force @@ -110,10 +138,12 @@ optional arguments: -r RETRIES, --retries RETRIES SNMP GET retries (floating point argument) -c CONFIG_FILE, --config CONFIG_FILE - read a configuration file including the full log dump of a previous operation with - '-d' flag (instead of accessing the printer via SNMP) + read a configuration file including the full log dump of a previous operation with '-d' flag (instead of accessing the printer via SNMP) --simdata SIMDATA_FILE write SNMP dictionary map to simdata file + -P PICKLE_FILE, --pickle PICKLE_FILE + Load a pickle configuration archive + -O, --override Override the default configuration with the one of the pickle file instead of merging Epson Printer Configuration via SNMP (TCP/IP) ``` @@ -160,7 +190,7 @@ Note: resetting the ink waste counter is just removing a warning; not replacing Within an [issue](https://codeberg.org/atufi/reinkpy/issues/12#issue-716809) in repo https://codeberg.org/atufi/reinkpy there is an interesting [attachment](https://codeberg.org/attachments/147f41a3-a6ea-45f6-8c2a-25bac4495a1d) which reports an extensive XML database of Epson model features. -The program "parse_devices.py" transforms this XML DB into the dictionary that *epson_print_conf.py* can use. +The program *parse_devices.py* transforms this XML DB into the dictionary that *epson_print_conf.py* can use. Here is a simple procedure to download that DB and run *parse_devices.py* to search for the XP-205 model and produce the related PRINTER_CONFIG dictionary to the standard output: @@ -169,14 +199,15 @@ curl -o devices.xml https://codeberg.org/attachments/147f41a3-a6ea-45f6-8c2a-25b python3 parse_devices.py -i -m XP-205 ``` -After generating the related printer configuration, *epson_print_conf.py* shall be manually edited to copy/paste the output of *parse_devices.py* within its PRINTER_CONFIG dictionary. +After generating the related printer configuration, *epson_print_conf.py* shall be manually edited to copy/paste the output of *parse_devices.py* within its PRINTER_CONFIG dictionary. Alternatively, the program is able to create a *pickle* configuration file, which the other programs can load. The `-m` option is optional and is used to filter the printer model in scope. If the produced output is not referred to the target model, use part of the model name as a filter (e.g., only the digits, like `parse_devices.py -i -m 315`) and select the appropriate model from the output. Program usage: ``` -parse_devices.py [-h] [-m PRINTER_MODEL] [-l LINE_LENGTH] [-i] [-d] [-t] [-v] [-f] [-e] [-c CONFIG_FILE] +parse_devices.py [-h] [-m PRINTER_MODEL] [-l LINE_LENGTH] [-i] [-d] [-t] [-v] [-f] [-e] [-c CONFIG_FILE] [-s DEFAULT_MODEL] -a HOSTNAME [-p PICKLE_FILE] [-I] + [-N] [-A] [-S] optional arguments: -h, --help show this help message and exit @@ -192,6 +223,16 @@ optional arguments: -e, --errors Add last_printer_fatal_errors -c CONFIG_FILE, --config CONFIG_FILE use the XML configuration file to generate the configuration + -s DEFAULT_MODEL, --default_model DEFAULT_MODEL + Default printer model. Example: -s XP-205 + -a HOSTNAME, --address HOSTNAME + Default printer host name or IP address. (Example: -a 192.168.1.87) + -p PICKLE_FILE, --pickle PICKLE_FILE + Save a pickle archive for subsequent load by ui.py and epson_print_conf.py + -I, --keep_invalid Do not remove printers without write_key or without read_key + -N, --keep_names Do not replace original names with converted names and add printers for all optional names + -A, --no_alias Do not add aliases for same printer with different names and remove aliased printers + -S, --no_same_as Do not add "same-as" for similar printers with different names Generate printer configuration from devices.xml ``` @@ -316,9 +357,11 @@ AC = Value ### Specification ```python -EpsonPrinter(model, hostname, port, timeout, retries, dry_run) +EpsonPrinter(conf_dict, replace_conf, model, hostname, port, timeout, retries, dry_run) ``` +- `conf_dict`: optional configuration file in place of the default PRINTER_CONFIG (optional, default to `{}`) +- `replace_conf`: (optional, default to False) set to True to replace PRINTER_CONFIG with `conf_dict` instead of merging it - `model`: printer model - `hostname`: IP address or network name of the printer - `port`: SNMP port number (default is 161) diff --git a/epson_print_conf.py b/epson_print_conf.py index 924d7cb..9367a5a 100644 --- a/epson_print_conf.py +++ b/epson_print_conf.py @@ -643,6 +643,8 @@ class EpsonPrinter: def __init__( self, + conf_dict: dict = {}, + replace_conf = False, model: str = None, hostname: str = None, port: int = 161, @@ -651,7 +653,19 @@ class EpsonPrinter: dry_run: bool = False ) -> None: """Initialise printer model.""" + def merge(source, destination): + for key, value in source.items(): + if isinstance(value, dict): + merge(value, destination.setdefault(key, {})) + else: + if key == "alias" and "alias" in destination: + destination[key] += value + else: + destination[key] = value + return destination # process "alias" definintion + if conf_dict and replace_conf: + self.PRINTER_CONFIG = conf_dict for printer_name, printer_data in self.PRINTER_CONFIG.copy().items(): if "alias" in printer_data: aliases = printer_data["alias"] @@ -672,6 +686,16 @@ class EpsonPrinter: ) else: self.PRINTER_CONFIG[alias_name] = printer_data + if conf_dict and not replace_conf: + self.PRINTER_CONFIG = merge(self.PRINTER_CONFIG, conf_dict) + for key, values in self.PRINTER_CONFIG.items(): + if 'alias' in values: + values['alias'] = [ + i for i in values['alias'] + if i not in self.PRINTER_CONFIG + ] + if not values['alias']: + del values['alias'] # process "same-as" definintion for printer_name, printer_data in self.PRINTER_CONFIG.copy().items(): if "same-as" in printer_data: @@ -2035,7 +2059,7 @@ if __name__ == "__main__": '--address', dest='hostname', action="store", - help='Printer host name or IP address. (Example: -m 192.168.1.87)', + help='Printer host name or IP address. (Example: -a 192.168.1.87)', required=True) parser.add_argument( '-p', @@ -2174,6 +2198,24 @@ if __name__ == "__main__": nargs=1, metavar='SIMDATA_FILE' ) + parser.add_argument( + '-P', + "--pickle", + dest='pickle', + type=argparse.FileType('rb'), + help="Load a pickle configuration archive", + default=None, + nargs=1, + metavar='PICKLE_FILE' + ) + parser.add_argument( + '-O', + "--override", + dest='override', + action='store_true', + help="Override the default configuration with the one of the pickle " + "file instead of merging", + ) args = parser.parse_args() logging_level = logging.WARNING @@ -2198,7 +2240,13 @@ if __name__ == "__main__": if args.debug: logging.getLogger().setLevel(logging.DEBUG) + conf_dict = {} + if args.pickle: + conf_dict = pickle.load(args.pickle[0]) + printer = EpsonPrinter( + conf_dict=conf_dict, + replace_conf=args.override, model=args.model, hostname=args.hostname, port=args.port, diff --git a/gui.py b/gui.py new file mode 100644 index 0000000..1e78e04 --- /dev/null +++ b/gui.py @@ -0,0 +1,11 @@ +import pickle +from ui import EpsonPrinterUI +from os import path + +PICKLE_CONF_FILE = "printer_conf.pickle" + +path_to_pickle = path.abspath(path.join(path.dirname(__file__), PICKLE_CONF_FILE)) +with open(path_to_pickle, 'rb') as fp: + conf_dict = pickle.load(fp) +app = EpsonPrinterUI(conf_dict=conf_dict, replace_conf=False) +app.mainloop() diff --git a/parse_devices.py b/parse_devices.py index 8638aa0..586e08a 100644 --- a/parse_devices.py +++ b/parse_devices.py @@ -219,71 +219,81 @@ def generate_config(config, traverse, add_fatal_errors, full, printer_model): printer_config[printer_short_name] = chars return printer_config -def normalize_config(config): +def normalize_config( + config, + remove_invalid, + expand_names, + add_alias, + add_same_as, + ): # Remove printers without write_key or without read_key - for base_key, base_items in config.copy().items(): - if 'write_key' not in base_items: - del config[base_key] - continue - if 'read_key' not in base_items: - del config[base_key] - continue + if remove_invalid: + for base_key, base_items in config.copy().items(): + if 'write_key' not in base_items: + del config[base_key] + continue + if 'read_key' not in base_items: + del config[base_key] + continue # Replace original names with converted names and add printers for all optional names - for key, items in config.copy().items(): - printer_list = get_printer_models(key) - del config[key] - for i in printer_list: - if i in config and config[i] != items: - print("ERROR key", key) - quit() - config[i] = items + if expand_names: + for key, items in config.copy().items(): + printer_list = get_printer_models(key) + del config[key] + for i in printer_list: + if i in config and config[i] != items: + print("ERROR key", key) + quit() + config[i] = items # Add aliases for same printer with different names and remove aliased printers - for base_key, base_items in config.copy().items(): - found = False - for key, items in config.copy().items(): - if not found: - if base_key == key and base_key in config: - found = True - continue - if base_key != key and items == base_items: # different name, same printer - if "alias" not in config[base_key]: - config[base_key]["alias"] = [] - for i in get_printer_models(key): - if i not in config[base_key]["alias"]: - config[base_key]["alias"].append(i) - del config[key] + if add_alias: + for base_key, base_items in config.copy().items(): + found = False + for key, items in config.copy().items(): + if not found: + if base_key == key and base_key in config: + found = True + continue + if base_key != key and items == base_items: # different name, same printer + if "alias" not in config[base_key]: + config[base_key]["alias"] = [] + for i in get_printer_models(key): + if i not in config[base_key]["alias"]: + config[base_key]["alias"].append(i) + del config[key] # Add "same-as" for almost same printer (IGNORED_KEYS) with different names - IGNORED_KEYS = ['write_key', 'read_key', 'alias', 'main_waste', 'borderless_waste'] - for base_key, base_items in config.copy().items(): - found = False - for key, items in config.copy().items(): - if not found: - if base_key == key and base_key in config: - found = True - continue - if base_key != key: - if equal_dicts(base_items, items, IGNORED_KEYS): # everything but the IGNORED_KEYS is the same - # Get the IGNORED_KEYS from the printer - write_key = base_items['write_key'] - read_key = base_items['read_key'] - alias = base_items['alias'] if 'alias' in base_items else [] - main_waste = base_items['main_waste'] if 'main_waste' in base_items else [] - borderless_waste = base_items['borderless_waste'] if 'borderless_waste' in base_items else [] - # Rebuild the printer with only the IGNORED_KEYS, then add the 'same-as' - del config[base_key] - config[base_key] = {} - config[base_key]['write_key'] = write_key - config[base_key]['read_key'] = read_key - if alias: - config[base_key]['alias'] = alias - if main_waste: - config[base_key]['main_waste'] = main_waste - if borderless_waste: - config[base_key]['borderless_waste'] = borderless_waste - config[base_key]['same-as'] = key + if add_same_as: + IGNORED_KEYS = ['write_key', 'read_key', 'alias', 'main_waste', 'borderless_waste'] + for base_key, base_items in config.copy().items(): + found = False + for key, items in config.copy().items(): + if not found: + if base_key == key and base_key in config: + found = True + continue + if base_key != key: + if equal_dicts(base_items, items, IGNORED_KEYS): # everything but the IGNORED_KEYS is the same + # Get the IGNORED_KEYS from the printer + write_key = base_items['write_key'] + read_key = base_items['read_key'] + alias = base_items['alias'] if 'alias' in base_items else [] + main_waste = base_items['main_waste'] if 'main_waste' in base_items else [] + borderless_waste = base_items['borderless_waste'] if 'borderless_waste' in base_items else [] + # Rebuild the printer with only the IGNORED_KEYS, then add the 'same-as' + del config[base_key] + config[base_key] = {} + config[base_key]['write_key'] = write_key + config[base_key]['read_key'] = read_key + if alias: + config[base_key]['alias'] = alias + if main_waste: + config[base_key]['main_waste'] = main_waste + if borderless_waste: + config[base_key]['borderless_waste'] = borderless_waste + config[base_key]['same-as'] = key return config @@ -294,69 +304,69 @@ def equal_dicts(a, b, ignore_keys): if __name__ == "__main__": import argparse + import pickle parser = argparse.ArgumentParser( epilog='Generate printer configuration from devices.xml' ) - parser.add_argument( '-m', '--model', dest='printer_model', default=False, action="store", - help='Printer model. Example: -m XP-205') - + help='Printer model. Example: -m XP-205' + ) parser.add_argument( '-l', '--line', dest='line_length', type=int, help='Set line length of the output (default: 120)', - default=120) - + default=120 + ) parser.add_argument( '-i', '--indent', dest='indent', action='store_true', - help='Indent output of 4 spaces') - + help='Indent output of 4 spaces' + ) parser.add_argument( '-d', '--debug', dest='debug', action='store_true', - help='Print debug information') - + help='Print debug information' + ) parser.add_argument( '-t', '--traverse', dest='traverse', action='store_true', - help='Traverse the XML, dumping content related to the printer model') - + help='Traverse the XML, dumping content related to the printer model' + ) parser.add_argument( '-v', '--verbose', dest='verbose', action='store_true', - help='Print verbose information') - + help='Print verbose information' + ) parser.add_argument( '-f', '--full', dest='full', action='store_true', - help='Generate additional tags') - + help='Generate additional tags' + ) parser.add_argument( '-e', '--errors', dest='add_fatal_errors', action='store_true', - help='Add last_printer_fatal_errors') - + help='Add last_printer_fatal_errors' + ) parser.add_argument( '-c', "--config", @@ -367,6 +377,59 @@ if __name__ == "__main__": nargs=1, metavar='CONFIG_FILE' ) + parser.add_argument( + '-s', + '--default_model', + dest='default_model', + action="store", + help='Default printer model. Example: -s XP-205' + ) + parser.add_argument( + '-a', + '--address', + dest='hostname', + action="store", + help='Default printer host name or IP address. (Example: -a 192.168.1.87)', + required=True + ) + parser.add_argument( + '-p', + "--pickle", + dest='pickle', + type=argparse.FileType('wb'), + help="Save a pickle archive for subsequent load by ui.py and epson_print_conf.py", + default=0, + nargs=1, + metavar='PICKLE_FILE' + ) + parser.add_argument( + '-I', + '--keep_invalid', + dest='keep_invalid', + action='store_true', + help='Do not remove printers without write_key or without read_key' + ) + parser.add_argument( + '-N', + '--keep_names', + dest='keep_names', + action='store_true', + help='Do not replace original names with converted names and add printers for all optional names' + ) + parser.add_argument( + '-A', + '--no_alias', + dest='no_alias', + action='store_true', + help='Do not add aliases for same printer with different names and remove aliased printers' + ) + parser.add_argument( + '-S', + '--no_same_as', + dest='no_same_as', + action='store_true', + help='Do not add "same-as" for similar printers with different names' + ) args = parser.parse_args() if args.debug: @@ -390,7 +453,26 @@ if __name__ == "__main__": full=args.full, printer_model=args.printer_model ) - normalized_config = normalize_config(printer_config) + normalized_config = normalize_config( + config=printer_config, + remove_invalid=not args.keep_invalid, + expand_names=not args.keep_names, + add_alias=not args.no_alias, + add_same_as=not args.no_same_as, + ) + if args.default_model: + if "internal_data" not in normalized_config: + normalized_config["internal_data"] = {} + normalized_config["internal_data"]["default_model"] = args.default_model + if args.hostname: + if "internal_data" not in normalized_config: + normalized_config["internal_data"] = {} + normalized_config["internal_data"]["hostname"] = args.hostname + if args.pickle: + pickle.dump(normalized_config, args.pickle[0]) # serialize the list + args.pickle[0].close() + quit() + try: import black config_str = "PRINTER_CONFIG = " + repr(normalized_config) diff --git a/printer_conf.pickle b/printer_conf.pickle new file mode 100644 index 0000000..e89841f Binary files /dev/null and b/printer_conf.pickle differ diff --git a/ui.py b/ui.py index facd029..b4cbaf2 100644 --- a/ui.py +++ b/ui.py @@ -125,7 +125,7 @@ class ToolTip: class EpsonPrinterUI(tk.Tk): - def __init__(self): + def __init__(self, conf_dict={}, replace_conf=False): super().__init__() self.title("Epson Printer Configuration - v" + VERSION) self.geometry("450x500") @@ -133,6 +133,8 @@ class EpsonPrinterUI(tk.Tk): self.printer_scanner = PrinterScanner() self.ip_list = [] self.ip_list_cycle = None + self.conf_dict = conf_dict + self.replace_conf = replace_conf # configure the main window to be resizable self.columnconfigure(0, weight=1) @@ -167,13 +169,21 @@ class EpsonPrinterUI(tk.Tk): model_frame.columnconfigure(1, weight=1) self.model_var = tk.StringVar() + if ( + "internal_data" in conf_dict + and "default_model" in conf_dict["internal_data"] + ): + self.model_var.set(conf_dict["internal_data"]["default_model"]) ttk.Label(model_frame, text="Model:").grid( row=0, column=0, sticky=tk.W, padx=PADX ) self.model_dropdown = ttk.Combobox( model_frame, textvariable=self.model_var, state="readonly" ) - self.model_dropdown["values"] = sorted(EpsonPrinter().valid_printers) + self.model_dropdown["values"] = sorted(EpsonPrinter( + conf_dict=self.conf_dict, + replace_conf=self.replace_conf + ).valid_printers) self.model_dropdown.grid( row=0, column=1, pady=PADY, padx=PADX, sticky=(tk.W, tk.E) ) @@ -193,6 +203,11 @@ class EpsonPrinterUI(tk.Tk): ip_frame.columnconfigure(1, weight=1) self.ip_var = tk.StringVar() + if ( + "internal_data" in conf_dict + and "hostname" in conf_dict["internal_data"] + ): + self.ip_var.set(conf_dict["internal_data"]["hostname"]) ttk.Label(ip_frame, text="IP Address:").grid( row=0, column=0, sticky=tk.W, padx=PADX ) @@ -446,7 +461,12 @@ class EpsonPrinterUI(tk.Tk): self.config(cursor="") self.update() return - printer = EpsonPrinter(model=model, hostname=ip_address) + printer = EpsonPrinter( + conf_dict=self.conf_dict, + replace_conf=self.replace_conf, + model=model, + hostname=ip_address + ) try: po_timer = printer.stats()["stats"]["Power off timer"] self.status_text.insert( @@ -478,7 +498,12 @@ class EpsonPrinterUI(tk.Tk): self.config(cursor="") self.update_idletasks() return - printer = EpsonPrinter(model=model, hostname=ip_address) + printer = EpsonPrinter( + conf_dict=self.conf_dict, + replace_conf=self.replace_conf, + model=model, + hostname=ip_address + ) try: po_timer = printer.stats()["stats"]["Power off timer"] po_timer = self.po_timer_var.get() @@ -525,7 +550,12 @@ class EpsonPrinterUI(tk.Tk): self.config(cursor="") self.update_idletasks() return - printer = EpsonPrinter(model=model, hostname=ip_address) + printer = EpsonPrinter( + conf_dict=self.conf_dict, + replace_conf=self.replace_conf, + model=model, + hostname=ip_address + ) try: date_string = datetime.strptime( printer.stats()["stats"]["First TI received time"], "%d %b %Y" @@ -560,7 +590,12 @@ class EpsonPrinterUI(tk.Tk): self.config(cursor="") self.update_idletasks() return - printer = EpsonPrinter(model=model, hostname=ip_address) + printer = EpsonPrinter( + conf_dict=self.conf_dict, + replace_conf=self.replace_conf, + model=model, + hostname=ip_address + ) try: date_string = datetime.strptime( printer.stats()["stats"]["First TI received time"], "%d %b %Y" @@ -624,7 +659,12 @@ class EpsonPrinterUI(tk.Tk): self.config(cursor="") self.update_idletasks() return - printer = EpsonPrinter(model=model, hostname=ip_address) + printer = EpsonPrinter( + conf_dict=self.conf_dict, + replace_conf=self.replace_conf, + model=model, + hostname=ip_address + ) try: self.show_treeview() @@ -662,7 +702,12 @@ class EpsonPrinterUI(tk.Tk): self.config(cursor="") self.update_idletasks() return - printer = EpsonPrinter(model=model, hostname=ip_address) + printer = EpsonPrinter( + conf_dict=self.conf_dict, + replace_conf=self.replace_conf, + model=model, + hostname=ip_address + ) try: printer.stats() # query the printer first response = messagebox.askyesno( @@ -714,7 +759,10 @@ class EpsonPrinterUI(tk.Tk): ) self.ip_var.set(printers[0]["ip"]) for model in get_printer_models(printers[0]["name"]): - if model in EpsonPrinter().valid_printers: + if model in EpsonPrinter( + conf_dict=self.conf_dict, + replace_conf=self.replace_conf + ).valid_printers: self.model_var.set(model) break else: @@ -835,5 +883,34 @@ class EpsonPrinterUI(tk.Tk): if __name__ == "__main__": - app = EpsonPrinterUI() + import argparse + import pickle + + parser = argparse.ArgumentParser( + epilog='epson_print_conf GUI' + ) + parser.add_argument( + '-P', + "--pickle", + dest='pickle', + type=argparse.FileType('rb'), + help="Save a pickle archive for subsequent load by ui.py and epson_print_conf.py", + default=None, + nargs=1, + metavar='PICKLE_FILE' + ) + parser.add_argument( + '-O', + "--override", + dest='override', + action='store_true', + help="Override the default configuration with the one of the pickle " + "file instead of merging", + ) + args = parser.parse_args() + conf_dict = {} + if args.pickle: + conf_dict = pickle.load(args.pickle[0]) + + app = EpsonPrinterUI(conf_dict=conf_dict, replace_conf=args.override) app.mainloop()