DataComparerLibrary 0.843__tar.gz → 0.845__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (23) hide show
  1. {datacomparerlibrary-0.843/src/DataComparerLibrary.egg-info → datacomparerlibrary-0.845}/PKG-INFO +60 -6
  2. datacomparerlibrary-0.843/PKG-INFO → datacomparerlibrary-0.845/README.rst +47 -23
  3. {datacomparerlibrary-0.843 → datacomparerlibrary-0.845}/setup.py +3 -1
  4. datacomparerlibrary-0.845/src/DataComparerLibrary/arraycomparer.py +206 -0
  5. datacomparerlibrary-0.845/src/DataComparerLibrary/datacomparer.py +135 -0
  6. datacomparerlibrary-0.845/src/DataComparerLibrary/datetimehandler.py +100 -0
  7. datacomparerlibrary-0.845/src/DataComparerLibrary/report.py +44 -0
  8. datacomparerlibrary-0.845/src/DataComparerLibrary/version.py +3 -0
  9. datacomparerlibrary-0.843/README.rst → datacomparerlibrary-0.845/src/DataComparerLibrary.egg-info/PKG-INFO +77 -3
  10. {datacomparerlibrary-0.843 → datacomparerlibrary-0.845}/src/DataComparerLibrary.egg-info/SOURCES.txt +3 -0
  11. datacomparerlibrary-0.843/src/DataComparerLibrary/datacomparer.py +0 -487
  12. datacomparerlibrary-0.843/src/DataComparerLibrary/version.py +0 -3
  13. {datacomparerlibrary-0.843 → datacomparerlibrary-0.845}/LICENSE.txt +0 -0
  14. {datacomparerlibrary-0.843 → datacomparerlibrary-0.845}/pyproject.toml +0 -0
  15. {datacomparerlibrary-0.843 → datacomparerlibrary-0.845}/setup.cfg +0 -0
  16. {datacomparerlibrary-0.843 → datacomparerlibrary-0.845}/src/DataComparerLibrary/__init__.py +0 -0
  17. {datacomparerlibrary-0.843 → datacomparerlibrary-0.845}/src/DataComparerLibrary/datasorter.py +0 -0
  18. {datacomparerlibrary-0.843 → datacomparerlibrary-0.845}/src/DataComparerLibrary/delimitertranslator.py +0 -0
  19. {datacomparerlibrary-0.843 → datacomparerlibrary-0.845}/src/DataComparerLibrary/fileconverter.py +0 -0
  20. {datacomparerlibrary-0.843 → datacomparerlibrary-0.845}/src/DataComparerLibrary/tools.py +0 -0
  21. {datacomparerlibrary-0.843 → datacomparerlibrary-0.845}/src/DataComparerLibrary.egg-info/dependency_links.txt +0 -0
  22. {datacomparerlibrary-0.843 → datacomparerlibrary-0.845}/src/DataComparerLibrary.egg-info/top_level.txt +0 -0
  23. {datacomparerlibrary-0.843 → datacomparerlibrary-0.845}/test/test1.py +0 -0
@@ -1,7 +1,7 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: DataComparerLibrary
3
- Version: 0.843
4
- Summary: For comparing csv-files or 2d-array with csv-file.
3
+ Version: 0.845
4
+ Summary: For comparing csv-files, 2d-array with a csv-file or 2d-arrays. For comparing text-files, text variable with a text-file or text variables. Including a sorting module.
5
5
  Home-page:
6
6
  Author: René Philip Zuijderduijn
7
7
  Author-email: datacomparerlibrary@outlook.com
@@ -15,8 +15,18 @@ Classifier: Programming Language :: Python :: 3.8
15
15
  Classifier: Programming Language :: Python :: 3.9
16
16
  Classifier: Programming Language :: Python :: 3.10
17
17
  Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
18
20
  Description-Content-Type: text/x-rst
19
21
  License-File: LICENSE.txt
22
+ Dynamic: author
23
+ Dynamic: author-email
24
+ Dynamic: classifier
25
+ Dynamic: description
26
+ Dynamic: description-content-type
27
+ Dynamic: keywords
28
+ Dynamic: license
29
+ Dynamic: summary
20
30
 
