After starting a thread on this list
(http://mail.python.org/pipermail/mailman-developers/2006-May/018787.html>
and also posting a request for feedback on Mailman-Users
<http://mail.python.org/pipermail/mailman-users/2006-June/051588.html>
which received no replies, I think I'm almost done with this. My patch
is attached for review, comment.
Basically, I implement a new Utils.strip_verbose_pattern() function
which converts verbose patterns to single-line, non-verbose
equivalents and add code to versions.py for a one time conversion of
existing topics regexps.
I then modify the Gui, etc so that all future multi-line patterns are
stored as entered, but compiled and used with the lines connected by
'|'.
Specifically, I would like advice and comment on two things.
First since the strip_verbose_pattern() function is basically a
one-time, list conversion function, would it be better added to
versions.py rather than Utils.py.
Second, when a topic pattern is first entered, an attempt is made to
compile it, and if this throws an exception, the error is reported in
the Gui and the topic is ignored. A similar thing is also done in
MailList.py which will catch (eventually) and log bad topic regexps
that might be entered with config_list or withlist.
My question here is in the error message and log message, The pattern I
report as invalid is the '|' joined pattern and not the original
entry. I think this makes more sense, but I'm interested in what
others think.
Finally, in writing this post I have thought of another issue. Someone
may have a saved config_list 'template' with old style 'verbose' topic
regexps which wouldn't get converted if applied to a new 2.2.x list.
Is this something to be concerned about? Note that this could be an
issue any time a list attribute is deleted or has its set of values
manipulated.
--
Mark Sapiro <[EMAIL PROTECTED]> The highway is for gamblers,
San Francisco Bay Area, California better use your sense - B. Dylan
Index: mailman/Mailman/Cgi/options.py
===================================================================
--- mailman/Mailman/Cgi/options.py (revision 7907)
+++ mailman/Mailman/Cgi/options.py (working copy)
@@ -33,6 +33,7 @@
from Mailman.htmlformat import *
+OR = '|'
SLASH = '/'
SETLANGUAGE = -1
@@ -1021,7 +1022,8 @@
table.AddRow([Bold(Label(_('Name:'))),
Utils.websafe(name)])
table.AddRow([Bold(Label(_('Pattern (as regexp):'))),
- '<pre>' + Utils.websafe(pattern) + '</pre>'])
+ '<pre>' + Utils.websafe(OR.join(pattern.splitlines()))
+ + '</pre>'])
table.AddRow([Bold(Label(_('Description:'))),
Utils.websafe(description)])
# Make colors look nice
Index: mailman/Mailman/Gui/Topics.py
===================================================================
--- mailman/Mailman/Gui/Topics.py (revision 7907)
+++ mailman/Mailman/Gui/Topics.py (working copy)
@@ -22,7 +22,9 @@
from Mailman.i18n import _
from Mailman.Gui.GUIBase import GUIBase
+OR = '|'
+
class Topics(GUIBase):
def GetConfigCategory(self):
@@ -119,9 +121,10 @@
# Make sure the pattern was a legal regular expression
name = Utils.websafe(name)
try:
- re.compile(pattern)
+ orpattern = OR.join(pattern.splitlines())
+ re.compile(orpattern)
except (re.error, TypeError):
- safepattern = Utils.websafe(pattern)
+ safepattern = Utils.websafe(orpattern)
doc.addError(_("""The topic pattern '%(safepattern)s' is not a
legal regular expression. It will be discarded."""))
continue
Index: mailman/Mailman/Handlers/Tagger.py
===================================================================
--- mailman/Mailman/Handlers/Tagger.py (revision 7907)
+++ mailman/Mailman/Handlers/Tagger.py (working copy)
@@ -23,6 +23,7 @@
import email.Iterators
import email.Parser
+OR = '|'
CRNL = '\r\n'
EMPTYSTRING = ''
NLTAB = '\n\t'
@@ -51,7 +52,8 @@
# added to the specific topics bucket.
hits = {}
for name, pattern, desc, emptyflag in mlist.topics:
- cre = re.compile(pattern, re.IGNORECASE | re.VERBOSE)
+ pattern = OR.join(pattern.splitlines())
+ cre = re.compile(pattern, re.IGNORECASE)
for line in matchlines:
if cre.search(line):
hits[name] = 1
Index: mailman/Mailman/MailList.py
===================================================================
--- mailman/Mailman/MailList.py (revision 7907)
+++ mailman/Mailman/MailList.py (working copy)
@@ -74,6 +74,7 @@
_ = i18n._
EMPTYSTRING = ''
+OR = '|'
clog = logging.getLogger('mailman.config')
elog = logging.getLogger('mailman.error')
@@ -742,10 +743,11 @@
goodtopics = []
for name, pattern, desc, emptyflag in self.topics:
try:
- re.compile(pattern)
+ orpattern = OR.join(pattern.splitlines())
+ re.compile(orpattern)
except (re.error, TypeError):
elog.error('Bad topic pattern "%s" for list: %s',
- pattern, self.internal_name())
+ orpattern, self.internal_name())
else:
goodtopics.append((name, pattern, desc, emptyflag))
self.topics = goodtopics
Index: mailman/Mailman/Utils.py
===================================================================
--- mailman/Mailman/Utils.py (revision 7907)
+++ mailman/Mailman/Utils.py (working copy)
@@ -47,6 +47,7 @@
EMPTYSTRING = ''
UEMPTYSTRING = u''
+CR = '\r'
NL = '\n'
DOT = '.'
IDENTCHARS = ascii_letters + digits + '_'
@@ -849,3 +850,58 @@
except (LookupError, UnicodeError, ValueError, HeaderParseError):
# possibly charset problem. return with undecoded string in one line.
return EMPTYSTRING.join(s.splitlines())
+
+
+def strip_verbose_pattern(pattern):
+ # Remove white space and comments from a verbose pattern and return a
+ # non-verbose, equivalent pattern. Replace CR and NL in the result
+ # with '\\r' and '\\n' respectively to avoid multi-line results.
+ if not isinstance(pattern, str):
+ return pattern
+ newpattern = ''
+ i = 0
+ inclass = False
+ skiptoeol = False
+ copynext = False
+ while i < len(pattern):
+ c = pattern[i]
+ if copynext:
+ if c == NL:
+ newpattern += '\\n'
+ elif c == CR:
+ newpattern += '\\r'
+ else:
+ newpattern += c
+ copynext = False
+ elif skiptoeol:
+ if c == NL:
+ skiptoeol = False
+ elif c == '#' and not inclass:
+ skiptoeol = True
+ elif c == '[' and not inclass:
+ inclass = True
+ newpattern += c
+ copynext = True
+ elif c == ']' and inclass:
+ inclass = False
+ newpattern += c
+ elif re.search('\s', c):
+ if inclass:
+ if c == NL:
+ newpattern += '\\n'
+ elif c == CR:
+ newpattern += '\\r'
+ else:
+ newpattern += c
+ elif c == '\\' and not inclass:
+ newpattern += c
+ copynext = True
+ else:
+ if c == NL:
+ newpattern += '\\n'
+ elif c == CR:
+ newpattern += '\\r'
+ else:
+ newpattern += c
+ i += 1
+ return newpattern
Index: mailman/Mailman/Version.py
===================================================================
--- mailman/Mailman/Version.py (revision 7907)
+++ mailman/Mailman/Version.py (working copy)
@@ -36,7 +36,7 @@
(REL_LEVEL << 4) | (REL_SERIAL << 0))
# config.pck schema version number
-DATA_FILE_VERSION = 97
+DATA_FILE_VERSION = 98
# qfile/*.db schema version number
QFILE_SCHEMA_VERSION = 3
Index: mailman/Mailman/versions.py
===================================================================
--- mailman/Mailman/versions.py (revision 7907)
+++ mailman/Mailman/versions.py (working copy)
@@ -307,6 +307,15 @@
pass
else:
l.digest_members[k] = 0
+ #
+ # Convert pre 2.2 topics regexps which were compiled in verbose mode
+ # to a non-verbose equivalent.
+ #
+ if stored_state['data_version'] <= 97 and stored_state.has_key('topics'):
+ l.topics = []
+ for name, pattern, description, emptyflag in stored_state['topics']:
+ pattern = Utils.strip_verbose_pattern(pattern)
+ l.topics.append((name, pattern, description, emptyflag))
_______________________________________________
Mailman-Developers mailing list
[email protected]
http://mail.python.org/mailman/listinfo/mailman-developers
Mailman FAQ: http://www.python.org/cgi-bin/faqw-mm.py
Searchable Archives:
http://www.mail-archive.com/mailman-developers%40python.org/
Unsubscribe:
http://mail.python.org/mailman/options/mailman-developers/archive%40jab.org
Security Policy:
http://www.python.org/cgi-bin/faqw-mm.py?req=show&file=faq01.027.htp