George Keishing | e7e9171 | 2021-09-03 11:28:44 -0500 | [diff] [blame] | 1 | #!/usr/bin/env python3 |
Steven Sombar | b6749a6 | 2017-10-06 08:34:23 -0500 | [diff] [blame] | 2 | |
| 3 | r""" |
| 4 | This module contains file functions such as file_diff. |
| 5 | """ |
| 6 | |
Steven Sombar | b6749a6 | 2017-10-06 08:34:23 -0500 | [diff] [blame] | 7 | import os |
| 8 | import re |
Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame^] | 9 | import time |
| 10 | |
Steven Sombar | b6749a6 | 2017-10-06 08:34:23 -0500 | [diff] [blame] | 11 | from gen_cmd import cmd_fnc_u |
Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame^] | 12 | |
Steven Sombar | b6749a6 | 2017-10-06 08:34:23 -0500 | [diff] [blame] | 13 | robot_env = 1 |
| 14 | try: |
George Keishing | e635ddc | 2022-12-08 07:38:02 -0600 | [diff] [blame] | 15 | from robot.libraries import DateTime |
Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame^] | 16 | from robot.libraries.BuiltIn import BuiltIn |
Steven Sombar | b6749a6 | 2017-10-06 08:34:23 -0500 | [diff] [blame] | 17 | except ImportError: |
| 18 | robot_env = 0 |
| 19 | |
| 20 | |
Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame^] | 21 | def file_diff(file1_path, file2_path, diff_file_path, skip_string): |
Steven Sombar | b6749a6 | 2017-10-06 08:34:23 -0500 | [diff] [blame] | 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 | |
Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame^] | 61 | if not os.path.exists(file1_path) or (not os.path.exists(file2_path)): |
Steven Sombar | b6749a6 | 2017-10-06 08:34:23 -0500 | [diff] [blame] | 62 | return INPUT_FILE_DOES_NOT_EXIST |
| 63 | try: |
Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame^] | 64 | with open(file1_path, "r") as file: |
Steven Sombar | b6749a6 | 2017-10-06 08:34:23 -0500 | [diff] [blame] | 65 | initial = file.readlines() |
Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame^] | 66 | with open(file2_path, "r") as file: |
Steven Sombar | b6749a6 | 2017-10-06 08:34:23 -0500 | [diff] [blame] | 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 | |
Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame^] | 81 | if initial == final: |
Steven Sombar | b6749a6 | 2017-10-06 08:34:23 -0500 | [diff] [blame] | 82 | try: |
Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame^] | 83 | file = open(diff_file_path, "w") |
Steven Sombar | b6749a6 | 2017-10-06 08:34:23 -0500 | [diff] [blame] | 84 | except IOError: |
| 85 | file.close() |
Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame^] | 86 | line_to_print = ( |
| 87 | "Specified skip (ignore) string = " + skip_string + "\n\n" |
| 88 | ) |
Steven Sombar | b6749a6 | 2017-10-06 08:34:23 -0500 | [diff] [blame] | 89 | file.write(line_to_print) |
Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame^] | 90 | line_to_print = ( |
| 91 | now |
| 92 | + " found no difference between file " |
| 93 | + file1_path |
| 94 | + " and " |
| 95 | + file2_path |
| 96 | + "\n" |
| 97 | ) |
Steven Sombar | b6749a6 | 2017-10-06 08:34:23 -0500 | [diff] [blame] | 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: |
Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame^] | 104 | file = open(diff_file_path, "w") |
Steven Sombar | b6749a6 | 2017-10-06 08:34:23 -0500 | [diff] [blame] | 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)) |
Patrick Williams | 20f3871 | 2022-12-08 06:18:26 -0600 | [diff] [blame^] | 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 | ) |
Steven Sombar | b6749a6 | 2017-10-06 08:34:23 -0500 | [diff] [blame] | 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: |
Joy Onyerikwu | d806cc0 | 2019-10-01 07:46:18 -0500 | [diff] [blame] | 128 | print("DIFF:\n", out_buf) |
Steven Sombar | b6749a6 | 2017-10-06 08:34:23 -0500 | [diff] [blame] | 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. |
Gunnar Mills | 096cd56 | 2018-03-26 10:19:12 -0500 | [diff] [blame] | 138 | return FILES_DO_NOT_MATCH |