← Back to team overview

openerp-dev-web team mailing list archive

[Merge] lp:~openerp-dev/openobject-server/trunk-cleaning-vmt into lp:openobject-server

 

Vo Minh Thu (OpenERP) has proposed merging lp:~openerp-dev/openobject-server/trunk-cleaning-vmt into lp:openobject-server.

Requested reviews:
  OpenERP Core Team (openerp)

For more details, see:
https://code.launchpad.net/~openerp-dev/openobject-server/trunk-cleaning-vmt/+merge/58482

Not a real merge proposal at this point, but a convenient way to share the diffs and comment about them.
-- 
https://code.launchpad.net/~openerp-dev/openobject-server/trunk-cleaning-vmt/+merge/58482
Your team OpenERP R&D Team is subscribed to branch lp:~openerp-dev/openobject-server/trunk-cleaning-vmt.
=== modified file 'openerp-server'
--- openerp-server	2011-03-24 09:50:12 +0000
+++ openerp-server	2011-04-20 12:02:14 +0000
@@ -39,10 +39,11 @@
 import sys
 import threading
 import traceback
+import time
 
-import openerp.release as release
-__author__ = release.author
-__version__ = release.version
+import openerp
+__author__ = openerp.release.author
+__version__ = openerp.release.version
 
 if os.name == 'posix':
     import pwd
@@ -53,80 +54,56 @@
         sys.exit(1)
 
 #-----------------------------------------------------------------------
-# import the tools module so that the commandline parameters are parsed
+# parse the command line
 #-----------------------------------------------------------------------
-import openerp.tools as tools
-tools.config.parse_config(sys.argv[1:])
+openerp.tools.config.parse_config(sys.argv[1:])
+config = openerp.tools.config
 
 #----------------------------------------------------------
 # get logger
 #----------------------------------------------------------
-import openerp.netsvc as netsvc
-netsvc.init_logger()
+openerp.netsvc.init_logger()
 logger = logging.getLogger('server')
 
-logger.info("OpenERP version - %s", release.version)
-for name, value in [('addons_path', tools.config['addons_path']),
-                    ('database hostname', tools.config['db_host'] or 'localhost'),
-                    ('database port', tools.config['db_port'] or '5432'),
-                    ('database user', tools.config['db_user'])]:
+logger.info("OpenERP version - %s", __version__)
+for name, value in [('addons_path', config['addons_path']),
+                    ('database hostname', config['db_host'] or 'localhost'),
+                    ('database port', config['db_port'] or '5432'),
+                    ('database user', config['db_user'])]:
     logger.info("%s - %s", name, value)
 
 # Don't allow if the connection to PostgreSQL done by postgres user
-if tools.config['db_user'] == 'postgres':
+if config['db_user'] == 'postgres':
     logger.error("Connecting to the database as 'postgres' user is forbidden, as it present major security issues. Shutting down.")
     sys.exit(1)
 
-import time
-
 #----------------------------------------------------------
 # init net service
 #----------------------------------------------------------
 logger.info('initialising distributed objects services')
 
-#---------------------------------------------------------------
-# connect to the database and initialize it with base if needed
-#---------------------------------------------------------------
-import openerp.pooler as pooler
-
-#----------------------------------------------------------
-# import basic modules
-#----------------------------------------------------------
-import openerp.osv as osv
-import openerp.workflow as workflow
-import openerp.report as report
-import openerp.service as service
-
-#----------------------------------------------------------
-# import addons
-#----------------------------------------------------------
-
-import openerp.addons as addons
-
 #----------------------------------------------------------
 # Load and update databases if requested
 #----------------------------------------------------------
 
