Skip to content

Commit de57f90

Browse files
Remove labscript_suite from default config file
But add it as a default option so that config files may continue to use it as an interpolation value. Saving config files whenever a value is set breaks this, as it actually saves the default value to disk. Without adding a guard against it, it actually writes any provided default values to disk before loading the existing config file, actually wiping out the user's config completely. So this commit removes the overridden methods that save back to disk. No labscript code actually sets config values except for some code in the BLACS plugins `__init__.py`, which adds the list of available plugins. Not writing this back to disk is fine. If we ever make GUI interfaces for manipulating the config file, it is poor form to just overwrite the user's config file anyway, which may re-order sections and remove comments. For that we would want to use something like https://pypi.org/project/ConfigUpdater/. Also simplify the code that gets the config path. There is only one place on disk for config paths now, and if it doesn't exist the user will get a FileNotFoundError with the full path, so I don't think there is a strong need to wrap that error in one written by us that basically says the same thing! This change removes the hostname and config_prefix variables. These variables are imported (unused) by lyse and runviewer, so I will remove them from those projects. They are also imported and used by BLACS to construct its config filepath. I will modify BLACS to instead put its config file in the standard config file locations for apps. Fixes #22
1 parent 21c6d8a commit de57f90

File tree

2 files changed

+27
-88
lines changed

2 files changed

+27
-88
lines changed

labscript_profile/default_profile/labconfig/example.ini

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
experiment_name = default_experiment
33
shared_drive = C:
44
experiment_shot_storage = %(shared_drive)s\Experiments\%(experiment_name)s
5-
labscript_suite = C:\labscript_suite
65
userlib=%(labscript_suite)s\userlib
76
pythonlib = %(userlib)s\pythonlib
87
labscriptlib = %(userlib)s\labscriptlib\%(experiment_name)s

labscript_utils/labconfig.py

Lines changed: 27 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -12,48 +12,13 @@
1212
#####################################################################
1313
import sys
1414
import os
15-
import socket
16-
import subprocess
17-
import errno
1815
import configparser
1916

20-
from labscript_profile import LABSCRIPT_SUITE_PROFILE
21-
# Look for a 'labconfig' folder in the labscript install directory:
22-
if LABSCRIPT_SUITE_PROFILE is not None:
23-
config_prefix = os.path.join(LABSCRIPT_SUITE_PROFILE, 'labconfig')
24-
else:
25-
# No labscript install directory found? Revert to system defaults
26-
if os.name == 'nt':
27-
config_prefix = os.path.abspath(r'C:\labconfig')
28-
else:
29-
config_prefix = os.path.join(os.getenv('HOME'),'labconfig')
30-
if not os.path.exists(config_prefix):
31-
config_prefix='/etc/labconfig/'
17+
from labscript_utils import dedent
18+
from labscript_profile import default_labconfig_path, LABSCRIPT_SUITE_PROFILE
3219

33-
if not os.path.exists(config_prefix):
34-
message = (r"Couldn't find labconfig folder. Please ensure it exists. " +
35-
r"If the labscript suite is installed, labconfig must be <labscript_suite_profile>/labconfig/. " +
36-
r"If the labscript suite is not installed, then C:\labconfig\ is checked on Windows, " +
37-
r" and $HOME/labconfig/ then /etc/labconfig/ checked on unix.")
38-
raise IOError(message)
20+
default_config_path = default_labconfig_path()
3921

40-
config_prefix = os.path.abspath(config_prefix)
41-
42-
if sys.platform == 'darwin':
43-
hostname = subprocess.check_output(['scutil', '--get', 'LocalHostName']).decode('utf8').strip()
44-
else:
45-
hostname = socket.gethostname()
46-
default_config_path = os.path.join(config_prefix,'%s.ini'%hostname)
47-
48-
49-
def mkdir_p(path):
50-
try:
51-
os.makedirs(path)
52-
except OSError as exc:
53-
if exc.errno == errno.EEXIST and os.path.isdir(path):
54-
pass
55-
else:
56-
raise
5722

