From e3f54d34f59f75d1bcf2637aee6dfa73f5cf90da Mon Sep 17 00:00:00 2001 From: Stefano Chiodino Date: Mon, 13 Aug 2018 19:43:32 +0100 Subject: [PATCH 1/4] Allow for period as a prefix and yaml extension for config file --- readthedocs/config/config.py | 16 +++++--------- readthedocs/config/find.py | 15 ++++++------- readthedocs/config/tests/test_config.py | 28 ++++++++++++++++++++++++- readthedocs/config/tests/test_find.py | 27 ++++++++---------------- 4 files changed, 49 insertions(+), 37 deletions(-) diff --git a/readthedocs/config/config.py b/readthedocs/config/config.py index 10a32f5b945..57f969b7277 100644 --- a/readthedocs/config/config.py +++ b/readthedocs/config/config.py @@ -31,7 +31,7 @@ ) ALL = 'all' -CONFIG_FILENAMES = ('readthedocs.yml', '.readthedocs.yml') +CONFIG_FILENAME_REGEX = r'\.?readthedocs.ya?ml' CONFIG_NOT_SUPPORTED = 'config-not-supported' VERSION_INVALID = 'version-invalid' @@ -48,7 +48,7 @@ DOCKER_DEFAULT_IMAGE = 'readthedocs/build' DOCKER_DEFAULT_VERSION = '2.0' -# These map to coordisponding settings in the .org, +# These map to corresponding settings in the .org, # so they haven't been renamed. DOCKER_IMAGE = '{}:{}'.format(DOCKER_DEFAULT_IMAGE, DOCKER_DEFAULT_VERSION) DOCKER_IMAGE_SETTINGS = { @@ -966,17 +966,11 @@ def load(path, env_config): the version of the configuration a build object would be load and validated, ``BuildConfigV1`` is the default. """ - filename = find_one(path, CONFIG_FILENAMES) + filename = find_one(path, CONFIG_FILENAME_REGEX) if not filename: - files = '{}'.format(', '.join(map(repr, CONFIG_FILENAMES[:-1]))) - if files: - files += ' or ' - files += '{!r}'.format(CONFIG_FILENAMES[-1]) - raise ConfigError( - 'No files {} found'.format(files), - code=CONFIG_REQUIRED, - ) + raise ConfigError('No configuration file found', + code=CONFIG_REQUIRED) build_configs = [] with open(filename, 'r') as configuration_file: try: diff --git a/readthedocs/config/find.py b/readthedocs/config/find.py index df83d098785..e518da13f2c 100644 --- a/readthedocs/config/find.py +++ b/readthedocs/config/find.py @@ -3,20 +3,21 @@ from __future__ import division, print_function, unicode_literals import os +import re -def find_all(path, filenames): - """Find all files in ``path`` that match in ``filenames``.""" +def find_all(path, filename_regex): + """Find all files in ``path`` that match ``filename_regex`` regex.""" path = os.path.abspath(path) for root, dirs, files in os.walk(path, topdown=True): dirs.sort() - for filename in filenames: - if filename in files: + for filename in files: + if re.match(filename_regex, filename): yield os.path.abspath(os.path.join(root, filename)) -def find_one(path, filenames): - """Find the first file in ``path`` that match in ``filenames``.""" - for _path in find_all(path, filenames): +def find_one(path, filename_regex): + """Find the first file in ``path`` that match ``filename_regex`` regex.""" + for _path in find_all(path, filename_regex): return _path return '' diff --git a/readthedocs/config/tests/test_config.py b/readthedocs/config/tests/test_config.py index ddbf59c2eac..a645926eedf 100644 --- a/readthedocs/config/tests/test_config.py +++ b/readthedocs/config/tests/test_config.py @@ -3,6 +3,7 @@ import os import textwrap +import re import pytest from mock import DEFAULT, patch @@ -13,7 +14,7 @@ ConfigOptionNotSupportedError, InvalidConfig, ProjectConfig, load) from readthedocs.config.config import ( CONFIG_NOT_SUPPORTED, NAME_INVALID, NAME_REQUIRED, PYTHON_INVALID, - VERSION_INVALID) + VERSION_INVALID, CONFIG_FILENAME_REGEX) from readthedocs.config.validation import ( INVALID_BOOL, INVALID_CHOICE, INVALID_LIST, INVALID_PATH, INVALID_STRING) @@ -49,6 +50,13 @@ 'nested': minimal_config_dir, } +yaml_extension_config_dir = { + 'readthedocs.yaml': '''\ +name: docs +type: sphinx +''' +} + def get_build_config(config, env_config=None, source_file='readthedocs.yml', source_position=0): @@ -137,6 +145,14 @@ def test_load_unknow_version(tmpdir): assert excinfo.value.code == VERSION_INVALID +def test_yaml_extension(tmpdir): + """ Make sure it's capable of loading the 'readthedocs' file with a 'yaml' extension. """ + apply_fs(tmpdir, yaml_extension_config_dir) + base = str(tmpdir) + config = load(base, env_config) + assert len(config) == 1 + + def test_build_config_has_source_file(tmpdir): base = str(apply_fs(tmpdir, minimal_config_dir)) build = load(base, env_config)[0] @@ -790,6 +806,13 @@ def test_raise_config_not_supported(): assert excinfo.value.code == CONFIG_NOT_SUPPORTED +@pytest.mark.parametrize("correct_config_filename", + [prefix + "readthedocs." + extension for prefix in {"", "."} + for extension in {"yml", "yaml"}]) +def test_config_filenames_regex(correct_config_filename): + assert re.match(CONFIG_FILENAME_REGEX, correct_config_filename) + + class TestBuildConfigV2(object): def get_build_config(self, config, env_config=None, @@ -1620,3 +1643,6 @@ def test_submodules_recursive_explict_default(self): assert build.submodules.include == [] assert build.submodules.exclude == [] assert build.submodules.recursive is False + + + diff --git a/readthedocs/config/tests/test_find.py b/readthedocs/config/tests/test_find.py index 3a74d027fbb..2b3ec530a1b 100644 --- a/readthedocs/config/tests/test_find.py +++ b/readthedocs/config/tests/test_find.py @@ -12,7 +12,7 @@ def test_find_no_files(tmpdir): with tmpdir.as_cwd(): - paths = list(find_all(os.getcwd(), ('readthedocs.yml',))) + paths = list(find_all(os.getcwd(), r'readthedocs.yml')) assert len(paths) == 0 @@ -20,7 +20,7 @@ def test_find_at_root(tmpdir): apply_fs(tmpdir, {'readthedocs.yml': '', 'otherfile.txt': ''}) base = str(tmpdir) - paths = list(find_all(base, ('readthedocs.yml',))) + paths = list(find_all(base, r'readthedocs\.yml')) assert paths == [ os.path.abspath(os.path.join(base, 'readthedocs.yml')) ] @@ -42,11 +42,11 @@ def test_find_nested(tmpdir): apply_fs(tmpdir, {'first/readthedocs.yml': ''}) base = str(tmpdir) - paths = list(find_all(base, ('readthedocs.yml',))) - assert set(paths) == set([ + paths = set(find_all(base, r'readthedocs\.yml')) + assert paths == { str(tmpdir.join('first', 'readthedocs.yml')), str(tmpdir.join('third', 'readthedocs.yml')), - ]) + } def test_find_multiple_files(tmpdir): @@ -66,21 +66,12 @@ def test_find_multiple_files(tmpdir): apply_fs(tmpdir, {'first/readthedocs.yml': ''}) base = str(tmpdir) - paths = list(find_all(base, ('readthedocs.yml', - '.readthedocs.yml'))) - assert paths == [ + paths = set(find_all(base, r'\.?readthedocs\.yml')) + assert paths == { str(tmpdir.join('first', 'readthedocs.yml')), str(tmpdir.join('first', '.readthedocs.yml')), str(tmpdir.join('third', 'readthedocs.yml')), - ] - - paths = list(find_all(base, ('.readthedocs.yml', - 'readthedocs.yml'))) - assert paths == [ - str(tmpdir.join('first', '.readthedocs.yml')), - str(tmpdir.join('first', 'readthedocs.yml')), - str(tmpdir.join('third', 'readthedocs.yml')), - ] + } @pytest.mark.skipif(not six.PY2, reason='Only for python2') @@ -92,5 +83,5 @@ def test_find_unicode_path(tmpdir): assert path == '' unicode_base_path = base_path.decode('utf-8') assert isinstance(unicode_base_path, unicode) - path = find_one(unicode_base_path, ('readthedocs.yml',)) + path = find_one(unicode_base_path, r'readthedocs\.yml') assert path == '' From a06beb8883678dcdb446b61362c14c71e324860b Mon Sep 17 00:00:00 2001 From: Stefano Chiodino Date: Fri, 24 Aug 2018 08:26:50 +0100 Subject: [PATCH 2/4] Changes to conform to readthedocs standards --- readthedocs/config/config.py | 6 ++++-- readthedocs/config/tests/test_config.py | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/readthedocs/config/config.py b/readthedocs/config/config.py index 57f969b7277..b325b62d0e9 100644 --- a/readthedocs/config/config.py +++ b/readthedocs/config/config.py @@ -969,8 +969,10 @@ def load(path, env_config): filename = find_one(path, CONFIG_FILENAME_REGEX) if not filename: - raise ConfigError('No configuration file found', - code=CONFIG_REQUIRED) + raise ConfigError( + 'No configuration file found', + code=CONFIG_REQUIRED + ) build_configs = [] with open(filename, 'r') as configuration_file: try: diff --git a/readthedocs/config/tests/test_config.py b/readthedocs/config/tests/test_config.py index a645926eedf..87b0ce3986e 100644 --- a/readthedocs/config/tests/test_config.py +++ b/readthedocs/config/tests/test_config.py @@ -146,7 +146,7 @@ def test_load_unknow_version(tmpdir): def test_yaml_extension(tmpdir): - """ Make sure it's capable of loading the 'readthedocs' file with a 'yaml' extension. """ + """Make sure it's capable of loading the 'readthedocs' file with a 'yaml' extension.""" apply_fs(tmpdir, yaml_extension_config_dir) base = str(tmpdir) config = load(base, env_config) @@ -806,8 +806,8 @@ def test_raise_config_not_supported(): assert excinfo.value.code == CONFIG_NOT_SUPPORTED -@pytest.mark.parametrize("correct_config_filename", - [prefix + "readthedocs." + extension for prefix in {"", "."} +@pytest.mark.parametrize('correct_config_filename', + [prefix + 'readthedocs.' + extension for prefix in {"", "."} for extension in {"yml", "yaml"}]) def test_config_filenames_regex(correct_config_filename): assert re.match(CONFIG_FILENAME_REGEX, correct_config_filename) From e5595fecefd11f1a5a240c3588aae7623e990744 Mon Sep 17 00:00:00 2001 From: Stefano Chiodino Date: Fri, 24 Aug 2018 08:29:13 +0100 Subject: [PATCH 3/4] Update test to use func new regex signature --- readthedocs/config/tests/test_find.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readthedocs/config/tests/test_find.py b/readthedocs/config/tests/test_find.py index 2b3ec530a1b..2005d839277 100644 --- a/readthedocs/config/tests/test_find.py +++ b/readthedocs/config/tests/test_find.py @@ -79,7 +79,7 @@ def test_find_unicode_path(tmpdir): base_path = os.path.abspath( os.path.join(os.path.dirname(__file__), 'fixtures/bad_encode_project') ) - path = find_one(base_path, ('readthedocs.yml',)) + path = find_one(base_path, r'readthedocs\.yml') assert path == '' unicode_base_path = base_path.decode('utf-8') assert isinstance(unicode_base_path, unicode) From f83462fb799e99b0274a735f209c201c504dd336 Mon Sep 17 00:00:00 2001 From: Stefano Chiodino Date: Fri, 24 Aug 2018 19:15:57 +0100 Subject: [PATCH 4/4] Remove extra lines --- readthedocs/config/tests/test_config.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/readthedocs/config/tests/test_config.py b/readthedocs/config/tests/test_config.py index 87b0ce3986e..a81462f1a42 100644 --- a/readthedocs/config/tests/test_config.py +++ b/readthedocs/config/tests/test_config.py @@ -1643,6 +1643,3 @@ def test_submodules_recursive_explict_default(self): assert build.submodules.include == [] assert build.submodules.exclude == [] assert build.submodules.recursive is False - - -