mirror of
https://github.com/adrienverge/yamllint.git
synced 2025-02-25 18:55:20 -06:00
config: Look for configuration file in parent directories
Inspired be ESLint's search, it looks for configuration files in all parent directories up until it reaches the user's home or root. closes #571
This commit is contained in:
parent
019c87d36d
commit
e636848ddc
@ -15,7 +15,8 @@ If ``-c`` is not provided, yamllint will look for a configuration file in the
|
||||
following locations (by order of preference):
|
||||
|
||||
- a file named ``.yamllint``, ``.yamllint.yaml``, or ``.yamllint.yml`` in the
|
||||
current working directory
|
||||
current working directory, or a parent directory (the search for this file is
|
||||
terminated at the user's home or filesystem root)
|
||||
- a filename referenced by ``$YAMLLINT_CONFIG_FILE``, if set
|
||||
- a file named ``$XDG_CONFIG_HOME/yamllint/config`` or
|
||||
``~/.config/yamllint/config``, if present
|
||||
|
@ -734,3 +734,64 @@ class CommandLineConfigTestCase(unittest.TestCase):
|
||||
|
||||
self.assertEqual((ctx.returncode, ctx.stdout, ctx.stderr),
|
||||
(0, '', ''))
|
||||
|
||||
def test_parent_config_file(self):
|
||||
workspace = {'a/b/c/d/e/f/g/a.yml': 'hello: world\n'}
|
||||
conf = ('---\n'
|
||||
'extends: relaxed\n')
|
||||
|
||||
for conf_file in ('.yamllint', '.yamllint.yml', '.yamllint.yaml'):
|
||||
with self.subTest(conf_file):
|
||||
with temp_workspace(workspace):
|
||||
with RunContext(self) as ctx:
|
||||
os.chdir('a/b/c/d/e/f')
|
||||
cli.run(('-f', 'parsable', '.'))
|
||||
|
||||
self.assertEqual((ctx.returncode, ctx.stdout, ctx.stderr),
|
||||
(0, './g/a.yml:1:1: [warning] missing '
|
||||
'document start "---" (document-start)\n',
|
||||
''))
|
||||
|
||||
with temp_workspace({**workspace, **{conf_file: conf}}):
|
||||
with RunContext(self) as ctx:
|
||||
os.chdir('a/b/c/d/e/f')
|
||||
cli.run(('-f', 'parsable', '.'))
|
||||
|
||||
self.assertEqual((ctx.returncode, ctx.stdout, ctx.stderr),
|
||||
(0, '', ''))
|
||||
|
||||
def test_multiple_parent_config_file(self):
|
||||
workspace = {'a/b/c/3spaces.yml': 'array:\n'
|
||||
' - item\n',
|
||||
'a/b/c/4spaces.yml': 'array:\n'
|
||||
' - item\n',
|
||||
'a/.yamllint': '---\n'
|
||||
'extends: relaxed\n'
|
||||
'rules:\n'
|
||||
' indentation:\n'
|
||||
' spaces: 4\n',
|
||||
}
|
||||
|
||||
conf3 = ('---\n'
|
||||
'extends: relaxed\n'
|
||||
'rules:\n'
|
||||
' indentation:\n'
|
||||
' spaces: 3\n')
|
||||
|
||||
with temp_workspace(workspace):
|
||||
with RunContext(self) as ctx:
|
||||
os.chdir('a/b/c')
|
||||
cli.run(('-f', 'parsable', '.'))
|
||||
|
||||
self.assertEqual((ctx.returncode, ctx.stdout, ctx.stderr),
|
||||
(0, './3spaces.yml:2:4: [warning] wrong indentation: '
|
||||
'expected 4 but found 3 (indentation)\n', ''))
|
||||
|
||||
with temp_workspace({**workspace, **{'a/b/.yamllint.yml': conf3}}):
|
||||
with RunContext(self) as ctx:
|
||||
os.chdir('a/b/c')
|
||||
cli.run(('-f', 'parsable', '.'))
|
||||
|
||||
self.assertEqual((ctx.returncode, ctx.stdout, ctx.stderr),
|
||||
(0, './4spaces.yml:2:5: [warning] wrong indentation: '
|
||||
'expected 3 but found 4 (indentation)\n', ''))
|
||||
|
@ -141,6 +141,19 @@ def show_problems(problems, file, args_format, no_warn):
|
||||
return max_level
|
||||
|
||||
|
||||
def find_project_config_filepath(path='.'):
|
||||
for filename in ('.yamllint', '.yamllint.yaml', '.yamllint.yml'):
|
||||
filepath = os.path.join(path, filename)
|
||||
if os.path.isfile(filepath):
|
||||
return filepath
|
||||
|
||||
if os.path.abspath(path) == os.path.abspath(os.path.expanduser('~')):
|
||||
return None
|
||||
if os.path.abspath(path) == os.path.abspath(os.path.join(path, '..')):
|
||||
return None
|
||||
return find_project_config_filepath(path=os.path.join(path, '..'))
|
||||
|
||||
|
||||
def run(argv=None):
|
||||
parser = argparse.ArgumentParser(prog=APP_NAME,
|
||||
description=APP_DESCRIPTION)
|
||||
@ -185,6 +198,7 @@ def run(argv=None):
|
||||
else:
|
||||
user_global_config = os.path.expanduser('~/.config/yamllint/config')
|
||||
|
||||
project_config_filepath = find_project_config_filepath()
|
||||
try:
|
||||
if args.config_data is not None:
|
||||
if args.config_data != '' and ':' not in args.config_data:
|
||||
@ -192,12 +206,8 @@ def run(argv=None):
|
||||
conf = YamlLintConfig(content=args.config_data)
|
||||
elif args.config_file is not None:
|
||||
conf = YamlLintConfig(file=args.config_file)
|
||||
elif os.path.isfile('.yamllint'):
|
||||
conf = YamlLintConfig(file='.yamllint')
|
||||
elif os.path.isfile('.yamllint.yaml'):
|
||||
conf = YamlLintConfig(file='.yamllint.yaml')
|
||||
elif os.path.isfile('.yamllint.yml'):
|
||||
conf = YamlLintConfig(file='.yamllint.yml')
|
||||
elif project_config_filepath:
|
||||
conf = YamlLintConfig(file=project_config_filepath)
|
||||
elif os.path.isfile(user_global_config):
|
||||
conf = YamlLintConfig(file=user_global_config)
|
||||
else:
|
||||
|
Loading…
Reference in New Issue
Block a user