forked from openlp/openlp
RFC PT3: Bibles
This commit is contained in:
parent
e71caf43e7
commit
554ab59caf
@ -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
|
||||
|
@ -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')
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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__)
|
||||
|
||||
|
@ -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):
|
||||
"""
|
||||
|
@ -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)
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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):
|
||||
"""
|
||||
|
Loading…
Reference in New Issue
Block a user