Use weakref for config.on_change. Fixes #156.

This commit is contained in:
Florian Bruhin 2014-10-08 10:40:46 +02:00
parent 7956f2b8e2
commit b7f2a6d143

View File

@ -29,6 +29,7 @@ import sys
import os.path import os.path
import inspect import inspect
import functools import functools
import weakref
import configparser import configparser
import collections import collections
import collections.abc import collections.abc
@ -43,8 +44,8 @@ from qutebrowser.utils import message, objreg, utils, standarddir, log
from qutebrowser.utils.usertypes import Completion from qutebrowser.utils.usertypes import Completion
ChangeHandler = collections.namedtuple('ChangeHandler', ['func', 'section', ChangeHandler = collections.namedtuple(
'option']) 'ChangeHandler', ['func_ref', 'section', 'option'])
change_handlers = [] change_handlers = []
@ -67,7 +68,7 @@ def on_change(func, sectname=None, optname=None):
if optname is not None and optname not in configdata.DATA[sectname]: if optname is not None and optname not in configdata.DATA[sectname]:
raise NoOptionError("Option '{}' does not exist in section " raise NoOptionError("Option '{}' does not exist in section "
"'{}'!".format(optname, sectname)) "'{}'!".format(optname, sectname))
change_handlers.append(ChangeHandler(func, sectname, optname)) change_handlers.append(ChangeHandler(weakref.ref(func), sectname, optname))
def get(*args, **kwargs): def get(*args, **kwargs):
@ -315,21 +316,28 @@ class ConfigManager(QObject):
sectname, optname)) sectname, optname))
if sectname in ('colors', 'fonts'): if sectname in ('colors', 'fonts'):
self.style_changed.emit(sectname, optname) self.style_changed.emit(sectname, optname)
to_delete = []
for handler in change_handlers: for handler in change_handlers:
if handler.section is not None and handler.section != sectname: func = handler.func_ref()
if func is None:
to_delete.append(handler)
continue continue
if handler.option is not None and handler.option != optname: elif handler.section is not None and handler.section != sectname:
continue continue
param_count = len(inspect.signature(handler.func).parameters) elif handler.option is not None and handler.option != optname:
continue
param_count = len(inspect.signature(func).parameters)
if param_count == 2: if param_count == 2:
handler.func(sectname, optname) func(sectname, optname)
elif param_count == 1: elif param_count == 1:
handler.func(sectname) func(sectname)
elif param_count == 0: elif param_count == 0:
handler.func() func()
else: else:
raise TypeError("Handler {} has invalid signature.".format( raise TypeError("Handler {} has invalid signature.".format(
handler.func.__qualname__)) func.__qualname__))
for handler in to_delete:
change_handlers.remove(handler)
def _after_set(self, changed_sect, changed_opt): def _after_set(self, changed_sect, changed_opt):
"""Clean up caches and emit signals after an option has been set.""" """Clean up caches and emit signals after an option has been set."""