Create an abstract Repository class

A Repository() returns the correctly instanciated dervivate of a
BaseRepository, depending on the parameters passed to it. The returned
instance is eg an ImapRepository(). This makes the code look nicer,
and we have less functions lying around outside of classes (no more
global LoadRepository() function).

This will also enable us to conveniently hand back a
LocalStatusRepository based on SQLITE rather than plain text, if the
user configures this to be the experimental and optional backend
(once it exists).

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
This commit is contained in:
Sebastian Spaeth 2011-03-03 11:05:15 +01:00 committed by Nicolas Sebrecht
parent d05162675c
commit d5e7620ce9
6 changed files with 82 additions and 35 deletions

View File

@ -16,6 +16,8 @@ New Features
Changes Changes
------- -------
* Rework the repository module
Bug Fixes Bug Fixes
--------- ---------

View File

@ -16,7 +16,7 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
from offlineimap import threadutil, mbnames, CustomConfig from offlineimap import threadutil, mbnames, CustomConfig
import offlineimap.repository.Base, offlineimap.repository.LocalStatus from offlineimap.repository import Repository
from offlineimap.ui import getglobalui from offlineimap.ui import getglobalui
from offlineimap.threadutil import InstanceLimitedThread, ExitNotifyThread from offlineimap.threadutil import InstanceLimitedThread, ExitNotifyThread
from subprocess import Popen, PIPE from subprocess import Popen, PIPE
@ -175,13 +175,10 @@ class AccountSynchronizationMixin:
if not os.path.exists(accountmetadata): if not os.path.exists(accountmetadata):
os.mkdir(accountmetadata, 0700) os.mkdir(accountmetadata, 0700)
self.remoterepos = offlineimap.repository.Base.LoadRepository(self.getconf('remoterepository'), self, 'remote') # get all three repositories
self.remoterepos = Repository(self, 'remote')
# Connect to the local repository. self.localrepos = Repository(self, 'local')
self.localrepos = offlineimap.repository.Base.LoadRepository(self.getconf('localrepository'), self, 'local') self.statusrepos = Repository(self, 'status')
# Connect to the local cache.
self.statusrepos = offlineimap.repository.LocalStatus.LocalStatusRepository(self.getconf('localrepository'), self)
#might need changes here to ensure that one account sync does not crash others... #might need changes here to ensure that one account sync does not crash others...
if not self.refreshperiod: if not self.refreshperiod:

View File

@ -16,32 +16,10 @@
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
from offlineimap import CustomConfig
from offlineimap.ui import getglobalui
import os.path import os.path
import traceback import traceback
from offlineimap import CustomConfig
def LoadRepository(name, account, reqtype): from offlineimap.ui import getglobalui
from offlineimap.repository.Gmail import GmailRepository
from offlineimap.repository.IMAP import IMAPRepository, MappedIMAPRepository
from offlineimap.repository.Maildir import MaildirRepository
if reqtype == 'remote':
# For now, we don't support Maildirs on the remote side.
typemap = {'IMAP': IMAPRepository,
'Gmail': GmailRepository}
elif reqtype == 'local':
typemap = {'IMAP': MappedIMAPRepository,
'Maildir': MaildirRepository}
else:
raise ValueError, "Request type %s not supported" % reqtype
config = account.getconfig()
repostype = config.get('Repository ' + name, 'type').strip()
try:
repo = typemap[repostype]
except KeyError:
raise Exception, "'%s' repository not supported for %s repositories."%\
(repostype, reqtype)
return repo(name, account)
class BaseRepository(CustomConfig.ConfigHelperMixin): class BaseRepository(CustomConfig.ConfigHelperMixin):
def __init__(self, reposname, account): def __init__(self, reposname, account):

View File

@ -15,7 +15,7 @@
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
from IMAP import IMAPRepository from offlineimap.repository.IMAP import IMAPRepository
from offlineimap import folder, imaputil from offlineimap import folder, imaputil
from offlineimap.imapserver import IMAPServer from offlineimap.imapserver import IMAPServer

View File

@ -16,7 +16,7 @@
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
from Base import BaseRepository from offlineimap.repository.Base import BaseRepository
from offlineimap import folder, imaputil, imapserver from offlineimap import folder, imaputil, imapserver
from offlineimap.folder.UIDMaps import MappedIMAPFolder from offlineimap.folder.UIDMaps import MappedIMAPFolder
from offlineimap.threadutil import ExitNotifyThread from offlineimap.threadutil import ExitNotifyThread

View File

@ -1 +1,71 @@
__all__ = ['Gmail', 'IMAP', 'Base', 'Maildir', 'LocalStatus'] # Copyright (C) 2002-2007 John Goerzen <jgoerzen@complete.org>
# 2010 Sebastian Spaeth <Sebastian@SSpaeth.de> and contributors
#
# 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 St, Fifth Floor, Boston, MA 02110-1301 USA
from offlineimap.repository.IMAP import IMAPRepository, MappedIMAPRepository
from offlineimap.repository.Gmail import GmailRepository
from offlineimap.repository.Maildir import MaildirRepository
from offlineimap.repository.LocalStatus import LocalStatusRepository
class Repository(object):
"""Abstract class that returns the correct Repository type
instance based on 'account' and 'reqtype', e.g. a
class:`ImapRepository` instance."""
def __new__(cls, account, reqtype):
"""
:param account: :class:`Account`
:param regtype: 'remote', 'local', or 'status'"""
if reqtype == 'remote':
name = account.getconf('remoterepository')
# We don't support Maildirs on the remote side.
typemap = {'IMAP': IMAPRepository,
'Gmail': GmailRepository}
elif reqtype == 'local':
name = account.getconf('localrepository')
typemap = {'IMAP': MappedIMAPRepository,
'Maildir': MaildirRepository}
elif reqtype == 'status':
# create and return a LocalStatusRepository
name = account.getconf('localrepository')
return LocalStatusRepository(name, account)
else:
raise ValueError, "Request type %s not supported" % reqtype
config = account.getconfig()
repostype = config.get('Repository ' + name, 'type').strip()
try:
repo = typemap[repostype]
except KeyError:
raise Exception, "'%s' repository not supported for %s repositories."%\
(repostype, reqtype)
return repo(name, account)
def __init__(self, account, reqtype):
"""Load the correct Repository type and return that. The
__init__ of the corresponding Repository class will be
executed instead of this stub
:param account: :class:`Account`
:param regtype: 'remote', 'local', or 'status'
"""
pass