st2client/st2client/commands/action.py
def _get_action_parameters_from_args(self, action, runner, args):
        """
        Build a dictionary with parameters which will be passed to the action by
        parsing parameters passed to the CLI.

        :param args: CLI argument.
        :type args: ``object``

        :rtype: ``dict``
        """
        action_ref_or_id = action.ref

        def read_file(file_path):
            if not os.path.exists(file_path):
                raise ValueError('File "%s" doesn\'t exist' % (file_path))

            if not os.path.isfile(file_path):
                raise ValueError('"%s" is not a file' % (file_path))

            with open(file_path, 'rb') as fp:
                content = fp.read()

            return content

        def transform_object(value):
            # Also support simple key1=val1,key2=val2 syntax
            if value.startswith('{'):
                # Assume it's JSON
                result = value = json.loads(value)
            else:
                pairs = value.split(',')

                result = {}
                for pair in pairs:
                    split = pair.split('=', 1)

                    if len(split) != 2:
                        continue

                    key, value = split
                    result[key] = value
            return result

        def transform_array(value):
            # Sometimes an array parameter only has a single element:
            #
            #     i.e. "st2 run foopack.fooaction arrayparam=51"
            #
            # Normally, json.loads would throw an exception, and the split method
            # would be used. However, since this is an int, not only would
            # splitting not work, but json.loads actually treats this as valid JSON,
            # but as an int, not an array. This causes a mismatch when the API is called.
            #
            # We want to try to handle this first, so it doesn't get accidentally
            # sent to the API as an int, instead of an array of single-element int.
            try:
                # Force this to be a list containing the single int, then
                # cast the whole thing to string so json.loads can handle it
                value = str([int(value)])
            except ValueError:
                # Original value wasn't an int, so just let it continue
                pass

            # At this point, the input is either a a "json.loads"-able construct
            # like [1, 2, 3], or even [1], or it is a comma-separated list,
            # Try both, in that order.
            try:
                result = json.loads(value)
            except ValueError:
                result = [v.strip() for v in value.split(',')]
            return result

        transformer = {
            'array': transform_array,
            'boolean': (lambda x: ast.literal_eval(x.capitalize())),
            'integer': int,
            'number': float,
            'object': transform_object,
            'string': str
        }

        def normalize(name, value):
            """ The desired type is contained in the action meta-data, so we can look that up
                and call the desired "caster" function listed in the "transformer" dict
            """

            # Users can also specify type for each array parameter inside an action metadata
            # (items: type: int for example) and this information is available here so we could
            # also leverage that to cast each array item to the correct type.

            if name in runner.runner_parameters:
                param = runner.runner_parameters[name]
                if 'type' in param and param['type'] in transformer:
                    return transformer[param['type']](value)

            if name in action.parameters:
                param = action.parameters[name]
                if 'type' in param and param['type'] in transformer:
                    return transformer[param['type']](value)
            return value

        result = {}

        if not args.parameters:
            return result

        for idx in range(len(args.parameters)):
            arg = args.parameters[idx]
            if '=' in arg:
                k, v = arg.split('=', 1)

                # Attribute for files are prefixed with "@"
                if k.startswith('@'):
                    k = k[1:]
                    is_file = True
                else:
                    is_file = False

                try:
                    if is_file:
                        # Files are handled a bit differently since we ship the content
                        # over the wire
                        file_path = os.path.normpath(pjoin(os.getcwd(), v))
                        file_name = os.path.basename(file_path)
                        content = read_file(file_path=file_path)

                        if action_ref_or_id == 'core.http':
                            # Special case for http runner
                            result['_file_name'] = file_name
                            result['file_content'] = content
                        else:
                            result[k] = content
                    else:
                        result[k] = normalize(k, v)
                except Exception as e:
                    # TODO: Move transformers in a separate module and handle
                    # exceptions there
                    if 'malformed string' in str(e):
                        message = ('Invalid value for boolean parameter. '
                                   'Valid values are: true, false')
                        raise ValueError(message)
                    else:
                        raise e
            else:
                result['cmd'] = ' '.join(args.parameters[idx:])
                break

        # Special case for http runner
        if 'file_content' in result:
            if 'method' not in result:
                # Default to POST if a method is not provided
                result['method'] = 'POST'

            if 'file_name' not in result:
                # File name not provided, use default file name
                result['file_name'] = result['_file_name']

            del result['_file_name']

        if args.inherit_env:
            result['env'] = self._get_inherited_env_vars()

        return result

        Build a dictionary with parameters which will be passed to the action by
        parsing parameters passed to the CLI.

        :param args: CLI argument.
        :type args: ``object``

        :rtype: ``dict``
        
