1#!/usr/bin/env python
2
3r"""
4This module provides many valuable functions such as my_parm_file.
5"""
6
7# sys and os are needed to get the program dir path and program name.
8import sys
9import os
10import ConfigParser
11import StringIO
12import re
13
14import gen_print as gp
15import gen_cmd as gc
16
17
18robot_env = 1
19try:
20    from robot.libraries.BuiltIn import BuiltIn
21except ImportError:
22    robot_env = 0
23
24
25###############################################################################
26def add_trailing_slash(dir_path):
27
28    r"""
29    Add a trailing slash to the directory path if it doesn't already have one
30    and return it.
31
32    Description of arguments:
33    dir_path                        A directory path.
34    """
35
36    return os.path.normpath(dir_path) + os.path.sep
37
38###############################################################################
39
40
41###############################################################################
42def which(file_path):
43
44    r"""
45    Find the full path of an executable file and return it.
46
47    The PATH environment variable dictates the results of this function.
48
49    Description of arguments:
50    file_path                       The relative file path (e.g. "my_file" or
51                                    "lib/my_file").
52    """
53
54    shell_rc, out_buf = gc.cmd_fnc_u("which " + file_path, quiet=1,
55                                     print_output=0, show_err=0)
56    if shell_rc != 0:
57        error_message = "Failed to find complete path for file \"" +\
58                        file_path + "\".\n"
59        error_message += gp.sprint_var(shell_rc, 1)
60        error_message += out_buf
61        if robot_env:
62            BuiltIn().fail(gp.sprint_error(error_message))
63        else:
64            gp.print_error_report(error_message)
65            return False
66
67    file_path = out_buf.rstrip("\n")
68
69    return file_path
70
71###############################################################################
72
73
74###############################################################################
75def dft(value, default):
76
77    r"""
78    Return default if value is None.  Otherwise, return value.
79
80    This is really just shorthand as shown below.
81
82    dft(value, default)
83
84    vs
85
86    default if value is None else value
87
88    Description of arguments:
89    value                           The value to be returned.
90    default                         The default value to return if value is
91                                    None.
92    """
93
94    return default if value is None else value
95
96###############################################################################
97
98
99###############################################################################
100def get_mod_global(var_name,
101                   default=None,
102                   mod_name="__main__"):
103
104    r"""
105    Get module global variable value and return it.
106
107    If we are running in a robot environment, the behavior will default to
108    calling get_variable_value.
109
110    Description of arguments:
111    var_name                        The name of the variable whose value is
112                                    sought.
113    default                         The value to return if the global does not
114                                    exist.
115    mod_name                        The name of the module containing the
116                                    global variable.
117    """
118
119    if robot_env:
120        return BuiltIn().get_variable_value("${" + var_name + "}", default)
121
122    try:
123        module = sys.modules[mod_name]
124    except KeyError:
125        gp.print_error_report("Programmer error - The mod_name passed to" +
126                              " this function is invalid:\n" +
127                              gp.sprint_var(mod_name))
128        raise ValueError('Programmer error.')
129
130    if default is None:
131        return getattr(module, var_name)
132    else:
133        return getattr(module, var_name, default)
134
135###############################################################################
136
137
138###############################################################################
139def global_default(var_value,
140                   default=0):
141
142    r"""
143    If var_value is not None, return it.  Otherwise, return the global
144    variable of the same name, if it exists.  If not, return default.
145
146    This is meant for use by functions needing help assigning dynamic default
147    values to their parms.  Example:
148
149    def func1(parm1=None):
150
151        parm1 = global_default(parm1, 0)
152
153    Description of arguments:
154    var_value                       The value being evaluated.
155    default                         The value to be returned if var_value is
156                                    None AND the global variable of the same
157                                    name does not exist.
158    """
159
160    var_name = gp.get_arg_name(0, 1, stack_frame_ix=2)
161
162    return dft(var_value, get_mod_global(var_name, 0))
163
164###############################################################################
165
166
167###############################################################################
168def set_mod_global(var_value,
169                   mod_name="__main__",
170                   var_name=None):
171
172    r"""
173    Set a global variable for a given module.
174
175    Description of arguments:
176    var_value                       The value to set in the variable.
177    mod_name                        The name of the module whose variable is
178                                    to be set.
179    var_name                        The name of the variable to set.  This
180                                    defaults to the name of the variable used
181                                    for var_value when calling this function.
182    """
183
184    try:
185        module = sys.modules[mod_name]
186    except KeyError:
187        gp.print_error_report("Programmer error - The mod_name passed to" +
188                              " this function is invalid:\n" +
189                              gp.sprint_var(mod_name))
190        raise ValueError('Programmer error.')
191
192    if var_name is None:
193        var_name = gp.get_arg_name(None, 1, 2)
194
195    setattr(module, var_name, var_value)
196
197###############################################################################
198
199
200###############################################################################
201def my_parm_file(prop_file_path):
202
203    r"""
204    Read a properties file, put the keys/values into a dictionary and return
205    the dictionary.
206
207    The properties file must have the following format:
208    var_name<= or :>var_value
209    Comment lines (those beginning with a "#") and blank lines are allowed and
210    will be ignored.  Leading and trailing single or double quotes will be
211    stripped from the value.  E.g.
212    var1="This one"
213    Quotes are stripped so the resulting value for var1 is:
214    This one
215
216    Description of arguments:
217    prop_file_path                  The caller should pass the path to the
218                                    properties file.
219    """
220
221    # ConfigParser expects at least one section header in the file (or you
222    # get ConfigParser.MissingSectionHeaderError).  Properties files don't
223    # need those so I'll write a dummy section header.
224
225    string_file = StringIO.StringIO()
226    # Write the dummy section header to the string file.
227    string_file.write('[dummysection]\n')
228    # Write the entire contents of the properties file to the string file.
229    string_file.write(open(prop_file_path).read())
230    # Rewind the string file.
231    string_file.seek(0, os.SEEK_SET)
232
233    # Create the ConfigParser object.
234    config_parser = ConfigParser.ConfigParser()
235    # Make the property names case-sensitive.
236    config_parser.optionxform = str
237    # Read the properties from the string file.
238    config_parser.readfp(string_file)
239    # Return the properties as a dictionary.
240    return dict(config_parser.items('dummysection'))
241
242###############################################################################
243
244
245###############################################################################
246def file_to_list(file_path,
247                 newlines=0,
248                 comments=1,
249                 trim=0):
250
251    r"""
252    Return the contents of a file as a list.  Each element of the resulting
253    list is one line from the file.
254
255    Description of arguments:
256    file_path                       The path to the file (relative or
257                                    absolute).
258    newlines                        Include newlines from the file in the
259                                    results.
260    comments                        Include comment lines and blank lines in
261                                    the results.  Comment lines are any that
262                                    begin with 0 or more spaces followed by
263                                    the pound sign ("#").
264    trim                            Trim white space from the beginning and
265                                    end of each line.
266    """
267
268    lines = []
269    file = open(file_path)
270    for line in file:
271        if not comments:
272            if re.match(r"[ ]*#|^$", line):
273                continue
274        if not newlines:
275            line = line.rstrip("\n")
276        if trim:
277            line = line.strip()
278        lines.append(line)
279
280    return lines
281
282###############################################################################
283
284
285###############################################################################
286def return_path_list():
287
288    r"""
289    This function will split the PATH environment variable into a PATH_LIST
290    and return it.  Each element in the list will be normalized and have a
291    trailing slash added.
292    """
293
294    PATH_LIST = os.environ['PATH'].split(":")
295    PATH_LIST = [os.path.normpath(path) + os.sep for path in PATH_LIST]
296
297    return PATH_LIST
298
299###############################################################################
300
301
302###############################################################################
303def quote_bash_parm(parm):
304
305    r"""
306    Return the bash command line parm with single quotes if they are needed.
307
308    Description of arguments:
309    parm                            The string to be quoted.
310    """
311
312    # If any of these characters are found in the parm string, then the
313    # string should be quoted.  This list is by no means complete and should
314    # be expanded as needed by the developer of this function.
315    bash_special_chars = set(' $')
316
317    if any((char in bash_special_chars) for char in parm):
318        return "'" + parm + "'"
319
320    return parm
321
322###############################################################################
323