Skip to content

Commit 838ae2f

Browse files
committed
Add timestamp prefix to output files to prevent overwriting
Resolves #22
1 parent 91db9da commit 838ae2f

File tree

3 files changed

+42
-20
lines changed

3 files changed

+42
-20
lines changed

code/data_exporting.py

+15-4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import pathlib
44
import typing
55
import operator
6+
from datetime import datetime
67

78
from grid_info import NUM_QUESTIONS, Field, RealOrVirtualField, VirtualField
89
import list_utils
@@ -22,6 +23,10 @@
2223
KEY_NOT_FOUND_MESSAGE = "NO KEY FOUND"
2324

2425

26+
def format_timestamp_for_file(timestamp: datetime) -> str:
27+
return timestamp.isoformat(sep="_").replace(":", "-")
28+
29+
2530
class OutputSheet():
2631
"""A lightweight matrix of data to be exported. Faster than a dataframe but
2732
can be easily converted to one when the need arises."""
@@ -40,12 +45,15 @@ def __init__(self, columns: typing.List[RealOrVirtualField]):
4045
self.data = [field_column_names + answer_columns]
4146
self.row_count = 0
4247

43-
def save(self, path: pathlib.PurePath, sort: bool):
48+
def save(self, path: pathlib.PurePath, filebasename: str, sort: bool,
49+
timestamp: datetime) -> pathlib.PurePath:
4450
if sort:
4551
self.sortByName()
46-
with open(str(path), 'w+', newline='') as output_file:
52+
output_path = path / f"{format_timestamp_for_file(timestamp)}__{filebasename}.csv"
53+
with open(str(output_path), 'w+', newline='') as output_file:
4754
writer = csv.writer(output_file)
4855
writer.writerows(self.data)
56+
return output_path
4957

5058
def sortByName(self):
5159
data = self.data[1:]
@@ -131,7 +139,8 @@ def clean_up(self, replace_empty_with: str = ""):
131139

132140

133141
def save_reordered_version(sheet: OutputSheet, arrangement_file: pathlib.Path,
134-
save_path: pathlib.Path):
142+
save_path: pathlib.Path, filebasename: str,
143+
timestamp: datetime) -> pathlib.PurePath:
135144
"""Reorder the output sheet based on a key arrangement file and save CSV."""
136145
# order_map will be a dict matching form code keys to a list where the
137146
# new index of question `i` in `key` is `order_map[key][i]`
@@ -167,6 +176,8 @@ def save_reordered_version(sheet: OutputSheet, arrangement_file: pathlib.Path,
167176
results.append(row_reordered)
168177
else:
169178
results.append(row)
170-
with open(str(save_path), 'w+', newline='') as output_file:
179+
output_path = save_path / f"{format_timestamp_for_file(timestamp)}__{filebasename}.csv"
180+
with open(str(output_path), 'w+', newline='') as output_file:
171181
writer = csv.writer(output_file)
172182
writer.writerows(results)
183+
return output_path

code/main.py

+25-9
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from datetime import datetime
12
import time
23
import typing
34
import textwrap
@@ -26,6 +27,9 @@
2627
sort_results = user_input.sort_results
2728

2829
progress = user_interface.ProgressTracker(user_input.root, len(image_paths))
30+
31+
files_timestamp = datetime.now().replace(microsecond=0)
32+
2933
try:
3034
for image_path in image_paths:
3135
progress.set_status(f"Processing '{image_path.name}'.")
@@ -76,23 +80,35 @@
7680
progress.step_progress()
7781

7882
answers_results.clean_up("G" if empty_answers_as_g else "")
79-
answers_results.save(output_folder / "results.csv", sort_results)
83+
answers_results.save(output_folder,
84+
"results",
85+
sort_results,
86+
timestamp=files_timestamp)
8087

81-
success_string = "✔️ All exams processed and saved to 'results.csv'.\n"
88+
success_string = "✔️ All exams processed and saved.\n"
8289

8390
if keys_file:
8491
keys_results.add_file(keys_file)
8592

8693
if (keys_results.row_count != 0):
87-
keys_results.save(output_folder / "keys.csv", sort_results)
88-
success_string += "✔️ All keys processed and saved to 'keys.csv'.\n"
94+
keys_path = keys_results.save(output_folder,
95+
"keys",
96+
sort_results,
97+
timestamp=files_timestamp)
98+
success_string += "✔️ All keys processed and saved.\n"
8999
scores = scoring.score_results(answers_results, keys_results)
90-
scores.save(output_folder / "scores.csv", sort_results)
91-
success_string += "✔️ All scored results processed and saved to 'scores.csv'."
100+
scores.save(output_folder,
101+
"scores",
102+
sort_results,
103+
timestamp=files_timestamp)
104+
success_string += "✔️ All scored results processed and saved."
92105
if arrangement_file:
93-
data_exporting.save_reordered_version(
94-
scores, arrangement_file, output_folder / "reordered.csv")
95-
success_string += "✔️ Reordered results saved to 'reordered.csv'."
106+
data_exporting.save_reordered_version(scores,
107+
arrangement_file,
108+
output_folder,
109+
"reordered",
110+
timestamp=files_timestamp)
111+
success_string += "✔️ Reordered results saved."
96112
else:
97113
success_string += "No exam keys were found, so no scoring was performed."
98114

code/user_interface.py

+2-7
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ def __init__(self):
235235
create_and_pack_label(app, "Select Output Folder", heading=True)
236236
create_and_pack_label(
237237
app,
238-
"Select a folder to save output files to.\nExisting files may be overwritten, so it's best to use an empty folder."
238+
"Select a folder to save output files to."
239239
)
240240

241241
self.__output_folder_picker = FolderPickerWidget(
@@ -297,12 +297,7 @@ def update_status(self):
297297
ok_to_submit = False
298298
else:
299299
self.output_folder = output_folder
300-
existing_csv_files = file_handling.filter_by_extensions(
301-
file_handling.list_file_paths(output_folder), [".csv"])
302-
if len(existing_csv_files) == 0:
303-
new_status += f"✔ Output folder selected.\n"
304-
else:
305-
new_status += f"✔⚠ Output folder selected. Existing CSV files may be overwritten.\n"
300+
new_status += f"✔ Output folder selected.\n"
306301

307302
keys_file = self.__answer_key_picker.selection
308303
if keys_file:

0 commit comments

Comments
 (0)