From a23d41a57f43c3a0f298d3918ae1712181fa544e Mon Sep 17 00:00:00 2001 From: Jason Gerard DeRose Date: Fri, 31 Oct 2008 18:17:08 -0600 Subject: [PATCH] Reoganized global option functionality to it is easy for any script to use the environment-related global options; lite-xmlrpc.py now uses same global options --- ipalib/cli.py | 29 +++++++++-------------------- ipalib/plugable.py | 27 +++++++++++++++++++++++++++ ipalib/util.py | 22 ++++++++++++++++++++++ lite-xmlrpc.py | 2 +- tests/test_ipalib/test_cli.py | 25 +++++++++++++++---------- 5 files changed, 74 insertions(+), 31 deletions(-) diff --git a/ipalib/cli.py b/ipalib/cli.py index 161ea1d82..c1ad82d52 100644 --- a/ipalib/cli.py +++ b/ipalib/cli.py @@ -31,6 +31,7 @@ import errors import plugable import ipa_types from config import set_default_env, read_config +import util def exit_error(error): sys.exit('ipa: ERROR: %s' % error) @@ -303,19 +304,7 @@ class CLI(object): """ self.__doing('bootstrap') self.parse_globals() - self.api.env.verbose = self.options.verbose - if self.options.config_file: - self.api.env.conf = self.options.config_file - overrides = {} - if self.options.environment: - for a in self.options.environment.split(','): - a = a.split('=', 1) - if len(a) < 2: - parser.error('badly specified environment string,'\ - 'use var1=val1[,var2=val2]..') - overrides[str(a[0].strip())] = a[1].strip() - overrides['context'] = 'cli' - self.api.bootstrap(**overrides) + self.api.bootstrap_from_options(self.options, context='cli') def parse_globals(self): """ @@ -337,17 +326,17 @@ class CLI(object): help='Prompt for all missing options interactively') parser.add_option('-n', dest='interactive', action='store_false', help='Don\'t prompt for any options interactively') - parser.add_option('-c', dest='config_file', - help='Specify different configuration file') - parser.add_option('-e', dest='environment', - help='Specify or override environment variables') - parser.add_option('-v', dest='verbose', action='store_true', - help='Verbose output') +# parser.add_option('-c', dest='config_file', +# help='Specify different configuration file') +# parser.add_option('-e', dest='environment', +# help='Specify or override environment variables') +# parser.add_option('-v', dest='verbose', action='store_true', +# help='Verbose output') parser.set_defaults( prompt_all=False, interactive=True, - verbose=False, ) + util.add_global_options(parser) (options, args) = parser.parse_args(list(self.argv)) self.options = options self.cmd_argv = tuple(args) diff --git a/ipalib/plugable.py b/ipalib/plugable.py index 9e612d68d..f552b61f6 100644 --- a/ipalib/plugable.py +++ b/ipalib/plugable.py @@ -26,6 +26,7 @@ http://docs.python.org/ref/sequence-types.html """ import re +import sys import inspect import threading import logging @@ -38,6 +39,7 @@ from constants import LOGGING_FILE_FORMAT, LOGGING_CONSOLE_FORMAT, DEFAULT_CONFI import util + class ReadOnly(object): """ Base class for classes with read-only attributes. @@ -812,6 +814,31 @@ class API(DictProxy): handler.setLevel(level) log.addHandler(handler) + def bootstrap_from_options(self, options=None, context=None): + if options is None: + parser = util.add_global_options() + (options, args) = parser.parse_args( + list(s.decode('utf-8') for s in sys.argv[1:]) + ) + overrides = {} + if options.env is not None: + assert type(options.env) is list + for item in options.env: + try: + (key, value) = item.split('=', 1) + except ValueError: + # FIXME: this should raise an IPA exception with an + # error code. + # --Jason, 2008-10-31 + pass + overrides[str(key.strip())] = value.strip() + for key in ('conf', 'debug', 'verbose'): + value = getattr(options, key, None) + if value is not None: + overrides[key] = value + if context is not None: + overrides['context'] = context + self.bootstrap(**overrides) def load_plugins(self): """ diff --git a/ipalib/util.py b/ipalib/util.py index 3222c5a7b..48a3a1296 100644 --- a/ipalib/util.py +++ b/ipalib/util.py @@ -24,6 +24,7 @@ Various utility functions. import os from os import path import imp +import optparse import krbV from constants import LOGGING_CONSOLE_FORMAT, LOGGING_FILE_FORMAT @@ -101,3 +102,24 @@ def import_plugins_subpackage(name): for name in find_modules_in_dir(src_dir): full_name = '%s.%s' % (plugins.__name__, name) __import__(full_name) + + +def add_global_options(parser=None): + """ + Add global options to an optparse.OptionParser instance. + """ + if parser is None: + parser = optparse.OptionParser() + parser.add_option('-e', dest='env', metavar='KEY=VAL', action='append', + help='Set environment variable KEY to VAL', + ) + parser.add_option('-c', dest='conf', metavar='FILE', + help='Load configuration from FILE', + ) + parser.add_option('-d', '--debug', action='store_true', + help='Produce full debuging output', + ) + parser.add_option('-v', '--verbose', action='store_true', + help='Produce more verbose output', + ) + return parser diff --git a/lite-xmlrpc.py b/lite-xmlrpc.py index 131ef8b3c..26204d92e 100755 --- a/lite-xmlrpc.py +++ b/lite-xmlrpc.py @@ -144,7 +144,7 @@ class LoggingSimpleXMLRPCRequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHa if __name__ == '__main__': - api.bootstrap(context='server') + api.bootstrap_from_options(context='server') api.finalize() logger = api.log diff --git a/tests/test_ipalib/test_cli.py b/tests/test_ipalib/test_cli.py index f13db51eb..565459421 100644 --- a/tests/test_ipalib/test_cli.py +++ b/tests/test_ipalib/test_cli.py @@ -189,7 +189,6 @@ class test_CLI(ClassChecker): keys = tuple(api.env) added = ( 'my_key', - 'whatever', 'from_default_conf', 'from_cli_conf' ) @@ -203,8 +202,7 @@ class test_CLI(ClassChecker): home.write(config_default, '.ipa', 'default.conf') home.write(config_cli, '.ipa', 'cli.conf') o.bootstrap() - assert api.env.my_key == 'my_val' - assert api.env.whatever == 'Hello' + assert api.env.my_key == 'my_val,whatever=Hello' assert api.env.from_default_conf == 'set in default.conf' assert api.env.from_cli_conf == 'set in cli.conf' assert list(api.env) == sorted(keys + added) @@ -213,22 +211,23 @@ class test_CLI(ClassChecker): """ Test the `ipalib.cli.CLI.parse_globals` method. """ - # Test with empty argv + # Test with empty argv: (o, api, home) = self.new() assert not hasattr(o, 'options') assert not hasattr(o, 'cmd_argv') assert o.isdone('parse_globals') is False o.parse_globals() assert o.isdone('parse_globals') is True + assert o.options.prompt_all is False assert o.options.interactive is True - assert o.options.verbose is False - assert o.options.config_file is None - assert o.options.environment is None + assert o.options.verbose is None + assert o.options.conf is None + assert o.options.env is None assert o.cmd_argv == tuple() e = raises(StandardError, o.parse_globals) assert str(e) == 'CLI.parse_globals() already called' - # Test with a populated argv + # Test with a populated argv: argv = ('-a', '-n', '-v', '-c', '/my/config.conf', '-e', 'my_key=my_val') cmd_argv = ('user-add', '--first', 'John', '--last', 'Doe') (o, api, home) = self.new(argv + cmd_argv) @@ -240,8 +239,14 @@ class test_CLI(ClassChecker): assert o.options.prompt_all is True assert o.options.interactive is False assert o.options.verbose is True - assert o.options.config_file == '/my/config.conf' - assert o.options.environment == 'my_key=my_val' + assert o.options.conf == '/my/config.conf' + assert o.options.env == ['my_key=my_val'] assert o.cmd_argv == cmd_argv e = raises(StandardError, o.parse_globals) assert str(e) == 'CLI.parse_globals() already called' + + # Test with multiple -e args: + argv = ('-e', 'key1=val1', '-e', 'key2=val2') + (o, api, home) = self.new(argv) + o.parse_globals() + assert o.options.env == ['key1=val1', 'key2=val2']