Update of /cvsroot/mailman/mailman3/src/mailman/categories
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv31133/src/mailman/categories
Added Files:
Tag: 3.0
__init__.py category.py constants.py properties.py xmlparse.py
Log Message:
Initial checkin of Mailman3 source
--- NEW FILE: __init__.py ---
# Copyright (C) 2004 Barry A. Warsaw
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place - Suite 330, Boston, MA 02111-1307, USA.
import os
allcats = {}
allvars = {}
specdir = os.path.join(os.path.dirname(__file__), 'specs')
def startup():
# Define here to avoid circular imports
from mailman.categories.xmlparse import xmlparse
# Parse all the category .xml files
for file in os.listdir(specdir):
catname, ext = os.path.splitext(file)
if ext <> '.xml':
continue
fp = open(os.path.join(specdir, file))
try:
cat = xmlparse(fp)
finally:
fp.close()
def shutdown():
pass
--- NEW FILE: category.py ---
# Copyright (C) 2004 Barry A. Warsaw
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place - Suite 330, Boston, MA 02111-1307, USA.
from mailman.categories import allcats, allvars
class Category(object):
def __init__(self, name, heading, description, parent=None):
self.name = name
self.heading = heading
self.description = description
self.parent = parent
# An ordered list of all attributes described in the XML file. This
# includes variables and section headers.
self.attributes = []
# A mapping from variable names to variable (i.e. Property) objects
self.variables = {}
# Subcategories
self.subcategories = {}
if parent:
allcats[parent.name + '.' + name] = self
else:
allcats[name] = self
def addSection(self, section):
self.attributes.append(section)
addAction = addSection
def addVariable(self, variable):
self.attributes.append(variable)
self.variables[variable.name] = variable
allvars[variable.name] = (variable, self)
def addSubcategory(self, subcat):
self.subcategories[subcat.name] = subcat
--- NEW FILE: constants.py ---
# Copyright (C) 2004 Barry A. Warsaw
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place - Suite 330, Boston, MA 02111-1307, USA.
"""Enums and other constants used by the category machinery."""
from mailman.interfaces.enum import Enum
class NoYes(Enum):
No = False
Yes = True
class AppendReplyTo(Enum):
No = 0
ThisList = 1
Explicit = 2
class Languages(Enum):
English = 0
Spanish = 1
Italian = 2
class EncodePrefixes(Enum):
Never = 0
Always = 1
AsNeeded = 2
class DeliveryModes(Enum):
Regular = 0
Digest = 1
Either = 2
class PersonalizationChoices(Enum):
No = 0
Yes = 1
Full = 2
class DigestVolumeFrequency(Enum):
Daily = 0
Weekly = 1
Quarterly = 2
Monthly = 3
Yearly = 4
--- NEW FILE: properties.py ---
# Copyright (C) 2004 Barry A. Warsaw
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place - Suite 330, Boston, MA 02111-1307, USA.
from email.Utils import parseaddr, formataddr
from mailman import utils
from mailman.categories import constants
from mailman.cgi.zpt import MailmanTemplate
from mailman.interfaces.enum import Enum
from mailman.profile import getOrCreateProfile
NL = '\n'
def _(s):
return s
class RadioStyle(Enum):
Horizontal = 1
Vertical = 2
Stacked = 3
class Property(object):
isattr = False
isheader = False
isaction = False
class Variable(Property):
isattr = True
def __init__(self, name, description=u'', details=u''):
self.name = name
self.description = description
self.details = details
def widget(self):
pt = MailmanTemplate(self._zptPath() + '.pt', here=self)
return pt.macros['widget']
def format(self, val):
"""Format value for display in widget."""
return val
def parse(self, val):
"""Parse widget text value into Python objects."""
return unicode(val[0])
def _zptPath(self):
raise NotImplementedError, self
def default(self):
raise NotImplementedError, self
class String(Variable):
def _zptPath(self):
return 'macro_string'
def default(self):
return ''
class Email(String):
pass
class Text(Variable):
def __init__(self, name, description=u'', details=u'', rows=5):
super(Text, self).__init__(name, description, details)
self.rows = rows
def _zptPath(self):
return 'macro_text'
def default(self):
return ''
class Number(Variable):
def _zptPath(self):
return 'macro_string'
def parse(self, val):
for type in (int, long, float):
try:
return type(val[0])
except ValueError:
pass
raise ValueError(val)
def default(self):
return 0
class EmailList(Text):
def format(self, val):
# val is a sequence of IProfiles
addrs = []
for profile in val:
addrs.append(formataddr((profile.realname, profile.address)))
return NL.join(addrs)
def parse(self, val):
rtn = []
# val is a list of lines, one email address per line
for line in val[0].splitlines():
name, addr = parseaddr(line)
profile, isNew = getOrCreateProfile(addr)
if isNew:
# Create a password for this user
password = utils.mksyllables(8)
profile.realname = name
profile.password = utils.hashPassword(password)
# XXX Sent notification to owner
from binascii import hexlify
print 'address:', profile.address, \
'realname:', profile.realname, \
'password:', password, \
'userid:', hexlify(profile.userid)
rtn.append(profile)
return rtn
def default(self):
return []
# Container class for path expressions in choices
class _Bag:
def __init__(self, label, enum):
self.label = label
self.value = enum
class Choices(Variable):
def __init__(self, name, description=u'', details=u'',
enum='NoYes', labels=None, style='Horizontal'):
super(Choices, self).__init__(name, description, details)
# Some of the configuration information is in the node attributes.
self.enum = getattr(constants, enum)
if labels is not None:
self.labels = labels.split(';')
else:
self.labels = [str(x) for x in self.enum]
self.style = getattr(RadioStyle, style)
def format(self, val):
# Return the integer value of the EnumInstance
return int(val)
def parse(self, val):
return self.enum[int(val[0])]
def choices(self):
for item in self.enum:
intval = int(item)
yield _Bag(self.labels[intval], intval)
def default(self):
return int(self.enum[0])
class Radio(Choices):
def _zptPath(self):
if self.style == RadioStyle.Horizontal:
return 'macro_radiohoriz'
elif self.style == RadioStyle.Vertical:
return 'macro_radiovert'
elif self.style == RadioStyle.Stacked:
return 'macro_radiostacked'
else:
raise ValueError('bad style: %s' % self.style)
class Toggle(Radio):
pass
class Pulldown(Choices):
def _zptPath(self):
return 'macro_pulldown'
class Select(Radio):
def _zptPath(self):
return 'macro_checkboxes'
def format(self, val):
return [int(x) for x in val]
def parse(self, val):
return [self.enum[int(x)] for x in val]
def default(self):
return []
class SectionHeader(Property):
isheader = True
def __init__(self, s):
self.heading = s
class Action(Property):
isaction = True
def __init__(self, name, label, description):
self.name = name
self.label = label
self.description = description
--- NEW FILE: xmlparse.py ---
# Copyright (C) 2004 Barry A. Warsaw
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place - Suite 330, Boston, MA 02111-1307, USA.
import re
import logging
from xml.dom import minidom
from xml.parsers.expat import ExpatError
from mailman.categories import properties
from mailman.categories.category import Category
from mailman.text.strings import dstring
SPACE = ' '
EMPTYSTRING = ''
RETMPL = '^<%s[^>]*?>(.*)</%s>$'
log = logging.getLogger('mailman.error')
def xmlstring(s):
# Convert all whitespace to a single space, strip whitespace off the front
# and end and turn the string into a $-substitutable string.
return SPACE.join(s.strip().split())
def visit(node, kws):
# Find the subnode values
for child in node.childNodes:
if child.nodeType == minidom.Node.ELEMENT_NODE:
name = child.tagName
text = xmlstring(child.toxml())
# We have to strip off the start and end tags.
mo = re.match(RETMPL % (name, name), text)
# name is going to be a unicode, but Python doesn't allow
# unicode objects as keywords to function calls. Since
# they must be ascii strings, we just coerce them here.
kws[str(name)] = mo.group(1)
def makecategory(node, parent=None):
name = xmlstring(node.getAttribute('name'))
heading = xmlstring(node.getAttribute('heading'))
descrip = xmlstring(node.getAttribute('description'))
category = Category(name, heading, descrip, parent)
# Now parse the subnodes, populating the category
for node in node.childNodes:
if node.nodeType <> minidom.Node.ELEMENT_NODE:
continue
if node.tagName == 'section':
text = xmlstring(node.childNodes[0].data)
header = properties.SectionHeader(text)
category.addSection(header)
elif node.tagName == 'variable':
classname = xmlstring(node.getAttribute('type'))
cls = getattr(properties, xmlstring(classname))
# Initialize the constructor keywords, from the attributes in the
# variable tag. But remove the type attribute, which instead
# describes class to use.
kws = dict([(str(k), node.getAttribute(k))
for k in node.attributes.keys()])
del kws['type']
visit(node, kws)
variable = cls(**kws)
category.addVariable(variable)
elif node.tagName == 'action':
kws = {}
visit(node, kws)
action = properties.Action(**kws)
category.addAction(action)
elif node.tagName == 'category':
subcat = makecategory(node, category)
category.addSubcategory(subcat)
return category
def xmlparse(fp):
category = None
# Parse the XML document and pull out the top-level category node.
try:
doc = minidom.parse(fp)
except ExpatError:
log.error('minidom parse error on file: %s', fp.name)
raise
doc.normalize()
# Find the category node
for node in doc.childNodes:
if node.nodeType <> minidom.Node.ELEMENT_NODE:
continue
if node.tagName == 'category':
category = makecategory(node)
break
assert category
return category
_______________________________________________
Mailman-checkins mailing list
[EMAIL PROTECTED]
Unsubscribe: http://mail.python.org/mailman/options/mailman-checkins/archive%40jab.org