-
Notifications
You must be signed in to change notification settings - Fork 25
Add submodule configuration #47
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,19 +6,23 @@ | |
from .parser import ParseError | ||
from .parser import parse | ||
from .validation import (validate_bool, validate_choice, validate_directory, | ||
validate_file, validate_string, ValidationError) | ||
validate_file, validate_list, validate_string, | ||
ValidationError) | ||
|
||
|
||
__all__ = ( | ||
'load', 'BuildConfig', 'ConfigError', 'InvalidConfig', 'ProjectConfig') | ||
|
||
|
||
CONFIG_FILENAMES = ('readthedocs.yml', '.readthedocs.yml') | ||
ALL = 'all' | ||
|
||
|
||
BASE_INVALID = 'base-invalid' | ||
BASE_NOT_A_DIR = 'base-not-a-directory' | ||
CONFIG_SYNTAX_INVALID = 'config-syntax-invalid' | ||
INVALID_KEYS_COMBINATION = 'invalid-keys-combination' | ||
MISSING_REQUIRED_KEY = 'missing-required-key' | ||
CONFIG_REQUIRED = 'config-required' | ||
NAME_REQUIRED = 'name-required' | ||
NAME_INVALID = 'name-invalid' | ||
|
@@ -168,6 +172,7 @@ def validate(self): | |
self.validate_base() | ||
self.validate_python() | ||
self.validate_formats() | ||
self.validate_submodules() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's fine triggering the validation here? |
||
|
||
self.validate_conda() | ||
self.validate_requirements_file() | ||
|
@@ -408,6 +413,66 @@ def validate_formats(self): | |
|
||
return True | ||
|
||
def validate_submodules(self): | ||
raw_submodules = self.raw_config.get('submodules') | ||
if raw_submodules is None: | ||
self['submodules'] = self.get_default_submodules_config() | ||
return None | ||
|
||
if 'include' in raw_submodules and 'exclude' in raw_submodules: | ||
self.error( | ||
'submodules', | ||
'It is not possible to include and exclude submodules', | ||
code=INVALID_KEYS_COMBINATION | ||
) | ||
|
||
self['submodules'] = {} | ||
submodules = self['submodules'] | ||
|
||
with self.catch_validation_error('submodules.recursive'): | ||
recursive = raw_submodules.get('recursive', False) | ||
submodules['recursive'] = validate_bool(recursive) | ||
|
||
if 'include' in raw_submodules: | ||
with self.catch_validation_error('submodules.include'): | ||
include = raw_submodules['include'] | ||
if include == ALL: | ||
submodules['include'] = ALL | ||
else: | ||
submodules['include'] = validate_list(include) | ||
self.validate_directories(submodules['include']) | ||
if not submodules['include']: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Forcing to be always false if |
||
submodules['recursive'] = False | ||
elif 'exclude' in raw_submodules: | ||
with self.catch_validation_error('submodules.exclude'): | ||
exclude = raw_submodules['exclude'] | ||
if exclude == ALL: | ||
submodules['exclude'] = ALL | ||
submodules['recursive'] = False | ||
else: | ||
submodules['exclude'] = validate_list(exclude) | ||
self.validate_directories(submodules['exclude']) | ||
elif submodules['recursive'] is True: | ||
self.error( | ||
'submodules', | ||
'You need to include submodules', | ||
code=MISSING_REQUIRED_KEY | ||
) | ||
return True | ||
|
||
def get_default_submodules_config(self): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This would be different for the previous projects submodules:
include: all
recursive: true And probably this would be managed by the rtd code... |
||
return { | ||
'include': [], | ||
'recursive': False, | ||
} | ||
|
||
def validate_directories(self, directories): | ||
base_path = os.path.dirname(self.source_file) | ||
return [ | ||
validate_directory(directory, base_path) | ||
for directory in directories | ||
] | ||
|
||
|
||
class ProjectConfig(list): | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,13 +9,17 @@ | |
from .config import load | ||
from .config import BuildConfig | ||
from .config import ProjectConfig | ||
from .config import ALL | ||
from .config import INVALID_KEYS_COMBINATION | ||
from .config import MISSING_REQUIRED_KEY | ||
from .config import TYPE_REQUIRED | ||
from .config import NAME_REQUIRED | ||
from .config import NAME_INVALID | ||
from .config import PYTHON_INVALID | ||
from .validation import INVALID_BOOL | ||
from .validation import INVALID_CHOICE | ||
from .validation import INVALID_DIRECTORY | ||
from .validation import INVALID_LIST | ||
from .validation import INVALID_PATH | ||
from .validation import INVALID_STRING | ||
|
||
|
@@ -349,6 +353,204 @@ def it_uses_validate_file(tmpdir): | |
assert args[0] == 'setup.py' | ||
|
||
|
||
def describe_validate_submodules(): | ||
|
||
def it_defaults_to_all_submodules(tmpdir): | ||
with tmpdir.as_cwd(): | ||
source_file = tmpdir.join('subdir', 'readthedocs.yml') | ||
build = get_build_config({}, source_file=str(source_file)) | ||
build.validate_submodules() | ||
# TODO: This will be the dafult behavior? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What I mean here is: on other parts of the code, when the key is not given, it doesn't get added to the build dict, and then the default values are chosen by rtd, I think with that current behavior we are repeating some logic. |
||
assert 'submodules' in build | ||
assert build['submodules']['include'] == [] | ||
assert build['submodules']['recursive'] is False | ||
|
||
def it_parses_include_key(tmpdir): | ||
apply_fs(tmpdir, {'sub-one': {}, 'sub-two': {}}) | ||
with tmpdir.as_cwd(): | ||
build = get_build_config({ | ||
'submodules': { | ||
'include': ['sub-one/', 'sub-two'], | ||
} | ||
}) | ||
build.validate_submodules() | ||
assert 'submodules' in build | ||
assert 'exclude' not in build['submodules'] | ||
assert build['submodules']['include'] == ['sub-one/', 'sub-two'] | ||
assert build['submodules']['recursive'] is False | ||
|
||
def it_validates_include_key(tmpdir): | ||
apply_fs(tmpdir, {'sub-one': {}, 'sub-two': {}}) | ||
with tmpdir.as_cwd(): | ||
build = get_build_config({ | ||
'submodules': { | ||
'include': ['sub-one/', 'sub-too'], | ||
} | ||
}) | ||
with raises(InvalidConfig) as excinfo: | ||
build.validate_submodules() | ||
assert excinfo.value.key == 'submodules.include' | ||
assert excinfo.value.code == INVALID_PATH | ||
|
||
def it_parses_exclude_key(tmpdir): | ||
apply_fs(tmpdir, {'sub-one': {}, 'sub-two': {}}) | ||
with tmpdir.as_cwd(): | ||
build = get_build_config({ | ||
'submodules': { | ||
'exclude': ['sub-two'], | ||
} | ||
}) | ||
build.validate_submodules() | ||
assert 'submodules' in build | ||
assert 'include' not in build['submodules'] | ||
assert build['submodules']['exclude'] == ['sub-two'] | ||
assert build['submodules']['recursive'] is False | ||
|
||
def it_validates_exclude_key(tmpdir): | ||
apply_fs(tmpdir, {'sub-one': {}, 'sub-two': {}}) | ||
with tmpdir.as_cwd(): | ||
build = get_build_config({ | ||
'submodules': { | ||
'exclude': ['sub-too'], | ||
} | ||
}) | ||
with raises(InvalidConfig) as excinfo: | ||
build.validate_submodules() | ||
assert excinfo.value.key == 'submodules.exclude' | ||
assert excinfo.value.code == INVALID_PATH | ||
|
||
def it_does_not_allow_exclude_and_include(tmpdir): | ||
build = get_build_config({ | ||
'submodules': { | ||
'include': ['sub-one'], | ||
'exclude': ['sub-two'], | ||
} | ||
}) | ||
with raises(InvalidConfig) as excinfo: | ||
build.validate_submodules() | ||
assert excinfo.value.key == 'submodules' | ||
assert excinfo.value.code == INVALID_KEYS_COMBINATION | ||
|
||
def it_requires_include_with_recursive(tmpdir): | ||
build = get_build_config({ | ||
'submodules': { | ||
'recursive': True, | ||
} | ||
}) | ||
with raises(InvalidConfig) as excinfo: | ||
build.validate_submodules() | ||
assert excinfo.value.key == 'submodules' | ||
assert excinfo.value.code == MISSING_REQUIRED_KEY | ||
|
||
def it_parses_recursive_key(tmpdir): | ||
apply_fs(tmpdir, {'sub-one': {}, 'sub-two': {}}) | ||
with tmpdir.as_cwd(): | ||
build = get_build_config({ | ||
'submodules': { | ||
'exclude': ['sub-two'], | ||
'recursive': True, | ||
}, | ||
}) | ||
build.validate_submodules() | ||
assert build['submodules']['recursive'] is True | ||
|
||
def it_validates_recursive_key(tmpdir): | ||
apply_fs(tmpdir, {'sub-one': {}, 'sub-two': {}}) | ||
with tmpdir.as_cwd(): | ||
build = get_build_config({ | ||
'submodules': { | ||
'exclude': ['sub-two'], | ||
'recursive': 'True', | ||
}, | ||
}) | ||
with raises(InvalidConfig) as excinfo: | ||
build.validate_submodules() | ||
assert excinfo.value.key == 'submodules.recursive' | ||
assert excinfo.value.code == INVALID_BOOL | ||
|
||
def it_accepts_all_keyword_on_include(tmpdir): | ||
apply_fs(tmpdir, {'sub-one': {}, 'sub-two': {}}) | ||
with tmpdir.as_cwd(): | ||
build = get_build_config({ | ||
'submodules': { | ||
'include': 'all', | ||
'recursive': True, | ||
}, | ||
}) | ||
build.validate_submodules() | ||
assert build['submodules']['include'] == ALL | ||
assert build['submodules']['recursive'] is True | ||
|
||
def it_validates_the_correct_type_for_include(tmpdir): | ||
apply_fs(tmpdir, {'sub-one': {}, 'sub-two': {}}) | ||
with tmpdir.as_cwd(): | ||
build = get_build_config({ | ||
'submodules': { | ||
'include': 'none', | ||
'recursive': True, | ||
}, | ||
}) | ||
with raises(InvalidConfig) as excinfo: | ||
build.validate_submodules() | ||
assert excinfo.value.key == 'submodules.include' | ||
assert excinfo.value.code == INVALID_LIST | ||
|
||
def it_accepts_all_keyword_on_exclude(tmpdir): | ||
apply_fs(tmpdir, {'sub-one': {}, 'sub-two': {}}) | ||
with tmpdir.as_cwd(): | ||
build = get_build_config({ | ||
'submodules': { | ||
'exclude': 'all', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If when There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We do it with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Still would be necessary There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To me, |
||
'recursive': True, | ||
}, | ||
}) | ||
build.validate_submodules() | ||
assert build['submodules']['exclude'] == ALL | ||
assert build['submodules']['recursive'] is False | ||
|
||
def it_validates_the_correct_type_for_exclude(tmpdir): | ||
apply_fs(tmpdir, {'sub-one': {}, 'sub-two': {}}) | ||
with tmpdir.as_cwd(): | ||
build = get_build_config({ | ||
'submodules': { | ||
'exclude': 'none', | ||
'recursive': True, | ||
}, | ||
}) | ||
with raises(InvalidConfig) as excinfo: | ||
build.validate_submodules() | ||
assert excinfo.value.key == 'submodules.exclude' | ||
assert excinfo.value.code == INVALID_LIST | ||
|
||
def it_parses_explicit_defaults(tmpdir): | ||
apply_fs(tmpdir, {'sub-one': {}, 'sub-two': {}}) | ||
with tmpdir.as_cwd(): | ||
build = get_build_config({ | ||
'submodules': { | ||
'include': [], | ||
'recursive': False, | ||
} | ||
}) | ||
build.validate_submodules() | ||
assert 'submodules' in build | ||
assert build['submodules']['include'] == [] | ||
assert build['submodules']['recursive'] is False | ||
|
||
def it_parses_explicit_wrong_defaults(tmpdir): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What would be the behavior for this case? Should be an error? Ignore this? or change the value of |
||
apply_fs(tmpdir, {'sub-one': {}, 'sub-two': {}}) | ||
with tmpdir.as_cwd(): | ||
build = get_build_config({ | ||
'submodules': { | ||
'include': [], | ||
'recursive': True, | ||
} | ||
}) | ||
build.validate_submodules() | ||
assert 'submodules' in build | ||
assert build['submodules']['include'] == [] | ||
assert build['submodules']['recursive'] is False | ||
|
||
|
||
def test_valid_build_config(): | ||
build = BuildConfig(env_config, | ||
minimal_config, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's fine this constant here?