Skip to content

Commit 4495095

Browse files
committed
New backup
The backup is now always the whole store file from before pressing the delete button. Sore class has been refactored a bit - it is now split into: 1) store 2) store_loader 3) store_writer Still to do: 1) store loader needs more unit tests 2) store unit test need fixing after the refactor
1 parent 868e88d commit 4495095

File tree

12 files changed

+284
-276
lines changed

12 files changed

+284
-276
lines changed

dls_barcode/data_store/comms_manager.py

Lines changed: 0 additions & 63 deletions
This file was deleted.

dls_barcode/data_store/store.py

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import uuid
2-
import os
32
import time
43

54
from dls_barcode.data_store.backup import Backup
6-
from dls_barcode.data_store.comms_manager import CommsManager
5+
from dls_barcode.data_store.store_writer import StoreWriter
76
from .record import Record
87

98

@@ -13,15 +12,11 @@ class Store:
1312
or deletions) are automatically written to the backing file.
1413
"""
1514

16-
def __init__(self, comms_manager):
15+
def __init__(self, store_writer, records):
1716
""" Initializes a new instance of Store.
1817
"""
19-
self._comms_manager = comms_manager
20-
self._comms_manager.make_img_dir()
21-
self._img_dir = self._comms_manager.get_img_dir()
22-
records = self._comms_manager.load_records_from_file()
18+
self._store_writer = store_writer
2319
self.records = records
24-
self._sort_records()
2520

2621
def size(self):
2722
""" Returns the number of records in the store
@@ -31,17 +26,17 @@ def size(self):
3126
def get_record(self, index):
3227
""" Get record by index where the 0th record is the most recent
3328
"""
29+
self._sort_records()
3430
return self.records[index] if self.records else None
3531

3632
def _add_record(self, holder_barcode, plate, holder_img, pins_img):
3733
""" Add a new record to the store and save to the backing file.
3834
"""
3935
merged_img = self._merge_holder_image_into_pins_image(holder_img, pins_img)
4036
guid = str(uuid.uuid4())
41-
filename = os.path.abspath(os.path.join(self._img_dir, guid + '.png'))
42-
merged_img.save_as(filename)
37+
self._store_writer.to_image(merged_img, guid)
4338

44-
record = Record.from_plate(holder_barcode, plate, filename)
39+
record = Record.from_plate(holder_barcode, plate, self._store_writer.get_img_path())
4540

4641
self.records.append(record)
4742
self._process_change()
@@ -57,8 +52,8 @@ def merge_record(self, holder_barcode, plate, holder_img, pins_img):
5752
def backup_records(self, directory):
5853
ts = time.localtime()
5954
file_name = time.strftime("%Y-%m-%d_%H-%M-%S", ts)
60-
backup_manger = CommsManager(directory, file_name)
61-
backup = Backup(backup_manger)
55+
backup_writer = StoreWriter(directory, file_name)
56+
backup = Backup(backup_writer)
6257
backup.backup_records(self.records)
6358

6459
def delete_records(self, records_to_delete):
@@ -67,17 +62,16 @@ def delete_records(self, records_to_delete):
6762
"""
6863
for record in records_to_delete:
6964
self.records.remove(record)
70-
self._comms_manager.remove_img_file(record)
65+
self._store_writer.remove_img_file(record)
7166

7267
self._process_change()
7368

74-
7569
def _process_change(self):
7670
""" Sort the records and save to file.
7771
"""
7872
self._sort_records()
79-
self._comms_manager.to_file(self.records)
80-
self._comms_manager.to_csv_file(self.records)
73+
self._store_writer.to_file(self.records)
74+
self._store_writer.to_csv_file(self.records)
8175

8276
def _sort_records(self):
8377
""" Sort the records in descending date order (most recent first).
@@ -93,5 +87,6 @@ def _merge_holder_image_into_pins_image(self, holder_img, pins_img):
9387
return merged_img
9488