Build a dictionary with parameters which will be passed to the action by
parsing parameters passed to the CLI.
Build a dictionary with parameters which will be passed to the action by parsing parameters passed to the CLI .
def _get_action_parameters_from_args(self, action, runner, args):
        action_ref_or_id = action.ref
        def read_file(file_path):
            if not os.path.exists(file_path):
                raise ValueError('File "%s" doesn\'t exist' % (file_path))
            if not os.path.isfile(file_path):
                raise ValueError('"%s" is not a file' % (file_path))
            with open(file_path, 'rb') as fp:
                content = fp.read()
            return content
        def transform_object(value):
            if value.startswith('{'):
                result = value = json.loads(value)
            else:
                pairs = value.split(',')
                result = {}
                for pair in pairs:
                    split = pair.split('=', 1)
                    if len(split) != 2:
                        continue
                    key, value = split
                    result[key] = value
            return result
        def transform_array(value):
                 i.e. "st2 run foopack.fooaction arrayparam=51"
             Normally, json.loads would throw an exception, and the split method
             would be used. However, since this is an int, not only would
             splitting not work, but json.loads actually treats this as valid JSON,
             but as an int, not an array. This causes a mismatch when the API is called.
             We want to try to handle this first, so it doesn't get accidentally
             sent to the API as an int, instead of an array of single-element int.
            try:
                 Force this to be a list containing the single int, then
                 cast the whole thing to string so json.loads can handle it
                value = str([int(value)])
            except ValueError:
                 Original value wasn't an int, so just let it continue
                pass
             At this point, the input is either a a "json.loads"-able construct
             like [1, 2, 3], or even [1], or it is a comma-separated list,
             Try both, in that order.
            try:
                result = json.loads(value)
            except ValueError:
                result = [v.strip() for v in value.split(',')]
            return result
        transformer = {
            'array': transform_array,
            'boolean': (lambda x: ast.literal_eval(x.capitalize())),
            'integer': int,
            'number': float,
            'object': transform_object,
            'string': str
        }
        def normalize(name, value):
             Users can also specify type for each array parameter inside an action metadata
             (items: type: int for example) and this information is available here so we could
             also leverage that to cast each array item to the correct type.
            if name in runner.runner_parameters:
                param = runner.runner_parameters[name]
                if 'type' in param and param['type'] in transformer:
                    return transformer[param['type']](value)
            if name in action.parameters:
                param = action.parameters[name]
                if 'type' in param and param['type'] in transformer:
                    return transformer[param['type']](value)
            return value
        result = {}
        if not args.parameters:
            return result
        for idx in range(len(args.parameters)):
            arg = args.parameters[idx]
            if '=' in arg:
                k, v = arg.split('=', 1)
                 Attribute for files are prefixed with "@"
                if k.startswith('@'):
                    k = k[1:]
                    is_file = True
                else:
                    is_file = False
                try:
                    if is_file:
                         Files are handled a bit differently since we ship the content
                         over the wire
                        file_path = os.path.normpath(pjoin(os.getcwd(), v))
                        file_name = os.path.basename(file_path)
                        content = read_file(file_path=file_path)
                        if action_ref_or_id == 'core.http':
                             Special case for http runner
                            result['_file_name'] = file_name
                            result['file_content'] = content
                        else:
                            result[k] = content
                    else:
                        result[k] = normalize(k, v)
                except Exception as e:
                     TODO: Move transformers in a separate module and handle
                     exceptions there
                    if 'malformed string' in str(e):
                        message = ('Invalid value for boolean parameter. '
                                   'Valid values are: true, false')
                        raise ValueError(message)
                    else:
                        raise e
            else:
                result['cmd'] = ' '.join(args.parameters[idx:])
                break
         Special case for http runner
        if 'file_content' in result:
            if 'method' not in result:
                 Default to POST if a method is not provided
                result['method'] = 'POST'
            if 'file_name' not in result:
                 File name not provided, use default file name
                result['file_name'] = result['_file_name']
            del result['_file_name']
        if args.inherit_env:
            result['env'] = self._get_inherited_env_vars()
        return result
