Skip to content

Commit 28aaf19

Browse files
Merge pull request #74 from Paperspace/PS-10842-accept-yaml-instead-of-options
Allow to read options from a file
2 parents 1507bb1 + 495a07d commit 28aaf19

File tree

9 files changed

+374
-90
lines changed

9 files changed

+374
-90
lines changed

Pipfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ click-help-colors = "*"
1818
colorama = "*"
1919
click-completion = "*"
2020
halo = "*"
21+
pyyaml = "*"
2122

2223
[dev-packages]
2324
twine = "*"

Pipfile.lock

Lines changed: 95 additions & 75 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

gradient/cli/common.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,14 @@
22
import json
33

44
import click
5+
import yaml
6+
from click.exceptions import Exit
57
from click_didyoumean import DYMMixin
68
from click_help_colors import HelpColorsGroup
9+
from gradient.cli import cli_types
10+
11+
OPTIONS_FILE_PARAMETER_NAME = "options_file"
12+
713

814
api_key_option = click.option(
915
"--apiKey",
@@ -47,3 +53,77 @@ def decorator(f):
4753
f.invoke = functools.partial(new_invoke, f)
4854

4955
return decorator
56+
57+
58+
def get_option_name(options_strings):
59+
for opt in options_strings:
60+
if not opt.startswith("-"):
61+
return opt
62+
63+
if opt.startswith("--"):
64+
return opt[2:]
65+
66+
67+
class ReadValueFromConfigFile(click.Parameter):
68+
def handle_parse_result(self, ctx, opts, args):
69+
config_file = ctx.params.get(OPTIONS_FILE_PARAMETER_NAME)
70+
if config_file:
71+
with open(config_file) as f:
72+
config_data = yaml.load(f, Loader=yaml.FullLoader)
73+
option_name = get_option_name(self.opts)
74+
value = config_data.get(option_name)
75+
if value is not None:
76+
if isinstance(value, dict):
77+
value = json.dumps(value)
78+
79+
opts[self.name] = value
80+
81+
return super(ReadValueFromConfigFile, self).handle_parse_result(
82+
ctx, opts, args)
83+
84+
85+
class ArgumentReadValueFromConfigFile(ReadValueFromConfigFile, click.Argument):
86+
pass
87+
88+
89+
class OptionReadValueFromConfigFile(ReadValueFromConfigFile, click.Option):
90+
pass
91+
92+
93+
def generate_options_template(ctx, param, value):
94+
if not value:
95+
return value
96+
97+
params = {}
98+
for param in ctx.command.params:
99+
option_name = get_option_name(param.opts)
100+
option_value = ctx.params.get(param.name) or param.default
101+
102+
if isinstance(param.type, cli_types.ChoiceType):
103+
for key, val in param.type.type_map.items():
104+
if val == option_value:
105+
option_value = key
106+
107+
params[option_name] = option_value
108+
109+
with open(value, "w") as f:
110+
yaml.safe_dump(params, f, default_flow_style=False)
111+
112+
raise Exit # to stop execution without executing the command
113+
114+
115+
def options_file(f):
116+
options = [
117+
click.option(
118+
"--optionsFile",
119+
OPTIONS_FILE_PARAMETER_NAME,
120+
help="Path to YAML file with predefined options",
121+
),
122+
click.option(
123+
"--optionsFileTemplate",
124+
callback=generate_options_template,
125+
expose_value=False,
126+
help="Generate template options file"
127+
)
128+
]
129+
return functools.reduce(lambda x, opt: opt(x), reversed(options), f)

0 commit comments

Comments
 (0)