21
31
  ===================
22
32
  DataComparerLibrary
@@ -106,8 +116,12 @@ The DataComparerLibrary can be used for:
106
116
  quotechar.
107
117
 
108
118
 
119
+ Comparing Data
120
+ --------------
121
+
122
+
109
123
  Examples of using the DataComparerLibrary for comparing data in Python
110
- ----------------------------------------------------------------------
124
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
111
125
 
112
126
  Below there are some examples how to call the methods of the DataComparerLibrary in Python::
113
127
 
@@ -122,7 +136,7 @@ Below there are some examples how to call the methods of the DataComparerLibrary
122
136
 
123
137
 
124
138
  Examples of using the DataComparerLibrary keywords for comparing data in Robot Framework
125
- ----------------------------------------------------------------------------------------
139
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
126
140
 
127
141
  Below there are some examples how to call the keywords of the DataComparerLibrary in Robot Framework::
128
142
 
@@ -146,7 +160,7 @@ Below there are some examples how to call the keywords of the DataComparerLibrar
146
160
 
147
161
 
148
162
  Examples comparing Actual Data with Expected Data
149
- -------------------------------------------------
163
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
150
164
 
151
165
  Below there is an example of actual and expected data with some different cases.
152
166
 
@@ -185,6 +199,46 @@ Based on current datetime = 2023-09-06 19:04:00 (example):
185
199
  +--------------+----------+--------------+---------------------------------+---------+-------------+
186
200
 
187
201
 
202
+ Comparing Text
203
+ --------------
204
+
205
+ Examples of using the DataComparerLibrary for comparing text in Python
206
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
207
+
208
+ Below there are some examples how to call the methods of the DataComparerLibrary in Python::
209
+
210
+
211
+ a = DataComparer
212
+ a.compare_text_files(self, actual_file, expected_file)
213
+ a.compare_text_variable_with_text_file(self, actual_text_input, expected_file)
214
+ a.compare_text_file_with_text_variable(self, actual_file, expected_text_input)
215
+ a.compare_text_variables(self, actual_text_input, expected_text_input)
216
+
217
+
218
+ Examples of using the DataComparerLibrary keywords for comparing text in Robot Framework
219
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
220
+
221
+ Below there are some examples how to call the keywords of the DataComparerLibrary in Robot Framework::
222
+
223
+
224
+ *** Settings ***
225
+ Library DataComparerLibrary
226
+
227
+ *** Test Cases ***
228
+ Testcase_DataComparer
229
+ Examples
230
+
231
+ *** Keywords ***
232
+ Examples
233
+ Run Keyword And Continue On Failure DataComparerLibrary.Compare Text Files C:\\Users\\actual.txt C:\\Users\\expected.txt
234
+ DataComparerLibrary.Compare Text Files C:\\Users\\actual.txt C:\\Users\\expected.txt
235
+ DataComparerLibrary.Compare Text Files C:\\Users\\actual.txt C:\\Users\\expected.txt
236
+ DataComparerLibrary.Compare Text Files C:\\Users\\actual.txt C:\\Users\\expected.txt
237
+ DataComparerLibrary.Compare Text Variable With File ${actual_text_input} C:\\Users\\expected.txt
238
+ DataComparerLibrary.Compare Text File With Text Variable C:\\Users\\actual.txt ${expected_text_input}
239
+ DataComparerLibrary.Compare Text Variables ${actual_text_input} ${expected_text_input}
240
+
241
+
188
242
 
189
243
  DataSorter
190
244
  ==========