-import openerp.service.http_server as service_http_server
-
-if not ( tools.config["stop_after_init"] or \
-    tools.config["translate_in"] or \
-    tools.config["translate_out"] ):
-    service_http_server.init_servers()
-    service_http_server.init_xmlrpc()
-    service_http_server.init_static_http()
-
-    import openerp.service.netrpc_server as service_netrpc_server
-    service_netrpc_server.init_servers()
-
-if tools.config['db_name']:
-    for dbname in tools.config['db_name'].split(','):
-        db,pool = pooler.get_db_and_pool(dbname, update_module=tools.config['init'] or tools.config['update'], pooljobs=False)
+if not ( config["stop_after_init"] or \
+    config["translate_in"] or \
+    config["translate_out"] ):
+    http_server = openerp.service.http_server
+    netrpc_server = openerp.service.netrpc_server
+    http_server.init_servers()
+    http_server.init_xmlrpc()
+    http_server.init_static_http()
+    netrpc_server.init_servers()
+
+if config['db_name']:
+    for dbname in config['db_name'].split(','):
+        db, pool = openerp.pooler.get_db_and_pool(dbname, update_module=config['init'] or config['update'], pooljobs=False)
         cr = db.cursor()
 
-        if tools.config["test_file"]:
-            logger.info('loading test file %s', tools.config["test_file"])
-            tools.convert_yaml_import(cr, 'base', file(tools.config["test_file"]), {}, 'test', True)
+        if config["test_file"]:
+            logger.info('loading test file %s', config["test_file"])
+            openerp.tools.convert_yaml_import(cr, 'base', file(config["test_file"]), {}, 'test', True)
             cr.rollback()
 
         pool.get('ir.cron')._poolJobs(db.dbname)
@@ -136,35 +113,33 @@
 #----------------------------------------------------------
 # translation stuff
 #----------------------------------------------------------
-if tools.config["translate_out"]:
-    import csv
-
-    if tools.config["language"]:
-        msg = "language %s" % (tools.config["language"],)
+if config["translate_out"]:
+    if config["language"]:
+        msg = "language %s" % (config["language"],)
     else:
         msg = "new language"
-    logger.info('writing translation file for %s to %s', msg, tools.config["translate_out"])
+    logger.info('writing translation file for %s to %s', msg, config["translate_out"])
 
-    fileformat = os.path.splitext(tools.config["translate_out"])[-1][1:].lower()
-    buf = file(tools.config["translate_out"], "w")
-    dbname = tools.config['db_name']
-    cr = pooler.get_db(dbname).cursor()
-    tools.trans_export(tools.config["language"], tools.config["translate_modules"] or ["all"], buf, fileformat, cr)
+    fileformat = os.path.splitext(config["translate_out"])[-1][1:].lower()
+    buf = file(config["translate_out"], "w")
+    dbname = config['db_name']
+    cr = openerp.pooler.get_db(dbname).cursor()
+    openerp.tools.trans_export(config["language"], config["translate_modules"] or ["all"], buf, fileformat, cr)
     cr.close()
     buf.close()
 
     logger.info('translation file written successfully')
     sys.exit(0)
 
-if tools.config["translate_in"]:
-    context = {'overwrite': tools.config["overwrite_existing_translations"]}
-    dbname = tools.config['db_name']
-    cr = pooler.get_db(dbname).cursor()
-    tools.trans_load(cr,
-                     tools.config["translate_in"], 
-                     tools.config["language"],
+if config["translate_in"]:
+    context = {'overwrite': config["overwrite_existing_translations"]}
+    dbname = config['db_name']
+    cr = openerp.pooler.get_db(dbname).cursor()
+    openerp.tools.trans_load(cr,
+                     config["translate_in"], 
+                     config["language"],
                      context=context)
-    tools.trans_update_res_ids(cr)
+    openerp.tools.trans_update_res_ids(cr)
     cr.commit()
     cr.close()
     sys.exit(0)
@@ -172,10 +147,9 @@
 #----------------------------------------------------------------------------------
 # if we don't want the server to continue to run after initialization, we quit here
 #----------------------------------------------------------------------------------
-if tools.config["stop_after_init"]:
+if config["stop_after_init"]:
     sys.exit(0)
 
-
 #----------------------------------------------------------
 # Launch Servers
 #----------------------------------------------------------
@@ -186,15 +160,16 @@
     [(getattr(signal, sign), sign) for sign in LST_SIGNALS]
 )
 
-netsvc.quit_signals_received = 0
+quit_signals_received = 0
 
 def handler(signum, frame):
     """
     :param signum: the signal number
     :param frame: the interrupted stack frame or None
     """
