Jelajahi Sumber

Make config validation error messages more consistent.

Signed-off-by: Daniel Nephin <[email protected]>
Daniel Nephin 10 tahun lalu
induk
melakukan
ea8032c115
3 mengubah file dengan 29 tambahan dan 27 penghapusan
  1. 16 17
      compose/config/validation.py
  2. 1 1
      tests/acceptance/cli_test.py
  3. 12 9
      tests/unit/config/config_test.py

+ 16 - 17
compose/config/validation.py

@@ -111,30 +111,29 @@ def validate_config_section(filename, config, section):
     """
     if not isinstance(config, dict):
         raise ConfigurationError(
-            "In file '{filename}' {section} must be a mapping, not "
-            "'{type}'.".format(
+            "In file '{filename}', {section} must be a mapping, not "
+            "{type}.".format(
                 filename=filename,
                 section=section,
-                type=python_type_to_yaml_type(config)))
+                type=anglicize_json_type(python_type_to_yaml_type(config))))
 
     for key, value in config.items():
         if not isinstance(key, six.string_types):
             raise ConfigurationError(
-                "In file '{filename}' {section} name {name} needs to be a "
-                "string, eg '{name}'".format(
+                "In file '{filename}', the {section} name {name} must be a "
+                "quoted string, i.e. '{name}'.".format(
                     filename=filename,
                     section=section,
                     name=key))
 
         if not isinstance(value, (dict, type(None))):
             raise ConfigurationError(
-                "In file '{filename}' {section} '{name}' is the wrong type. "
-                "It should be a mapping of configuration options, it is a "
-                "'{type}'.".format(
+                "In file '{filename}', {section} '{name}' must be a mapping not "
+                "{type}.".format(
                     filename=filename,
                     section=section,
                     name=key,
-                    type=python_type_to_yaml_type(value)))
+                    type=anglicize_json_type(python_type_to_yaml_type(value))))
 
 
 def validate_top_level_object(config_file):
@@ -203,10 +202,10 @@ def get_unsupported_config_msg(path, error_key):
     return msg
 
 
-def anglicize_validator(validator):
-    if validator in ["array", "object"]:
-        return 'an ' + validator
-    return 'a ' + validator
+def anglicize_json_type(json_type):
+    if json_type.startswith(('a', 'e', 'i', 'o', 'u')):
+        return 'an ' + json_type
+    return 'a ' + json_type
 
 
 def is_service_dict_schema(schema_id):
@@ -314,14 +313,14 @@ def _parse_valid_types_from_validator(validator):
     a valid type. Parse the valid types and prefix with the correct article.
     """
     if not isinstance(validator, list):
-        return anglicize_validator(validator)
+        return anglicize_json_type(validator)
 
     if len(validator) == 1:
-        return anglicize_validator(validator[0])
+        return anglicize_json_type(validator[0])
 
     return "{}, or {}".format(
-        ", ".join([anglicize_validator(validator[0])] + validator[1:-1]),
-        anglicize_validator(validator[-1]))
+        ", ".join([anglicize_json_type(validator[0])] + validator[1:-1]),
+        anglicize_json_type(validator[-1]))
 
 
 def _parse_oneof_validator(error):

+ 1 - 1
tests/acceptance/cli_test.py

@@ -159,7 +159,7 @@ class CLITestCase(DockerClientTestCase):
             '-f', 'tests/fixtures/invalid-composefile/invalid.yml',
             'config', '-q'
         ], returncode=1)
-        assert "'notaservice' is the wrong type" in result.stderr
+        assert "'notaservice' must be a mapping" in result.stderr
 
     # TODO: this shouldn't be v2-dependent
     @v2_only()

+ 12 - 9
tests/unit/config/config_test.py

@@ -268,7 +268,7 @@ class ConfigTest(unittest.TestCase):
         })
         with pytest.raises(ConfigurationError) as exc:
             config.load(config_details)
-        assert "volume must be a mapping, not 'array'" in exc.exconly()
+        assert "volume must be a mapping, not an array" in exc.exconly()
 
     def test_networks_invalid_type_list(self):
         config_details = build_config_details({
@@ -280,7 +280,7 @@ class ConfigTest(unittest.TestCase):
         })
         with pytest.raises(ConfigurationError) as exc:
             config.load(config_details)
-        assert "network must be a mapping, not 'array'" in exc.exconly()
+        assert "network must be a mapping, not an array" in exc.exconly()
 
     def test_load_service_with_name_version(self):
         with mock.patch('compose.config.config.log') as mock_logging:
@@ -392,8 +392,7 @@ class ConfigTest(unittest.TestCase):
             'filename.yml')
         with pytest.raises(ConfigurationError) as exc:
             config.load(config_details)
-        error_msg = "service 'web' is the wrong type"
-        assert error_msg in exc.exconly()
+        assert "service 'web' must be a mapping not a string." in exc.exconly()
 
     def test_config_integer_service_name_raise_validation_error(self):
         with pytest.raises(ConfigurationError) as excinfo:
@@ -405,8 +404,10 @@ class ConfigTest(unittest.TestCase):
                 )
             )
 
-        assert "In file 'filename.yml' service name 1 needs to be a string, eg '1'" \
-            in excinfo.exconly()
+        assert (
+            "In file 'filename.yml', the service name 1 must be a quoted string, i.e. '1'" in
+            excinfo.exconly()
+        )
 
     def test_config_integer_service_name_raise_validation_error_v2(self):
         with pytest.raises(ConfigurationError) as excinfo:
@@ -421,8 +422,10 @@ class ConfigTest(unittest.TestCase):
                 )
             )
 
-        assert "In file 'filename.yml' service name 1 needs to be a string, eg '1'" \
-            in excinfo.exconly()
+        assert (
+            "In file 'filename.yml', the service name 1 must be a quoted string, i.e. '1'." in
+            excinfo.exconly()
+        )
 
     def test_load_with_multiple_files_v1(self):
         base_file = config.ConfigFile(
@@ -556,7 +559,7 @@ class ConfigTest(unittest.TestCase):
 
         with pytest.raises(ConfigurationError) as exc:
             config.load(details)
-        assert "service 'bogus' is the wrong type" in exc.exconly()
+        assert "service 'bogus' must be a mapping not a string." in exc.exconly()
         assert "In file 'override.yaml'" in exc.exconly()
 
     def test_load_sorts_in_dependency_order(self):