def _get_action_parameters_from_args ( self , action , runner , args ) : action_ref_or_id = action . ref def read_file ( file_path ) : if not os . path . exists ( file_path ) : raise ValueError ( 'File "%s" doesn\'t exist' % ( file_path ) ) if not os . path . isfile ( file_path ) : raise ValueError ( '"%s" is not a file' % ( file_path ) ) with open ( file_path , 'rb' ) as fp : content = fp . read ( ) return content def transform_object ( value ) : if value . startswith ( '{' ) : result = value = json . loads ( value ) else : pairs = value . split ( ',' ) result = { } for pair in pairs : split = pair . split ( '=' , 1 ) if len ( split ) != 2 : continue key , value = split result [ key ] = value return result def transform_array ( value ) : try : value = str ( [ int ( value ) ] ) except ValueError : pass try : result = json . loads ( value ) except ValueError : result = [ v . strip ( ) for v in value . split ( ',' ) ] return result transformer = { 'array' : transform_array , 'boolean' : ( lambda x : ast . literal_eval ( x . capitalize ( ) ) ) , 'integer' : int , 'number' : float , 'object' : transform_object , 'string' : str } def normalize ( name , value ) : """ The desired type is contained in the action meta-data, so we can look that up
                and call the desired "caster" function listed in the "transformer" dict
            """ if name in runner . runner_parameters : param = runner . runner_parameters [ name ] if 'type' in param and param [ 'type' ] in transformer : return transformer [ param [ 'type' ] ] ( value ) if name in action . parameters : param = action . parameters [ name ] if 'type' in param and param [ 'type' ] in transformer : return transformer [ param [ 'type' ] ] ( value ) return value result = { } if not args . parameters : return result for idx in range ( len ( args . parameters ) ) : arg = args . parameters [ idx ] if '=' in arg : k , v = arg . split ( '=' , 1 ) if k . startswith ( '@' ) : k = k [ 1 : ] is_file = True else : is_file = False try : if is_file : file_path = os . path . normpath ( pjoin ( os . getcwd ( ) , v ) ) file_name = os . path . basename ( file_path ) content = read_file ( file_path = file_path ) if action_ref_or_id == 'core.http' : result [ '_file_name' ] = file_name result [ 'file_content' ] = content else : result [ k ] = content else : result [ k ] = normalize ( k , v ) except Exception as e : if 'malformed string' in str ( e ) : message = ( 'Invalid value for boolean parameter. ' 'Valid values are: true, false' ) raise ValueError ( message ) else : raise e else : result [ 'cmd' ] = ' ' . join ( args . parameters [ idx : ] ) break if 'file_content' in result : if 'method' not in result : result [ 'method' ] = 'POST' if 'file_name' not in result : result [ 'file_name' ] = result [ '_file_name' ] del result [ '_file_name' ] if args . inherit_env : result [ 'env' ] = self . _get_inherited_env_vars ( ) return result
Build a dictionary with parameters which will be passed to the action by
parsing parameters passed to the CLI.
Build a dictionary with parameters which will be passed to the action by parsing parameters passed to the CLI .
"""
        Build a dictionary with parameters which will be passed to the action by
        parsing parameters passed to the CLI.

        :param args: CLI argument.
        :type args: ``object``

        :rtype: ``dict``
        """ # Also support simple key1=val1,key2=val2 syntax # Assume it's JSON # Sometimes an array parameter only has a single element: # #     i.e. "st2 run foopack.fooaction arrayparam=51" # # Normally, json.loads would throw an exception, and the split method # would be used. However, since this is an int, not only would # splitting not work, but json.loads actually treats this as valid JSON, # but as an int, not an array. This causes a mismatch when the API is called. # # We want to try to handle this first, so it doesn't get accidentally # sent to the API as an int, instead of an array of single-element int. # Force this to be a list containing the single int, then # cast the whole thing to string so json.loads can handle it # Original value wasn't an int, so just let it continue # At this point, the input is either a a "json.loads"-able construct # like [1, 2, 3], or even [1], or it is a comma-separated list, # Try both, in that order. """ The desired type is contained in the action meta-data, so we can look that up
                and call the desired "caster" function listed in the "transformer" dict
            """ # Users can also specify type for each array parameter inside an action metadata # (items: type: int for example) and this information is available here so we could # also leverage that to cast each array item to the correct type. # Attribute for files are prefixed with "@" # Files are handled a bit differently since we ship the content # over the wire # Special case for http runner # TODO: Move transformers in a separate module and handle # exceptions there # Special case for http runner # Default to POST if a method is not provided # File name not provided, use default file name
None
``dict``
self
action
runner
args
None