From 5495accf05d77e1c4ff2855f5e42c2e56f51e45d Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Sat, 8 Dec 2007 11:51:36 -0500 Subject: [PATCH] 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. --- Mailman/database/__init__.py | 102 +++++++++++++++++--------- Mailman/database/{model => }/address.py | 6 +- Mailman/database/{model => }/language.py | 0 Mailman/database/listmanager.py | 7 +- Mailman/database/{model => }/mailinglist.py | 6 +- Mailman/database/{model => }/mailman.sql | 0 Mailman/database/{model => }/member.py | 2 +- Mailman/database/{model => }/message.py | 2 +- Mailman/database/messagestore.py | 10 +-- Mailman/database/{__init__.py => model.py} | 61 ++++------------ Mailman/database/model/__init__.py | 108 ---------------------------- Mailman/database/{model => }/pending.py | 2 +- Mailman/database/{model => }/preferences.py | 2 +- Mailman/database/{model => }/requests.py | 2 +- Mailman/database/{model => }/roster.py | 3 +- Mailman/database/{model => }/user.py | 6 +- Mailman/database/usermanager.py | 15 +--- Mailman/database/{model => }/version.py | 2 +- {Mailman/data => data}/PythonPowered.png | Bin {Mailman/data => data}/__init__.py | 0 {Mailman/data => data}/coverage.py | 0 {Mailman/data => data}/gnu-head-tiny.jpg | Bin {Mailman/data => data}/mailman-large.jpg | Bin {Mailman/data => data}/mailman.cfg.in | 0 {Mailman/data => data}/mailman.in | 0 {Mailman/data => data}/mailman.jpg | Bin {Mailman/data => data}/mm-icon.png | Bin {Mailman/data => data}/paths.py.in | 0 28 files changed, 103 insertions(+), 233 deletions(-) rename Mailman/database/{model => }/address.py (95%) rename Mailman/database/{model => }/language.py (100%) rename Mailman/database/{model => }/mailinglist.py (98%) rename Mailman/database/{model => }/mailman.sql (100%) rename Mailman/database/{model => }/member.py (98%) rename Mailman/database/{model => }/message.py (97%) copy Mailman/database/{__init__.py => model.py} (50%) delete mode 100644 Mailman/database/model/__init__.py rename Mailman/database/{model => }/pending.py (99%) rename Mailman/database/{model => }/preferences.py (96%) rename Mailman/database/{model => }/requests.py (99%) rename Mailman/database/{model => }/roster.py (98%) rename Mailman/database/{model => }/user.py (94%) rename Mailman/database/{model => }/version.py (96%) rename {Mailman/data => data}/PythonPowered.png (100%) rename {Mailman/data => data}/__init__.py (100%) rename {Mailman/data => data}/coverage.py (100%) rename {Mailman/data => data}/gnu-head-tiny.jpg (100%) rename {Mailman/data => data}/mailman-large.jpg (100%) rename {Mailman/data => data}/mailman.cfg.in (100%) rename {Mailman/data => data}/mailman.in (100%) rename {Mailman/data => data}/mailman.jpg (100%) rename {Mailman/data => data}/mm-icon.png (100%) rename {Mailman/data => data}/paths.py.in (100%) diff --git a/Mailman/database/__init__.py b/Mailman/database/__init__.py index 78b118be6..d332254c6 100644 --- a/Mailman/database/__init__.py +++ b/Mailman/database/__init__.py @@ -23,15 +23,23 @@ __all__ = [ ] 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.usermanager import UserManager 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.version import Version +from Mailman.interfaces import IDatabase @@ -47,46 +55,74 @@ class StockDatabase: 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) diff --git a/Mailman/database/model/address.py b/Mailman/database/address.py similarity index 95% rename from Mailman/database/model/address.py rename to Mailman/database/address.py index b8e2f0f31..a67fe41dc 100644 --- a/Mailman/database/model/address.py +++ b/Mailman/database/address.py @@ -21,7 +21,9 @@ from zope.interface import implements 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 @@ class Address(Model): 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, diff --git a/Mailman/database/model/language.py b/Mailman/database/language.py similarity index 100% rename from Mailman/database/model/language.py rename to Mailman/database/language.py diff --git a/Mailman/database/listmanager.py b/Mailman/database/listmanager.py index 48e7fe62c..01720b37c 100644 --- a/Mailman/database/listmanager.py +++ b/Mailman/database/listmanager.py @@ -24,6 +24,7 @@ from zope.interface import implements 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 @@ class ListManager(object): 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 @@ class ListManager(object): 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 @@ class ListManager(object): @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) diff --git a/Mailman/database/model/mailinglist.py b/Mailman/database/mailinglist.py similarity index 98% rename from Mailman/database/model/mailinglist.py rename to Mailman/database/mailinglist.py index 3a3396758..04c872aab 100644 --- a/Mailman/database/model/mailinglist.py +++ b/Mailman/database/mailinglist.py @@ -23,10 +23,12 @@ from zope.interface import implements 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 @@ class MailingList(Model): # 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) diff --git a/Mailman/database/model/mailman.sql b/Mailman/database/mailman.sql similarity index 100% rename from Mailman/database/model/mailman.sql rename to Mailman/database/mailman.sql diff --git a/Mailman/database/model/member.py b/Mailman/database/member.py similarity index 98% rename from Mailman/database/model/member.py rename to Mailman/database/member.py index 3f9775d3c..f77b8c7c3 100644 --- a/Mailman/database/model/member.py +++ b/Mailman/database/member.py @@ -21,7 +21,7 @@ from zope.interface import implements 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 diff --git a/Mailman/database/model/message.py b/Mailman/database/message.py similarity index 97% rename from Mailman/database/model/message.py rename to Mailman/database/message.py index c4ea4a636..b8a7e3dfb 100644 --- a/Mailman/database/model/message.py +++ b/Mailman/database/message.py @@ -19,7 +19,7 @@ from storm.locals import * 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 diff --git a/Mailman/database/messagestore.py b/Mailman/database/messagestore.py index 7c90918ac..69c5d58d5 100644 --- a/Mailman/database/messagestore.py +++ b/Mailman/database/messagestore.py @@ -32,6 +32,7 @@ from zope.interface import implements 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 @@ class MessageStore: 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 @@ class MessageStore: 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 @@ class MessageStore: 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 @@ class MessageStore: @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) diff --git a/Mailman/database/__init__.py b/Mailman/database/model.py similarity index 50% copy from Mailman/database/__init__.py copy to Mailman/database/model.py index 78b118be6..3b41af123 100644 --- a/Mailman/database/__init__.py +++ b/Mailman/database/model.py @@ -15,66 +15,22 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. -from __future__ import with_statement +"""Base class for all database classes.""" __metaclass__ = type __all__ = [ - 'StockDatabase', + 'Model', ] -import os - -from locknix.lockfile import Lock from storm.properties import PropertyPublisherMeta -from zope.interface import implements - -from Mailman.interfaces import IDatabase -from Mailman.database.listmanager import ListManager -from Mailman.database.usermanager import UserManager -from Mailman.database.messagestore import MessageStore -class StockDatabase: - implements(IDatabase) - - def __init__(self): - self.list_manager = None - self.user_manager = None - self.message_store = None - self.pendings = None - self.requests = None - 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.list_manager = ListManager() - self.user_manager = UserManager() - self.message_store = MessageStore() - self.pendings = Pendings() - self.requests = Requests() - - def _reset(self): - for model_class in _class_registry: - for row in self.store.find(model_class): - self.store.remove(row) - - - -_class_registry = set() - - 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. @@ -84,9 +40,16 @@ class ModelMeta(PropertyPublisherMeta): # This is required by the test framework. if name == 'Model': return - _class_registry.add(self) + 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 diff --git a/Mailman/database/model/__init__.py b/Mailman/database/model/__init__.py deleted file mode 100644 index c15670403..000000000 --- a/Mailman/database/model/__init__.py +++ /dev/null @@ -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) diff --git a/Mailman/database/model/pending.py b/Mailman/database/pending.py similarity index 99% rename from Mailman/database/model/pending.py rename to Mailman/database/pending.py index 3f3e2caa0..1a272391d 100644 --- a/Mailman/database/model/pending.py +++ b/Mailman/database/pending.py @@ -28,7 +28,7 @@ from zope.interface import implements 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) diff --git a/Mailman/database/model/preferences.py b/Mailman/database/preferences.py similarity index 96% rename from Mailman/database/model/preferences.py rename to Mailman/database/preferences.py index 65d909bd0..726856f74 100644 --- a/Mailman/database/model/preferences.py +++ b/Mailman/database/preferences.py @@ -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 diff --git a/Mailman/database/model/requests.py b/Mailman/database/requests.py similarity index 99% rename from Mailman/database/model/requests.py rename to Mailman/database/requests.py index 64fff7c48..d86960f1d 100644 --- a/Mailman/database/model/requests.py +++ b/Mailman/database/requests.py @@ -22,7 +22,7 @@ from storm.locals import * 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 diff --git a/Mailman/database/model/roster.py b/Mailman/database/roster.py similarity index 98% rename from Mailman/database/model/roster.py rename to Mailman/database/roster.py index 55723893d..9bd97316f 100644 --- a/Mailman/database/model/roster.py +++ b/Mailman/database/roster.py @@ -27,7 +27,8 @@ from zope.interface import implements 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 diff --git a/Mailman/database/model/user.py b/Mailman/database/user.py similarity index 94% rename from Mailman/database/model/user.py rename to Mailman/database/user.py index 84b5a4595..3ca320f36 100644 --- a/Mailman/database/model/user.py +++ b/Mailman/database/user.py @@ -21,9 +21,9 @@ from zope.interface import implements 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 diff --git a/Mailman/database/usermanager.py b/Mailman/database/usermanager.py index ab41409d8..19024d06c 100644 --- a/Mailman/database/usermanager.py +++ b/Mailman/database/usermanager.py @@ -25,6 +25,9 @@ from zope.interface import implements 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 @@ class UserManager(object): 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 @@ class UserManager(object): @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 @@ class UserManager(object): 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 @@ class UserManager(object): 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 @@ class UserManager(object): @property def addresses(self): - # Avoid circular imports. - from Mailman.database.model.address import Address for address in config.db.store.find(Address): yield address diff --git a/Mailman/database/model/version.py b/Mailman/database/version.py similarity index 96% rename from Mailman/database/model/version.py rename to Mailman/database/version.py index 2f4ff3f4d..a9aaeb45d 100644 --- a/Mailman/database/model/version.py +++ b/Mailman/database/version.py @@ -16,7 +16,7 @@ # USA. from storm.locals import * -from Mailman.database import Model +from Mailman.database.model import Model diff --git a/Mailman/data/PythonPowered.png b/data/PythonPowered.png similarity index 100% rename from Mailman/data/PythonPowered.png rename to data/PythonPowered.png diff --git a/Mailman/data/__init__.py b/data/__init__.py similarity index 100% rename from Mailman/data/__init__.py rename to data/__init__.py diff --git a/Mailman/data/coverage.py b/data/coverage.py similarity index 100% rename from Mailman/data/coverage.py rename to data/coverage.py diff --git a/Mailman/data/gnu-head-tiny.jpg b/data/gnu-head-tiny.jpg similarity index 100% rename from Mailman/data/gnu-head-tiny.jpg rename to data/gnu-head-tiny.jpg diff --git a/Mailman/data/mailman-large.jpg b/data/mailman-large.jpg similarity index 100% rename from Mailman/data/mailman-large.jpg rename to data/mailman-large.jpg diff --git a/Mailman/data/mailman.cfg.in b/data/mailman.cfg.in similarity index 100% rename from Mailman/data/mailman.cfg.in rename to data/mailman.cfg.in diff --git a/Mailman/data/mailman.in b/data/mailman.in similarity index 100% rename from Mailman/data/mailman.in rename to data/mailman.in diff --git a/Mailman/data/mailman.jpg b/data/mailman.jpg similarity index 100% rename from Mailman/data/mailman.jpg rename to data/mailman.jpg diff --git a/Mailman/data/mm-icon.png b/data/mm-icon.png similarity index 100% rename from Mailman/data/mm-icon.png rename to data/mm-icon.png diff --git a/Mailman/data/paths.py.in b/data/paths.py.in similarity index 100% rename from Mailman/data/paths.py.in rename to data/paths.py.in -- 2.11.4.GIT