From 602f1c7ecbe49a5dc692157d7d5c19d3677b90db Mon Sep 17 00:00:00 2001 From: Valentin Lorentz Date: Sat, 4 Aug 2012 13:52:02 +0200 Subject: [PATCH] utils/str.py: Use classes Multiple* instead of lambda functions. As in Python 3, functions are bound to a class when assigned to an attribute, lambda functions get two parameters, unless they are decorated with classmethod(). And there is no reason to ask plugin developpers use this decorator, while we avoid them doing this (more over, it is not obvious to debug if they forgot it). --- src/utils/str.py | 32 ++++++++++++++++++++++---------- test/test_utils.py | 4 ++-- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/utils/str.py b/src/utils/str.py index 66d52bd6b..eb5561231 100644 --- a/src/utils/str.py +++ b/src/utils/str.py @@ -218,19 +218,31 @@ def perlVariableSubstitute(vars, text): return '$' + unbraced return _perlVarSubstituteRe.sub(replacer, text) -def multipleReplacer(dict_): - """Return a function that replaces all dict keys by the associated +class MultipleReplacer: + """Return a callable that replaces all dict keys by the associated value. More efficient than multiple .replace().""" - dict_ = {re.escape(key): val for key,val in dict_.items()} - matcher = re.compile('|'.join(dict_.keys())) - return lambda x:matcher.sub(lambda m: dict_[m.group(0)], x) -def multipleRemover(list_): - """Return a function that removes all words in the list. A bit more + # We use an object instead of a lambda function because it avoids the + # need for using the staticmethod() on the lambda function if assigning + # it to a class in Python 3. + def __init__(self, dict_): + self._dict = dict_ + dict_ = {re.escape(key): val for key,val in dict_.items()} + self._matcher = re.compile('|'.join(dict_.keys())) + def __call__(self, s): + return self._matcher.sub(lambda m: self._dict[m.group(0)], s) +def multipleReplacer(dict_): + return MultipleReplacer(dict_) + +class MultipleRemover: + """Return a callable that removes all words in the list. A bit more efficient than multipleReplacer""" - list_ = [re.escape(x) for x in list_] - matcher = re.compile('|'.join(list_)) - return lambda x:matcher.sub(lambda m: '', x) + # See comment of MultipleReplacer + def __init__(self, list_): + list_ = [re.escape(x) for x in list_] + self._matcher = re.compile('|'.join(list_)) + def __call__(self, s): + return self._matcher.sub(lambda m: '', s) diff --git a/test/test_utils.py b/test/test_utils.py index 627ba0761..57f3e13dc 100644 --- a/test/test_utils.py +++ b/test/test_utils.py @@ -310,11 +310,11 @@ class StrTest(SupyTestCase): self.assertEqual(f('bar'), 'foobar') def testMultipleReplacer(self): - replacer = utils.str.multipleReplacer({'foo': 'bar', 'a': 'b'}) + replacer = utils.str.MultipleReplacer({'foo': 'bar', 'a': 'b'}) self.assertEqual(replacer('hi foo hi'), 'hi bar hi') def testMultipleRemover(self): - remover = utils.str.multipleRemover(['foo', 'bar']) + remover = utils.str.MultipleRemover(['foo', 'bar']) self.assertEqual(remover('testfoobarbaz'), 'testbaz') def testPReToReplacerDifferentSeparator(self):