From anonymous, 9 Months ago, written in Diff-output.
Embed
  1. diff --git a/doc/help/settings.asciidoc b/doc/help/settings.asciidoc
  2. index 0c2d09d5f..bfbb8672e 100644
  3. --- a/doc/help/settings.asciidoc
  4. +++ b/doc/help/settings.asciidoc
  5. @@ -376,6 +376,8 @@ Default keybindings. If you want to add bindings, modify `bindings.commands` ins
  6.  The main purpose of this setting is that you can set it to an empty dictionary if you want to load no default keybindings at all.
  7.  If you want to preserve default bindings (and get new bindings when there is an update), use `config.bind()` in `config.py` or the `:bind` command, and leave this setting alone.
  8.  
  9. +This setting can only be set in config.py.
  10. +
  11.  Type: <<types,Dict>>
  12.  
  13.  Default:
  14. diff --git a/qutebrowser/completion/models/configmodel.py b/qutebrowser/completion/models/configmodel.py
  15. index 877de62b7..b462442a0 100644
  16. --- a/qutebrowser/completion/models/configmodel.py
  17. +++ b/qutebrowser/completion/models/configmodel.py
  18. @@ -29,7 +29,8 @@ def option(*, info):
  19.      """A CompletionModel filled with settings and their descriptions."""
  20.      model = completionmodel.CompletionModel(column_widths=(20, 70, 10))
  21.      options = ((opt.name, opt.description, info.config.get_str(opt.name))
  22. -               for opt in configdata.DATA.values())
  23. +               for opt in configdata.DATA.values()
  24. +               if not opt.no_autoconfig)
  25.      model.add_category(listcategory.ListCategory("Options", options))
  26.      return model
  27.  
  28. diff --git a/qutebrowser/config/config.py b/qutebrowser/config/config.py
  29. index eb2a81594..de8cc7042 100644
  30. --- a/qutebrowser/config/config.py
  31. +++ b/qutebrowser/config/config.py
  32. @@ -286,6 +286,11 @@ class Config(QObject):
  33.          log.config.debug("Config option changed: {} = {}".format(
  34.              opt.name, value))
  35.  
  36. +    def _check_yaml(self, opt, save_yaml):
  37. +        """Make sure the given option may be set in autoconfig.yml."""
  38. +        if save_yaml and opt.no_autoconfig:
  39. +            raise configexc.NoAutoconfigError(opt.name)
  40. +
  41.      def read_yaml(self):
  42.          """Read the YAML settings from self._yaml."""
  43.          self._yaml.load()
  44. @@ -383,7 +388,9 @@ class Config(QObject):
  45.  
  46.          If save_yaml=True is given, store the new value to YAML.
  47.          """
  48. -        self._set_value(self.get_opt(name), value, pattern=pattern)
  49. +        opt = self.get_opt(name)
  50. +        self._check_yaml(opt, save_yaml)
  51. +        self._set_value(opt, value, pattern=pattern)
  52.          if save_yaml:
  53.              self._yaml.set_obj(name, value, pattern=pattern)
  54.  
  55. @@ -393,6 +400,7 @@ class Config(QObject):
  56.          If save_yaml=True is given, store the new value to YAML.
  57.          """
  58.          opt = self.get_opt(name)
  59. +        self._check_yaml(opt, save_yaml)
  60.          converted = opt.typ.from_str(value)
  61.          log.config.debug("Setting {} (type {}) to {!r} (converted from {!r})"
  62.                           .format(name, opt.typ.__class__.__name__, converted,
  63. @@ -403,7 +411,8 @@ class Config(QObject):
  64.  
  65.      def unset(self, name, *, save_yaml=False, pattern=None):
  66.          """Set the given setting back to its default."""
  67. -        self.get_opt(name)  # To check whether it exists
  68. +        opt = self.get_opt(name)
  69. +        self._check_yaml(opt, save_yaml)
  70.          changed = self._values[name].remove(pattern)
  71.          if changed:
  72.              self.changed.emit(name)
  73. diff --git a/qutebrowser/config/configdata.py b/qutebrowser/config/configdata.py
  74. index 52ad123e1..c617fca14 100644
  75. --- a/qutebrowser/config/configdata.py
  76. +++ b/qutebrowser/config/configdata.py
  77. @@ -50,6 +50,7 @@ class Option:
  78.      description = attr.ib()
  79.      supports_pattern = attr.ib(default=False)
  80.      restart = attr.ib(default=False)
  81. +    no_autoconfig = attr.ib(default=False)
  82.  
  83.  
  84.  @attr.s
  85. @@ -199,7 +200,7 @@ def _read_yaml(yaml_data):
  86.      data = utils.yaml_load(yaml_data)
  87.  
  88.      keys = {'type', 'default', 'desc', 'backend', 'restart',
  89. -            'supports_pattern'}
  90. +            'supports_pattern', 'no_autoconfig'}
  91.  
  92.      for name, option in data.items():
  93.          if set(option.keys()) == {'renamed'}:
  94. @@ -227,6 +228,7 @@ def _read_yaml(yaml_data):
  95.              description=option['desc'],
  96.              restart=option.get('restart', False),
  97.              supports_pattern=option.get('supports_pattern', False),
  98. +            no_autoconfig=option.get('no_autoconfig', False),
  99.          )
  100.  
  101.      # Make sure no key shadows another.
  102. diff --git a/qutebrowser/config/configdata.yml b/qutebrowser/config/configdata.yml
  103. index 28c3a5d87..92d100744 100644
  104. --- a/qutebrowser/config/configdata.yml
  105. +++ b/qutebrowser/config/configdata.yml
  106. @@ -2177,6 +2177,7 @@ bindings.key_mappings:
  107.      `bindings.commands`), the mapping is ignored.
  108.  
  109.  bindings.default:
  110. +  no_autoconfig: true
  111.    default:
  112.      normal:
  113.        <Escape>: clear-keychain ;; search ;; fullscreen --leave
  114. diff --git a/qutebrowser/config/configexc.py b/qutebrowser/config/configexc.py
  115. index e08bec913..4d1ab5d7f 100644
  116. --- a/qutebrowser/config/configexc.py
  117. +++ b/qutebrowser/config/configexc.py
  118. @@ -31,6 +31,15 @@ class Error(Exception):
  119.      pass
  120.  
  121.  
  122. +class NoAutoconfigError(Error):
  123. +
  124. +    """Raised when this option can't be set in autoconfig.yml."""
  125. +
  126. +    def __init__(self, name):
  127. +        super().__init__("The {} setting can only be set in config.py!"
  128. +                         .format(name))
  129. +
  130. +
  131.  class BackendError(Error):
  132.  
  133.      """Raised when this setting is unavailable with the current backend."""
  134. diff --git a/qutebrowser/config/configfiles.py b/qutebrowser/config/configfiles.py
  135. index 05ed23e60..fdb1583e0 100644
  136. --- a/qutebrowser/config/configfiles.py
  137. +++ b/qutebrowser/config/configfiles.py
  138. @@ -262,6 +262,12 @@ class YamlConfig(QObject):
  139.              del settings[old]
  140.              self._mark_changed()
  141.  
  142. +        # bindings.default can't be set in autoconfig.yml anymore, so ignore
  143. +        # old values.
  144. +        if 'bindings.default' in settings:
  145. +            del settings['bindings.default']
  146. +            self._mark_changed()
  147. +
  148.          return settings
  149.  
  150.      def _validate(self, settings):
  151. diff --git a/qutebrowser/html/settings.html b/qutebrowser/html/settings.html
  152. index b370c0d91..62b424a59 100644
  153. --- a/qutebrowser/html/settings.html
  154. +++ b/qutebrowser/html/settings.html
  155. @@ -33,7 +33,7 @@ input { width: 98%; }
  156.          <th>Setting</th>
  157.          <th>Value</th>
  158.      </tr>
  159. -  {% for option in configdata.DATA.values() %}
  160. +  {% for option in configdata.DATA.values() if not option.no_autoconfig %}
  161.      <tr>
  162.        <!-- FIXME: convert to string properly -->
  163.        <td class="setting">{{ option.name }} (Current: {{ confget(option.name) | string |truncate(100) }})
  164. diff --git a/scripts/dev/src2asciidoc.py b/scripts/dev/src2asciidoc.py
  165. index 5fab901fc..cc00c3757 100755
  166. --- a/scripts/dev/src2asciidoc.py
  167. +++ b/scripts/dev/src2asciidoc.py
  168. @@ -421,6 +421,8 @@ def _generate_setting_option(f, opt):
  169.          f.write("This setting requires a restart.\n")
  170.      if opt.supports_pattern:
  171.          f.write("\nThis setting supports URL patterns.\n")
  172. +    if opt.no_autoconfig:
  173. +        f.write("\nThis setting can only be set in config.py.\n")
  174.      f.write("\n")
  175.      typ = opt.typ.get_name().replace(',', '&#44;')
  176.      f.write('Type: <<types,{typ}>>\n'.format(typ=typ))
  177. diff --git a/tests/unit/completion/test_models.py b/tests/unit/completion/test_models.py
  178. index 5240f2813..e14c5a466 100644
  179. --- a/tests/unit/completion/test_models.py
  180. +++ b/tests/unit/completion/test_models.py
  181. @@ -111,7 +111,8 @@ def configdata_stub(config_stub, monkeypatch, configdata_init):
  182.                  ])
  183.              },
  184.              backends=[],
  185. -            raw_backends=None)),
  186. +            raw_backends=None,
  187. +            no_autoconfig=True)),
  188.          ('bindings.commands', configdata.Option(
  189.              name='bindings.commands',
  190.              description='Default keybindings',
  191. @@ -655,8 +656,6 @@ def test_setting_option_completion(qtmodeltester, config_stub,
  192.              ('bindings.commands', 'Default keybindings', (
  193.                  '{"normal": {"<Ctrl+q>": "quit", "ZQ": "quit", '
  194.                  '"I": "invalid", "d": "scroll down"}}')),
  195. -            ('bindings.default', 'Default keybindings',
  196. -             '{"normal": {"<Ctrl+q>": "quit", "d": "tab-close"}}'),
  197.              ('content.javascript.enabled', 'Enable/Disable JavaScript',
  198.               'true'),
  199.          ]
  200. diff --git a/tests/unit/config/test_config.py b/tests/unit/config/test_config.py
  201. index 40e82ba4b..d51d79370 100644
  202. --- a/tests/unit/config/test_config.py
  203. +++ b/tests/unit/config/test_config.py
  204. @@ -621,6 +621,34 @@ class TestConfig:
  205.                  meth('content.cookies.accept', 'all')
  206.          assert not conf._values['content.cookies.accept']
  207.  
  208. +    @pytest.mark.parametrize('method, value', [
  209. +        ('set_obj', {}),
  210. +        ('set_str', '{}'),
  211. +    ])
  212. +    def test_set_no_autoconfig_save(self, conf, qtbot, yaml_value,
  213. +                                    method, value):
  214. +        meth = getattr(conf, method)
  215. +        option = 'bindings.default'
  216. +        with pytest.raises(configexc.NoAutoconfigError):
  217. +            with qtbot.assert_not_emitted(conf.changed):
  218. +                meth(option, value, save_yaml=True)
  219. +
  220. +        assert not conf._values[option]
  221. +        assert yaml_value(option) is configutils.UNSET
  222. +
  223. +    @pytest.mark.parametrize('method, value', [
  224. +        ('set_obj', {}),
  225. +        ('set_str', '{}'),
  226. +    ])
  227. +    def test_set_no_autoconfig_no_save(self, conf, qtbot, yaml_value,
  228. +                                       method, value):
  229. +        meth = getattr(conf, method)
  230. +        option = 'bindings.default'
  231. +        with qtbot.wait_signal(conf.changed):
  232. +            meth(option, value)
  233. +
  234. +        assert conf._values[option]
  235. +
  236.      @pytest.mark.parametrize('method', ['set_obj', 'set_str'])
  237.      def test_set_no_pattern(self, conf, method, qtbot):
  238.          meth = getattr(conf, method)
  239. diff --git a/tests/unit/config/test_configexc.py b/tests/unit/config/test_configexc.py
  240. index c41e02b4c..c11850a15 100644
  241. --- a/tests/unit/config/test_configexc.py
  242. +++ b/tests/unit/config/test_configexc.py
  243. @@ -48,6 +48,12 @@ def test_no_option_error_clash():
  244.          configexc.NoOptionError('opt', deleted=True, renamed='foo')
  245.  
  246.  
  247. +def test_no_autoconfig_error():
  248. +    e = configexc.NoAutoconfigError('opt')
  249. +    expected = "The opt setting can only be set in config.py!"
  250. +    assert str(e) == expected
  251. +
  252. +
  253.  def test_backend_error():
  254.      e = configexc.BackendError('foo', usertypes.Backend.QtWebKit)
  255.      expected = "The foo setting is not available with the QtWebKit backend!"
  256. diff --git a/tests/unit/config/test_configfiles.py b/tests/unit/config/test_configfiles.py
  257. index d3b3f5726..96f5d4976 100644
  258. --- a/tests/unit/config/test_configfiles.py
  259. +++ b/tests/unit/config/test_configfiles.py
  260. @@ -223,6 +223,16 @@ class TestYaml:
  261.          mode = 'persist' if persist else 'normal'
  262.          assert data['tabs.mode_on_change']['global'] == mode
  263.  
  264. +    def test_bindings_default(self, yaml, autoconfig):
  265. +        """Make sure bindings.default gets removed from autoconfig.yml."""
  266. +        autoconfig.write({'bindings.default': {'global': '{}'}})
  267. +
  268. +        yaml.load()
  269. +        yaml._save()
  270. +
  271. +        data = autoconfig.read()
  272. +        assert 'bindings.default' not in data
  273. +
  274.      def test_renamed_key_unknown_target(self, monkeypatch, yaml,
  275.                                          autoconfig):
  276.          """A key marked as renamed with invalid name should raise an error."""
  277.