-    netsvc.quit_signals_received += 1
-    if netsvc.quit_signals_received > 1:
+    global quit_signals_received
+    quit_signals_received += 1
+    if quit_signals_received > 1:
         sys.stderr.write("Forced shutdown.\n")
         os._exit(0)
 
@@ -219,10 +194,10 @@
     signal.signal(signal.SIGQUIT, dumpstacks)
 
 def quit():
-    netsvc.Agent.quit()
-    netsvc.Server.quitAll()
-    if tools.config['pidfile']:
-        os.unlink(tools.config['pidfile'])
+    openerp.netsvc.Agent.quit()
+    openerp.netsvc.Server.quitAll()
+    if config['pidfile']:
+        os.unlink(config['pidfile'])
     logger = logging.getLogger('shutdown')
     logger.info("Initiating OpenERP Server shutdown")
     logger.info("Hit CTRL-C again or send a second signal to immediately terminate the server...")
@@ -240,17 +215,17 @@
                 time.sleep(0.05)
     sys.exit(0)
 
-if tools.config['pidfile']:
-    fd = open(tools.config['pidfile'], 'w')
+if config['pidfile']:
+    fd = open(config['pidfile'], 'w')
     pidtext = "%d" % (os.getpid())
     fd.write(pidtext)
     fd.close()
 
-netsvc.Server.startAll()
+openerp.netsvc.Server.startAll()
 
 logger.info('OpenERP server is running, waiting for connections...')
 
-while netsvc.quit_signals_received == 0:
+while quit_signals_received == 0:
     time.sleep(60)
 
 quit()

=== modified file 'openerp/__init__.py'
--- openerp/__init__.py	2011-02-08 09:29:23 +0000
+++ openerp/__init__.py	2011-04-20 12:02:14 +0000
@@ -19,7 +19,12 @@
 #
 ##############################################################################
 
+""" OpenERP core library.
+
+"""
+
 import addons
+import conf
 import ir
 import loglevels
 import netsvc

=== modified file 'openerp/addons/__init__.py'
--- openerp/addons/__init__.py	2011-02-08 13:27:19 +0000
+++ openerp/addons/__init__.py	2011-04-20 12:02:14 +0000
@@ -166,7 +166,13 @@
 
 
 def get_module_path(module, downloaded=False):
-    """Return the path of the given module."""
+    """Return the path of the given module.
+
+    Search the addons paths and return the first path where the given
+    module is found. If downloaded is True, return the default addons
+    path if nothing else is found.
+
+    """
     initialize_sys_path()
     for adp in ad_paths:
         if os.path.exists(opj(adp, module)) or os.path.exists(opj(adp, '%s.zip' % module)):

