From ed37fb66469b9199d136afe6c190c5752202d62e Mon Sep 17 00:00:00 2001 From: Valentin Lorentz Date: Fri, 15 May 2015 16:48:00 +0200 Subject: [PATCH] String & core: Add support for G flag in matchers. Closes GH-1072. --- plugins/String/plugin.py | 10 ++++------ plugins/String/test.py | 2 ++ src/commands.py | 2 ++ src/utils/str.py | 23 +++++++++++++++++++++-- 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/plugins/String/plugin.py b/plugins/String/plugin.py index ec6d5e368..adcc77e00 100644 --- a/plugins/String/plugin.py +++ b/plugins/String/plugin.py @@ -191,7 +191,7 @@ class String(callbacks.Plugin): len = wrap(len, ['text']) @internationalizeDocstring - def re(self, irc, msg, args, ff, text): + def re(self, irc, msg, args, f, text): """ If is of the form m/regexp/flags, returns the portion of @@ -199,10 +199,6 @@ class String(callbacks.Plugin): s/regexp/replacement/flags, returns the result of applying such a regexp to . """ - if isinstance(ff, (types.FunctionType, types.MethodType)): - f = ff - else: - f = lambda s: ff.search(s) and ff.search(s).group(0) or '' if f('') and len(f(' ')) > len(f(''))+1: # Matches the empty string. s = _('You probably don\'t want to match the empty string.') irc.error(s) @@ -210,12 +206,14 @@ class String(callbacks.Plugin): t = self.registryValue('re.timeout') try: v = process(f, text, timeout=t, pn=self.name(), cn='re') + if isinstance(v, list): + v = format('%L', v) irc.reply(v) except commands.ProcessTimeoutError as e: irc.error("ProcessTimeoutError: %s" % (e,)) except re.error as e: irc.error(e.args[0]) - re = thread(wrap(re, [first('regexpMatcher', 'regexpReplacer'), + re = thread(wrap(re, [first('regexpMatcherMany', 'regexpReplacer'), 'text'])) def xor(self, irc, msg, args, password, text): diff --git a/plugins/String/test.py b/plugins/String/test.py index e4e0ca4c8..b3d5aec60 100644 --- a/plugins/String/test.py +++ b/plugins/String/test.py @@ -117,6 +117,8 @@ class StringTestCase(PluginTestCase): self.assertResponse('re s/user/luser/ user user', 'luser user') self.assertNotRegexp('re m/foo/ bar', 'has no attribute') self.assertResponse('re m/a\S+y/ "the bot angryman is hairy"','angry') + self.assertResponse('re m/a\S+y/g "the bot angryman is hairy"', + 'angry and airy') def testReNotEmptyString(self): self.assertError('re s//foo/g blah') diff --git a/src/commands.py b/src/commands.py index f1adf6fbf..6342ebce7 100644 --- a/src/commands.py +++ b/src/commands.py @@ -450,6 +450,7 @@ def _getRe(f): return get getMatcher = _getRe(utils.str.perlReToPythonRe) +getMatcherMany = _getRe(utils.str.perlReToFindall) getReplacer = _getRe(utils.str.perlReToReplacer) def getNick(irc, msg, args, state): @@ -772,6 +773,7 @@ wrappers = ircutils.IrcDict({ 'private': private, 'public': public, 'regexpMatcher': getMatcher, + 'regexpMatcherMany': getMatcherMany, 'regexpReplacer': getReplacer, 'seenNick': getSeenNick, 'something': getSomething, diff --git a/src/utils/str.py b/src/utils/str.py index 5f822e56f..aaca5403c 100644 --- a/src/utils/str.py +++ b/src/utils/str.py @@ -170,7 +170,7 @@ def _getSep(s, allowBraces=False): '"%s"' % braces) return separator -def perlReToPythonRe(s): +def perlReToPythonRe(s, allowG=False): """Converts a string representation of a Perl regular expression (i.e., m/^foo$/i or /foo|bar/) to a Python regular expression. """ @@ -188,15 +188,34 @@ def perlReToPythonRe(s): if opener != closer: regexp = regexp.replace('\\'+closer, closer) flag = 0 + g = False try: for c in flags.upper(): + if c == 'G' and allowG: + g = True + continue flag |= getattr(re, c) except AttributeError: raise ValueError('Invalid flag: %s' % c) try: - return re.compile(regexp, flag) + r = re.compile(regexp, flag) except re.error as e: raise ValueError(str(e)) + if allowG: + return (r, g) + else: + return r + +def perlReToFindall(s): + """Converts a string representation of a Perl regular expression (i.e., + m/^foo$/i or /foo|bar/) to a Python regular expression, with support for + G flag + """ + (r, g) = perlReToPythonRe(s, allowG=True) + if g: + return lambda s: r.findall(s) + else: + return lambda s: r.search(s) and r.search(s).group(0) or '' def perlReToReplacer(s): """Converts a string representation of a Perl regular expression (i.e.,