From 6a3be33fcd333b4389a7754bf1c503b664840722 Mon Sep 17 00:00:00 2001 From: Valentin Lorentz Date: Sat, 5 Sep 2020 21:40:40 +0200 Subject: [PATCH] registry: Don't use an internal state for Regexp, it breaks net- and chan- specific values. --- plugins/Config/test.py | 73 +++++++++++++++++++++++++++++++++++++++++- src/registry.py | 34 ++++++++------------ 2 files changed, 85 insertions(+), 22 deletions(-) diff --git a/plugins/Config/test.py b/plugins/Config/test.py index 858c29e0b..09c26eaf5 100644 --- a/plugins/Config/test.py +++ b/plugins/Config/test.py @@ -39,7 +39,7 @@ def random_string(): class ConfigTestCase(ChannelPluginTestCase): # We add utilities so there's something in supybot.plugins. - plugins = ('Config', 'User', 'Utilities') + plugins = ('Config', 'User', 'Utilities', 'Web') prefix1 = 'somethingElse!user@host1.tld' prefix2 = 'EvensomethingElse!user@host2.tld' @@ -437,6 +437,77 @@ class ConfigTestCase(ChannelPluginTestCase): self.assertFalse( conf.supybot.reply.whenAddressedBy.strings.get(':test')._wasSet) + def testResetRegexpChannel(self): + """Specifically tests resetting a Regexp value, as they have an extra + internal state that needs to be reset; see the comment in plugin.py""" + self.assertResponse( + 'config plugins.Web.nonSnarfingRegexp', + 'Global: ; #test @ test: ' + ) + self.assertResponse( + 'config plugins.Web.nonSnarfingRegexp m/foo/', + 'The operation succeeded.' + ) + self.assertResponse( + 'config channel plugins.Web.nonSnarfingRegexp m/bar/', + 'The operation succeeded.' + ) + self.assertResponse( + 'config plugins.Web.nonSnarfingRegexp', + 'Global: m/foo/; #test @ test: m/bar/' + ) + self.assertResponse( + 'config reset channel plugins.Web.nonSnarfingRegexp', + 'The operation succeeded.' + ) + self.assertResponse('config plugins.Web.nonSnarfingRegexp', + 'Global: m/foo/; #test @ test: m/foo/' + ) + self.assertResponse( + 'config plugins.Web.nonSnarfingRegexp ""', + 'The operation succeeded.' + ) + self.assertResponse( + 'config plugins.Web.nonSnarfingRegexp', + 'Global: ; #test @ test: ' + ) + + def testResetRegexpNetwork(self): + """Specifically tests resetting a Regexp value, as they have an extra + internal state that needs to be reset; see the comment in plugin.py""" + self.assertResponse( + 'config plugins.Web.nonSnarfingRegexp', + 'Global: ; #test @ test: ' + ) + self.assertResponse( + 'config plugins.Web.nonSnarfingRegexp m/foo/', + 'The operation succeeded.' + ) + self.assertResponse( + 'config network plugins.Web.nonSnarfingRegexp m/bar/', + 'The operation succeeded.' + ) + self.assertResponse( + 'config plugins.Web.nonSnarfingRegexp', + 'Global: m/foo/; #test @ test: m/bar/' + ) + self.assertResponse( + 'config reset network plugins.Web.nonSnarfingRegexp', + 'The operation succeeded.' + ) + self.assertResponse('config plugins.Web.nonSnarfingRegexp', + 'Global: m/foo/; #test @ test: m/foo/' + ) + self.assertResponse( + 'config plugins.Web.nonSnarfingRegexp ""', + 'The operation succeeded.' + ) + self.assertResponse( + 'config plugins.Web.nonSnarfingRegexp', + 'Global: ; #test @ test: ' + ) + + # vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79: diff --git a/src/registry.py b/src/registry.py index 56cd441ab..a87532a27 100644 --- a/src/registry.py +++ b/src/registry.py @@ -749,14 +749,7 @@ class StringWithSpaceOnRight(String): class Regexp(Value): """Value must be a valid regular expression.""" - __slots__ = ('sr', 'value', '__parent') errormsg = _('Value must be a valid regular expression, not %r.') - def __init__(self, *args, **kwargs): - kwargs['setDefault'] = False - self.sr = '' - self.value = None - self.__parent = super(Regexp, self) - self.__parent.__init__(*args, **kwargs) def error(self, e): s = 'Value must be a regexp of the form m/.../ or /.../. %s' % e @@ -767,26 +760,25 @@ class Regexp(Value): def set(self, s): try: if s: - self.setValue(utils.str.perlReToPythonRe(s), sr=s) + # We need to preserve the original string, as it's shown in + # the user interface and the config file. + # It might be tempting to set the original string as an + # attribute, but doing so would result in inconsistent states + # for childs of this variable, should they be reset, or the + # value of there parent change. + v = (s, utils.str.perlReToPythonRe(s)) else: - self.setValue(None) + v = ('', '') except ValueError as e: self.error(e) - - def setValue(self, v, sr=None): - if v is None: - self.sr = '' - self.__parent.setValue(None) - elif sr is not None: - self.sr = sr - self.__parent.setValue(v) else: - raise InvalidRegistryValue('Can\'t setValue a regexp, there would be an inconsistency '\ - 'between the regexp and the recorded string value.') + super().set(v) + + def __call__(self): + return self.value[1] def __str__(self): - self() # Gotta update if we've been reloaded. - return self.sr + return self.value[0] class SeparatedListOf(Value): __slots__ = ()