[PATCH 03/17] Convert to use OptionParser for command line handling.

Sebastian Spaeth Sebastian at SSpaeth.de
Mon Nov 29 16:02:11 GMT 2010


This version is feature-identical to before. With this change, we
should have feature and behavior parity with jgoerzen's original
offlineimap again.

Signed-off-by: Sebastian Spaeth <Sebastian at SSpaeth.de>
---
 bin/offlineimap        |    4 +-
 offlineimap.py         |    4 +-
 offlineimap/init.py    |  222 ++++++++++++++++++++++++++++++++++--------------
 offlineimap/version.py |   94 --------------------
 4 files changed, 161 insertions(+), 163 deletions(-)

diff --git a/bin/offlineimap b/bin/offlineimap
index 420ddb0..e78e6e0 100755
--- a/bin/offlineimap
+++ b/bin/offlineimap
@@ -19,5 +19,5 @@
 
 from offlineimap import OfflineImap
 
-offlineimap = OfflineImap()
-offlineimap.startup('6.2.0')
+OfflineImap()
+
diff --git a/offlineimap.py b/offlineimap.py
index 566bd36..24255d3 100755
--- a/offlineimap.py
+++ b/offlineimap.py
@@ -19,5 +19,5 @@
 
 from offlineimap import OfflineImap
 
-offlineimap = OfflineImap()
-offlineimap.startup('6.2.0')
+OfflineImap()
+
diff --git a/offlineimap/init.py b/offlineimap/init.py
index 5f7f007..05bcec9 100644
--- a/offlineimap/init.py
+++ b/offlineimap/init.py
@@ -21,11 +21,13 @@ from offlineimap import imapserver, threadutil, version, syncmaster, accounts
 from offlineimap.localeval import LocalEval
 from offlineimap.threadutil import InstanceLimitedThread, ExitNotifyThread
 import offlineimap.ui
+from offlineimap.ui.detector import DEFAULT_UI_LIST
 import os, sys
 from offlineimap.CustomConfig import CustomConfigParser as ConfigParser
 import threading, socket
-from getopt import getopt
+from optparse import OptionParser
 import signal
+import logging
 
 try:
     import fcntl
@@ -37,6 +39,9 @@ lockfd = None
 
 class OfflineImap:
 
+    def __init__(self):
+        self.parse_commandline()
+
     def lock(self, config, ui):
         global lockfd, hasfcntl
         if not hasfcntl:
@@ -48,80 +53,167 @@ class OfflineImap:
             ui.locked()
             ui.terminate(1)
     
