Skip to content

Allow for period as a prefix and yaml extension for config file #4512

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Aug 27, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 5 additions & 9 deletions readthedocs/config/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand All @@ -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 = {
Expand Down Expand Up @@ -903,16 +903,12 @@ 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,
'No configuration file found',
code=CONFIG_REQUIRED
)
build_configs = []
with open(filename, 'r') as configuration_file:
Expand Down
15 changes: 8 additions & 7 deletions readthedocs/config/find.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 ''
25 changes: 24 additions & 1 deletion readthedocs/config/tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import os
import textwrap
import re

import pytest
from mock import DEFAULT, patch
Expand All @@ -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.models import Conda
from readthedocs.config.validation import (
INVALID_BOOL, INVALID_CHOICE, INVALID_LIST, INVALID_PATH, INVALID_STRING)
Expand Down Expand Up @@ -50,6 +51,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):
Expand Down Expand Up @@ -138,6 +146,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]
Expand Down Expand Up @@ -766,6 +782,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,
Expand Down
29 changes: 10 additions & 19 deletions readthedocs/config/tests/test_find.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@

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


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'))
]
Expand All @@ -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):
Expand All @@ -66,31 +66,22 @@ 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')
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)
path = find_one(unicode_base_path, ('readthedocs.yml',))
path = find_one(unicode_base_path, r'readthedocs\.yml')
assert path == ''