Skip to content

Commit 6c9028a

Browse files
authored
close calibration file before deleting it, to avoid windows error (#164)
* close calibration file before deleting it, to avoid windows error * refactors reading and validating calibration data
1 parent e32253c commit 6c9028a

File tree

5 files changed

+52
-28
lines changed

5 files changed

+52
-28
lines changed

opentrons/instruments/instrument.py

Lines changed: 25 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@
55

66
from opentrons.containers.calibrator import Calibrator
77
from opentrons.util.vector import (Vector, VectorEncoder)
8+
from opentrons.util import environment
89
from opentrons.robot.command import Command
910
from opentrons import Robot
1011

12+
from opentrons.util.log import get_logger
13+
1114

1215
JSON_ERROR = None
1316
if sys.version_info > (3, 4):
@@ -16,8 +19,7 @@
1619
JSON_ERROR = json.decoder.JSONDecodeError
1720

1821

19-
CALIBRATIONS_FOLDER = 'calibrations'
20-
CALIBRATIONS_FILE = 'calibrations.json'
22+
log = get_logger(__name__)
2123

2224

2325
class Instrument(object):
@@ -121,13 +123,8 @@ def init_calibrations(self, key, attributes=None):
121123
for key in attributes:
122124
self.persisted_defaults[key] = copy.copy(getattr(self, key))
123125

124-
if not os.path.isdir(self._get_calibration_dir()):
125-
os.mkdir(self._get_calibration_dir())
126-
127126
if not os.path.isfile(self._get_calibration_file_path()):
128127
self._write_blank_calibrations_file()
129-
else:
130-
self._check_calibrations_version()
131128

132129
def update_calibrations(self):
133130
"""
@@ -180,18 +177,11 @@ def _write_blank_calibrations_file(self):
180177
'data': {}
181178
}))
182179

183-
def _get_calibration_dir(self):
184-
"""
185-
:return: the directory to save calibration data
186-
"""
187-
DATA_DIR = os.environ.get('APP_DATA_DIR') or os.getcwd()
188-
return os.path.join(DATA_DIR, CALIBRATIONS_FOLDER)
189-
190180
def _get_calibration_file_path(self):
191181
"""
192182
:return: the absolute file path of the calibration file
193183
"""
194-
return os.path.join(self._get_calibration_dir(), CALIBRATIONS_FILE)
184+
return environment.get_path('CALIBRATIONS_FILE')
195185

196186
def _get_calibration(self):
197187
"""
@@ -212,30 +202,37 @@ def _build_calibration_data(self):
212202
def _read_calibrations(self):
213203
"""
214204
Reads calibration data from file system.
205+
Expects a valid valibration format
215206
:return: json of calibration data
216207
"""
217-
with open(self._get_calibration_file_path()) as f:
218-
try:
219-
loaded_json = json.load(f)
220-
except json.decoder.JSONDecodeError:
221-
self._write_blank_calibrations_file()
222-
return self._read_calibrations()
223-
return self._restore_vector(loaded_json)
208+
file_path = self._get_calibration_file_path()
209+
self._validate_calibration_file(file_path)
210+
loaded_json = ""
211+
with open(file_path) as f:
212+
loaded_json = json.load(f)
224213

225-
def _check_calibrations_version(self):
214+
return self._restore_vector(loaded_json)
215+
216+
def _validate_calibration_file(self, file_path):
226217
"""
227218
Read calibration file, and checks for version number
228219
If no version number, file is replaced with version number
229220
"""
230-
with open(self._get_calibration_file_path()) as f:
221+
valid = False
222+
with open(file_path) as f:
231223
try:
232224
file = json.load(f)
233225
version = file.get('version')
234226
data = file.get('data')
235-
if not version or not data or len(file.keys()) > 2:
236-
self._write_blank_calibrations_file()
237-
except json.decoder.JSONDecodeError:
238-
self._write_blank_calibrations_file()
227+
if version and data and len(file.keys()) == 2:
228+
valid = True
229+
except json.decoder.JSONDecodeError as e:
230+
log.error(
231+
'Error parsing calibration data (file: {}): {}'.format(
232+
file_path, e))
233+
234+
if not valid:
235+
self._write_blank_calibrations_file()
239236

240237
def _strip_vector(self, obj, root=True):
241238
"""

opentrons/util/environment.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ def refresh():
1616
'LOG_FILE': os.path.join(APP_DATA_DIR, 'logs', 'api.log'),
1717
'CONTAINERS_DIR': os.path.join(APP_DATA_DIR, 'containers'),
1818
'CALIBRATIONS_DIR': os.path.join(APP_DATA_DIR, 'calibrations'),
19+
'CALIBRATIONS_FILE':
20+
os.path.join(APP_DATA_DIR, 'calibrations', 'calibrations.json'),
1921
'APP_IS_ALIVE_URL': 'http://localhost:31950',
2022
'APP_JUPYTER_UPLOAD_URL': 'http://localhost:31950/upload-jupyter',
2123
})
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{asdfsad}

tests/opentrons/labware/test_crud_calibrations.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1+
import shutil
2+
import os
3+
import json
14
import unittest
25

36
from opentrons import Robot
47
from opentrons import containers, instruments
58
from opentrons.util.vector import Vector
9+
from opentrons.util import environment
610

711

812
class CrudCalibrationsTestCase(unittest.TestCase):
@@ -71,3 +75,22 @@ def test_delete_calibrations_data(self):
7175
self.assertDictEqual(self.p200.positions, {
7276
'top': None, 'bottom': None, 'blow_out': None, 'drop_tip': None
7377
})
78+
79+
def test_delete_old_calibration_file(self):
80+
81+
def test_file(file_name):
82+
calib_dir = environment.get_path('CALIBRATIONS_DIR')
83+
shutil.copyfile(
84+
os.path.join(os.path.dirname(__file__), file_name),
85+
os.path.join(calib_dir, 'calibrations.json')
86+
)
87+
88+
instruments.instrument.Instrument()._read_calibrations()
89+
90+
file = os.path.join(calib_dir, 'calibrations.json')
91+
with open(file) as f:
92+
calib_object = json.load(f)
93+
self.assertEquals(calib_object['version'], 1)
94+
95+
test_file('data/calibrations.json')
96+
test_file('data/invalid_json.json')

0 commit comments

Comments
 (0)