~sambuddhabasu1/mailman/fix_mailman_run_error

« back to all changes in this revision

Viewing changes to Mailman/database/__init__.py

  • Committer: Barry Warsaw
  • Date: 2007-12-08 16:51:36 UTC
  • Revision ID: barry@python.org-20071208165136-gcm3v8d7o3jbb0tt
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.

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
    ]
24
24
 
25
25
import os
 
26
import Mailman.Version
26
27
 
27
28
from locknix.lockfile import Lock
28
 
from storm.properties import PropertyPublisherMeta
 
29
from storm.locals import create_database, Store
 
30
from string import Template
 
31
from urlparse import urlparse
29
32
from zope.interface import implements
30
33
 
31
 
from Mailman.interfaces import IDatabase
 
34
from Mailman.Errors import SchemaVersionMismatchError
 
35
from Mailman.configuration import config
32
36
from Mailman.database.listmanager import ListManager
 
37
from Mailman.database.messagestore import MessageStore
 
38
from Mailman.database.pending import Pendings
 
39
from Mailman.database.requests import Requests
33
40
from Mailman.database.usermanager import UserManager
34
 
from Mailman.database.messagestore import MessageStore
 
41
from Mailman.database.version import Version
 
42
from Mailman.interfaces import IDatabase
35
43
 
36
44
 
37
45
 
47
55
        self._store = None
48
56
 
49
57
    def initialize(self, debug=None):
50
 
        # Avoid circular imports.
51
 
        from Mailman.configuration import config
52
 
        from Mailman.database import model
53
 
        from Mailman.database.model import Pendings
54
 
        from Mailman.database.model import Requests
55
58
        # Serialize this so we don't get multiple processes trying to create
56
59
        # the database at the same time.
57
60
        with Lock(os.path.join(config.LOCK_DIR, 'dbcreate.lck')):
58
 
            self.store = model.initialize(debug)
 
61
            self._create(debug)
59
62
        self.list_manager = ListManager()
60
63
        self.user_manager = UserManager()
61
64
        self.message_store = MessageStore()
62
65
        self.pendings = Pendings()
63
66
        self.requests = Requests()
64
67
 
 
68
    def _create(self, debug):
 
69
        # Calculate the engine url.
 
70
        url = Template(config.DEFAULT_DATABASE_URL).safe_substitute(
 
71
            config.paths)
 
72
        # XXX By design of SQLite, database file creation does not honor
 
73
        # umask.  See their ticket #1193:
 
74
        # http://www.sqlite.org/cvstrac/tktview?tn=1193,31
 
75
        #
 
76
        # This sucks for us because the mailman.db file /must/ be group
 
77
        # writable, however even though we guarantee our umask is 002 here, it
 
78
        # still gets created without the necessary g+w permission, due to
 
79
        # SQLite's policy.  This should only affect SQLite engines because its
 
80
        # the only one that creates a little file on the local file system.
 
81
        # This kludges around their bug by "touch"ing the database file before
 
82
        # SQLite has any chance to create it, thus honoring the umask and
 
83
        # ensuring the right permissions.  We only try to do this for SQLite
 
84
        # engines, and yes, we could have chmod'd the file after the fact, but
 
85
        # half dozen and all...
 
86
        touch(url)
 
87
        database = create_database(url)
 
88
        store = Store(database)
 
89
        database.DEBUG = (config.DEFAULT_DATABASE_ECHO
 
90
                          if debug is None else debug)
 
91
        # Storm does not currently have schema creation.  This is not an ideal
 
92
        # way to handle creating the database, but it's cheap and easy for
 
93
        # now.
 
94
        import Mailman.database
 
95
        schema_file = os.path.join(
 
96
            os.path.dirname(Mailman.database.__file__),
 
97
            'mailman.sql')
 
98
        with open(schema_file) as fp:
 
99
            sql = fp.read()
 
100
        for statement in sql.split(';'):
 
101
            store.execute(statement + ';')
 
102
        # Validate schema version.
 
103
        v = store.find(Version, component=u'schema').one()
 
104
        if not v:
 
105
            # Database has not yet been initialized
 
106
            v = Version(component=u'schema',
 
107
                        version=Mailman.Version.DATABASE_SCHEMA_VERSION)
 
108
            store.add(v)
 
109
        elif v.version <> Mailman.Version.DATABASE_SCHEMA_VERSION:
 
110
            # XXX Update schema
 
111
            raise SchemaVersionMismatchError(v.version)
 
112
        self.store = store
 
113
 
65
114
    def _reset(self):
66
 
        for model_class in _class_registry:
67
 
            for row in self.store.find(model_class):
68
 
                self.store.remove(row)
 
115
        from Mailman.database.model import ModelMeta
 
116
        ModelMeta._reset(self.store)
69
117
 
70
118
 
71
119
 
72
 
_class_registry = set()
73
 
 
74
 
 
75
 
class ModelMeta(PropertyPublisherMeta):
76
 
    """Do more magic on table classes."""
77
 
 
78
 
    def __init__(self, name, bases, dict):
79
 
        # Before we let the base class do it's thing, force an __storm_table__
80
 
        # property to enforce our table naming convention.
81
 
        self.__storm_table__ = name.lower()
82
 
        super(ModelMeta, self).__init__(name, bases, dict)
83
 
        # Register the model class so that it can be more easily cleared.
84
 
        # This is required by the test framework.
85
 
        if name == 'Model':
86
 
            return
87
 
        _class_registry.add(self)
88
 
 
89
 
 
90
 
class Model(object):
91
 
    """Like Storm's `Storm` subclass, but with a bit extra."""
92
 
    __metaclass__ = ModelMeta
 
120
def touch(url):
 
121
    parts = urlparse(url)
 
122
    if parts.scheme <> 'sqlite':
 
123
        return
 
124
    path = os.path.normpath(parts.path)
 
125
    fd = os.open(path, os.O_WRONLY |  os.O_NONBLOCK | os.O_CREAT, 0666)
 
126
    # Ignore errors
 
127
    if fd > 0:
 
128
        os.close(fd)