From 5a9042ab3efb9e69f6b11a341373c302a688578b Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Wed, 18 Oct 2017 13:53:26 +0200 Subject: [PATCH] Add a config.source() method --- doc/changelog.asciidoc | 1 + doc/help/configuring.asciidoc | 3 +++ qutebrowser/config/configfiles.py | 9 ++++++++ tests/unit/config/test_configfiles.py | 32 +++++++++++++++++++++++++++ 4 files changed, 45 insertions(+) diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc index 03eca9485..99b3ef11b 100644 --- a/doc/changelog.asciidoc +++ b/doc/changelog.asciidoc @@ -29,6 +29,7 @@ Added command in the completion. - New `:tab-give` and `:tab-take` commands, to give tabs to another window, or take them from another window. +- New `config.source(...)` method for `config.py` to source another file. Fixed ~~~~~ diff --git a/doc/help/configuring.asciidoc b/doc/help/configuring.asciidoc index e442b03a6..af555beb3 100644 --- a/doc/help/configuring.asciidoc +++ b/doc/help/configuring.asciidoc @@ -238,6 +238,9 @@ that via `import utils` as well. While it's in some cases possible to import code from the qutebrowser installation, doing so is unsupported and discouraged. +To read config data from a different file with `c` and `config` available, you +can use `config.source('otherfile.py')` in your `config.py`. + Getting the config directory ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/qutebrowser/config/configfiles.py b/qutebrowser/config/configfiles.py index e1a10848e..605c7372d 100644 --- a/qutebrowser/config/configfiles.py +++ b/qutebrowser/config/configfiles.py @@ -259,6 +259,15 @@ class ConfigAPI: with self._handle_error('unbinding', key): self._keyconfig.unbind(key, mode=mode) + def source(self, filename): + if not os.path.isabs(filename): + filename = str(self.configdir / filename) + + try: + read_config_py(filename) + except configexc.ConfigFileErrors as e: + self.errors += e.errors + class ConfigPyWriter: diff --git a/tests/unit/config/test_configfiles.py b/tests/unit/config/test_configfiles.py index 9a2ff37ab..2159a6604 100644 --- a/tests/unit/config/test_configfiles.py +++ b/tests/unit/config/test_configfiles.py @@ -580,6 +580,38 @@ class TestConfigPy: assert isinstance(error.exception, ZeroDivisionError) assert error.traceback is not None + @pytest.mark.parametrize('location', ['abs', 'rel']) + def test_source(self, tmpdir, confpy, location): + if location == 'abs': + subfile = tmpdir / 'subfile.py' + arg = str(subfile) + else: + subfile = tmpdir / 'config' / 'subfile.py' + arg = 'subfile.py' + + subfile.write_text("c.content.javascript.enabled = False", + encoding='utf-8') + confpy.write("config.source('{}')".format(arg)) + confpy.read() + + assert not config.instance._values['content.javascript.enabled'] + + def test_source_errors(self, tmpdir, confpy): + subfile = tmpdir / 'config' / 'subfile.py' + subfile.write_text("c.foo = 42", encoding='utf-8') + confpy.write("config.source('subfile.py')") + error = confpy.read(error=True) + + assert error.text == "While setting 'foo'" + assert isinstance(error.exception, configexc.NoOptionError) + + def test_source_not_found(self, confpy): + confpy.write("config.source('doesnotexist.py')") + error = confpy.read(error=True) + + assert error.text == "Error while reading doesnotexist.py" + assert isinstance(error.exception, FileNotFoundError) + class TestConfigPyWriter: