Skip to content

Commit dc7833a

Browse files
Merge pull request #48 from chrisjbillington/save-load-appconfig
Add `labconfig.{save,load}_appconfig()`
2 parents 8111c28 + 69bcbbd commit dc7833a

File tree

1 file changed

+45
-1
lines changed

1 file changed

+45
-1
lines changed

labscript_utils/labconfig.py

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@
1010
# for the full license. #
1111
# #
1212
#####################################################################
13-
import sys
1413
import os
1514
import configparser
15+
from ast import literal_eval
16+
from pprint import pformat
17+
from pathlib import Path
1618

1719
from labscript_utils import dedent
1820
from labscript_profile import default_labconfig_path, LABSCRIPT_SUITE_PROFILE
@@ -69,3 +71,45 @@ def __init__(
6971
not have the required keys. Make sure the config file containes the
7072
following structure:\n{self.file_format}"""
7173
raise Exception(dedent(msg))
74+
75+
76+
def save_appconfig(filename, data):
77+
"""Save a dictionary as an ini file. The keys of the dictionary comprise the section
78+
names, and the values must themselves be dictionaries for the names and values
79+
within each section. All section values will be converted to strings with
80+
pprint.pformat()."""
81+
# Error checking
82+
for section_name, section in data.items():
83+
for name, value in section.items():
84+
try:
85+
valid = value == literal_eval(pformat(value))
86+
except (ValueError, SyntaxError):
87+
valid = False
88+
if not valid:
89+
msg = f"{section_name}/{name} value {value} not a Python built-in type"
90+
raise TypeError(msg)
91+
data = {
92+
section_name: {name: pformat(value) for name, value in section.items()}
93+
for section_name, section in data.items()
94+
}
95+
c = configparser.ConfigParser(interpolation=None)
96+
c.optionxform = str # preserve case
97+
c.read_dict(data)
98+
Path(filename).parent.mkdir(parents=True, exist_ok=True)
99+
with open(filename, 'w') as f:
100+
c.write(f)
101+
102+
103+
def load_appconfig(filename):
104+
"""Load an .ini file and return a dictionary of its contents. All values will be
105+
converted to Python objects with ast.literal_eval(). All keys will be lowercase
106+
regardless of the written contents on the .ini file."""
107+
c = configparser.ConfigParser(interpolation=None)
108+
c.optionxform = str # preserve case
109+
# No file? No config - don't crash.
110+
if Path(filename).exists():
111+
c.read(filename)
112+
return {
113+
section_name: {name: literal_eval(value) for name, value in section.items()}
114+
for section_name, section in c.items()
115+
}

0 commit comments

Comments
 (0)