@@ -1,23 +1,3 @@
1
- Metadata-Version: 2.1
2
- Name: DataComparerLibrary
3
- Version: 0.843
4
- Summary: For comparing csv-files or 2d-array with csv-file.
5
- Home-page:
6
- Author: René Philip Zuijderduijn
7
- Author-email: datacomparerlibrary@outlook.com
8
- License: Apache
9
- Keywords: robotframework testing test-automation datacompare
10
- Classifier: License :: OSI Approved :: Apache Software License
11
- Classifier: Operating System :: Microsoft :: Windows :: Windows 10
12
- Classifier: Operating System :: Microsoft :: Windows :: Windows 11
13
- Classifier: Programming Language :: Python :: 3.7
14
- Classifier: Programming Language :: Python :: 3.8
15
- Classifier: Programming Language :: Python :: 3.9
16
- Classifier: Programming Language :: Python :: 3.10
17
- Classifier: Programming Language :: Python :: 3.11
18
- Description-Content-Type: text/x-rst
19
- License-File: LICENSE.txt
20
-
21
1
  ===================
22
2
  DataComparerLibrary
23
3
  ===================
@@ -106,8 +86,12 @@ The DataComparerLibrary can be used for:
106
86
  quotechar.
107
87
 
108
88
 
89
+ Comparing Data
90
+ --------------
91
+
92
+
109
93
  Examples of using the DataComparerLibrary for comparing data in Python
110
- ----------------------------------------------------------------------
94
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
111
95
 
112
96
  Below there are some examples how to call the methods of the DataComparerLibrary in Python::
113
97
 
@@ -122,7 +106,7 @@ Below there are some examples how to call the methods of the DataComparerLibrary
122
106
 
123
107
 
124
108
  Examples of using the DataComparerLibrary keywords for comparing data in Robot Framework
125
- ----------------------------------------------------------------------------------------
109
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
126
110
 
127
111
  Below there are some examples how to call the keywords of the DataComparerLibrary in Robot Framework::
128
112
 
@@ -146,7 +130,7 @@ Below there are some examples how to call the keywords of the DataComparerLibrar
146
130
 
147
131
 
148
132
  Examples comparing Actual Data with Expected Data
149
- -------------------------------------------------
133
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
150
134
 
151
135
  Below there is an example of actual and expected data with some different cases.
152
136
 
@@ -185,6 +169,46 @@ Based on current datetime = 2023-09-06 19:04:00 (example):
185
169
  +--------------+----------+--------------+---------------------------------+---------+-------------+
186
170
 
187
171
 
172
+ Comparing Text
173
+ --------------
174
+
175
+ Examples of using the DataComparerLibrary for comparing text in Python
176
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
177
+
178
+ Below there are some examples how to call the methods of the DataComparerLibrary in Python::
179
+
180
+
181
+ a = DataComparer
182
+ a.compare_text_files(self, actual_file, expected_file)
183
+ a.compare_text_variable_with_text_file(self, actual_text_input, expected_file)
184
+ a.compare_text_file_with_text_variable(self, actual_file, expected_text_input)
185
+ a.compare_text_variables(self, actual_text_input, expected_text_input)
186
+
187
+
188
+ Examples of using the DataComparerLibrary keywords for comparing text in Robot Framework
189
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
190
+
191
+ Below there are some examples how to call the keywords of the DataComparerLibrary in Robot Framework::
192
+
193
+
194
+ *** Settings ***
195
+ Library DataComparerLibrary
196
+
197
+ *** Test Cases ***
198
+ Testcase_DataComparer
199
+ Examples
200
+
201
+ *** Keywords ***
202
+ Examples
203
+ Run Keyword And Continue On Failure DataComparerLibrary.Compare Text Files C:\\Users\\actual.txt C:\\Users\\expected.txt
204
+ DataComparerLibrary.Compare Text Files C:\\Users\\actual.txt C:\\Users\\expected.txt
205
+ DataComparerLibrary.Compare Text Files C:\\Users\\actual.txt C:\\Users\\expected.txt
206
+ DataComparerLibrary.Compare Text Files C:\\Users\\actual.txt C:\\Users\\expected.txt
207
+ DataComparerLibrary.Compare Text Variable With File ${actual_text_input} C:\\Users\\expected.txt
208
+ DataComparerLibrary.Compare Text File With Text Variable C:\\Users\\actual.txt ${expected_text_input}
209
+ DataComparerLibrary.Compare Text Variables ${actual_text_input} ${expected_text_input}
210
+
211
+
188
212
 
189
213
  DataSorter
190
214
  ==========
