Merge branch 'ss/use-optionparser' into next
Conflicts: offlineimap/init.py Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
This commit is contained in:
commit
1bfa125f49
@ -19,5 +19,5 @@
|
|||||||
|
|
||||||
from offlineimap import OfflineImap
|
from offlineimap import OfflineImap
|
||||||
|
|
||||||
offlineimap = OfflineImap()
|
oi = OfflineImap()
|
||||||
offlineimap.startup('6.3.1')
|
oi.run()
|
||||||
|
@ -19,5 +19,5 @@
|
|||||||
|
|
||||||
from offlineimap import OfflineImap
|
from offlineimap import OfflineImap
|
||||||
|
|
||||||
offlineimap = OfflineImap()
|
oi = OfflineImap()
|
||||||
offlineimap.startup('6.3.1')
|
oi.run()
|
||||||
|
@ -21,11 +21,14 @@ from offlineimap import imapserver, threadutil, version, syncmaster, accounts
|
|||||||
from offlineimap.localeval import LocalEval
|
from offlineimap.localeval import LocalEval
|
||||||
from offlineimap.threadutil import InstanceLimitedThread, ExitNotifyThread
|
from offlineimap.threadutil import InstanceLimitedThread, ExitNotifyThread
|
||||||
import offlineimap.ui
|
import offlineimap.ui
|
||||||
import os, sys
|
|
||||||
from offlineimap.CustomConfig import CustomConfigParser
|
from offlineimap.CustomConfig import CustomConfigParser
|
||||||
|
from offlineimap.ui.detector import DEFAULT_UI_LIST
|
||||||
|
from optparse import OptionParser
|
||||||
|
import re, os, sys
|
||||||
|
from threading import *
|
||||||
import threading, socket
|
import threading, socket
|
||||||
from getopt import getopt
|
|
||||||
import signal
|
import signal
|
||||||
|
import logging
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import fcntl
|
import fcntl
|
||||||
@ -36,7 +39,12 @@ except:
|
|||||||
lockfd = None
|
lockfd = None
|
||||||
|
|
||||||
class OfflineImap:
|
class OfflineImap:
|
||||||
|
"""The main class that encapsulates the high level use of OfflineImap.
|
||||||
|
|
||||||
|
To invoke OfflineImap you would call it with:
|
||||||
|
oi = OfflineImap()
|
||||||
|
oi.run()
|
||||||
|
"""
|
||||||
def lock(self, config, ui):
|
def lock(self, config, ui):
|
||||||
global lockfd, hasfcntl
|
global lockfd, hasfcntl
|
||||||
if not hasfcntl:
|
if not hasfcntl:
|
||||||
@ -48,80 +56,169 @@ class OfflineImap:
|
|||||||
ui.locked()
|
ui.locked()
|
||||||
ui.terminate(1)
|
ui.terminate(1)
|
||||||
|
|
||||||
def startup(self, versionno):
|
def run(self):
|
||||||
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)
|
"""Parse the commandline and invoke everything"""
|
||||||
options = {}
|
|
||||||
options['-k'] = []
|
parser = OptionParser()
|
||||||
if '--help' in sys.argv[1:]:
|
parser.add_option("-1",
|
||||||
sys.stdout.write(version.getcmdhelp() + "\n")
|
action="store_true", dest="singlethreading",
|
||||||
sys.exit(0)
|
default=False,
|
||||||
|
help="Disable all multithreading operations and use "
|
||||||
for optlist in getopt(sys.argv[1:], 'P:1oqa:c:d:l:u:hk:f:')[0]:
|
"solely a single-thread sync. This effectively sets the "
|
||||||
if optlist[0] == '-k':
|
"maxsyncaccounts and all maxconnections configuration file "
|
||||||
options[optlist[0]].append(optlist[1])
|
"variables to 1.")
|
||||||
else:
|
|
||||||
options[optlist[0]] = optlist[1]
|
parser.add_option("-P", dest="profiledir", metavar="DIR",
|
||||||
|
help="Sets OfflineIMAP into profile mode. The program "
|
||||||
if options.has_key('-h'):
|
"will create DIR (it must not already exist). "
|
||||||
sys.stdout.write(version.getcmdhelp())
|
"As it runs, Python profiling information about each "
|
||||||
sys.stdout.write("\n")
|
"thread is logged into profiledir. Please note: "
|
||||||
sys.exit(0)
|
"This option is present for debugging and optimization "
|
||||||
configfilename = os.path.expanduser("~/.offlineimaprc")
|
"only, and should NOT be used unless you have a "
|
||||||
if options.has_key('-c'):
|
"specific reason to do so. It will significantly "
|
||||||
configfilename = options['-c']
|
"decrease program performance, may reduce reliability, "
|
||||||
if options.has_key('-P'):
|
"and can generate huge amounts of data. This option "
|
||||||
if not options.has_key('-1'):
|
"implies the -1 option.")
|
||||||
sys.stderr.write("FATAL: profile mode REQUIRES -1\n")
|
|
||||||
sys.exit(100)
|
parser.add_option("-a", dest="accounts", metavar="ACCOUNTS",
|
||||||
profiledir = options['-P']
|
help="""Overrides the accounts section in the config file.
|
||||||
os.mkdir(profiledir)
|
Lets you specify a particular account or set of
|
||||||
threadutil.setprofiledir(profiledir)
|
accounts to sync without having to edit the config
|
||||||
sys.stderr.write("WARNING: profile mode engaged;\nPotentially large data will be created in " + profiledir + "\n")
|
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. It is recommended "
|
||||||
|
"to 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 folder names "
|
||||||
|
"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 (if a flag on the remote IMAP "
|
||||||
|
"changes, and we have the message locally, it will be left "
|
||||||
|
"untouched in a quick run.")
|
||||||
|
|
||||||
|
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 = CustomConfigParser()
|
config = CustomConfigParser()
|
||||||
if not os.path.exists(configfilename):
|
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)
|
sys.exit(1)
|
||||||
|
|
||||||
config.read(configfilename)
|
config.read(configfilename)
|
||||||
|
|
||||||
# override config values with option '-k'
|
#profile mode chosen?
|
||||||
for option in options['-k']:
|
if options.profiledir:
|
||||||
(key, value) = option.split('=', 1)
|
if not options.singlethreading:
|
||||||
if ':' in key:
|
logging.warn("Profile mode: Forcing to singlethreaded.")
|
||||||
(secname, key) = key.split(':', 1)
|
options.singlethreaded = True
|
||||||
section = secname.replace("_", " ")
|
profiledir = options.profiledir
|
||||||
else:
|
os.mkdir(profiledir)
|
||||||
section = "general"
|
threadutil.setprofiledir(profiledir)
|
||||||
config.set(section, key, value)
|
logging.warn("Profile mode: Potentially large data will be "
|
||||||
|
"created in '%s'" % profiledir)
|
||||||
ui = offlineimap.ui.detector.findUI(config, options.get('-u'))
|
|
||||||
|
#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)
|
offlineimap.ui.UIBase.setglobalui(ui)
|
||||||
|
|
||||||
if options.has_key('-l'):
|
if options.logfile:
|
||||||
ui.setlogfd(open(options['-l'], 'wt'))
|
ui.setlogfd(open(options.logfile, 'wt'))
|
||||||
|
|
||||||
|
#welcome blurb
|
||||||
ui.init_banner()
|
ui.init_banner()
|
||||||
|
|
||||||
if options.has_key('-d'):
|
if options.debugtype:
|
||||||
for debugtype in options['-d'].split(','):
|
if options.debugtype.lower() == 'all':
|
||||||
ui.add_debug(debugtype.strip())
|
options.debugtype = 'imap,maildir,thread'
|
||||||
if debugtype == 'imap':
|
for type in options.debugtype.split(','):
|
||||||
|
type = type.strip()
|
||||||
|
ui.add_debug(type)
|
||||||
|
if type.lower() == 'imap':
|
||||||
imaplib.Debug = 5
|
imaplib.Debug = 5
|
||||||
if debugtype == 'thread':
|
if type.lower() == 'thread':
|
||||||
threading._VERBOSE = 1
|
threading._VERBOSE = 1
|
||||||
|
|
||||||
if options.has_key('-o'):
|
if options.runonce:
|
||||||
# FIXME: maybe need a better
|
# FIXME: maybe need a better
|
||||||
for section in accounts.getaccountlist(config):
|
for section in accounts.getaccountlist(config):
|
||||||
config.remove_option('Account ' + section, "autorefresh")
|
config.remove_option('Account ' + section, "autorefresh")
|
||||||
|
|
||||||
if options.has_key('-q'):
|
if options.quick:
|
||||||
for section in accounts.getaccountlist(config):
|
for section in accounts.getaccountlist(config):
|
||||||
config.set('Account ' + section, "quick", '-1')
|
config.set('Account ' + section, "quick", '-1')
|
||||||
|
|
||||||
if options.has_key('-f'):
|
if options.folders:
|
||||||
foldernames = options['-f'].replace(" ", "").split(",")
|
foldernames = options.folders.replace(" ", "").split(",")
|
||||||
folderfilter = "lambda f: f in %s" % foldernames
|
folderfilter = "lambda f: f in %s" % foldernames
|
||||||
folderincludes = "[]"
|
folderincludes = "[]"
|
||||||
for accountname in accounts.getaccountlist(config):
|
for accountname in accounts.getaccountlist(config):
|
||||||
@ -133,7 +230,7 @@ class OfflineImap:
|
|||||||
for section in [remote_repo_section, local_repo_section]:
|
for section in [remote_repo_section, local_repo_section]:
|
||||||
config.set(section, "folderfilter", folderfilter)
|
config.set(section, "folderfilter", folderfilter)
|
||||||
config.set(section, "folderincludes", folderincludes)
|
config.set(section, "folderincludes", folderincludes)
|
||||||
|
|
||||||
self.lock(config, ui)
|
self.lock(config, ui)
|
||||||
|
|
||||||
|
|
||||||
@ -152,7 +249,7 @@ class OfflineImap:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if options.has_key('-l'):
|
if options.logfile:
|
||||||
sys.stderr = ui.logfile
|
sys.stderr = ui.logfile
|
||||||
|
|
||||||
socktimeout = config.getdefaultint("general", "socktimeout", 0)
|
socktimeout = config.getdefaultint("general", "socktimeout", 0)
|
||||||
@ -160,8 +257,8 @@ class OfflineImap:
|
|||||||
socket.setdefaulttimeout(socktimeout)
|
socket.setdefaulttimeout(socktimeout)
|
||||||
|
|
||||||
activeaccounts = config.get("general", "accounts")
|
activeaccounts = config.get("general", "accounts")
|
||||||
if options.has_key('-a'):
|
if options.accounts:
|
||||||
activeaccounts = options['-a']
|
activeaccounts = options.accounts
|
||||||
activeaccounts = activeaccounts.replace(" ", "")
|
activeaccounts = activeaccounts.replace(" ", "")
|
||||||
activeaccounts = activeaccounts.split(",")
|
activeaccounts = activeaccounts.split(",")
|
||||||
allaccounts = accounts.AccountHashGenerator(config)
|
allaccounts = accounts.AccountHashGenerator(config)
|
||||||
@ -183,7 +280,7 @@ class OfflineImap:
|
|||||||
remoterepos = None
|
remoterepos = None
|
||||||
localrepos = None
|
localrepos = None
|
||||||
|
|
||||||
if options.has_key('-1'):
|
if options.singlethreading:
|
||||||
threadutil.initInstanceLimit("ACCOUNTLIMIT", 1)
|
threadutil.initInstanceLimit("ACCOUNTLIMIT", 1)
|
||||||
else:
|
else:
|
||||||
threadutil.initInstanceLimit("ACCOUNTLIMIT",
|
threadutil.initInstanceLimit("ACCOUNTLIMIT",
|
||||||
@ -192,7 +289,7 @@ class OfflineImap:
|
|||||||
for reposname in config.getsectionlist('Repository'):
|
for reposname in config.getsectionlist('Repository'):
|
||||||
for instancename in ["FOLDER_" + reposname,
|
for instancename in ["FOLDER_" + reposname,
|
||||||
"MSGCOPY_" + reposname]:
|
"MSGCOPY_" + reposname]:
|
||||||
if options.has_key('-1'):
|
if options.singlethreading:
|
||||||
threadutil.initInstanceLimit(instancename, 1)
|
threadutil.initInstanceLimit(instancename, 1)
|
||||||
else:
|
else:
|
||||||
threadutil.initInstanceLimit(instancename,
|
threadutil.initInstanceLimit(instancename,
|
||||||
|
@ -33,97 +33,3 @@ GNU General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA"""
|
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
|
|
||||||
|
Loading…
Reference in New Issue
Block a user