summaryrefslogtreecommitdiff
path: root/Mailman/database/dbcontext.py
diff options
context:
space:
mode:
authorBarry Warsaw2007-07-23 01:57:48 -0400
committerBarry Warsaw2007-07-23 01:57:48 -0400
commitd07e48b456a35daed967a4b9cfb2cd4e00471d51 (patch)
treeb02e223999800b8a8d33d0a697f895dd0900f862 /Mailman/database/dbcontext.py
parent2e4314fc178f34170b82aaa2f8ed4d0f5440f4f4 (diff)
downloadmailman-d07e48b456a35daed967a4b9cfb2cd4e00471d51.tar.gz
mailman-d07e48b456a35daed967a4b9cfb2cd4e00471d51.tar.zst
mailman-d07e48b456a35daed967a4b9cfb2cd4e00471d51.zip
Diffstat (limited to 'Mailman/database/dbcontext.py')
-rw-r--r--Mailman/database/dbcontext.py174
1 files changed, 0 insertions, 174 deletions
diff --git a/Mailman/database/dbcontext.py b/Mailman/database/dbcontext.py
deleted file mode 100644
index eaf87be93..000000000
--- a/Mailman/database/dbcontext.py
+++ /dev/null
@@ -1,174 +0,0 @@
-# Copyright (C) 2006-2007 by the Free Software Foundation, Inc.
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
-# USA.
-
-import os
-import sys
-import logging
-import weakref
-
-from elixir import create_all, metadata, objectstore
-from sqlalchemy import create_engine
-from string import Template
-from urlparse import urlparse
-
-from Mailman import Version
-from Mailman.configuration import config
-from Mailman.database.txnsupport import txn
-
-
-
-class MlistRef(weakref.ref):
- def __init__(self, mlist, callback):
- super(MlistRef, self).__init__(mlist, callback)
- self.fqdn_listname = mlist.fqdn_listname
-
-
-
-class DBContext(object):
- def __init__(self):
- # Special transaction used only for MailList.Lock() .Save() and
- # .Unlock() interface.
- self._mlist_txns = {}
-
- def connect(self):
- # Calculate the engine url
- url = Template(config.SQLALCHEMY_ENGINE_URL).safe_substitute(
- config.paths)
- # XXX By design of SQLite, database file creation does not honor
- # umask. See their ticket #1193:
- # http://www.sqlite.org/cvstrac/tktview?tn=1193,31
- #
- # This sucks for us because the mailman.db file /must/ be group
- # writable, however even though we guarantee our umask is 002 here, it
- # still gets created without the necessary g+w permission, due to
- # SQLite's policy. This should only affect SQLite engines because its
- # the only one that creates a little file on the local file system.
- # This kludges around their bug by "touch"ing the database file before
- # SQLite has any chance to create it, thus honoring the umask and
- # ensuring the right permissions. We only try to do this for SQLite
- # engines, and yes, we could have chmod'd the file after the fact, but
- # half dozen and all...
- self._touch(url)
- engine = create_engine(url)
- engine.echo = config.SQLALCHEMY_ECHO
- metadata.connect(engine)
- # Load and create the Elixir active records. This works by
- # side-effect.
- import Mailman.database.model
- create_all()
- # Validate schema version.
- v = Mailman.database.model.Version.get_by(component='schema')
- if not v:
- # Database has not yet been initialized
- v = Mailman.database.model.Version(
- component='schema',
- version=Version.DATABASE_SCHEMA_VERSION)
- objectstore.flush()
- elif v.version <> Version.DATABASE_SCHEMA_VERSION:
- # XXX Update schema
- raise SchemaVersionMismatchError(v.version)
-
- def _touch(self, url):
- parts = urlparse(url)
- if parts.scheme <> 'sqlite':
- return
- path = os.path.normpath(parts.path)
- fd = os.open(path, os.O_WRONLY | os.O_NONBLOCK | os.O_CREAT, 0666)
- # Ignore errors
- if fd > 0:
- os.close(fd)
-
- # Cooperative method for use with @txn decorator
- def _withtxn(self, meth, *args, **kws):
- try:
- txn = objectstore.session.current.create_transaction()
- rtn = meth(*args, **kws)
- except:
- txn.rollback()
- raise
- else:
- txn.commit()
- return rtn
-
- def _unlock_mref(self, mref):
- txn = self._mlist_txns.pop(mref.fqdn_listname, None)
- if txn is not None:
- txn.rollback()
-
- # Higher level interface
- def api_lock(self, mlist):
- # Don't try to re-lock a list
- if mlist.fqdn_listname in self._mlist_txns:
- return
- txn = objectstore.session.current.create_transaction()
- mref = MlistRef(mlist, self._unlock_mref)
- # If mlist.host_name is changed, its fqdn_listname attribute will no
- # longer match, so its transaction will not get committed when the
- # list is saved. To avoid this, store on the mlist object the key
- # under which its transaction is stored.
- txnkey = mlist._txnkey = mlist.fqdn_listname
- self._mlist_txns[txnkey] = txn
-
- def api_unlock(self, mlist):
- try:
- txnkey = mlist._txnkey
- except AttributeError:
- return
- txn = self._mlist_txns.pop(txnkey, None)
- if txn is not None:
- txn.rollback()
- del mlist._txnkey
-
- def api_load(self, mlist):
- # Mark the MailList object such that future attribute accesses will
- # refresh from the database.
- objectstore.session.current.expire(mlist)
-
- def api_save(self, mlist):
- # When dealing with MailLists, .Save() will always be followed by
- # .Unlock(). However lists can also be unlocked without saving. But
- # if it's been locked it will always be unlocked. So the rollback in
- # unlock will essentially be no-op'd if we've already saved the list.
- try:
- txnkey = mlist._txnkey
- except AttributeError:
- return
- txn = self._mlist_txns.pop(txnkey, None)
- if txn is not None:
- txn.commit()
-
- @txn
- def api_add_list(self, mlist):
- objectstore.session.current.save(mlist)
-
- @txn
- def api_remove_list(self, mlist):
- objectstore.session.current.delete(mlist)
-
- @txn
- def api_find_list(self, listname, hostname):
- from Mailman.MailList import MailList
- q = objectstore.session.current.query(MailList)
- mlists = q.select_by(list_name=listname, host_name=hostname)
- assert len(mlists) <= 1, 'Duplicate mailing lists!'
- if mlists:
- return mlists[0]
- return None
-
-
-
-dbcontext = DBContext()