mirror of
https://github.com/borgmatic-collective/borgmatic.git
synced 2026-07-29 21:03:02 +02:00
Expose propertyless YAML objects from configuration (e.g. "constants") as command-line flags (#303).
This commit is contained in:
@@ -307,7 +307,7 @@ def make_argument_description(schema, flag_name):
|
||||
if '[0]' in flag_name:
|
||||
description += ' To specify a different list element, replace the "[0]" with another array index ("[1]", "[2]", etc.).'
|
||||
|
||||
if example and schema_type == 'array':
|
||||
if example and schema_type in ('array', 'object'):
|
||||
example_buffer = io.StringIO()
|
||||
yaml = ruamel.yaml.YAML(typ='safe')
|
||||
yaml.default_flow_style = True
|
||||
@@ -453,13 +453,15 @@ def add_arguments_from_schema(arguments_group, schema, unparsed_arguments, names
|
||||
if schema_type == 'object':
|
||||
properties = schema.get('properties')
|
||||
|
||||
# If there are child properties, recurse for each one. But if there are no child properties,
|
||||
# fall through so that a flag gets added below for the (empty) object.
|
||||
if properties:
|
||||
for name, child in properties.items():
|
||||
add_arguments_from_schema(
|
||||
arguments_group, child, unparsed_arguments, names + (name,)
|
||||
)
|
||||
|
||||
return
|
||||
return
|
||||
|
||||
# If this is an "array" type, recurse for each items type child option. Don't return yet so that
|
||||
# a flag also gets added below for the array itself.
|
||||
@@ -485,9 +487,9 @@ def add_arguments_from_schema(arguments_group, schema, unparsed_arguments, names
|
||||
metavar = names[-1].upper()
|
||||
description = make_argument_description(schema, flag_name)
|
||||
|
||||
# array=str instead of list here to support specifying a list as a YAML string on the
|
||||
# The ...=str given here is to support specifying an object or an array as a YAML string on the
|
||||
# command-line.
|
||||
argument_type = borgmatic.config.schema.parse_type(schema_type, array=str)
|
||||
argument_type = borgmatic.config.schema.parse_type(schema_type, object=str, array=str)
|
||||
full_flag_name = f"--{flag_name.replace('_', '-')}"
|
||||
|
||||
# As a UX nicety, allow boolean options that have a default of false to have command-line flags
|
||||
|
||||
@@ -4,6 +4,22 @@ from flexmock import flexmock
|
||||
from borgmatic.commands import arguments as module
|
||||
|
||||
|
||||
def test_make_argument_description_with_object_adds_example():
|
||||
assert (
|
||||
module.make_argument_description(
|
||||
schema={
|
||||
'description': 'Thing.',
|
||||
'type': 'object',
|
||||
'example': {'bar': 'baz'},
|
||||
},
|
||||
flag_name='flag',
|
||||
)
|
||||
# Apparently different versions of ruamel.yaml serialize this
|
||||
# differently.
|
||||
in ('Thing. Example value: "bar: baz"' 'Thing. Example value: "{bar: baz}"')
|
||||
)
|
||||
|
||||
|
||||
def test_make_argument_description_with_array_adds_example():
|
||||
assert (
|
||||
module.make_argument_description(
|
||||
|
||||
@@ -590,6 +590,42 @@ def test_make_argument_description_without_description_bails():
|
||||
)
|
||||
|
||||
|
||||
def test_make_argument_description_with_object_adds_example():
|
||||
buffer = flexmock()
|
||||
buffer.should_receive('getvalue').and_return('{foo: example}')
|
||||
flexmock(module.io).should_receive('StringIO').and_return(buffer)
|
||||
yaml = flexmock()
|
||||
yaml.should_receive('dump')
|
||||
flexmock(module.ruamel.yaml).should_receive('YAML').and_return(yaml)
|
||||
|
||||
assert (
|
||||
module.make_argument_description(
|
||||
schema={
|
||||
'description': 'Thing.',
|
||||
'type': 'object',
|
||||
'example': {'foo': 'example'},
|
||||
},
|
||||
flag_name='flag',
|
||||
)
|
||||
== 'Thing. Example value: "{foo: example}"'
|
||||
)
|
||||
|
||||
|
||||
def test_make_argument_description_with_object_skips_missing_example():
|
||||
flexmock(module.ruamel.yaml).should_receive('YAML').never()
|
||||
|
||||
assert (
|
||||
module.make_argument_description(
|
||||
schema={
|
||||
'description': 'Thing.',
|
||||
'type': 'object',
|
||||
},
|
||||
flag_name='flag',
|
||||
)
|
||||
== 'Thing.'
|
||||
)
|
||||
|
||||
|
||||
def test_make_argument_description_with_array_adds_example():
|
||||
buffer = flexmock()
|
||||
buffer.should_receive('getvalue').and_return('[example]')
|
||||
@@ -612,9 +648,7 @@ def test_make_argument_description_with_array_adds_example():
|
||||
|
||||
|
||||
def test_make_argument_description_with_array_skips_missing_example():
|
||||
yaml = flexmock()
|
||||
yaml.should_receive('dump').and_return('[example]')
|
||||
flexmock(module.ruamel.yaml).should_receive('YAML').and_return(yaml)
|
||||
flexmock(module.ruamel.yaml).should_receive('YAML').never()
|
||||
|
||||
assert (
|
||||
module.make_argument_description(
|
||||
@@ -951,12 +985,17 @@ def test_add_arguments_from_schema_with_empty_multi_type_raises():
|
||||
)
|
||||
|
||||
|
||||
def test_add_arguments_from_schema_with_propertyless_option_does_not_add_flag():
|
||||
def test_add_arguments_from_schema_with_propertyless_option_adds_flag():
|
||||
arguments_group = flexmock()
|
||||
flexmock(module).should_receive('make_argument_description').never()
|
||||
flexmock(module.borgmatic.config.schema).should_receive('parse_type').never()
|
||||
arguments_group.should_receive('add_argument').never()
|
||||
flexmock(module).should_receive('add_array_element_arguments').never()
|
||||
flexmock(module).should_receive('make_argument_description').and_return('help')
|
||||
flexmock(module.borgmatic.config.schema).should_receive('parse_type').and_return(str)
|
||||
arguments_group.should_receive('add_argument').with_args(
|
||||
'--foo',
|
||||
type=str,
|
||||
metavar='FOO',
|
||||
help='help',
|
||||
).once()
|
||||
flexmock(module).should_receive('add_array_element_arguments')
|
||||
|
||||
module.add_arguments_from_schema(
|
||||
arguments_group=arguments_group,
|
||||
|
||||
Reference in New Issue
Block a user