diff --git a/openlp/.version b/openlp/.version index 5e9287b86..1fe2d3795 100644 --- a/openlp/.version +++ b/openlp/.version @@ -1 +1 @@ -1.9.11 +1.9.12 diff --git a/openlp/core/ui/advancedtab.py b/openlp/core/ui/advancedtab.py index 2d6b534c4..0276fcebc 100644 --- a/openlp/core/ui/advancedtab.py +++ b/openlp/core/ui/advancedtab.py @@ -38,7 +38,7 @@ import sys from openlp.core.lib import SettingsTab, translate, build_icon, Receiver from openlp.core.lib.settings import Settings from openlp.core.lib.ui import UiStrings -from openlp.core.utils import get_images_filter, AppLocation +from openlp.core.utils import get_images_filter, AppLocation, format_time from openlp.core.lib import SlideLimits log = logging.getLogger(__name__) @@ -622,7 +622,7 @@ class AdvancedTab(SettingsTab): time = time.replace(hour = self.serviceNameTime.time().hour(), minute = self.serviceNameTime.time().minute()) try: - service_name_example = time.strftime(unicode( + service_name_example = format_time(unicode( self.serviceNameEdit.text())) except ValueError: preset_is_valid = False diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index d49c988c6..0dc4ef864 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -47,7 +47,8 @@ from openlp.core.lib.ui import UiStrings, critical_error_message_box, \ create_widget_action, find_and_set_in_combo_box from openlp.core.ui import ServiceNoteForm, ServiceItemEditForm, StartTimeForm from openlp.core.ui.printserviceform import PrintServiceForm -from openlp.core.utils import AppLocation, delete_file, split_filename +from openlp.core.utils import AppLocation, delete_file, split_filename, \ + format_time from openlp.core.utils.actions import ActionList, CategoryOrder class ServiceManagerList(QtGui.QTreeWidget): @@ -621,7 +622,7 @@ class ServiceManager(QtGui.QWidget): '/\\?*|<>\[\]":+\nSee http://docs.python.org/library/' 'datetime.html#strftime-strptime-behavior for more ' 'information.')).toString()) - default_filename = time.strftime(default_pattern) + default_filename = format_time(default_pattern) else: default_filename = u'' directory = unicode(SettingsManager.get_last_dir( diff --git a/openlp/core/utils/__init__.py b/openlp/core/utils/__init__.py index 224ab4344..393916408 100644 --- a/openlp/core/utils/__init__.py +++ b/openlp/core/utils/__init__.py @@ -35,6 +35,7 @@ import os import re from subprocess import Popen, PIPE import sys +import time import urllib2 from openlp.core.lib.settings import Settings @@ -469,10 +470,24 @@ def get_uno_instance(resolver): return resolver.resolve(u'uno:socket,host=localhost,port=2002;' \ + u'urp;StarOffice.ComponentContext') + +def format_time(text): + """ + Workaround for Python built-in time formatting fuction time.strftime(). + + time.strftime() accepts only ascii characters. This function accepts + unicode string and passes individual % placeholders to time.strftime(). + This ensures only ascii characters are passed to time.strftime(). + """ + def match_formatting(match): + return time.strftime(match.group()) + return re.sub('\%[a-zA-Z]', match_formatting, text) + + from languagemanager import LanguageManager from actions import ActionList __all__ = [u'AppLocation', u'get_application_version', u'check_latest_version', u'add_actions', u'get_filesystem_encoding', u'LanguageManager', u'ActionList', u'get_web_page', u'get_uno_command', u'get_uno_instance', - u'delete_file', u'clean_filename'] + u'delete_file', u'clean_filename', u'format_time'] diff --git a/openlp/plugins/bibles/lib/http.py b/openlp/plugins/bibles/lib/http.py index a223465da..bd08e1a41 100644 --- a/openlp/plugins/bibles/lib/http.py +++ b/openlp/plugins/bibles/lib/http.py @@ -124,6 +124,8 @@ class BGExtract(object): self._remove_elements(tag, 'div', 'footnotes') self._remove_elements(tag, 'div', 'crossrefs') self._remove_elements(tag, 'h3') + self._remove_elements(tag, 'h4') + self._remove_elements(tag, 'h5') def _extract_verses(self, tags): """ @@ -155,12 +157,59 @@ class BGExtract(object): text = text.replace(old, new) text = u' '.join(text.split()) if verse and text: - verses.append((int(verse.strip()), text)) + verse = verse.strip() + try: + verse = int(verse) + except (TypeError, ValueError): + verse_parts = verse.split(u'-') + if len(verse_parts) > 1: + verse = int(verse_parts[0]) + verses.append((verse, text)) verse_list = {} for verse, text in verses[::-1]: verse_list[verse] = text return verse_list + def _extract_verses_old(self, div): + """ + Use the old style of parsing for those Bibles on BG who mysteriously + have not been migrated to the new (still broken) HTML. + + ``div`` + The parent div. + """ + verse_list = {} + # Cater for inconsistent mark up in the first verse of a chapter. + first_verse = div.find(u'versenum') + if first_verse and first_verse.contents: + verse_list[1] = unicode(first_verse.contents[0]) + for verse in div(u'sup', u'versenum'): + raw_verse_num = verse.next + clean_verse_num = 0 + # Not all verses exist in all translations and may or may not be + # represented by a verse number. If they are not fine, if they are + # it will probably be in a format that breaks int(). We will then + # have no idea what garbage may be sucked in to the verse text so + # if we do not get a clean int() then ignore the verse completely. + try: + clean_verse_num = int(str(raw_verse_num)) + except ValueError: + log.warn(u'Illegal verse number: %s', unicode(raw_verse_num)) + if clean_verse_num: + verse_text = raw_verse_num.next + part = raw_verse_num.next.next + while not (isinstance(part, Tag) and + part.get(u'class') == u'versenum'): + # While we are still in the same verse grab all the text. + if isinstance(part, NavigableString): + verse_text += part + if isinstance(part.next, Tag) and part.next.name == u'div': + # Run out of verses so stop. + break + part = part.next + verse_list[clean_verse_num] = unicode(verse_text) + return verse_list + def get_bible_chapter(self, version, book_name, chapter): """ Access and decode Bibles via the BibleGateway website. @@ -189,7 +238,13 @@ class BGExtract(object): Receiver.send_message(u'openlp_process_events') div = soup.find('div', 'result-text-style-normal') self._clean_soup(div) - verse_list = self._extract_verses(div.findAll('span', 'text')) + span_list = div.findAll('span', 'text') + log.debug('Span list: %s', span_list) + if not span_list: + # If we don't get any spans then we must have the old HTML format + verse_list = self._extract_verses_old(div) + else: + verse_list = self._extract_verses(span_list) if not verse_list: log.debug(u'No content found in the BibleGateway response.') send_error_message(u'parse')