diff --git a/openlp/core/lib/db.py b/openlp/core/lib/db.py index 323b48e39..7517998f0 100644 --- a/openlp/core/lib/db.py +++ b/openlp/core/lib/db.py @@ -74,13 +74,20 @@ class Manager(object): """ Provide generic object persistence management """ - def __init__(self, plugin_name, init_schema): + def __init__(self, plugin_name, init_schema, db_file_name=None): """ Runs the initialisation process that includes creating the connection to the database and the tables if they don't exist. ``plugin_name`` The name to setup paths and settings section names + + ``init_schema`` + The init_schema function for this database + + ``db_file_name`` + The file name to use for this database. Defaults to None resulting + in the plugin_name being used. """ settings = QtCore.QSettings() settings.beginGroup(plugin_name) @@ -88,8 +95,13 @@ class Manager(object): db_type = unicode( settings.value(u'db type', QtCore.QVariant(u'sqlite')).toString()) if db_type == u'sqlite': - self.db_url = u'sqlite:///%s/%s.sqlite' % ( - AppLocation.get_section_data_path(plugin_name), plugin_name) + if db_file_name: + self.db_url = u'sqlite:///%s/%s' % ( + AppLocation.get_section_data_path(plugin_name), + db_file_name) + else: + self.db_url = u'sqlite:///%s/%s.sqlite' % ( + AppLocation.get_section_data_path(plugin_name), plugin_name) else: self.db_url = u'%s://%s:%s@%s/%s' % (db_type, unicode(settings.value(u'db username').toString()), @@ -99,6 +111,30 @@ class Manager(object): settings.endGroup() self.session = init_schema(self.db_url) + def delete_database(self, plugin_name, db_file_name=None): + """ + Remove a database file from the system. + + ``plugin_name`` + The name of the plugin to remove the database for + + ``db_file_name`` + The database file name. Defaults to None resulting in the + plugin_name being used. + """ + db_file_path = None + if db_file_name: + db_file_path = os.path.join( + AppLocation.get_section_data_path(plugin_name), db_file_name) + else: + db_file_path = os.path.join( + AppLocation.get_section_data_path(plugin_name), plugin_name) + try: + os.remove(db_file_path) + return True + except OSError: + return False + def insert_object(self, object_instance): """ Save an object to the database diff --git a/openlp/plugins/bibles/forms/importwizardform.py b/openlp/plugins/bibles/forms/importwizardform.py index b1eafcd61..023391615 100644 --- a/openlp/plugins/bibles/forms/importwizardform.py +++ b/openlp/plugins/bibles/forms/importwizardform.py @@ -224,7 +224,7 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): Show the file open dialog for the OSIS file. """ self.getFileName( - translate(u'BiblesPlugin.ImportWizardForm', u'Open OSIS File'), + translate(u'BiblesPlugin.ImportWizardForm', u'Open OSIS File'), self.OSISLocationEdit) def onBooksFileButtonClicked(self): @@ -239,10 +239,8 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): """ Show the file open dialog for the verses CSV file. """ - self.getFileName( - translate(u'BiblesPlugin.ImportWizardForm', - u'Open Verses CSV File'), - self.CsvVerseLocationEdit) + self.getFileName(translate(u'BiblesPlugin.ImportWizardForm', + u'Open Verses CSV File'), self.CsvVerseLocationEdit) def onOpenSongBrowseButtonClicked(self): """ @@ -450,11 +448,11 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): self.ImportProgressLabel.setText( translate(u'BiblesPlugin.ImportWizardForm', u'Your Bible import failed.')) - importer.delete() + importer.delete_database(self.bibleplugin.settingsSection, + importer.file) def postImport(self): self.ImportProgressBar.setValue(self.ImportProgressBar.maximum()) self.finishButton.setVisible(True) self.cancelButton.setVisible(False) Receiver.send_message(u'openlp_process_events') - diff --git a/openlp/plugins/bibles/lib/csvbible.py b/openlp/plugins/bibles/lib/csvbible.py index 3cfe9dea5..9a504f48f 100644 --- a/openlp/plugins/bibles/lib/csvbible.py +++ b/openlp/plugins/bibles/lib/csvbible.py @@ -97,11 +97,11 @@ class CSVBible(BibleDB): book_ptr = book.name self.wizard.incrementProgressBar( u'Importing %s %s' % (book.name, line[1])) - self.commit() + self.session.commit() self.create_verse(book.id, line[1], line[2], unicode(line[3], details['encoding'])) Receiver.send_message(u'openlp_process_events') - self.commit() + self.session.commit() except IOError: log.exception(u'Loading verses from file failed') success = False @@ -113,5 +113,3 @@ class CSVBible(BibleDB): return False else: return success - - diff --git a/openlp/plugins/bibles/lib/db.py b/openlp/plugins/bibles/lib/db.py index 97983e72c..7733261db 100644 --- a/openlp/plugins/bibles/lib/db.py +++ b/openlp/plugins/bibles/lib/db.py @@ -23,19 +23,98 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -import os import logging import chardet import re -from sqlalchemy import or_ from PyQt4 import QtCore +from sqlalchemy import Column, ForeignKey, or_, Table, types +from sqlalchemy.orm import class_mapper, mapper, relation +from sqlalchemy.orm.exc import UnmappedClassError -from openlp.plugins.bibles.lib.models import * +from openlp.core.lib.db import BaseModel, init_db, Manager log = logging.getLogger(__name__) -class BibleDB(QtCore.QObject): +class BibleMeta(BaseModel): + """ + Bible Meta Data + """ + pass + +class Testament(BaseModel): + """ + Bible Testaments + """ + pass + +class Book(BaseModel): + """ + Song model + """ + pass + +class Verse(BaseModel): + """ + Topic model + """ + pass + +def init_schema(url): + """ + Setup a bible database connection and initialise the database schema + + ``url`` + The database to setup + """ + session, metadata = init_db(url) + + meta_table = Table(u'metadata', metadata, + Column(u'key', types.Unicode(255), primary_key=True, index=True), + Column(u'value', types.Unicode(255)), + ) + testament_table = Table(u'testament', metadata, + Column(u'id', types.Integer, primary_key=True), + Column(u'name', types.Unicode(50)), + ) + book_table = Table(u'book', metadata, + Column(u'id', types.Integer, primary_key=True), + Column(u'testament_id', types.Integer, ForeignKey(u'testament.id')), + Column(u'name', types.Unicode(50), index=True), + Column(u'abbreviation', types.Unicode(5), index=True), + ) + verse_table = Table(u'verse', metadata, + Column(u'id', types.Integer, primary_key=True, index=True), + Column(u'book_id', types.Integer, ForeignKey(u'book.id'), index=True), + Column(u'chapter', types.Integer, index=True), + Column(u'verse', types.Integer, index=True), + Column(u'text', types.UnicodeText, index=True), + ) + + try: + class_mapper(BibleMeta) + except UnmappedClassError: + mapper(BibleMeta, meta_table) + try: + class_mapper(Testament) + except UnmappedClassError: + mapper(Testament, testament_table, + properties={'books': relation(Book, backref='testament')}) + try: + class_mapper(Book) + except UnmappedClassError: + mapper(Book, book_table, + properties={'verses': relation(Verse, backref='book')}) + try: + class_mapper(Verse) + except UnmappedClassError: + mapper(Verse, verse_table) + + metadata.create_all(checkfirst=True) + return session + + +class BibleDB(QtCore.QObject, Manager): """ This class represents a database-bound Bible. It is used as a base class for all the custom importers, so that the can implement their own import @@ -72,24 +151,7 @@ class BibleDB(QtCore.QObject): self.file = self.clean_filename(self.name) if u'file' in kwargs: self.file = kwargs[u'file'] - self.db_file = os.path.join(kwargs[u'path'], self.file) - log.debug(u'Load bible %s on path %s', self.file, self.db_file) - settings = QtCore.QSettings() - settings.beginGroup(u'bibles') - db_type = unicode( - settings.value(u'db type', QtCore.QVariant(u'sqlite')).toString()) - db_url = u'' - if db_type == u'sqlite': - db_url = u'sqlite:///' + self.db_file - else: - db_url = u'%s://%s:%s@%s/%s' % (db_type, - unicode(settings.value(u'db username').toString()), - unicode(settings.value(u'db password').toString()), - unicode(settings.value(u'db hostname').toString()), - unicode(settings.value(u'db database').toString())) - settings.endGroup() - self.session = init_models(db_url) - metadata.create_all(checkfirst=True) + Manager.__init__(self, u'bibles', init_schema, self.file) if u'file' in kwargs: self.get_name() @@ -104,7 +166,7 @@ class BibleDB(QtCore.QObject): """ Returns the version name of the Bible. """ - version_name = self.get_meta(u'Version') + version_name = self.get_object(BibleMeta, u'Version') if version_name: self.name = version_name.value else: @@ -124,16 +186,6 @@ class BibleDB(QtCore.QObject): old_filename = re.sub(r'[^\w]+', u'_', old_filename).strip(u'_') return old_filename + u'.sqlite' - def delete(self): - """ - Remove the Bible database file. Used when a Bible import fails. - """ - try: - os.remove(self.db_file) - return True - except OSError: - return False - def register(self, wizard): """ This method basically just initialialises the database. It is called @@ -148,33 +200,15 @@ class BibleDB(QtCore.QObject): self.create_tables() return self.name - def commit(self): - """ - Perform a database commit. - """ - log.debug('Committing...') - self.session.commit() - def create_tables(self): """ Create some initial metadata. """ log.debug(u'createTables') self.create_meta(u'dbversion', u'2') - self.create_testament(u'Old Testament') - self.create_testament(u'New Testament') - self.create_testament(u'Apocrypha') - - def create_testament(self, testament): - """ - Add a testament to the database. - - ``testament`` - The testament name. - """ - log.debug(u'BibleDB.create_testament("%s")', testament) - self.session.add(Testament.populate(name=testament)) - self.commit() + self.insert_object(Testament.populate(name=u'Old Testament')) + self.insert_object(Testament.populate(name=u'New Testament')) + self.insert_object(Testament.populate(name=u'Apocrypha')) def create_book(self, name, abbrev, testament=1): """ @@ -192,8 +226,7 @@ class BibleDB(QtCore.QObject): log.debug(u'create_book %s,%s', name, abbrev) book = Book.populate(name=name, abbreviation=abbrev, testament_id=testament) - self.session.add(book) - self.commit() + self.insert_object(book) return book def create_chapter(self, book_id, chapter, textlist): @@ -220,7 +253,7 @@ class BibleDB(QtCore.QObject): text = verse_text ) self.session.add(verse) - self.commit() + self.session.commit() def create_verse(self, book_id, chapter, verse, text): """ @@ -252,12 +285,7 @@ class BibleDB(QtCore.QObject): def create_meta(self, key, value): log.debug(u'save_meta %s/%s', key, value) - self.session.add(BibleMeta.populate(key=key, value=value)) - self.commit() - - def get_books(self): - log.debug(u'BibleDB.get_books()') - return self.session.query(Book).order_by(Book.id).all() + self.insert_object(BibleMeta.populate(key=key, value=value)) def get_book(self, book): log.debug(u'BibleDb.get_book("%s")', book) @@ -362,19 +390,6 @@ class BibleDB(QtCore.QObject): else: return count - def get_meta(self, key): - log.debug(u'get meta %s', key) - return self.session.query(BibleMeta).get(key) - - def delete_meta(self, metakey): - biblemeta = self.get_meta(metakey) - try: - self.session.delete(biblemeta) - self.commit() - return True - except: - return False - def dump_bible(self): log.debug(u'.........Dumping Bible Database') log.debug('...............................Books ') @@ -383,4 +398,3 @@ class BibleDB(QtCore.QObject): log.debug(u'...............................Verses ') verses = self.session.query(Verse).all() log.debug(verses) - diff --git a/openlp/plugins/bibles/lib/http.py b/openlp/plugins/bibles/lib/http.py index d3d6ca5f6..0b613b4b6 100644 --- a/openlp/plugins/bibles/lib/http.py +++ b/openlp/plugins/bibles/lib/http.py @@ -35,8 +35,7 @@ from openlp.core.lib import Receiver from openlp.core.utils import AppLocation from openlp.plugins.bibles.lib.common import BibleCommon, SearchResults, \ unescape -from openlp.plugins.bibles.lib.db import BibleDB -from openlp.plugins.bibles.lib.models import Book +from openlp.plugins.bibles.lib.db import BibleDB, Book log = logging.getLogger(__name__) diff --git a/openlp/plugins/bibles/lib/manager.py b/openlp/plugins/bibles/lib/manager.py index 7ef18a604..39f3c255b 100644 --- a/openlp/plugins/bibles/lib/manager.py +++ b/openlp/plugins/bibles/lib/manager.py @@ -29,12 +29,12 @@ from PyQt4 import QtCore from openlp.core.lib import SettingsManager from openlp.core.utils import AppLocation +from openlp.plugins.bibles.lib.db import BibleDB, Book, BibleMeta from common import parse_reference from opensong import OpenSongBible from osis import OSISBible from csvbible import CSVBible -from db import BibleDB from http import HTTPBible log = logging.getLogger(__name__) @@ -137,11 +137,13 @@ class BibleManager(object): log.debug(u'Bible Name: "%s"', name) self.db_cache[name] = bible # look to see if lazy load bible exists and get create getter. - source = self.db_cache[name].get_meta(u'download source') + source = self.db_cache[name].get_object(BibleMeta, + u'download source') if source: - download_name = \ - self.db_cache[name].get_meta(u'download name').value - meta_proxy = self.db_cache[name].get_meta(u'proxy url') + download_name = self.db_cache[name].get_object(BibleMeta, + u'download name').value + meta_proxy = self.db_cache[name].get_object(BibleMeta, + u'proxy url') web_bible = HTTPBible(self.parent, path=self.path, file=filename, download_source=source.value, download_name=download_name) @@ -196,7 +198,7 @@ class BibleManager(object): u'name': book.name, u'chapters': self.db_cache[bible].get_chapter_count(book.name) } - for book in self.db_cache[bible].get_books() + for book in self.db_cache[bible].get_all_objects(Book, Book.id) ] def get_chapter_count(self, bible, book): @@ -249,7 +251,7 @@ class BibleManager(object): Returns the meta data for a given key """ log.debug(u'get_meta %s,%s', bible, key) - return self.db_cache[bible].get_meta(key) + return self.db_cache[bible].get_object(BibleMeta, key) def exists(self, name): """ diff --git a/openlp/plugins/bibles/lib/models.py b/openlp/plugins/bibles/lib/models.py deleted file mode 100644 index 2cd52fb0b..000000000 --- a/openlp/plugins/bibles/lib/models.py +++ /dev/null @@ -1,94 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin # -# Thompson, Jon Tibble, Carsten Tinggaard # -# --------------------------------------------------------------------------- # -# 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; version 2 of the License. # -# # -# 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., 59 # -# Temple Place, Suite 330, Boston, MA 02111-1307 USA # -############################################################################### - -from sqlalchemy import Column, Table, MetaData, ForeignKey, types, \ - create_engine -from sqlalchemy.orm import mapper, relation, sessionmaker, scoped_session - -from openlp.core.lib.db import BaseModel - - -class BibleMeta(BaseModel): - """ - Bible Meta Data - """ - pass - - -class Testament(BaseModel): - """ - Bible Testaments - """ - pass - - -class Book(BaseModel): - """ - Song model - """ - pass - - -class Verse(BaseModel): - """ - Topic model - """ - pass - -def init_models(db_url): - engine = create_engine(db_url) - metadata.bind = engine - session = scoped_session(sessionmaker(autoflush=True, autocommit=False, - bind=engine)) - return session - -metadata = MetaData() -meta_table = Table(u'metadata', metadata, - Column(u'key', types.Unicode(255), primary_key=True, index=True), - Column(u'value', types.Unicode(255)), -) -testament_table = Table(u'testament', metadata, - Column(u'id', types.Integer, primary_key=True), - Column(u'name', types.Unicode(50)), -) -book_table = Table(u'book', metadata, - Column(u'id', types.Integer, primary_key=True), - Column(u'testament_id', types.Integer, ForeignKey(u'testament.id')), - Column(u'name', types.Unicode(50), index=True), - Column(u'abbreviation', types.Unicode(5), index=True), -) -verse_table = Table(u'verse', metadata, - Column(u'id', types.Integer, primary_key=True, index=True), - Column(u'book_id', types.Integer, ForeignKey(u'book.id'), index=True), - Column(u'chapter', types.Integer, index=True), - Column(u'verse', types.Integer, index=True), - Column(u'text', types.UnicodeText, index=True), -) -mapper(BibleMeta, meta_table) -mapper(Testament, testament_table, - properties={'books': relation(Book, backref='testament')}) -mapper(Book, book_table, - properties={'verses': relation(Verse, backref='book')}) -mapper(Verse, verse_table) diff --git a/openlp/plugins/bibles/lib/opensong.py b/openlp/plugins/bibles/lib/opensong.py index b2df50257..dfdc542ef 100644 --- a/openlp/plugins/bibles/lib/opensong.py +++ b/openlp/plugins/bibles/lib/opensong.py @@ -90,7 +90,7 @@ class OpenSongBible(BibleDB): QtCore.QString('%s %s %s' % ( translate(u'BiblesPlugin.Opensong', u'Importing'), \ db_book.name, chapter.attrib[u'n']))) - self.commit() + self.session.commit() except IOError: log.exception(u'Loading bible from OpenSong file failed') success = False diff --git a/openlp/plugins/bibles/lib/osis.py b/openlp/plugins/bibles/lib/osis.py index b4a2a2aa1..2f30cf63c 100644 --- a/openlp/plugins/bibles/lib/osis.py +++ b/openlp/plugins/bibles/lib/osis.py @@ -136,7 +136,7 @@ class OSISBible(BibleDB): self.wizard.ImportProgressBar.setMaximum(260) if last_chapter != chapter: if last_chapter != 0: - self.commit() + self.session.commit() self.wizard.incrementProgressBar( u'Importing %s %s...' % \ (self.books[match.group(1)][0], chapter)) @@ -162,7 +162,7 @@ class OSISBible(BibleDB): verse_text = self.spaces_regex.sub(u' ', verse_text) self.create_verse(db_book.id, chapter, verse, verse_text) Receiver.send_message(u'openlp_process_events') - self.commit() + self.session.commit() self.wizard.incrementProgressBar(u'Finishing import...') if match_count == 0: success = False diff --git a/openlp/plugins/songs/lib/songimport.py b/openlp/plugins/songs/lib/songimport.py index 2d6a4cd21..36a9b9953 100644 --- a/openlp/plugins/songs/lib/songimport.py +++ b/openlp/plugins/songs/lib/songimport.py @@ -28,8 +28,8 @@ import string from PyQt4 import QtGui from openlp.core.lib import SongXMLBuilder +from openlp.plugins.songs.lib import VerseType from openlp.plugins.songs.lib.db import Song, Author, Topic, Book -from openlp.plugins.songs.forms import VerseType class SongImport(object): """