9589
def is_latest_holder_barcode(self, holder_barcode):
90+
self._sort_records()
9691
latest_record = self.get_record(0)
9792
return latest_record is not None and holder_barcode == latest_record.holder_barcode
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import os
2+
3+
from dls_barcode.data_store.record import Record
4+
from dls_util.file import FileManager
5+
6+
7+
class StoreLoader:
8+
9+
def __init__(self, directory, file_name, file_manager=FileManager()):
10+
self._directory = directory
11+
self._file_name = file_name
12+
self._file_manager= file_manager
13+
self._path = None
14+
self._records = []
15+
16+
def load_records_from_file(self):
17+
""" Clear the current record store and load a new set of records from the specified file. """
18+
self._build_file_path()
19+
if not self._check_if_file():
20+
return self._records
21+
self._build_records_from_lines(self._read_lines())
22+
return self._records
23+
24+
def _build_file_path(self):
25+
self._path = os.path.join(self._directory, self._file_name + '.txt')
26+
27+
def _check_if_file(self):
28+
return self._file_manager.is_file(self._path)
29+
30+
def _read_lines(self):
31+
return self._file_manager.read_lines(self._path)
32+
33+
def _build_records_from_lines(self, lines):
34+
for line in lines:
35+
try:
36+
record = Record.from_string(line)
37+
self._records.append(record)
38+
except Exception:
39+
print("Failed to parse store Record: {}".format(line))
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import os
2+
3+
from dls_barcode.data_store.record import Record
4+
from dls_util.file import FileManager
5+
6+
7+
class StoreWriter:
8+
""" Maintains writing records to file and saving png images in a sub-folder
9+
"""
10+
11+
def __init__(self, directory, file_name, file_manager=FileManager()):
12+
self._file_manager = file_manager
13+
self._directory = directory
14+
self._file_name = file_name
15+
self._image_path = None
16+
17+
def to_file(self, records):
18+
""" Save the contents of the store to the backing file
19+
"""
20+
self._file_manager.make_dir_when_no_dir(self._directory)
21+
file = os.path.join(self._directory, self._file_name + '.txt')
22+
record_lines = [rec.to_string() + "\n" for rec in records]
23+
self._file_manager.write_lines(file, record_lines)
24+
25+
def to_csv_file(self, records):
26+
""" Save the contents of the store to the backing csv file
27+
"""
28+
self._file_manager.make_dir_when_no_dir(self._directory)
29+
csv_file = os.path.join(self._directory, self._file_name + ".csv")
30+
record_lines = [rec.to_csv_string() + "\n" for rec in records]
31+
self._file_manager.write_lines(csv_file, record_lines)
32+
33+
def to_image(self, image, name):
34+
dr = self._make_img_dir()
35+
self._image_path = os.path.abspath(os.path.join(dr, name + '.png'))
36+
image.save_as(self._image_path)
37+
38+
def get_img_path(self):
39+
return self._image_path
40+
41+
def _make_img_dir(self):
42+
self._file_manager.make_dir_when_no_dir(self._directory)
43+
img_dir = os.path.join(self._directory, "img_dir")
44+
self._file_manager.make_dir_when_no_dir(img_dir)
45+
return img_dir
46+
47+
def remove_img_file(self, record):
48+
if self._file_manager.is_file(record.image_path):
49+
self._file_manager.remove(record.image_path)

dls_barcode/gui/record_table.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
from PyQt5.QtWidgets import QGroupBox, QVBoxLayout, QHBoxLayout, QTableWidget, QMessageBox
66

77
from dls_barcode.data_store import Store
8-
from dls_barcode.data_store.comms_manager import CommsManager
8+
from dls_barcode.data_store.store_loader import StoreLoader
9+
from dls_barcode.data_store.store_writer import StoreWriter
910

1011
# todo: allow delete key to be used for deletion
1112
# todo: allow record selection with arrow keys
@@ -22,8 +23,10 @@ def __init__(self, barcode_table, image_frame, options):
2223
super(ScanRecordTable, self).__init__()
2324

2425
# Read the store from file
25-
comms_manger = CommsManager(options.get_store_directory(), "store")
26-
self._store = Store(comms_manger)
26+
store_writer = StoreWriter(options.get_store_directory(), "store")
27+
store_loader = StoreLoader(options.get_store_directory(), "store")
28+
29+
self._store = Store(store_writer, store_loader.load_records_from_file())
2730
self._options = options
2831

2932
self._barcodeTable = barcode_table

dls_util/file/file_manager.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,8 @@ def make_dir(self, path):
2929
os.makedirs(path)
3030

3131
def remove(self, path):
32-
os.remove(path)
32+
os.remove(path)
33+
34+
def make_dir_when_no_dir(self, dr):
35+
if not self.is_dir(dr):
36+
self.make_dir(dr)