-    def startup(self, versionno):
-        assert versionno == version.versionstr, "Revision of main program (%s) does not match that of library (%s).  Please double-check your PYTHONPATH and installation locations." % (versionno, version.versionstr)
-        options = {}
-        options['-k'] = []
-        if '--help' in sys.argv[1:]:
-            sys.stdout.write(version.getcmdhelp() + "\n")
-            sys.exit(0)
-    
-        for optlist in getopt(sys.argv[1:], 'P:1oqa:c:d:l:u:hk:f:')[0]:
-            if optlist[0] == '-k':
-                options[optlist[0]].append(optlist[1])
-            else:
-                options[optlist[0]] = optlist[1]
-    
-        if options.has_key('-h'):
-            sys.stdout.write(version.getcmdhelp())
-            sys.stdout.write("\n")
-            sys.exit(0)
-        configfilename = os.path.expanduser("~/.offlineimaprc")
-        if options.has_key('-c'):
-            configfilename = options['-c']
-        if options.has_key('-P'):
-            if not options.has_key('-1'):
-                sys.stderr.write("FATAL: profile mode REQUIRES -1\n")
-                sys.exit(100)
-            profiledir = options['-P']
-            os.mkdir(profiledir)
-            threadutil.setprofiledir(profiledir)
-            sys.stderr.write("WARNING: profile mode engaged;\nPotentially large data will be created in " + profiledir + "\n")
+    def parse_commandline(self):
+        """Parse the commandline and invoke everything"""
+
+        parser = OptionParser()
+        parser.add_option("-1",
+                  action="store_true", dest="singlethreading",
+                  default=False,
+                  help="Disable all multithreading  operations and use "
+              "solely a single-thread sync. This effectively sets the "
+              "maxsyncaccounts and all maxconnections configuration file "
+              "variables to 1.")
+
+        parser.add_option("-P", dest="profiledir", metavar="DIR",
+                  help="Sets OfflineIMAP into profile mode. The program "
+              "will create DIR (it must not already exist). "
+              "As it runs, Python profiling information about each "
+              "thread  is  logged  into  profiledir.  Please note: "
+              "This option is present for debugging and optimization "
+              "only, and should NOT be used unless you have a "
+              "specific reason to do so. It  will  significantly "
+              "slow  program  performance, may reduce reliability, "
+              "and can generate huge amounts of  data. This option "
+              "implies the -1 option.")
+
+        parser.add_option("-a", dest="accounts", metavar="ACCOUNTS",
+                  help="""Overrides  the accounts section in the config file.
+              Lets you specify a particular  account  or  set  of
+              accounts  to sync without having to edit the config
+              file. You  might  use  this  to  exclude  certain accounts,
+              or to sync some accounts that you normally prefer not to.""")
+
+        parser.add_option("-c", dest="configfile", metavar="FILE",
+                  default="~/.offlineimaprc",
+                  help="Specifies a configuration file to use in lieu of "
+                       "the default, ~/.offlineimaprc.")
+
+        parser.add_option("-d", dest="debugtype", metavar="type1,[type2...]",
+                  help=
+              "Enables debugging for OfflineIMAP.  This is useful "
+              "if you are trying to track down a malfunction or "
+              "figure out what is going on under the hood.  I suggest "
+              "that you use this with -1 in order to make the "
+              "results more sensible. This option requires one or more "
+              "debugtypes, separated by commas. "
+              "These define what exactly  will be debugged, "
+              "and so far include two options: imap, "
+              "maildir or ALL.  The imap option will enable IMAP protocol "
+              "stream and parsing debugging.  Note that the output "
+              "may contain passwords, so take care to remove  that "
+              "from the debugging output before sending it to anyone else. "
+              "The maildir option will enable debugging "
+              "for certain Maildir operations.")
+
+        parser.add_option("-l", dest="logfile", metavar="FILE",
+                  help="Log to FILE")
+
+        parser.add_option("-f", dest="folders", metavar="folder1,[folder2...]",
+                  help=
+              """Only sync the specified folders.  The "foldername"s
+              are    the   *untranslated*    foldernames.    This
+              command-line  option  overrides any  "folderfilter"
+              and "folderincludes" options  in the  configuration 
+              file.""")
+
+        parser.add_option("-k", dest="configoverride",
+                  action="append",
+                  metavar="[section:]option=value",
+                  help=
+        """Override configuration file option.  If"section" is
+              omitted, it defaults to "general".  Any underscores
+              "_" in the section name are replaced with spaces:
+              for instance,  to override  option "autorefresh" in
+              the "[Account Personal]" section in the config file
+              one would use "-k Account_Personal:autorefresh=30".""")
+
+        parser.add_option("-o",
+                  action="store_true", dest="runonce",
+                  default=False,
+                  help="Run only once, ignoring any autorefresh setting "
+                       "in the configuration file.")
+
+        parser.add_option("-q",
+                  action="store_true", dest="quick",
+                  default=False,
+                  help="Run  only quick synchronizations. Ignore any "
+                       "flag updates on IMAP servers.")
+
+        parser.add_option("-u", dest="interface",
+                  help="Specifies an alternative user interface to "
+              "use. This overrides the default specified in the "
+              "configuration file. The UI specified with -u  will "
+              "be forced to be used, even if checks determine that it is "
+              "not usable. Possible interface choices are: %s " %
+              ", ".join(DEFAULT_UI_LIST))
+
+        (options, args) = parser.parse_args()
+
+        #read in configuration file
+        configfilename = os.path.expanduser(options.configfile)
     
         config = ConfigParser()
         if not os.path.exists(configfilename):
-            sys.stderr.write(" *** Config file %s does not exist; aborting!\n" % configfilename)
+            logging.error(" *** Config file '%s' does not exist; aborting!" %
+                          configfilename)
             sys.exit(1)
-    
         config.read(configfilename)
