Michael Pasternak has uploaded a new change for review.

Change subject: cli: --storagedomain appears as an option in all vm actions 
#856164
......................................................................

cli: --storagedomain appears as an option in all vm actions #856164

The reason for this is that actions for vm exist in two dimensions,

1. None
2. storagedomain

e.g vm has actions when it in context of storagedomain (like import)
and without any context (like start, stop, etc.), auto-completion refactored
to be action context-aware and exclude not relevant options for the
given context.

https://bugzilla.redhat.com/show_bug.cgi?id=856164

Change-Id: Ie8daaf69385450ab8e17d041e2309ad3a0e29a33
Signed-off-by: Michael Pasternak <mpast...@redhat.com>
---
M src/ovirtcli/shell/actioncmdshell.py
M src/ovirtcli/shell/cmdshell.py
M src/ovirtcli/utils/autocompletionhelper.py
3 files changed, 130 insertions(+), 32 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-engine-cli refs/changes/45/8145/1

diff --git a/src/ovirtcli/shell/actioncmdshell.py 
b/src/ovirtcli/shell/actioncmdshell.py
index 3e8e720..60593f7 100644
--- a/src/ovirtcli/shell/actioncmdshell.py
+++ b/src/ovirtcli/shell/actioncmdshell.py
@@ -27,55 +27,153 @@
 
     def __init__(self, context, parser):
         CmdShell.__init__(self, context, parser)
+        self.complete_exceptions = ['delete', 'update']
+        self.identifier_template = '--%s-identifier'
 
     def do_action(self, args):
         return self.context.execute_string(ActionCmdShell.NAME + ' ' + args + 
'\n')
 
     def __add_resource_specific_options(self, obj, specific_options, line, 
key=None):
         obj_type = TypeHelper.getDecoratorType(TypeHelper.to_singular(obj))
+        gda = MethodHelper.get_documented_arguments
+        gat = TypeHelper.get_actionable_types
+        memeber = key if key is not None else obj
+        method_args = []
+        action = None
+
         if obj_type and hasattr(brokers, obj_type):
-
-            args = TypeHelper.get_actionable_types(expendNestedTypes=True)
-            specific_arguments = self.get_resource_specific_options(args,
-                                                                    line,
-                                                                    
callback=self.__add_resource_specific_arguments)
-
-            action = None
-            memeber = key if key is not None else obj
-            for arg in line.split():
-                if specific_arguments.has_key(memeber) and arg in 
specific_arguments[memeber]:
-                    action = arg
-                    break
-
+            action = self.__get_method_name_by_args(obj,
+                                                    line.split(' '),
+                                                    
gat(expendNestedTypes=True),
+                                                    line)
             if action:
                 obj_typ_ref = getattr(brokers, obj_type)
                 if obj_typ_ref and hasattr(obj_typ_ref, action):
-                    method_args = 
MethodHelper.get_documented_arguments(method_ref=getattr(obj_typ_ref, action),
-                                                                        
as_params_collection=True,
-                                                                        
spilt_or=True)
+                    method_args = gda(method_ref=getattr(obj_typ_ref, action),
+                                      as_params_collection=True,
+                                      spilt_or=True)
                     if method_args:
                         specific_options[memeber] = method_args
 
