def args_to_objects(args): r""" Run source_to_object() on each element in args and return the result. Description of argument(s): args A type of dictionary, list, set, tuple or simple object whose elements are to be converted via a call to source_to_object(). """ type_of_dict = gp.is_dict(args) if type_of_dict: if type_of_dict == gp.dict_type(): return {k: source_to_object(v) for (k, v) in args.items()} elif type_of_dict == gp.ordered_dict_type(): return collections.OrderedDict((k, v) for (k, v) in args.items()) elif type_of_dict == gp.dot_dict_type(): return DotDict((k, v) for (k, v) in args.items()) elif type_of_dict == gp.normalized_dict_type(): return NormalizedDict((k, v) for (k, v) in args.items()) # Assume args is list, tuple or set. if type(args) in (list, set): return [source_to_object(arg) for arg in args] elif type(args) is tuple: return tuple([source_to_object(arg) for arg in args]) return source_to_object(args)
def nested_get(key_name, structure): r""" Return a list of all values from the nested structure that have the given key name. Example: Given a dictionary structure named "personnel" with the following contents: personnel: [manager]: [last_name]: Doe [first_name]: John [accountant]: [last_name]: Smith [first_name]: Will The following code... last_names = nested_get('last_name', personnel) print_var(last_names) Would result in the following data returned: last_names: last_names[0]: Doe last_names[1]: Smith Description of argument(s): key_name The key name (e.g. 'last_name'). structure Any nested combination of lists or dictionaries (e.g. a dictionary, a dictionary of dictionaries, a list of dictionaries, etc.). This function will locate the given key at any level within the structure and include its value in the returned list. """ result = [] if type(structure) is list: for entry in structure: result += nested_get(key_name, entry) return result elif gp.is_dict(structure): for key, value in structure.items(): result += nested_get(key_name, value) if key == key_name: result.append(value) return result
def create_command_string(command, *pos_parms, **options): r""" Create and return a bash command string consisting of the given arguments formatted as text. The default formatting of options is as follows: <single dash><option name><space delim><option value> Example: -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 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. 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: command_string = create_command_string('cd', '~') 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: command_string = create_command_string('cd', '\'~\'') Result: cd '~' command_string = create_command_string('grep', '\'^[^ ]*=\'', '/tmp/myfile', i=None, m='1', arg_dashes='--', color='always') 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. command_string = create_command_string('grep', quote_bash_parm('^[^ ]*='), '/tmp/myfile', i=None, m='1', arg_dashes='--', color='always') 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. command_string = create_command_string('my_pgm', '/tmp/myfile', i=None, m='1', arg_dashes='--', password='******') 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='******') Result: my_pgm -i -m 1 --password="******" /tmp/myfile command_string = create_command_string('ipmitool', 'power status', I='lanplus', C='3', U='root', P='0penBmc', H='wsbmc010') 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. Example: kwargs = collections.OrderedDict([('pass', 0), ('fail', 0)]) command_string = create_command_string('my program', 'pos_parm1', kwargs) Result: 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: def create_ipmi_ext_command_string(command, **kwargs): return create_command_string('ipmitool', command, _stack_frame_ix_=2, **kwargs) Example call of wrapper function: 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). """ arg_dashes = "-" delim = default_arg_delim(arg_dashes) command_string = command 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). 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. 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. options = re_order_kwargs(stack_frame_ix, **options) for key, value in options.items(): # Check for special values in options and process them. if key == "arg_dashes": arg_dashes = str(value) delim = default_arg_delim(arg_dashes) continue if key == "arg_delim": delim = str(value) continue # Format the options elements into the command string. command_string += " " + arg_dashes + key if value is not None: command_string += delim if re.match(r'^(["].*["]|[\'].*[\'])$', str(value)): # Already quoted. 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. command_string = ' '.join([command_string] + list(filter(None, pos_parms))) return command_string