-    
-        # override config values with option '-k'
-        for option in options['-k']:
-            (key, value) = option.split('=', 1)
-            if ':' in key:
-                (secname, key) = key.split(':', 1)
-                section = secname.replace("_", " ")
-            else:
-                section = "general"
-            config.set(section, key, value)
-    
-        ui = offlineimap.ui.detector.findUI(config, options.get('-u'))
+
+        #profile mode chosen?
+        if options.profiledir:
+            if not options.singlethreading:
+                logging.warn("Profile mode: Forcing to singlethreaded.")
+                options.singlethreaded = True
+            profiledir = options.profiledir
+            os.mkdir(profiledir)
+            threadutil.setprofiledir(profiledir)
+            logging.warn("Profile mode: Potentially large data will be "
+                         "created in '%s'" % profiledir)
+
+        #override a config value
+        if options.configoverride:
+            for option in options.configoverride:
+                (key, value) = option.split('=', 1)
+                if ':' in key:
+                    (secname, key) = key.split(':', 1)
+                    section = secname.replace("_", " ")
+                else:
+                    section = "general"
+                config.set(section, key, value)
+
+        #init the ui, and set up additional log files
+        ui = offlineimap.ui.detector.findUI(config, options.interface)
         offlineimap.ui.UIBase.setglobalui(ui)
     
-        if options.has_key('-l'):
-            ui.setlogfd(open(options['-l'], 'wt'))
+        if options.logfile:
+            ui.setlogfd(open(options.logfile, 'wt'))
     
+        #welcome blurb
         ui.init_banner()
-    
-        if options.has_key('-d'):
-            for debugtype in options['-d'].split(','):
-                ui.add_debug(debugtype.strip())
-                if debugtype == 'imap':
+
+        if options.debugtype:
+            if options.debugtype.lower() == 'all':
+                options.debugtype = 'imap,maildir,thread'
+            for type in options.debugtype.split(','):
+                type = type.strip()
+                ui.add_debug(type)
+                if type.lower() == 'imap':
                     imaplib.Debug = 5
-                if debugtype == 'thread':
+                if type.lower() == 'thread':
                     threading._VERBOSE = 1
-    
-        if options.has_key('-o'):
+
+        if options.runonce:
             # FIXME: maybe need a better
             for section in accounts.getaccountlist(config):
                 config.remove_option('Account ' + section, "autorefresh")
-    
-        if options.has_key('-q'):
+
+        if options.quick:
             for section in accounts.getaccountlist(config):
                 config.set('Account ' + section, "quick", '-1')
-    
-        if options.has_key('-f'):
-            foldernames = options['-f'].replace(" ", "").split(",")
+
+        if options.folders:
+            foldernames = options.folders.replace(" ", "").split(",")
             folderfilter = "lambda f: f in %s" % foldernames
             folderincludes = "[]"
             for accountname in accounts.getaccountlist(config):
@@ -133,7 +225,7 @@ class OfflineImap:
                 for section in [remote_repo_section, local_repo_section]:
                     config.set(section, "folderfilter", folderfilter)
                     config.set(section, "folderincludes", folderincludes)
-    
+
         self.lock(config, ui)
 
     
@@ -152,7 +244,7 @@ class OfflineImap:
             pass
     
         try:
-            if options.has_key('-l'):
+            if options.logfile:
                 sys.stderr = ui.logfile
     
             socktimeout = config.getdefaultint("general", "socktimeout", 0)
@@ -160,8 +252,8 @@ class OfflineImap:
                 socket.setdefaulttimeout(socktimeout)
     
             activeaccounts = config.get("general", "accounts")
-            if options.has_key('-a'):
-                activeaccounts = options['-a']
+            if options.accounts:
+                activeaccounts = options.accounts
             activeaccounts = activeaccounts.replace(" ", "")
             activeaccounts = activeaccounts.split(",")
             allaccounts = accounts.AccountHashGenerator(config)
@@ -183,7 +275,7 @@ class OfflineImap:
             remoterepos = None
             localrepos = None
     
