From 261b162f4512609fb8fabd23f44e6ddc0536d43b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20=27Necoro=27=20Neumann?= Date: Thu, 20 May 2010 13:01:27 +0200 Subject: More declarative handling of the database types --- portato/db/__init__.py | 95 ++++++++++++++++++++++----------------- portato/db/exceptions.py | 2 + portato/gui/windows/preference.py | 8 ++-- 3 files changed, 59 insertions(+), 46 deletions(-) (limited to 'portato') diff --git a/portato/db/__init__.py b/portato/db/__init__.py index 21d8f80..bb5c6fc 100644 --- a/portato/db/__init__.py +++ b/portato/db/__init__.py @@ -12,66 +12,79 @@ from __future__ import absolute_import +from collections import namedtuple + from . import database as db -from .exceptions import UnknownDatabaseTypeError, DatabaseInstantiationError +from .exceptions import UnknownDatabaseTypeError, DatabaseInstantiationError, DatabaseInitError from ..session import Session, SectionDict from ..helper import debug, warning, error, info +from ..odict import OrderedDict + +DBType = namedtuple("DBType", "name descr module cls alt") + +types = [ + ("eixsql", + DBType( + _("eix + SQLite"), + _("Similar to SQLite, but now uses the eix database to get the package information.\nThis should be much faster on startup, but requires that your eix database is always up-to-date.\nAdditionally, this is the only database allowing searching in descriptions."), + "eix_sql", "EixSQLDatabase", + "sql")), + ("sql", + DBType( + _("SQLite"), + _("Uses an SQLite-database to store package information.\nMay take longer to generate at the first time, but has advantages if portato is re-started with an unchanged portage tree. Additionally it allows to use fast SQL expressions for fetching the data."), + "sql", "SQLDatabase", + "dict")), + ("dict", + DBType( + _("Hashmap"), + _("Uses an in-memory hashmap to store package information.\nHas been used since at least version 0.3.3, but all information has to be regenerated on each startup."), + "hash", "HashDatabase", + None)) + ] -types = ( - ("eixsql", _("eix + SQLite"), _("Similar to SQLite, but now uses the eix database to get the package information.\nThis should be much faster on startup, but requires that your eix database is always up-to-date.\nAdditionally, this is the only database allowing searching in descriptions.")), - ("sql", _("SQLite"), _("Uses an SQLite-database to store package information.\nMay take longer to generate at the first time, but has advantages if portato is re-started with an unchanged portage tree. Additionally it allows to use fast SQL expressions for fetching the data.")), - ("dict", _("Hashmap"), _("Uses an in-memory hashmap to store package information.\nHas been used since at least version 0.3.3, but all information has to be regenerated on each startup.")) - ) +types = OrderedDict(types) class Database(db.Database): DEFAULT = "dict" def __new__ (cls, type = None): - if not '_the_instance' in cls.__dict__: - dbcls = cls._generate(type) - cls._the_instance = dbcls(cls._get_session()) - elif type is not None: - raise DatabaseInstantiationError("Database instantiation called with 'type' argument multiple times.") + try: + if not '_the_instance' in cls.__dict__: + dbcls = cls._generate(type) + cls._the_instance = dbcls(cls._get_session()) + elif type is not None: + raise DatabaseInstantiationError("Database instantiation called with 'type' argument multiple times.") + except (ImportError, DatabaseInitError) as e: + db = types[cls.DB_TYPE] + error(_("Cannot load %s."), db.cls) + error(_("Error: %s"), e) + + if db.alt is not None: + return cls.__new__(cls, db.alt) + else: + error(_("No alternative database given. Aborting.")) + raise DatabaseInstantiationError("Cannot load database.") + return cls._the_instance @classmethod def _generate(cls, type): - if type is None: warning("No database type specified! Falling back to default.") type = cls.DEFAULT - - cls.DB_TYPE = type - msg = _("Using database type '%s'") - if type == "sql": - info(msg, "SQLDatabase") - try: - from .sql import SQLDatabase - except ImportError: - warning(_("Cannot load %s."), "SQLDatabase") - return cls._generate("dict") - else: - return SQLDatabase - - elif type == "dict": - info(msg, "HashDatabase") - from .hash import HashDatabase - return HashDatabase - - elif type == "eixsql": - info(msg,"EixSQLDatabase") - try: - from .eix_sql import EixSQLDatabase - except ImportError: - warning(_("Cannot load %s."), "EixSQLDatabase.") - return cls._generate("sql") - else: - return EixSQLDatabase - - else: + try: + db = types[type] + except KeyError: error(_("Unknown database type: %s"), type) raise UnknownDatabaseTypeError, type + + cls.DB_TYPE = type + info(_("Using database type '%s'"), db.cls) + + mod = __import__(db.module, globals(), locals(), [db.cls]) + return getattr(mod, db.cls) @classmethod def _get_session(cls): diff --git a/portato/db/exceptions.py b/portato/db/exceptions.py index 8a6e424..82fa337 100644 --- a/portato/db/exceptions.py +++ b/portato/db/exceptions.py @@ -22,3 +22,5 @@ class DatabaseInstantiationError (DatabaseError): class UnsupportedSearchTypeError(DatabaseError): pass +class DatabaseInitError (DatabaseError): + pass diff --git a/portato/gui/windows/preference.py b/portato/gui/windows/preference.py index 2b6974e..dd2a892 100644 --- a/portato/gui/windows/preference.py +++ b/portato/gui/windows/preference.py @@ -168,14 +168,12 @@ class PreferenceWindow (AbstractDialog): self.databaseCombo = self.tree.get_widget("databaseCombo") model = gtk.ListStore(str, str, str) - ctr = 0 active = 0 - for k, name, desc in db.types: - if k == dbtype: + for ctr, (key, t) in enumerate(db.types.iteritems()): + if key == dbtype: active = ctr - model.append([name, desc, k]) - ctr += 1 + model.append([t.name, t.descr, key]) self.databaseCombo.set_model(model) self.databaseCombo.set_active(active) -- cgit v1.2.3