Selaa lähdekoodia

Factor out schema type comparion in config generation and get several tests passing (#303).

Dan Helfman 2 kuukautta sitten
vanhempi
sitoutus
57721937a3

+ 1 - 0
borgmatic/commands/arguments.py

@@ -297,6 +297,7 @@ def make_argument_description(schema, flag_name):
     an example or additional information as appropriate based on its type. Return the updated
     description for use in a command-line argument.
     '''
+    # FIXME: Argument descriptions are apparently broken right now.
     description = schema.get('description')
     schema_type = schema.get('type')
 

+ 4 - 8
borgmatic/config/generate.py

@@ -36,10 +36,10 @@ def schema_to_sample_configuration(schema, source_config=None, level=0, parent_i
     schema_type = schema.get('type')
     example = schema.get('example')
 
-    if schema_type == 'array' or (isinstance(schema_type, list) and 'array' in schema_type):
+    if borgmatic.config.schema.compare_types(schema_type, {'array'}):
         config = ruamel.yaml.comments.CommentedSeq(
             example
-            if schema['items'].get('type') in SCALAR_SCHEMA_TYPES
+            if borgmatic.config.schema.compare_types(schema['items'].get('type'), SCALAR_SCHEMA_TYPES)
             else [
                 schema_to_sample_configuration(
                     schema['items'], source_config, level, parent_is_sequence=True
@@ -47,7 +47,7 @@ def schema_to_sample_configuration(schema, source_config=None, level=0, parent_i
             ]
         )
         add_comments_to_configuration_sequence(config, schema, indent=(level * INDENT))
-    elif schema_type == 'object' or (isinstance(schema_type, list) and 'object' in schema_type):
+    elif borgmatic.config.schema.compare_types(schema_type, {'object'}):
         if source_config and isinstance(source_config, list) and isinstance(source_config[0], dict):
             source_config = dict(collections.ChainMap(*source_config))
 
@@ -66,11 +66,7 @@ def schema_to_sample_configuration(schema, source_config=None, level=0, parent_i
         add_comments_to_configuration_object(
             config, schema, source_config, indent=indent, skip_first=parent_is_sequence
         )
-    elif isinstance(schema_type, list) and all(
-        element_schema_type in SCALAR_SCHEMA_TYPES for element_schema_type in schema_type
-    ):
-        return example
-    elif schema_type in SCALAR_SCHEMA_TYPES:
+    elif borgmatic.config.schema.compare_types(schema_type, SCALAR_SCHEMA_TYPES, match=all):
         return example
     else:
         raise ValueError(f'Schema at level {level} is unsupported: {schema}')

+ 22 - 0
borgmatic/config/schema.py

@@ -39,3 +39,25 @@ def parse_type(schema_type):
         }[schema_type]
     except KeyError:
         raise ValueError(f'Unknown type in configuration schema: {schema_type}')
+
+
+def compare_types(schema_type, target_types, match=any):
+    '''
+    Given a schema type as a string or a list of strings (representing multiple types) and a set of
+    target type strings, return whether every schema type is in the set of target types.
+
+    If the schema type is a list of strings, use the given match function (such as any or all) to
+    compare elements.
+    '''
+    if isinstance(schema_type, list):
+        if match(
+            element_schema_type in target_types for element_schema_type in schema_type
+        ):
+            return True
+
+        return False
+
+    if schema_type in target_types:
+        return True
+
+    return False

+ 20 - 8
tests/unit/config/test_generate.py

@@ -2,6 +2,7 @@ import pytest
 from flexmock import flexmock
 
 from borgmatic.config import generate as module
+import borgmatic.config.schema
 
 
 def test_schema_to_sample_configuration_generates_config_map_with_examples():
@@ -9,13 +10,16 @@ def test_schema_to_sample_configuration_generates_config_map_with_examples():
         'type': 'object',
         'properties': dict(
             [
-                ('field1', {'example': 'Example 1'}),
-                ('field2', {'example': 'Example 2'}),
-                ('field3', {'example': 'Example 3'}),
+                ('field1', {'type': 'string', 'example': 'Example 1'}),
+                ('field2', {'type': 'string', 'example': 'Example 2'}),
+                ('field3', {'type': 'string', 'example': 'Example 3'}),
             ]
         ),
     }
-    flexmock(module).should_receive('get_properties').and_return(schema['properties'])
+    flexmock(module.borgmatic.config.schema).should_receive('compare_types').and_return(False)
+    flexmock(module.borgmatic.config.schema).should_receive('compare_types').with_args('object', {'object'}).and_return(True)
+    flexmock(module.borgmatic.config.schema).should_receive('compare_types').with_args('string', module.SCALAR_SCHEMA_TYPES, match=all).and_return(True)
+    flexmock(module.borgmatic.config.schema).should_receive('get_properties').and_return(schema['properties'])
     flexmock(module.ruamel.yaml.comments).should_receive('CommentedMap').replace_with(dict)
     flexmock(module).should_receive('add_comments_to_configuration_object')
 
@@ -46,11 +50,15 @@ def test_schema_to_sample_configuration_generates_config_sequence_of_maps_with_e
         'items': {
             'type': 'object',
             'properties': dict(
-                [('field1', {'example': 'Example 1'}), ('field2', {'example': 'Example 2'})]
+                [('field1', {'type': 'string', 'example': 'Example 1'}), ('field2', {'type': 'string', 'example': 'Example 2'})]
             ),
         },
     }
-    flexmock(module).should_receive('get_properties').and_return(schema['items']['properties'])
+    flexmock(module.borgmatic.config.schema).should_receive('compare_types').and_return(False)
+    flexmock(module.borgmatic.config.schema).should_receive('compare_types').with_args('array', {'array'}).and_return(True)
+    flexmock(module.borgmatic.config.schema).should_receive('compare_types').with_args('object', {'object'}).and_return(True)
+    flexmock(module.borgmatic.config.schema).should_receive('compare_types').with_args('string', module.SCALAR_SCHEMA_TYPES, match=all).and_return(True)
+    flexmock(module.borgmatic.config.schema).should_receive('get_properties').and_return(schema['items']['properties'])
     flexmock(module.ruamel.yaml.comments).should_receive('CommentedSeq').replace_with(list)
     flexmock(module).should_receive('add_comments_to_configuration_sequence')
     flexmock(module).should_receive('add_comments_to_configuration_object')
@@ -66,11 +74,15 @@ def test_schema_to_sample_configuration_generates_config_sequence_of_maps_with_m
         'items': {
             'type': ['object', 'null'],
             'properties': dict(
-                [('field1', {'example': 'Example 1'}), ('field2', {'example': 'Example 2'})]
+                [('field1', {'type': 'string', 'example': 'Example 1'}), ('field2', {'type': 'string', 'example': 'Example 2'})]
             ),
         },
     }
-    flexmock(module).should_receive('get_properties').and_return(schema['items']['properties'])
+    flexmock(module.borgmatic.config.schema).should_receive('compare_types').and_return(False)
+    flexmock(module.borgmatic.config.schema).should_receive('compare_types').with_args('array', {'array'}).and_return(True)
+    flexmock(module.borgmatic.config.schema).should_receive('compare_types').with_args(['object', 'null'], {'object'}).and_return(True)
+    flexmock(module.borgmatic.config.schema).should_receive('compare_types').with_args('string', module.SCALAR_SCHEMA_TYPES, match=all).and_return(True)
+    flexmock(module.borgmatic.config.schema).should_receive('get_properties').and_return(schema['items']['properties'])
     flexmock(module.ruamel.yaml.comments).should_receive('CommentedSeq').replace_with(list)
     flexmock(module).should_receive('add_comments_to_configuration_sequence')
     flexmock(module).should_receive('add_comments_to_configuration_object')