=== added directory 'openerp/conf'
=== added file 'openerp/conf/__init__.py'
--- openerp/conf/__init__.py	1970-01-01 00:00:00 +0000
+++ openerp/conf/__init__.py	2011-04-20 12:02:14 +0000
@@ -0,0 +1,33 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    OpenERP, Open Source Management Solution
+#    Copyright (C) 2011 OpenERP s.a. (<http://openerp.com>).
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU Affero General Public License as
+#    published by the Free Software Foundation, either version 3 of the
+#    License, or (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+""" Library-wide configuration variables.
+
+For now, configuration code is in openerp.tools.config. It is in mainly
+unprocessed form, e.g. addons_path is a string with commas-separated
+paths. The aim is to have code related to configuration (command line
+parsing, configuration file loading and saving, ...) in this module
+and provide real Python variables, e.g. addons_paths is really a list
+of paths.
+
+"""
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

=== modified file 'openerp/osv/osv.py'
--- openerp/osv/osv.py	2011-02-07 12:57:23 +0000
+++ openerp/osv/osv.py	2011-04-20 12:02:14 +0000
@@ -34,7 +34,6 @@
 
 module_list = []
 module_class_list = {}
-class_pool = {}
 
 class except_osv(Exception):
     def __init__(self, name, value, exc_type='warning'):
@@ -271,7 +270,6 @@
         if not hasattr(cls, '_module'):
             cls._module = module
         module_class_list.setdefault(cls._module, []).append(cls)
-        class_pool[cls._name] = cls
         if module not in module_list:
             module_list.append(cls._module)
         return None

=== modified file 'openerp/pooler.py'
--- openerp/pooler.py	2011-02-07 12:57:23 +0000
+++ openerp/pooler.py	2011-04-20 12:02:14 +0000
@@ -22,6 +22,7 @@
 pool_dic = {}
 
 def get_db_and_pool(db_name, force_demo=False, status=None, update_module=False, pooljobs=True):
+    """Return a database connection and an initialized osv_pool."""
     if not status:
         status={}
 
@@ -33,8 +34,12 @@
         import openerp.addons as addons
         import openerp.osv.osv as osv_osv
         pool = osv_osv.osv_pool()
+
+        # Initializing an osv_pool will call general code which will in turn
+        # call get_db_and_pool (this function) to obtain the osv_pool begin
+        # initialized. Make it available in the pool_dic then remove it if
+        # an exception is raised.
         pool_dic[db_name] = pool
-
         try:
             addons.load_modules(db, force_demo, status, update_module)
         except Exception:
@@ -55,12 +60,14 @@
 
 
 def restart_pool(db_name, force_demo=False, status=None, update_module=False):
+    """Delete an existing osv_pool and return a database connection and a newly initialized osv_pool."""
     if db_name in pool_dic:
         del pool_dic[db_name]
     return get_db_and_pool(db_name, force_demo, status, update_module=update_module)
 
 
 def get_db_only(db_name):
+    """Return a database connection."""
     # ATTENTION:
     # do not put this import outside this function
     # sql_db must not be loaded before the logger is initialized.
@@ -72,10 +79,12 @@
 
 
 def get_db(db_name):
+    """Return a database connection. The corresponding osv_pool is initialize."""
     return get_db_and_pool(db_name)[0]
 
 
 def get_pool(db_name, force_demo=False, status=None, update_module=False):
+    """Return an osv_pool."""
     pool = get_db_and_pool(db_name, force_demo, status, update_module)[1]
     return pool
 

=== modified file 'openerp/service/__init__.py'
--- openerp/service/__init__.py	2009-10-20 10:52:23 +0000
+++ openerp/service/__init__.py	2011-04-20 12:02:14 +0000
@@ -19,6 +19,8 @@
 #
 ##############################################################################
 
+import http_server
+import netrpc_server
 import web_services
 
 

=== modified file 'openerp/tools/config.py'
--- openerp/tools/config.py	2011-04-18 13:10:23 +0000
+++ openerp/tools/config.py	2011-04-20 12:02:14 +0000
@@ -39,67 +39,21 @@
 
 class configmanager(object):
     def __init__(self, fname=None):
+        # Options not exposed on the command line. Command line options will be added
+        # from optparse's parser.
         self.options = {
-            'email_from':False,
-            'xmlrpc_interface': '',    # this will bind the server to all interfaces
-            'xmlrpc_port': 8069,
-            'netrpc_interface': '',
-            'netrpc_port': 8070,
-            'xmlrpcs_interface': '',    # this will bind the server to all interfaces
-            'xmlrpcs_port': 8071,
-            'db_host': False,
-            'db_port': False,
-            'db_name': False,
-            'db_user': False,
-            'db_password': False,
-            'db_maxconn': 64,
-            'reportgz': False,
-            'netrpc': True,
-            'xmlrpc': True,
-            'xmlrpcs': True,
-            'translate_in': None,
-            'translate_out': None,
-            'overwrite_existing_translations': False,
-            'load_language': None,
-            'language': None,
-            'pg_path': None,
             'admin_passwd': 'admin',
             'csv_internal_sep': ',',
-            'addons_path': None,
-            'root_path': None,
-            'debug_mode': False,
-            'import_partial': "",
-            'pidfile': None,
-            'logfile': None,
-            'logrotate': True,
-            'smtp_server': 'localhost',
-            'smtp_user': False,
-            'smtp_port':25,
-            'smtp_ssl':False,
-            'smtp_password': False,
-            'stop_after_init': False,   # this will stop the server after initialization
-            'syslog' : False,
-            'log_level': logging.INFO,
-            'assert_exit_level': logging.ERROR, # level above which a failed assert will be raised
-            'cache_timeout': 100000,
             'login_message': False,
-            'list_db' : True,
-            'timezone' : False, # to override the default TZ
-            'test_file' : False,
-            'test_report_directory' : False,
-            'test_disable' : False,
-            'test_commit' : False,
-            'static_http_enable': False,
-            'static_http_document_root': None,
-            'static_http_url_prefix': None,
-            'secure_cert_file': 'server.cert',
-            'secure_pkey_file': 'server.pkey',
             'publisher_warranty_url': 'http://services.openerp.com/publisher-warranty/',
-            'osv_memory_count_limit': None, # number of records in each osv_memory virtual table
-            'osv_memory_age_limit': 1, # hours
+            'reportgz': False,
+            'root_path': None,
         }
 
-        self.blacklist_for_save = set(["publisher_warranty_url", "load_language", "root_path"])
+        # Not exposed in the configuration file.
+        self.blacklist_for_save = set(
+            ['publisher_warranty_url', 'load_language', 'root_path',
+            'init', 'save', 'config', 'update'])
 
         self.misc = {}
         self.config_file = fname
@@ -122,15 +76,18 @@
         group.add_option("--without-demo", dest="without_demo",
                           help="disable loading demo data for modules to be installed (comma-separated, use \"all\" for all modules). Requires -d and -i. Default is %default",
                           default=False)
-        group.add_option("-P", "--import-partial", dest="import_partial",
-                        help="Use this for big data importation, if it crashes you will be able to continue at the current state. Provide a filename to store intermediate importation states.", default=False)
+        group.add_option("-P", "--import-partial", dest="import_partial", default='',
+                        help="Use this for big data importation, if it crashes you will be able to continue at the current state. Provide a filename to store intermediate importation states.")
         group.add_option("--pidfile", dest="pidfile", help="file where the server pid will be stored")
         parser.add_option_group(group)
 
         group = optparse.OptionGroup(parser, "XML-RPC Configuration")
-        group.add_option("--xmlrpc-interface", dest="xmlrpc_interface", help="specify the TCP IP address for the XML-RPC protocol")
-        group.add_option("--xmlrpc-port", dest="xmlrpc_port", help="specify the TCP port for the XML-RPC protocol", type="int")
-        group.add_option("--no-xmlrpc", dest="xmlrpc", action="store_false", help="disable the XML-RPC protocol")
+        group.add_option("--xmlrpc-interface", dest="xmlrpc_interface", default='',
+                         help="Specify the TCP IP address for the XML-RPC protocol. The empty string binds to all interfaces.")
+        group.add_option("--xmlrpc-port", dest="xmlrpc_port", default=8069,
+                         help="specify the TCP port for the XML-RPC protocol", type="int")
+        group.add_option("--no-xmlrpc", dest="xmlrpc", action="store_false", default=True,
+                         help="disable the XML-RPC protocol")
         parser.add_option_group(group)
 
         title = "XML-RPC Secure Configuration"
@@ -138,18 +95,26 @@
             title += " (disabled as ssl is unavailable)"
 
         group = optparse.OptionGroup(parser, title)
-        group.add_option("--xmlrpcs-interface", dest="xmlrpcs_interface", help="specify the TCP IP address for the XML-RPC Secure protocol")
-        group.add_option("--xmlrpcs-port", dest="xmlrpcs_port", help="specify the TCP port for the XML-RPC Secure protocol", type="int")
-        group.add_option("--no-xmlrpcs", dest="xmlrpcs", action="store_false", help="disable the XML-RPC Secure protocol")
-        group.add_option("--cert-file", dest="secure_cert_file", help="specify the certificate file for the SSL connection")
-        group.add_option("--pkey-file", dest="secure_pkey_file", help="specify the private key file for the SSL connection")
+        group.add_option("--xmlrpcs-interface", dest="xmlrpcs_interface", default='',
+                         help="Specify the TCP IP address for the XML-RPC Secure protocol. The empty string binds to all interfaces.")
+        group.add_option("--xmlrpcs-port", dest="xmlrpcs_port", default=8071,
+                         help="specify the TCP port for the XML-RPC Secure protocol", type="int")
+        group.add_option("--no-xmlrpcs", dest="xmlrpcs", action="store_false", default=True,
+                         help="disable the XML-RPC Secure protocol")
+        group.add_option("--cert-file", dest="secure_cert_file", default='server.cert',
+                         help="specify the certificate file for the SSL connection")
+        group.add_option("--pkey-file", dest="secure_pkey_file", default='server.pkey',
+                         help="specify the private key file for the SSL connection")
         parser.add_option_group(group)
 
         # NET-RPC
         group = optparse.OptionGroup(parser, "NET-RPC Configuration")
-        group.add_option("--netrpc-interface", dest="netrpc_interface", help="specify the TCP IP address for the NETRPC protocol")
-        group.add_option("--netrpc-port", dest="netrpc_port", help="specify the TCP port for the NETRPC protocol", type="int")
-        group.add_option("--no-netrpc", dest="netrpc", action="store_false", help="disable the NETRPC protocol")
+        group.add_option("--netrpc-interface", dest="netrpc_interface", default='',
+                         help="specify the TCP IP address for the NETRPC protocol")
+        group.add_option("--netrpc-port", dest="netrpc_port", default=8070,
+                         help="specify the TCP port for the NETRPC protocol", type="int")
+        group.add_option("--no-netrpc", dest="netrpc", action="store_false", default=True,
+                         help="disable the NETRPC protocol")
         parser.add_option_group(group)
 
         # Static HTTP
@@ -161,45 +126,60 @@
 
         # Testing Group
         group = optparse.OptionGroup(parser, "Testing Configuration")
-        group.add_option("--test-file", dest="test_file", help="Launch a YML test file.")
-        group.add_option("--test-report-directory", dest="test_report_directory", help="If set, will save sample of all reports in this directory.")
+        group.add_option("--test-file", dest="test_file", default=False,
+                         help="Launch a YML test file.")
+        group.add_option("--test-report-directory", dest="test_report_directory", default=False,
+                         help="If set, will save sample of all reports in this directory.")
         group.add_option("--test-disable", action="store_true", dest="test_disable",
                          default=False, help="Disable loading test files.")
         group.add_option("--test-commit", action="store_true", dest="test_commit",
                          default=False, help="Commit database changes performed by tests.")
         group.add_option("--assert-exit-level", dest='assert_exit_level', type="choice", choices=self._LOGLEVELS.keys(),
-                          help="specify the level at which a failed assertion will stop the server. Accepted values: %s" % (self._LOGLEVELS.keys(),))
+                         default='error',
+                         help="specify the level at which a failed assertion will stop the server. Accepted values: %s" % (self._LOGLEVELS.keys(),))
         parser.add_option_group(group)
 
         # Logging Group
         group = optparse.OptionGroup(parser, "Logging Configuration")
         group.add_option("--logfile", dest="logfile", help="file where the server log will be stored")
-        group.add_option("--no-logrotate", dest="logrotate", action="store_false",
+        group.add_option("--no-logrotate", dest="logrotate", action="store_false", default=True,
                          help="do not rotate the logfile")
         group.add_option("--syslog", action="store_true", dest="syslog",
                          default=False, help="Send the log to the syslog server")
         group.add_option('--log-level', dest='log_level', type='choice', choices=self._LOGLEVELS.keys(),
+                         default='info',
                          help='specify the level of the logging. Accepted values: ' + str(self._LOGLEVELS.keys()))
         parser.add_option_group(group)
 
         # SMTP Group
         group = optparse.OptionGroup(parser, "SMTP Configuration")
-        group.add_option('--email-from', dest='email_from', help='specify the SMTP email address for sending email')
-        group.add_option('--smtp', dest='smtp_server', help='specify the SMTP server for sending email')
-        group.add_option('--smtp-port', dest='smtp_port', help='specify the SMTP port', type="int")
-        group.add_option('--smtp-ssl', dest='smtp_ssl', action='store_true', help='specify the SMTP server support SSL or not')
-        group.add_option('--smtp-user', dest='smtp_user', help='specify the SMTP username for sending email')
-        group.add_option('--smtp-password', dest='smtp_password', help='specify the SMTP password for sending email')
+        group.add_option('--email-from', dest='email_from', default=False,
+                         help='specify the SMTP email address for sending email')
+        group.add_option('--smtp', dest='smtp_server', default='localhost',
+                         help='specify the SMTP server for sending email')
+        group.add_option('--smtp-port', dest='smtp_port', default=25,
+                         help='specify the SMTP port', type="int")
+        group.add_option('--smtp-ssl', dest='smtp_ssl', action='store_true', default=False,
+                         help='specify the SMTP server support SSL or not')
+        group.add_option('--smtp-user', dest='smtp_user', default=False,
+                         help='specify the SMTP username for sending email')
+        group.add_option('--smtp-password', dest='smtp_password', default=False,
+                         help='specify the SMTP password for sending email')
         parser.add_option_group(group)
 
         group = optparse.OptionGroup(parser, "Database related options")
-        group.add_option("-d", "--database", dest="db_name", help="specify the database name")
-        group.add_option("-r", "--db_user", dest="db_user", help="specify the database user name")
-        group.add_option("-w", "--db_password", dest="db_password", help="specify the database password")
+        group.add_option("-d", "--database", dest="db_name", default=False,
+                         help="specify the database name")
+        group.add_option("-r", "--db_user", dest="db_user", default=False,
+                         help="specify the database user name")
+        group.add_option("-w", "--db_password", dest="db_password", default=False,
+                         help="specify the database password")
         group.add_option("--pg_path", dest="pg_path", help="specify the pg executable path")
-        group.add_option("--db_host", dest="db_host", help="specify the database host")
-        group.add_option("--db_port", dest="db_port", help="specify the database port", type="int")
-        group.add_option("--db_maxconn", dest="db_maxconn", type='int',
+        group.add_option("--db_host", dest="db_host", default=False,
+                         help="specify the database host")
+        group.add_option("--db_port", dest="db_port", default=False,
+                         help="specify the database port", type="int")
+        group.add_option("--db_maxconn", dest="db_maxconn", type='int', default=64,
                          help="specify the the maximum number of physical connections to posgresql")
         parser.add_option_group(group)
 
@@ -211,6 +191,7 @@
         group.add_option('--load-language', dest="load_language",
                          help="specifies the languages for the translations you want to be loaded")
         group.add_option('-l', "--language", dest="language",
+                         default=None,
                          help="specify the language of the translation file. Use it with --i18n-export or --i18n-import")
         group.add_option("--i18n-export", dest="translate_out",
                          help="export all sentences to be translated to a CSV file, a PO file or a TGZ archive and exit")
@@ -226,17 +207,19 @@
         parser.add_option_group(group)
 
         security = optparse.OptionGroup(parser, 'Security-related options')
-        security.add_option('--no-database-list', action="store_false", dest='list_db', help="disable the ability to return the list of databases")
+        security.add_option('--no-database-list', action="store_false", dest='list_db', default=True,
+                            help="disable the ability to return the list of databases")
         parser.add_option_group(security)
 
         # Advanced options
         group = optparse.OptionGroup(parser, "Advanced options")
-        group.add_option("--cache-timeout", dest="cache_timeout",
+        group.add_option("--cache-timeout", dest="cache_timeout", default=100000,
                           help="set the timeout for the cache system", type="int")
         group.add_option('--debug', dest='debug_mode', action='store_true', default=False, help='enable debug mode')
         group.add_option("--stop-after-init", action="store_true", dest="stop_after_init", default=False,
-                          help="stop the server after it initializes")
-        group.add_option("-t", "--timezone", dest="timezone", help="specify reference timezone for the server (e.g. Europe/Brussels")
+                          help="stop the server after its initialization")
+        group.add_option("-t", "--timezone", dest="timezone", default=False,
+                         help="specify reference timezone for the server (e.g. Europe/Brussels")
         group.add_option("--osv-memory-count-limit", dest="osv_memory_count_limit", default=False,
                          help="Force a limit on the maximum number of records kept in the virtual "
                               "osv_memory tables. The default is False, which means no count-based limit.",
@@ -248,6 +231,14 @@
                          type="float")
         parser.add_option_group(group)
 
+        # Copy all optparse options into self.options.
+        for group in parser.option_groups:
+            for option in group.option_list:
+                if option.default == ('NO', 'DEFAULT'):
+                    self.options[option.dest] = None
+                else:
+                    self.options[option.dest] = option.default
+
         self.parse_config()
 
     def parse_config(self, args=[]):