Commit ac0f1c39 authored by Barry Warsaw's avatar Barry Warsaw

Schema change. After discussion at Pycon, we decided to change "real_name" to

"display_name" across the board.

 * `IMailingList.real_name` -> `IMailingList.display_name`
 * `IUser.real_name` -> `IUser.display_name`
 * `IAddress.real_name` -> `IAddress.display_name`

 * Schema changes:
   - real_name        -> display_name (mailinglist, user, address)
parent 0589c867
......@@ -415,7 +415,7 @@ class Article(pipermail.Article):
d["datestr_html"] = self.quote(ctime(int(self.date)))
d["body"] = self._get_body()
d['listurl'] = self._mlist.script_url('listinfo')
d['listname'] = self._mlist.real_name
d['listname'] = self._mlist.display_name
d['encoding'] = ''
charset = self._lang.charset
d["encoding"] = html_charset % charset
......@@ -639,7 +639,7 @@ class HyperArchive(pipermail.T):
return html_quote(ctime(s), self.lang.code)
# Avoid i18n side-effects
with _.using(mlist.preferred_language.code):
d = {"listname": html_quote(mlist.real_name, self.lang.code),
d = {"listname": html_quote(mlist.display_name, self.lang.code),
"archtype": self.type,
"archive": self.volNameToDesc(self.archive),
"listinfo": mlist.script_url('listinfo'),
......@@ -672,7 +672,7 @@ class HyperArchive(pipermail.T):
mlist = self.maillist
listname = mlist.fqdn_listname
mbox = os.path.join(mlist.archive_dir()+'.mbox', listname+'.mbox')
d = {"listname": mlist.real_name,
d = {"listname": mlist.display_name,
"listinfo": mlist.script_url('listinfo'),
"fullarch": '../%s.mbox/%s.mbox' % (listname, listname),
"size": sizeof(mbox, mlist.preferred_language),
......
......@@ -215,7 +215,7 @@ def send_probe(member, msg):
)
# Calculate the Subject header, in the member's preferred language.
with _.using(member.preferred_language.code):
subject = _('$mlist.real_name mailing list probe message')
subject = _('$mlist.display_name mailing list probe message')
# Craft the probe message. This will be a multipart where the first part
# is the probe text and the second part is the message that caused this
# probe to be sent.
......
......@@ -119,13 +119,13 @@ the system, they won't be created again.
>>> user_b = user_manager.get_user('bperson@example.com')
>>> user_c = user_manager.get_user('cperson@example.com')
>>> user_d = user_manager.get_user('dperson@example.com')
>>> user_a.real_name = 'Anne Person'
>>> user_b.real_name = 'Bart Person'
>>> user_c.real_name = 'Caty Person'
>>> user_d.real_name = 'Dirk Person'
>>> user_a.display_name = 'Anne Person'
>>> user_b.display_name = 'Bart Person'
>>> user_c.display_name = 'Caty Person'
>>> user_d.display_name = 'Dirk Person'
>>> mlist_3 = create_list('test_3@example.com', owners)
>>> dump_list(user.real_name for user in mlist_3.owners.users)
>>> dump_list(user.display_name for user in mlist_3.owners.users)
Anne Person
Bart Person
Caty Person
......
......@@ -43,7 +43,7 @@ from mailman.utilities.i18n import make
def add_member(mlist, email, realname, password, delivery_mode, language,
def add_member(mlist, email, display_name, password, delivery_mode, language,
role=MemberRole.member):
"""Add a member right now.
......@@ -54,8 +54,8 @@ def add_member(mlist, email, realname, password, delivery_mode, language,
:type mlist: `IMailingList`
:param email: The email address to subscribe.
:type email: str
:param realname: The subscriber's full name.
:type realname: str
:param display_name: The subscriber's full name.
:type display_name: str
:param password: The subscriber's plain text password.
:type password: str
:param delivery_mode: The delivery mode the subscriber has chosen.
......@@ -86,14 +86,15 @@ def add_member(mlist, email, realname, password, delivery_mode, language,
if address is None:
# Nope, we don't even know about this address, so create both the
# user and address now.
user = user_manager.create_user(email, realname)
user = user_manager.create_user(email, display_name)
# Do it this way so we don't have to flush the previous change.
address = list(user.addresses)[0]
else:
# The address object exists, but it's not linked to a user.
# Create the user and link it now.
user = user_manager.create_user()
user.real_name = (realname if realname else address.real_name)
user.display_name = (
display_name if display_name else address.display_name)
user.link(address)
# Encrypt the password using the currently selected scheme. The
# scheme is recorded in the hashed password string.
......@@ -148,12 +149,12 @@ def delete_member(mlist, email, admin_notif=None, userack=None):
# ...and to the administrator.
if admin_notif:
user = getUtility(IUserManager).get_user(email)
realname = user.real_name
subject = _('$mlist.real_name unsubscription notification')
display_name = user.display_name
subject = _('$mlist.display_name unsubscription notification')
text = make('adminunsubscribeack.txt',
mailing_list=mlist,
listname=mlist.real_name,
member=formataddr((realname, email)),
listname=mlist.display_name,
member=formataddr((display_name, email)),
)
msg = OwnerNotification(mlist, subject, text,
roster=mlist.administrators)
......
......@@ -162,7 +162,7 @@ def handle_message(mlist, id, action,
# Get a copy of the original message from the message store.
msg = message_store.get_message_by_id(message_id)
# It's possible the forwarding address list is a comma separated list
# of realname/address pairs.
# of display_name/address pairs.
addresses = [addr[1] for addr in getaddresses(forward)]
language = mlist.preferred_language
if len(addresses) == 1:
......@@ -197,10 +197,10 @@ def handle_message(mlist, id, action,
def hold_subscription(mlist, address, realname, password, mode, language):
def hold_subscription(mlist, address, display_name, password, mode, language):
data = dict(when=now().isoformat(),
address=address,
realname=realname,
display_name=display_name,
password=password,
delivery_mode=str(mode),
language=language)
......@@ -213,7 +213,7 @@ def hold_subscription(mlist, address, realname, password, mode, language):
# Possibly notify the administrator in default list language
if mlist.admin_immed_notify:
subject = _(
'New subscription request to list $mlist.real_name from $address')
'New subscription request to $mlist.display_name from $address')
text = make('subauth.txt',
mailing_list=mlist,
username=address,
......@@ -249,11 +249,11 @@ def handle_subscription(mlist, id, action, comment=None):
enum_value = data['delivery_mode'].split('.')[-1]
delivery_mode = DeliveryMode(enum_value)
address = data['address']
realname = data['realname']
display_name = data['display_name']
language = getUtility(ILanguageManager)[data['language']]
password = data['password']
try:
add_member(mlist, address, realname, password,
add_member(mlist, address, display_name, password,
delivery_mode, language)
except AlreadySubscribedError:
# The address got subscribed in some other way after the original
......@@ -264,9 +264,9 @@ def handle_subscription(mlist, id, action, comment=None):
send_welcome_message(mlist, address, language, delivery_mode)
if mlist.admin_notify_mchanges:
send_admin_subscription_notice(
mlist, address, realname, language)
mlist, address, display_name, language)
slog.info('%s: new %s, %s %s', mlist.fqdn_listname,
delivery_mode, formataddr((realname, address)),
delivery_mode, formataddr((display_name, address)),
'via admin approval')
else:
raise AssertionError('Unexpected action: {0}'.format(action))
......@@ -285,7 +285,7 @@ def hold_unsubscription(mlist, address):
# Possibly notify the administrator of the hold
if mlist.admin_immed_notify:
subject = _(
'New unsubscription request from $mlist.real_name by $address')
'New unsubscription request from $mlist.display_name by $address')
text = make('unsubauth.txt',
mailing_list=mlist,
address=address,
......@@ -335,7 +335,7 @@ def _refuse(mlist, request, recip, comment, origmsg=None, lang=None):
# As this message is going to the requester, try to set the language to
# his/her language choice, if they are a member. Otherwise use the list's
# preferred language.
realname = mlist.real_name
display_name = mlist.display_name
if lang is None:
member = mlist.members.get_member(recip)
lang = (mlist.preferred_language
......@@ -357,7 +357,7 @@ def _refuse(mlist, request, recip, comment, origmsg=None, lang=None):
'---------- ' + _('Original Message') + ' ----------',
str(origmsg)
])
subject = _('Request to mailing list "$realname" rejected')
subject = _('Request to mailing list "$display_name" rejected')
msg = UserNotification(recip, mlist.bounces_address, subject, text, lang)
msg.send(mlist)
......
......@@ -17,7 +17,7 @@
"""Sending notifications."""
from __future__ import unicode_literals
from __future__ import absolute_import, print_function, unicode_literals
__metaclass__ = type
__all__ = [
......@@ -80,12 +80,12 @@ def send_welcome_message(mlist, address, language, delivery_mode, text=''):
# Find the IMember object which is subscribed to the mailing list, because
# from there, we can get the member's options url.
member = mlist.members.get_member(address)
user_name = member.user.real_name
user_name = member.user.display_name
options_url = member.options_url
# Get the text from the template.
text = expand(welcome, dict(
fqdn_listname=mlist.fqdn_listname,
list_name=mlist.real_name,
list_name=mlist.display_name,
listinfo_uri=mlist.script_url('listinfo'),
list_requests=mlist.request_address,
user_name=user_name,
......@@ -99,7 +99,7 @@ def send_welcome_message(mlist, address, language, delivery_mode, text=''):
msg = UserNotification(
formataddr((user_name, address)),
mlist.request_address,
_('Welcome to the "$mlist.real_name" mailing list${digmode}'),
_('Welcome to the "$mlist.display_name" mailing list${digmode}'),
text, language)
msg['X-No-Archive'] = 'yes'
msg.send(mlist, verp=as_boolean(config.mta.verp_personalized_deliveries))
......@@ -125,31 +125,32 @@ def send_goodbye_message(mlist, address, language):
goodbye = ''
msg = UserNotification(
address, mlist.bounces_address,
_('You have been unsubscribed from the $mlist.real_name mailing list'),
_('You have been unsubscribed from the $mlist.display_name '
'mailing list'),
goodbye, language)
msg.send(mlist, verp=as_boolean(config.mta.verp_personalized_deliveries))
def send_admin_subscription_notice(mlist, address, full_name, language):
def send_admin_subscription_notice(mlist, address, display_name, language):
"""Send the list administrators a subscription notice.
:param mlist: the mailing list
:param mlist: The mailing list.
:type mlist: IMailingList
:param address: the address being subscribed
:param address: The address being subscribed.
:type address: string
:param full_name: the name of the subscriber
:type full_name: string
:param language: the language of the address's realname
:param display_name: The name of the subscriber.
:type display_name: string
:param language: The language of the address's display name.
:type language: string
"""
with _.using(mlist.preferred_language.code):
subject = _('$mlist.real_name subscription notification')
full_name = full_name.encode(language.charset, 'replace')
subject = _('$mlist.display_name subscription notification')
display_name = display_name.encode(language.charset, 'replace')
text = make('adminsubscribeack.txt',
mailing_list=mlist,
listname=mlist.real_name,
member=formataddr((full_name, address)),
listname=mlist.display_name,
member=formataddr((display_name, address)),
)
msg = OwnerNotification(mlist, subject, text, roster=mlist.administrators)
msg.send(mlist)
......@@ -59,7 +59,7 @@ class Registrar:
implements(IRegistrar)
def register(self, mlist, email, real_name=None, delivery_mode=None):
def register(self, mlist, email, display_name=None, delivery_mode=None):
"""See `IUserRegistrar`."""
if delivery_mode is None:
delivery_mode = DeliveryMode.regular
......@@ -70,7 +70,7 @@ class Registrar:
pendable = PendableRegistration(
type=PendableRegistration.PEND_KEY,
email=email,
real_name=real_name,
display_name=display_name,
delivery_mode=delivery_mode.name)
pendable['list_name'] = mlist.fqdn_listname
token = getUtility(IPendings).add(pendable)
......@@ -104,7 +104,7 @@ class Registrar:
return False
missing = object()
email = pendable.get('email', missing)
real_name = pendable.get('real_name', missing)
display_name = pendable.get('display_name', missing)
list_name = pendable.get('list_name', missing)
pended_delivery_mode = pendable.get('delivery_mode', 'regular')
try:
......@@ -133,7 +133,7 @@ class Registrar:
# and link the two together
if address is None:
assert user is None, 'How did we get a user but not an address?'
user = user_manager.create_user(email, real_name)
user = user_manager.create_user(email, display_name)
# Because the database changes haven't been flushed, we can't use
# IUserManager.get_address() to find the IAddress just created
# under the hood. Instead, iterate through the IUser's addresses,
......@@ -145,7 +145,7 @@ class Registrar:
raise AssertionError('Could not find expected IAddress')
elif user is None:
user = user_manager.create_user()
user.real_name = real_name
user.display_name = display_name
user.link(address)
else:
# The IAddress and linked IUser already exist, so all we need to
......
......@@ -145,7 +145,7 @@ class SubscriptionService:
yield member
def join(self, fqdn_listname, subscriber,
real_name=None,
display_name=None,
delivery_mode=DeliveryMode.regular,
role=MemberRole.member):
"""See `ISubscriptionService`."""
......@@ -158,8 +158,8 @@ class SubscriptionService:
# it's a valid email address, and let InvalidEmailAddressError
# propagate up.
getUtility(IEmailValidator).validate(subscriber)
if real_name is None:
real_name, at, domain = subscriber.partition('@')
if display_name is None:
display_name, at, domain = subscriber.partition('@')
# Because we want to keep the REST API simple, there is no
# password or language given to us. We'll use the system's
# default language for the user's default language. We'll set the
......@@ -167,7 +167,7 @@ class SubscriptionService:
# it can't be retrieved. Note that none of these are used unless
# the address is completely new to us.
password = generate(int(config.passwords.password_length))
return add_member(mlist, subscriber, real_name, password,
return add_member(mlist, subscriber, display_name, password,
delivery_mode,
system_preferences.preferred_language, role)
else:
......
......@@ -50,7 +50,7 @@ class TestNotifications(unittest.TestCase):
def setUp(self):
self._mlist = create_list('test@example.com')
self._mlist.welcome_message_uri = 'mailman:///welcome.txt'
self._mlist.real_name = 'Test List'
self._mlist.display_name = 'Test List'
self.var_dir = tempfile.mkdtemp()
config.push('template config', """\
[paths.testing]
......
......@@ -109,7 +109,7 @@ class Lists:
for mlist in mailing_lists:
if args.names:
identifier = '{0} [{1}]'.format(
mlist.fqdn_listname, mlist.real_name)
mlist.fqdn_listname, mlist.display_name)
else:
identifier = mlist.fqdn_listname
longest = max(len(identifier), longest)
......
......@@ -17,7 +17,7 @@
"""The 'members' subcommand."""
from __future__ import absolute_import, unicode_literals
from __future__ import absolute_import, print_function, unicode_literals
__metaclass__ = type
__all__ = [
......@@ -155,7 +155,7 @@ class Members:
try:
addresses = list(mlist.members.addresses)
if len(addresses) == 0:
print >> fp, mlist.fqdn_listname, 'has no members'
print(mlist.fqdn_listname, 'has no members', file=fp)
return
for address in sorted(addresses, key=attrgetter('email')):
if args.regular:
......@@ -170,8 +170,9 @@ class Members:
member = mlist.members.get_member(address.email)
if member.delivery_status not in status_types:
continue
print >> fp, formataddr(
(address.real_name, address.original_email))
print(
formataddr((address.display_name, address.original_email)),
file=fp)
finally:
if fp is not sys.stdout:
fp.close()
......@@ -194,19 +195,20 @@ class Members:
if line.startswith('#') or len(line.strip()) == 0:
continue
# Parse the line and ensure that the values are unicodes.
real_name, email = parseaddr(line)
real_name = real_name.decode(fp.encoding)
display_name, email = parseaddr(line)
display_name = display_name.decode(fp.encoding)
email = email.decode(fp.encoding)
# Give the user a default, user-friendly password.
password = generate(int(config.passwords.password_length))
try:
add_member(mlist, email, real_name, password,
add_member(mlist, email, display_name, password,
DeliveryMode.regular,
mlist.preferred_language.code)
except AlreadySubscribedError:
# It's okay if the address is already subscribed, just
# print a warning and continue.
print 'Already subscribed (skipping):', email, real_name
print('Already subscribed (skipping):',
email, display_name)
finally:
if fp is not sys.stdin:
fp.close()
......
......@@ -230,8 +230,8 @@ As another example, say you wanted to change the display name for a particular
mailing list. You could put the following function in a file called
'change.pw':
def change(mlist, real_name):
mlist.real_name = real_name
def change(mlist, display_name):
mlist.display_name = display_name
# Required to save changes to the database.
commit()
......
......@@ -48,9 +48,9 @@ import, the mailing list's 'real name' has changed.
>>> FakeArgs.pickle_file = [
... resource_filename('mailman.testing', 'config.pck')]
>>> print mlist.real_name
>>> print mlist.display_name
Import
>>> command.process(FakeArgs)
>>> print mlist.real_name
>>> print mlist.display_name
Test
......@@ -157,7 +157,7 @@ list.
<BLANKLINE>
>>> user = user_manager.get_user('anne@example.com')
>>> print user.real_name
>>> print user.display_name
Anne Person
>>> list(user.addresses)
[<Address: Anne Person <anne@example.com> [verified] at ...>]
......
......@@ -54,8 +54,8 @@ single argument, the mailing list.
... def showme(mailing_list):
... print "The list's name is", mailing_list.fqdn_listname
...
... def realname(mailing_list):
... print "The list's real name is", mailing_list.real_name
... def displayname(mailing_list):
... print "The list's display name is", mailing_list.display_name
... """
If the name of the function is the same as the module, then you only need to
......@@ -71,9 +71,9 @@ name the function once.
The function's name can also be different than the modules name. In that
case, just give the full module path name to the function you want to call.
>>> args.run = 'showme.realname'
>>> args.run = 'showme.displayname'
>>> command.process(args)
The list's real name is Aardvark
The list's display name is Aardvark
Multiple lists
......@@ -89,14 +89,14 @@ must start with a caret.
>>> args.listname = '^.*example.com'
>>> command.process(args)
The list's real name is Aardvark
The list's real name is Badger
The list's real name is Badboys
The list's display name is Aardvark
The list's display name is Badger
The list's display name is Badboys
>>> args.listname = '^bad.*'
>>> command.process(args)
The list's real name is Badger
The list's real name is Badboys
The list's display name is Badger
The list's display name is Badboys
>>> args.listname = '^foo'
>>> command.process(args)
......
......@@ -65,7 +65,7 @@ used.
delivery_mode = self._parse_arguments(arguments, results)
if delivery_mode is ContinueProcessing.no:
return ContinueProcessing.no
real_name, address = parseaddr(msg['from'])
display_name, address = parseaddr(msg['from'])
# Address could be None or the empty string.
if not address:
address = msg.sender
......@@ -81,7 +81,7 @@ used.
return ContinueProcessing.yes
joins.add(address)
results.joins = joins
person = formataddr((real_name, address))
person = formataddr((display_name, address))
# Is this person already a member of the list? Search for all
# matching memberships.
members = getUtility(ISubscriptionService).find_members(
......@@ -90,7 +90,7 @@ used.
print(_('$person is already a member'), file=results)
else:
getUtility(IRegistrar).register(mlist, address,
real_name, delivery_mode)
display_name, delivery_mode)
print(_('Confirmation email sent to $person'), file=results)
return ContinueProcessing.yes
......@@ -177,7 +177,7 @@ You may be asked to confirm your request.""")
file=results)
return ContinueProcessing.no
member.unsubscribe()
person = formataddr((user.real_name, email))
person = formataddr((user.display_name, email))
print(_('$person left $mlist.fqdn_listname'), file=results)
return ContinueProcessing.yes
......
......@@ -89,7 +89,7 @@ CREATE TABLE mailinglist (
posting_pipeline TEXT,
preferred_language TEXT,
private_roster BOOLEAN,
real_name TEXT,
display_name TEXT,
reject_these_nonmembers BYTEA,
reply_goes_to_list INTEGER,
reply_to_address TEXT,
......@@ -154,7 +154,7 @@ CREATE TABLE address (
id SERIAL NOT NULL,
email TEXT,
_original TEXT,
real_name TEXT,
display_name TEXT,
verified_on TIMESTAMP,
registered_on TIMESTAMP,
user_id INTEGER,
......@@ -168,7 +168,7 @@ CREATE TABLE address (
CREATE TABLE "user" (
id SERIAL NOT NULL,
real_name TEXT,
display_name TEXT,
password BYTEA,
_user_id UUID,
_created_on TIMESTAMP,
......
......@@ -27,7 +27,7 @@ CREATE TABLE address (
id INTEGER NOT NULL,
email TEXT,
_original TEXT,
real_name TEXT,
display_name TEXT,
verified_on TIMESTAMP,
registered_on TIMESTAMP,
user_id INTEGER,
......@@ -185,7 +185,7 @@ CREATE TABLE mailinglist (
posting_pipeline TEXT,
preferred_language TEXT,
private_roster BOOLEAN,
real_name TEXT,
display_name TEXT,
reject_these_nonmembers BLOB,
reply_goes_to_list INTEGER,
reply_to_address TEXT,
......@@ -278,7 +278,7 @@ CREATE TABLE preferences (
CREATE TABLE user (
id INTEGER NOT NULL,
real_name TEXT,
display_name TEXT,
password BINARY,
_user_id TEXT,
_created_on TIMESTAMP,
......
......@@ -62,6 +62,7 @@ Database
- digest_footer -> digest_footer_uri
- start_chain -> posting_chain
- pipeline -> posting_pipeline
- real_name -> display_name (mailinglist, user, address)
REST
----
......@@ -86,6 +87,9 @@ Interfaces
* New `ITemplateLoader` utility.
* `ILanguageManager.add()` returns the `ILanguage` object just created.
* `IMailinglist.decorators` removed; it was unused
* `IMailingList.real_name` -> `IMailingList.display_name`
* `IUser.real_name` -> `IUser.display_name`
* `IAddress.real_name` -> `IAddress.display_name`
Commands
--------
......
......@@ -142,7 +142,7 @@ class Message(email.message.Message):
else '')
else:
field_values = self.get_all(header, [])
senders.extend(address.lower() for (real_name, address)
senders.extend(address.lower() for (display_name, address)
in email.utils.getaddresses(field_values))
# Filter out None and the empty string.
return [sender for sender in senders if sender]
......
......@@ -84,8 +84,8 @@ class IAddress(Interface):
case preserved email address; `email` will always be lower case.
""")
real_name = Attribute(
"""Optional real name associated with the email address.""")
display_name = Attribute(
"""Optional display name associated with the email address.""")
registered_on = Attribute(
"""The date and time at which this email address was registered.
......
......@@ -91,11 +91,9 @@ class IMailingList(Interface):
domain = Attribute(
"""The `IDomain` that this mailing list is defined in.""")
real_name = Attribute("""\
The short human-readable descriptive name for the mailing list. By
default, this is the capitalized `list_name`, but it can be changed to
anything. This is used in locations such as the message footers and
Subject prefix.
display_name = Attribute("""\
The short human-readable descriptive name for the mailing list. This
is used in locations such as the message footers and Subject prefix.
""")
description = Attribute("""\
......
......@@ -42,7 +42,7 @@ class IRegistrar(Interface):
syntax checking, or confirmation, while this interface does.
"""
def register(mlist, email, real_name=None, delivery_mode=None):
def register(mlist, email, display_name=None, delivery_mode=None):
"""Register the email address, requesting verification.
No `IAddress` or `IUser` is created during this step, but after
......@@ -58,8 +58,8 @@ class IRegistrar(Interface):
:type mlist: `IMailingList`
:param email: The email address to register.
:type email: str
:param real_name: The optional real name of the user.
:type real_name: str
:param display_name: The optional display name of the user.
:type display_name: str
:param delivery_mode: The optional delivery mode for this
registration. If not given, regular delivery is used.
:type delivery_mode: `DeliveryMode`
......
......@@ -92,7 +92,7 @@ class ISubscriptionService(Interface):
def __iter__():
"""See `get_members()`."""
def join(fqdn_listname, subscriber, real_name=None,
def join(fqdn_listname, subscriber, display_name=None,
delivery_mode=DeliveryMode.regular,
role=MemberRole.member):
"""Subscribe to a mailing list.
......@@ -109,10 +109,10 @@ class ISubscriptionService(Interface):
:param subscriber: The email address or user id of the user getting
subscribed.
:type subscriber: string or int
:param real_name: The name of the user. This is only used if a new
:param display_name: The name of the user. This is only used if a new
user is created, and it defaults to the local part of the email
address if not given.
:type real_name: string
:type display_name: string
:param delivery_mode: The delivery mode for this subscription. This
can be one of the enum values of `DeliveryMode`. If not given,
regular delivery is assumed.
......
......@@ -47,8 +47,8 @@ class UnverifiedAddressError(MailmanError):
class IUser(Interface):
"""A basic user."""
real_name = Attribute(
"""This user's real name.""")
display_name = Attribute(
"""This user's display name.""")
password = Attribute(
"""This user's password information.""")
......@@ -68,17 +68,17 @@ class IUser(Interface):
memberships = Attribute(
"""A roster of this user's memberships.""")
def register(email, real_name=None):
def register(email, display_name=None):
"""Register the given email address and link it to this user.