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