-            if options.has_key('-1'):
+            if options.singlethreading:
                 threadutil.initInstanceLimit("ACCOUNTLIMIT", 1)
             else:
                 threadutil.initInstanceLimit("ACCOUNTLIMIT",
@@ -192,7 +284,7 @@ class OfflineImap:
             for reposname in config.getsectionlist('Repository'):
                 for instancename in ["FOLDER_" + reposname,
                                      "MSGCOPY_" + reposname]:
-                    if options.has_key('-1'):
+                    if options.singlethreading:
                         threadutil.initInstanceLimit(instancename, 1)
                     else:
                         threadutil.initInstanceLimit(instancename,
diff --git a/offlineimap/version.py b/offlineimap/version.py
index 6ae95fc..aca9310 100644
--- a/offlineimap/version.py
+++ b/offlineimap/version.py
@@ -33,97 +33,3 @@ GNU General Public License for more details.
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA"""
-
-def getcmdhelp():
-    from offlineimap.ui import detector
-    import os
-    uilist = ""
-    for ui in detector.DEFAULT_UI_LIST:
-        uilist += "                " + ui + os.linesep
-    return """
-       offlineimap [ -1 ] [ -P profiledir ] [ -a accountlist ]  [
-       -c configfile  ] [ -d debugtype[,debugtype...]  ] [ -o ] [
-       -u interface ] [ -q ]
-
-       offlineimap -h | --help
-
-       -1     Disable   all  multithreading  operations  and  use
-              solely a single-thread sync.  This effectively sets
-              the maxsyncaccounts and all maxconnections configu-
-              ration file variables to 1.
-
-       -P profiledir
-              Sets OfflineIMAP into profile  mode.   The  program
-              will create profiledir (it must not already exist).
-              As it runs, Python profiling information about each
-              thread  is  logged  into  profiledir.  Please note:
-              This option is present for debugging and  optimiza-
-              tion only, and should NOT be used unless you have a
-              specific reason to do so.   It  will  significantly
-              slow  program  performance, may reduce reliability,
-              and can generate huge amounts of  data.   You  must
-              use the -1 option when you use -P.
-
-
-       -a accountlist
-              Overrides  the accounts section in the config file.
-              Lets you specify a particular  account  or  set  of
-              accounts  to sync without having to edit the config
-              file.   You  might  use  this  to  exclude  certain
-              accounts,  or  to  sync some accounts that you nor-
-              mally prefer not to.
-
-       -c configfile
-              Specifies a configuration file to use  in  lieu  of
-              the default, ~/.offlineimaprc.
-
-       -d debugtype[,debugtype...]
-              Enables  debugging for OfflineIMAP.  This is useful
-              if you are trying to track down  a  malfunction  or
-              figure out what is going on under the hood.  I sug-
-              gest that you use this with -1 in order to make the
-              results more sensible.
-
-              -d  now  requires one or more debugtypes, separated
-              by commas.   These  define  what  exactly  will  be
-              debugged,  and so far include two options: imap and
-              maildir.  The imap option will enable IMAP protocol
-              stream and parsing debugging.  Note that the output
-              may contain passwords, so take care to remove  that
-              from the debugging output before sending it to any-
-              one else.  The maildir option will enable debugging
-              for certain Maildir operations.
-
-       -f foldername[,foldername...]
-              Only sync the specified folders.  The "foldername"s
-              are    the   *untranslated*    foldernames.    This
-              command-line  option  overrides any  "folderfilter"
-              and "folderincludes" options  in the  configuration 
-              file.
-
-       -k [section:]option=value
-              Override configuration file option.  If"section" is
-              omitted, it defaults to "general".  Any underscores
-              "_" in the section name are replaced with spaces:
-              for instance,  to override  option "autorefresh" in
-              the "[Account Personal]" section in the config file
-              one would use "-k Account_Personal:autorefresh=30".
-              
-       -o     Run only once,  ignoring any autorefresh setting in
-              the config file.
-
-       -q     Run  only quick synchronizations.   Ignore any flag
-              updates on IMAP servers.
-
-       -h, --help
-              Show summary of options.
-
-       -u interface
-              Specifies an alternative user interface  module  to
-              use.   This  overrides the default specified in the
-              configuration file.  The UI specified with -u  will
-              be  forced to be used, even if its isuable() method
-              states that it cannot be.   Use  this  option  with
-              care.   The  pre-defined  options, described in the
-              USER INTERFACES section of the man page, are:
-""" + uilist
-- 
1.7.1





More information about the OfflineIMAP-project mailing list