1#!/usr/bin/env python
2
3r"""
4This module contains file functions such as file_diff.
5"""
6
7import time
8import os
9import re
10from gen_cmd import cmd_fnc_u
11robot_env = 1
12try:
13    from robot.libraries.BuiltIn import BuiltIn
14    from robot.libraries import DateTime
15except ImportError:
16    robot_env = 0
17
18
19##########################################################################
20def file_diff(file1_path,
21              file2_path,
22              diff_file_path,
23              skip_string):
24    r"""
25    Compare the contents of two text files.  The comparison uses the Unix
26    'diff' command.  Differences can be selectively ignored by use of
27    the skip_string parameter.  The output of diff command is written
28    to a user-specified file and is also written (logged) to the console.
29
30    Description of arguments:
31    file1_path       File containing text data.
32    file2_path       Text file to compare to file1.
33    diff_file_path   Text file which will contain the diff output.
34    skip_string      To allow for differences which may expected or immaterial,
35                     skip_string parameter is a word or a string of comma
36                     separated words which specify what should be ignored.
37                     For example, "size,speed".  Any line containing the word
38                     size or the word speed will be ignored when the diff is
39                     performed.  This parameter is optional.
40
41    Returns:
42    0 if both files contain the same information or they differ only in
43      items specified by the skip_string.
44    2 if FILES_DO_NOT_MATCH.
45    3 if INPUT_FILE_DOES_NOT_EXIST.
46    4 if IO_EXCEPTION_READING_FILE.
47    5 if IO_EXCEPTION_WRITING_FILE.
48    6 if INPUT_FILE_MALFORMED
49    """
50
51    FILES_MATCH = 0
52    FILES_DO_NOT_MATCH = 2
53    INPUT_FILE_DOES_NOT_EXIST = 3
54    IO_EXCEPTION_READING_FILE = 4
55    IO_EXCEPTION_WRITING_FILE = 5
56    INPUT_FILE_MALFORMED = 6
57
58    # The minimum size in bytes a file must be.
59    min_file_byte_size = 1
60
61    now = time.strftime("%Y-%m-%d %H:%M:%S")
62
63    if (not os.path.exists(file1_path) or (not os.path.exists(file2_path))):
64        return INPUT_FILE_DOES_NOT_EXIST
65    try:
66        with open(file1_path, 'r') as file:
67            initial = file.readlines()
68        with open(file2_path, 'r') as file:
69            final = file.readlines()
70    except IOError:
71        file.close()
72        return IO_EXCEPTION_READING_FILE
73    except ValueError:
74        file.close()
75        return INPUT_FILE_MALFORMED
76    else:
77        file.close()
78
79    # Must have more than a trivial number of bytes.
80    if len(initial) < min_file_byte_size:
81        return INPUT_FILE_MALFORMED
82
83    if (initial == final):
84        try:
85            file = open(diff_file_path, 'w')
86        except IOError:
87            file.close()
88        line_to_print = "Specified skip (ignore) string = " + \
89            skip_string + "\n\n"
90        file.write(line_to_print)
91        line_to_print = now + " found no difference between file " + \
92            file1_path + " and " + \
93            file2_path + "\n"
94        file.write(line_to_print)
95        file.close()
96        return FILES_MATCH
97
98    # Find the differences and write difference report to diff_file_path file
99    try:
100        file = open(diff_file_path, 'w')
101    except IOError:
102        file.close()
103        return IO_EXCEPTION_WRITING_FILE
104
105    # Form a UNIX diff command and its parameters as a string.  For example,
106    # if skip_string="size,capacity",  command = 'diff  -I "size"
107    # -I "capacity"  file1_path file2_path'.
108    skip_list = filter(None, re.split(r"[ ]*,[ ]*", skip_string))
109    ignore_string = ' '.join([("-I " + '"' + x + '"') for x in skip_list])
110    command = ' '.join(filter(None, ["diff", ignore_string, file1_path,
111                       file2_path]))
112
113    line_to_print = now + "   " + command + "\n"
114    file.write(line_to_print)
115
116    # Run the command and get the differences
117    rc, out_buf = cmd_fnc_u(command, quiet=0, print_output=0, show_err=0)
118
119    # Write the differences to the specified diff_file and console.
120    if robot_env == 1:
121        BuiltIn().log_to_console("DIFF:\n" + out_buf)
122    else:
123        print "DIFF:\n", out_buf
124
125    file.write(out_buf)
126    file.close()
127
128    if rc == 0:
129        # Any differences found were on the skip_string.
130        return FILES_MATCH
131    else:
132        # We have at least one difference not in the skip_string.
133        return FILES_DO_NOT_MATCH
134###############################################################################
135