summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAbhilash Raj2014-09-12 18:38:19 +0530
committerAbhilash Raj2014-09-12 18:38:19 +0530
commit4dc18daeaeaf65be50397293b54a9874bfaca228 (patch)
treee30d97167205938b32ae407a5f5653f298d0309d /src
parentdb1f5638fe1ab83406a305c3f108c4a1bcfd9cd7 (diff)
downloadmailman-4dc18daeaeaf65be50397293b54a9874bfaca228.tar.gz
mailman-4dc18daeaeaf65be50397293b54a9874bfaca228.tar.zst
mailman-4dc18daeaeaf65be50397293b54a9874bfaca228.zip
Diffstat (limited to 'src')
-rw-r--r--src/mailman/database/base.py99
-rw-r--r--src/mailman/database/factory.py6
-rw-r--r--src/mailman/database/model.py15
-rw-r--r--src/mailman/model/autorespond.py20
-rw-r--r--src/mailman/model/bans.py17
-rw-r--r--src/mailman/model/bounce.py2
-rw-r--r--src/mailman/model/listmanager.py4
-rw-r--r--src/mailman/model/mailinglist.py7
-rw-r--r--src/mailman/model/roster.py38
-rw-r--r--src/mailman/model/tests/test_listmanager.py8
-rw-r--r--src/mailman/model/user.py6
-rw-r--r--src/mailman/model/usermanager.py14
12 files changed, 121 insertions, 115 deletions
diff --git a/src/mailman/database/base.py b/src/mailman/database/base.py
index a2392bb3a..0bc530e6b 100644
--- a/src/mailman/database/base.py
+++ b/src/mailman/database/base.py
@@ -68,6 +68,16 @@ class SABaseDatabase:
def _prepare(self, url):
pass
+ def _database_exists(self):
+ """Return True if the database exists and is initialized.
+
+ Return False when Mailman needs to create and initialize the
+ underlying database schema.
+
+ Base classes *must* override this.
+ """
+ raise NotImplementedError
+
def _pre_reset(self, store):
"""Clean up method for testing.
@@ -90,11 +100,10 @@ class SABaseDatabase:
log.debug('Database url: %s', url)
self.url = url
self._prepare(url)
- engine = create_engine(url)
- Session = sessionmaker(bind=engine)
- store = Session()
- self.store = store
- store.commit()
+ self.engine = create_engine(url)
+ Session = sessionmaker(bind=self.engine)
+ self.store = Session()
+ self.store.commit()
def load_migrations(self, until=None):
"""Load schema migrations.
@@ -103,45 +112,47 @@ class SABaseDatabase:
With default value of None, load all migrations.
:type until: string
"""
- migrations_path = config.database.migrations_path
- if '.' in migrations_path:
- parent, dot, child = migrations_path.rpartition('.')
- else:
- parent = migrations_path
- child = ''
- # If the database does not yet exist, load the base schema.
- filenames = sorted(resource_listdir(parent, child))
- # Find out which schema migrations have already been loaded.
- if self._database_exists(self.store):
- versions = set(version.version for version in
- self.store.find(Version, component='schema'))
- else:
- versions = set()
- for filename in filenames:
- module_fn, extension = os.path.splitext(filename)
- if extension != '.py':
- continue
- parts = module_fn.split('_')
- if len(parts) < 2:
- continue
- version = parts[1].strip()
- if len(version) == 0:
- # Not a schema migration file.
- continue
- if version in versions:
- log.debug('already migrated to %s', version)
- continue
- if until is not None and version > until:
- # We're done.
- break
- module_path = migrations_path + '.' + module_fn
- __import__(module_path)
- upgrade = getattr(sys.modules[module_path], 'upgrade', None)
- if upgrade is None:
- continue
- log.debug('migrating db to %s: %s', version, module_path)
- upgrade(self, self.store, version, module_path)
- self.commit()
+ from mailman.database.model import Model
+ Model.metadata.create_all(self.engine)
+ # migrations_path = config.database.migrations_path
+ # if '.' in migrations_path:
+ # parent, dot, child = migrations_path.rpartition('.')
+ # else:
+ # parent = migrations_path
+ # child = ''
+ # # If the database does not yet exist, load the base schema.
+ # filenames = sorted(resource_listdir(parent, child))
+ # # Find out which schema migrations have already been loaded.
+ # if self._database_exists(self.store):
+ # versions = set(version.version for version in
+ # self.store.query(Version, component='schema'))
+ # else:
+ # versions = set()
+ # for filename in filenames:
+ # module_fn, extension = os.path.splitext(filename)
+ # if extension != '.py':
+ # continue
+ # parts = module_fn.split('_')
+ # if len(parts) < 2:
+ # continue
+ # version = parts[1].strip()
+ # if len(version) == 0:
+ # # Not a schema migration file.
+ # continue
+ # if version in versions:
+ # log.debug('already migrated to %s', version)
+ # continue
+ # if until is not None and version > until:
+ # # We're done.
+ # break
+ # module_path = migrations_path + '.' + module_fn
+ # __import__(module_path)
+ # upgrade = getattr(sys.modules[module_path], 'upgrade', None)
+ # if upgrade is None:
+ # continue
+ # log.debug('migrating db to %s: %s', version, module_path)
+ # upgrade(self, self.store, version, module_path)
+ # self.commit()
def load_sql(self, store, sql):
"""Load the given SQL into the store.
diff --git a/src/mailman/database/factory.py b/src/mailman/database/factory.py
index 426d283e1..64fcc242c 100644
--- a/src/mailman/database/factory.py
+++ b/src/mailman/database/factory.py
@@ -54,7 +54,7 @@ class DatabaseFactory:
database = call_name(database_class)
verifyObject(IDatabase, database)
database.initialize()
- #database.load_migrations()
+ database.load_migrations()
database.commit()
return database
@@ -62,10 +62,10 @@ class DatabaseFactory:
def _reset(self):
"""See `IDatabase`."""
- from mailman.database.model import ModelMeta
+ from mailman.database.model import Model
self.store.rollback()
self._pre_reset(self.store)
- ModelMeta._reset(self.store)
+ Model._reset(self)
self._post_reset(self.store)
self.store.commit()
diff --git a/src/mailman/database/model.py b/src/mailman/database/model.py
index 4b8478fc6..0cb60b7cd 100644
--- a/src/mailman/database/model.py
+++ b/src/mailman/database/model.py
@@ -50,13 +50,14 @@ class ModelMeta(object):
ModelMeta._class_registry.add(self)
@staticmethod
- def _reset(store):
- from mailman.config import config
- config.db._pre_reset(store)
+ def _reset(db):
+ Model.metadata.drop_all(db.engine)
+ Model.metadata.create_all(db.engine)
+
# Make sure this is deterministic, by sorting on the storm table name.
- classes = sorted(ModelMeta._class_registry,
- key=attrgetter('__tablename__'))
- for model_class in classes:
- store.query(model_class).delete()
+ # classes = sorted(ModelMeta._class_registry,
+ # key=attrgetter('__tablename__'))
+ # for model_class in classes:
+ # store.query(model_class).delete()
Model = declarative_base(cls=ModelMeta)
diff --git a/src/mailman/model/autorespond.py b/src/mailman/model/autorespond.py
index 92e0b6ebe..47f15cd54 100644
--- a/src/mailman/model/autorespond.py
+++ b/src/mailman/model/autorespond.py
@@ -75,12 +75,11 @@ class AutoResponseSet:
@dbconnection
def todays_count(self, store, address, response_type):
"""See `IAutoResponseSet`."""
- return store.find(
- AutoResponseRecord,
- And(AutoResponseRecord.address == address,
- AutoResponseRecord.mailing_list == self._mailing_list,
- AutoResponseRecord.response_type == response_type,
- AutoResponseRecord.date_sent == today())).count()
+ return store.find(AutoResponseRecord).filter_by(
+ address = address,
+ mailing_list = self._mailing_list,
+ response_type = response_type,
+ date_sent = today()).count()
@dbconnection
def response_sent(self, store, address, response_type):
@@ -92,10 +91,9 @@ class AutoResponseSet:
@dbconnection
def last_response(self, store, address, response_type):
"""See `IAutoResponseSet`."""
- results = store.find(
- AutoResponseRecord,
- And(AutoResponseRecord.address == address,
- AutoResponseRecord.mailing_list == self._mailing_list,
- AutoResponseRecord.response_type == response_type)
+ results = store.find(AutoResponseRecord).filter_by(
+ address = address,
+ mailing_list = self._mailing_list,
+ response_type = response_type
).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 57dbdbbd5..bf02f3127 100644
--- a/src/mailman/model/bans.py
+++ b/src/mailman/model/bans.py
@@ -64,7 +64,7 @@ class BanManager:
@dbconnection
def ban(self, store, email):
"""See `IBanManager`."""
- bans = store.find(Ban, email=email, list_id=self._list_id)
+ bans = store.query(Ban).filter_by(email=email, list_id=self._list_id)
if bans.count() == 0:
ban = Ban(email, self._list_id)
store.add(ban)
@@ -72,7 +72,8 @@ class BanManager:
@dbconnection
def unban(self, store, email):
"""See `IBanManager`."""
- ban = store.find(Ban, email=email, list_id=self._list_id).one()
+ ban = store.query(Ban).filter_by(email=email,
+ list_id=self._list_id).first()
if ban is not None:
store.remove(ban)
@@ -83,32 +84,32 @@ class BanManager:
if list_id is None:
# The client is asking for global bans. Look up bans on the
# specific email address first.
- bans = store.find(Ban, email=email, list_id=None)
+ bans = store.query(Ban).filter_by(email=email, list_id=None)
if bans.count() > 0:
return True
# And now look for global pattern bans.
- bans = store.find(Ban, list_id=None)
+ bans = store.query(Ban).filter_by(list_id=None)
for ban in bans:
if (ban.email.startswith('^') and
re.match(ban.email, email, re.IGNORECASE) is not None):
return True
else:
# This is a list-specific ban.
- bans = store.find(Ban, email=email, list_id=list_id)
+ bans = store.query(Ban).filter_by(email=email, list_id=list_id)
if bans.count() > 0:
return True
# Try global bans next.
- bans = store.find(Ban, email=email, list_id=None)
+ bans = store.query(Ban).filter_by(email=email, list_id=None)
if bans.count() > 0:
return True
# Now try specific mailing list bans, but with a pattern.
- bans = store.find(Ban, list_id=list_id)
+ bans = store.query(Ban).filteR_by(list_id=list_id)
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 = store.find(Ban, list_id=None)
+ bans = store.query(Ban).filter_by(list_id=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 b3f053cba..7340a4824 100644
--- a/src/mailman/model/bounce.py
+++ b/src/mailman/model/bounce.py
@@ -85,5 +85,5 @@ class BounceProcessor:
@dbconnection
def unprocessed(self, store):
"""See `IBounceProcessor`."""
- for event in store.find(BounceEvent, BounceEvent.processed == False):
+ for event in store.query(BounceEvent).filter_by(processed = False):
yield event
diff --git a/src/mailman/model/listmanager.py b/src/mailman/model/listmanager.py
index df1a31d04..a67f7b5e1 100644
--- a/src/mailman/model/listmanager.py
+++ b/src/mailman/model/listmanager.py
@@ -66,12 +66,12 @@ class ListManager:
"""See `IListManager`."""
listname, at, hostname = fqdn_listname.partition('@')
list_id = '{0}.{1}'.format(listname, hostname)
- return store.query(MailingList).filter_by(_list_id=list_id).one()
+ return store.query(MailingList).filter_by(_list_id=list_id).first()
@dbconnection
def get_by_list_id(self, store, list_id):
"""See `IListManager`."""
- return store.query(MailingList).filter_by(_list_id=list_id).one()
+ return store.query(MailingList).filter_by(_list_id=list_id).first()
@dbconnection
def delete(self, store, mlist):
diff --git a/src/mailman/model/mailinglist.py b/src/mailman/model/mailinglist.py
index 324d709d6..abbf370e8 100644
--- a/src/mailman/model/mailinglist.py
+++ b/src/mailman/model/mailinglist.py
@@ -355,10 +355,9 @@ class MailingList(Model):
"""See `IMailingList`."""
# First, delete all existing MIME type filter patterns.
store = Store.of(self)
- results = store.find(
- ContentFilter,
- And(ContentFilter.mailing_list == self,
- ContentFilter.filter_type == FilterType.filter_mime))
+ results = store.query(ContentFilter).filter(
+ ContentFilter.mailing_list == self,
+ ContentFilter.filter_type == FilterType.filter_mime)
results.remove()
# Now add all the new filter types.
for mime_type in sequence:
diff --git a/src/mailman/model/roster.py b/src/mailman/model/roster.py
index f641c2846..c8bfdc582 100644
--- a/src/mailman/model/roster.py
+++ b/src/mailman/model/roster.py
@@ -38,6 +38,7 @@ __all__ = [
#from storm.expr import And, Or
+from sqlalchemy import and_, or_
from zope.interface import implementer
from mailman.database.transaction import dbconnection
@@ -65,8 +66,7 @@ class AbstractRoster:
@dbconnection
def _query(self, store):
- return store.find(
- Member,
+ return store.query(Member).filter(
Member.list_id == self._mlist.list_id,
Member.role == self.role)
@@ -104,8 +104,7 @@ class AbstractRoster:
@dbconnection
def get_member(self, store, address):
"""See `IRoster`."""
- results = store.find(
- Member,
+ results = store.query(Member).filter(
Member.list_id == self._mlist.list_id,
Member.role == self.role,
Address.email == address,
@@ -160,19 +159,17 @@ class AdministratorRoster(AbstractRoster):
@dbconnection
def _query(self, store):
- return store.find(
- Member,
+ return store.query(Member).filter(
Member.list_id == self._mlist.list_id,
- Or(Member.role == MemberRole.owner,
+ or_(Member.role == MemberRole.owner,
Member.role == MemberRole.moderator))
@dbconnection
def get_member(self, store, address):
"""See `IRoster`."""
- results = store.find(
- Member,
+ results = store.query(Member).filter(
Member.list_id == self._mlist.list_id,
- Or(Member.role == MemberRole.moderator,
+ or_(Member.role == MemberRole.moderator,
Member.role == MemberRole.owner),
Address.email == address,
Member.address_id == Address.id)
@@ -206,10 +203,9 @@ class DeliveryMemberRoster(AbstractRoster):
:return: A generator of members.
:rtype: generator
"""
- results = store.find(
- Member,
- And(Member.list_id == self._mlist.list_id,
- Member.role == MemberRole.member))
+ results = store.query(Member).filter(
+ list_id == self._mlist.list_id,
+ role == MemberRole.member)
for member in results:
if member.delivery_mode in delivery_modes:
yield member
@@ -250,7 +246,7 @@ class Subscribers(AbstractRoster):
@dbconnection
def _query(self, store):
- return store.find(Member, Member.list_id == self._mlist.list_id)
+ return store.query(Member).filter_by(list_id = self._mlist.list_id)
@@ -265,11 +261,10 @@ class Memberships:
@dbconnection
def _query(self, store):
- results = store.find(
- Member,
- Or(Member.user_id == self._user.id,
- And(Address.user_id == self._user.id,
- Member.address_id == Address.id)))
+ results = store.query(Member).filter(
+ or_(Member.user_id == self._user.id,
+ and_(Member.user_id == self._user.id,
+ Member.address_id == Address.id)))
return results.config(distinct=True)
@property
@@ -297,8 +292,7 @@ class Memberships:
@dbconnection
def get_member(self, store, address):
"""See `IRoster`."""
- results = store.find(
- Member,
+ results = store.query(Member).filter(
Member.address_id == Address.id,
Address.user_id == self._user.id)
if results.count() == 0:
diff --git a/src/mailman/model/tests/test_listmanager.py b/src/mailman/model/tests/test_listmanager.py
index 2d3a4e3dc..287a4dba5 100644
--- a/src/mailman/model/tests/test_listmanager.py
+++ b/src/mailman/model/tests/test_listmanager.py
@@ -29,7 +29,7 @@ __all__ = [
import unittest
-from storm.locals import Store
+from sqlalchemy.orm import sessionmaker
from zope.component import getUtility
from mailman.app.lifecycle import create_list
@@ -139,9 +139,9 @@ Message-ID: <argon>
for name in filter_names:
setattr(self._ant, name, ['test-filter-1', 'test-filter-2'])
getUtility(IListManager).delete(self._ant)
- store = Store.of(self._ant)
- filters = store.find(ContentFilter,
- ContentFilter.mailing_list == self._ant)
+ Session = sessionmaker()
+ store = Session.object_session(self._ant)
+ filters = store.query(ContentFilter).filter_by(mailing_list = self._ant)
self.assertEqual(filters.count(), 0)
diff --git a/src/mailman/model/user.py b/src/mailman/model/user.py
index 88bf62085..efe00c6aa 100644
--- a/src/mailman/model/user.py
+++ b/src/mailman/model/user.py
@@ -59,11 +59,13 @@ class User(Model):
_user_id = Column(UUID)
_created_on = Column(DateTime)
- addresses = relationship('Address',
+ addresses = relationship('Address',
backref='user',
foreign_keys='[Address.user_id]')
- _preferred_address_id = Column(Integer, ForeignKey('address.id'))
+ _preferred_address_id = Column(Integer, ForeignKey('address.id',
+ use_alter=True,
+ name='prefered_address_id'))
_preferred_address = relationship('Address',
foreign_keys=[_preferred_address_id])
diff --git a/src/mailman/model/usermanager.py b/src/mailman/model/usermanager.py
index 6f4a7ff5c..a5ee40ae8 100644
--- a/src/mailman/model/usermanager.py
+++ b/src/mailman/model/usermanager.py
@@ -57,7 +57,7 @@ class UserManager:
@dbconnection
def get_user(self, store, email):
"""See `IUserManager`."""
- addresses = store.find(Address, email=email.lower())
+ addresses = store.query(Address).filter_by(email=email.lower())
if addresses.count() == 0:
return None
return addresses.one().user
@@ -65,7 +65,7 @@ class UserManager:
@dbconnection
def get_user_by_id(self, store, user_id):
"""See `IUserManager`."""
- users = store.find(User, _user_id=user_id)
+ users = store.query(User).filter_by(_user_id=user_id)
if users.count() == 0:
return None
return users.one()
@@ -74,13 +74,13 @@ class UserManager:
@dbconnection
def users(self, store):
"""See `IUserManager`."""
- for user in store.find(User):
+ for user in store.query(User).all():
yield user
@dbconnection
def create_address(self, store, email, display_name=None):
"""See `IUserManager`."""
- addresses = store.find(Address, email=email.lower())
+ addresses = store.query(Address).filter_by(email=email.lower())
if addresses.count() == 1:
found = addresses[0]
raise ExistingAddressError(found.original_email)
@@ -106,7 +106,7 @@ class UserManager:
@dbconnection
def get_address(self, store, email):
"""See `IUserManager`."""
- addresses = store.find(Address, email=email.lower())
+ addresses = store.query(Address).filter_by(email=email.lower())
if addresses.count() == 0:
return None
return addresses.one()
@@ -115,12 +115,12 @@ class UserManager:
@dbconnection
def addresses(self, store):
"""See `IUserManager`."""
- for address in store.find(Address):
+ for address in store.query(Address).all():
yield address
@property
@dbconnection
def members(self, store):
"""See `IUserManager."""
- for member in store.find(Member):
+ for member in store.query(Member).all():
yield member