1#!/usr/bin/env python
2
3r"""
4Define variable manipulation functions.
5"""
6
7import os
8import re
9
10try:
11    from robot.utils import DotDict
12except ImportError:
13    pass
14
15import collections
16
17import gen_print as gp
18import gen_misc as gm
19
20
21def create_var_dict(*args):
22
23    r"""
24    Create a dictionary whose keys/values are the arg names/arg values passed
25    to it and return it to the caller.
26
27    Note: The resulting dictionary will be ordered.
28
29    Description of argument(s):
30    *args  An unlimited number of arguments to be processed.
31
32    Example use:
33
34    first_name = 'Steve'
35    last_name = 'Smith'
36    var_dict = create_var_dict(first_name, last_name)
37
38    gp.print_var(var_dict)
39
40    The print-out of the resulting var dictionary is:
41    var_dict:
42      var_dict[first_name]:                           Steve
43      var_dict[last_name]:                            Smith
44    """
45
46    try:
47        result_dict = collections.OrderedDict()
48    except AttributeError:
49        result_dict = DotDict()
50
51    arg_num = 1
52    for arg in args:
53        arg_name = gp.get_arg_name(None, arg_num, stack_frame_ix=2)
54        result_dict[arg_name] = arg
55        arg_num += 1
56
57    return result_dict
58
59
60default_record_delim = ':'
61default_key_val_delim = '.'
62
63
64def join_dict(dict,
65              record_delim=default_record_delim,
66              key_val_delim=default_key_val_delim):
67
68    r"""
69    Join a dictionary's keys and values into a string and return the string.
70
71    Description of argument(s):
72    dict                            The dictionary whose keys and values are
73                                    to be joined.
74    record_delim                    The delimiter to be used to separate
75                                    dictionary pairs in the resulting string.
76    key_val_delim                   The delimiter to be used to separate keys
77                                    from values in the resulting string.
78
79    Example use:
80
81    gp.print_var(var_dict)
82    str1 = join_dict(var_dict)
83    gp.pvar(str1)
84
85    Program output.
86    var_dict:
87      var_dict[first_name]:                           Steve
88      var_dict[last_name]:                            Smith
89    str1:
90    first_name.Steve:last_name.Smith
91    """
92
93    format_str = '%s' + key_val_delim + '%s'
94    return record_delim.join([format_str % (key, value) for (key, value) in
95                             dict.items()])
96
97
98def split_to_dict(string,
99                  record_delim=default_record_delim,
100                  key_val_delim=default_key_val_delim):
101
102    r"""
103    Split a string into a dictionary and return it.
104
105    This function is the complement to join_dict.
106
107    Description of argument(s):
108    string                          The string to be split into a dictionary.
109                                    The string must have the proper delimiters
110                                    in it.  A string created by join_dict
111                                    would qualify.
112    record_delim                    The delimiter to be used to separate
113                                    dictionary pairs in the input string.
114    key_val_delim                   The delimiter to be used to separate
115                                    keys/values in the input string.
116
117    Example use:
118
119    gp.print_var(str1)
120    new_dict = split_to_dict(str1)
121    gp.print_var(new_dict)
122
123
124    Program output.
125    str1:
126    first_name.Steve:last_name.Smith
127    new_dict:
128      new_dict[first_name]:                           Steve
129      new_dict[last_name]:                            Smith
130    """
131
132    try:
133        result_dict = collections.OrderedDict()
134    except AttributeError:
135        result_dict = DotDict()
136
137    raw_keys_values = string.split(record_delim)
138    for key_value in raw_keys_values:
139        key_value_list = key_value.split(key_val_delim)
140        try:
141            result_dict[key_value_list[0]] = key_value_list[1]
142        except IndexError:
143            result_dict[key_value_list[0]] = ""
144
145    return result_dict
146
147
148def create_file_path(file_name_dict,
149                     dir_path="/tmp/",
150                     file_suffix=""):
151
152    r"""
153    Create a file path using the given parameters and return it.
154
155    Description of argument(s):
156    file_name_dict                  A dictionary with keys/values which are to
157                                    appear as part of the file name.
158    dir_path                        The dir_path that is to appear as part of
159                                    the file name.
160    file_suffix                     A suffix to be included as part of the
161                                    file name.
162    """
163
164    dir_path = gm.add_trailing_slash(dir_path)
165    return dir_path + join_dict(file_name_dict) + file_suffix
166
167
168def parse_file_path(file_path):
169
170    r"""
171    Parse a file path created by create_file_path and return the result as a
172    dictionary.
173
174    This function is the complement to create_file_path.
175
176    Description of argument(s):
177    file_path                       The file_path.
178
179    Example use:
180    gp.pvar(boot_results_file_path)
181    file_path_data = parse_file_path(boot_results_file_path)
182    gp.pvar(file_path_data)
183
184    Program output.
185
186    boot_results_file_path:
187    /tmp/pgm_name.obmc_boot_test:openbmc_nickname.beye6:master_pid.2039:boot_re
188    sults
189    file_path_data:
190      file_path_data[dir_path]:                       /tmp/
191      file_path_data[pgm_name]:                       obmc_boot_test
192      file_path_data[openbmc_nickname]:               beye6
193      file_path_data[master_pid]:                     2039
194      file_path_data[boot_results]:
195    """
196
197    try:
198        result_dict = collections.OrderedDict()
199    except AttributeError:
200        result_dict = DotDict()
201
202    dir_path = os.path.dirname(file_path) + os.sep
203    file_path = os.path.basename(file_path)
204
205    result_dict['dir_path'] = dir_path
206
207    result_dict.update(split_to_dict(file_path))
208
209    return result_dict
210
211
212def parse_key_value(string,
213                    delim=":",
214                    strip=" ",
215                    to_lower=1,
216                    underscores=1):
217
218    r"""
219    Parse a key/value string and return as a key/value tuple.
220
221    This function is useful for parsing a line of program output or data that
222    is in the following form:
223    <key or variable name><delimiter><value>
224
225    An example of a key/value string would be as follows:
226
227    Current Limit State: No Active Power Limit
228
229    In the example shown, the delimiter is ":".  The resulting key would be as
230    follows:
231    Current Limit State
232
233    Note: If one were to take the default values of to_lower=1 and
234    underscores=1, the resulting key would be as follows:
235    current_limit_state
236
237    The to_lower and underscores arguments are provided for those who wish to
238    have their key names have the look and feel of python variable names.
239
240    The resulting value for the example above would be as follows:
241    No Active Power Limit
242
243    Another example:
244    name=Mike
245
246    In this case, the delim would be "=", the key is "name" and the value is
247    "Mike".
248
249    Description of argument(s):
250    string                          The string to be parsed.
251    delim                           The delimiter which separates the key from
252                                    the value.
253    strip                           The characters (if any) to strip from the
254                                    beginning and end of both the key and the
255                                    value.
256    to_lower                        Change the key name to lower case.
257    underscores                     Change any blanks found in the key name to
258                                    underscores.
259    """
260
261    pair = string.split(delim)
262
263    key = pair[0].strip(strip)
264    if len(pair) == 0:
265        value = ""
266    else:
267        value = "".join(pair[1:]).strip(strip)
268
269    if to_lower:
270        key = key.lower()
271    if underscores:
272        key = re.sub(r" ", "_", key)
273
274    return key, value
275
276
277def key_value_list_to_dict(list,
278                           **args):
279
280    r"""
281    Convert a list containing key/value strings to a dictionary and return it.
282
283    See docstring of parse_key_value function for details on key/value strings.
284
285    Example usage:
286
287    For the following value of list:
288
289    list:
290      list[0]:          Current Limit State: No Active Power Limit
291      list[1]:          Exception actions:   Hard Power Off & Log Event to SEL
292      list[2]:          Power Limit:         0 Watts
293      list[3]:          Correction time:     0 milliseconds
294      list[4]:          Sampling period:     0 seconds
295
296    And the following call in python:
297
298    power_limit = key_value_outbuf_to_dict(list)
299
300    The resulting power_limit directory would look like this:
301
302    power_limit:
303      [current_limit_state]:        No Active Power Limit
304      [exception_actions]:          Hard Power Off & Log Event to SEL
305      [power_limit]:                0 Watts
306      [correction_time]:            0 milliseconds
307      [sampling_period]:            0 seconds
308
309    Description of argument(s):
310    list                            A list of key/value strings.  (See
311                                    docstring of parse_key_value function for
312                                    details).
313    **args                          Arguments to be interpreted by
314                                    parse_key_value.  (See docstring of
315                                    parse_key_value function for details).
316    """
317
318    try:
319        result_dict = collections.OrderedDict()
320    except AttributeError:
321        result_dict = DotDict()
322
323    for entry in list:
324        key, value = parse_key_value(entry, **args)
325        result_dict[key] = value
326
327    return result_dict
328
329
330def key_value_outbuf_to_dict(out_buf,
331                             **args):
332
333    r"""
334    Convert a buffer with a key/value string on each line to a dictionary and
335    return it.
336
337    Each line in the out_buf should end with a \n.
338
339    See docstring of parse_key_value function for details on key/value strings.
340
341    Example usage:
342
343    For the following value of out_buf:
344
345    Current Limit State: No Active Power Limit
346    Exception actions:   Hard Power Off & Log Event to SEL
347    Power Limit:         0 Watts
348    Correction time:     0 milliseconds
349    Sampling period:     0 seconds
350
351    And the following call in python:
352
353    power_limit = key_value_outbuf_to_dict(out_buf)
354
355    The resulting power_limit directory would look like this:
356
357    power_limit:
358      [current_limit_state]:        No Active Power Limit
359      [exception_actions]:          Hard Power Off & Log Event to SEL
360      [power_limit]:                0 Watts
361      [correction_time]:            0 milliseconds
362      [sampling_period]:            0 seconds
363
364    Description of argument(s):
365    out_buf                         A buffer with a key/value string on each
366                                    line. (See docstring of parse_key_value
367                                    function for details).
368    **args                          Arguments to be interpreted by
369                                    parse_key_value.  (See docstring of
370                                    parse_key_value function for details).
371    """
372
373    # Create key_var_list and remove null entries.
374    key_var_list = list(filter(None, out_buf.split("\n")))
375    return key_value_list_to_dict(key_var_list, **args)
376