prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Launching keyhint widget causes 100% usage of one CPU core
  That's how it was for as long as I can remember, reproducible with all of my hardware (pressing _g_ or _;_ is enough). I don't think that's an intended behavior.
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `qutebrowser/misc/keyhintwidget.py`
  Content:
  ```
  1 # vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
  2 
  3 # Copyright 2016-2019 Ryan Roden-Corrent (rcorre) <ryan@rcorre.net>
  4 #
  5 # This file is part of qutebrowser.
  6 #
  7 # qutebrowser is free software: you can redistribute it and/or modify
  8 # it under the terms of the GNU General Public License as published by
  9 # the Free Software Foundation, either version 3 of the License, or
  10 # (at your option) any later version.
  11 #
  12 # qutebrowser is distributed in the hope that it will be useful,
  13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 # GNU General Public License for more details.
  16 #
  17 # You should have received a copy of the GNU General Public License
  18 # along with qutebrowser.  If not, see <http://www.gnu.org/licenses/>.
  19 
  20 """Small window that pops up to show hints for possible keystrings.
  21 
  22 When a user inputs a key that forms a partial match, this shows a small window
  23 with each possible completion of that keystring and the corresponding command.
  24 It is intended to help discoverability of keybindings.
  25 """
  26 
  27 import html
  28 import fnmatch
  29 import re
  30 
  31 from PyQt5.QtWidgets import QLabel, QSizePolicy
  32 from PyQt5.QtCore import pyqtSlot, pyqtSignal, Qt
  33 
  34 from qutebrowser.config import config
  35 from qutebrowser.utils import utils, usertypes
  36 from qutebrowser.misc import objects
  37 from qutebrowser.keyinput import keyutils
  38 
  39 
  40 class KeyHintView(QLabel):
  41 
  42     """The view showing hints for key bindings based on the current key string.
  43 
  44     Attributes:
  45         _win_id: Window ID of parent.
  46 
  47     Signals:
  48         update_geometry: Emitted when this widget should be resized/positioned.
  49     """
  50 
  51     STYLESHEET = """
  52         QLabel {
  53             font: {{ conf.fonts.keyhint }};
  54             color: {{ conf.colors.keyhint.fg }};
  55             background-color: {{ conf.colors.keyhint.bg }};
  56             padding: 6px;
  57             {% if conf.statusbar.position == 'top' %}
  58                 border-bottom-right-radius: {{ conf.keyhint.radius }}px;
  59             {% else %}
  60                 border-top-right-radius: {{ conf.keyhint.radius }}px;
  61             {% endif %}
  62         }
  63     """
  64     update_geometry = pyqtSignal()
  65 
  66     def __init__(self, win_id, parent=None):
  67         super().__init__(parent)
  68         self.setTextFormat(Qt.RichText)
  69         self._win_id = win_id
  70         self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Minimum)
  71         self.hide()
  72         self._show_timer = usertypes.Timer(self, 'keyhint_show')
  73         self._show_timer.timeout.connect(self.show)
  74         config.set_register_stylesheet(self)
  75 
  76     def __repr__(self):
  77         return utils.get_repr(self, win_id=self._win_id)
  78 
  79     def showEvent(self, e):
  80         """Adjust the keyhint size when it's freshly shown."""
  81         self.update_geometry.emit()
  82         super().showEvent(e)
  83 
  84     @pyqtSlot(str)
  85     def update_keyhint(self, modename, prefix):
  86         """Show hints for the given prefix (or hide if prefix is empty).
  87 
  88         Args:
  89             prefix: The current partial keystring.
  90         """
  91         countstr, prefix = re.fullmatch(r'(\d*)(.*)', prefix).groups()
  92         if not prefix:
  93             self._show_timer.stop()
  94             self.hide()
  95             return
  96 
  97         def blacklisted(keychain):
  98             return any(fnmatch.fnmatchcase(keychain, glob)
  99                        for glob in config.val.keyhint.blacklist)
  100 
  101         def takes_count(cmdstr):
  102             """Return true iff this command can take a count argument."""
  103             cmdname = cmdstr.split(' ')[0]
  104             cmd = objects.commands.get(cmdname)
  105             return cmd and cmd.takes_count()
  106 
  107         bindings_dict = config.key_instance.get_bindings_for(modename)
  108         bindings = [(k, v) for (k, v) in sorted(bindings_dict.items())
  109                     if keyutils.KeySequence.parse(prefix).matches(k) and
  110                     not blacklisted(str(k)) and
  111                     (takes_count(v) or not countstr)]
  112 
  113         if not bindings:
  114             self._show_timer.stop()
  115             return
  116 
  117         # delay so a quickly typed keychain doesn't display hints
  118         self._show_timer.setInterval(config.val.keyhint.delay)
  119         self._show_timer.start()
  120         suffix_color = html.escape(config.val.colors.keyhint.suffix.fg)
  121 
  122         text = ''
  123         for seq, cmd in bindings:
  124             text += (
  125                 "<tr>"
  126                 "<td>{}</td>"
  127                 "<td style='color: {}'>{}</td>"
  128                 "<td style='padding-left: 2ex'>{}</td>"
  129                 "</tr>"
  130             ).format(
  131                 html.escape(prefix),
  132                 suffix_color,
  133                 html.escape(str(seq)[len(prefix):]),
  134                 html.escape(cmd)
  135             )
  136         text = '<table>{}</table>'.format(text)
  137 
  138         self.setText(text)
  139         self.adjustSize()
  140         self.update_geometry.emit()
  141
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/qutebrowser/misc/keyhintwidget.py b/qutebrowser/misc/keyhintwidget.py
  --- a/qutebrowser/misc/keyhintwidget.py
  +++ b/qutebrowser/misc/keyhintwidget.py
  @@ -71,6 +71,7 @@
           self.hide()
           self._show_timer = usertypes.Timer(self, 'keyhint_show')
           self._show_timer.timeout.connect(self.show)
  +        self._show_timer.setSingleShot(True)
           config.set_register_stylesheet(self)
   
       def __repr__(self):
  
verification_info: {"golden_diff": "diff --git a/qutebrowser/misc/keyhintwidget.py b/qutebrowser/misc/keyhintwidget.py\n--- a/qutebrowser/misc/keyhintwidget.py\n+++ b/qutebrowser/misc/keyhintwidget.py\n@@ -71,6 +71,7 @@\n         self.hide()\n         self._show_timer = usertypes.Timer(self, 'keyhint_show')\n         self._show_timer.timeout.connect(self.show)\n+        self._show_timer.setSingleShot(True)\n         config.set_register_stylesheet(self)\n \n     def __repr__(self):\n", "issue": "Launching keyhint widget causes 100% usage of one CPU core\nThat's how it was for as long as I can remember, reproducible with all of my hardware (pressing _g_ or _;_ is enough). I don't think that's an intended behavior.\n", "before_files": [{"content": "# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:\n\n# Copyright 2016-2019 Ryan Roden-Corrent (rcorre) <ryan@rcorre.net>\n#\n# This file is part of qutebrowser.\n#\n# qutebrowser is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# qutebrowser is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with qutebrowser.  If not, see <http://www.gnu.org/licenses/>.\n\n\"\"\"Small window that pops up to show hints for possible keystrings.\n\nWhen a user inputs a key that forms a partial match, this shows a small window\nwith each possible completion of that keystring and the corresponding command.\nIt is intended to help discoverability of keybindings.\n\"\"\"\n\nimport html\nimport fnmatch\nimport re\n\nfrom PyQt5.QtWidgets import QLabel, QSizePolicy\nfrom PyQt5.QtCore import pyqtSlot, pyqtSignal, Qt\n\nfrom qutebrowser.config import config\nfrom qutebrowser.utils import utils, usertypes\nfrom qutebrowser.misc import objects\nfrom qutebrowser.keyinput import keyutils\n\n\nclass KeyHintView(QLabel):\n\n    \"\"\"The view showing hints for key bindings based on the current key string.\n\n    Attributes:\n        _win_id: Window ID of parent.\n\n    Signals:\n        update_geometry: Emitted when this widget should be resized/positioned.\n    \"\"\"\n\n    STYLESHEET = \"\"\"\n        QLabel {\n            font: {{ conf.fonts.keyhint }};\n            color: {{ conf.colors.keyhint.fg }};\n            background-color: {{ conf.colors.keyhint.bg }};\n            padding: 6px;\n            {% if conf.statusbar.position == 'top' %}\n                border-bottom-right-radius: {{ conf.keyhint.radius }}px;\n            {% else %}\n                border-top-right-radius: {{ conf.keyhint.radius }}px;\n            {% endif %}\n        }\n    \"\"\"\n    update_geometry = pyqtSignal()\n\n    def __init__(self, win_id, parent=None):\n        super().__init__(parent)\n        self.setTextFormat(Qt.RichText)\n        self._win_id = win_id\n        self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Minimum)\n        self.hide()\n        self._show_timer = usertypes.Timer(self, 'keyhint_show')\n        self._show_timer.timeout.connect(self.show)\n        config.set_register_stylesheet(self)\n\n    def __repr__(self):\n        return utils.get_repr(self, win_id=self._win_id)\n\n    def showEvent(self, e):\n        \"\"\"Adjust the keyhint size when it's freshly shown.\"\"\"\n        self.update_geometry.emit()\n        super().showEvent(e)\n\n    @pyqtSlot(str)\n    def update_keyhint(self, modename, prefix):\n        \"\"\"Show hints for the given prefix (or hide if prefix is empty).\n\n        Args:\n            prefix: The current partial keystring.\n        \"\"\"\n        countstr, prefix = re.fullmatch(r'(\\d*)(.*)', prefix).groups()\n        if not prefix:\n            self._show_timer.stop()\n            self.hide()\n            return\n\n        def blacklisted(keychain):\n            return any(fnmatch.fnmatchcase(keychain, glob)\n                       for glob in config.val.keyhint.blacklist)\n\n        def takes_count(cmdstr):\n            \"\"\"Return true iff this command can take a count argument.\"\"\"\n            cmdname = cmdstr.split(' ')[0]\n            cmd = objects.commands.get(cmdname)\n            return cmd and cmd.takes_count()\n\n        bindings_dict = config.key_instance.get_bindings_for(modename)\n        bindings = [(k, v) for (k, v) in sorted(bindings_dict.items())\n                    if keyutils.KeySequence.parse(prefix).matches(k) and\n                    not blacklisted(str(k)) and\n                    (takes_count(v) or not countstr)]\n\n        if not bindings:\n            self._show_timer.stop()\n            return\n\n        # delay so a quickly typed keychain doesn't display hints\n        self._show_timer.setInterval(config.val.keyhint.delay)\n        self._show_timer.start()\n        suffix_color = html.escape(config.val.colors.keyhint.suffix.fg)\n\n        text = ''\n        for seq, cmd in bindings:\n            text += (\n                \"<tr>\"\n                \"<td>{}</td>\"\n                \"<td style='color: {}'>{}</td>\"\n                \"<td style='padding-left: 2ex'>{}</td>\"\n                \"</tr>\"\n            ).format(\n                html.escape(prefix),\n                suffix_color,\n                html.escape(str(seq)[len(prefix):]),\n                html.escape(cmd)\n            )\n        text = '<table>{}</table>'.format(text)\n\n        self.setText(text)\n        self.adjustSize()\n        self.update_geometry.emit()\n", "path": "qutebrowser/misc/keyhintwidget.py"}], "after_files": [{"content": "# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:\n\n# Copyright 2016-2019 Ryan Roden-Corrent (rcorre) <ryan@rcorre.net>\n#\n# This file is part of qutebrowser.\n#\n# qutebrowser is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# qutebrowser is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with qutebrowser.  If not, see <http://www.gnu.org/licenses/>.\n\n\"\"\"Small window that pops up to show hints for possible keystrings.\n\nWhen a user inputs a key that forms a partial match, this shows a small window\nwith each possible completion of that keystring and the corresponding command.\nIt is intended to help discoverability of keybindings.\n\"\"\"\n\nimport html\nimport fnmatch\nimport re\n\nfrom PyQt5.QtWidgets import QLabel, QSizePolicy\nfrom PyQt5.QtCore import pyqtSlot, pyqtSignal, Qt\n\nfrom qutebrowser.config import config\nfrom qutebrowser.utils import utils, usertypes\nfrom qutebrowser.misc import objects\nfrom qutebrowser.keyinput import keyutils\n\n\nclass KeyHintView(QLabel):\n\n    \"\"\"The view showing hints for key bindings based on the current key string.\n\n    Attributes:\n        _win_id: Window ID of parent.\n\n    Signals:\n        update_geometry: Emitted when this widget should be resized/positioned.\n    \"\"\"\n\n    STYLESHEET = \"\"\"\n        QLabel {\n            font: {{ conf.fonts.keyhint }};\n            color: {{ conf.colors.keyhint.fg }};\n            background-color: {{ conf.colors.keyhint.bg }};\n            padding: 6px;\n            {% if conf.statusbar.position == 'top' %}\n                border-bottom-right-radius: {{ conf.keyhint.radius }}px;\n            {% else %}\n                border-top-right-radius: {{ conf.keyhint.radius }}px;\n            {% endif %}\n        }\n    \"\"\"\n    update_geometry = pyqtSignal()\n\n    def __init__(self, win_id, parent=None):\n        super().__init__(parent)\n        self.setTextFormat(Qt.RichText)\n        self._win_id = win_id\n        self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Minimum)\n        self.hide()\n        self._show_timer = usertypes.Timer(self, 'keyhint_show')\n        self._show_timer.timeout.connect(self.show)\n        self._show_timer.setSingleShot(True)\n        config.set_register_stylesheet(self)\n\n    def __repr__(self):\n        return utils.get_repr(self, win_id=self._win_id)\n\n    def showEvent(self, e):\n        \"\"\"Adjust the keyhint size when it's freshly shown.\"\"\"\n        self.update_geometry.emit()\n        super().showEvent(e)\n\n    @pyqtSlot(str)\n    def update_keyhint(self, modename, prefix):\n        \"\"\"Show hints for the given prefix (or hide if prefix is empty).\n\n        Args:\n            prefix: The current partial keystring.\n        \"\"\"\n        countstr, prefix = re.fullmatch(r'(\\d*)(.*)', prefix).groups()\n        if not prefix:\n            self._show_timer.stop()\n            self.hide()\n            return\n\n        def blacklisted(keychain):\n            return any(fnmatch.fnmatchcase(keychain, glob)\n                       for glob in config.val.keyhint.blacklist)\n\n        def takes_count(cmdstr):\n            \"\"\"Return true iff this command can take a count argument.\"\"\"\n            cmdname = cmdstr.split(' ')[0]\n            cmd = objects.commands.get(cmdname)\n            return cmd and cmd.takes_count()\n\n        bindings_dict = config.key_instance.get_bindings_for(modename)\n        bindings = [(k, v) for (k, v) in sorted(bindings_dict.items())\n                    if keyutils.KeySequence.parse(prefix).matches(k) and\n                    not blacklisted(str(k)) and\n                    (takes_count(v) or not countstr)]\n\n        if not bindings:\n            self._show_timer.stop()\n            return\n\n        # delay so a quickly typed keychain doesn't display hints\n        self._show_timer.setInterval(config.val.keyhint.delay)\n        self._show_timer.start()\n        suffix_color = html.escape(config.val.colors.keyhint.suffix.fg)\n\n        text = ''\n        for seq, cmd in bindings:\n            text += (\n                \"<tr>\"\n                \"<td>{}</td>\"\n                \"<td style='color: {}'>{}</td>\"\n                \"<td style='padding-left: 2ex'>{}</td>\"\n                \"</tr>\"\n            ).format(\n                html.escape(prefix),\n                suffix_color,\n                html.escape(str(seq)[len(prefix):]),\n                html.escape(cmd)\n            )\n        text = '<table>{}</table>'.format(text)\n\n        self.setText(text)\n        self.adjustSize()\n        self.update_geometry.emit()\n", "path": "qutebrowser/misc/keyhintwidget.py"}]}