shell_cmd support for error_regexes arg
Also changed comments and doc strings to wrap at 110 chars vs 79.
Change-Id: I5eaa432af2cef5605e8fb6bd6de7f25e6010e1d0
Signed-off-by: Michael Walsh <micwalsh@us.ibm.com>
diff --git a/lib/gen_cmd.py b/lib/gen_cmd.py
index b202396..ab672a7 100644
--- a/lib/gen_cmd.py
+++ b/lib/gen_cmd.py
@@ -24,8 +24,8 @@
from robot.libraries.BuiltIn import BuiltIn
-# cmd_fnc and cmd_fnc_u should now be considered deprecated. shell_cmd and
-# t_shell_cmd should be used instead.
+# cmd_fnc and cmd_fnc_u should now be considered deprecated. shell_cmd and t_shell_cmd should be used
+# instead.
def cmd_fnc(cmd_buf,
quiet=None,
test_mode=None,
@@ -35,32 +35,23 @@
return_stderr=0,
ignore_err=1):
r"""
- Run the given command in a shell and return the shell return code and the
- output.
+ Run the given command in a shell and return the shell return code and the output.
Description of arguments:
cmd_buf The command string to be run in a shell.
- quiet Indicates whether this function should run
- the print_issuing() function which prints
- "Issuing: <cmd string>" to stdout.
- test_mode If test_mode is set, this function will
- not actually run the command. If
- print_output is set, it will print
- "(test_mode) Issuing: <cmd string>" to
+ quiet Indicates whether this function should run the print_issuing() function
+ which prints "Issuing: <cmd string>" to stdout.
+ test_mode If test_mode is set, this function will not actually run the command. If
+ print_output is set, it will print "(test_mode) Issuing: <cmd string>" to
stdout.
- debug If debug is set, this function will print
- extra debug info.
- print_output If this is set, this function will print
- the stdout/stderr generated by the shell
- command.
- show_err If show_err is set, this function will
- print a standardized error report if the
- shell command returns non-zero.
- return_stderr If return_stderr is set, this function
- will process the stdout and stderr streams
- from the shell command separately. It
- will also return stderr in addition to the
- return code and the stdout.
+ debug If debug is set, this function will print extra debug info.
+ print_output If this is set, this function will print the stdout/stderr generated by
+ the shell command.
+ show_err If show_err is set, this function will print a standardized error report
+ if the shell command returns non-zero.
+ return_stderr If return_stderr is set, this function will process the stdout and stderr
+ streams from the shell command separately. It will also return stderr in
+ addition to the return code and the stdout.
"""
# Determine default values.
@@ -159,38 +150,30 @@
def parse_command_string(command_string):
r"""
- Parse a bash command-line command string and return the result as a
- dictionary of parms.
+ Parse a bash command-line command string and return the result as a dictionary of parms.
- This can be useful for answering questions like "What did the user specify
- as the value for parm x in the command string?".
+ This can be useful for answering questions like "What did the user specify as the value for parm x in the
+ command string?".
- This function expects the command string to follow the following posix
- conventions:
+ This function expects the command string to follow the following posix conventions:
- Short parameters:
-<parm name><space><arg value>
- Long parameters:
--<parm name>=<arg value>
- The first item in the string will be considered to be the command. All
- values not conforming to the specifications above will be considered
- positional parms. If there are multiple parms with the same name, they
- will be put into a list (see illustration below where "-v" is specified
- multiple times).
+ The first item in the string will be considered to be the command. All values not conforming to the
+ specifications above will be considered positional parms. If there are multiple parms with the same
+ name, they will be put into a list (see illustration below where "-v" is specified multiple times).
Description of argument(s):
- command_string The complete command string including all
- parameters and arguments.
+ command_string The complete command string including all parameters and arguments.
Sample input:
- robot_cmd_buf: robot -v
- OPENBMC_HOST:dummy1 -v keyword_string:'Set Auto Reboot no' -v
- lib_file_path:/home/user1/git/openbmc-test-automation/lib/utils.robot -v
- quiet:0 -v test_mode:0 -v debug:0
- --outputdir='/home/user1/status/children/'
- --output=dummy1.Auto_reboot.170802.124544.output.xml
- --log=dummy1.Auto_reboot.170802.124544.log.html
+ robot_cmd_buf: robot -v OPENBMC_HOST:dummy1 -v keyword_string:'Set
+ Auto Reboot no' -v lib_file_path:/home/user1/git/openbmc-test-automation/lib/utils.robot -v quiet:0 -v
+ test_mode:0 -v debug:0 --outputdir='/home/user1/status/children/'
+ --output=dummy1.Auto_reboot.170802.124544.output.xml --log=dummy1.Auto_reboot.170802.124544.log.html
--report=dummy1.Auto_reboot.170802.124544.report.html
/home/user1/git/openbmc-test-automation/extended/run_keyword.robot
@@ -200,28 +183,22 @@
robot_cmd_buf_dict[command]: robot
robot_cmd_buf_dict[v]:
robot_cmd_buf_dict[v][0]: OPENBMC_HOST:dummy1
- robot_cmd_buf_dict[v][1]: keyword_string:Set Auto
- Reboot no
+ robot_cmd_buf_dict[v][1]: keyword_string:Set Auto Reboot no
robot_cmd_buf_dict[v][2]:
lib_file_path:/home/user1/git/openbmc-test-automation/lib/utils.robot
robot_cmd_buf_dict[v][3]: quiet:0
robot_cmd_buf_dict[v][4]: test_mode:0
robot_cmd_buf_dict[v][5]: debug:0
- robot_cmd_buf_dict[outputdir]:
- /home/user1/status/children/
- robot_cmd_buf_dict[output]:
- dummy1.Auto_reboot.170802.124544.output.xml
- robot_cmd_buf_dict[log]:
- dummy1.Auto_reboot.170802.124544.log.html
- robot_cmd_buf_dict[report]:
- dummy1.Auto_reboot.170802.124544.report.html
+ robot_cmd_buf_dict[outputdir]: /home/user1/status/children/
+ robot_cmd_buf_dict[output]: dummy1.Auto_reboot.170802.124544.output.xml
+ robot_cmd_buf_dict[log]: dummy1.Auto_reboot.170802.124544.log.html
+ robot_cmd_buf_dict[report]: dummy1.Auto_reboot.170802.124544.report.html
robot_cmd_buf_dict[positional]:
/home/user1/git/openbmc-test-automation/extended/run_keyword.robot
"""
- # We want the parms in the string broken down the way bash would do it,
- # so we'll call upon bash to do that by creating a simple inline bash
- # function.
+ # We want the parms in the string broken down the way bash would do it, so we'll call upon bash to do
+ # that by creating a simple inline bash function.
bash_func_def = "function parse { for parm in \"${@}\" ; do" +\
" echo $parm ; done ; }"
@@ -293,76 +270,58 @@
valid_rcs=[0],
ignore_err=None,
return_stderr=0,
- fork=0):
+ fork=0,
+ error_regexes=None):
r"""
- Run the given command string in a shell and return a tuple consisting of
- the shell return code and the output.
+ Run the given command string in a shell and return a tuple consisting of the shell return code and the
+ output.
Description of argument(s):
- command_string The command string to be run in a shell
- (e.g. "ls /tmp").
- quiet If set to 0, this function will print
- "Issuing: <cmd string>" to stdout. When
- the quiet argument is set to None, this
- function will assign a default value by
- searching upward in the stack for the
- quiet variable value. If no such value is
- found, quiet is set to 0.
- print_output If this is set, this function will print
- the stdout/stderr generated by the shell
- command to stdout.
- show_err If show_err is set, this function will
- print a standardized error report if the
- shell command fails (i.e. if the shell
- command returns a shell_rc that is not in
- valid_rcs). Note: Error text is only
- printed if ALL attempts to run the
- command_string fail. In other words, if
- the command execution is ultimately
- successful, initial failures are hidden.
- test_mode If test_mode is set, this function will
- not actually run the command. If
- print_output is also set, this function
- will print "(test_mode) Issuing: <cmd
- string>" to stdout. A caller should call
- shell_cmd directly if they wish to have
- the command string run unconditionally.
- They should call the t_shell_cmd wrapper
- (defined below) if they wish to run the
- command string only if the prevailing
- test_mode variable is set to 0.
- time_out A time-out value expressed in seconds. If
- the command string has not finished
- executing within <time_out> seconds, it
- will be halted and counted as an error.
- max_attempts The max number of attempts that should be
- made to run the command string.
- retry_sleep_time The number of seconds to sleep between
- attempts.
- valid_rcs A list of integers indicating which
- shell_rc values are not to be considered
- errors.
- ignore_err Ignore error means that a failure
- encountered by running the command string
- will not be raised as a python exception.
- When the ignore_err argument is set to
- None, this function will assign a default
- value by searching upward in the stack for
- the ignore_err variable value. If no such
- value is found, ignore_err is set to 1.
- return_stderr If return_stderr is set, this function
- will process the stdout and stderr streams
- from the shell command separately. In
- such a case, the tuple returned by this
- function will consist of three values
- rather than just two: rc, stdout, stderr.
- fork Run the command string asynchronously
- (i.e. don't wait for status of the child
- process and don't try to get
- stdout/stderr) and return the Popen object
- created by the subprocess.popen()
- function. See the kill_cmd function for
- details on how to process the popen object.
+ command_string The command string to be run in a shell (e.g. "ls /tmp").
+ quiet If set to 0, this function will print "Issuing: <cmd string>" to stdout.
+ When the quiet argument is set to None, this function will assign a
+ default value by searching upward in the stack for the quiet variable
+ value. If no such value is found, quiet is set to 0.
+ print_output If this is set, this function will print the stdout/stderr generated by
+ the shell command to stdout.
+ show_err If show_err is set, this function will print a standardized error report
+ if the shell command fails (i.e. if the shell command returns a shell_rc
+ that is not in valid_rcs). Note: Error text is only printed if ALL
+ attempts to run the command_string fail. In other words, if the command
+ execution is ultimately successful, initial failures are hidden.
+ test_mode If test_mode is set, this function will not actually run the command. If
+ print_output is also set, this function will print "(test_mode) Issuing:
+ <cmd string>" to stdout. A caller should call shell_cmd directly if they
+ wish to have the command string run unconditionally. They should call
+ the t_shell_cmd wrapper (defined below) if they wish to run the command
+ string only if the prevailing test_mode variable is set to 0.
+ time_out A time-out value expressed in seconds. If the command string has not
+ finished executing within <time_out> seconds, it will be halted and
+ counted as an error.
+ max_attempts The max number of attempts that should be made to run the command string.
+ retry_sleep_time The number of seconds to sleep between attempts.
+ valid_rcs A list of integers indicating which shell_rc values are not to be
+ considered errors.
+ ignore_err Ignore error means that a failure encountered by running the command
+ string will not be raised as a python exception. When the ignore_err
+ argument is set to None, this function will assign a default value by
+ searching upward in the stack for the ignore_err variable value. If no
+ such value is found, ignore_err is set to 1.
+ return_stderr If return_stderr is set, this function will process the stdout and stderr
+ streams from the shell command separately. In such a case, the tuple
+ returned by this function will consist of three values rather than just
+ two: rc, stdout, stderr.
+ fork Run the command string asynchronously (i.e. don't wait for status of the
+ child process and don't try to get stdout/stderr) and return the Popen
+ object created by the subprocess.popen() function. See the kill_cmd
+ function for details on how to process the popen object.
+ error_regexes A list of regular expressions to be used to identify errors in the
+ command output. If there is a match for any of these regular
+ expressions, the command will be considered a failure and the shell_rc
+ will be set to -1. For example, if error_regexes = ['ERROR:'] and the
+ command output contains 'ERROR: Unrecognized option', it will be counted
+ as an error even if the command returned 0. This is useful when running
+ commands that do not always return non-zero on error.
"""
err_msg = gv.valid_value(command_string)
@@ -386,11 +345,9 @@
stderr = subprocess.PIPE if return_stderr else subprocess.STDOUT
- # Write all output to func_out_history_buf rather than directly to
- # stdout. This allows us to decide what to print after all attempts to
- # run the command string have been made. func_out_history_buf will
- # contain the complete history from the current invocation of this
- # function.
+ # Write all output to func_out_history_buf rather than directly to stdout. This allows us to decide
+ # what to print after all attempts to run the command string have been made. func_out_history_buf will
+ # contain the complete history from the current invocation of this function.
global command_timed_out
command_timed_out = False
func_out_history_buf = ""
@@ -419,9 +376,8 @@
signal.signal(signal.SIGALRM, original_sigalrm_handler)
signal.alarm(0)
- # Output from this loop iteration is written to func_out_buf for
- # later processing. This can include stdout, stderr and our own error
- # messages.
+ # Output from this loop iteration is written to func_out_buf for later processing. This can include
+ # stdout, stderr and our own error messages.
func_out_buf = ""
if print_output:
if return_stderr:
@@ -429,12 +385,18 @@
func_out_buf += stdout_buf
shell_rc = sub_proc.returncode
if shell_rc in valid_rcs:
- break
+ # Check output for text indicating there is an error.
+ if error_regexes and re.match('|'.join(error_regexes), stdout_buf):
+ shell_rc = -1
+ else:
+ break
err_msg = "The prior shell command failed.\n"
err_msg += gp.sprint_var(attempt_num)
err_msg += gp.sprint_vars(command_string, command_timed_out, time_out)
err_msg += gp.sprint_varx("child_pid", sub_proc.pid)
err_msg += gp.sprint_vars(shell_rc, valid_rcs, fmt=gp.hexa())
+ if error_regexes:
+ err_msg += gp.sprint_vars(error_regexes)
if not print_output:
if return_stderr:
err_msg += "stderr_buf:\n" + stderr_buf
@@ -454,12 +416,10 @@
if show_err:
gp.gp_print(func_out_history_buf, stream='stderr')
else:
- # There is no error information to show so just print output from
- # last loop iteration.
+ # There is no error information to show so just print output from last loop iteration.
gp.gp_print(func_out_buf)
if not ignore_err:
- # If the caller has already asked to show error info, avoid
- # repeating that in the failure message.
+ # If the caller has already asked to show error info, avoid repeating that in the failure message.
err_msg = "The prior shell command failed.\n" if show_err \
else err_msg
if robot_env:
@@ -473,8 +433,8 @@
def t_shell_cmd(command_string, **kwargs):
r"""
- Search upward in the the call stack to obtain the test_mode argument, add
- it to kwargs and then call shell_cmd and return the result.
+ Search upward in the the call stack to obtain the test_mode argument, add it to kwargs and then call
+ shell_cmd and return the result.
See shell_cmd prolog for details on all arguments.
"""
@@ -493,11 +453,10 @@
def kill_cmd(popen, sig=signal.SIGTERM):
r"""
- Kill the subprocess represented by the Popen object and return a tuple
- consisting of the shell return code and the output.
+ Kill the subprocess represented by the Popen object and return a tuple consisting of the shell return
+ code and the output.
- This function is meant to be used as the follow-up for a call to
- shell_cmd(..., fork=1).
+ This function is meant to be used as the follow-up for a call to shell_cmd(..., fork=1).
Example:
popen = shell_cmd("some_pgm.py", fork=1)
@@ -505,8 +464,7 @@
shell_rc, output = kill_cmd(popen)
Description of argument(s):
- popen A Popen object returned by the
- subprocess.Popen() command.
+ popen A Popen object returned by the subprocess.Popen() command.
sig The signal to be sent to the child process.
"""
@@ -519,11 +477,10 @@
def re_order_kwargs(stack_frame_ix, **kwargs):
r"""
- Re-order the kwargs to match the order in which they were specified on a
- function invocation and return as an ordered dictionary.
+ Re-order the kwargs to match the order in which they were specified on a function invocation and return
+ as an ordered dictionary.
- Note that this re_order_kwargs function should not be necessary in python
- versions 3.6 and beyond.
+ Note that this re_order_kwargs function should not be necessary in python versions 3.6 and beyond.
Example:
@@ -537,8 +494,7 @@
kwargs = re_order_kwargs(first_arg_num=2, stack_frame_ix=3, **kwargs)
- The kwargs dictionary before calling re_order_kwargs (where order is not
- guaranteed):
+ The kwargs dictionary before calling re_order_kwargs (where order is not guaranteed):
kwargs:
kwargs[arg3]: three
@@ -552,16 +508,13 @@
kwargs[arg2]: two
kwargs[arg3]: three
- Note that the re-ordered kwargs match the order specified on the call to
- func1.
+ Note that the re-ordered kwargs match the order specified on the call to func1.
Description of argument(s):
- stack_frame_ix The stack frame of the function whose
- kwargs values must be re-ordered. 0 is
- the stack frame of re_order_kwargs, 1 is
- the stack from of its caller and so on.
- kwargs The keyword argument dictionary which is
- to be re-ordered.
+ stack_frame_ix The stack frame of the function whose kwargs values must be re-ordered.
+ 0 is the stack frame of re_order_kwargs, 1 is the stack from of its
+ caller and so on.
+ kwargs The keyword argument dictionary which is to be re-ordered.
"""
new_kwargs = collections.OrderedDict()
@@ -587,12 +540,11 @@
r"""
Return the default argument delimiter value for the given arg_dashes value.
- Note: this function is useful for functions that manipulate bash command
- line arguments (e.g. --parm=1 or -parm 1).
+ Note: this function is useful for functions that manipulate bash command line arguments (e.g. --parm=1 or
+ -parm 1).
Description of argument(s):
- arg_dashes The argument dashes specifier (usually,
- "-" or "--").
+ arg_dashes The argument dashes specifier (usually, "-" or "--").
"""
if arg_dashes == "--":
@@ -603,8 +555,7 @@
def create_command_string(command, *pos_parms, **options):
r"""
- Create and return a bash command string consisting of the given arguments
- formatted as text.
+ Create and return a bash command string consisting of the given arguments formatted as text.
The default formatting of options is as follows:
@@ -614,24 +565,20 @@
-parm value
- The caller can change the kind of dashes/delimiters used by specifying
- "arg_dashes" and/or "arg_delims" as options. These options are processed
- specially by the create_command_string function and do NOT get inserted
- into the resulting command string. All options following the
- arg_dashes/arg_delims options will then use the specified values for
- dashes/delims. In the special case of arg_dashes equal to "--", the
+ The caller can change the kind of dashes/delimiters used by specifying "arg_dashes" and/or "arg_delims"
+ as options. These options are processed specially by the create_command_string function and do NOT get
+ inserted into the resulting command string. All options following the arg_dashes/arg_delims options will
+ then use the specified values for dashes/delims. In the special case of arg_dashes equal to "--", the
arg_delim will automatically be changed to "=". See examples below.
Quoting rules:
- The create_command_string function will single quote option values as
- needed to prevent bash expansion. If the caller wishes to defeat this
- action, they may single or double quote the option value themselves. See
- examples below.
+ The create_command_string function will single quote option values as needed to prevent bash expansion.
+ If the caller wishes to defeat this action, they may single or double quote the option value themselves.
+ See examples below.
- pos_parms are NOT automatically quoted. The caller is advised to either
- explicitly add quotes or to use the quote_bash_parm functions to quote any
- pos_parms.
+ pos_parms are NOT automatically quoted. The caller is advised to either explicitly add quotes or to use
+ the quote_bash_parm functions to quote any pos_parms.
Examples:
@@ -640,9 +587,8 @@
Result:
cd ~
- Note that the pos_parm ("~") does NOT get quoted, as per the
- aforementioned rules. If quotes are desired, they may be added explicitly
- by the caller:
+ Note that the pos_parm ("~") does NOT get quoted, as per the aforementioned rules. If quotes are
+ desired, they may be added explicitly by the caller:
command_string = create_command_string('cd', '\'~\'')
@@ -655,11 +601,10 @@
Result:
grep -i -m 1 --color=always '^[^ ]*=' /tmp/myfile
- In the preceding example, note the use of None to cause the "i" parm to be
- treated as a flag (i.e. no argument value is generated). Also, note the
- use of arg_dashes to change the type of dashes used on all subsequent
- options. The following example is equivalent to the prior. Note that
- quote_bash_parm is used instead of including the quotes explicitly.
+ In the preceding example, note the use of None to cause the "i" parm to be treated as a flag (i.e. no
+ argument value is generated). Also, note the use of arg_dashes to change the type of dashes used on all
+ subsequent options. The following example is equivalent to the prior. Note that quote_bash_parm is used
+ instead of including the quotes explicitly.
command_string = create_command_string('grep', quote_bash_parm('^[^ ]*='),
'/tmp/myfile', i=None, m='1', arg_dashes='--', color='always')
@@ -667,14 +612,14 @@
Result:
grep -i -m 1 --color=always '^[^ ]*=' /tmp/myfile
- In the following example, note the automatic quoting of the password
- option, as per the aforementioned rules.
+ In the following example, note the automatic quoting of the password option, as per the aforementioned
+ rules.
command_string = create_command_string('my_pgm', '/tmp/myfile', i=None,
m='1', arg_dashes='--', password='${my_pw}')
- However, let's say that the caller wishes to have bash expand the password
- value. To achieve this, the caller can use double quotes:
+ However, let's say that the caller wishes to have bash expand the password value. To achieve this, the
+ caller can use double quotes:
command_string = create_command_string('my_pgm', '/tmp/myfile', i=None,
m='1', arg_dashes='--', password='"${my_pw}"')
@@ -688,12 +633,11 @@
Result:
ipmitool -I lanplus -C 3 -U root -P 0penBmc -H wsbmc010 power status
- By default create_command_string will take measures to preserve the order
- of the callers options. In some cases, this effort may fail (as when
- calling directly from a robot program). In this case, the caller can
- accept the responsibility of keeping an ordered list of options by calling
- this function with the last positional parm as some kind of dictionary
- (preferably an OrderedDict) and avoiding the use of any actual option args.
+ By default create_command_string will take measures to preserve the order of the callers options. In
+ some cases, this effort may fail (as when calling directly from a robot program). In this case, the
+ caller can accept the responsibility of keeping an ordered list of options by calling this function with
+ the last positional parm as some kind of dictionary (preferably an OrderedDict) and avoiding the use of
+ any actual option args.
Example:
kwargs = collections.OrderedDict([('pass', 0), ('fail', 0)])
@@ -703,10 +647,9 @@
my program -pass 0 -fail 0 pos_parm1
- Note to programmers who wish to write a wrapper to this function: If the
- python version is less than 3.6, to get the options to be processed
- correctly, the wrapper function must include a _stack_frame_ix_ keyword
- argument to allow this function to properly re-order options:
+ Note to programmers who wish to write a wrapper to this function: If the python version is less than
+ 3.6, to get the options to be processed correctly, the wrapper function must include a _stack_frame_ix_
+ keyword argument to allow this function to properly re-order options:
def create_ipmi_ext_command_string(command, **kwargs):
@@ -715,21 +658,15 @@
Example call of wrapper function:
- command_string = create_ipmi_ext_command_string('power status',
- I='lanplus')
+ command_string = create_ipmi_ext_command_string('power status', I='lanplus')
Description of argument(s):
- command The command (e.g. "cat", "sort",
- "ipmitool", etc.).
- pos_parms The positional parms for the command (e.g.
- PATTERN, FILENAME, etc.). These will be
- placed at the end of the resulting command
- string.
- options The command options (e.g. "-m 1",
- "--max-count=NUM", etc.). Note that if
- the value of any option is None, then it
- will be understood to be a flag (for which
- no value is required).
+ command The command (e.g. "cat", "sort", "ipmitool", etc.).
+ pos_parms The positional parms for the command (e.g. PATTERN, FILENAME, etc.).
+ These will be placed at the end of the resulting command string.
+ options The command options (e.g. "-m 1", "--max-count=NUM", etc.). Note that if
+ the value of any option is None, then it will be understood to be a flag
+ (for which no value is required).
"""
arg_dashes = "-"
@@ -740,18 +677,16 @@
if len(pos_parms) > 0 and gp.is_dict(pos_parms[-1]):
# Convert pos_parms from tuple to list.
pos_parms = list(pos_parms)
- # Re-assign options to be the last pos_parm value (which is a
- # dictionary).
+ # Re-assign options to be the last pos_parm value (which is a dictionary).
options = pos_parms[-1]
# Now delete the last pos_parm.
del pos_parms[-1]
else:
- # Either get stack_frame_ix from the caller via options or set it to
- # the default value.
+ # Either get stack_frame_ix from the caller via options or set it to the default value.
stack_frame_ix = options.pop('_stack_frame_ix_', 1)
if gm.python_version < gm.ordered_dict_version:
- # Re-establish the original options order as specified on the
- # original line of code. This function depends on correct order.
+ # Re-establish the original options order as specified on the original line of code. This
+ # function depends on correct order.
options = re_order_kwargs(stack_frame_ix, **options)
for key, value in options.items():
# Check for special values in options and process them.
@@ -771,8 +706,8 @@
command_string += str(value)
else:
command_string += gm.quote_bash_parm(str(value))
- # Finally, append the pos_parms to the end of the command_string. Use
- # filter to eliminate blank pos parms.
+ # Finally, append the pos_parms to the end of the command_string. Use filter to eliminate blank pos
+ # parms.
command_string = ' '.join([command_string] + list(filter(None, pos_parms)))
return command_string