@@ -22,7 +22,7 @@ with open(join(this_directory, 'src', 'DataComparerLibrary', 'version.py')) as f
22
22
  def main():
23
23
  setup(name='DataComparerLibrary',
24
24
  version=VERSION,
25
- description="For comparing csv-files or 2d-array with csv-file.",
25
+ description="For comparing csv-files, 2d-array with a csv-file or 2d-arrays. For comparing text-files, text variable with a text-file or text variables. Including a sorting module.",
26
26
  long_description=README,
27
27
  long_description_content_type="text/x-rst",
28
28
  url="",
@@ -38,6 +38,8 @@ def main():
38
38
  "Programming Language :: Python :: 3.9",
39
39
  "Programming Language :: Python :: 3.10",
40
40
  "Programming Language :: Python :: 3.11",
41
+ "Programming Language :: Python :: 3.12",
42
+ "Programming Language :: Python :: 3.13",
41
43
  ],
42
44
  keywords='robotframework testing test-automation datacompare',
43
45
  package_dir={'': 'src'},
@@ -0,0 +1,206 @@
1
+ import fnmatch
2
+ import re
3
+
4
+ from DataComparerLibrary.datetimehandler import DatetimeHandler
5
+ from DataComparerLibrary.report import Report
6
+ from DataComparerLibrary.tools import Tools
7
+
8
+ class ArrayComparer:
9
+ def compare_data(self, actual_data, expected_data_including_templates, template_literals_dict):
10
+ difference_found = False
11
+ #
12
+ if actual_data and type(actual_data[0]) is not list: # only a single row
13
+ actual_data = [actual_data,] # add row to tuple of lenght 1
14
+ #
15
+ if expected_data_including_templates and type(expected_data_including_templates[0]) is not list: # only a single row
16
+ expected_data_including_templates = [expected_data_including_templates,] # add row to tuple of lenght 1
17
+
18
+ number_of_rows_actual_data = len(actual_data)
19
+ number_of_rows_expected_data = len(expected_data_including_templates)
20
+
21
+ number_of_rows = max(number_of_rows_actual_data, number_of_rows_expected_data)
22
+
23
+ Report.show_2d_array(self, "Actual data", actual_data, 20)
24
+ Report.show_2d_array(self, "Expected data", expected_data_including_templates, 20)
25
+
26
+ Report().show_header_differences_actual_and_expected_data()
27
+
28
+ for row_nr in range(number_of_rows):
29
+ if row_nr >= number_of_rows_actual_data:
30
+ difference_found = True
31
+ if len(expected_data_including_templates[row_nr]) == 0:
32
+ Report.show_differences_comparation_result(self, row_nr, 0, "", "", "Row actual data is not PRESENT. Row expected data is EMPTY.")
33
+ else:
34
+ Report.show_differences_comparation_result(self, row_nr, 0, "", expected_data_including_templates[row_nr][0], "Row actual data is not PRESENT.")
35
+ continue
36
+ #
37
+ if row_nr >= number_of_rows_expected_data:
38
+ difference_found = True
39
+ if len(actual_data[row_nr]) == 0:
40
+ Report.show_differences_comparation_result(self, row_nr, 0, "", "", "Row actual data is EMPTY. Row expected data is not PRESENT.")
41
+ else:
42
+ Report.show_differences_comparation_result(self, row_nr, 0, actual_data[row_nr][0], "", "Row expected data is not PRESENT.")
43
+ continue
44
+ #
45
+ number_of_columns_actual_data = len(actual_data[row_nr])
46
+ number_of_columns_expected_data = len(expected_data_including_templates[row_nr])
47
+
48
+ number_of_columns = max(number_of_columns_actual_data, number_of_columns_expected_data)
49
+
50
+ for column_nr in range(number_of_columns):
51
+ expected_data_including_date_template = None
52
+ expected_data_with_wildcard = None
53
+ skip_exception_rule_used = False
54
+ #
55
+ if column_nr >= number_of_columns_actual_data:
56
+ difference_found = True
57
+ Report.show_differences_comparation_result(self, row_nr, column_nr, "", expected_data_including_templates[row_nr][column_nr], "Column actual data is not PRESENT.")
58
+ continue
59
+ #
60
+ if column_nr >= number_of_columns_expected_data:
61
+ difference_found = True
62
+ Report.show_differences_comparation_result(self, row_nr, column_nr, actual_data[row_nr][column_nr], "", "Column expected data is not PRESENT.")
63
+ continue
64
+ #
65
+ if actual_data[row_nr][column_nr] != expected_data_including_templates[row_nr][column_nr]:
66
+ # Replace literal templates with fixed external strings.
67
+ if template_literals_dict:
68
+ for i in range(0, len(template_literals_dict)):
69
+ # key = list(template_literals_dict.keys())[i]
70
+ # value = list(template_literals_dict.values())[i]
71
+ # print("key: ", key)
72
+ # print("value: ", value)
73
+ expected_data_including_templates[row_nr][column_nr] = expected_data_including_templates[row_nr][column_nr].replace(list(template_literals_dict.keys())[i], list(template_literals_dict.values())[i])
74
+ # print("actual_data[row_nr][column_nr]: \n", actual_data[row_nr][column_nr])
75
+ # print("expected_data_including_templates[row_nr][column_nr]: \n", expected_data_including_templates[row_nr][column_nr])
76
+
77
+
78
+ # Verify if difference is a matter of string versus integer representation.
79
+ if str(actual_data[row_nr][column_nr]) == str(expected_data_including_templates[row_nr][column_nr]):
80
+ if isinstance(actual_data[row_nr][column_nr], int) and isinstance(expected_data_including_templates[row_nr][column_nr], str):
81
+ difference_found = True
82
+ Report.show_differences_comparation_result(self, row_nr, column_nr, actual_data[row_nr][column_nr], expected_data_including_templates[row_nr][column_nr], "There is a difference between actual and expected data. Actual data is an integer while expected data is a string.")
83
+ elif isinstance(actual_data[row_nr][column_nr], str) and isinstance(expected_data_including_templates[row_nr][column_nr], int):
84
+ difference_found = True
85
+ Report.show_differences_comparation_result(self, row_nr, column_nr, actual_data[row_nr][column_nr], expected_data_including_templates[row_nr][column_nr], "There is a difference between actual and expected data. Actual data is a string while expected data is an integer.")
86
+ continue
87
+ #
88
+ # If data in actual and expected field doesn't match, check if a template has been used in expected data.
89
+ match expected_data_including_templates[row_nr][column_nr].upper():
90
+ case "{PRESENT}":
91
+ if not actual_data[row_nr][column_nr]:
92
+ # No data is present in actual data field.
93
+ difference_found = True
94
+ Report.show_differences_comparation_result(self, row_nr, column_nr, actual_data[row_nr][column_nr], expected_data_including_templates[row_nr][column_nr], "Actual data field is not PRESENT")
95
+ #
96
+ case "{EMPTY}":
97
+ if actual_data[row_nr][column_nr]:
98
+ # Actual data field is not empty.
99
+ difference_found = True
100
+ Report.show_differences_comparation_result(self, row_nr, column_nr, actual_data[row_nr][column_nr], expected_data_including_templates[row_nr][column_nr], "Actual data field is not EMPTY")
101
+ #
102
+ case "{INTEGER}":
103
+ if isinstance(actual_data[row_nr][column_nr], int):
104
+ # A real integer.
105
+ continue
106
+ #
107
+ # Verify if string is integer.
108
+ if not actual_data[row_nr][column_nr].isdigit():
109
+ # Not positive integer field.
110
+ difference_found = True
111
+ Report.show_differences_comparation_result(self, row_nr, column_nr, actual_data[row_nr][column_nr], expected_data_including_templates[row_nr][column_nr], "Actual data field is not INTEGER.")
112
+ #
113
+ case "{SKIP}":
114
+ pass
115
+ case _:
116
+ if "{SKIP}" in expected_data_including_templates[row_nr][column_nr].upper() or "{DATETIME_FORMAT():YYYYMMDDHHMMSSFF6}" in expected_data_including_templates[row_nr][column_nr].upper():
117
+ if expected_data_including_templates[row_nr][column_nr].upper() == "{SKIP}":
118
+ # Complete actual data field will be skipped for verification.
119
+ pass
120
+ else:
121
+ # Part(s) of the actual data field will be skipped for verification.
122
+ # Replace {SKIP}, ignoring cases, by wildcard *.
123
+ # compiled = re.compile(re.escape("{SKIP}"), re.IGNORECASE)
124
+ # expected_data_with_wildcard = compiled.sub("*", expected_data_including_templates[row_nr][column_nr])
125
+ compiled = re.compile(re.escape("{SKIP}"), re.IGNORECASE)
126
+ compiled2 = re.compile(re.escape("{DATETIME_FORMAT():YYYYMMDDHHMMSSFF6}"), re.IGNORECASE)
127
+ expected_data_with_wildcard = compiled2.sub("*", compiled.sub("*", expected_data_including_templates[row_nr][column_nr]))
128
+ #
129
+ if fnmatch.fnmatch(actual_data[row_nr][column_nr], expected_data_with_wildcard):
130
+ skip_exception_rule_used = True
131
+ continue
132
+ #
133
+ if expected_data_with_wildcard is None:
134
+ # Wildcards not used.
135
+ expected_data_including_date_template = expected_data_including_templates[row_nr][column_nr]
136
+ else:
137
+ expected_data_including_date_template = expected_data_with_wildcard
138
+ #
139
+ if "{NOW()" in expected_data_including_templates[row_nr][column_nr].upper():
140
+ matches = ["{NOW():", "{NOW()+", "{NOW()-"]
141
+ if all([x not in expected_data_including_templates[row_nr][column_nr].upper() for x in matches]):
142
+ difference_found = True
143
+ Report.show_differences_comparation_result(self, row_nr, column_nr, actual_data[row_nr][column_nr], expected_data_including_templates[row_nr][column_nr], "NOW() has been found in expected data field, but format is incorrect.")
144
+ continue
145
+ #
146
+ expected_data = DatetimeHandler.replace_date_template_in_expected_data(self, expected_data_including_date_template)
147
+ #
148
+ if expected_data == -1:
149
+ difference_found = True
150
+ Report.show_differences_comparation_result(self, row_nr, column_nr, actual_data[row_nr][column_nr], expected_data_including_templates[row_nr][column_nr], "NOW() has been found in expected data field, but format is incorrect.")
151
+ else:
152
+ if not fnmatch.fnmatch(actual_data[row_nr][column_nr], expected_data):
153
+ # No match despite using of wildcard(s).
154
+ difference_found = True
155
+ Report.show_differences_comparation_result(self, row_nr, column_nr, actual_data[row_nr][column_nr], expected_data_including_templates[row_nr][column_nr], "Date template format displayed. See also next message line.")
156
+ Report.show_differences_comparation_result(self, row_nr, column_nr, actual_data[row_nr][column_nr], expected_data, "There is a difference between actual and expected data.")
157
+ continue
158
+ #
159
+ elif "{NOT(" in expected_data_including_templates[row_nr][column_nr].upper():
160
+ try:
161
+ unwanted_expected_data = ArrayComparer.__get_unwanted_expected_data(self, expected_data_including_date_template)
162
+ #
163
+ if actual_data[row_nr][column_nr] == unwanted_expected_data:
164
+ # Unwanted match.
165
+ difference_found = True
166
+ Report.show_differences_comparation_result(self, row_nr, column_nr, actual_data[row_nr][column_nr], expected_data_including_templates[row_nr][column_nr], "NOT() template format displayed. See also next message line.")
167
+ Report.show_differences_comparation_result(self, row_nr, column_nr, actual_data[row_nr][column_nr], unwanted_expected_data, "Actual and expected data are equal. However actual data should NOT be equal to the expected data!!!")
168
+ except Exception as exception_message:
169
+ # print(f"An exception occurred: {exception_message}")
170
+ difference_found = True
171
+ Report.show_differences_comparation_result(self, row_nr, column_nr, actual_data[row_nr][column_nr], expected_data_including_templates[row_nr][column_nr], "NOT() has been found in expected data field, but format is incorrect.")
172
+ #
173
+ else:
174
+ if not skip_exception_rule_used:
175
+ # No exceptions.
176
+ difference_found = True
177
+ Report.show_differences_comparation_result(self, row_nr, column_nr, actual_data[row_nr][column_nr], expected_data_including_templates[row_nr][column_nr], "There is a difference between actual and expected data. No exception rule has been used.")
178
+ #
179
+ if difference_found:
180
+ print("\n\n\n")
181
+ raise Exception("There is a difference between actual and expected data. See detail information.")
182
+ else:
183
+ print("There are no differences between actual and expected data found.")
184
+ print("\n\n\n")
185
+
186
+ #Report().show_footer_comparation_result()
187
+
188
+
189
+ def __get_unwanted_expected_data(self, expected_data_field_including_date_template):
190
+ position_open_brace = expected_data_field_including_date_template.find("{NOT(")
191
+ position_close_brace = expected_data_field_including_date_template.find(")}", position_open_brace)
192
+ #
193
+ if position_open_brace == -1:
194
+ #print("position_open_brace:", position_open_brace)
195
+ raise Exception()
196
+ #
197
+ if position_close_brace == -1:
198
+ #print("position_close_brace:", position_close_brace)
199
+ raise Exception()
200
+ #
201
+ unwanted_expected_data = expected_data_field_including_date_template[position_open_brace+5:position_close_brace]
202
+ #
203
+ if Tools.is_integer(self, unwanted_expected_data):
204
+ unwanted_expected_data = int(unwanted_expected_data)
205
+ return unwanted_expected_data
206
+
@@ -0,0 +1,135 @@
1
+ # Script for comparing csv-files, 2d-array with a csv-file or 2d-arrays and for comparing text-files, text variable with a text-file or text variables.
2
+ #
3
+ import csv
4
+ import os
5
+
6
+ from DataComparerLibrary.arraycomparer import ArrayComparer
7
+
8
+
9
+ class DataComparer:
10
+ def compare_data_2d_array_with_file(self, actual_data, expected_file, delimiter_expected_data=",", quotechar_expected_data='"', template_literals_dict=None):
11
+ self.__check_if_actual_data_is_present(actual_data)
12
+ self.__check_if_expected_file_is_present(expected_file)
13
+ #
14
+ expected_data = self.__open_csv_input_file(expected_file, delimiter_expected_data, quotechar_expected_data)
15
+ #
16
+ ArrayComparer.compare_data(self, actual_data, expected_data, template_literals_dict)
17
+
18
+
19
+ def compare_data_file_with_2d_array(self, actual_file, expected_data, delimiter_actual_data=",", quotechar_actual_data='"', template_literals_dict=None):
20
+ self.__check_if_actual_file_is_present(actual_file)
21
+ self.__check_if_expected_data_is_present(expected_data)
22
+ #
23
+ actual_data = self.__open_csv_input_file(actual_file, delimiter_actual_data, quotechar_actual_data)
24
+ #
25
+ ArrayComparer.compare_data(self, actual_data, expected_data, template_literals_dict)
26
+
27
+
28
+ def compare_data_2d_arrays(self, actual_data, expected_data, template_literals_dict=None):
29
+ self.__check_if_actual_data_is_present(actual_data)
30
+ self.__check_if_expected_data_is_present(expected_data)
31
+ #
32
+ ArrayComparer.compare_data(self, actual_data, expected_data, template_literals_dict)
33
+
34
+
35
+ def compare_data_files(self, actual_file, expected_file, delimiter_actual_data=",", delimiter_expected_data=",", quotechar_actual_data='"', quotechar_expected_data='"', template_literals_dict=None):
36
+ self.__check_if_actual_file_is_present(actual_file)
37
+ self.__check_if_expected_file_is_present(expected_file)
38
+ #
39
+ actual_data = self.__open_csv_input_file(actual_file, delimiter_actual_data, quotechar_actual_data)
40
+ expected_data = self.__open_csv_input_file(expected_file, delimiter_expected_data, quotechar_expected_data)
41
+ #
42
+ ArrayComparer.compare_data(self, actual_data, expected_data, template_literals_dict)
43
+
44
+
45
+ def compare_text_variable_with_text_file(self, actual_text, expected_file, template_literals_dict=None):
46
+ self.__check_if_actual_data_is_present(actual_text)
47
+ self.__check_if_expected_file_is_present(expected_file)
48
+ #
49
+ actual_data = self.__split_text_into_textline_array(actual_text)
50
+ expected_data = self.__split_textfile_into_textline_array(expected_file)
51
+ #
52
+ ArrayComparer.compare_data(self, actual_data, expected_data, template_literals_dict)
53
+
54
+
55
+ def compare_text_file_with_text_variable(self, actual_file, expected_text, template_literals_dict=None):
56
+ self.__check_if_actual_file_is_present(actual_file)
57
+ self.__check_if_expected_data_is_present(expected_text)
58
+ #
59
+ actual_data = self.__split_textfile_into_textline_array(actual_file)
60
+ expected_data = self.__split_text_into_textline_array(expected_text)
61
+ #
62
+ ArrayComparer.compare_data(self, actual_data, expected_data, template_literals_dict)
63
+
64
+
65
+ def compare_text_variables(self, actual_text, expected_text, template_literals_dict=None):
66
+ self.__check_if_actual_data_is_present(actual_text)
67
+ self.__check_if_expected_data_is_present(expected_text)
68
+ #
69
+ actual_data = self.__split_text_into_textline_array(actual_text)
70
+ expected_data = self.__split_text_into_textline_array(expected_text)
71
+ #
72
+ ArrayComparer.compare_data(self, actual_data, expected_data, template_literals_dict)
73
+
74
+
75
+ def compare_text_files(self, actual_file, expected_file, template_literals_dict=None):
76
+ self.__check_if_actual_file_is_present(actual_file)
77
+ self.__check_if_expected_file_is_present(expected_file)
78
+ #
79
+ actual_data = self.__split_textfile_into_textline_array(actual_file)
80
+ expected_data = self.__split_textfile_into_textline_array(expected_file)
81
+ #
82
+ ArrayComparer.compare_data(self, actual_data, expected_data, template_literals_dict)
83
+
84
+
85
+
86
+ def __check_if_actual_data_is_present(self, data):
87
+ if data == None:
88
+ raise Exception("Actual Input data unknown.")
89
+
90
+
91
+ def __check_if_expected_data_is_present(self, data):
92
+ if data == None:
93
+ raise Exception("Expected Input data unknown.")
94
+
95
+
96
+ def __check_if_actual_file_is_present(self, file):
97
+ if os.path.exists(file):
98
+ print("actual_file: ", file)
99
+ else:
100
+ raise Exception("Actual Input file doesn't exists: ", file)
101
+
102
+
103
+ def __check_if_expected_file_is_present(self, file):
104
+ if os.path.exists(file):
105
+ print("expected_file: ", file)
106
+ else:
107
+ raise Exception("Expected Input file doesn't exists: ", file)
108
+
109
+
110
+ def __open_csv_input_file(self, input_file, delimiter_data=",", quotechar_data='"'):
111
+ with open(input_file, mode='rt', encoding='utf-8') as input_file:
112
+ if len(delimiter_data) == 1:
113
+ data = list(csv.reader(input_file, delimiter=delimiter_data, quotechar=quotechar_data))
114
+ else:
115
+ data = list(csv.reader((line.replace(delimiter_data, chr(255)) for line in input_file), delimiter=chr(255), quotechar=quotechar_data))
116
+ #
117
+ return data
118
+
119
+
120
+ def __split_text_into_textline_array(self, text):
121
+ data = []
122
+ for line in text.split('\n'):
123
+ data.append(line.strip('\n').split(chr(255)))
124
+ #
125
+ return data
126
+
127
+
128
+ def __split_textfile_into_textline_array(self, input_file):
129
+ with open(input_file, mode='rt', encoding='utf-8') as input_file:
130
+ data = []
131
+ for line in input_file.readlines():
132
+ data.append(line.strip('\n').split(chr(255)))
133
+ #
134
+ return data
135
+