openlp-core team mailing list archive
-
openlp-core team
-
Mailing list archive
-
Message #02821
[Merge] lp:~meths/openlp/testing into lp:openlp
Jon Tibble has proposed merging lp:~meths/openlp/testing into lp:openlp.
Requested reviews:
Tim Bentley (trb143)
Raoul Snyman (raoul-snyman)
Refactor bible reference code:
* Allow more formats
* Reject previously allowed incorrect formats
* Give users feedback from incorrect bible reference entry instead of being silent
Remove unused code
--
https://code.launchpad.net/~meths/openlp/testing/+merge/31368
Your team OpenLP Core is subscribed to branch lp:openlp.
=== modified file 'openlp/plugins/bibles/lib/__init__.py'
--- openlp/plugins/bibles/lib/__init__.py 2010-07-27 09:32:52 +0000
+++ openlp/plugins/bibles/lib/__init__.py 2010-07-30 12:08:25 +0000
@@ -23,8 +23,163 @@
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
-
-from common import BibleCommon
+"""
+The :mod:`lib` module contains all the library functionality for the bibles
+plugin.
+"""
+import logging
+import re
+
+log = logging.getLogger(__name__)
+
+BIBLE_REFERENCE = re.compile(
+ r'^([\w ]+?) *([0-9]+)' # Initial book and chapter
+ r'(?: *[:|v|V] *([0-9]+))?' # Verse for first chapter
+ r'(?: *- *([0-9]+|end$))?' # Range for verses or chapters
+ r'(?:(?:,([0-9]+))?' # Second chapter
+ r' *[,|:|v|V] *([0-9]+|end$)' # More range for verses or chapters
+ r'(?: *- *([0-9]+|end$))?)?$', # End of second verse range
+ re.UNICODE)
+
+def check_end(match_group):
+ """
+ Check if a regular expression match group contains the text u'end' or
+ should be converted to an int.
+
+ ``match_group``
+ The match group to check.
+ """
+ if match_group == u'end':
+ return -1
+ else:
+ return int(match_group)
+
+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.
+
+ BIBLE_REFERENCE regular expression produces the following match groups:
+ 0 This is a special group consisting of the whole string that matched.
+ 1 [\w ]+ The book the reference is from.
+ 2 [0-9]+ The first (or only) chapter in the reference.
+ 3 None|[0-9]+ None or the only verse or the first verse in a
+ verse range or the start verse in a chapter range.
+ 4 None|[0-9]+|end None or the end verse of the first verse range or
+ the end chapter of a chapter range.
+ 5 None|[0-9]+ None or the second chapter in multiple
+ (non-ranged) chapters.
+ 6 None|[0-9]+|end None, the start of the second verse range or the
+ end of a chapter range.
+ 7 None|[0-9]+|end None or the end of the second verse range.
+
+ The reference list is a list of tuples, with each tuple structured like
+ this::
+ (book, chapter, start_verse, end_verse)
+
+ ``reference``
+ The bible reference to parse.
+
+ Returns None or a reference list.
+ """
+ reference = reference.strip()
+ log.debug('parse_reference("%s")', reference)
+ unified_ref_list = []
+ match = BIBLE_REFERENCE.match(reference)
+ if match:
+ log.debug(u'Matched reference %s' % reference)
+ book = match.group(1)
+ chapter = int(match.group(2))
+ if match.group(7):
+ # Two verse ranges
+ vr1_start = int(match.group(3))
+ vr1_end = int(match.group(4))
+ unified_ref_list.append((book, chapter, vr1_start, vr1_end))
+ vr2_start = int(match.group(6))
+ vr2_end = check_end(match.group(7))
+ if match.group(5):
+ # One verse range per chapter
+ chapter2 = int(match.group(5))
+ unified_ref_list.append((book, chapter2, vr2_start, vr2_end))
+ else:
+ unified_ref_list.append((book, chapter, vr2_start, vr2_end))
+ elif match.group(6):
+ # Chapter range with verses
+ if match.group(3):
+ vr1_start = int(match.group(3))
+ else:
+ vr1_start = 1
+ if match.group(2) == match.group(4):
+ vr1_end = int(match.group(6))
+ unified_ref_list.append((book, chapter, vr1_start, vr1_end))
+ else:
+ vr1_end = -1
+ unified_ref_list.append((book, chapter, vr1_start, vr1_end))
+ vr2_end = check_end(match.group(6))
+ if int(match.group(4)) > chapter:
+ for x in range(chapter + 1, int(match.group(4)) + 1):
+ if x == int(match.group(4)):
+ unified_ref_list.append((book, x, 1, vr2_end))
+ else:
+ unified_ref_list.append((book, x, 1, -1))
+ elif match.group(4):
+ # Chapter range or chapter and verse range
+ if match.group(3):
+ vr1_start = int(match.group(3))
+ vr1_end = check_end(match.group(4))
+ if vr1_end == -1 or vr1_end > vr1_start:
+ unified_ref_list.append((book, chapter, vr1_start, vr1_end))
+ else:
+ log.debug(u'Ambiguous reference: %s' % reference)
+ return None
+ elif match.group(4) != u'end':
+ for x in range(chapter, int(match.group(4)) + 1):
+ unified_ref_list.append((book, x, 1, -1))
+ else:
+ log.debug(u'Unsupported reference: %s' % reference)
+ return None
+ elif match.group(3):
+ # Single chapter and verse
+ verse = int(match.group(3))
+ unified_ref_list.append((book, chapter, verse, verse))
+ else:
+ # Single chapter
+ unified_ref_list.append((book, chapter, -1, -1))
+ else:
+ log.debug(u'Invalid reference: %s' % reference)
+ return None
+ return unified_ref_list
+
+
+class SearchResults(object):
+ """
+ Encapsulate a set of search results. This is Bible-type independant.
+ """
+ def __init__(self, book, chapter, verselist):
+ """
+ Create the search result object.
+
+ ``book``
+ The book of the Bible.
+
+ ``chapter``
+ The chapter of the book.
+
+ ``verselist``
+ The list of verses for this reading
+ """
+ self.book = book
+ self.chapter = chapter
+ self.verselist = verselist
+
+ def has_verselist(self):
+ """
+ Returns whether or not the verse list contains verses.
+ """
+ return len(self.verselist) > 0
+
+
from manager import BibleManager
from biblestab import BiblesTab
from mediaitem import BibleMediaItem
=== removed file 'openlp/plugins/bibles/lib/common.py'
--- openlp/plugins/bibles/lib/common.py 2010-07-26 20:31:05 +0000
+++ openlp/plugins/bibles/lib/common.py 1970-01-01 00:00:00 +0000
@@ -1,256 +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, Meinert Jordan, Andreas Preikschat, Christian #
-# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
-# Carsten Tinggaard, Frode Woldsund #
-# --------------------------------------------------------------------------- #
-# 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 #
-###############################################################################
-
-import urllib2
-import logging
-import re
-import chardet
-import htmlentitydefs
-
-only_verses = re.compile(r'([\w .]+)[ ]+([0-9]+)[ ]*[:|v|V][ ]*([0-9]+)'
- r'(?:[ ]*-[ ]*([0-9]+|end))?(?:[ ]*,[ ]*([0-9]+)'
- r'(?:[ ]*-[ ]*([0-9]+|end))?)?',
- re.UNICODE)
-chapter_range = re.compile(r'([\w .]+)[ ]+([0-9]+)[ ]*[:|v|V][ ]*'
- r'([0-9]+|end)[ ]*-[ ]*([0-9]+)[ ]*[:|v|V][ ]*([0-9]+|end)',
- re.UNICODE)
-
-log = logging.getLogger(__name__)
-
-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()
- log.debug('parse_reference("%s")', reference)
- 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:
- log.debug('Found a chapter range.')
- book = match.group(1)
- from_verse = match.group(3)
- to_verse = match.group(5)
- if int(match.group(2)) == int(match.group(4)):
- reference_list.append(
- (book, int(match.group(2)), from_verse, to_verse)
- )
- else:
- if int(match.group(2)) > int(match.group(4)):
- from_chapter = int(match.group(4))
- to_chapter = int(match.group(2))
- else:
- from_chapter = int(match.group(2))
- to_chapter = int(match.group(4))
- for chapter in xrange(from_chapter, to_chapter + 1):
- if chapter == from_chapter:
- reference_list.append((book, chapter, from_verse, -1))
- elif chapter == to_chapter:
- reference_list.append((book, chapter, 1, to_verse))
- else:
- reference_list.append((book, chapter, 1, -1))
- else:
- match = only_verses.match(reference)
- if match:
- log.debug('Found a verse range.')
- 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)
- ])
- else:
- log.debug('Didn\'t find anything.')
- log.debug(reference_list)
- return reference_list
-
-class SearchResults(object):
- """
- Encapsulate a set of search results. This is Bible-type independant.
- """
- def __init__(self, book, chapter, verselist):
- """
- Create the search result object.
-
- ``book``
- The book of the Bible.
-
- ``chapter``
- The chapter of the book.
-
- ``verselist``
- The list of verses for this reading
- """
- self.book = book
- self.chapter = chapter
- self.verselist = verselist
-
- def has_verselist(self):
- """
- Returns whether or not the verse list contains verses.
- """
- return len(self.verselist) > 0
-
-
-class BibleCommon(object):
- """
- A common ancestor for bible download sites.
- """
- log.info(u'BibleCommon')
-
- def _get_web_text(self, urlstring, proxyurl):
- """
- Get the HTML from the web page.
-
- ``urlstring``
- The URL of the page to open.
-
- ``proxyurl``
- The URL of a proxy server used to access the Internet.
- """
- log.debug(u'get_web_text %s %s', proxyurl, urlstring)
- if proxyurl:
- proxy_support = urllib2.ProxyHandler({'http': self.proxyurl})
- http_support = urllib2.HTTPHandler()
- opener = urllib2.build_opener(proxy_support, http_support)
- urllib2.install_opener(opener)
- xml_string = u''
- req = urllib2.Request(urlstring)
- #Make us look like an IE Browser on XP to stop blocking by web site
- req.add_header(u'User-Agent',
- u'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)')
- try:
- handle = urllib2.urlopen(req)
- html = handle.read()
- details = chardet.detect(html)
- xml_string = unicode(html, details[u'encoding'])
- except IOError, e:
- if hasattr(e, u'reason'):
- log.exception(u'Reason for failure: %s', e.reason)
- return xml_string
-
- def _clean_text(self, text):
- """
- Clean up text and remove extra characters after been downloaded from
- the Internet.
-
- ``text``
- The text from the web page that needs to be cleaned up.
- """
- #return text.rstrip()
- # Remove Headings from the Text
- start_tag = text.find(u'<h')
- while start_tag > -1:
- end_tag = text.find(u'</h', start_tag)
- text = text[:(start_tag - 1)] + text[(end_tag + 4)]
- start_tag = text.find(u'<h')
- # Remove Support References from the Text
- start_tag = text.find(u'<sup>')
- while start_tag > -1:
- end_tag = text.find(u'</sup>')
- text = text[:start_tag] + text[end_tag + 6:len(text)]
- start_tag = text.find(u'<sup>')
- start_tag = text.find(u'<SUP>')
- while start_tag > -1:
- end_tag = text.find(u'</SUP>')
- text = text[:start_tag] + text[end_tag + 6:len(text)]
- start_tag = text.find(u'<SUP>')
- # Static Clean ups
- text = text.replace(u'\n', u'')
- text = text.replace(u'\r', u'')
- text = text.replace(u' ', u'')
- text = text.replace(u'<P>', u'')
- text = text.replace(u'<I>', u'')
- text = text.replace(u'</I>', u'')
- text = text.replace(u'<P />', u'')
- text = text.replace(u'<p />', u'')
- text = text.replace(u'</P>', u'')
- text = text.replace(u'<BR>', u'')
- text = text.replace(u'<BR />', u'')
- text = text.replace(u'"', u'\"')
- text = text.replace(u''', u'\'')
- # Remove some other tags
- start_tag = text.find(u'<')
- while start_tag > -1:
- end_tag = text.find(u'>', start_tag)
- text = text[:start_tag] + text[end_tag + 1:]
- start_tag = text.find(u'<')
- text = text.replace(u'>', u'')
- return text.rstrip().lstrip()
-
-
-def unescape(text):
- """
- Removes HTML or XML character references and entities from a text string.
- Courtesy of Fredrik Lundh, http://effbot.org/zone/re-sub.htm#unescape-html
-
- @param text The HTML (or XML) source text.
- @return The plain text, as a Unicode string, if necessary.
- """
- def fixup(markup):
- text = markup.group(0)
- if text.startswith(u'&#'):
- # character reference
- try:
- if text.startswith(u'&#x'):
- return unichr(int(text[3:-1], 16))
- else:
- return unichr(int(text[2:-1]))
- except ValueError:
- pass
- else:
- # named entity
- try:
- text = unichr(htmlentitydefs.name2codepoint[text[1:-1]])
- except KeyError:
- pass
- return text # leave as is
- return re.sub(u'&#?\w+;', fixup, text)
=== modified file 'openlp/plugins/bibles/lib/http.py'
--- openlp/plugins/bibles/lib/http.py 2010-07-27 15:01:06 +0000
+++ openlp/plugins/bibles/lib/http.py 2010-07-30 12:08:25 +0000
@@ -36,7 +36,7 @@
from openlp.core.lib import Receiver
from openlp.core.utils import AppLocation
-from openlp.plugins.bibles.lib.common import BibleCommon, SearchResults
+from openlp.plugins.bibles.lib import SearchResults
from openlp.plugins.bibles.lib.db import BibleDB, Book
log = logging.getLogger(__name__)
@@ -177,7 +177,7 @@
return 0
-class BGExtract(BibleCommon):
+class BGExtract(object):
"""
Extract verses from BibleGateway
"""
@@ -239,7 +239,8 @@
found_count += 1
return SearchResults(bookname, chapter, verse_list)
-class CWExtract(BibleCommon):
+
+class CWExtract(object):
"""
Extract verses from CrossWalk/BibleStudyTools
"""
=== modified file 'openlp/plugins/bibles/lib/manager.py'
--- openlp/plugins/bibles/lib/manager.py 2010-07-28 13:15:39 +0000
+++ openlp/plugins/bibles/lib/manager.py 2010-07-30 12:08:25 +0000
@@ -26,13 +26,13 @@
import logging
-from PyQt4 import QtCore
+from PyQt4 import QtCore, QtGui
-from openlp.core.lib import SettingsManager
+from openlp.core.lib import SettingsManager, translate
from openlp.core.utils import AppLocation
+from openlp.plugins.bibles.lib import parse_reference
from openlp.plugins.bibles.lib.db import BibleDB, BibleMeta
-from common import parse_reference
from opensong import OpenSongBible
from osis import OSISBible
from csvbible import CSVBible
@@ -229,13 +229,33 @@
``versetext``
Unicode. The scripture reference. Valid scripture references are:
+ - Genesis 1
+ - Genesis 1-2
- Genesis 1:1
- Genesis 1:1-10
+ - Genesis 1:1-10,15-20
- Genesis 1:1-2:10
+ - Genesis 1:1-10,2:1-10
"""
log.debug(u'BibleManager.get_verses("%s", "%s")', bible, versetext)
reflist = parse_reference(versetext)
- return self.db_cache[bible].get_verses(reflist)
+ if reflist:
+ return self.db_cache[bible].get_verses(reflist)
+ else:
+ QtGui.QMessageBox.information(self.parent.mediaItem,
+ translate('BiblesPlugin.BibleManager',
+ 'Scripture Reference Error'),
+ translate('BiblesPlugin.BibleManager', 'Your scripture '
+ 'reference is either not supported by OpenLP or invalid. '
+ 'Please make sure your reference conforms to one of the '
+ 'following patterns:\n\n'
+ 'Book Chapter\n'
+ 'Book Chapter-Chapter\n'
+ 'Book Chapter:Verse-Verse\n'
+ 'Book Chapter:Verse-Verse,Verse-Verse\n'
+ 'Book Chapter:Verse-Verse,Chapter:Verse-Verse\n'
+ 'Book Chapter:Verse-Chapter:Verse\n'))
+ return None
def save_meta_data(self, bible, version, copyright, permissions):
"""
=== modified file 'openlp/plugins/bibles/lib/mediaitem.py'
--- openlp/plugins/bibles/lib/mediaitem.py 2010-07-26 06:06:17 +0000
+++ openlp/plugins/bibles/lib/mediaitem.py 2010-07-30 12:08:25 +0000
@@ -431,8 +431,8 @@
chapter_to = int(self.AdvancedToChapter.currentText())
verse_from = int(self.AdvancedFromVerse.currentText())
verse_to = int(self.AdvancedToVerse.currentText())
- versetext = u'%s %s:%s-%s:%s' % (book, chapter_from, verse_from, \
- chapter_to, verse_to)
+ versetext = u'%s %s:%s-%s:%s' % (book, chapter_from, verse_from,
+ chapter_to, verse_to)
self.search_results = self.parent.manager.get_verses(bible, versetext)
if self.ClearAdvancedSearchComboBox.currentIndex() == 0:
self.listView.clear()
@@ -656,7 +656,3 @@
row = self.listView.setCurrentRow(count)
if row:
row.setSelected(True)
-
- def searchByReference(self, bible, search):
- log.debug(u'searchByReference %s, %s', bible, search)
- self.search_results = self.parent.manager.get_verses(bible, search)
Follow ups