From eabd349902dd26937e2b4d26061c081fcb8a4139 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20Verg=C3=A9?= Date: Thu, 21 Apr 2016 22:24:24 +0200 Subject: [PATCH] Config: Allow a user-global configuration file Instead of just looking for `.yamllint` in the current working directory, also look for `~/.config/yamllint/config` (using `$XDG_CONFIG_HOME` or `$HOME`, see [1] and [2] for information). [1]: https://specifications.freedesktop.org/basedir-spec/basedir-spec-0.6.html [2]: https://wiki.archlinux.org/index.php/XDG_Base_Directory_support Closes: #6 --- README.rst | 2 +- docs/configuration.rst | 14 +++++++++++--- tests/test_cli.py | 43 ++++++++++++++++++++++++++++++++++++++++++ yamllint/cli.py | 11 +++++++++++ 4 files changed, 66 insertions(+), 4 deletions(-) diff --git a/README.rst b/README.rst index 788b617..66796c3 100644 --- a/README.rst +++ b/README.rst @@ -82,7 +82,7 @@ Usage yamllint -d relaxed file.yaml # Use a custom lint configuration - yamllint -c ~/myconfig file.yml + yamllint -c /path/to/myconfig file-to-lint.yaml .. code:: bash diff --git a/docs/configuration.rst b/docs/configuration.rst index 0ba7729..06cb102 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -5,12 +5,20 @@ yamllint uses a set of *rules* to check sources files for problems. Each rule is independent from the others, and can be enabled, disabled or tweaked. All these settings can be gathered in a configuration file. -To use a custom configuration file, either name it ``.yamllint`` in your working -directory, or use the ``-c`` option: +To use a custom configuration file, use the ``-c`` option: .. code:: bash - yamllint -c ~/myconfig file.yaml + yamllint -c /path/to/myconfig file-to-lint.yaml + +If ``-c`` is not provided, yamllint will look for a configuration file in the +following locations (by order of preference): + +- ``.yamllint`` in the current working directory +- ``$XDG_CONFIG_HOME/yamllint/config`` +- ``$HOME/.config/yamllint/config`` + +Finally if no config file is found, the default configuration is applied. Default configuration --------------------- diff --git a/tests/test_cli.py b/tests/test_cli.py index f0a2c94..29557c7 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -153,6 +153,49 @@ class CommandLineTestCase(unittest.TestCase): self.assertEqual(out, '') self.assertRegexpMatches(err, r'^invalid config: not a dict') + def test_run_with_config_file(self): + with open(os.path.join(self.wd, 'config'), 'w') as f: + f.write('rules: {trailing-spaces: disable}') + + with self.assertRaises(SystemExit) as ctx: + cli.run(('-c', f.name, os.path.join(self.wd, 'a.yaml'))) + self.assertEqual(ctx.exception.code, 0) + + with open(os.path.join(self.wd, 'config'), 'w') as f: + f.write('rules: {trailing-spaces: enable}') + + with self.assertRaises(SystemExit) as ctx: + cli.run(('-c', f.name, os.path.join(self.wd, 'a.yaml'))) + self.assertEqual(ctx.exception.code, 1) + + def test_run_with_user_global_config_file(self): + home = os.path.join(self.wd, 'fake-home') + os.mkdir(home) + dir = os.path.join(home, '.config') + os.mkdir(dir) + dir = os.path.join(dir, 'yamllint') + os.mkdir(dir) + config = os.path.join(dir, 'config') + + temp = os.environ['HOME'] + os.environ['HOME'] = home + + with open(config, 'w') as f: + f.write('rules: {trailing-spaces: disable}') + + with self.assertRaises(SystemExit) as ctx: + cli.run((os.path.join(self.wd, 'a.yaml'), )) + self.assertEqual(ctx.exception.code, 0) + + with open(config, 'w') as f: + f.write('rules: {trailing-spaces: enable}') + + with self.assertRaises(SystemExit) as ctx: + cli.run((os.path.join(self.wd, 'a.yaml'), )) + self.assertEqual(ctx.exception.code, 1) + + os.environ['HOME'] = temp + def test_run_version(self): sys.stdout, sys.stderr = StringIO(), StringIO() with self.assertRaises(SystemExit) as ctx: diff --git a/yamllint/cli.py b/yamllint/cli.py index c308c80..8e01701 100644 --- a/yamllint/cli.py +++ b/yamllint/cli.py @@ -86,6 +86,15 @@ def run(argv=None): 'simultaneously.', file=sys.stderr) sys.exit(-1) + # User-global config is supposed to be in ~/.config/yamllint/config + user_global_config = None + if 'XDG_CONFIG_HOME' in os.environ: + user_global_config = os.path.join( + os.environ['XDG_CONFIG_HOME'], 'yamllint', 'config') + elif 'HOME' in os.environ: + user_global_config = os.path.join( + os.environ['HOME'], '.config', 'yamllint', 'config') + try: if args.config_data is not None: if args.config_data != '' and ':' not in args.config_data: @@ -95,6 +104,8 @@ def run(argv=None): conf = YamlLintConfig(file=args.config_file) elif os.path.isfile('.yamllint'): conf = YamlLintConfig(file='.yamllint') + elif user_global_config and os.path.isfile(user_global_config): + conf = YamlLintConfig(file=user_global_config) else: conf = YamlLintConfig('extends: default') except YamlLintConfigError as e: