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