Skip to content

Commit 6a7f805

Browse files
authored
Merge pull request #63 from edanalytics/feature/cli_yaml_overrides
adds a `--set` flag to the CLI to enable overriding config values in `lightbeam.yml`
2 parents 5ed3a74 + bc42410 commit 6a7f805

2 files changed

Lines changed: 52 additions & 3 deletions

File tree

lightbeam/__main__.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,11 @@ def main(argv=None):
108108
type=str,
109109
help='produces a JSON output file with structured information about run results'
110110
)
111+
parser.add_argument("--set",
112+
type=str,
113+
nargs="*",
114+
help='overrides a setting in the config YAML; example: --set fetch.page_size 1000'
115+
)
111116

112117
defaults = { "selector":"*", "params": "", "older_than": "", "newer_than": "", "resend_status_codes": "", "results_file": "" }
113118
parser.set_defaults(**defaults)
@@ -143,6 +148,12 @@ def main(argv=None):
143148

144149
if not args.config_file:
145150
logger.error("config file not specified with `-c` flag, and no default {" + ", ".join(DEFAULT_CONFIG_FILES) + "} found")
151+
152+
if args.set and len(args.set)%2 != 0: # odd number of overrides
153+
logger.error("overrides specified with --set must be followed by an even number of strings (key value key value ...)")
154+
overrides = None
155+
if args.set:
156+
overrides = dict(zip(args.set[::2], args.set[1::2]))
146157

147158
lb = Lightbeam(
148159
config_file=args.config_file,
@@ -158,7 +169,8 @@ def main(argv=None):
158169
older_than=args.older_than,
159170
newer_than=args.newer_than,
160171
resend_status_codes=args.resend_status_codes,
161-
results_file=args.results_file
172+
results_file=args.results_file,
173+
overrides=overrides,
162174
)
163175
try:
164176
logger.info("starting...")

lightbeam/lightbeam.py

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ class Lightbeam:
5555
MAX_STATUS_REASONS_TO_DISPLAY = 10
5656
DATA_FILE_EXTENSIONS = ['json', 'jsonl', 'ndjson']
5757

58-
def __init__(self, config_file, logger=None, selector="*", exclude="", keep_keys="*", drop_keys="", query="{}", params="", wipe=False, force=False, older_than="", newer_than="", resend_status_codes="", results_file=""):
58+
def __init__(self, config_file, logger=None, selector="*", exclude="", keep_keys="*", drop_keys="", query="{}", params="", wipe=False, force=False, older_than="", newer_than="", resend_status_codes="", results_file="", overrides={}):
5959
self.config_file = config_file
6060
self.logger = logger
6161
self.errors = 0
@@ -82,12 +82,16 @@ def __init__(self, config_file, logger=None, selector="*", exclude="", keep_keys
8282
self.token_version = 0
8383
self.results_file = os.path.abspath(results_file) if results_file else None
8484
self.start_timestamp = datetime.now()
85+
self.overrides = overrides
8586

8687
# load params and/or env vars for config YAML interpolation
8788
self.params = json.loads(params) if params else {}
8889
user_config = self.load_config_file()
89-
9090
self.config = util.merge_dicts(user_config, self.config_defaults)
91+
92+
# inject overrides into config
93+
if self.overrides: self.inject_cli_overrides()
94+
9195
if "state_dir" in self.config:
9296
self.track_state = True
9397
self.config["state_dir"] = os.path.expanduser(self.config["state_dir"])
@@ -129,6 +133,39 @@ def __init__(self, config_file, logger=None, selector="*", exclude="", keep_keys
129133
"resources": {}
130134
}
131135

136+
def inject_cli_overrides(self):
137+
# parse self.overrides into configs:
138+
for key, value in self.overrides.items():
139+
self.config = Lightbeam.set_path(self.config, key, value)
140+
141+
@staticmethod
142+
def set_path(my_dict, path, value):
143+
path_pieces = path.split(".")
144+
current = my_dict
145+
for path_piece in path_pieces[:-1]:
146+
if path_piece not in current.keys():
147+
current[path_piece] = {}
148+
current = current[path_piece]
149+
current[path_pieces[-1]] = Lightbeam.autocast(value)
150+
return my_dict
151+
152+
@staticmethod
153+
def autocast(value):
154+
if value.lower() in ['true', 'yes', 'on', 't', 'y']:
155+
return True
156+
elif value.lower() in ['false', 'no', 'off', 'f', 'n']:
157+
return False
158+
elif '.' in value:
159+
try:
160+
return float(value)
161+
except ValueError:
162+
return value
163+
else:
164+
try:
165+
return int(value)
166+
except ValueError:
167+
return value
168+
132169
# this is intended to be called before any CRITICAL errors;
133170
# any cleanup tasks should go here:
134171
def shutdown(self, method):

0 commit comments

Comments
 (0)