summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRob Crittenden <rcritten@redhat.com>2009-07-10 16:43:47 -0400
committerRob Crittenden <rcritten@redhat.com>2009-07-10 16:44:22 -0400
commit0e29dd7226119e69f3bf123395251140ad4260ca (patch)
tree68f423b62a64b2fecc692eb6b95af945c2597e21
parente31d5fb1cfc7b7b2ed47202e0ef1c462f01a046b (diff)
downloadfreeipa-0e29dd7226119e69f3bf123395251140ad4260ca.tar.gz
freeipa-0e29dd7226119e69f3bf123395251140ad4260ca.tar.xz
freeipa-0e29dd7226119e69f3bf123395251140ad4260ca.zip
Add textui function to display and prompt user for selection for *-find.
Since we may end up executing a *-show when an entry is selected we need to defer destroying the connection context.
-rw-r--r--ipalib/backend.py4
-rw-r--r--ipalib/cli.py70
2 files changed, 66 insertions, 8 deletions
diff --git a/ipalib/backend.py b/ipalib/backend.py
index 0c93b16e6..da7fc2922 100644
--- a/ipalib/backend.py
+++ b/ipalib/backend.py
@@ -102,6 +102,9 @@ class Executioner(Backend):
else:
self.Backend.xmlclient.connect()
+ def destroy_context(self):
+ destroy_context()
+
def execute(self, _name, *args, **options):
error = None
try:
@@ -115,7 +118,6 @@ class Executioner(Backend):
'non-public: %s: %s', e.__class__.__name__, str(e)
)
error = InternalError()
- destroy_context()
if error is None:
return result
assert isinstance(error, PublicError)
diff --git a/ipalib/cli.py b/ipalib/cli.py
index 6dc0c0682..df0cd37ca 100644
--- a/ipalib/cli.py
+++ b/ipalib/cli.py
@@ -422,6 +422,59 @@ class textui(backend.Backend):
print ''
self.print_error(_('Cancelled.'))
+ def select_entry(self, entries, format, attrs, display_count=True):
+ """
+ Display a list of lines in with formatting defined in ``format``.
+ ``attrs`` is a list of attributes in the format.
+
+ Prompt user for a selection and return the value (index of
+ ``entries`` -1).
+
+ If only one entry is provided then always return 0.
+
+ Return: 0..n for the index of the selected entry
+ -1 if all entries should be displayed
+ -2 to quit, no entries to be displayed
+ """
+ if not self.env.interactive or not sys.stdout.isatty():
+ return -1
+
+ counter = len(entries)
+ i = 1
+ for e in entries:
+ # There is no guarantee that all attrs are in any given
+ # entry
+ d = {}
+ for a in attrs:
+ d[a] = e.get(a, '')
+ self.print_line("%d: %s" % (i, format % d))
+ i = i + 1
+
+ if display_count:
+ self.print_count(entries, 'Found %d match', 'Found %d matches')
+
+ while True:
+ try:
+ resp = self.prompt("Choose one: (1 - %s), a for all, q to quit" % counter)
+ except EOFError:
+ return -2
+
+ if resp.lower() == "q":
+ return -2
+ if resp.lower() == "a":
+ return -1
+ try:
+ selection = int(resp) - 1
+ if (selection >= 0 and selection < counter):
+ break
+ except:
+ # fall through to the error msg
+ pass
+
+ self.print_line("Please enter a number between 1 and %s" % counter)
+
+ self.print_line('')
+ return selection
class help(frontend.Command):
"""
@@ -630,13 +683,16 @@ class cli(backend.Executioner):
kw = self.parse(cmd, argv)
if self.env.interactive:
self.prompt_interactively(cmd, kw)
- result = self.execute(name, **kw)
- if callable(cmd.output_for_cli):
- for param in cmd.params():
- if param.password and param.name in kw:
- del kw[param.name]
- (args, options) = cmd.params_2_args_options(**kw)
- cmd.output_for_cli(self.api.Backend.textui, result, *args, **options)
+ try:
+ result = self.execute(name, **kw)
+ if callable(cmd.output_for_cli):
+ for param in cmd.params():
+ if param.password and param.name in kw:
+ del kw[param.name]
+ (args, options) = cmd.params_2_args_options(**kw)
+ cmd.output_for_cli(self.api.Backend.textui, result, *args, **options)
+ finally:
+ self.destroy_context()
def parse(self, cmd, argv):
parser = self.build_parser(cmd)