summaryrefslogtreecommitdiff
path: root/src/mailman/model
diff options
context:
space:
mode:
Diffstat (limited to 'src/mailman/model')
-rw-r--r--src/mailman/model/address.py7
-rw-r--r--src/mailman/model/autorespond.py29
-rw-r--r--src/mailman/model/bans.py45
-rw-r--r--src/mailman/model/bounce.py28
-rw-r--r--src/mailman/model/digests.py7
-rw-r--r--src/mailman/model/docs/pending.rst9
-rw-r--r--src/mailman/model/docs/registration.rst9
-rw-r--r--src/mailman/model/docs/requests.rst2
-rw-r--r--src/mailman/model/domain.py48
-rw-r--r--src/mailman/model/language.py7
-rw-r--r--src/mailman/model/listmanager.py54
-rw-r--r--src/mailman/model/mailinglist.py14
-rw-r--r--src/mailman/model/member.py16
-rw-r--r--src/mailman/model/message.py15
-rw-r--r--src/mailman/model/messagestore.py38
-rw-r--r--src/mailman/model/mime.py8
-rw-r--r--src/mailman/model/pending.py33
-rw-r--r--src/mailman/model/preferences.py7
-rw-r--r--src/mailman/model/requests.py50
-rw-r--r--src/mailman/model/roster.py54
-rw-r--r--src/mailman/model/tests/test_bounce.py25
-rw-r--r--src/mailman/model/uid.py18
-rw-r--r--src/mailman/model/user.py26
-rw-r--r--src/mailman/model/usermanager.py56
24 files changed, 339 insertions, 266 deletions
diff --git a/src/mailman/model/address.py b/src/mailman/model/address.py
index a12a993a8..d8ab65a80 100644
--- a/src/mailman/model/address.py
+++ b/src/mailman/model/address.py
@@ -17,7 +17,7 @@
"""Model for addresses."""
-from __future__ import absolute_import, unicode_literals
+from __future__ import absolute_import, print_function, unicode_literals
__metaclass__ = type
__all__ = [
@@ -28,7 +28,7 @@ __all__ = [
from email.utils import formataddr
from storm.locals import DateTime, Int, Reference, Unicode
from zope.event import notify
-from zope.interface import implements
+from zope.interface import implementer
from mailman.database.model import Model
from mailman.interfaces.address import AddressVerificationEvent, IAddress
@@ -36,8 +36,9 @@ from mailman.utilities.datetime import now
+@implementer(IAddress)
class Address(Model):
- implements(IAddress)
+ """See `IAddress`."""
id = Int(primary=True)
email = Unicode()
diff --git a/src/mailman/model/autorespond.py b/src/mailman/model/autorespond.py
index 7b42205b4..567dcd19e 100644
--- a/src/mailman/model/autorespond.py
+++ b/src/mailman/model/autorespond.py
@@ -17,7 +17,7 @@
"""Module stuff."""
-from __future__ import absolute_import, unicode_literals
+from __future__ import absolute_import, print_function, unicode_literals
__metaclass__ = type
__all__ = [
@@ -27,10 +27,10 @@ __all__ = [
from storm.locals import And, Date, Desc, Int, Reference
-from zope.interface import implements
+from zope.interface import implementer
-from mailman.config import config
from mailman.database.model import Model
+from mailman.database.transaction import dbconnection
from mailman.database.types import Enum
from mailman.interfaces.autorespond import (
IAutoResponseRecord, IAutoResponseSet, Response)
@@ -38,8 +38,9 @@ from mailman.utilities.datetime import today
+@implementer(IAutoResponseRecord)
class AutoResponseRecord(Model):
- implements(IAutoResponseRecord)
+ """See `IAutoResponseRecord`."""
id = Int(primary=True)
@@ -60,33 +61,37 @@ class AutoResponseRecord(Model):
+@implementer(IAutoResponseSet)
class AutoResponseSet:
- implements(IAutoResponseSet)
+ """See `IAutoResponseSet`."""
def __init__(self, mailing_list):
self._mailing_list = mailing_list
- def todays_count(self, address, response_type):
+ @dbconnection
+ def todays_count(self, store, address, response_type):
"""See `IAutoResponseSet`."""
- return config.db.store.find(
+ return store.find(
AutoResponseRecord,
And(AutoResponseRecord.address == address,
AutoResponseRecord.mailing_list == self._mailing_list,
AutoResponseRecord.response_type == response_type,
AutoResponseRecord.date_sent == today())).count()
- def response_sent(self, address, response_type):
+ @dbconnection
+ def response_sent(self, store, address, response_type):
"""See `IAutoResponseSet`."""
response = AutoResponseRecord(
self._mailing_list, address, response_type)
- config.db.store.add(response)
+ store.add(response)
- def last_response(self, address, response_type):
+ @dbconnection
+ def last_response(self, store, address, response_type):
"""See `IAutoResponseSet`."""
- results = config.db.store.find(
+ results = store.find(
AutoResponseRecord,
And(AutoResponseRecord.address == address,
AutoResponseRecord.mailing_list == self._mailing_list,
AutoResponseRecord.response_type == response_type)
- ).order_by(Desc(AutoResponseRecord.date_sent))
+ ).order_by(Desc(AutoResponseRecord.date_sent))
return (None if results.count() == 0 else results.first())
diff --git a/src/mailman/model/bans.py b/src/mailman/model/bans.py
index 9dc0c51ba..b6de9336f 100644
--- a/src/mailman/model/bans.py
+++ b/src/mailman/model/bans.py
@@ -17,7 +17,7 @@
"""Ban manager."""
-from __future__ import absolute_import, unicode_literals
+from __future__ import absolute_import, print_function, unicode_literals
__metaclass__ = type
__all__ = [
@@ -28,16 +28,17 @@ __all__ = [
import re
from storm.locals import Int, Unicode
-from zope.interface import implements
+from zope.interface import implementer
-from mailman.config import config
from mailman.database.model import Model
+from mailman.database.transaction import dbconnection
from mailman.interfaces.bans import IBan, IBanManager
+@implementer(IBan)
class Ban(Model):
- implements(IBan)
+ """See `IBan`."""
id = Int(primary=True)
email = Unicode()
@@ -50,46 +51,47 @@ class Ban(Model):
+@implementer(IBanManager)
class BanManager:
- implements(IBanManager)
+ """See `IBanManager`."""
- def ban(self, email, mailing_list=None):
+ @dbconnection
+ def ban(self, store, email, mailing_list=None):
"""See `IBanManager`."""
- bans = config.db.store.find(
- Ban, email=email, mailing_list=mailing_list)
+ bans = store.find(Ban, email=email, mailing_list=mailing_list)
if bans.count() == 0:
ban = Ban(email, mailing_list)
- config.db.store.add(ban)
+ store.add(ban)
- def unban(self, email, mailing_list=None):
+ @dbconnection
+ def unban(self, store, email, mailing_list=None):
"""See `IBanManager`."""
- ban = config.db.store.find(
- Ban, email=email, mailing_list=mailing_list).one()
+ ban = store.find(Ban, email=email, mailing_list=mailing_list).one()
if ban is not None:
- config.db.store.remove(ban)
+ store.remove(ban)
- def is_banned(self, email, mailing_list=None):
+ @dbconnection
+ def is_banned(self, store, email, mailing_list=None):
"""See `IBanManager`."""
# A specific mailing list ban is being checked, however the email
# address could be banned specifically, or globally.
if mailing_list is not None:
# Try specific bans first.
- bans = config.db.store.find(
- Ban, email=email, mailing_list=mailing_list)
+ bans = store.find(Ban, email=email, mailing_list=mailing_list)
if bans.count() > 0:
return True
# Try global bans next.
- bans = config.db.store.find(Ban, email=email, mailing_list=None)
+ bans = store.find(Ban, email=email, mailing_list=None)
if bans.count() > 0:
return True
# Now try specific mailing list bans, but with a pattern.
- bans = config.db.store.find(Ban, mailing_list=mailing_list)
+ bans = store.find(Ban, mailing_list=mailing_list)
for ban in bans:
if (ban.email.startswith('^') and
re.match(ban.email, email, re.IGNORECASE) is not None):
return True
# And now try global pattern bans.
- bans = config.db.store.find(Ban, mailing_list=None)
+ bans = store.find(Ban, mailing_list=None)
for ban in bans:
if (ban.email.startswith('^') and
re.match(ban.email, email, re.IGNORECASE) is not None):
@@ -97,12 +99,11 @@ class BanManager:
else:
# The client is asking for global bans. Look up bans on the
# specific email address first.
- bans = config.db.store.find(
- Ban, email=email, mailing_list=None)
+ bans = store.find(Ban, email=email, mailing_list=None)
if bans.count() > 0:
return True
# And now look for global pattern bans.
- bans = config.db.store.find(Ban, mailing_list=None)
+ bans = store.find(Ban, mailing_list=None)
for ban in bans:
if (ban.email.startswith('^') and
re.match(ban.email, email, re.IGNORECASE) is not None):
diff --git a/src/mailman/model/bounce.py b/src/mailman/model/bounce.py
index 8c55e3d16..628e076bf 100644
--- a/src/mailman/model/bounce.py
+++ b/src/mailman/model/bounce.py
@@ -17,7 +17,7 @@
"""Bounce support."""
-from __future__ import absolute_import, unicode_literals
+from __future__ import absolute_import, print_function, unicode_literals
__metaclass__ = type
__all__ = [
@@ -27,10 +27,10 @@ __all__ = [
from storm.locals import Bool, Int, DateTime, Unicode
-from zope.interface import implements
+from zope.interface import implementer
-from mailman.config import config
from mailman.database.model import Model
+from mailman.database.transaction import dbconnection
from mailman.database.types import Enum
from mailman.interfaces.bounce import (
BounceContext, IBounceEvent, IBounceProcessor)
@@ -38,8 +38,9 @@ from mailman.utilities.datetime import now
+@implementer(IBounceEvent)
class BounceEvent(Model):
- implements(IBounceEvent)
+ """See `IBounceEvent`."""
id = Int(primary=True)
list_name = Unicode()
@@ -59,24 +60,27 @@ class BounceEvent(Model):
+@implementer(IBounceProcessor)
class BounceProcessor:
- implements(IBounceProcessor)
+ """See `IBounceProcessor`."""
- def register(self, mlist, email, msg, where=None):
+ @dbconnection
+ def register(self, store, mlist, email, msg, where=None):
"""See `IBounceProcessor`."""
event = BounceEvent(mlist.fqdn_listname, email, msg, where)
- config.db.store.add(event)
+ store.add(event)
return event
@property
- def events(self):
+ @dbconnection
+ def events(self, store):
"""See `IBounceProcessor`."""
- for event in config.db.store.find(BounceEvent):
+ for event in store.find(BounceEvent):
yield event
@property
- def unprocessed(self):
+ @dbconnection
+ def unprocessed(self, store):
"""See `IBounceProcessor`."""
- for event in config.db.store.find(BounceEvent,
- BounceEvent.processed == False):
+ for event in store.find(BounceEvent, BounceEvent.processed == False):
yield event
diff --git a/src/mailman/model/digests.py b/src/mailman/model/digests.py
index d7805ebf6..1d422ce8b 100644
--- a/src/mailman/model/digests.py
+++ b/src/mailman/model/digests.py
@@ -17,7 +17,7 @@
"""One last digest."""
-from __future__ import absolute_import, unicode_literals
+from __future__ import absolute_import, print_function, unicode_literals
__metaclass__ = type
__all__ = [
@@ -26,7 +26,7 @@ __all__ = [
from storm.locals import Int, Reference
-from zope.interface import implements
+from zope.interface import implementer
from mailman.database.model import Model
from mailman.database.types import Enum
@@ -35,8 +35,9 @@ from mailman.interfaces.member import DeliveryMode
+@implementer(IOneLastDigest)
class OneLastDigest(Model):
- implements(IOneLastDigest)
+ """See `IOneLastDigest`."""
id = Int(primary=True)
diff --git a/src/mailman/model/docs/pending.rst b/src/mailman/model/docs/pending.rst
index 1bf1ee0e9..3d33dd5da 100644
--- a/src/mailman/model/docs/pending.rst
+++ b/src/mailman/model/docs/pending.rst
@@ -15,11 +15,14 @@ In order to pend an event, you first need a pending database.
The pending database can add any ``IPendable`` to the database, returning a
token that can be used in urls and such.
+::
- >>> from zope.interface import implements
+ >>> from zope.interface import implementer
>>> from mailman.interfaces.pending import IPendable
- >>> class SimplePendable(dict):
- ... implements(IPendable)
+ >>> @implementer(IPendable)
+ ... class SimplePendable(dict):
+ ... pass
+
>>> subscription = SimplePendable(
... type='subscription',
... address='aperson@example.com',
diff --git a/src/mailman/model/docs/registration.rst b/src/mailman/model/docs/registration.rst
index eecb3a8cd..58e9d7a86 100644
--- a/src/mailman/model/docs/registration.rst
+++ b/src/mailman/model/docs/registration.rst
@@ -318,12 +318,15 @@ confirm method will just return False.
Likewise, if you try to confirm, through the `IUserRegistrar` interface, a
token that doesn't match a registration event, you will get ``None``.
However, the pending event matched with that token will still be removed.
+::
>>> from mailman.interfaces.pending import IPendable
- >>> from zope.interface import implements
+ >>> from zope.interface import implementer
+
+ >>> @implementer(IPendable)
+ ... class SimplePendable(dict):
+ ... pass
- >>> class SimplePendable(dict):
- ... implements(IPendable)
>>> pendable = SimplePendable(type='foo', bar='baz')
>>> token = pendingdb.add(pendable)
>>> registrar.confirm(token)
diff --git a/src/mailman/model/docs/requests.rst b/src/mailman/model/docs/requests.rst
index a20823a91..a51cbc099 100644
--- a/src/mailman/model/docs/requests.rst
+++ b/src/mailman/model/docs/requests.rst
@@ -696,7 +696,7 @@ Frank Person is now a member of the mailing list.
>>> print member.user.display_name
Frank Person
>>> print member.user.password
- {CLEARTEXT}abcxyz
+ {plaintext}abcxyz
Holding unsubscription requests
diff --git a/src/mailman/model/domain.py b/src/mailman/model/domain.py
index 49c935740..de6a9005a 100644
--- a/src/mailman/model/domain.py
+++ b/src/mailman/model/domain.py
@@ -17,7 +17,7 @@
"""Domains."""
-from __future__ import unicode_literals
+from __future__ import absolute_import, print_function, unicode_literals
__metaclass__ = type
__all__ = [
@@ -29,10 +29,10 @@ __all__ = [
from urlparse import urljoin, urlparse
from storm.locals import Int, Unicode
from zope.event import notify
-from zope.interface import implements
+from zope.interface import implementer
-from mailman.config import config
from mailman.database.model import Model
+from mailman.database.transaction import dbconnection
from mailman.interfaces.domain import (
BadDomainSpecificationError, DomainCreatedEvent, DomainCreatingEvent,
DomainDeletedEvent, DomainDeletingEvent, IDomain, IDomainManager)
@@ -40,11 +40,10 @@ from mailman.model.mailinglist import MailingList
+@implementer(IDomain)
class Domain(Model):
"""Domains."""
- implements(IDomain)
-
id = Int(primary=True)
mail_host = Unicode()
@@ -90,9 +89,10 @@ class Domain(Model):
return urlparse(self.base_url).scheme
@property
- def mailing_lists(self):
+ @dbconnection
+ def mailing_lists(self, store):
"""See `IDomain`."""
- mailing_lists = config.db.store.find(
+ mailing_lists = store.find(
MailingList,
MailingList.mail_host == self.mail_host)
for mlist in mailing_lists:
@@ -114,12 +114,13 @@ class Domain(Model):
+@implementer(IDomainManager)
class DomainManager:
"""Domain manager."""
- implements(IDomainManager)
-
- def add(self, mail_host,
+ @dbconnection
+ def add(self, store,
+ mail_host,
description=None,
base_url=None,
contact_address=None):
@@ -131,20 +132,22 @@ class DomainManager:
'Duplicate email host: %s' % mail_host)
notify(DomainCreatingEvent(mail_host))
domain = Domain(mail_host, description, base_url, contact_address)
- config.db.store.add(domain)
+ store.add(domain)
notify(DomainCreatedEvent(domain))
return domain
- def remove(self, mail_host):
+ @dbconnection
+ def remove(self, store, mail_host):
domain = self[mail_host]
notify(DomainDeletingEvent(domain))
- config.db.store.remove(domain)
+ store.remove(domain)
notify(DomainDeletedEvent(mail_host))
return domain
- def get(self, mail_host, default=None):
+ @dbconnection
+ def get(self, store, mail_host, default=None):
"""See `IDomainManager`."""
- domains = config.db.store.find(Domain, mail_host=mail_host)
+ domains = store.find(Domain, mail_host=mail_host)
if domains.count() < 1:
return default
assert domains.count() == 1, (
@@ -159,14 +162,17 @@ class DomainManager:
raise KeyError(mail_host)
return domain
- def __len__(self):
- return config.db.store.find(Domain).count()
+ @dbconnection
+ def __len__(self, store):
+ return store.find(Domain).count()
- def __iter__(self):
+ @dbconnection
+ def __iter__(self, store):
"""See `IDomainManager`."""
- for domain in config.db.store.find(Domain):
+ for domain in store.find(Domain):
yield domain
- def __contains__(self, mail_host):
+ @dbconnection
+ def __contains__(self, store, mail_host):
"""See `IDomainManager`."""
- return config.db.store.find(Domain, mail_host=mail_host).count() > 0
+ return store.find(Domain, mail_host=mail_host).count() > 0
diff --git a/src/mailman/model/language.py b/src/mailman/model/language.py
index da86b326c..b593721df 100644
--- a/src/mailman/model/language.py
+++ b/src/mailman/model/language.py
@@ -17,7 +17,7 @@
"""Model for languages."""
-from __future__ import absolute_import, unicode_literals
+from __future__ import absolute_import, print_function, unicode_literals
__metaclass__ = type
__all__ = [
@@ -26,15 +26,16 @@ __all__ = [
from storm.locals import Int, Unicode
-from zope.interface import implements
+from zope.interface import implementer
from mailman.database import Model
from mailman.interfaces import ILanguage
+@implementer(ILanguage)
class Language(Model):
- implements(ILanguage)
+ """See `ILanguage`."""
id = Int(primary=True)
code = Unicode()
diff --git a/src/mailman/model/listmanager.py b/src/mailman/model/listmanager.py
index 0ea87a082..b4bc4b323 100644
--- a/src/mailman/model/listmanager.py
+++ b/src/mailman/model/listmanager.py
@@ -17,7 +17,7 @@
"""A mailing list manager."""
-from __future__ import absolute_import, unicode_literals
+from __future__ import absolute_import, print_function, unicode_literals
__metaclass__ = type
__all__ = [
@@ -26,9 +26,9 @@ __all__ = [
from zope.event import notify
-from zope.interface import implements
+from zope.interface import implementer
-from mailman.config import config
+from mailman.database.transaction import dbconnection
from mailman.interfaces.address import InvalidEmailAddressError
from mailman.interfaces.listmanager import (
IListManager, ListAlreadyExistsError, ListCreatedEvent, ListCreatingEvent,
@@ -38,18 +38,18 @@ from mailman.utilities.datetime import now
+@implementer(IListManager)
class ListManager:
"""An implementation of the `IListManager` interface."""
- implements(IListManager)
-
- def create(self, fqdn_listname):
+ @dbconnection
+ def create(self, store, fqdn_listname):
"""See `IListManager`."""
listname, at, hostname = fqdn_listname.partition('@')
if len(hostname) == 0:
raise InvalidEmailAddressError(fqdn_listname)
notify(ListCreatingEvent(fqdn_listname))
- mlist = config.db.store.find(
+ mlist = store.find(
MailingList,
MailingList.list_name == listname,
MailingList.mail_host == hostname).one()
@@ -57,47 +57,53 @@ class ListManager:
raise ListAlreadyExistsError(fqdn_listname)
mlist = MailingList(fqdn_listname)
mlist.created_at = now()
- config.db.store.add(mlist)
+ store.add(mlist)
notify(ListCreatedEvent(mlist))
return mlist
- def get(self, fqdn_listname):
+ @dbconnection
+ def get(self, store, fqdn_listname):
"""See `IListManager`."""
listname, at, hostname = fqdn_listname.partition('@')
- return config.db.store.find(MailingList,
- list_name=listname,
- mail_host=hostname).one()
+ return store.find(MailingList,
+ list_name=listname,
+ mail_host=hostname).one()
- def delete(self, mlist):
+ @dbconnection
+ def delete(self, store, mlist):
"""See `IListManager`."""
fqdn_listname = mlist.fqdn_listname
notify(ListDeletingEvent(mlist))
- config.db.store.remove(mlist)
+ store.remove(mlist)
notify(ListDeletedEvent(fqdn_listname))
@property
- def mailing_lists(self):
+ @dbconnection
+ def mailing_lists(self, store):
"""See `IListManager`."""
- for mlist in config.db.store.find(MailingList):
+ for mlist in store.find(MailingList):
yield mlist
- def __iter__(self):
+ @dbconnection
+ def __iter__(self, store):
"""See `IListManager`."""
- for mlist in config.db.store.find(MailingList):
+ for mlist in store.find(MailingList):
yield mlist
@property
- def names(self):
+ @dbconnection
+ def names(self, store):
"""See `IListManager`."""
- result_set = config.db.store.find(MailingList)
- for mail_host, list_name in result_set.values(MailingList.mail_host,
+ result_set = store.find(MailingList)
+ for mail_host, list_name in result_set.values(MailingList.mail_host,
MailingList.list_name):
yield '{0}@{1}'.format(list_name, mail_host)
@property
- def name_components(self):
+ @dbconnection
+ def name_components(self, store):
"""See `IListManager`."""
- result_set = config.db.store.find(MailingList)
- for mail_host, list_name in result_set.values(MailingList.mail_host,
+ result_set = store.find(MailingList)
+ for mail_host, list_name in result_set.values(MailingList.mail_host,
MailingList.list_name):
yield list_name, mail_host
diff --git a/src/mailman/model/mailinglist.py b/src/mailman/model/mailinglist.py
index 18c411fc4..294daa566 100644
--- a/src/mailman/model/mailinglist.py
+++ b/src/mailman/model/mailinglist.py
@@ -17,7 +17,7 @@
"""Model for mailing lists."""
-from __future__ import absolute_import, unicode_literals
+from __future__ import absolute_import, print_function, unicode_literals
__metaclass__ = type
__all__ = [
@@ -33,7 +33,7 @@ from storm.locals import (
TimeDelta, Unicode)
from urlparse import urljoin
from zope.component import getUtility
-from zope.interface import implements
+from zope.interface import implementer
from mailman.config import config
from mailman.database.model import Model
@@ -68,8 +68,9 @@ UNDERSCORE = '_'
+@implementer(IMailingList)
class MailingList(Model):
- implements(IMailingList)
+ """See `IMailingList`."""
id = Int(primary=True)
@@ -490,8 +491,9 @@ class MailingList(Model):
+@implementer(IAcceptableAlias)
class AcceptableAlias(Model):
- implements(IAcceptableAlias)
+ """See `IAcceptableAlias`."""
id = Int(primary=True)
@@ -505,8 +507,10 @@ class AcceptableAlias(Model):
self.alias = alias
+
+@implementer(IAcceptableAliasSet)
class AcceptableAliasSet:
- implements(IAcceptableAliasSet)
+ """See `IAcceptableAliasSet`."""
def __init__(self, mailing_list):
self._mailing_list = mailing_list
diff --git a/src/mailman/model/member.py b/src/mailman/model/member.py
index ae83fb388..b791ea0f2 100644
--- a/src/mailman/model/member.py
+++ b/src/mailman/model/member.py
@@ -17,7 +17,7 @@
"""Model for members."""
-from __future__ import absolute_import, unicode_literals
+from __future__ import absolute_import, print_function, unicode_literals
__metaclass__ = type
__all__ = [
@@ -27,11 +27,11 @@ __all__ = [
from storm.locals import Int, Reference, Unicode
from storm.properties import UUID
from zope.component import getUtility
-from zope.interface import implements
+from zope.interface import implementer
-from mailman.config import config
from mailman.core.constants import system_preferences
from mailman.database.model import Model
+from mailman.database.transaction import dbconnection
from mailman.database.types import Enum
from mailman.interfaces.action import Action
from mailman.interfaces.address import IAddress
@@ -46,8 +46,9 @@ uid_factory = UniqueIDFactory(context='members')
+@implementer(IMember)
class Member(Model):
- implements(IMember)
+ """See `IMember`."""
id = Int(primary=True)
_member_id = UUID()
@@ -176,7 +177,8 @@ class Member(Model):
# XXX Um, this is definitely wrong
return 'http://example.com/' + self.address.email
- def unsubscribe(self):
+ @dbconnection
+ def unsubscribe(self, store):
"""See `IMember`."""
- config.db.store.remove(self.preferences)
- config.db.store.remove(self)
+ store.remove(self.preferences)
+ store.remove(self)
diff --git a/src/mailman/model/message.py b/src/mailman/model/message.py
index 3345c64c9..190b4055c 100644
--- a/src/mailman/model/message.py
+++ b/src/mailman/model/message.py
@@ -17,8 +17,7 @@
"""Model for messages."""
-
-from __future__ import absolute_import, unicode_literals
+from __future__ import absolute_import, print_function, unicode_literals
__metaclass__ = type
__all__ = [
@@ -26,28 +25,28 @@ __all__ = [
]
from storm.locals import AutoReload, Int, RawStr, Unicode
-from zope.interface import implements
+from zope.interface import implementer
-from mailman.config import config
from mailman.database.model import Model
+from mailman.database.transaction import dbconnection
from mailman.interfaces.messages import IMessage
+@implementer(IMessage)
class Message(Model):
"""A message in the message store."""
- implements(IMessage)
-
id = Int(primary=True, default=AutoReload)
message_id = Unicode()
message_id_hash = RawStr()
path = RawStr()
# This is a Messge-ID field representation, not a database row id.
- def __init__(self, message_id, message_id_hash, path):
+ @dbconnection
+ def __init__(self, store, message_id, message_id_hash, path):
super(Message, self).__init__()
self.message_id = message_id
self.message_id_hash = message_id_hash
self.path = path
- config.db.store.add(self)
+ store.add(self)
diff --git a/src/mailman/model/messagestore.py b/src/mailman/model/messagestore.py
index 59490993b..156375e6f 100644
--- a/src/mailman/model/messagestore.py
+++ b/src/mailman/model/messagestore.py
@@ -17,8 +17,7 @@
"""Model for message stores."""
-
-from __future__ import absolute_import, unicode_literals
+from __future__ import absolute_import, print_function, unicode_literals
__metaclass__ = type
__all__ = [
@@ -31,9 +30,10 @@ import base64
import hashlib
import cPickle as pickle
-from zope.interface import implements
+from zope.interface import implementer
from mailman.config import config
+from mailman.database.transaction import dbconnection
from mailman.interfaces.messages import IMessageStore
from mailman.model.message import Message
from mailman.utilities.filesystem import makedirs
@@ -46,10 +46,12 @@ EMPTYSTRING = ''
+@implementer(IMessageStore)
class MessageStore:
- implements(IMessageStore)
+ """See `IMessageStore`."""
- def add(self, message):
+ @dbconnection
+ def add(self, store, message):
# Ensure that the message has the requisite headers.
message_ids = message.get_all('message-id', [])
if len(message_ids) <> 1:
@@ -57,8 +59,7 @@ class MessageStore:
# Calculate and insert the X-Message-ID-Hash.
message_id = message_ids[0]
# Complain if the Message-ID already exists in the storage.
- existing = config.db.store.find(Message,
- Message.message_id == message_id).one()
+ existing = store.find(Message, Message.message_id == message_id).one()
if existing is not None:
raise ValueError(
'Message ID already exists in message store: {0}'.format(
@@ -104,34 +105,37 @@ class MessageStore:
with open(path) as fp:
return pickle.load(fp)
- def get_message_by_id(self, message_id):
- row = config.db.store.find(Message, message_id=message_id).one()
+ @dbconnection
+ def get_message_by_id(self, store, message_id):
+ row = store.find(Message, message_id=message_id).one()
if row is None:
return None
return self._get_message(row)
- def get_message_by_hash(self, message_id_hash):
+ @dbconnection
+ def get_message_by_hash(self, store, message_id_hash):
# It's possible the hash came from a message header, in which case it
# will be a Unicode. However when coming from source code, it may be
# an 8-string. Coerce to the latter if necessary; it must be
# US-ASCII.
if isinstance(message_id_hash, unicode):
message_id_hash = message_id_hash.encode('ascii')
- row = config.db.store.find(Message,
- message_id_hash=message_id_hash).one()
+ row = store.find(Message, message_id_hash=message_id_hash).one()
if row is None:
return None
return self._get_message(row)
@property
- def messages(self):
- for row in config.db.store.find(Message):
+ @dbconnection
+ def messages(self, store):
+ for row in store.find(Message):
yield self._get_message(row)
- def delete_message(self, message_id):
- row = config.db.store.find(Message, message_id=message_id).one()
+ @dbconnection
+ def delete_message(self, store, message_id):
+ row = store.find(Message, message_id=message_id).one()
if row is None:
raise LookupError(message_id)
path = os.path.join(config.MESSAGES_DIR, row.path)
os.remove(path)
- config.db.store.remove(row)
+ store.remove(row)
diff --git a/src/mailman/model/mime.py b/src/mailman/model/mime.py
index c611aab89..462bb9016 100644
--- a/src/mailman/model/mime.py
+++ b/src/mailman/model/mime.py
@@ -15,9 +15,9 @@
# You should have received a copy of the GNU General Public License along with
# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
-"""Module stuff."""
+"""The content filter."""
-from __future__ import absolute_import, unicode_literals
+from __future__ import absolute_import, print_function, unicode_literals
__metaclass__ = type
__all__ = [
@@ -26,7 +26,7 @@ __all__ = [
from storm.locals import Int, Reference, Unicode
-from zope.interface import implements
+from zope.interface import implementer
from mailman.database.model import Model
from mailman.database.types import Enum
@@ -34,9 +34,9 @@ from mailman.interfaces.mime import IContentFilter, FilterType
+@implementer(IContentFilter)
class ContentFilter(Model):
"""A single filter criteria."""
- implements(IContentFilter)
id = Int(primary=True)
diff --git a/src/mailman/model/pending.py b/src/mailman/model/pending.py
index 557361c6f..727e4f754 100644
--- a/src/mailman/model/pending.py
+++ b/src/mailman/model/pending.py
@@ -17,7 +17,7 @@
"""Implementations of the IPendable and IPending interfaces."""
-from __future__ import absolute_import, unicode_literals
+from __future__ import absolute_import, print_function, unicode_literals
__metaclass__ = type
__all__ = [
@@ -32,11 +32,12 @@ import hashlib
from lazr.config import as_timedelta
from storm.locals import DateTime, Int, RawStr, ReferenceSet, Unicode
-from zope.interface import implements
+from zope.interface import implementer
from zope.interface.verify import verifyObject
from mailman.config import config
from mailman.database.model import Model
+from mailman.database.transaction import dbconnection
from mailman.interfaces.pending import (
IPendable, IPended, IPendedKeyValue, IPendings)
from mailman.utilities.datetime import now
@@ -44,11 +45,10 @@ from mailman.utilities.modules import call_name
+@implementer(IPendedKeyValue)
class PendedKeyValue(Model):
"""A pended key/value pair, tied to a token."""
- implements(IPendedKeyValue)
-
def __init__(self, key, value):
self.key = key
self.value = value
@@ -59,11 +59,11 @@ class PendedKeyValue(Model):
pended_id = Int()
+
+@implementer(IPended)
class Pended(Model):
"""A pended event, tied to a token."""
- implements(IPended)
-
def __init__(self, token, expiration_date):
super(Pended, self).__init__()
self.token = token
@@ -76,17 +76,18 @@ class Pended(Model):
+@implementer(IPendable)
class UnpendedPendable(dict):
- implements(IPendable)
+ pass
+@implementer(IPendings)
class Pendings:
"""Implementation of the IPending interface."""
- implements(IPendings)
-
- def add(self, pendable, lifetime=None):
+ @dbconnection
+ def add(self, store, pendable, lifetime=None):
verifyObject(IPendable, pendable)
# Calculate the token and the lifetime.
if lifetime is None:
@@ -104,7 +105,7 @@ class Pendings:
token = hashlib.sha1(repr(x)).hexdigest()
# In practice, we'll never get a duplicate, but we'll be anal
# about checking anyway.
- if config.db.store.find(Pended, token=token).count() == 0:
+ if store.find(Pended, token=token).count() == 0:
break
else:
raise AssertionError('Could not find a valid pendings token')
@@ -129,11 +130,11 @@ class Pendings:
'\2'.join(value))
keyval = PendedKeyValue(key=key, value=value)
pending.key_values.add(keyval)
- config.db.store.add(pending)
+ store.add(pending)
return token
- def confirm(self, token, expunge=True):
- store = config.db.store
+ @dbconnection
+ def confirm(self, store, token, expunge=True):
# Token can come in as a unicode, but it's stored in the database as
# bytes. They must be ascii.
pendings = store.find(Pended, token=str(token))
@@ -158,8 +159,8 @@ class Pendings:
store.remove(pending)
return pendable
- def evict(self):
- store = config.db.store
+ @dbconnection
+ def evict(self, store):
right_now = now()
for pending in store.find(Pended):
if pending.expiration_date < right_now:
diff --git a/src/mailman/model/preferences.py b/src/mailman/model/preferences.py
index 234c7399e..fdc30a94d 100644
--- a/src/mailman/model/preferences.py
+++ b/src/mailman/model/preferences.py
@@ -17,7 +17,7 @@
"""Model for preferences."""
-from __future__ import absolute_import, unicode_literals
+from __future__ import absolute_import, print_function, unicode_literals
__metaclass__ = type
__all__ = [
@@ -27,7 +27,7 @@ __all__ = [
from storm.locals import Bool, Int, Unicode
from zope.component import getUtility
-from zope.interface import implements
+from zope.interface import implementer
from mailman.database.model import Model
from mailman.database.types import Enum
@@ -37,8 +37,9 @@ from mailman.interfaces.preferences import IPreferences
+@implementer(IPreferences)
class Preferences(Model):
- implements(IPreferences)
+ """See `IPreferences`."""
id = Int(primary=True)
acknowledge_posts = Bool()
diff --git a/src/mailman/model/requests.py b/src/mailman/model/requests.py
index 4a3efa67f..a92332e4a 100644
--- a/src/mailman/model/requests.py
+++ b/src/mailman/model/requests.py
@@ -17,7 +17,7 @@
"""Implementations of the pending requests interfaces."""
-from __future__ import absolute_import, unicode_literals
+from __future__ import absolute_import, print_function, unicode_literals
__metaclass__ = type
__all__ = [
@@ -27,52 +27,56 @@ __all__ = [
from datetime import timedelta
from storm.locals import AutoReload, Int, RawStr, Reference, Unicode
from zope.component import getUtility
-from zope.interface import implements
+from zope.interface import implementer
-from mailman.config import config
from mailman.database.model import Model
+from mailman.database.transaction import dbconnection
from mailman.database.types import Enum
from mailman.interfaces.pending import IPendable, IPendings
from mailman.interfaces.requests import IListRequests, RequestType
+@implementer(IPendable)
class DataPendable(dict):
- implements(IPendable)
+ pass
+@implementer(IListRequests)
class ListRequests:
- implements(IListRequests)
def __init__(self, mailing_list):
self.mailing_list = mailing_list
@property
- def count(self):
- return config.db.store.find(
- _Request, mailing_list=self.mailing_list).count()
+ @dbconnection
+ def count(self, store):
+ return store.find(_Request, mailing_list=self.mailing_list).count()
- def count_of(self, request_type):
- return config.db.store.find(
+ @dbconnection
+ def count_of(self, store, request_type):
+ return store.find(
_Request,
mailing_list=self.mailing_list, request_type=request_type).count()
@property
- def held_requests(self):
- results = config.db.store.find(
- _Request, mailing_list=self.mailing_list)
+ @dbconnection
+ def held_requests(self, store):
+ results = store.find(_Request, mailing_list=self.mailing_list)
for request in results:
yield request
- def of_type(self, request_type):
- results = config.db.store.find(
+ @dbconnection
+ def of_type(self, store, request_type):
+ results = store.find(
_Request,
mailing_list=self.mailing_list, request_type=request_type)
for request in results:
yield request
- def hold_request(self, request_type, key, data=None):
+ @dbconnection
+ def hold_request(self, store, request_type, key, data=None):
if request_type not in RequestType:
raise TypeError(request_type)
if data is None:
@@ -87,11 +91,12 @@ class ListRequests:
token = getUtility(IPendings).add(pendable, timedelta(days=5000))
data_hash = token
request = _Request(key, request_type, self.mailing_list, data_hash)
- config.db.store.add(request)
+ store.add(request)
return request.id
- def get_request(self, request_id, request_type=None):
- result = config.db.store.get(_Request, request_id)
+ @dbconnection
+ def get_request(self, store, request_id, request_type=None):
+ result = store.get(_Request, request_id)
if result is None:
return None
if request_type is not None and result.request_type != request_type:
@@ -104,13 +109,14 @@ class ListRequests:
data.update(pendable)
return result.key, data
- def delete_request(self, request_id):
- request = config.db.store.get(_Request, request_id)
+ @dbconnection
+ def delete_request(self, store, request_id):
+ request = store.get(_Request, request_id)
if request is None:
raise KeyError(request_id)
# Throw away the pended data.
getUtility(IPendings).confirm(request.data_hash)
- config.db.store.remove(request)
+ store.remove(request)
diff --git a/src/mailman/model/roster.py b/src/mailman/model/roster.py
index 48d434ab1..56dad4bc8 100644
--- a/src/mailman/model/roster.py
+++ b/src/mailman/model/roster.py
@@ -22,7 +22,7 @@ the ones that fit a particular role. These are used as the member, owner,
moderator, and administrator roster filters.
"""
-from __future__ import absolute_import, unicode_literals
+from __future__ import absolute_import, print_function, unicode_literals
__metaclass__ = type
__all__ = [
@@ -38,9 +38,9 @@ __all__ = [
from storm.expr import And, Or
-from zope.interface import implements
+from zope.interface import implementer
-from mailman.config import config
+from mailman.database.transaction import dbconnection
from mailman.interfaces.member import DeliveryMode, MemberRole
from mailman.interfaces.roster import IRoster
from mailman.model.address import Address
@@ -48,6 +48,7 @@ from mailman.model.member import Member
+@implementer(IRoster)
class AbstractRoster:
"""An abstract IRoster class.
@@ -57,15 +58,14 @@ class AbstractRoster:
This requires that subclasses implement the 'members' property.
"""
- implements(IRoster)
-
role = None
def __init__(self, mlist):
self._mlist = mlist
- def _query(self):
- return config.db.store.find(
+ @dbconnection
+ def _query(self, store):
+ return store.find(
Member,
mailing_list=self._mlist.fqdn_listname,
role=self.role)
@@ -101,9 +101,10 @@ class AbstractRoster:
for member in self.members:
yield member.address
- def get_member(self, address):
+ @dbconnection
+ def get_member(self, store, address):
"""See `IRoster`."""
- results = config.db.store.find(
+ results = store.find(
Member,
Member.mailing_list == self._mlist.fqdn_listname,
Member.role == self.role,
@@ -157,16 +158,18 @@ class AdministratorRoster(AbstractRoster):
name = 'administrator'
- def _query(self):
- return config.db.store.find(
+ @dbconnection
+ def _query(self, store):
+ return store.find(
Member,
Member.mailing_list == self._mlist.fqdn_listname,
Or(Member.role == MemberRole.owner,
Member.role == MemberRole.moderator))
- def get_member(self, address):
+ @dbconnection
+ def get_member(self, store, address):
"""See `IRoster`."""
- results = config.db.store.find(
+ results = store.find(
Member,
Member.mailing_list == self._mlist.fqdn_listname,
Or(Member.role == MemberRole.moderator,
@@ -194,7 +197,8 @@ class DeliveryMemberRoster(AbstractRoster):
# checking the delivery mode to a query parameter.
return len(tuple(self.members))
- def _get_members(self, *delivery_modes):
+ @dbconnection
+ def _get_members(self, store, *delivery_modes):
"""The set of members for a mailing list, filter by delivery mode.
:param delivery_modes: The modes to filter on.
@@ -202,7 +206,7 @@ class DeliveryMemberRoster(AbstractRoster):
:return: A generator of members.
:rtype: generator
"""
- results = config.db.store.find(
+ results = store.find(
Member,
And(Member.mailing_list == self._mlist.fqdn_listname,
Member.role == MemberRole.member))
@@ -244,25 +248,24 @@ class Subscribers(AbstractRoster):
name = 'subscribers'
- def _query(self):
- return config.db.store.find(
- Member,
- mailing_list=self._mlist.fqdn_listname)
+ @dbconnection
+ def _query(self, store):
+ return store.find(Member, mailing_list=self._mlist.fqdn_listname)
+@implementer(IRoster)
class Memberships:
"""A roster of a single user's memberships."""
- implements(IRoster)
-
name = 'memberships'
def __init__(self, user):
self._user = user
- def _query(self):
- results = config.db.store.find(
+ @dbconnection
+ def _query(self, store):
+ results = store.find(
Member,
Or(Member.user_id == self._user.id,
And(Address.user_id == self._user.id,
@@ -291,9 +294,10 @@ class Memberships:
for address in self._user.addresses:
yield address
- def get_member(self, address):
+ @dbconnection
+ def get_member(self, store, address):
"""See `IRoster`."""
- results = config.db.store.find(
+ results = store.find(
Member,
Member.address_id == Address.id,
Address.user_id == self._user.id)
diff --git a/src/mailman/model/tests/test_bounce.py b/src/mailman/model/tests/test_bounce.py
index da2b661ea..377fab4cc 100644
--- a/src/mailman/model/tests/test_bounce.py
+++ b/src/mailman/model/tests/test_bounce.py
@@ -17,7 +17,7 @@
"""Test bounce model objects."""
-from __future__ import absolute_import, unicode_literals
+from __future__ import absolute_import, print_function, unicode_literals
__metaclass__ = type
__all__ = [
@@ -30,7 +30,7 @@ from datetime import datetime
from zope.component import getUtility
from mailman.app.lifecycle import create_list
-from mailman.config import config
+from mailman.database.transaction import transaction
from mailman.interfaces.bounce import BounceContext, IBounceProcessor
from mailman.testing.helpers import (
specialized_message_from_string as message_from_string)
@@ -52,8 +52,9 @@ Message-Id: <first>
""")
def test_events_iterator(self):
- self._processor.register(self._mlist, 'anne@example.com', self._msg)
- config.db.commit()
+ with transaction():
+ self._processor.register(
+ self._mlist, 'anne@example.com', self._msg)
events = list(self._processor.events)
self.assertEqual(len(events), 1)
event = events[0]
@@ -75,23 +76,25 @@ Message-Id: <first>
self.assertEqual(event.processed, False)
def test_unprocessed_events_iterator(self):
- self._processor.register(self._mlist, 'anne@example.com', self._msg)
- self._processor.register(self._mlist, 'bart@example.com', self._msg)
- config.db.commit()
+ with transaction():
+ self._processor.register(
+ self._mlist, 'anne@example.com', self._msg)
+ self._processor.register(
+ self._mlist, 'bart@example.com', self._msg)
events = list(self._processor.events)
self.assertEqual(len(events), 2)
unprocessed = list(self._processor.unprocessed)
# The unprocessed list will be exactly the same right now.
self.assertEqual(len(unprocessed), 2)
# Process one of the events.
- events[0].processed = True
- config.db.commit()
+ with transaction():
+ events[0].processed = True
# Now there will be only one unprocessed event.
unprocessed = list(self._processor.unprocessed)
self.assertEqual(len(unprocessed), 1)
# Process the other event.
- events[1].processed = True
- config.db.commit()
+ with transaction():
+ events[1].processed = True
# Now there will be no unprocessed events.
unprocessed = list(self._processor.unprocessed)
self.assertEqual(len(unprocessed), 0)
diff --git a/src/mailman/model/uid.py b/src/mailman/model/uid.py
index c3564aa40..08eae8aff 100644
--- a/src/mailman/model/uid.py
+++ b/src/mailman/model/uid.py
@@ -17,7 +17,7 @@
"""Unique IDs."""
-from __future__ import absolute_import, unicode_literals
+from __future__ import absolute_import, print_function, unicode_literals
__metaclass__ = type
__all__ = [
@@ -28,8 +28,8 @@ __all__ = [
from storm.locals import Int
from storm.properties import UUID
-from mailman.config import config
from mailman.database.model import Model
+from mailman.database.transaction import dbconnection
@@ -48,23 +48,29 @@ class UID(Model):
id = Int(primary=True)
uid = UUID()
- def __init__(self, uid):
+ @dbconnection
+ def __init__(self, store, uid):
super(UID, self).__init__()
self.uid = uid
- config.db.store.add(self)
+ store.add(self)
def __repr__(self):
return '<UID {0} at {1}>'.format(self.uid, id(self))
@staticmethod
- def record(uid):
+ @dbconnection
+ # Note that the parameter order is deliberate reversed here. Normally,
+ # `store` is the first parameter after `self`, but since this is a
+ # staticmethod and there is no self, the decorator will see the uid in
+ # arg[0].
+ def record(uid, store):
"""Record the uid in the database.
:param uid: The unique id.
:type uid: unicode
:raises ValueError: if the id is not unique.
"""
- existing = config.db.store.find(UID, uid=uid)
+ existing = store.find(UID, uid=uid)
if existing.count() != 0:
raise ValueError(uid)
return UID(uid)
diff --git a/src/mailman/model/user.py b/src/mailman/model/user.py
index 9ca9b5aea..a723df44e 100644
--- a/src/mailman/model/user.py
+++ b/src/mailman/model/user.py
@@ -17,7 +17,7 @@
"""Model for users."""
-from __future__ import absolute_import, unicode_literals
+from __future__ import absolute_import, print_function, unicode_literals
__metaclass__ = type
__all__ = [
@@ -28,10 +28,10 @@ from storm.locals import (
DateTime, Int, RawStr, Reference, ReferenceSet, Unicode)
from storm.properties import UUID
from zope.event import notify
-from zope.interface import implements
+from zope.interface import implementer
-from mailman.config import config
from mailman.database.model import Model
+from mailman.database.transaction import dbconnection
from mailman.interfaces.address import (
AddressAlreadyLinkedError, AddressNotLinkedError)
from mailman.interfaces.user import (
@@ -47,11 +47,10 @@ uid_factory = UniqueIDFactory(context='users')
+@implementer(IUser)
class User(Model):
"""Mailman users."""
- implements(IUser)
-
id = Int(primary=True)
display_name = Unicode()
_password = RawStr(name='password')
@@ -64,16 +63,17 @@ class User(Model):
preferences_id = Int()
preferences = Reference(preferences_id, 'Preferences.id')
- def __init__(self, display_name=None, preferences=None):
+ @dbconnection
+ def __init__(self, store, display_name=None, preferences=None):
super(User, self).__init__()
self._created_on = date_factory.now()
user_id = uid_factory.new_uid()
- assert config.db.store.find(User, _user_id=user_id).count() == 0, (
+ assert store.find(User, _user_id=user_id).count() == 0, (
'Duplicate user id {0}'.format(user_id))
self._user_id = user_id
self.display_name = ('' if display_name is None else display_name)
self.preferences = preferences
- config.db.store.add(self)
+ store.add(self)
def __repr__(self):
short_user_id = self.user_id.int
@@ -135,18 +135,20 @@ class User(Model):
"""See `IUser`."""
self._preferred_address = None
- def controls(self, email):
+ @dbconnection
+ def controls(self, store, email):
"""See `IUser`."""
- found = config.db.store.find(Address, email=email)
+ found = store.find(Address, email=email)
if found.count() == 0:
return False
assert found.count() == 1, 'Unexpected count'
return found[0].user is self
- def register(self, email, display_name=None):
+ @dbconnection
+ def register(self, store, email, display_name=None):
"""See `IUser`."""
# First, see if the address already exists
- address = config.db.store.find(Address, email=email).one()
+ address = store.find(Address, email=email).one()
if address is None:
if display_name is None:
display_name = ''
diff --git a/src/mailman/model/usermanager.py b/src/mailman/model/usermanager.py
index c8a5c65a2..4c7daaa59 100644
--- a/src/mailman/model/usermanager.py
+++ b/src/mailman/model/usermanager.py
@@ -17,7 +17,7 @@
"""A user manager."""
-from __future__ import absolute_import, unicode_literals
+from __future__ import absolute_import, print_function, unicode_literals
__metaclass__ = type
__all__ = [
@@ -25,9 +25,9 @@ __all__ = [
]
-from zope.interface import implements
+from zope.interface import implementer
-from mailman.config import config
+from mailman.database.transaction import dbconnection
from mailman.interfaces.address import ExistingAddressError
from mailman.interfaces.usermanager import IUserManager
from mailman.model.address import Address
@@ -37,8 +37,9 @@ from mailman.model.user import User
+@implementer(IUserManager)
class UserManager:
- implements(IUserManager)
+ """See `IUserManager`."""
def create_user(self, email=None, display_name=None):
"""See `IUserManager`."""
@@ -48,33 +49,38 @@ class UserManager:
user.link(address)
return user
- def delete_user(self, user):
+ @dbconnection
+ def delete_user(self, store, user):
"""See `IUserManager`."""
- config.db.store.remove(user)
+ store.remove(user)
- def get_user(self, email):
+ @dbconnection
+ def get_user(self, store, email):
"""See `IUserManager`."""
- addresses = config.db.store.find(Address, email=email.lower())
+ addresses = store.find(Address, email=email.lower())
if addresses.count() == 0:
return None
return addresses.one().user
- def get_user_by_id(self, user_id):
+ @dbconnection
+ def get_user_by_id(self, store, user_id):
"""See `IUserManager`."""
- users = config.db.store.find(User, _user_id=user_id)
+ users = store.find(User, _user_id=user_id)
if users.count() == 0:
return None
return users.one()
@property
- def users(self):
+ @dbconnection
+ def users(self, store):
"""See `IUserManager`."""
- for user in config.db.store.find(User):
+ for user in store.find(User):
yield user
- def create_address(self, email, display_name=None):
+ @dbconnection
+ def create_address(self, store, email, display_name=None):
"""See `IUserManager`."""
- addresses = config.db.store.find(Address, email=email.lower())
+ addresses = store.find(Address, email=email.lower())
if addresses.count() == 1:
found = addresses[0]
raise ExistingAddressError(found.original_email)
@@ -85,32 +91,36 @@ class UserManager:
# constructor will do the right thing.
address = Address(email, display_name)
address.preferences = Preferences()
- config.db.store.add(address)
+ store.add(address)
return address
- def delete_address(self, address):
+ @dbconnection
+ def delete_address(self, store, address):
"""See `IUserManager`."""
# If there's a user controlling this address, it has to first be
# unlinked before the address can be deleted.
if address.user:
address.user.unlink(address)
- config.db.store.remove(address)
+ store.remove(address)
- def get_address(self, email):
+ @dbconnection
+ def get_address(self, store, email):
"""See `IUserManager`."""
- addresses = config.db.store.find(Address, email=email.lower())
+ addresses = store.find(Address, email=email.lower())
if addresses.count() == 0:
return None
return addresses.one()
@property
- def addresses(self):
+ @dbconnection
+ def addresses(self, store):
"""See `IUserManager`."""
- for address in config.db.store.find(Address):
+ for address in store.find(Address):
yield address
@property
- def members(self):
+ @dbconnection
+ def members(self, store):
"""See `IUserManager."""
- for member in config.db.store.find(Member):
+ for member in store.find(Member):
yield member