mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2024-12-25 08:21:05 -06:00
Started cleanup work on CLI class, added unit tests for CLI.parse_globals()
This commit is contained in:
parent
d76202fea3
commit
10026284db
4
ipa
4
ipa
@ -31,5 +31,7 @@ from ipalib.cli import CLI
|
|||||||
api.load_plugins()
|
api.load_plugins()
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
cli = CLI(api)
|
cli = CLI(api,
|
||||||
|
(s.decode('utf-8') for s in sys.args[1:])
|
||||||
|
)
|
||||||
sys.exit(cli.run())
|
sys.exit(cli.run())
|
||||||
|
115
ipalib/cli.py
115
ipalib/cli.py
@ -84,6 +84,24 @@ class help(frontend.Application):
|
|||||||
print 'Purpose: %s' % cmd.doc
|
print 'Purpose: %s' % cmd.doc
|
||||||
self.application.build_parser(cmd).print_help()
|
self.application.build_parser(cmd).print_help()
|
||||||
|
|
||||||
|
def print_commands(self):
|
||||||
|
std = set(self.api.Command) - set(self.api.Application)
|
||||||
|
print '\nStandard IPA commands:'
|
||||||
|
for key in sorted(std):
|
||||||
|
cmd = self.api.Command[key]
|
||||||
|
self.print_cmd(cmd)
|
||||||
|
print '\nSpecial CLI commands:'
|
||||||
|
for cmd in self.api.Application():
|
||||||
|
self.print_cmd(cmd)
|
||||||
|
print '\nUse the --help option to see all the global options'
|
||||||
|
print ''
|
||||||
|
|
||||||
|
def print_cmd(self, cmd):
|
||||||
|
print ' %s %s' % (
|
||||||
|
to_cli(cmd.name).ljust(self.mcl),
|
||||||
|
cmd.doc,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class console(frontend.Application):
|
class console(frontend.Application):
|
||||||
'Start the IPA interactive Python console.'
|
'Start the IPA interactive Python console.'
|
||||||
@ -207,32 +225,24 @@ class CLI(object):
|
|||||||
__d = None
|
__d = None
|
||||||
__mcl = None
|
__mcl = None
|
||||||
|
|
||||||
def __init__(self, api):
|
def __init__(self, api, argv):
|
||||||
self.__api = api
|
self.api = api
|
||||||
self.__all_interactive = False
|
self.argv = tuple(argv)
|
||||||
self.__not_interactive = False
|
self.__done = set()
|
||||||
|
|
||||||
def __get_api(self):
|
def __doing(self, name):
|
||||||
return self.__api
|
if name in self.__done:
|
||||||
api = property(__get_api)
|
raise StandardError(
|
||||||
|
'%s.%s() already called' % (self.__class__.__name__, name)
|
||||||
def print_commands(self):
|
|
||||||
std = set(self.api.Command) - set(self.api.Application)
|
|
||||||
print '\nStandard IPA commands:'
|
|
||||||
for key in sorted(std):
|
|
||||||
cmd = self.api.Command[key]
|
|
||||||
self.print_cmd(cmd)
|
|
||||||
print '\nSpecial CLI commands:'
|
|
||||||
for cmd in self.api.Application():
|
|
||||||
self.print_cmd(cmd)
|
|
||||||
print '\nUse the --help option to see all the global options'
|
|
||||||
print ''
|
|
||||||
|
|
||||||
def print_cmd(self, cmd):
|
|
||||||
print ' %s %s' % (
|
|
||||||
to_cli(cmd.name).ljust(self.mcl),
|
|
||||||
cmd.doc,
|
|
||||||
)
|
)
|
||||||
|
self.__done.add(name)
|
||||||
|
|
||||||
|
def __do_if_not_done(self, name):
|
||||||
|
if name not in self.__done:
|
||||||
|
getattr(self, name)()
|
||||||
|
|
||||||
|
def isdone(self, name):
|
||||||
|
return name in self.__done
|
||||||
|
|
||||||
def __contains__(self, key):
|
def __contains__(self, key):
|
||||||
assert self.__d is not None, 'you must call finalize() first'
|
assert self.__d is not None, 'you must call finalize() first'
|
||||||
@ -360,10 +370,11 @@ class CLI(object):
|
|||||||
parser.add_option(o)
|
parser.add_option(o)
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
def parse_globals(self, argv=sys.argv[1:]):
|
def parse_globals(self):
|
||||||
|
self.__doing('parse_globals')
|
||||||
parser = optparse.OptionParser()
|
parser = optparse.OptionParser()
|
||||||
parser.disable_interspersed_args()
|
parser.disable_interspersed_args()
|
||||||
parser.add_option('-a', dest='interactive', action='store_true',
|
parser.add_option('-a', dest='prompt_all', action='store_true',
|
||||||
help='Prompt for all missing options interactively')
|
help='Prompt for all missing options interactively')
|
||||||
parser.add_option('-n', dest='interactive', action='store_false',
|
parser.add_option('-n', dest='interactive', action='store_false',
|
||||||
help='Don\'t prompt for any options interactively')
|
help='Don\'t prompt for any options interactively')
|
||||||
@ -373,29 +384,39 @@ class CLI(object):
|
|||||||
help='Specify or override environment variables')
|
help='Specify or override environment variables')
|
||||||
parser.add_option('-v', dest='verbose', action='store_true',
|
parser.add_option('-v', dest='verbose', action='store_true',
|
||||||
help='Verbose output')
|
help='Verbose output')
|
||||||
(options, args) = parser.parse_args(argv)
|
parser.set_defaults(
|
||||||
|
prompt_all=False,
|
||||||
|
interactive=True,
|
||||||
|
verbose=False,
|
||||||
|
)
|
||||||
|
(options, args) = parser.parse_args(list(self.argv))
|
||||||
|
self.options = options
|
||||||
|
self.cmd_argv = tuple(args)
|
||||||
|
|
||||||
if options.interactive == True:
|
def bootstrap(self):
|
||||||
self.__all_interactive = True
|
pass
|
||||||
elif options.interactive == False:
|
|
||||||
self.__not_interactive = True
|
|
||||||
if options.verbose != None:
|
|
||||||
self.api.env.verbose = True
|
|
||||||
if options.environment:
|
|
||||||
env_dict = {}
|
|
||||||
for a in options.environment.split(','):
|
|
||||||
a = a.split('=', 1)
|
|
||||||
if len(a) < 2:
|
|
||||||
parser.error('badly specified environment string,'\
|
|
||||||
'use var1=val1[,var2=val2]..')
|
|
||||||
env_dict[a[0].strip()] = a[1].strip()
|
|
||||||
self.api.env.update(env_dict, True)
|
|
||||||
if options.config_file:
|
|
||||||
self.api.env.update(read_config(options.config_file), True)
|
|
||||||
else:
|
|
||||||
self.api.env.update(read_config(), True)
|
|
||||||
|
|
||||||
return args
|
# if options.interactive == True:
|
||||||
|
# self.__all_interactive = True
|
||||||
|
# elif options.interactive == False:
|
||||||
|
# self.__not_interactive = True
|
||||||
|
# if options.verbose != None:
|
||||||
|
# self.api.env.verbose = True
|
||||||
|
# if options.environment:
|
||||||
|
# env_dict = {}
|
||||||
|
# for a in options.environment.split(','):
|
||||||
|
# a = a.split('=', 1)
|
||||||
|
# if len(a) < 2:
|
||||||
|
# parser.error('badly specified environment string,'\
|
||||||
|
# 'use var1=val1[,var2=val2]..')
|
||||||
|
# env_dict[a[0].strip()] = a[1].strip()
|
||||||
|
# self.api.env.update(env_dict, True)
|
||||||
|
# if options.config_file:
|
||||||
|
# self.api.env.update(read_config(options.config_file), True)
|
||||||
|
# else:
|
||||||
|
# self.api.env.update(read_config(), True)
|
||||||
|
|
||||||
|
# return args
|
||||||
|
|
||||||
def get_usage(self, cmd):
|
def get_usage(self, cmd):
|
||||||
return ' '.join(self.get_usage_iter(cmd))
|
return ' '.join(self.get_usage_iter(cmd))
|
||||||
|
@ -22,7 +22,7 @@ Test the `ipalib.cli` module.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from tests.util import raises, getitem, no_set, no_del, read_only, ClassChecker
|
from tests.util import raises, getitem, no_set, no_del, read_only, ClassChecker
|
||||||
from ipalib import cli, plugable
|
from ipalib import cli, plugable, frontend, backend
|
||||||
|
|
||||||
|
|
||||||
def test_to_cli():
|
def test_to_cli():
|
||||||
@ -81,60 +81,61 @@ class test_CLI(ClassChecker):
|
|||||||
"""
|
"""
|
||||||
_cls = cli.CLI
|
_cls = cli.CLI
|
||||||
|
|
||||||
def test_class(self):
|
def new(self, argv):
|
||||||
"""
|
api = plugable.API(
|
||||||
Test the `ipalib.cli.CLI` class.
|
frontend.Command,
|
||||||
"""
|
frontend.Object,
|
||||||
assert type(self.cls.api) is property
|
frontend.Method,
|
||||||
|
frontend.Property,
|
||||||
def test_api(self):
|
frontend.Application,
|
||||||
"""
|
backend.Backend,
|
||||||
Test the `ipalib.cli.CLI.api` property.
|
|
||||||
"""
|
|
||||||
api = 'the plugable.API instance'
|
|
||||||
o = self.cls(api)
|
|
||||||
assert read_only(o, 'api') is api
|
|
||||||
|
|
||||||
def dont_parse(self):
|
|
||||||
"""
|
|
||||||
Test the `ipalib.cli.CLI.parse` method.
|
|
||||||
"""
|
|
||||||
o = self.cls(None)
|
|
||||||
args = ['hello', 'naughty', 'nurse']
|
|
||||||
kw = dict(
|
|
||||||
first_name='Naughty',
|
|
||||||
last_name='Nurse',
|
|
||||||
)
|
)
|
||||||
opts = ['--%s=%s' % (k.replace('_', '-'), v) for (k, v) in kw.items()]
|
o = self.cls(api, argv)
|
||||||
assert o.parse(args + []) == (args, {})
|
assert o.api is api
|
||||||
assert o.parse(opts + []) == ([], kw)
|
return o
|
||||||
assert o.parse(args + opts) == (args, kw)
|
|
||||||
assert o.parse(opts + args) == (args, kw)
|
|
||||||
|
|
||||||
def test_mcl(self):
|
def test_init(self):
|
||||||
"""
|
"""
|
||||||
Test the `ipalib.cli.CLI.mcl` property .
|
Test the `ipalib.cli.CLI.__init__` method.
|
||||||
"""
|
"""
|
||||||
cnt = 100
|
argv = ['-v', 'user-add', '--first=Jonh', '--last=Doe']
|
||||||
api = DummyAPI(cnt)
|
o = self.new(argv)
|
||||||
len(api.Command) == cnt
|
assert type(o.api) is plugable.API
|
||||||
o = self.cls(api)
|
assert o.argv == tuple(argv)
|
||||||
assert o.mcl is None
|
|
||||||
o.build_map()
|
|
||||||
assert o.mcl == 6 # len('cmd_99')
|
|
||||||
|
|
||||||
def test_dict(self):
|
def test_parse_globals(self):
|
||||||
"""
|
"""
|
||||||
Test container emulation of `ipalib.cli.CLI` class.
|
Test the `ipalib.cli.CLI.parse_globals` method.
|
||||||
"""
|
"""
|
||||||
cnt = 25
|
# Test with empty argv
|
||||||
api = DummyAPI(cnt)
|
o = self.new([])
|
||||||
assert len(api.Command) == cnt
|
assert not hasattr(o, 'options')
|
||||||
o = self.cls(api)
|
assert not hasattr(o, 'cmd_argv')
|
||||||
o.build_map()
|
assert o.isdone('parse_globals') is False
|
||||||
for cmd in api.Command():
|
o.parse_globals()
|
||||||
key = cli.to_cli(cmd.name)
|
assert o.isdone('parse_globals') is True
|
||||||
assert key in o
|
assert o.options.interactive is True
|
||||||
assert o[key] is cmd
|
assert o.options.verbose is False
|
||||||
assert cmd.name not in o
|
assert o.options.config_file is None
|
||||||
raises(KeyError, getitem, o, cmd.name)
|
assert o.options.environment 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
|
||||||
|
argv = ('-a', '-n', '-v', '-c', '/my/config.conf', '-e', 'my_key=my_val')
|
||||||
|
cmd_argv = ('user-add', '--first', 'John', '--last', 'Doe')
|
||||||
|
o = self.new(argv + cmd_argv)
|
||||||
|
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 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.cmd_argv == cmd_argv
|
||||||
|
e = raises(StandardError, o.parse_globals)
|
||||||
|
assert str(e) == 'CLI.parse_globals() already called'
|
||||||
|
Loading…
Reference in New Issue
Block a user