tests/system_tests/test_unipuck_scan.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from dls_barcode.config.barcode_config import BarcodeConfig
44
from dls_barcode.data_store import Store
5-
from dls_barcode.data_store.store_manager import StoreManager
5+
from dls_barcode.data_store.store_writer import StoreWriter
66
from dls_barcode.scan import GeometryScanner
77
from dls_util.image import Image
88
from dls_util.file import FileManager
@@ -20,7 +20,8 @@
2020
if os.path.isdir(store_dir.value()):
2121
shutil.rmtree(store_dir.value())
2222

23-
STORE = StoreManager(store_dir, OPTIONS.store_capacity, OPTIONS.backup_time).create_store()
23+
comms_manger = StoreWriter(OPTIONS.get_store_directory(), "store")
24+
STORE = Store(comms_manger)
2425

2526

2627
def test_generator():

tests/system_tests/test_unipuck_scan_locator.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
from dls_barcode.config.barcode_config import BarcodeConfig
77
from dls_barcode.data_store import Store
8-
from dls_barcode.data_store.store_manager import StoreManager
8+
from dls_barcode.data_store.store_writer import StoreWriter
99
from dls_barcode.geometry.unipuck import Unipuck
1010
from dls_barcode.scan import GeometryScanner
1111
from dls_util import Color
@@ -26,9 +26,8 @@
2626
store_dir = OPTIONS.store_directory
2727
if os.path.isdir(store_dir.value()):
2828
shutil.rmtree(store_dir.value())
29-
30-
STORE = StoreManager(store_dir, OPTIONS.store_capacity, OPTIONS.backup_time).create_store()
31-
29+
comms_manger = StoreWriter(OPTIONS.get_store_directory(), "store")
30+
STORE = Store(comms_manger)
3231
def test_generator():
3332
TEST_CASES = generate_test_cases()
3433
for params in TEST_CASES:

tests/unit_tests/test_dls_barcode/test_data_store/test_backup.py

Lines changed: 1 addition & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -20,69 +20,14 @@ def setUp(self):
2020
record_three.to_string.return_value = 'string_three'
2121
self.records = [record_one, record_two, record_three]
2222

23-
def test_truncate_removes_all_old_records(self):
24-
# Arrange
25-
self.comms_man.load_records_from_file.return_value = self.records
26-
27-
# Act
28-
backup = Backup(self.comms_man, self.backup_time)
29-
orig_size = len(backup._records)
30-
backup._truncate_record_list()
31-
32-
# Assert
33-
new_size = len(backup._records)
34-
self.assertNotEqual(orig_size, new_size)
35-
self.assertEqual(new_size, 2)
36-
37-
def test_backup_records_adds_new_records_to_existing_list(self):
38-
# Arrange
39-
self.comms_man.load_records_from_file.return_value = self.records
40-
41-
# Act
42-
backup = Backup(self.comms_man, self.backup_time)
43-
backup.backup_records(self.records)
44-
45-
# Assert
46-
self.assertEqual(len(backup._records), 4) #old truncated
47-
48-
def test_backup_records_removes_old_records_from_the_passed_when_its_called(self):
49-
# Arrange
50-
self.comms_man.load_records_from_file.return_value = []
51-
52-
# Act
53-
backup = Backup(self.comms_man, self.backup_time)
54-
backup.backup_records(self.records)
55-
56-
# Assert
57-
self.assertEqual(len(backup._records), 2)
58-
5923
def test_backup_records_to_csv_file(self):
6024
#Arrange
6125
self.comms_man.to_csv_file = MagicMock()
62-
backup = Backup(self.comms_man, self.backup_time)
26+
backup = Backup(self.comms_man)
6327

6428
# Act
6529
backup.backup_records([])
6630

6731
#Assert
6832
self.comms_man.to_csv_file.assert_called_once()
6933

70-
def test_is_old_returns_true_for_records_older_than_assumed_number_of_weeks(self):
71-
# Arrange
72-
record = self.records[2]
73-
74-
# Act
75-
backup = Backup(self.comms_man, self.backup_time)
76-
77-
# Assert
78-
self.assertTrue(backup._is_old(record))
79-
80-
def test_is_old_returns_false_for_records_younger_than_assumed_number_of_weeks(self):
81-
# Arrange
82-
record = self.records[0]
83-
84-
# Act
85-
backup = Backup(self.comms_man, self.backup_time)
86-
87-
# Assert
88-
self.assertFalse(backup._is_old(record))

0 commit comments

Comments
 (0)