|
10 | 10 | # for the full license. #
|
11 | 11 | # #
|
12 | 12 | #####################################################################
|
13 |
| -import sys |
14 | 13 | import os
|
15 | 14 | import configparser
|
| 15 | +from ast import literal_eval |
| 16 | +from pprint import pformat |
| 17 | +from pathlib import Path |
16 | 18 |
|
17 | 19 | from labscript_utils import dedent
|
18 | 20 | from labscript_profile import default_labconfig_path, LABSCRIPT_SUITE_PROFILE
|
@@ -69,3 +71,45 @@ def __init__(
|
69 | 71 | not have the required keys. Make sure the config file containes the
|
70 | 72 | following structure:\n{self.file_format}"""
|
71 | 73 | 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