+    def __get_resource_actions(self, obj, args, line):
+        gom = MethodHelper.get_object_methods
+        gdt = TypeHelper.getDecoratorType
+        obj_type = gdt(obj)
+        actions = []
+
+        if obj_type:
+            #add base resource actions
+            actions = gom(getattr(brokers, obj_type),
+                          exceptions=self.complete_exceptions)
+
+            #add sub-resources actions
+            if  args.has_key(obj) and args[obj]:
+                self.__add_sub_resourse_actions(obj, args, line, actions)
+
+        return actions
+
+
+    def __get_method_name_by_args(self, obj, spl, args, line):
+        actions = self.__get_resource_actions(obj, args, line)
+
+        for item in spl:
+            if item in actions: return item
+
+    def __add_sub_resourse_actions(self, obj, args, line, actions):
+        gdt = TypeHelper.getDecoratorType
+        gom = MethodHelper.get_object_methods
+
+        if obj in args.keys():
+            for cons in args[obj].split(', '):
+                spl = line.strip().split(' ')
+                if cons != 'None':
+                    spl.append(self.identifier_template % cons)
+                    base = self._resolve_base(spl[1:])
+                    if base:
+                        obj_type = gdt(TypeHelper.to_singular(base))
+                        actions.extend(gom(getattr(brokers, obj_type),
+                                           
exceptions=self.complete_exceptions))
+
+
     def __add_resource_specific_arguments(self, obj, specific_options, line, 
key=None):
-        obj_type = TypeHelper.getDecoratorType(TypeHelper.to_singular(obj))
-        if obj_type and hasattr(brokers, obj_type):
-            method_args = MethodHelper.get_object_methods(getattr(brokers, 
obj_type),
-                                                          
exceptions=['delete', 'update'])
-            if method_args:
-                specific_options[obj if key == None else key] = method_args
+        gdt = TypeHelper.getDecoratorType
+        obj_type = gdt(TypeHelper.to_singular(obj))
+        args = TypeHelper.get_actionable_types(expendNestedTypes=True)
+        gom = MethodHelper.get_object_methods
+        actions = []
+
+        method = self.__get_method_name_by_args(obj, line.split(' '), args, 
line)
+
+        # collect resource args if yet not used
+        if not method and obj_type and hasattr(brokers, obj_type):
+            #add base resource actions
+            actions = gom(getattr(brokers, obj_type),
+                          exceptions=self.complete_exceptions)
+
+            if args.has_key(obj) and args[obj]:
+                #add sub-resources actions
+                self.__add_sub_resourse_actions(obj, args, line, actions)
+
+        specific_options[obj if key == None else key] = actions
+
+
+    def __get_action_args(self, line):
+        args = TypeHelper.get_actionable_types(expendNestedTypes=True)
+        spl = line.rstrip().split(' ')
+        gom = MethodHelper.get_object_methods
+        gdt = TypeHelper.getDecoratorType
+
+        if len(spl) >= 3:
+            new_cons = ''
+            obj = spl[1].strip()
+
+            #top level resource in possibilities
+            if args.has_key(obj) and args[obj] and args[obj].find('None') != 
-1:
+                act = spl[3].strip() if len(spl) > 3 \
+                                     else spl[-1].strip()
+            #possibilities refer only to the sub-resource
+            else:
+                for item in spl:
+                    if item.endswith('-identifier'):
+                        args[obj] = new_cons
+                        return args
+                return args
+
+            for cons in args[obj].split(', '):
+                if cons == 'None':
+                    obj_type = gdt(obj)
+                    if not obj_type: continue
+                    actions = gom(getattr(brokers, obj_type),
+                                  exceptions=self.complete_exceptions)
+                    if actions and act in actions:
+                        new_cons += 'None, '
+                else:
+                    tmp_spl = spl[:]
+                    tmp_spl.append(self.identifier_template % cons)
+                    base = self._resolve_base(tmp_spl[1:])
+                    if base:
+                        obj_type = gdt(TypeHelper.to_singular(base))
+                        if not obj_type: continue
+                        actions = gom(getattr(brokers, obj_type),
+                                      exceptions=self.complete_exceptions)
+                        if actions and act in actions:
+                            new_cons += cons + ', '
+
+            args[obj] = new_cons[:len(new_cons) - 2] if len(new_cons) > 3 \
+                                                     else ''
+
+        return args
 
     def complete_action(self, text, line, begidx, endidx):
-        args = TypeHelper.get_actionable_types(expendNestedTypes=True)
-        specific_arguments = {}
+        args = self.__get_action_args(line)
 
         specific_options = self.get_resource_specific_options(args,
                                                               line,
                                                               
callback=self.__add_resource_specific_options)
 
-        if not specific_options:
-            specific_arguments = self.get_resource_specific_options(args,
-                                                                    line,
-                                                                    
callback=self.__add_resource_specific_arguments)
+        specific_arguments = self.get_resource_specific_options(args,
+                                                                line,
+                                                                
callback=self.__add_resource_specific_arguments)
 
         return AutoCompletionHelper.complete(line,
                                              text,
diff --git a/src/ovirtcli/shell/cmdshell.py b/src/ovirtcli/shell/cmdshell.py
index 2ea999a..7ed5956 100644
--- a/src/ovirtcli/shell/cmdshell.py
+++ b/src/ovirtcli/shell/cmdshell.py
@@ -84,9 +84,9 @@
 
         if line:
             spl = line.rstrip().split(' ')
-            if len(spl) > 2:
+            if len(spl) >= 2:
                 obj = spl[1].strip()
-                base = self.__resolve_base(spl[1:])
+                base = self._resolve_base(spl[1:])
                 if base:
                     callback(base, specific_options, line=line, key=obj)
                 else:
@@ -96,7 +96,7 @@
 
             return specific_options
 
-    def __resolve_base(self, args):
+    def _resolve_base(self, args):
         """resolves a base object from a set of '--type-identifier value' 
options."""
         PARENT_IDENTIFIER = '-identifier'
         parnet_candidates = [item for item in args
diff --git a/src/ovirtcli/utils/autocompletionhelper.py 
b/src/ovirtcli/utils/autocompletionhelper.py
index a79c9c4..df27ded 100644
--- a/src/ovirtcli/utils/autocompletionhelper.py
+++ b/src/ovirtcli/utils/autocompletionhelper.py
@@ -23,7 +23,7 @@
             if args[key] != None:
                 vals = []
                 for val in args[key].split(','):
-                    vals.append(val.strip())
+                    if val and val != '': vals.append(val.strip())
 
                 if common_options:
                     vals.extend(common_options)


--
To view, visit http://gerrit.ovirt.org/8145
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ie8daaf69385450ab8e17d041e2309ad3a0e29a33
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-engine-cli
Gerrit-Branch: master
Gerrit-Owner: Michael Pasternak <mpast...@redhat.com>
_______________________________________________
Engine-patches mailing list
Engine-patches@ovirt.org
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to