diff --git a/readthedocs/config/config.py b/readthedocs/config/config.py index eb745d03c7f..b3d6b8aa875 100644 --- a/readthedocs/config/config.py +++ b/readthedocs/config/config.py @@ -114,12 +114,19 @@ def __init__(self, key, code, error_message, source_file=None): self.code = code self.source_file = source_file message = self.message_template.format( - key=key, + key=self._get_display_key(), code=code, error=error_message, ) super().__init__(message, code=code) + def _get_display_key(self): + # Checks for patterns similar to `python.install.0.requirements` + # if matched change to `python.install[0].requirements` using backreference. + return re.sub( + r'^(python\.install)(\.)(\d+)(\.\w+)$', r'\1[\3]\4', self.key + ) + class BuildConfigBase: diff --git a/readthedocs/config/tests/test_config.py b/readthedocs/config/tests/test_config.py index 5769b5ceb8d..51befd21bef 100644 --- a/readthedocs/config/tests/test_config.py +++ b/readthedocs/config/tests/test_config.py @@ -1098,6 +1098,23 @@ def test_python_install_requirements_does_not_allow_null(self, tmpdir): build.validate() assert excinfo.value.key == 'python.install.0.requirements' + def test_python_install_requirements_error_msg(self, tmpdir): + build = self.get_build_config( + { + 'python': { + 'install': [{ + 'path': '.', + 'requirements': None, + }], + }, + }, + source_file=str(tmpdir.join('readthedocs.yml')), + ) + with raises(InvalidConfig) as excinfo: + build.validate() + + assert str(excinfo.value) == 'Invalid "python.install[0].requirements": expected string' + def test_python_install_requirements_does_not_allow_empty_string(self, tmpdir): build = self.get_build_config( {