Lots of changes here, I think.

- Pluggable import system
- The enumeration class provides the correct importer class
- Reworked Bible verse parsing, using regular expressions
- Reworked verse query method to accept multiple verse ranges
- Renamed lots of methods, which is probably gonna break lots of stuff
This commit is contained in:
Raoul Snyman 2009-12-30 19:29:08 +02:00
parent 34ab7ea901
commit 0374233db6
10 changed files with 474 additions and 366 deletions

View File

@ -169,6 +169,15 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok))
self.CopyrightEdit.setFocus()
return False
elif self.biblemanager.exists(
self.field(u'license_version').toString()):
QtGui.QMessageBox.critical(self,
self.trUtf8('Bible Exists'),
self.trUtf8('This Bible already exists! Please import '
'a different Bible or first delete the existing one.'),
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok))
self.VersionNameEdit.setFocus()
return False
return True
if self.currentId() == 3:
# Progress page
@ -317,22 +326,22 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
success = False
if bible_type == BibleFormat.OSIS:
# Import an OSIS bible
success = self.biblemanager.register_osis_file_bible(
unicode(self.field(u'license_version').toString()),
unicode(self.field(u'osis_location').toString())
success = self.biblemanager.import_bible(BibleFormat.OSIS,
name=unicode(self.field(u'license_version').toString()),
filename=unicode(self.field(u'osis_location').toString())
)
elif bible_type == BibleFormat.CSV:
# Import a CSV bible
success = self.biblemanager.register_csv_file_bible(
unicode(self.field(u'license_version').toString()),
self.field(u'csv_booksfile').toString(),
self.field(u'csv_versefile').toString()
success = self.biblemanager.import_bible(BibleFormat.CSV,
name=unicode(self.field(u'license_version').toString()),
booksfile=self.field(u'csv_booksfile').toString(),
versefile=self.field(u'csv_versefile').toString()
)
elif bible_type == BibleFormat.OpenSong:
# Import an OpenSong bible
success = self.biblemanager.register_opensong_bible(
unicode(self.field(u'license_version').toString()),
self.field(u'opensong_file').toString()
success = self.biblemanager.import_bible(BibleFormat.OpenSong,
name=unicode(self.field(u'license_version').toString()),
filename=self.field(u'opensong_file').toString()
)
elif bible_type == BibleFormat.WebDownload:
# Import a bible from the web
@ -344,13 +353,13 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
elif download_location == DownloadLocation.BibleGateway:
bible = self.web_bible_list[DownloadLocation.BibleGateway][
unicode(self.BibleComboBox.currentText())]
success = self.biblemanager.register_http_bible(
unicode(self.field(u'license_version').toString()),
unicode(DownloadLocation.get_name(download_location)),
unicode(bible),
unicode(self.field(u'proxy_server').toString()),
unicode(self.field(u'proxy_username').toString()),
unicode(self.field(u'proxy_password').toString())
success = self.biblemanager.import_bible(BibleFormat.WebDownload,
name=unicode(self.field(u'license_version').toString()),
download_source=unicode(DownloadLocation.get_name(download_location)),
download_name=unicode(bible),
proxy_server=unicode(self.field(u'proxy_server').toString()),
proxy_username=unicode(self.field(u'proxy_username').toString()),
proxy_password=unicode(self.field(u'proxy_password').toString())
)
if success:
self.biblemanager.save_meta_data(
@ -359,6 +368,7 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
unicode(self.field(u'license_copyright').toString()),
unicode(self.field(u'license_permission').toString())
)
self.biblemanager.reload_bibles()
self.ImportProgressLabel.setText(self.trUtf8('Finished import.'))
else:
self.ImportProgressLabel.setText(

View File

@ -26,6 +26,63 @@
import urllib2
import chardet
import logging
import re
only_verses = re.compile(r'([a-zA-Z0-9 ]+)[ ]+([0-9]+)[ ]*[:|v|V][ ]*([0-9]+)'
r'(?:[ ]*-[ ]*([0-9]+|end))?(?:[ ]*,[ ]*([0-9]+)(?:[ ]*-[ ]*([0-9]+|end))?)?',
re.UNICODE)
chapter_range = re.compile(r'([a-zA-Z0-9 ]+)[ ]+([0-9]+)[ ]*[:|v|V][ ]*'
r'([0-9]+)[ ]*-[ ]*([0-9]+)[ ]*[:|v|V][ ]*([0-9]+)',
re.UNICODE)
def parse_reference(reference):
"""
This is the über-awesome function that takes a person's typed in string
and converts it to a reference list, a list of references to be queried
from the Bible database files.
The reference list is a list of tuples, with each tuple structured like
this::
(book, chapter, start_verse, end_verse)
"""
reference = reference.strip()
reference_list = []
# We start with the most "complicated" match first, so that they are found
# first, and we don't have any "false positives".
match = chapter_range.match(reference)
if match:
reference_list.extend([
(match.group(1), match.group(2), match.group(3), -1),
(match.group(1), match.group(4), 1, match.group(5))
])
else:
match = only_verses.match(reference)
if match:
book = match.group(1)
chapter = match.group(2)
verse = match.group(3)
if match.group(4) is None:
reference_list.append((book, chapter, verse, verse))
elif match.group(5) is None:
end_verse = match.group(4)
if end_verse == u'end':
end_verse = -1
reference_list.append((book, chapter, verse, end_verse))
elif match.group(6) is None:
reference_list.extend([
(book, chapter, verse, match.group(4)),
(book, chapter, match.group(5), match.group(5))
])
else:
end_verse = match.group(6)
if end_verse == u'end':
end_verse = -1
reference_list.extend([
(book, chapter, verse, match.group(4)),
(book, chapter, match.group(5), end_verse)
])
return reference_list
class SearchResults:
"""
@ -81,14 +138,6 @@ class BibleCommon(object):
log = logging.getLogger(u'BibleCommon')
log.info(u'BibleCommon')
def __init__(self):
"""
An empty constructor... not sure why I'm here.
"""
self.loadbible = True
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'openlpstopimport'), self.stop_import)
def _get_web_text(self, urlstring, proxyurl):
"""
Get the HTML from the web page.

View File

@ -26,8 +26,8 @@
import logging
import chardet
from openlp.plugins.bibles.lib.db import BibleDB
from openlp.core.lib import Receiver
from db import BibleDB
log = logging.getLogger(__name__)
@ -44,20 +44,22 @@ class CSVBible(BibleDB):
"""
log.info(__name__)
BibleDB.__init__(self, **kwargs)
if u'booksfile' not in kwargs:
raise KeyError(u'You have to supply a file to import books from.')
self.booksfile = kwargs[u'booksfile']
if u'versesfile' not in kwargs:
raise KeyError(u'You have to supply a file to import verses from.')
self.versesfile = kwargs[u'versesfile']
def stop_import(self):
self.loadbible = False
def load_data(self, booksfile, versesfile, dialogobject):
def do_import(self):
#Populate the Tables
success = True
fbooks = None
try:
fbooks = open(booksfile, 'r')
count = 0
fbooks = open(self.booksfile, 'r')
for line in fbooks:
# cancel pressed
if not self.loadbible:
if self.stop_import:
break
details = chardet.detect(line)
line = unicode(line, details['encoding'])
@ -65,12 +67,8 @@ class CSVBible(BibleDB):
p1 = p[1].replace(u'"', u'')
p2 = p[2].replace(u'"', u'')
p3 = p[3].replace(u'"', u'')
self.bibledb.create_book(p2, p3, int(p1))
count += 1
#Flush the screen events
if count % 3 == 0:
Receiver.send_message(u'process_events')
count = 0
self.create_book(p2, p3, int(p1))
Receiver.send_message(u'process_events')
except:
log.exception(u'Loading books from file failed')
success = False
@ -82,10 +80,9 @@ class CSVBible(BibleDB):
fverse = None
try:
fverse = open(versesfile, 'r')
count = 0
book_ptr = None
for line in fverse:
if not self.loadbible: # cancel pressed
if self.stop_import: # cancel pressed
break
details = chardet.detect(line)
line = unicode(line, details['encoding'])
@ -94,28 +91,23 @@ class CSVBible(BibleDB):
p0 = p[0].replace(u'"', u'')
p3 = p[3].replace(u'"', u'')
if book_ptr is not p0:
book = self.bibledb.get_bible_book(p0)
book = self.get_book(p0)
book_ptr = book.name
# increament the progress bar
dialogobject.incrementProgressBar(u'Importing %s %s' % \
book.name)
self.bibledb.add_verse(book.id, p[1], p[2], p3)
count += 1
#Every x verses repaint the screen
if count % 3 == 0:
Receiver.send_message(u'process_events')
count = 0
self.bibledb.save_verses()
self.wizard.incrementProgressBar(
u'Importing %s %s' % book.name)
self.commit()
self.add_verse(book.id, p[1], p[2], p3)
Receiver.send_message(u'process_events')
self.commit()
except:
log.exception(u'Loading verses from file failed')
success = False
finally:
if fverse:
fverse.close()
if not self.loadbible:
dialogobject.incrementProgressBar(u'Import canceled!')
dialogobject.ImportProgressBar.setValue(
dialogobject.ImportProgressBar.maximum())
if self.stop_import:
self.wizard.incrementProgressBar(u'Import canceled!')
return False
else:
return success

View File

@ -26,12 +26,15 @@
import os
import logging
from common import BibleCommon
from sqlalchemy import or_
from PyQt4 import QtCore
from openlp.core.lib import Receiver
from models import *
log = logging.getLogger(__name__)
class BibleDB(BibleCommon):
class BibleDB():
"""
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
@ -40,22 +43,39 @@ class BibleDB(BibleCommon):
"""
def __init__(self, **kwargs):
"""
The constructor loads up the database and creates and initialises the
tables if the database doesn't exist.
**Required keyword arguments:**
``path``
The path to the bible database file.
``name``
The name of the database. This is also used as the file name for
SQLite databases.
``config``
The configuration object, passed in from the plugin.
"""
log.info(u'BibleDBimpl loaded')
if u'biblepath' not in kwargs:
if u'path' not in kwargs:
raise KeyError(u'Missing keyword argument "path".')
if u'biblename' not in kwargs:
if u'name' not in kwargs:
raise KeyError(u'Missing keyword argument "name".')
if u'config' not in kwargs:
raise KeyError(u'Missing keyword argument "config".')
# Connect to database
self.stop_import = False
self.name = kwargs[u'name']
self.config = kwargs[u'config']
self.db_file = os.path.join(kwargs[u'path'],
u'%s.sqlite' % kwargs[u'biblename'])
log.debug(u'Load bible %s on path %s', biblename, self.biblefile)
u'%s.sqlite' % kwargs[u'name'])
log.debug(u'Load bible %s on path %s', kwargs[u'name'], self.db_file)
db_type = self.config.get_config(u'db type', u'sqlite')
db_url = u''
if db_type == u'sqlite':
db_url = u'sqlite:///' + self.biblefile
db_url = u'sqlite:///' + self.db_file
else:
db_url = u'%s://%s:%s@%s/%s' % \
(db_type, self.config.get_config(u'db username'),
@ -65,134 +85,200 @@ class BibleDB(BibleCommon):
self.metadata, self.session = init_models(db_url)
self.metadata.create_all(checkfirst=True)
def register(self):
"""
This method basically just initialialises the database. It is called
from the Bible Manager when a Bible is imported. Descendant classes
may want to override this method to supply their own custom
initialisation as well.
"""
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'openlpstopimport'), self.stop_import)
self.create_tables()
return self.name
def stop_import(self):
"""
Stops the import of the Bible.
"""
log.debug('Stopping import!')
self.stop_import = True
def commit(self):
log.debug('Committing...')
self.session.commit()
def create_tables(self):
log.debug(u'createTables')
self.save_meta(u'dbversion', u'2')
self._load_testament(u'Old Testament')
self._load_testament(u'New Testament')
self._load_testament(u'Apocrypha')
self.create_testament(u'Old Testament')
self.create_testament(u'New Testament')
self.create_testament(u'Apocrypha')
def add_verse(self, bookid, chap, vse, text):
verse = Verse()
verse.book_id = bookid
verse.chapter = chap
verse.verse = vse
verse.text = text
def create_testament(self, testament):
log.debug(u'%s: %s', __name__, testament)
self.session.add(Testament.populate(name=testament))
self.commit()
def create_book(self, name, abbrev, testament=1):
log.debug(u'create_book %s,%s', bookname, bookabbrev)
book = Book.populate(name=name, abbreviation=abbrev,
testament_id=testament)
self.session.add(book)
self.commit()
return book
def create_chapter(self, book_id, chapter, textlist):
log.debug(u'create_chapter %s,%s', bookid, chap)
#text list has book and chapter as first two elements of the array
for verse_number, verse_text in textlist.iteritems():
verse = Verse.populate(
book_id = book_id,
chapter = chap,
verse = verse_number,
text = verse_text
)
self.session.add(verse)
self.commit()
def create_verse(self, book_id, chapter, verse, text):
verse = Verse.populate(
book_id=book_id,
chapter=chapter,
verse=verse,
text=text
)
self.session.add(verse)
return verse
def save_verses(self):
log.debug('Saving verses...')
self.session.commit()
def create_chapter(self, bookid, chap, textlist):
log.debug(u'create_chapter %s,%s', bookid, chap)
#text list has book and chapter as first to elements of the array
for verse_number, verse_text in textlist.iteritems():
verse = Verse()
verse.book_id = bookid
verse.chapter = chap
verse.verse = verse_number
verse.text = verse_text
self.session.add(verse)
self.session.commit()
def create_book(self, bookname, bookabbrev, testament=1):
log.debug(u'create_book %s,%s', bookname, bookabbrev)
book = Book()
book.testament_id = testament
book.name = bookname
book.abbreviation = bookabbrev
self.session.add(book)
self.session.commit()
return book
def save_meta(self, key, value):
def create_meta(self, key, value):
log.debug(u'save_meta %s/%s', key, value)
bmeta = BibleMeta()
bmeta.key = key
bmeta.value = value
self.session.add(bmeta)
self.session.commit()
self.session.add(BibleMeta.populate(key=key, value=value))
self.commit()
def get_meta(self, metakey):
log.debug(u'get meta %s', metakey)
return self.session.query(BibleMeta).filter_by(key=metakey).first()
def get_books(self):
log.debug(__name__)
return self.session.query(Book).order_by(Book.id).all()
def get_book(self, book):
log.debug(u'%s: %s', __name__, book)
db_book = self.session.query(Book)\
.filter_by(Book.name.like(book + u'%'))\
.first()
if db_book is None:
db_book = self.session.query(Book)\
.filter(Book.abbreviation.like(book + u'%'))\
.first()
return db_book
def get_chapter(self, id, chapter):
log.debug(u'%s: %s, %s', __name__, id, chapter)
return self.session.query(Verse)\
.filter_by(chapter=chapter)\
.filter_by(book_id=id)\
.first()
def get_verses(self, reference_list):
"""
This is probably the most used function. It retrieves the list of
verses based on the user's query.
``reference_list``
This is the list of references the media manager item wants. It is
a list of tuples, with the following format::
(book, chapter, start_verse, end_verse)
Therefore, when you are looking for multiple items, simply break
them up into references like this, bundle them into a list. This
function then runs through the list, and returns an amalgamated
list of ``Verse`` objects. For example::
[(u'Genesis', 1, 1, 1), (u'Genesis', 2, 2, 3)]
"""
log.debug(u'%s: %s', __name__, reference_list)
verse_list = []
for book, chapter, start_verse, end_verse in reference_list:
db_book = self.get_book(book)
if end_verse == -1:
end_verse = self.get_chapter_count(book)
if db_book:
book = book.name
log.debug(u'Book name corrected to "%s"' % book)
verses = self.session.query(Verse)\
.filter_by(book_id=book.id)\
.filter_by(chapter=chapter)\
.filter(Verse.verse >= start_verse)\
.filter(Verse.verse <= end_verse)\
.order_by(Verse.verse)\
.all()
verse_list.extend(verses)
return verse_list
def verse_search(self, text):
"""
Search for verses containing text ``text``.
``text``
The text to search for. If the text contains commas, it will be
split apart and OR'd on the list of values. If the text just
contains spaces, it will split apart and AND'd on the list of
values.
"""
log.debug(u'%s: %s', __name__, text)
verses = self.session.query(Verse)
if text.find(u',') > -1:
or_clause = []
keywords = [u'%%%s%%' % keyword.strip() for keyword in text.split(u',')]
for keyword in keywords:
or_clause.append(Verse.text.like(keyword))
verses = verses.filter(or_(*or_clause))
else:
keywords = [u'%%%s%%' % keyword.strip() for keyword in text.split(u' ')]
for keyword in keywords:
verses = verses.filter(Verse.text.like(keyword))
verses = verses.all()
return verses
def get_chapter_count(self, book):
log.debug(u'%s: %s', __name__, book)
count = self.session.query(Verse.chapter).join(Book)\
.filter(Book.name==book)\
.distinct().count()
#verse = self.session.query(Verse).join(Book).filter(
# Book.name == bookname).order_by(Verse.chapter.desc()).first()
if not count:
return 0
else:
return count
def get_verse_count(self, book, chapter):
log.debug(u'%s: %s, %s', __name__, book, chapter)
count = self.session.query(Verse).join(Book)\
.filter(Book.name==book)\
.filter(Verse.chapter==chapter)\
.count()
#verse = self.session.query(Verse).join(Book).filter(
# Book.name == bookname).filter(
# Verse.chapter == chapter).order_by(Verse.verse.desc()).first()
if not count:
return 0
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.session.commit()
self.commit()
return True
except:
return False
def _load_testament(self, testament):
log.debug(u'load_testaments %s', testament)
test = ONTestament()
test.name = testament
self.session.add(test)
self.session.commit()
def get_bible_books(self):
log.debug(u'get_bible_books')
return self.session.query(Book).order_by(Book.id).all()
def get_max_bible_book_verses(self, bookname, chapter):
log.debug(u'get_max_bible_book_verses %s, %s', bookname, chapter)
verse = self.session.query(Verse).join(Book).filter(
Book.name == bookname).filter(
Verse.chapter == chapter).order_by(Verse.verse.desc()).first()
if verse == None:
return 0
else:
return verse.verse
def get_max_bible_book_chapter(self, bookname):
log.debug(u'get_max_bible_book_chapter %s', bookname)
verse = self.session.query(Verse).join(Book).filter(
Book.name == bookname).order_by(Verse.chapter.desc()).first()
if verse == None:
return 0
else:
return verse.chapter
def get_bible_book(self, bookname):
log.debug(u'get_bible_book %s', bookname)
book = self.session.query(Book).filter(
Book.name.like(bookname + u'%')).first()
if book is None:
book = self.session.query(Book).filter(
Book.abbreviation.like(bookname + u'%')).first()
return book
def get_bible_chapter(self, id, chapter):
log.debug(u'get_bible_chapter %s, %s', id, chapter)
return self.session.query(Verse).filter_by(chapter=chapter).filter_by(
book_id=id).first()
def get_bible_text(self, bookname, chapter, sverse, everse):
log.debug(u'get_bible_text %s, %s, %s, %s', bookname, chapter, sverse,
everse)
#Look up book name or abbreviation
book = self.get_bible_book(bookname)
if book:
bookname = book.name
log.debug(u'bookname corrected to %s' % bookname)
verses = self.session.query(Verse).join(Book).filter(
Book.name == bookname).filter(Verse.chapter == chapter).filter(
Verse.verse>=sverse).filter(Verse.verse<=everse).order_by(
Verse.verse).all()
return verses
def get_verses_from_text(self, versetext):
log.debug(u'get_verses_from_text %s',versetext)
versetext = u'%%%s%%' % versetext
verses = self.session.query(Verse).filter(
Verse.text.like(versetext)).all()
return verses
def dump_bible(self):
log.debug( u'.........Dumping Bible Database')
log.debug( '...............................Books ')
@ -201,3 +287,4 @@ class BibleDB(BibleCommon):
log.debug( u'...............................Verses ')
verses = self.session.query(Verse).all()
log.debug(verses)

View File

@ -26,17 +26,18 @@
import logging
from common import BibleCommon, SearchResults
from db import BibleDB
class BGExtract(BibleCommon):
global log
log = logging.getLogger(u'BibleHTTPMgr(BG_extract)')
log.info(u'BG_extract loaded')
def __init__(self, proxyurl= None):
def __init__(self, proxyurl=None):
log.debug(u'init %s', proxyurl)
self.proxyurl = proxyurl
def get_bible_chapter(self, version, bookname, chapter) :
def get_chapter(self, version, bookname, chapter) :
"""
Access and decode bibles via the BibleGateway website
@ -49,12 +50,10 @@ class BGExtract(BibleCommon):
``chapter``
Chapter number
"""
log.debug(u'get_bible_chapter %s,%s,%s',
version, bookname, chapter)
urlstring = \
u'http://www.biblegateway.com/passage/?search=%s+%d&version=%s' % \
(bookname, chapter, version)
log.debug(u'BibleGateway urm = %s' % urlstring)
log.debug(u'get_bible_chapter %s, %s, %s', version, bookname, chapter)
urlstring = u'http://www.biblegateway.com/passage/?search=%s+%d' \
u'&version=%s' % (bookname, chapter, version)
log.debug(u'BibleGateway url = %s' % urlstring)
xml_string = self._get_web_text(urlstring, self.proxyurl)
verseSearch = u'<sup class=\"versenum'
verseFootnote = u'<sup class=\'footnote'
@ -171,11 +170,12 @@ class CWExtract(BibleCommon):
bible[verse] = self._clean_text(verseText)
return SearchResults(book_title, book_chapter, bible)
class HTTPBible(object):
class HTTPBible(BibleDB):
global log
log = logging.getLogger(u'BibleHTTPMgr')
log.info(u'BibleHTTP manager loaded')
def __init__(self):
def __init__(self, **kwargs):
"""
Finds all the bibles defined for the system
Creates an Interface Object for each bible containing connection
@ -185,44 +185,51 @@ class HTTPBible(object):
Init confirms the bible exists and stores the database path.
"""
self.biblesource = u''
self.proxyurl = None
self.bibleid = None
if u'download_source' not in kwargs:
raise KeyError(u'Missing keyword argument "download_source"')
if u'download_name' not in kwargs:
raise KeyError(u'Missing keyword argument "download_name"')
self.download_source = kwargs[u'download_source']
self.download_name = kwargs[u'download_name']
if u'proxy_server' in kwargs:
self.proxy_server = kwargs[u'proxy_server']
else:
self.proxy_server = None
if u'proxy_username' in kwargs:
self.proxy_username = kwargs[u'proxy_username']
else:
self.proxy_username = None
if u'proxy_password' in kwargs:
self.proxy_password = kwargs[u'proxy_password']
else:
self.proxy_password = None
def set_proxy(self, proxyurl):
"""
Set the Proxy Url
"""
log.debug(u'set_proxy %s', proxyurl)
self.proxyurl = proxyurl
def register(self):
name = BibleDB.register(self)
self.create_meta(u'download source', self.download_source)
self.create_meta(u'download name', self.download_name)
if self.proxy_server:
self.create_meta(u'proxy server', self.proxy_server)
if self.proxy_username:
# store the proxy userid
self.create_meta(u'proxy username', self.proxy_username)
if self.proxy_password:
# store the proxy password
self.create_meta(u'proxy password', self.proxy_password)
return name
def set_bibleid(self, bibleid):
"""
Set the bible id.
The shore identifier of the the bible.
"""
log.debug(u'set_bibleid %s', bibleid)
self.bibleid = bibleid
def set_bible_source(self, biblesource):
"""
Set the source of where the bible text is coming from
"""
log.debug(u'set_bible_source %s', biblesource)
self.biblesource = biblesource
def get_bible_chapter(self, version, bookname, chapter):
def get_bible_chapter(self, version, book, chapter):
"""
Receive the request and call the relevant handler methods
"""
log.debug(u'get_bible_chapter %s,%s,%s',
version, bookname, chapter)
version, book, chapter)
log.debug(u'biblesource = %s', self.biblesource)
try:
if self.biblesource.lower() == u'crosswalk':
ev = CWExtract(self.proxyurl)
else:
ev = BGExtract(self.proxyurl)
return ev.get_bible_chapter(self.bibleid, bookname, chapter)
return ev.get_bible_chapter(self.bibleid, book, chapter)
except:
log.exception("Failed to get bible chapter")

View File

@ -26,11 +26,12 @@
import logging
import os
from common import parse_reference
from opensong import OpenSongBible
from osis import OSISBible
from csv import CSVBible
from bibleDBimpl import BibleDBImpl
from bibleHTTPimpl import BibleHTTPImpl
from db import BibleDB
from http import HTTPBible
class BibleMode(object):
"""
@ -90,9 +91,9 @@ class BibleManager(object):
def __init__(self, config):
"""
Finds all the bibles defined for the system and creates an
interface object for each bible containing connection
information. Throws Exception if no Bibles are found.
Finds all the bibles defined for the system and creates an interface
object for each bible containing connection information. Throws
Exception if no Bibles are found.
Init confirms the bible exists and stores the database path.
@ -103,23 +104,23 @@ class BibleManager(object):
log.debug(u'Bible Initialising')
self.web = u'Web'
# dict of bible database objects
self.bible_db_cache = None
self.db_cache = None
# dict of bible http readers
self.bible_http_cache = None
self.bible_path = self.config.get_data_path()
self.http_cache = None
self.path = self.config.get_data_path()
#get proxy name for screen
self.proxy_name = self.config.get_config(u'proxy name')
self.bible_suffix = u'sqlite'
self.suffix = u'sqlite'
self.import_wizard = None
self.reload_bibles()
self.media = None
def reload_bibles(self):
log.debug(u'Reload bibles')
files = self.config.get_files(self.bibleSuffix)
files = self.config.get_files(self.suffix)
log.debug(u'Bible Files %s', files)
self.bible_db_cache = {}
self.bible_http_cache = {}
self.db_cache = {}
self.http_cache = {}
# books of the bible with testaments
self.book_testaments = {}
# books of the bible with chapter count
@ -127,38 +128,32 @@ class BibleManager(object):
# books of the bible with abbreviation
self.book_abbreviations = {}
self.web_bibles_present = False
for f in files:
nme = f.split(u'.')
bname = nme[0]
self.bible_db_cache[bname] = BibleDBImpl(self.bible_path,
bname, self.config)
for filename in files:
name, extension = os.path.splitext(filename)
self.db_cache[name] = BibleDB(path=self.path, name=name, config=self.config)
# look to see if lazy load bible exists and get create getter.
biblesource = self.bible_db_cache[bname].get_meta(u'WEB')
if biblesource:
source = self.db_cache[name].get_meta(u'web')
if source:
self.web_bibles_present = True
nhttp = BibleHTTPImpl()
web_bible = HTTPBible()
# tell The Server where to get the verses from.
nhttp.set_bible_source(biblesource.value)
self.bible_http_cache [bname] = nhttp
web_bible.set_source(source.value)
self.http_cache[name] = web_bible
# look to see if lazy load bible exists and get create getter.
meta = self.bible_db_cache[bname].get_meta(u'proxy')
proxy = None
if meta:
proxy = meta.value
meta_proxy = self.db_cache[name].get_meta(u'proxy url')
proxy_url = None
if meta_proxy:
proxy_url = meta_proxy.value
# tell The Server where to get the verses from.
nhttp.set_proxy(proxy)
web_bible.set_proxy_url(proxy_url)
# look to see if lazy load bible exists and get create getter.
bibleid = self.bible_db_cache[bname].get_meta(u'bibleid').value
bible_id = self.db_cache[name].get_meta(u'bible id').value
# tell The Server where to get the verses from.
nhttp.set_bibleid(bibleid)
else:
# makes the Full / partial code easier.
self.bible_http_cache [bname] = None
web_bible.set_bible_id(bible_id)
#else:
# # makes the Full / partial code easier.
# self.http_cache[name] = None
if self.web_bibles_present:
# books of the bible linked to bibleid {osis, name}
self.book_testaments = {}
# books of the bible linked to bibleid {osis, abbrev}
self.book_abbreviations = {}
filepath = os.path.split(os.path.abspath(__file__))[0]
filepath = os.path.abspath(os.path.join(
filepath, u'..', u'resources', u'httpbooks.csv'))
@ -191,13 +186,18 @@ class BibleManager(object):
Register a bible in the bible cache, and then import the verses.
``type``
What type of Bible,
What type of Bible, one of the BibleFormat values.
``**kwargs``
Keyword arguments to send to the actualy importer class.
"""
impl_class = BibleFormat.get_handler(type)
bible_impl = impl_class(**kwargs)
bible_name = bible_impl.register()
BibleDBImpl(self.biblePath, bible_name, self.config)
bible_impl.do_import()
class_ = BibleFormat.get_class(type)
kwargs[u'path'] = self.path
kwargs[u'config'] = self.config
importer = class_(**kwargs)
name = importer.register()
self.db_cache[name] = importer
return importer.do_import()
def register_http_bible(self, biblename, biblesource, bibleid,
proxyurl=None, proxyid=None, proxypass=None):
@ -236,9 +236,9 @@ class BibleManager(object):
nhttp.set_bible_source(biblesource)
self.bible_http_cache[biblename] = nhttp
# register a lazy loading interest
nbible.save_meta(u'WEB', biblesource)
nbible.create_meta(u'WEB', biblesource)
# store the web id of the bible
nbible.save_meta(u'bibleid', bibleid)
nbible.create_meta(u'bibleid', bibleid)
if proxyurl:
# store the proxy URL
nbible.save_meta(u'proxy', proxyurl)
@ -326,14 +326,14 @@ class BibleManager(object):
def get_bibles(self, mode=BibleMode.Full):
"""
Returns a list of Books of the bible. When ``mode`` is set to
``BibleMode.Full`` this method returns all the Bibles for the
Advanced Search, and when the mode is ``BibleMode.Partial``
this method returns all the bibles for the Quick Search.
``BibleMode.Full`` this method returns all the Bibles for the Advanced
Search, and when the mode is ``BibleMode.Partial`` this method returns
all the bibles for the Quick Search.
"""
log.debug(u'get_bibles')
bible_list = []
for bible_name, bible_object in self.bible_db_cache.iteritems():
if self.bible_http_cache[bible_name]:
for bible_name, bible_object in self.db_cache.iteritems():
if bible_name in self.http_cache and self.http_cache[bible_name]:
bible_name = u'%s (%s)' % (bible_name, self.web)
bible_list.append(bible_name)
return bible_list
@ -378,14 +378,15 @@ class BibleManager(object):
return self.bible_db_cache[bible].get_max_bible_book_verses(
book, chapter)
def get_verse_from_text(self, bible, versetext):
def get_verses(self, bible, versetext):
"""
Returns all the number of verses for a given
book and chapterMaxBibleBookVerses
"""
log.debug(u'get_verses_from_text %s,%s', bible, versetext)
reflist = parse_reference(versetext)
web, bible = self.is_bible_web(bible)
return self.bible_db_cache[bible].get_verses_from_text(versetext)
return self.bible_db_cache[bible].get_verses(reflist)
def save_meta_data(self, bible, version, copyright, permissions):
"""
@ -505,12 +506,12 @@ class BibleManager(object):
text.extend(txt)
return text
def _is_new_bible(self, name):
def exists(self, name):
"""
Check cache to see if new bible
"""
for bible, o in self.bible_db_cache.iteritems():
for bible, db_object in self.db_cache.iteritems():
log.debug(u'Bible from cache in is_new_bible %s', bible)
if bible == name:
return False
return True
return True
return False

View File

@ -32,12 +32,17 @@ from openlp.core.lib import MediaManagerItem, Receiver, str_to_bool, \
BaseListWithDnD
from openlp.plugins.bibles.forms import ImportWizardForm
from openlp.plugins.bibles.lib.manager import BibleMode
from openlp.plugins.bibles.lib.common import parse_reference
class BibleListView(BaseListWithDnD):
"""
Drag and drop capable list for Bibles.
"""
def __init__(self, parent=None):
self.PluginName = u'Bibles'
BaseListWithDnD.__init__(self, parent)
class BibleMediaItem(MediaManagerItem):
"""
This is the custom media manager item for Bibles.
@ -380,8 +385,8 @@ class BibleMediaItem(MediaManagerItem):
if self.ClearQuickSearchComboBox.currentIndex() == 0:
self.ListView.clear()
if self.QuickSearchComboBox.currentIndex() == 1:
self.search_results = self.parent.biblemanager.get_verse_from_text(
bible, text)
self.search_results = \
self.parent.biblemanager.get_verses(bible, text)
else:
self.searchByReference(bible, text)
if self.search_results:

View File

@ -50,7 +50,7 @@ class BibleMeta(BaseModel):
pass
class ONTestament(BaseModel):
class Testament(BaseModel):
"""
Bible Testaments
"""
@ -101,7 +101,7 @@ verse_table = Table(u'verse', metadata,
Column(u'text', types.UnicodeText, index=True),
)
mapper(BibleMeta, meta_table)
mapper(ONTestament, testament_table,
mapper(Testament, testament_table,
properties={'books': relation(Book, backref='testament')})
mapper(Book, book_table,
properties={'verses': relation(Verse, backref='book')})

View File

@ -33,54 +33,34 @@ from lxml import objectify
from PyQt4 import QtCore
from openlp.core.lib import Receiver
from db import BibleDB
class OpenSongBible(object):
log = logging.getLogger(__name__)
class OpenSongBible(BibleDB):
"""
OSIS Bible format importer class.
OpenSong Bible format importer class.
"""
global log
log = logging.getLogger(__name__)
log.info(u'BibleOpenSongImpl loaded')
def __init__(self, biblepath, bibledb):
def __init__(self, **kwargs):
"""
Constructor to create and set up an instance of the
BibleOpenSongImpl class.
``biblepath``
This does not seem to be used.
``bibledb``
A reference to a Bible database object.
Constructor to create and set up an instance of the OpenSongBible
class. This class is used to import Bibles from OpenSong's XML format.
"""
log.info(u'BibleOpenSongImpl Initialising')
self.bibledb = bibledb
self.loadbible = True
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'openlpstopimport'), self.stop_import)
log.debug(__name__)
BibleDB.__init__(self, **kwargs)
if u'filename' not in kwargs:
raise KeyError(u'You have to supply a file name to import from.')
self.filename = kwargs[u'filename']
def stop_import(self):
"""
Stops the import of the Bible.
"""
self.loadbible = False
def load_data(self, bible_file, dialogobject=None):
def do_import(self):
"""
Loads a Bible from file.
``bible_file``
The file to import from.
``dialogobject``
The Import dialog, so that we can increase the counter on
the progress bar.
"""
log.info(u'Load data for %s' % bible_file)
bible_file = unicode(bible_file)
log.debug(u'Starting OpenSong import from "%s"' % self.filename)
detect_file = None
try:
detect_file = open(bible_file, u'r')
detect_file = open(self.filename, u'r')
details = chardet.detect(detect_file.read(3000))
except:
log.exception(u'Failed to detect OpenSong file encoding')
@ -88,39 +68,37 @@ class OpenSongBible(object):
finally:
if detect_file:
detect_file.close()
opensong_bible = None
file = None
success = True
try:
opensong_bible = codecs.open(bible_file, u'r', details['encoding'])
opensong = objectify.parse(opensong_bible)
file = codecs.open(self.filename, u'r', details['encoding'])
opensong = objectify.parse(file)
bible = opensong.getroot()
for book in bible.b:
if not self.loadbible:
if self.stop_import:
break
dbbook = self.bibledb.create_book(book.attrib[u'n'],
book.attrib[u'n'][:4])
db_book = self.create_book(book.attrib[u'n'],
book.attrib[u'n'][:4])
for chapter in book.c:
if not self.loadbible:
if self.stop_import:
break
for verse in chapter.v:
if not self.loadbible:
if self.stop_import:
break
self.bibledb.add_verse(dbbook.id, chapter.attrib[u'n'],
self.add_verse(db_book.id, chapter.attrib[u'n'],
verse.attrib[u'n'], verse.text)
Receiver.send_message(u'process_events')
dialogobject.incrementProgressBar(u'Importing %s %s' % \
self.wizard.incrementProgressBar(u'Importing %s %s' % \
(dbbook.name, str(chapter.attrib[u'n'])))
self.bibledb.save_verses()
self.commit()
except:
log.exception(u'Loading bible from OpenSong file failed')
success = False
finally:
if opensong_bible:
opensong_bible.close()
if not self.loadbible:
dialogobject.incrementProgressBar(u'Import canceled!')
dialogobject.ImportProgressBar.setValue(
dialogobject.ImportProgressBar.maximum())
if file:
file.close()
if self.stop_import:
self.wizard.incrementProgressBar(u'Import canceled!')
return False
else:
return success

View File

@ -33,8 +33,9 @@ import re
from PyQt4 import QtCore
from openlp.core.lib import Receiver
from db import BibleDB
class OSISBible(object):
class OSISBible(BibleDB):
"""
OSIS Bible format importer class.
"""
@ -42,18 +43,16 @@ class OSISBible(object):
log = logging.getLogger(u'BibleOSISImpl')
log.info(u'BibleOSISImpl loaded')
def __init__(self, biblepath, bibledb):
def __init__(self, **kwargs):
"""
Constructor to create and set up an instance of the
BibleOSISImpl class.
``biblepath``
This does not seem to be used.
``bibledb``
A reference to a Bible database object.
Constructor to create and set up an instance of the OpenSongBible
class. This class is used to import Bibles from OpenSong's XML format.
"""
log.info(u'BibleOSISImpl Initialising')
log.debug(__name__)
BibleDB.__init__(self, **kwargs)
if u'filename' not in kwargs:
raise KeyError(u'You have to supply a file name to import from.')
self.filename = kwargs[u'filename']
self.verse_regex = re.compile(
r'<verse osisID="([a-zA-Z0-9 ]*).([0-9]*).([0-9]*)">(.*?)</verse>')
self.note_regex = re.compile(r'<note(.*?)>(.*?)</note>')
@ -66,13 +65,11 @@ class OSISBible(object):
self.w_regex = re.compile(r'<w (.*?)>')
self.q_regex = re.compile(r'<q (.*?)>')
self.spaces_regex = re.compile(r'([ ]{2,})')
self.bibledb = bibledb
self.books = {}
filepath = os.path.split(os.path.abspath(__file__))[0]
filepath = os.path.abspath(os.path.join(
filepath, u'..', u'resources', u'osisbooks.csv'))
fbibles = None
self.loadbible = True
try:
fbibles = open(filepath, u'r')
for line in fbibles:
@ -84,31 +81,15 @@ class OSISBible(object):
finally:
if fbibles:
fbibles.close()
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'openlpstopimport'), self.stop_import)
def stop_import(self):
"""
Stops the import of the Bible.
"""
log.debug('Stopping import!')
self.loadbible = False
def load_data(self, osisfile_record, dialogobject=None):
def do_import(self):
"""
Loads a Bible from file.
``osisfile_record``
The file to import from.
``dialogobject``
The Import dialog, so that we can increase the counter on
the progress bar.
"""
log.info(u'Load data for %s' % osisfile_record)
log.debug(u'Starting OSIS import from "%s"' % self.filename)
detect_file = None
try:
detect_file = open(osisfile_record, u'r')
detect_file = open(self.filename, u'r')
details = chardet.detect(detect_file.read(3000))
except:
log.exception(u'Failed to detect OSIS file encoding')
@ -119,12 +100,12 @@ class OSISBible(object):
osis = None
success = True
try:
osis = codecs.open(osisfile_record, u'r', details['encoding'])
osis = codecs.open(self.filename, u'r', details['encoding'])
last_chapter = 0
testament = 1
db_book = None
for file_record in osis:
if not self.loadbible:
if self.stop_import:
break
match = self.verse_regex.search(file_record)
if match:
@ -142,13 +123,13 @@ class OSISBible(object):
testament)
if last_chapter == 0:
if book == u'Gen':
dialogobject.ImportProgressBar.setMaximum(1188)
self.wizard.ImportProgressBar.setMaximum(1188)
else:
dialogobject.ImportProgressBar.setMaximum(260)
self.wizard.ImportProgressBar.setMaximum(260)
if last_chapter != chapter:
if last_chapter != 0:
self.bibledb.save_verses()
dialogobject.incrementProgressBar(
self.wizard.incrementProgressBar(
u'Importing %s %s...' % \
(self.books[match.group(1)][0], chapter))
last_chapter = chapter
@ -170,20 +151,18 @@ class OSISBible(object):
.replace(u'</lg>', u'').replace(u'</q>', u'')\
.replace(u'</div>', u'')
verse_text = self.spaces_regex.sub(u' ', verse_text)
self.bibledb.add_verse(db_book.id, chapter, verse, verse_text)
self.add_verse(db_book.id, chapter, verse, verse_text)
Receiver.send_message(u'process_events')
self.bibledb.save_verses()
dialogobject.incrementProgressBar(u'Finishing import...')
self.commit()
self.wizard.incrementProgressBar(u'Finishing import...')
except:
log.exception(u'Loading bible from OSIS file failed')
success = False
finally:
if osis:
osis.close()
if not self.loadbible:
dialogobject.incrementProgressBar(u'Import canceled!')
dialogobject.ImportProgressBar.setValue(
dialogobject.ImportProgressBar.maximum())
if self.stop_import:
self.wizard.incrementProgressBar(u'Import canceled!')
return False
else:
return success