------------------------------------------------------------ revno: 6580 committer: Barry Warsaw <[EMAIL PROTECTED]> branch nick: 3.0 timestamp: Sat 2007-12-08 11:51:36 -0500 message: Reorganize the database subpackage, primarily by removing the 'model' subdirectory and updating all relevant imports. Move of the circular import problems have been eliminated in the process. removed: Mailman/data/__init__.py Mailman/database/model/ Mailman/database/model/__init__.py added: Mailman/database/model.py renamed: Mailman/data => data Mailman/database/model/address.py => Mailman/database/address.py Mailman/database/model/language.py => Mailman/database/language.py Mailman/database/model/mailinglist.py => Mailman/database/mailinglist.py Mailman/database/model/mailman.sql => Mailman/database/mailman.sql Mailman/database/model/member.py => Mailman/database/member.py Mailman/database/model/message.py => Mailman/database/message.py Mailman/database/model/pending.py => Mailman/database/pending.py Mailman/database/model/preferences.py => Mailman/database/preferences.py Mailman/database/model/requests.py => Mailman/database/requests.py Mailman/database/model/roster.py => Mailman/database/roster.py Mailman/database/model/user.py => Mailman/database/user.py Mailman/database/model/version.py => Mailman/database/version.py modified: Mailman/database/__init__.py Mailman/database/listmanager.py Mailman/database/messagestore.py Mailman/database/usermanager.py Mailman/database/address.py Mailman/database/mailinglist.py Mailman/database/member.py Mailman/database/message.py Mailman/database/pending.py Mailman/database/preferences.py Mailman/database/requests.py Mailman/database/roster.py Mailman/database/user.py Mailman/database/version.py
=== removed file 'Mailman/data/__init__.py' === removed directory 'Mailman/database/model' === removed file 'Mailman/database/model/__init__.py' --- a/Mailman/database/model/__init__.py 2007-11-04 23:10:21 +0000 +++ b/Mailman/database/model/__init__.py 1970-01-01 00:00:00 +0000 @@ -1,108 +0,0 @@ -# Copyright (C) 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. - -from __future__ import with_statement - -__all__ = [ - 'Address', - 'Language', - 'MailingList', - 'Message', - 'Pendings', - 'Preferences', - 'User', - 'Version', - ] - -import os -import sys - -from storm import database -from storm.locals import create_database, Store -from string import Template -from urlparse import urlparse - -import Mailman.Version - -from Mailman import constants -from Mailman.Errors import SchemaVersionMismatchError -from Mailman.configuration import config -from Mailman.database.model.address import Address -from Mailman.database.model.language import Language -from Mailman.database.model.mailinglist import MailingList -from Mailman.database.model.member import Member -from Mailman.database.model.message import Message -from Mailman.database.model.pending import Pendings -from Mailman.database.model.preferences import Preferences -from Mailman.database.model.requests import Requests -from Mailman.database.model.user import User -from Mailman.database.model.version import Version - - - -def initialize(debug): - # Calculate the engine url. - url = Template(config.DEFAULT_DATABASE_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... - touch(url) - database = create_database(url) - store = Store(database) - database.DEBUG = (config.DEFAULT_DATABASE_ECHO if debug is None else debug) - # XXX Storm does not currently have schema creation. This is not an ideal - # way to handle creating the database, but it's cheap and easy for now. - import Mailman.database.model - schema_file = os.path.join( - os.path.dirname(Mailman.database.model.__file__), - 'mailman.sql') - with open(schema_file) as fp: - sql = fp.read() - for statement in sql.split(';'): - store.execute(statement + ';') - # Validate schema version. - v = store.find(Version, component=u'schema').one() - if not v: - # Database has not yet been initialized - v = Version(component=u'schema', - version=Mailman.Version.DATABASE_SCHEMA_VERSION) - store.add(v) - elif v.version <> Mailman.Version.DATABASE_SCHEMA_VERSION: - # XXX Update schema - raise SchemaVersionMismatchError(v.version) - return store - - -def touch(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) === added file 'Mailman/database/model.py' --- a/Mailman/database/model.py 1970-01-01 00:00:00 +0000 +++ b/Mailman/database/model.py 2007-12-08 16:51:36 +0000 @@ -0,0 +1,55 @@ +# 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. + +"""Base class for all database classes.""" + +__metaclass__ = type +__all__ = [ + 'Model', + ] + +from storm.properties import PropertyPublisherMeta + + + +class ModelMeta(PropertyPublisherMeta): + """Do more magic on table classes.""" + + _class_registry = set() + + def __init__(self, name, bases, dict): + # Before we let the base class do it's thing, force an __storm_table__ + # property to enforce our table naming convention. + self.__storm_table__ = name.lower() + super(ModelMeta, self).__init__(name, bases, dict) + # Register the model class so that it can be more easily cleared. + # This is required by the test framework. + if name == 'Model': + return + ModelMeta._class_registry.add(self) + + @staticmethod + def _reset(store): + for model_class in ModelMeta._class_registry: + for row in store.find(model_class): + store.remove(row) + + + +class Model(object): + """Like Storm's `Storm` subclass, but with a bit extra.""" + __metaclass__ = ModelMeta === renamed directory 'Mailman/data' => 'data' === renamed file 'Mailman/database/model/address.py' => 'Mailman/database/address.py' --- a/Mailman/database/model/address.py 2007-11-06 23:16:22 +0000 +++ b/Mailman/database/address.py 2007-12-08 16:51:36 +0000 @@ -21,7 +21,9 @@ from Mailman import Errors from Mailman.configuration import config -from Mailman.database import Model +from Mailman.database.member import Member +from Mailman.database.model import Model +from Mailman.database.preferences import Preferences from Mailman.interfaces import IAddress @@ -63,8 +65,6 @@ address_str, verified, self.address, id(self)) def subscribe(self, mailing_list, role): - from Mailman.database.model import Member - from Mailman.database.model import Preferences # This member has no preferences by default. member = config.db.store.find( Member, === renamed file 'Mailman/database/model/language.py' => 'Mailman/database/language.py' === renamed file 'Mailman/database/model/mailinglist.py' => 'Mailman/database/mailinglist.py' --- a/Mailman/database/model/mailinglist.py 2007-11-08 16:54:25 +0000 +++ b/Mailman/database/mailinglist.py 2007-12-08 16:51:36 +0000 @@ -23,10 +23,12 @@ from Mailman.Utils import fqdn_listname, makedirs, split_listname from Mailman.configuration import config -from Mailman.database import Model +from Mailman.database import roster +from Mailman.database.model import Model from Mailman.database.types import Enum from Mailman.interfaces import IMailingList, Personalization + SPACE = ' ' UNDERSCORE = '_' @@ -182,8 +184,6 @@ # XXX FIXME def _restore(self): - # Avoid circular imports. - from Mailman.database.model import roster self.owners = roster.OwnerRoster(self) self.moderators = roster.ModeratorRoster(self) self.administrators = roster.AdministratorRoster(self) === renamed file 'Mailman/database/model/mailman.sql' => 'Mailman/database/mailman.sql' === renamed file 'Mailman/database/model/member.py' => 'Mailman/database/member.py' --- a/Mailman/database/model/member.py 2007-11-08 23:42:56 +0000 +++ b/Mailman/database/member.py 2007-12-08 16:51:36 +0000 @@ -21,7 +21,7 @@ from Mailman.Utils import split_listname from Mailman.configuration import config from Mailman.constants import SystemDefaultPreferences -from Mailman.database import Model +from Mailman.database.model import Model from Mailman.database.types import Enum from Mailman.interfaces import IMember, IPreferences === renamed file 'Mailman/database/model/message.py' => 'Mailman/database/message.py' --- a/Mailman/database/model/message.py 2007-11-10 18:14:51 +0000 +++ b/Mailman/database/message.py 2007-12-08 16:51:36 +0000 @@ -19,7 +19,7 @@ from zope.interface import implements from Mailman.configuration import config -from Mailman.database import Model +from Mailman.database.model import Model from Mailman.interfaces import IMessage === renamed file 'Mailman/database/model/pending.py' => 'Mailman/database/pending.py' --- a/Mailman/database/model/pending.py 2007-11-17 05:05:23 +0000 +++ b/Mailman/database/pending.py 2007-12-08 16:51:36 +0000 @@ -28,7 +28,7 @@ from zope.interface.verify import verifyObject from Mailman.configuration import config -from Mailman.database import Model +from Mailman.database.model import Model from Mailman.interfaces import ( IPendable, IPended, IPendedKeyValue, IPendings) === renamed file 'Mailman/database/model/preferences.py' => 'Mailman/database/preferences.py' --- a/Mailman/database/model/preferences.py 2007-11-06 23:16:22 +0000 +++ b/Mailman/database/preferences.py 2007-12-08 16:51:36 +0000 @@ -18,7 +18,7 @@ from storm.locals import * from zope.interface import implements -from Mailman.database import Model +from Mailman.database.model import Model from Mailman.database.types import Enum from Mailman.interfaces import IPreferences === renamed file 'Mailman/database/model/requests.py' => 'Mailman/database/requests.py' --- a/Mailman/database/model/requests.py 2007-11-17 05:05:23 +0000 +++ b/Mailman/database/requests.py 2007-12-08 16:51:36 +0000 @@ -22,7 +22,7 @@ from zope.interface import implements from Mailman.configuration import config -from Mailman.database import Model +from Mailman.database.model import Model from Mailman.database.types import Enum from Mailman.interfaces import IListRequests, IPendable, IRequests, RequestType === renamed file 'Mailman/database/model/roster.py' => 'Mailman/database/roster.py' --- a/Mailman/database/model/roster.py 2007-11-08 23:42:56 +0000 +++ b/Mailman/database/roster.py 2007-12-08 16:51:36 +0000 @@ -27,7 +27,8 @@ from Mailman.configuration import config from Mailman.constants import SystemDefaultPreferences -from Mailman.database.model import Address, Member +from Mailman.database.address import Address +from Mailman.database.member import Member from Mailman.interfaces import DeliveryMode, IRoster, MemberRole === renamed file 'Mailman/database/model/user.py' => 'Mailman/database/user.py' --- a/Mailman/database/model/user.py 2007-11-08 11:55:24 +0000 +++ b/Mailman/database/user.py 2007-12-08 16:51:36 +0000 @@ -21,9 +21,9 @@ from Mailman import Errors from Mailman.configuration import config -from Mailman.database import Model -from Mailman.database.model import Address -from Mailman.database.model import Preferences +from Mailman.database.model import Model +from Mailman.database.address import Address +from Mailman.database.preferences import Preferences from Mailman.interfaces import IUser === renamed file 'Mailman/database/model/version.py' => 'Mailman/database/version.py' --- a/Mailman/database/model/version.py 2007-11-04 23:10:21 +0000 +++ b/Mailman/database/version.py 2007-12-08 16:51:36 +0000 @@ -16,7 +16,7 @@ # USA. from storm.locals import * -from Mailman.database import Model +from Mailman.database.model import Model === modified file 'Mailman/database/__init__.py' --- a/Mailman/database/__init__.py 2007-11-07 11:55:13 +0000 +++ b/Mailman/database/__init__.py 2007-12-08 16:51:36 +0000 @@ -23,15 +23,23 @@ ] import os +import Mailman.Version from locknix.lockfile import Lock -from storm.properties import PropertyPublisherMeta +from storm.locals import create_database, Store +from string import Template +from urlparse import urlparse from zope.interface import implements -from Mailman.interfaces import IDatabase +from Mailman.Errors import SchemaVersionMismatchError +from Mailman.configuration import config from Mailman.database.listmanager import ListManager +from Mailman.database.messagestore import MessageStore +from Mailman.database.pending import Pendings +from Mailman.database.requests import Requests from Mailman.database.usermanager import UserManager -from Mailman.database.messagestore import MessageStore +from Mailman.database.version import Version +from Mailman.interfaces import IDatabase @@ -47,46 +55,74 @@ self._store = None def initialize(self, debug=None): - # Avoid circular imports. - from Mailman.configuration import config - from Mailman.database import model - from Mailman.database.model import Pendings - from Mailman.database.model import Requests # Serialize this so we don't get multiple processes trying to create # the database at the same time. with Lock(os.path.join(config.LOCK_DIR, 'dbcreate.lck')): - self.store = model.initialize(debug) + self._create(debug) self.list_manager = ListManager() self.user_manager = UserManager() self.message_store = MessageStore() self.pendings = Pendings() self.requests = Requests() + def _create(self, debug): + # Calculate the engine url. + url = Template(config.DEFAULT_DATABASE_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... + touch(url) + database = create_database(url) + store = Store(database) + database.DEBUG = (config.DEFAULT_DATABASE_ECHO + if debug is None else debug) + # Storm does not currently have schema creation. This is not an ideal + # way to handle creating the database, but it's cheap and easy for + # now. + import Mailman.database + schema_file = os.path.join( + os.path.dirname(Mailman.database.__file__), + 'mailman.sql') + with open(schema_file) as fp: + sql = fp.read() + for statement in sql.split(';'): + store.execute(statement + ';') + # Validate schema version. + v = store.find(Version, component=u'schema').one() + if not v: + # Database has not yet been initialized + v = Version(component=u'schema', + version=Mailman.Version.DATABASE_SCHEMA_VERSION) + store.add(v) + elif v.version <> Mailman.Version.DATABASE_SCHEMA_VERSION: + # XXX Update schema + raise SchemaVersionMismatchError(v.version) + self.store = store + def _reset(self): - for model_class in _class_registry: - for row in self.store.find(model_class): - self.store.remove(row) + from Mailman.database.model import ModelMeta + ModelMeta._reset(self.store) -_class_registry = set() - - -class ModelMeta(PropertyPublisherMeta): - """Do more magic on table classes.""" - - def __init__(self, name, bases, dict): - # Before we let the base class do it's thing, force an __storm_table__ - # property to enforce our table naming convention. - self.__storm_table__ = name.lower() - super(ModelMeta, self).__init__(name, bases, dict) - # Register the model class so that it can be more easily cleared. - # This is required by the test framework. - if name == 'Model': - return - _class_registry.add(self) - - -class Model(object): - """Like Storm's `Storm` subclass, but with a bit extra.""" - __metaclass__ = ModelMeta +def touch(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) === modified file 'Mailman/database/listmanager.py' --- a/Mailman/database/listmanager.py 2007-11-10 18:14:51 +0000 +++ b/Mailman/database/listmanager.py 2007-12-08 16:51:36 +0000 @@ -24,6 +24,7 @@ from Mailman import Errors from Mailman.Utils import split_listname, fqdn_listname from Mailman.configuration import config +from Mailman.database.mailinglist import MailingList from Mailman.interfaces import IListManager @@ -32,8 +33,6 @@ implements(IListManager) def create(self, fqdn_listname): - # Avoid circular imports. - from Mailman.database.model import MailingList listname, hostname = split_listname(fqdn_listname) mlist = config.db.store.find( MailingList, @@ -50,8 +49,6 @@ config.db.store.remove(mlist) def get(self, fqdn_listname): - # Avoid circular imports. - from Mailman.database.model import MailingList listname, hostname = split_listname(fqdn_listname) mlist = config.db.store.find(MailingList, list_name=listname, @@ -70,7 +67,5 @@ @property def names(self): - # Avoid circular imports. - from Mailman.database.model import MailingList for mlist in config.db.store.find(MailingList): yield fqdn_listname(mlist.list_name, mlist.host_name) === modified file 'Mailman/database/messagestore.py' --- a/Mailman/database/messagestore.py 2007-11-10 18:14:51 +0000 +++ b/Mailman/database/messagestore.py 2007-12-08 16:51:36 +0000 @@ -32,6 +32,7 @@ from Mailman import Utils from Mailman.configuration import config +from Mailman.database.message import Message from Mailman.interfaces import IMessageStore # It could be very bad if you have already stored files and you change this @@ -45,7 +46,6 @@ implements(IMessageStore) def add(self, message): - from Mailman.database.model import Message # Ensure that the message has the requisite headers. message_ids = message.get_all('message-id', []) if len(message_ids) <> 1: @@ -96,14 +96,10 @@ return pickle.load(fp) def get_messages_by_message_id(self, message_id): - # Avoid circular imports. - from Mailman.database.model.message import Message for msgrow in config.db.store.find(Message, message_id=message_id): yield self._msgobj(msgrow) def get_messages_by_hash(self, hash): - # Avoid circular imports. - from Mailman.database.model.message import Message # 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 will # always be an 8-string. Coerce to the latter if necessary; it must @@ -119,8 +115,6 @@ seqno = int(seqno) except ValueError: return None - # Avoid circular imports. - from Mailman.database.model.message import Message messages = config.db.store.find(Message, id=seqno) if messages.count() == 0: return None @@ -137,8 +131,6 @@ @property def messages(self): - # Avoid circular imports. - from Mailman.database.model.message import Message for msgrow in config.db.store.find(Message): yield self._msgobj(msgrow) === modified file 'Mailman/database/usermanager.py' --- a/Mailman/database/usermanager.py 2007-11-08 11:55:24 +0000 +++ b/Mailman/database/usermanager.py 2007-12-08 16:51:36 +0000 @@ -25,6 +25,9 @@ from Mailman import Errors from Mailman.configuration import config +from Mailman.database.address import Address +from Mailman.database.preferences import Preferences +from Mailman.database.user import User from Mailman.interfaces import IUserManager @@ -33,8 +36,6 @@ implements(IUserManager) def create_user(self, address=None, real_name=None): - # Avoid circular imports. - from Mailman.database.model import Address, Preferences, User user = User() user.real_name = (u'' if real_name is None else real_name) if address: @@ -50,14 +51,10 @@ @property def users(self): - # Avoid circular imports. - from Mailman.database.model import User for user in config.db.store.find(User): yield user def get_user(self, address): - # Avoid circular imports. - from Mailman.database.model import Address addresses = config.db.store.find(Address, address=address.lower()) if addresses.count() == 0: return None @@ -67,8 +64,6 @@ raise AssertionError('Unexpected query count') def create_address(self, address, real_name=None): - # Avoid circular imports. - from Mailman.database.model import Address, Preferences addresses = config.db.store.find(Address, address=address.lower()) if addresses.count() == 1: found = addresses[0] @@ -91,8 +86,6 @@ config.db.store.remove(address) def get_address(self, address): - # Avoid circular imports. - from Mailman.database.model import Address addresses = config.db.store.find(Address, address=address.lower()) if addresses.count() == 0: return None @@ -103,7 +96,5 @@ @property def addresses(self): - # Avoid circular imports. - from Mailman.database.model.address import Address for address in config.db.store.find(Address): yield address -- https://code.launchpad.net/~mailman-coders/mailman/3.0 You are receiving this branch notification because you are subscribed to it. To unsubscribe from this branch go to https://code.launchpad.net/~mailman-coders/mailman/3.0/+subscription/mailman-checkins. _______________________________________________ Mailman-checkins mailing list Mailman-checkins@python.org Unsubscribe: http://mail.python.org/mailman/options/mailman-checkins/archive%40jab.org