5823
class EnvInterpolation(configparser.BasicInterpolation):
5924
"""Interpolation which expands environment variables in values,
@@ -63,69 +28,44 @@ def before_get(self, *args):
6328
value = super(EnvInterpolation, self).before_get(*args)
6429
return os.path.expandvars(value)
6530

31+
6632
class LabConfig(configparser.ConfigParser):
6733
NoOptionError = configparser.NoOptionError
6834
NoSectionError = configparser.NoSectionError
6935

70-
def __init__(self,config_path=default_config_path,required_params={},defaults={}):
71-
if isinstance(config_path,list):
36+
def __init__(
37+
self, config_path=default_config_path, required_params=None, defaults=None,
38+
):
39+
if required_params is None:
40+
required_params = {}
41+
if defaults is None:
42+
defaults = {}
43+
defaults['labscript_suite'] = LABSCRIPT_SUITE_PROFILE
44+
if isinstance(config_path, list):
7245
self.config_path = config_path[0]
7346
else:
7447
self.config_path = config_path
7548

7649
self.file_format = ""
7750
for section, options in required_params.items():
78-
self.file_format += "[%s]\n"%section
51+
self.file_format += "[%s]\n" % section
7952
for option in options:
80-
self.file_format += "%s = <value>\n"%option
81-
82-
# Ensure the folder exists:
83-
mkdir_p(os.path.dirname(self.config_path))
84-
85-
# If the file doesn't exist, create it
86-
if not os.path.exists(self.config_path):
87-
with open(self.config_path,'a+') as f:
88-
f.write(self.file_format)
53+
self.file_format += "%s = <value>\n" % option
8954

9055
# Load the config file
91-
configparser.ConfigParser.__init__(self, defaults=defaults, interpolation=EnvInterpolation())
92-
self.read(config_path) #read all files in the config path if it is a list (self.config_path only contains one string)
56+
configparser.ConfigParser.__init__(
57+
self, defaults=defaults, interpolation=EnvInterpolation()
58+
)
59+
# read all files in the config path if it is a list (self.config_path only
60+
# contains one string):
61+
self.read(config_path)
9362

9463
try:
9564
for section, options in required_params.items():
9665
for option in options:
97-
self.get(section,option)
98-
99-
except configparser.NoOptionError as e:
100-
raise Exception('The experiment configuration file located at %s does not have the required keys. Make sure the config file containes the following structure:\n%s'%(config_path, self.file_format))
101-
102-
103-
# Overwrite the add_section method to only attempt to add a section if it doesn't
104-
# exist. We don't ever care whether a section exists or not, only that it does exist
105-
# when we try and save an attribute into it.
106-
def add_section(self,section):
107-
# Create the group if it doesn't exist
108-
if not section.lower() == 'default' and not self.has_section(section):
109-
configparser.ConfigParser.add_section(self, section)
110-
111-
# Overwrite the set method so that it adds the section if it doesn't exist,
112-
# and immediately saves the data to the file (to avoid data loss on program crash)
113-
def set(self, section, option, value):
114-
self.add_section(section)
115-
configparser.ConfigParser.set(self,section,option,value)
116-
self.save()
117-
118-
# Overwrite the remove section function so that it immediately saves the change to disk
119-
def remove_section(self,section):
120-
configparser.ConfigParser.remove_section(self,section)
121-
self.save()
122-
123-
# Overwrite the remove option function so that it immediately saves the change to disk
124-
def remove_option(self,section,option):
125-
configparser.ConfigParser.remove_option(self,section,option)
126-
self.save()
127-
128-
# Provide a convenience method to save the contents of the ConfigParser to disk
129-
def save(self):
130-
with open(self.config_path, 'w+') as f:
131-
self.write(f)
66+
self.get(section, option)
67+
except configparser.NoOptionError:
68+
msg = f"""The experiment configuration file located at {config_path} does
69+
not have the required keys. Make sure the config file containes the
70+
following structure:\n{self.file_format}"""
71+
raise Exception(dedent(msg))

0 commit comments

Comments
 (0)