Skip to content

Commit 55f848b

Browse files
Fixing pilot db access
* Very minor one, fixes to the way :class:`.Terminal` accesses the ``pilot_db.json`` file to use :attr:`.Terminal.pilots` property that makes a new pilot_db.json file if one doesn't exist, but otherwise loads the one that is found in ``prefs.get('PILOT_DB')`` * Reorganized :class:`.Terminal` source to group properties together & minor additions of type hinting * Fixed some bad fallback behavior looking for files in old hardcoded default directories, eg. in the ye olde :func:`.utils.get_pilotdb` * bump version to 0.3.5
1 parent 0753925 commit 55f848b

File tree

6 files changed

+114
-71
lines changed

6 files changed

+114
-71
lines changed

autopilot/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
__author__ = 'Jonny Saunders <[email protected]>'
2-
__version__ = '0.3.4'
2+
__version__ = '0.3.5'

autopilot/core/gui.py

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -274,15 +274,8 @@ def update_db(self, **kwargs):
274274
if 'state' in val.keys():
275275
del val['state']
276276

277-
try:
278-
with open(prefs.get('PILOT_DB'), 'w') as pilot_file:
279-
json.dump(self.pilots, pilot_file, indent=4, separators=(',', ': '))
280-
except NameError:
281-
try:
282-
with open('/usr/autopilot/pilot_db.json', 'w') as pilot_file:
283-
json.dump(self.pilots, pilot_file, indent=4, separators=(',', ': '))
284-
except IOError:
285-
Exception('Couldnt update pilot db!')
277+
with open(prefs.get('PILOT_DB'), 'w') as pilot_file:
278+
json.dump(self.pilots, pilot_file, indent=4, separators=(',', ': '))
286279

287280
####################################
288281
# Control Panel Widgets

autopilot/core/terminal.py

Lines changed: 89 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import json
33
import sys
44
import os
5+
from pathlib import Path
56

67
import datetime
78
import logging
@@ -108,7 +109,6 @@ class Terminal(QtWidgets.QMainWindow):
108109
node (:class:`~.networking.Net_Node`): Our Net_Node we use to communicate with our main networking object
109110
networking (:class:`~.networking.Terminal_Station`): Our networking object to communicate with the outside world
110111
subjects (dict): A dictionary mapping subject ID to :class:`~.subject.Subject` object.
111-
pilots (dict): A dictionary mapping pilot ID to a list of its subjects, its IP, and any other pilot attributes.
112112
layout (:class:`QtWidgets.QGridLayout`): Layout used to organize widgets
113113
control_panel (:class:`~.gui.Control_Panel`): Control Panel to manage pilots and subjects
114114
data_panel (:class:`~.plots.Plot_Widget`): Plots for each pilot and subject.
@@ -130,7 +130,6 @@ def __init__(self):
130130

131131
# data
132132
self.subjects = {} # Dict of our open subject objects
133-
self.pilots = None
134133

135134
# gui
136135
self.layout = None
@@ -141,13 +140,12 @@ def __init__(self):
141140
self.data_panel = None
142141
self.logo = None
143142

143+
# property private attributes
144+
self._pilots = None
145+
144146
# logging
145147
self.logger = init_logger(self)
146148

