# HG changeset patch # User Paul Boddie # Date 1508015716 -7200 # Node ID 843793de5ac04a507c904c676145cd59fa7918da # Parent e6f48190f9b35a6310440736f0e9885cbafad779 Reorganised command line argument/option processing and help text generation. diff -r e6f48190f9b3 -r 843793de5ac0 imiptools/__init__.py --- a/imiptools/__init__.py Sat Oct 14 19:11:58 2017 +0200 +++ b/imiptools/__init__.py Sat Oct 14 23:15:16 2017 +0200 @@ -36,9 +36,13 @@ # Processing of incoming messages. def get_all_values(msg, key): + + "Return all values in 'msg' for 'key'." + l = [] for v in msg.get_all(key) or []: - l += [s.strip() for s in v.split(",")] + for s in v.split(","): + l.append(s.strip()) return l class Processor: @@ -127,90 +131,25 @@ given 'stream'. """ - # Obtain the different kinds of recipients plus sender address. - - original_recipients = [] - recipients = [] - senders = [] - lmtp = [] - store_type = [] - store_dir = [] - publishing_dir = [] - preferences_dir = [] - journal_dir = [] - local_smtp = False - - l = [] - - for arg in args: - - # Switch to collecting recipients. - - if arg == "-o": - l = original_recipients - - # Switch to collecting senders. - - elif arg == "-s": - l = senders - - # Switch to getting the LMTP socket. - - elif arg == "-l": - l = lmtp - - # Detect sending to local users via SMTP. + args = parse_args(args, {"--show-config" : ("show_config", False)}) - elif arg == "-L": - local_smtp = True - - # Switch to getting the store type. - - elif arg == "-T": - l = store_type - - # Switch to getting the store directory. - - elif arg == "-S": - l = store_dir - - # Switch to getting the publishing directory. - - elif arg == "-P": - l = publishing_dir - - # Switch to getting the preferences directory. - - elif arg == "-p": - l = preferences_dir - - # Switch to getting the journal directory. - - elif arg == "-j": - l = journal_dir - - # Ignore debugging options. - - elif arg == "-d": - self.debug = True - else: - l.append(arg) - - getvalue = lambda value, default=None: value and value[0] or default - - self.messenger = Messenger(lmtp_socket=getvalue(lmtp), local_smtp=local_smtp, sender=getvalue(senders)) + self.debug = args["debug"] # Obtain arguments or configured defaults. - self.store_type = getvalue(store_type, settings["STORE_TYPE"]) - self.store_dir = getvalue(store_dir, settings["STORE_DIR"]) - self.journal_dir = getvalue(journal_dir, settings["JOURNAL_DIR"]) - self.preferences_dir = getvalue(preferences_dir, settings["PREFERENCES_DIR"]) - self.publishing_dir = getvalue(publishing_dir, settings["PUBLISH_DIR"]) + self.store_type = args.get("store_type") or settings["STORE_TYPE"] + self.store_dir = args.get("store_dir") or settings["STORE_DIR"] + self.journal_dir = args.get("journal_dir") or settings["JOURNAL_DIR"] + self.preferences_dir = args.get("preferences_dir") or settings["PREFERENCES_DIR"] + self.publishing_dir = args.get("publishing_dir") or settings["PUBLISH_DIR"] + + self.messenger = Messenger(lmtp_socket=args["lmtp"], + local_smtp=args["local_smtp"], + sender=(args["senders"] or [None])[0]) # Show configuration and exit if requested. - if "--show-config" in args: + if args["show_config"]: print """\ Store type: %s Store directory: %s @@ -229,7 +168,7 @@ # Process the input. - self.process(stream, original_recipients) + self.process(stream, args["original_recipients"]) def __call__(self): @@ -240,54 +179,18 @@ args = sys.argv[1:] - if "--help" in args: - print >>sys.stderr, """\ -Usage: %s [ -o ... ] [-s ... ] [ -l | -L ] \\ - [ -T ] [ -P ] \\ - [ -p ] [ -j ] \\ - [ -d ] [ --show-config ] - -Address options: - --o Indicate the original recipients of the message, overriding any found in - the message headers --s Indicate the senders of the message, overriding any found in the message - headers - -Delivery options: - --l The socket filename for LMTP communication with a mailbox solution, - selecting the LMTP delivery method --L Selects the local SMTP delivery method, requiring a suitable mail system - configuration + # Show the help text if requested. -(Where a program needs to deliver messages, one of the above options must be -specified.) - -Configuration options (overriding configured defaults): - --j Indicates the location of quota-related journal information --P Indicates the location of published free/busy resources --p Indicates the location of user preference directories --S Indicates the location of the calendar data store containing user storage - directories --T Indicates the store and journal type (the configured value if omitted) + if "--help" in args: + show_help(os.path.split(sys.argv[0])[-1]) -Output options: - --d Run in debug mode, producing informative output describing the behaviour - of the program, displaying responses on standard output instead of sending - messages - -Diagnostic options: - ---show-config Show the configuration with the specified options and exit - without performing any actions -""" % os.path.split(sys.argv[0])[-1] + # In debug mode, process the message without exception handling. elif "-d" in args: self.process_args(args, sys.stdin) + + # Otherwise, process the message and handle exceptions gracefully. + else: try: self.process_args(args, sys.stdin) @@ -465,4 +368,118 @@ else: return False +# Standard arguments used by imip-agent programs. + +def parse_args(args, extra_argdefs=None): + + """ + Interpret the given program arguments 'args'. Any 'extra_argdefs' define a + mapping from option arguments to (option name, starting value) tuples to be + considered in addition to (or as replacements for) the default definitions. + """ + + argdefs = { + "-d" : ("debug", False), + "-j" : ("journal_dir", None), + "-l" : ("lmtp", None), + "-L" : ("local_smtp", False), + "-o" : ("original_recipients", []), + "-p" : ("preferences_dir", None), + "-P" : ("publishing_dir", None), + "-s" : ("senders", []), + "-S" : ("store_dir", None), + "-T" : ("store_type", None), + } + + argdefs.update(extra_argdefs) + + l = [] + option = None + + for arg in args: + + # Set any selected option value. + + if option and argdefs.has_key(option): + name, value = argdefs[option] + argdefs[option] = name, arg + option = None + + # Where recognised, obtain the option name and value. + + elif argdefs.has_key(arg): + name, value = argdefs[arg] + + # For boolean options, invert the current value. + + if isinstance(value, bool): + argdefs[arg] = name, not value + + # For list options, switch to the given list and collect arguments. + + elif isinstance(value, list): + l = value + + # Otherwise, select the option. + + else: + option = arg + + # Where unrecognised, collect the argument in the current list. + + else: + l.append(arg) + + # Return a mapping from option names to values. + + return dict(argdefs.values()) + +def show_help(progname): + print >>sys.stderr, help_text % progname + +help_text = """\ +Usage: %s [ -o ... ] [-s ... ] [ -l | -L ] \\ + [ -T ] [ -P ] \\ + [ -p ] [ -j ] \\ + [ -d ] [ --show-config ] + +Address options: + +-o Indicate the original recipients of the message, overriding any found in + the message headers +-s Indicate the senders of the message, overriding any found in the message + headers + +Delivery options: + +-l The socket filename for LMTP communication with a mailbox solution, + selecting the LMTP delivery method +-L Selects the local SMTP delivery method, requiring a suitable mail system + configuration + +(Where a program needs to deliver messages, one of the above options must be +specified.) + +Configuration options (overriding configured defaults): + +-j Indicates the location of quota-related journal information +-P Indicates the location of published free/busy resources +-p Indicates the location of user preference directories +-S Indicates the location of the calendar data store containing user storage + directories +-T Indicates the store and journal type (the configured value if omitted) + +Output options: + +-d Run in debug mode, producing informative output describing the behaviour + of the program, displaying responses on standard output instead of sending + messages + +Diagnostic options: + +--show-config Show the configuration with the specified options and exit + without performing any actions +""" + # vim: tabstop=4 expandtab shiftwidth=4