Skip to content

Commit b13d051

Browse files
committed
finished command line tool lightlab config
1 parent 33591db commit b13d051

File tree

5 files changed

+355
-113
lines changed

5 files changed

+355
-113
lines changed

.coveragerc

+1
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ omit = lightlab/equipment/lab_instruments/*
44
[report]
55
skip_covered = True
66
omit = lightlab/equipment/lab_instruments/*
7+
show_missing = True

lightlab/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,5 @@ def log_visa_to_screen(level=WARNING):
3333

3434
log_to_screen(INFO)
3535
log_visa_to_screen(WARNING)
36+
37+
import lightlab.util.config as config # noqa

lightlab/command_line.py

+2-113
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,5 @@
1-
import os
2-
from configparser import ConfigParser, NoSectionError
3-
from pathlib import Path
4-
5-
user_config_dir = os.path.expanduser("~") + "/.lightlab"
6-
user_config_path = user_config_dir + "/config.ini"
7-
user_config_path = Path(user_config_path).resolve()
8-
91
import argparse
2+
from lightlab.util.config import config_main
103

114
parser = argparse.ArgumentParser(description="lightlab configuration tool")
125
parser.add_argument('command', type=str, choices=['labstate', 'config'],
@@ -28,108 +21,4 @@ def main():
2821

2922

3023
def labstate_main(args):
31-
print("labstate", labstate_parser.parse_args(args))
32-
33-
34-
config_cmd_parser = argparse.ArgumentParser(
35-
prog="lightlab config", formatter_class=argparse.RawTextHelpFormatter)
36-
config_cmd_parser.add_argument('action', action='store', type=str,
37-
help="write-default: write default configuration\n"
38-
"get [a.b [a2.b2]]: get configuration values\n"
39-
"set a.b c: set configuration value\n"
40-
"unset a.b: unset configuration value\n", nargs='?',
41-
choices=("write-default", "get", "set", "unset"), metavar="command")
42-
config_cmd_parser.add_argument('params', nargs=argparse.REMAINDER)
43-
44-
45-
default_config = {"labstate": {'filepath': '~/.lightlab/labstate.json'}}
46-
47-
48-
def write_default_config():
49-
config = ConfigParser()
50-
config.read_dict(default_config)
51-
with open(user_config_path, 'w') as user_config_file:
52-
config.write(user_config_file)
53-
54-
55-
def get_config():
56-
if not os.path.isfile(user_config_path):
57-
os.makedirs(user_config_dir, exist_ok=True)
58-
user_config_path.touch()
59-
60-
config = ConfigParser()
61-
config.read_dict(default_config) # Read default first
62-
config.read(user_config_path)
63-
return config
64-
65-
66-
def parse_param(param):
67-
if not param:
68-
return (None, None)
69-
split_param = param.split(".")
70-
section, item = None, None
71-
if len(split_param) > 0:
72-
section = split_param[0] if split_param[0] else None
73-
if len(split_param) > 1:
74-
item = split_param[1] if split_param[1] else None
75-
return (section, item)
76-
77-
78-
def get_config_param(param, config):
79-
section, item = parse_param(param)
80-
if section is not None and item is not None:
81-
gotten_param = config.get(section, item)
82-
print(f"{section}.{item}: {gotten_param}")
83-
elif section is not None and item is None:
84-
for key, value in config[section].items():
85-
print(f"{section}.{key}: {value}")
86-
else:
87-
for section in config.sections():
88-
for key, value in config[section].items():
89-
print(f"{section}.{key}: {value}")
90-
return False
91-
92-
93-
def config_main(args):
94-
config_args = config_cmd_parser.parse_args(args)
95-
params = config_args.params
96-
config = get_config()
97-
if config_args.action == 'write-default':
98-
write_default_config()
99-
print("Default config printed.")
100-
elif config_args.action == 'get':
101-
if len(params) > 0:
102-
for param in params:
103-
get_config_param(param, config)
104-
else:
105-
get_config_param(None, config)
106-
elif config_args.action == 'set':
107-
if len(params) == 2:
108-
param = params[0]
109-
set_value = params[1]
110-
section, item = parse_param(param)
111-
if section not in config:
112-
config[section] = {}
113-
config[section][item] = set_value
114-
else:
115-
raise RuntimeError(f"Invalid syntax. Use lightlab config set section.item value.")
116-
with open(user_config_path, 'w') as user_config_file:
117-
config.write(user_config_file)
118-
elif config_args.action == 'unset':
119-
if len(params) == 1:
120-
param = params[0]
121-
section, item = parse_param(param)
122-
if section and item:
123-
try:
124-
success = config.remove_option(section, item)
125-
except NoSectionError:
126-
success = False
127-
elif section:
128-
success = config.remove_section(section)
129-
print(f"{section}.{item} unset", "successfully" if success else "unsuccessfully")
130-
else:
131-
raise RuntimeError(f"Invalid syntax. Use lightlab config unset section.item")
132-
with open(user_config_path, 'w') as user_config_file:
133-
config.write(user_config_file)
134-
else:
135-
config_cmd_parser.print_help()
24+
print("labstate feature not yet implemented")

lightlab/util/config.py

+180
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
import os
2+
import sys
3+
from configparser import ConfigParser
4+
from pathlib import Path
5+
import argparse
6+
7+
user_config_dir = os.path.expanduser("~") + "/.lightlab"
8+
user_config_path = user_config_dir + "/config.conf"
9+
user_config_path = Path(user_config_path).resolve()
10+
11+
default_config = {"labstate": {'filepath': '~/.lightlab/labstate.json'}}
12+
13+
14+
def write_default_config():
15+
config = ConfigParser()
16+
config.read_dict(default_config)
17+
with open(user_config_path, 'w') as user_config_file:
18+
config.write(user_config_file)
19+
20+
21+
def get_config():
22+
config = ConfigParser()
23+
config.read_dict(default_config) # Read default first
24+
if os.path.isfile(user_config_path):
25+
config.read(user_config_path)
26+
return config
27+
28+
29+
def parse_param(param):
30+
if not param:
31+
return (None, None)
32+
split_param = param.split(".")
33+
section, item = None, None
34+
if len(split_param) > 0:
35+
section = split_param[0] if split_param[0] else None
36+
if len(split_param) > 1:
37+
item = split_param[1] if split_param[1] else None
38+
return (section, item)
39+
40+
41+
class InvalidSection(RuntimeError):
42+
pass
43+
44+
45+
class InvalidOption(RuntimeError):
46+
pass
47+
48+
49+
def validate_param(section, option):
50+
if section is not None and section not in default_config.keys():
51+
raise InvalidSection(f"Unknown section {section}")
52+
if option is not None and option not in default_config[section].keys():
53+
raise InvalidOption(f"Unknown option {option}")
54+
if section is None or option is None:
55+
return False
56+
return True
57+
58+
59+
def get_config_param(param):
60+
config = get_config()
61+
section, item = parse_param(param)
62+
if validate_param(section, item):
63+
return config.get(section, item)
64+
else:
65+
raise InvalidOption(param)
66+
67+
68+
def print_config_param(param):
69+
config = get_config()
70+
section, item = parse_param(param)
71+
72+
# raise exception if section or item are invalid
73+
validate_param(section, item)
74+
75+
if section is not None and item is not None:
76+
gotten_param = get_config_param(param)
77+
print(f"{section}.{item}: {gotten_param}")
78+
elif section is not None and item is None:
79+
for key, value in config[section].items():
80+
print(f"{section}.{key}: {value}")
81+
else:
82+
for section in config.sections():
83+
for key, value in config[section].items():
84+
print(f"{section}.{key}: {value}")
85+
return False
86+
87+
88+
def set_config_param(param, value):
89+
config = get_config()
90+
section, item = parse_param(param)
91+
if validate_param(section, item):
92+
config[section][item] = value
93+
else:
94+
raise InvalidOption(f"Cannot set '{param}'")
95+
config_save(config)
96+
return config
97+
98+
99+
def reset_config_param(param):
100+
config = get_config()
101+
section, item = parse_param(param)
102+
validate_param(section, item)
103+
if section is not None and item is not None:
104+
config.remove_option(section, item)
105+
print(f"{section}.{item} reset.")
106+
elif section is not None and item is None:
107+
config.remove_section(section)
108+
print(f"{section}.* reset.")
109+
config_save(config)
110+
return config
111+
112+
113+
def config_save(config):
114+
# remove all items that are default
115+
unset_items = []
116+
for section in config.sections():
117+
if section in default_config.keys():
118+
for option in config[section].keys():
119+
if option in default_config[section].keys():
120+
if config[section][option] == default_config[section][option]:
121+
unset_items.append((section, option))
122+
for section, item in unset_items:
123+
config.remove_option(section, item)
124+
125+
# remove all sections that are default
126+
unset_sections = []
127+
for section in config.sections():
128+
if len(config[section].keys()) == 0:
129+
unset_sections.append(section)
130+
for section in unset_sections:
131+
config.remove_section(section)
132+
133+
if not os.path.isfile(user_config_path):
134+
os.makedirs(user_config_dir, exist_ok=True)
135+
user_config_path.touch()
136+
137+
with open(user_config_path, 'w') as user_config_file:
138+
config.write(user_config_file)
139+
print(f'----saving {user_config_path}-----', file=sys.stderr)
140+
config.write(sys.stderr)
141+
print(f'----------------------------------', file=sys.stderr)
142+
return True
143+
144+
145+
config_cmd_parser = argparse.ArgumentParser(
146+
prog="lightlab config", formatter_class=argparse.RawTextHelpFormatter)
147+
config_cmd_parser.add_argument('action', action='store', type=str,
148+
help="write-default: write default configuration\n"
149+
"get [a.b [a2.b2]]: get configuration values\n"
150+
"set a.b c: set configuration value\n"
151+
"unset a.b: unset configuration value\n", nargs='?',
152+
choices=("write-default", "get", "set", "reset"), metavar="command")
153+
config_cmd_parser.add_argument('params', nargs=argparse.REMAINDER)
154+
155+
156+
def config_main(args):
157+
config_args = config_cmd_parser.parse_args(args)
158+
params = config_args.params
159+
if config_args.action == 'write-default':
160+
write_default_config()
161+
print("Default config written.")
162+
elif config_args.action == 'get':
163+
if len(params) > 0:
164+
for param in params:
165+
print_config_param(param)
166+
else:
167+
print_config_param(None)
168+
elif config_args.action == 'set':
169+
if len(params) == 2:
170+
param = params[0]
171+
set_value = params[1]
172+
set_config_param(param, set_value)
173+
else:
174+
raise RuntimeError(f"Invalid syntax. Use lightlab config set section.item value.")
175+
elif config_args.action == 'reset':
176+
if len(params) == 1:
177+
param = params[0]
178+
reset_config_param(param)
179+
else:
180+
raise RuntimeError(f"Invalid syntax. Use lightlab config unset section.item")

0 commit comments

Comments
 (0)