147-
# Load pilots db as ordered dictionary
148-
with open(prefs.get('PILOT_DB')) as pilot_file:
149-
self.pilots = json.load(pilot_file, object_pairs_hook=odict)
150-
151149
# Listen dictionary - which methods to call for different messages
152150
# Methods are spawned in new threads using handle_message
153151
self.listens = {
@@ -378,6 +376,91 @@ def reset_ui(self):
378376
self.setCentralWidget(self.widget)
379377
self.initUI()
380378

379+
################
380+
# Properties
381+
382+
@property
383+
def pilots(self) -> odict:
384+
"""
385+
A dictionary mapping pilot ID to its attributes, including a list of its subjects assigned to it, its IP, etc.
386+
387+
Returns:
388+
dict: like ``self.pilots['pilot_id'] = {'subjects': ['subject_0', 'subject_1'], 'ip': '192.168.0.101'}``
389+
"""
390+
391+
# try to load, if none exists make one
392+
if self._pilots is None:
393+
394+
pilot_db_fn = Path(prefs.get('PILOT_DB'))
395+
396+
# if pilot file doesn't exist, make blank one
397+
if not pilot_db_fn.exists():
398+
self.logger.warning(f'No pilot_db.json file was found at {pilot_db_fn}, creating a new one')
399+
self._pilots = odict()
400+
with open(pilot_db_fn, 'w') as pilot_file:
401+
json.dump(self._pilots, pilot_file)
402+
403+
# otherwise, try to load it
404+
else:
405+
try:
406+
# Load pilots db as ordered dictionary
407+
with open(pilot_db_fn, 'r') as pilot_file:
408+
self._pilots = json.load(pilot_file, object_pairs_hook=odict)
409+
except Exception as e:
410+
self.logger.exception((f"Exception opening pilot_db.json file at {pilot_db_fn}, got exception: {e}.\n",
411+
"Not proceeding to prevent possibly overwriting corrupt pilot_db.file"))
412+
raise e
413+
414+
return self._pilots
415+
416+
417+
@property
418+
def protocols(self) -> list:
419+
"""
420+
List of protocol names available in ``PROTOCOLDIR``
421+
422+
Returns:
423+
list: list of protocol names in ``prefs.get('PROTOCOLDIR')``
424+
"""
425+
# get list of protocol files
426+
protocols = os.listdir(prefs.get('PROTOCOLDIR'))
427+
protocols = [os.path.splitext(p)[0] for p in protocols if p.endswith('.json')]
428+
return protocols
429+
430+
@property
431+
def subject_protocols(self) -> dict:
432+
"""
433+
434+
Returns:
435+
subject_protocols (dict): a dictionary of subjects: [protocol, step]
436+
"""
437+
# get subjects and current protocols
438+
subjects = self.subject_list
439+
subjects_protocols = {}
440+
for subject in subjects:
441+
if subject not in self.subjects.keys():
442+
self.subjects[subject] = Subject(subject)
443+
444+
subjects_protocols[subject] = [self.subjects[subject].protocol_name, self.subjects[subject].step]
445+
446+
return subjects_protocols
447+
448+
@property
449+
def subject_list(self) -> list:
450+
"""
451+
Get a list of all subject IDs
452+
453+
Returns:
454+
list: list of all subject IDs present in :attr:`.Terminal.pilots`
455+
"""
456+
subjects = []
457+
for pilot, vals in self.pilots.items():
458+
subjects.extend(vals['subjects'])
459+
460+
# use sets to get a unique list
461+
subjects = list(set(subjects))
462+
463+
return subjects
381464

382465
##########################3
383466
# Listens & inter-object methods
@@ -626,23 +709,6 @@ def new_protocol(self):
626709
with open(protocol_file, 'w') as pfile_open:
627710
json.dump(save_steps, pfile_open, indent=4, separators=(',', ': '), sort_keys=True)
628711

629-
@property
630-
def subject_list(self):
631-
"""
632-
Get a list of all subject IDs
633-
634-
Returns:
635-
list: list of all subject IDs present in :attr:`.Terminal.pilots`
636-
"""
637-
subjects = []
638-
for pilot, vals in self.pilots.items():
639-
subjects.extend(vals['subjects'])
640-
641-
# use sets to get a unique list
642-
subjects = list(set(subjects))
643-
644-
return subjects
645-
646712
def subject_weights(self):
647713
"""
648714
Gets recent weights from all :attr:`~.Terminal.subjects` and
@@ -692,36 +758,6 @@ def update_protocols(self):
692758
msgbox.setDetailedText("\n".join(sorted(updated_subjects)))
693759
msgbox.exec_()
694760

695-
@property
696-
def protocols(self):
697-
"""
698-
Returns:
699-
list: list of protocol files in ``prefs.get('PROTOCOLDIR')``
700-
"""
701-
# get list of protocol files
702-
protocols = os.listdir(prefs.get('PROTOCOLDIR'))
703-
protocols = [os.path.splitext(p)[0] for p in protocols if p.endswith('.json')]
704-
return protocols
705-
706-
@property
707-
def subject_protocols(self):
708-
"""
709-
710-
Returns:
711-
subject_protocols (dict): a dictionary of subjects: [protocol, step]
712-
"""
713-
# get subjects and current protocols
714-
subjects = self.subject_list
715-
subjects_protocols = {}
716-
for subject in subjects:
717-
if subject not in self.subjects.keys():
718-
self.subjects[subject] = Subject(subject)
719-
720-
subjects_protocols[subject] = [self.subjects[subject].protocol_name, self.subjects[subject].step]
721-
722-
return subjects_protocols
723-
724-
725761
def reassign_protocols(self):
726762
"""
727763
Batch reassign protocols and steps.

autopilot/core/utils.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
except ImportError:
88
pass
99

10+
from collections import OrderedDict as odict
1011
import json
1112
import pandas as pd
1213
from scipy.stats import linregress
@@ -165,23 +166,23 @@ def load_pilotdb(file_name=None, reverse=False):
165166
Try to load the file_db
166167
167168
Args:
168-
reverse:
169-
file_name:
169+
reverse (bool): Return inverted pilot db mapping subjects: pilots (default False)
170+
file_name (str): Path of ``pilot_db.json``, if None, use ``prefs.get('PILOT_DB')``
170171
171172
Returns:
172-
173+
:class:`collections.OrderedDict` : pilot_db.json or reversed pilot_db
173174
"""
174175

175176
if file_name is None:
176-
file_name = '/usr/autopilot/pilot_db.json'
177+
file_name = prefs.get('PILOT_DB')
177178

178179
with open(file_name) as pilot_file:
179-
pilot_db = json.load(pilot_file)
180+
pilot_db = json.load(pilot_file, object_pairs_hook=odict)
180181

181182
if reverse:
182183
# simplify pilot db
183-
pilot_db = {k: v['subjects'] for k, v in pilot_db.items()}
184-
pilot_dict = {}
184+
pilot_db = odict({k: v['subjects'] for k, v in pilot_db.items()})
185+
pilot_dict = odict()
185186
for pilot, subjectlist in pilot_db.items():
186187
for ms in subjectlist:
187188
pilot_dict[ms] = pilot

docs/changelog/v0.3.0.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
.. _changelog_v030:
22

3+
v0.3.5 (February 22, 2021)
4+
--------------------------
5+
6+
Bugfixes
7+
~~~~~~~~
8+
9+
* Very minor one, fixes to the way :class:`.Terminal` accesses the ``pilot_db.json`` file to use :attr:`.Terminal.pilots`
10+
property that makes a new pilot_db.json file if one doesn't exist, but otherwise loads the one that is found in
11+
``prefs.get('PILOT_DB')``
12+
* Reorganized :class:`.Terminal` source to group properties together & minor additions of type hinting
13+
* Fixed some bad fallback behavior looking for files in old hardcoded default directories, eg. in the ye olde
14+
:func:`.utils.get_pilotdb`
15+
316
v0.3.4 (December 13, 2020)
417
---------------------------
518

docs/notes/building.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
deployment
22
- write docs
33
- write changelog
4-
- bump version in setup.py
4+
- bump version in __init__.py
55

66
- do PR
77
- merge

0 commit comments

Comments
 (0)