def __init__(self, sourceFolder, givenName, encoding='utf-8'): """ Constructor: just sets up the Zefania Bible object. """ # Setup and initialise the base class first Bible.__init__(self) self.objectNameString = "Zefania XML Bible object" self.objectTypeString = "Zefania" # Now we can set our object variables self.sourceFolder, self.givenName, self.encoding = sourceFolder, givenName, encoding self.sourceFilepath = os.path.join(self.sourceFolder, self.givenName) self.tree = self.header = None # Will hold the XML data # Get the data tables that we need for proper checking #self.ISOLanguages = ISO_639_3_Languages().loadData() self.genericBOS = BibleOrganizationalSystem("GENERIC-KJV-66-ENG") # Do a preliminary check on the readability of our file if not os.access(self.sourceFilepath, os.R_OK): print("ZefaniaXMLBible: File '{}' is unreadable".format( self.sourceFilepath)) self.name = self.givenName
def __init__(self, sourceFolder, givenName, encoding='utf-8'): """ Constructor: just sets up the XML Bible file converter object. """ # Setup and initialise the base class first if BibleOrgSysGlobals.debugFlag: print("OpenSongXMLBible( {}, {}, {} )".format( sourceFolder, givenName, encoding)) Bible.__init__(self) self.objectNameString = 'OpenSong XML Bible object' self.objectTypeString = 'OpenSong' # Now we can set our object variables self.sourceFolder, self.givenName, self.encoding = sourceFolder, givenName, encoding self.sourceFilepath = os.path.join(self.sourceFolder, self.givenName) self.tree = None # Will hold the XML data # Get the data tables that we need for proper checking #self.ISOLanguages = ISO_639_3_Languages().loadData() self.genericBOS = BibleOrganizationalSystem('GENERIC-KJV-66-ENG') # Do a preliminary check on the readability of our file if not os.access(self.sourceFilepath, os.R_OK): print("OpenSongXMLBible: File {!r} is unreadable".format( self.sourceFilepath)) self.name = self.givenName
def main(): """ This is the main program for the app which just tries to open and load some kind of Bible file(s) from the inputFolder that you specified and then export a PhotoBible (in the default OutputFiles folder). Note that the standard verbosityLevel is 2: -s (silent) is 0 -q (quiet) is 1 -i (information) is 3 -v (verbose) is 4. """ if BibleOrgSysGlobals.verbosityLevel > 0: print( ProgNameVersion ) ourBibleOrganizationalSystem = BibleOrganizationalSystem( "GENERIC-KJV-66-ENG" ) ourVersificationSystem = ourBibleOrganizationalSystem.getVersificationSystemName() ourBibleSingleReference = BibleSingleReference( ourBibleOrganizationalSystem ) print( _("Use QUIT or EXIT to finish.") ) while True: # Loop until they stop it userInput = input( '\n' + _("Enter a verse number 1..31102 or a single Bible verse reference (or QUIT): ") ) if userInput.lower() in ('exit', 'quit', 'q', 'stop', 'halt',): break # See if it's an absolute verse number try: userInt = int(userInput) except ValueError: userInt = None if userInt: if 1 <= userInt <= 31102: BBB, C, V = ourBibleOrganizationalSystem.convertAbsoluteVerseNumber( userInt ) print( _("{} verse number {} is {} {}:{}").format( ourVersificationSystem, userInt, BBB, C, V ) ) else: print( _("Absolute verse numbers must be in range 1..31,102.") ) else: # assume it's a Bible reference adjustedUserInput = userInput if ':' not in adjustedUserInput: for alternative in ('.', ',', '-',): # Handle possible alternative C:V punctuations if alternative in adjustedUserInput: adjustedUserInput = adjustedUserInput.replace( alternative, ':', 1 ) break results = ourBibleSingleReference.parseReferenceString( adjustedUserInput ) #print( results ) successFlag, haveWarnings, BBB, C, V, S = results if successFlag: print( _("{!r} converted to {} {}:{} in our internal system.").format( userInput, BBB, C, V ) ) absoluteVerseNumber = ourBibleOrganizationalSystem.getAbsoluteVerseNumber( BBB, C, V ) print( _(" {} {}:{} is verse number {:,} in the {} versification system.").format( BBB, C, V, absoluteVerseNumber, ourVersificationSystem ) ) if BibleOrgSysGlobals.debugFlag: print( _(" {} {}:{} is verse number 0x{:04x} in the {} versification system.").format( BBB, C, V, absoluteVerseNumber, ourVersificationSystem ) ) else: print( _("Unable to find a valid single verse reference in your input: {!r}").format( userInput ) )
def __init__(self, sourceFolder, sourceFilename, encoding=None): """ Constructor: just sets up the Bible object. encoding is irrelevant because it's a binary format. """ # Setup and initialise the base class first Bible.__init__(self) self.objectNameString = 'EasyWorship Bible object' self.objectTypeString = 'EWB' # Now we can set our object variables self.sourceFolder, self.sourceFilename, self.encoding = sourceFolder, sourceFilename, encoding self.sourceFilepath = os.path.join(self.sourceFolder, self.sourceFilename) # Do a preliminary check on the readability of our file if not os.access(self.sourceFilepath, os.R_OK): logging.critical( _("EasyWorshipBible: File {!r} is unreadable").format( self.sourceFilepath)) global BOS if BOS is None: BOS = BibleOrganizationalSystem('GENERIC-KJV-66-ENG') self.abbreviation = self.sourceFilename[:-4] # Remove file extension
def __init__( self, sourceFolder, givenName, encoding='utf-8' ): """ Constructor: just sets up the XML Bible file converter object. """ # Setup and initialise the base class first if BibleOrgSysGlobals.debugFlag: print( "OpenSongXMLBible( {}, {}, {} )".format( sourceFolder, givenName, encoding ) ) Bible.__init__( self ) self.objectNameString = "OpenSong XML Bible object" self.objectTypeString = "OpenSong" # Now we can set our object variables self.sourceFolder, self.givenName, self.encoding = sourceFolder, givenName, encoding self.sourceFilepath = os.path.join( self.sourceFolder, self.givenName ) self.tree = None # Will hold the XML data # Get the data tables that we need for proper checking #self.ISOLanguages = ISO_639_3_Languages().loadData() self.genericBOS = BibleOrganizationalSystem( "GENERIC-KJV-66-ENG" ) # Do a preliminary check on the readability of our file if not os.access( self.sourceFilepath, os.R_OK ): print( "OpenSongXMLBible: File {!r} is unreadable".format( self.sourceFilepath ) ) self.name = self.givenName
def preload( self ): """ Load the metadata from the SQLite3 database. """ if BibleOrgSysGlobals.debugFlag and debuggingThisModule: print( exp("preload()") ) if BibleOrgSysGlobals.verbosityLevel > 2: print( _("Preloading {}…").format( self.sourceFilepath ) ) fileExtensionUpper = self.fileExtension.upper() if fileExtensionUpper not in FILENAME_ENDINGS_TO_ACCEPT: logging.critical( "{} doesn't appear to be a MySword file".format( self.sourceFilename ) ) elif not self.sourceFilename.upper().endswith( BIBLE_FILENAME_ENDINGS_TO_ACCEPT[0] ): logging.critical( "{} doesn't appear to be a MySword Bible file".format( self.sourceFilename ) ) connection = sqlite3.connect( self.sourceFilepath ) connection.row_factory = sqlite3.Row # Enable row names self.cursor = connection.cursor() # First get the settings if self.suppliedMetadata is None: self.suppliedMetadata = {} self.suppliedMetadata['MySword'] = {} self.cursor.execute( 'select * from Details' ) row = self.cursor.fetchone() for key in row.keys(): self.suppliedMetadata['MySword'][key] = row[key] #print( self.suppliedMetadata['MySword'] ); halt #if 'Description' in self.settingsDict and len(self.settingsDict['Description'])<40: self.name = self.settingsDict['Description'] #if 'Abbreviation' in self.settingsDict: self.abbreviation = self.settingsDict['Abbreviation'] if 'encryption' in self.suppliedMetadata['MySword']: logging.critical( "{} is encrypted: level {}".format( self.sourceFilename, self.suppliedMetadata['MySword']['encryption'] ) ) self.BOS = BibleOrganizationalSystem( 'GENERIC-KJV-66-ENG' ) self.preloadDone = True
def preload(self): """ Load the metadata from the SQLite3 database. """ if BibleOrgSysGlobals.debugFlag and debuggingThisModule: print(exp("preload()")) if BibleOrgSysGlobals.verbosityLevel > 2: print(_("Preloading {}…").format(self.sourceFilepath)) fileExtensionUpper = self.fileExtension.upper() if fileExtensionUpper not in FILENAME_ENDINGS_TO_ACCEPT: logging.critical("{} doesn't appear to be a MySword file".format( self.sourceFilename)) elif not self.sourceFilename.upper().endswith( BIBLE_FILENAME_ENDINGS_TO_ACCEPT[0]): logging.critical( "{} doesn't appear to be a MySword Bible file".format( self.sourceFilename)) connection = sqlite3.connect(self.sourceFilepath) connection.row_factory = sqlite3.Row # Enable row names self.cursor = connection.cursor() # First get the settings if self.suppliedMetadata is None: self.suppliedMetadata = {} self.suppliedMetadata['MySword'] = {} self.cursor.execute('select * from Details') row = self.cursor.fetchone() for key in row.keys(): self.suppliedMetadata['MySword'][key] = row[key] #print( self.suppliedMetadata['MySword'] ); halt #if 'Description' in self.settingsDict and len(self.settingsDict['Description'])<40: self.name = self.settingsDict['Description'] #if 'Abbreviation' in self.settingsDict: self.abbreviation = self.settingsDict['Abbreviation'] if 'encryption' in self.suppliedMetadata['MySword']: logging.critical("{} is encrypted: level {}".format( self.sourceFilename, self.suppliedMetadata['MySword']['encryption'])) self.BOS = BibleOrganizationalSystem('GENERIC-KJV-66-ENG') self.preloadDone = True
def __init__( self, sourceFolder, givenName, encoding='utf-8' ): """ Constructor: just sets up the Haggai Bible object. """ # Setup and initialise the base class first Bible.__init__( self ) self.objectNameString = 'Haggai XML Bible object' self.objectTypeString = 'Haggai' # Now we can set our object variables self.sourceFolder, self.givenName, self.encoding = sourceFolder, givenName, encoding self.sourceFilepath = os.path.join( self.sourceFolder, self.givenName ) self.XMLTree = self.header = None # Will hold the XML data # Get the data tables that we need for proper checking #self.ISOLanguages = ISO_639_3_Languages().loadData() self.genericBOS = BibleOrganizationalSystem( 'GENERIC-KJV-66-ENG' ) # Do a preliminary check on the readability of our file if not os.access( self.sourceFilepath, os.R_OK ): print( "HaggaiXMLBible: File {!r} is unreadable".format( self.sourceFilepath ) ) self.name = self.givenName
class MySwordBible( Bible ): """ Class for reading, validating, and converting MySwordBible files. """ def __init__( self, sourceFolder, givenFilename, encoding='utf-8' ): """ Constructor: just sets up the Bible object. """ # Setup and initialise the base class first Bible.__init__( self ) self.objectNameString = 'MySword Bible object' self.objectTypeString = 'MySword' # Now we can set our object variables self.sourceFolder, self.sourceFilename, self.encoding = sourceFolder, givenFilename, encoding self.sourceFilepath = os.path.join( self.sourceFolder, self.sourceFilename ) # Do a preliminary check on the readability of our file if not os.access( self.sourceFilepath, os.R_OK ): logging.critical( _("MySwordBible: File {!r} is unreadable").format( self.sourceFilepath ) ) filenameBits = os.path.splitext( self.sourceFilename ) self.name = filenameBits[0] self.fileExtension = filenameBits[1] #if self.fileExtension.upper().endswith('X'): #logging.warning( _("MySwordBible: File {!r} is encrypted").format( self.sourceFilepath ) ) # end of MySwordBible.__init__ def preload( self ): """ Load the metadata from the SQLite3 database. """ if BibleOrgSysGlobals.debugFlag and debuggingThisModule: print( exp("preload()") ) if BibleOrgSysGlobals.verbosityLevel > 2: print( _("Preloading {}…").format( self.sourceFilepath ) ) fileExtensionUpper = self.fileExtension.upper() if fileExtensionUpper not in FILENAME_ENDINGS_TO_ACCEPT: logging.critical( "{} doesn't appear to be a MySword file".format( self.sourceFilename ) ) elif not self.sourceFilename.upper().endswith( BIBLE_FILENAME_ENDINGS_TO_ACCEPT[0] ): logging.critical( "{} doesn't appear to be a MySword Bible file".format( self.sourceFilename ) ) connection = sqlite3.connect( self.sourceFilepath ) connection.row_factory = sqlite3.Row # Enable row names self.cursor = connection.cursor() # First get the settings if self.suppliedMetadata is None: self.suppliedMetadata = {} self.suppliedMetadata['MySword'] = {} self.cursor.execute( 'select * from Details' ) row = self.cursor.fetchone() for key in row.keys(): self.suppliedMetadata['MySword'][key] = row[key] #print( self.suppliedMetadata['MySword'] ); halt #if 'Description' in self.settingsDict and len(self.settingsDict['Description'])<40: self.name = self.settingsDict['Description'] #if 'Abbreviation' in self.settingsDict: self.abbreviation = self.settingsDict['Abbreviation'] if 'encryption' in self.suppliedMetadata['MySword']: logging.critical( "{} is encrypted: level {}".format( self.sourceFilename, self.suppliedMetadata['MySword']['encryption'] ) ) self.BOS = BibleOrganizationalSystem( 'GENERIC-KJV-66-ENG' ) self.preloadDone = True # end of MySwordBible.preload def load( self ): """ Load all the books out of the SQLite3 database. """ if BibleOrgSysGlobals.debugFlag and debuggingThisModule: print( exp("load()") ) assert self.preloadDone if BibleOrgSysGlobals.verbosityLevel > 2: print( _("Loading {}…").format( self.sourceFilepath ) ) if self.suppliedMetadata['MySword']['OT'] and self.suppliedMetadata['MySword']['NT']: testament, BBB = 'BOTH', 'GEN' booksExpected, textLineCountExpected = 66, 31102 elif self.suppliedMetadata['MySword']['OT']: testament, BBB = 'OT', 'GEN' booksExpected, textLineCountExpected = 39, 23145 elif self.suppliedMetadata['MySword']['NT']: testament, BBB = 'NT', 'MAT' booksExpected, textLineCountExpected = 27, 7957 # Create the first book thisBook = BibleBook( self, BBB ) thisBook.objectNameString = 'MySword Bible Book object' thisBook.objectTypeString = 'MySword' verseList = self.BOS.getNumVersesList( BBB ) numC, numV = len(verseList), verseList[0] nBBB = BibleOrgSysGlobals.BibleBooksCodes.getReferenceNumber( BBB ) C = V = 1 bookCount = 0 ourGlobals = {} continued = ourGlobals['haveParagraph'] = False haveLines = False while True: self.cursor.execute('select Scripture from Bible where Book=? and Chapter=? and Verse=?', (nBBB,C,V) ) try: row = self.cursor.fetchone() line = row[0] except TypeError: # This reference is missing (row is None) #print( "something wrong at", BBB, C, V ) #if BibleOrgSysGlobals.debugFlag: halt #print( row ) line = None #print ( nBBB, BBB, C, V, 'MySw file line is "' + line + '"' ) if line is None: logging.warning( "MySwordBible.load: Found missing verse line at {} {}:{}".format( BBB, C, V ) ) else: # line is not None if not isinstance( line, str ): if 'encryption' in self.suppliedMetadata['MySword']: logging.critical( "MySwordBible.load: Unable to decrypt verse line at {} {}:{} {!r}".format( BBB, C, V, line ) ) break else: logging.critical( "MySwordBible.load: Unable to decode verse line at {} {}:{} {!r} {}".format( BBB, C, V, line, self.suppliedMetadata['MySword'] ) ) elif not line: logging.warning( "MySwordBible.load: Found blank verse line at {} {}:{}".format( BBB, C, V ) ) else: haveLines = True # Some modules end lines with \r\n or have it in the middle! # (We just ignore these for now) while line and line[-1] in '\r\n': line = line[:-1] if '\r' in line or '\n' in line: # (in the middle) logging.warning( "MySwordBible.load: Found CR or LF characters in verse line at {} {}:{}".format( BBB, C, V ) ) line = line.replace( '\r\n', ' ' ).replace( '\r', ' ' ).replace( '\n', ' ' ) #print( "MySword.load", BBB, C, V, repr(line) ) handleLine( self.name, BBB, C, V, line, thisBook, ourGlobals ) V += 1 if V > numV: C += 1 if C > numC: # Save this book now if haveLines: if BibleOrgSysGlobals.verbosityLevel > 3: print( " MySword saving", BBB, bookCount+1 ) self.stashBook( thisBook ) #else: print( "Not saving", BBB ) bookCount += 1 # Not the number saved but the number we attempted to process if bookCount >= booksExpected: break BBB = self.BOS.getNextBookCode( BBB ) # Create the next book thisBook = BibleBook( self, BBB ) thisBook.objectNameString = 'MySword Bible Book object' thisBook.objectTypeString = 'MySword' haveLines = False verseList = self.BOS.getNumVersesList( BBB ) numC, numV = len(verseList), verseList[0] nBBB = BibleOrgSysGlobals.BibleBooksCodes.getReferenceNumber( BBB ) C = V = 1 #thisBook.addLine( 'c', str(C) ) else: # next chapter only #thisBook.addLine( 'c', str(C) ) numV = verseList[C-1] V = 1 if ourGlobals['haveParagraph']: thisBook.addLine( 'p', '' ) ourGlobals['haveParagraph'] = False self.cursor.close() self.applySuppliedMetadata( 'MySword' ) # Copy some to self.settingsDict self.doPostLoadProcessing() # end of MySwordBible.load def loadBook( self, BBB ): """ Load the requested book out of the SQLite3 database. """ if BibleOrgSysGlobals.debugFlag and debuggingThisModule: print( exp("loadBook( {} )").format( BBB ) ) assert self.preloadDone if BBB in self.books: if BibleOrgSysGlobals.debugFlag: print( " {} is already loaded -- returning".format( BBB ) ) return # Already loaded if BBB in self.triedLoadingBook: logging.warning( "We had already tried loading MySwordBible {} for {}".format( BBB, self.name ) ) return # We've already attempted to load this book self.triedLoadingBook[BBB] = True self.bookNeedsReloading[BBB] = False if BibleOrgSysGlobals.verbosityLevel > 2 or BibleOrgSysGlobals.debugFlag: print( _("MySwordBible: Loading {} from {}…").format( BBB, self.sourceFilepath ) ) #if self.suppliedMetadata['MySword']['OT'] and self.suppliedMetadata['MySword']['NT']: #testament, BBB = 'BOTH', 'GEN' #booksExpected, textLineCountExpected = 1, 31102 #elif self.suppliedMetadata['MySword']['OT']: #testament, BBB = 'OT', 'GEN' #booksExpected, textLineCountExpected = 1, 23145 #elif self.suppliedMetadata['MySword']['NT']: #testament, BBB = 'NT', 'MAT' #booksExpected, textLineCountExpected = 1, 7957 # Create the first book thisBook = BibleBook( self, BBB ) thisBook.objectNameString = 'MySword Bible Book object' thisBook.objectTypeString = 'MySword' verseList = self.BOS.getNumVersesList( BBB ) numC, numV = len(verseList), verseList[0] nBBB = BibleOrgSysGlobals.BibleBooksCodes.getReferenceNumber( BBB ) C = V = 1 #bookCount = 0 ourGlobals = {} continued = ourGlobals['haveParagraph'] = False haveLines = False while True: self.cursor.execute('select Scripture from Bible where Book=? and Chapter=? and Verse=?', (nBBB,C,V) ) try: row = self.cursor.fetchone() line = row[0] except TypeError: # This reference is missing (row is None) #print( "something wrong at", BBB, C, V ) #if BibleOrgSysGlobals.debugFlag: halt #print( row ) line = None #print ( nBBB, BBB, C, V, 'MySw file line is "' + line + '"' ) if line is None: logging.warning( "MySwordBible.load: Found missing verse line at {} {}:{}".format( BBB, C, V ) ) else: # line is not None if not isinstance( line, str ): if 'encryption' in self.suppliedMetadata['MySword']: logging.critical( "MySwordBible.load: Unable to decrypt verse line at {} {}:{} {!r}".format( BBB, C, V, line ) ) break else: logging.critical( "MySwordBible.load: Unable to decode verse line at {} {}:{} {!r} {}".format( BBB, C, V, line, self.suppliedMetadata['MySword'] ) ) elif not line: logging.warning( "MySwordBible.load: Found blank verse line at {} {}:{}".format( BBB, C, V ) ) else: haveLines = True # Some modules end lines with \r\n or have it in the middle! # (We just ignore these for now) while line and line[-1] in '\r\n': line = line[:-1] if '\r' in line or '\n' in line: # (in the middle) logging.warning( "MySwordBible.load: Found CR or LF characters in verse line at {} {}:{}".format( BBB, C, V ) ) line = line.replace( '\r\n', ' ' ).replace( '\r', ' ' ).replace( '\n', ' ' ) #print( "MySword.load", BBB, C, V, repr(line) ) handleLine( self.name, BBB, C, V, line, thisBook, ourGlobals ) V += 1 if V > numV: C += 1 if C <= numC: # next chapter only #thisBook.addLine( 'c', str(C) ) numV = verseList[C-1] V = 1 else: # Save this book now if haveLines: if BibleOrgSysGlobals.verbosityLevel > 2: print( " MySword saving", BBB ) self.stashBook( thisBook ) #else: print( "Not saving", BBB ) break if ourGlobals['haveParagraph']: thisBook.addLine( 'p', '' ) ourGlobals['haveParagraph'] = False
class BibleReferenceBox(Frame, BibleBox): """ """ def __init__(self, parentWindow, parentFrame, parentApp, internalBible, referenceObject): """ """ if BibleOrgSysGlobals.debugFlag: print( exp("BibleReferenceBox.__init__( {}, {}. {}, {}, {} )").format( parentWindow, parentFrame, parentApp, internalBible.getAName(), referenceObject)) self.parentWindow, self.parentFrame, self.parentApp, self.referenceObject = parentWindow, parentFrame, parentApp, referenceObject self.internalBible = handleInternalBibles(self.parentApp, internalBible, self) Frame.__init__(self, parentFrame) BibleBox.__init__(self, parentApp) # Set some dummy values required soon #self._contextViewRadioVar, self._formatViewRadioVar, self._groupRadioVar = tk.IntVar(), tk.IntVar(), tk.StringVar() #self._groupCode = BIBLE_GROUP_CODES[0] # Put into first/default BCV group #self._contextViewMode = DEFAULT #self._formatViewMode = DEFAULT self.currentVerseKey = SimpleVerseKey('UNK', '1', '1') # Unknown book #if self._contextViewMode == DEFAULT: #self._contextViewMode = 'ByVerse' #self.parentWindow.viewVersesBefore, self.parentWindow.viewVersesAfter = 2, 6 #if self._formatViewMode == DEFAULT: #self._formatViewMode = 'Formatted' # Create a title bar titleBar = Frame(self) Button(titleBar, text=_('Close'), command=self.doClose).pack(side=tk.RIGHT) ## Try to get the title width somewhere near correct (if moduleID is a long path) #adjModuleID = moduleID #self.update() # so we can get the geometry #width = parseWindowSize( self.parentWindow.winfo_geometry() )[0] - 60 # Allow for above button #if len(adjModuleID)*10 > width: # Note: this doesn't adjust if the window size is changed #print( "BRB here1", len(adjModuleID), width, repr(adjModuleID) ) #x = len(adjModuleID)*100/width # not perfect (too small) for narrow windows #adjModuleID = '…' + adjModuleID[int(x):] #print( "BRB here2", len(adjModuleID), x, repr(adjModuleID) ) #titleText = '{} ({})'.format( adjModuleID, boxType.replace( 'BibleReferenceBox', '' ) ) titleText = self.referenceObject.getShortText() self.titleLabel = tk.Label(titleBar, text=titleText) self.titleLabel.pack(side=tk.TOP, fill=tk.X) titleBar.pack(side=tk.TOP, fill=tk.X) # Create a scroll bar to fill the right-hand side of the window self.vScrollbar = Scrollbar(self) self.vScrollbar.pack(side=tk.RIGHT, fill=tk.Y) self.textBox = BText(self, height=5, yscrollcommand=self.vScrollbar.set) self.textBox.configure(wrap='word') self.textBox.pack(expand=tk.YES, fill=tk.X) # Full width self.vScrollbar.configure( command=self.textBox.yview) # link the scrollbar to the text box self.createStandardBoxKeyboardBindings() self.textBox.bind( '<Button-1>', self.setFocus ) # So disabled text box can still do select and copy functions # Set-up our standard Bible styles for USFMKey, styleDict in self.parentApp.stylesheet.getTKStyles( ).items(): self.textBox.tag_configure(USFMKey, **styleDict) # Create the style # Add our extra specialised styles self.textBox.tag_configure('contextHeader', background='pink', font='helvetica 6 bold') self.textBox.tag_configure('context', background='pink', font='helvetica 6') self.textBox.tag_configure('markersHeader', background='yellow3', font='helvetica 6 bold') self.textBox.tag_configure('markers', background='yellow3', font='helvetica 6') self.pack(expand=tk.YES, fill=tk.BOTH) # Pack the frame # Set-up our Bible system and our callables self.BibleOrganisationalSystem = BibleOrganizationalSystem( 'GENERIC-KJV-81-ENG') # temp self.getNumChapters = self.BibleOrganisationalSystem.getNumChapters self.getNumVerses = lambda b,c: MAX_PSEUDOVERSES if c=='0' or c==0 \ else self.BibleOrganisationalSystem.getNumVerses( b, c ) self.isValidBCVRef = self.BibleOrganisationalSystem.isValidBCVRef self.getFirstBookCode = self.BibleOrganisationalSystem.getFirstBookCode self.getPreviousBookCode = self.BibleOrganisationalSystem.getPreviousBookCode self.getNextBookCode = self.BibleOrganisationalSystem.getNextBookCode self.getBBBFromText = self.BibleOrganisationalSystem.getBBBFromText self.getBookName = self.BibleOrganisationalSystem.getBookName self.getBookList = self.BibleOrganisationalSystem.getBookList self.maxChaptersThisBook, self.maxVersesThisChapter = 150, 150 # temp self.verseCache = OrderedDict() self.updateShownReferences(self.referenceObject) # end of BibleReferenceBox.__init__ def createStandardBoxKeyboardBindings(self): """ Create keyboard bindings for this widget. """ if BibleOrgSysGlobals.debugFlag and debuggingThisModule: print(exp("BibleReferenceBox.createStandardBoxKeyboardBindings()")) for name, command in ( ('SelectAll', self.doSelectAll), ('Copy', self.doCopy), ('Find', self.doBoxFind), ('Refind', self.doBoxRefind), #('Info',self.doShowInfo), #('ShowMain',self.doShowMainWindow), ('Close', self.doClose), ): self._createStandardBoxKeyboardBinding(name, command) # end of BibleReferenceBox.createStandardBoxKeyboardBindings() def xxxgotoBCV(self, BBB, C, V): """ """ if BibleOrgSysGlobals.debugFlag: print( exp("BibleReferenceBox.gotoBCV( {} {}:{} from {} )").format( BBB, C, V, self.currentVerseKey)) # We really need to convert versification systems here adjBBB, adjC, adjV, adjS = self.BibleOrganisationalSystem.convertToReferenceVersification( BBB, C, V) self.parentWindow.gotoGroupBCV( self._groupCode, adjBBB, adjC, adjV) # then the App will update me by calling updateShownBCV # end of BibleReferenceBox.gotoBCV def getContextVerseData(self, verseKey): """ Fetches and returns the internal Bible data for the given reference. """ if BibleOrgSysGlobals.debugFlag and debuggingThisModule: print( exp("BibleReferenceBox.getContextVerseData( {} )").format( verseKey)) if self.internalBible is not None: try: return self.internalBible.getContextVerseData(verseKey) except KeyError: # Could be after a verse-bridge ??? if verseKey.getChapterNumber() != '0': logging.error( exp("BibleReferenceBox.getContextVerseData for {} {} got a KeyError") \ .format( self.boxType, verseKey ) ) # end of BibleReferenceBox.getContextVerseData #def XXXgetSwordVerseKey( self, verseKey ): ##if BibleOrgSysGlobals.debugFlag and debuggingThisModule: print( exp("getSwordVerseKey( {} )").format( verseKey ) ) #BBB, C, V = verseKey.getBCV() #return self.parentApp.SwordInterface.makeKey( BBB, C, V ) ## end of BibleReferenceBox.getSwordVerseKey def getCachedVerseData(self, verseKey): """ Checks to see if the requested verse is in our cache, otherwise calls getContextVerseData (from the superclass) to fetch it. The cache keeps the newest or most recently used entries at the end. When it gets too large, it drops the first entry. """ #if BibleOrgSysGlobals.debugFlag and debuggingThisModule: print( exp("getCachedVerseData( {} )").format( verseKey ) ) verseKeyHash = verseKey.makeHash() if verseKeyHash in self.verseCache: #if BibleOrgSysGlobals.debugFlag and debuggingThisModule: print( " " + exp("Retrieved from BibleReferenceBox cache") ) self.verseCache.move_to_end(verseKeyHash) #print( " returning", self.verseCache[verseKeyHash][0] ) return self.verseCache[verseKeyHash] verseContextData = self.getContextVerseData(verseKey) self.verseCache[verseKeyHash] = verseContextData if len(self.verseCache) > MAX_CACHED_VERSES: #print( "Removing oldest cached entry", len(self.verseCache) ) self.verseCache.popitem(last=False) return verseContextData # end of BibleReferenceBox.getCachedVerseData def updateShownReferences(self, newReferenceObject): """ Updates self in various ways depending on the contextViewMode held by the enclosing window. The new verse references are in the reference versification system in one of these objects: SimpleVerseKey (accepts 'GEN_1:1' or 'GEN','1','1') SimpleVersesKey (accepts 'MAT_6:1,4') VerseRangeKey (accepts 'JNA_2:1-7') Leaves the textbox in the disabled state. """ if BibleOrgSysGlobals.debugFlag and debuggingThisModule: print( "BibleReferenceBox.updateShownReferences( {} ) for {}".format( newReferenceObject, self.internalBible.getAName())) assert isinstance( newReferenceObject, SimpleVerseKey) or isinstance( newReferenceObject, SimpleVersesKey) or isinstance( newReferenceObject, VerseRangeKey) for j, referenceVerse in enumerate(newReferenceObject): #print( " refVerse", j, referenceVerse ) assert isinstance(referenceVerse, SimpleVerseKey) refBBB, refC, refV, refS = referenceVerse.getBCVS() BBB, C, V, S = self.BibleOrganisationalSystem.convertFromReferenceVersification( refBBB, refC, refV, refS) newVerseKey = SimpleVerseKey(BBB, C, V, S) #print( " newVK", newVerseKey ) # Set firstFlag as False (rather than j==0) so don't get context displayed self.displayAppendVerse(False, newVerseKey, self.getCachedVerseData(newVerseKey), lastFlag=False) self.textBox.configure(state=tk.DISABLED) # Don't allow editing # end of BibleReferenceBox.updateShownReferences def doClose(self, event=None): """ Called from the GUI. Can be overridden. """ self.closeReferenceBox() # end of BibleReferenceBox.doClose def closeReferenceBox(self): """ Called to finally and irreversibly remove this box from our list and close it. """ if BibleOrgSysGlobals.debugFlag and debuggingThisModule: print(exp("BibleReferenceBox.closeReferenceBox()")) if self in self.parentWindow.referenceBoxes: self.parentWindow.referenceBoxes.remove(self) self.destroy() else: # we might not have finished making our box yet if BibleOrgSysGlobals.debugFlag: print( exp("BibleReferenceBox.closeReferenceBox() for {} wasn't in list" ).format(self.windowType)) try: self.destroy() except tk.TclError: pass # never mind if BibleOrgSysGlobals.debugFlag: self.parentApp.setDebugText("Closed resource box")
def load(self): """ Load a single source file and load book elements. """ if BibleOrgSysGlobals.verbosityLevel > 2: print(_("Loading {}...").format(self.sourceFilepath)) fileExtensionUpper = self.fileExtension.upper() if fileExtensionUpper not in filenameEndingsToAccept: logging.critical("{} doesn't appear to be a MySword file".format( self.sourceFilename)) elif not self.sourceFilename.upper().endswith( BibleFilenameEndingsToAccept[0]): logging.critical( "{} doesn't appear to be a MySword Bible file".format( self.sourceFilename)) connection = sqlite3.connect(self.sourceFilepath) connection.row_factory = sqlite3.Row # Enable row names cursor = connection.cursor() # First get the settings cursor.execute('select * from Details') row = cursor.fetchone() for key in row.keys(): self.settingsDict[key] = row[key] #print( self.settingsDict ); halt if 'Description' in self.settingsDict and len( self.settingsDict['Description']) < 40: self.name = self.settingsDict['Description'] if 'Abbreviation' in self.settingsDict: self.abbreviation = self.settingsDict['Abbreviation'] if 'encryption' in self.settingsDict: logging.critical("{} is encrypted: level {}".format( self.sourceFilename, self.settingsDict['encryption'])) if self.settingsDict['OT'] and self.settingsDict['NT']: testament, BBB = 'BOTH', 'GEN' booksExpected, textLineCountExpected = 66, 31102 elif self.settingsDict['OT']: testament, BBB = 'OT', 'GEN' booksExpected, textLineCountExpected = 39, 23145 elif self.settingsDict['NT']: testament, BBB = 'NT', 'MAT' booksExpected, textLineCountExpected = 27, 7957 BOS = BibleOrganizationalSystem("GENERIC-KJV-66-ENG") # Create the first book thisBook = BibleBook(self, BBB) thisBook.objectNameString = "MySword Bible Book object" thisBook.objectTypeString = "MySword" verseList = BOS.getNumVersesList(BBB) numC, numV = len(verseList), verseList[0] nBBB = BibleOrgSysGlobals.BibleBooksCodes.getReferenceNumber(BBB) C = V = 1 bookCount = 0 ourGlobals = {} continued = ourGlobals['haveParagraph'] = False haveLines = False while True: cursor.execute( 'select Scripture from Bible where Book=? and Chapter=? and Verse=?', (nBBB, C, V)) try: row = cursor.fetchone() line = row[0] except TypeError: # This reference is missing (row is None) #print( "something wrong at", BBB, C, V ) #if BibleOrgSysGlobals.debugFlag: halt #print( row ) line = None #print ( nBBB, BBB, C, V, 'MySw file line is "' + line + '"' ) if line is None: logging.warning( "MySwordBible.load: Found missing verse line at {} {}:{}". format(BBB, C, V)) else: # line is not None if not isinstance(line, str): if 'encryption' in self.settingsDict: logging.critical( "MySwordBible.load: Unable to decrypt verse line at {} {}:{} {}" .format(BBB, C, V, repr(line))) break else: logging.critical( "MySwordBible.load: Unable to decode verse line at {} {}:{} {} {}" .format(BBB, C, V, repr(line), self.settingsDict)) elif not line: logging.warning( "MySwordBible.load: Found blank verse line at {} {}:{}" .format(BBB, C, V)) else: haveLines = True # Some modules end lines with \r\n or have it in the middle! # (We just ignore these for now) while line and line[-1] in '\r\n': line = line[:-1] if '\r' in line or '\n' in line: # (in the middle) logging.warning( "MySwordBible.load: Found CR or LF characters in verse line at {} {}:{}" .format(BBB, C, V)) line = line.replace('\r\n', ' ').replace('\r', ' ').replace('\n', ' ') #print( "MySword.load", BBB, C, V, repr(line) ) handleLine(self.name, BBB, C, V, line, thisBook, ourGlobals) V += 1 if V > numV: C += 1 if C > numC: # Save this book now if haveLines: if BibleOrgSysGlobals.verbosityLevel > 3: print("Saving", BBB, bookCount + 1) self.saveBook(thisBook) #else: print( "Not saving", BBB ) bookCount += 1 # Not the number saved but the number we attempted to process if bookCount >= booksExpected: break BBB = BOS.getNextBookCode(BBB) # Create the next book thisBook = BibleBook(self, BBB) thisBook.objectNameString = "MySword Bible Book object" thisBook.objectTypeString = "MySword" haveLines = False verseList = BOS.getNumVersesList(BBB) numC, numV = len(verseList), verseList[0] nBBB = BibleOrgSysGlobals.BibleBooksCodes.getReferenceNumber( BBB) C = V = 1 #thisBook.addLine( 'c', str(C) ) else: # next chapter only #thisBook.addLine( 'c', str(C) ) numV = verseList[C - 1] V = 1 if ourGlobals['haveParagraph']: thisBook.addLine('p', '') ourGlobals['haveParagraph'] = False cursor.close() self.doPostLoadProcessing()
class MySwordBible(Bible): """ Class for reading, validating, and converting MySwordBible files. """ def __init__(self, sourceFolder, givenFilename, encoding='utf-8'): """ Constructor: just sets up the Bible object. """ # Setup and initialise the base class first Bible.__init__(self) self.objectNameString = 'MySword Bible object' self.objectTypeString = 'MySword' # Now we can set our object variables self.sourceFolder, self.sourceFilename, self.encoding = sourceFolder, givenFilename, encoding self.sourceFilepath = os.path.join(self.sourceFolder, self.sourceFilename) # Do a preliminary check on the readability of our file if not os.access(self.sourceFilepath, os.R_OK): logging.critical( _("MySwordBible: File {!r} is unreadable").format( self.sourceFilepath)) filenameBits = os.path.splitext(self.sourceFilename) self.name = filenameBits[0] self.fileExtension = filenameBits[1] #if self.fileExtension.upper().endswith('X'): #logging.warning( _("MySwordBible: File {!r} is encrypted").format( self.sourceFilepath ) ) # end of MySwordBible.__init__ def preload(self): """ Load the metadata from the SQLite3 database. """ if BibleOrgSysGlobals.debugFlag and debuggingThisModule: print(exp("preload()")) if BibleOrgSysGlobals.verbosityLevel > 2: print(_("Preloading {}…").format(self.sourceFilepath)) fileExtensionUpper = self.fileExtension.upper() if fileExtensionUpper not in FILENAME_ENDINGS_TO_ACCEPT: logging.critical("{} doesn't appear to be a MySword file".format( self.sourceFilename)) elif not self.sourceFilename.upper().endswith( BIBLE_FILENAME_ENDINGS_TO_ACCEPT[0]): logging.critical( "{} doesn't appear to be a MySword Bible file".format( self.sourceFilename)) connection = sqlite3.connect(self.sourceFilepath) connection.row_factory = sqlite3.Row # Enable row names self.cursor = connection.cursor() # First get the settings if self.suppliedMetadata is None: self.suppliedMetadata = {} self.suppliedMetadata['MySword'] = {} self.cursor.execute('select * from Details') row = self.cursor.fetchone() for key in row.keys(): self.suppliedMetadata['MySword'][key] = row[key] #print( self.suppliedMetadata['MySword'] ); halt #if 'Description' in self.settingsDict and len(self.settingsDict['Description'])<40: self.name = self.settingsDict['Description'] #if 'Abbreviation' in self.settingsDict: self.abbreviation = self.settingsDict['Abbreviation'] if 'encryption' in self.suppliedMetadata['MySword']: logging.critical("{} is encrypted: level {}".format( self.sourceFilename, self.suppliedMetadata['MySword']['encryption'])) self.BOS = BibleOrganizationalSystem('GENERIC-KJV-66-ENG') self.preloadDone = True # end of MySwordBible.preload def load(self): """ Load all the books out of the SQLite3 database. """ if BibleOrgSysGlobals.debugFlag and debuggingThisModule: print(exp("load()")) assert self.preloadDone if BibleOrgSysGlobals.verbosityLevel > 2: print(_("Loading {}…").format(self.sourceFilepath)) if self.suppliedMetadata['MySword']['OT'] and self.suppliedMetadata[ 'MySword']['NT']: testament, BBB = 'BOTH', 'GEN' booksExpected, textLineCountExpected = 66, 31102 elif self.suppliedMetadata['MySword']['OT']: testament, BBB = 'OT', 'GEN' booksExpected, textLineCountExpected = 39, 23145 elif self.suppliedMetadata['MySword']['NT']: testament, BBB = 'NT', 'MAT' booksExpected, textLineCountExpected = 27, 7957 # Create the first book thisBook = BibleBook(self, BBB) thisBook.objectNameString = 'MySword Bible Book object' thisBook.objectTypeString = 'MySword' verseList = self.BOS.getNumVersesList(BBB) numC, numV = len(verseList), verseList[0] nBBB = BibleOrgSysGlobals.BibleBooksCodes.getReferenceNumber(BBB) C = V = 1 bookCount = 0 ourGlobals = {} continued = ourGlobals['haveParagraph'] = False haveLines = False while True: self.cursor.execute( 'select Scripture from Bible where Book=? and Chapter=? and Verse=?', (nBBB, C, V)) try: row = self.cursor.fetchone() line = row[0] except TypeError: # This reference is missing (row is None) #print( "something wrong at", BBB, C, V ) #if BibleOrgSysGlobals.debugFlag: halt #print( row ) line = None #print ( nBBB, BBB, C, V, 'MySw file line is "' + line + '"' ) if line is None: logging.warning( "MySwordBible.load: Found missing verse line at {} {}:{}". format(BBB, C, V)) else: # line is not None if not isinstance(line, str): if 'encryption' in self.suppliedMetadata['MySword']: logging.critical( "MySwordBible.load: Unable to decrypt verse line at {} {}:{} {!r}" .format(BBB, C, V, line)) break else: logging.critical( "MySwordBible.load: Unable to decode verse line at {} {}:{} {!r} {}" .format(BBB, C, V, line, self.suppliedMetadata['MySword'])) elif not line: logging.warning( "MySwordBible.load: Found blank verse line at {} {}:{}" .format(BBB, C, V)) else: haveLines = True # Some modules end lines with \r\n or have it in the middle! # (We just ignore these for now) while line and line[-1] in '\r\n': line = line[:-1] if '\r' in line or '\n' in line: # (in the middle) logging.warning( "MySwordBible.load: Found CR or LF characters in verse line at {} {}:{}" .format(BBB, C, V)) line = line.replace('\r\n', ' ').replace('\r', ' ').replace('\n', ' ') #print( "MySword.load", BBB, C, V, repr(line) ) handleLine(self.name, BBB, C, V, line, thisBook, ourGlobals) V += 1 if V > numV: C += 1 if C > numC: # Save this book now if haveLines: if BibleOrgSysGlobals.verbosityLevel > 3: print(" MySword saving", BBB, bookCount + 1) self.stashBook(thisBook) #else: print( "Not saving", BBB ) bookCount += 1 # Not the number saved but the number we attempted to process if bookCount >= booksExpected: break BBB = self.BOS.getNextBookCode(BBB) # Create the next book thisBook = BibleBook(self, BBB) thisBook.objectNameString = 'MySword Bible Book object' thisBook.objectTypeString = 'MySword' haveLines = False verseList = self.BOS.getNumVersesList(BBB) numC, numV = len(verseList), verseList[0] nBBB = BibleOrgSysGlobals.BibleBooksCodes.getReferenceNumber( BBB) C = V = 1 #thisBook.addLine( 'c', str(C) ) else: # next chapter only #thisBook.addLine( 'c', str(C) ) numV = verseList[C - 1] V = 1 if ourGlobals['haveParagraph']: thisBook.addLine('p', '') ourGlobals['haveParagraph'] = False self.cursor.close() self.applySuppliedMetadata('MySword') # Copy some to self.settingsDict self.doPostLoadProcessing() # end of MySwordBible.load def loadBook(self, BBB): """ Load the requested book out of the SQLite3 database. """ if BibleOrgSysGlobals.debugFlag and debuggingThisModule: print(exp("loadBook( {} )").format(BBB)) assert self.preloadDone if BBB in self.books: if BibleOrgSysGlobals.debugFlag: print(" {} is already loaded -- returning".format(BBB)) return # Already loaded if BBB in self.triedLoadingBook: logging.warning( "We had already tried loading MySwordBible {} for {}".format( BBB, self.name)) return # We've already attempted to load this book self.triedLoadingBook[BBB] = True self.bookNeedsReloading[BBB] = False if BibleOrgSysGlobals.verbosityLevel > 2 or BibleOrgSysGlobals.debugFlag: print( _("MySwordBible: Loading {} from {}…").format( BBB, self.sourceFilepath)) #if self.suppliedMetadata['MySword']['OT'] and self.suppliedMetadata['MySword']['NT']: #testament, BBB = 'BOTH', 'GEN' #booksExpected, textLineCountExpected = 1, 31102 #elif self.suppliedMetadata['MySword']['OT']: #testament, BBB = 'OT', 'GEN' #booksExpected, textLineCountExpected = 1, 23145 #elif self.suppliedMetadata['MySword']['NT']: #testament, BBB = 'NT', 'MAT' #booksExpected, textLineCountExpected = 1, 7957 # Create the first book thisBook = BibleBook(self, BBB) thisBook.objectNameString = 'MySword Bible Book object' thisBook.objectTypeString = 'MySword' verseList = self.BOS.getNumVersesList(BBB) numC, numV = len(verseList), verseList[0] nBBB = BibleOrgSysGlobals.BibleBooksCodes.getReferenceNumber(BBB) C = V = 1 #bookCount = 0 ourGlobals = {} continued = ourGlobals['haveParagraph'] = False haveLines = False while True: self.cursor.execute( 'select Scripture from Bible where Book=? and Chapter=? and Verse=?', (nBBB, C, V)) try: row = self.cursor.fetchone() line = row[0] except TypeError: # This reference is missing (row is None) #print( "something wrong at", BBB, C, V ) #if BibleOrgSysGlobals.debugFlag: halt #print( row ) line = None #print ( nBBB, BBB, C, V, 'MySw file line is "' + line + '"' ) if line is None: logging.warning( "MySwordBible.load: Found missing verse line at {} {}:{}". format(BBB, C, V)) else: # line is not None if not isinstance(line, str): if 'encryption' in self.suppliedMetadata['MySword']: logging.critical( "MySwordBible.load: Unable to decrypt verse line at {} {}:{} {!r}" .format(BBB, C, V, line)) break else: logging.critical( "MySwordBible.load: Unable to decode verse line at {} {}:{} {!r} {}" .format(BBB, C, V, line, self.suppliedMetadata['MySword'])) elif not line: logging.warning( "MySwordBible.load: Found blank verse line at {} {}:{}" .format(BBB, C, V)) else: haveLines = True # Some modules end lines with \r\n or have it in the middle! # (We just ignore these for now) while line and line[-1] in '\r\n': line = line[:-1] if '\r' in line or '\n' in line: # (in the middle) logging.warning( "MySwordBible.load: Found CR or LF characters in verse line at {} {}:{}" .format(BBB, C, V)) line = line.replace('\r\n', ' ').replace('\r', ' ').replace('\n', ' ') #print( "MySword.load", BBB, C, V, repr(line) ) handleLine(self.name, BBB, C, V, line, thisBook, ourGlobals) V += 1 if V > numV: C += 1 if C <= numC: # next chapter only #thisBook.addLine( 'c', str(C) ) numV = verseList[C - 1] V = 1 else: # Save this book now if haveLines: if BibleOrgSysGlobals.verbosityLevel > 2: print(" MySword saving", BBB) self.stashBook(thisBook) #else: print( "Not saving", BBB ) break if ourGlobals['haveParagraph']: thisBook.addLine('p', '') ourGlobals['haveParagraph'] = False
def load( self ): """ Load a single source file and load book elements. """ if Globals.verbosityLevel > 2: print( _("Loading {}...").format( self.sourceFilepath ) ) loadErrors = [] fileExtensionUpper = self.fileExtension.upper() if fileExtensionUpper not in filenameEndingsToAccept: logging.critical( "{} doesn't appear to be a e-Sword file".format( self.sourceFilename ) ) elif not self.sourceFilename.upper().endswith( BibleFilenameEndingsToAccept[0] ): logging.critical( "{} doesn't appear to be a e-Sword Bible file".format( self.sourceFilename ) ) connection = sqlite3.connect( self.sourceFilepath ) connection.row_factory = sqlite3.Row # Enable row names cursor = connection.cursor() # First get the settings cursor.execute( 'select * from Details' ) row = cursor.fetchone() for key in row.keys(): self.settingsDict[key] = row[key] #print( self.settingsDict ); halt if 'Description' in self.settingsDict and len(self.settingsDict['Description'])<40: self.name = self.settingsDict['Description'] if 'Abbreviation' in self.settingsDict: self.abbreviation = self.settingsDict['Abbreviation'] if 'encryption' in self.settingsDict: logging.critical( "{} is encrypted: level {}".format( self.sourceFilename, self.settingsDict['encryption'] ) ) # Just get some information from the file cursor.execute( 'select * from Bible' ) rows = cursor.fetchall() numRows = len(rows) if Globals.debugFlag or Globals.verbosityLevel>2: print( '{} rows found'.format( numRows ) ) BBBn1 = rows[0][0] if Globals.debugFlag or Globals.verbosityLevel>2: print( 'First book number is {}'.format( BBBn1 ) ) del rows BBB1 = None if BBBn1 <= 66: BBB1 = Globals.BibleBooksCodes.getBBBFromReferenceNumber( BBBn1 ) testament = BBB = None booksExpected = textLineCountExpected = 0 if self.settingsDict['OT'] and self.settingsDict['NT']: testament, BBB = 'BOTH', 'GEN' booksExpected, textLineCountExpected = 66, 31102 elif self.settingsDict['OT']: testament, BBB = 'OT', 'GEN' booksExpected, textLineCountExpected = 39, 23145 elif self.settingsDict['NT']: testament, BBB = 'NT', 'MAT' booksExpected, textLineCountExpected = 27, 7957 elif self.settingsDict['Abbreviation'] == 'VIN2011': # Handle encoding error logging.critical( "e-Sword settings encoding error -- no testament set: {}".format( self.settingsDict ) ) loadErrors.append( "e-Sword settings encoding error -- no testament set: {}".format( self.settingsDict ) ) testament, BBB = 'BOTH', 'GEN' booksExpected, textLineCountExpected = 66, 31102 elif self.settingsDict['Apocrypha']: # incomplete testament, BBB = 'AP', 'XXX' booksExpected, textLineCountExpected = 99, 999999 halt if not BBB: logging.critical( "e-Sword settings encoding error -- no testament set: {}".format( self.settingsDict ) ) loadErrors.append( "e-Sword settings encoding error -- no testament set: {}".format( self.settingsDict ) ) if 0: cursor.execute( 'select * from Bible' ) rows = cursor.fetchall() print( "rows", len(rows) ) for row in rows: assert( len(row) == 4 ) BBBn, C, V, text = row # First three are integers, the last is a string print( BBBn, C, V, repr(text) ) if C==2: break del rows # Takes a lot of memory if Globals.debugFlag or Globals.verbosityLevel>2: print( "Testament={} BBB={} BBB1={}, bE={}, tLCE={} nR={}".format( testament, BBB, BBB1, booksExpected, textLineCountExpected, numRows ) ) if BBB1 != BBB: logging.critical( "First book seems wrong: {} instead of {}".format( BBB1, BBB ) ) loadErrors.append( "First book seems wrong: {} instead of {}".format( BBB1, BBB ) ) if not BBB: BBB = BBB1 if numRows != textLineCountExpected: logging.critical( "Row count seems wrong: {} instead of {}".format( numRows, textLineCountExpected ) ) loadErrors.append( "Row count seems wrong: {} instead of {}".format( numRows, textLineCountExpected ) ) #halt BOS = BibleOrganizationalSystem( "GENERIC-KJV-66-ENG" ) # Create the first book thisBook = BibleBook( self.name, BBB ) thisBook.objectNameString = "e-Sword Bible Book object" thisBook.objectTypeString = "e-Sword" verseList = BOS.getNumVersesList( BBB ) numC, numV = len(verseList), verseList[0] nBBB = Globals.BibleBooksCodes.getReferenceNumber( BBB ) C = V = 1 bookCount = 0 ourGlobals = {} continued = ourGlobals['haveParagraph'] = False haveLines = False while True: cursor.execute('select Scripture from Bible where Book=? and Chapter=? and Verse=?', (nBBB,C,V) ) try: row = cursor.fetchone() line = row[0] except: # This reference is missing #print( "something wrong at", BBB, C, V ) #if Globals.debugFlag: halt #print( row ) line = None #print ( nBBB, BBB, C, V, 'e-Sw file line is "' + line + '"' ) if line is None: logging.warning( "ESwordBible.load: Found missing verse line at {} {}:{}".format( BBB, C, V ) ) else: # line is not None if not isinstance( line, str ): if 'encryption' in self.settingsDict: logging.critical( "ESwordBible.load: Unable to decrypt verse line at {} {}:{} {}".format( BBB, C, V, repr(line) ) ) break else: logging.critical( "ESwordBible.load: Probably encrypted module: Unable to decode verse line at {} {}:{} {} {}".format( BBB, C, V, repr(line), self.settingsDict ) ) break elif not line: logging.warning( "ESwordBible.load: Found blank verse line at {} {}:{}".format( BBB, C, V ) ) else: haveLines = True # Some modules end lines with \r\n or have it in the middle! # (We just ignore these for now) if '\r' in line or '\n' in line: if Globals.debugFlag: logging.warning( "ESwordBible.load: Found CR or LF characters in verse line at {} {}:{}".format( BBB, C, V ) ) #print( repr(line) ) while line and line[-1] in '\r\n': line = line[:-1] # Remove CR/LFs from the end line = line.replace( '\r\n', ' ' ).replace( '\r', ' ' ).replace( '\n', ' ' ) # Replace CR/LFs in the middle #print( "e-Sword.load", BBB, C, V, repr(line) ) self.handleLine( self.name, BBB, C, V, line, thisBook, ourGlobals ) V += 1 if V > numV: C += 1 if C > numC: # Save this book now if haveLines: if Globals.verbosityLevel > 3: print( "Saving", BBB, bookCount+1 ) self.saveBook( thisBook ) #else: print( "Not saving", BBB ) bookCount += 1 # Not the number saved but the number we attempted to process if bookCount >= booksExpected: break BBB = BOS.getNextBookCode( BBB ) # Create the next book thisBook = BibleBook( self.name, BBB ) thisBook.objectNameString = "e-Sword Bible Book object" thisBook.objectTypeString = "e-Sword" haveLines = False verseList = BOS.getNumVersesList( BBB ) numC, numV = len(verseList), verseList[0] nBBB = Globals.BibleBooksCodes.getReferenceNumber( BBB ) C = V = 1 #thisBook.appendLine( 'c', str(C) ) else: # next chapter only #thisBook.appendLine( 'c', str(C) ) numV = verseList[C-1] V = 1 if ourGlobals['haveParagraph']: thisBook.appendLine( 'p', '' ) ourGlobals['haveParagraph'] = False if Globals.strictCheckingFlag or Globals.debugFlag: self.checkForExtraMaterial( cursor, BOS ) cursor.close() if loadErrors: self.errorDictionary['Load Errors'] = loadErrors self.doPostLoadProcessing()
class OpenSongXMLBible(Bible): """ Class for reading, validating, and converting OpenSong Bible XML. """ treeTag = 'bible' bookTag = 'b' chapterTag = 'c' verseTag = 'v' def __init__(self, sourceFolder, givenName, encoding='utf-8'): """ Constructor: just sets up the XML Bible file converter object. """ # Setup and initialise the base class first if BibleOrgSysGlobals.debugFlag: print("OpenSongXMLBible( {}, {}, {} )".format( sourceFolder, givenName, encoding)) Bible.__init__(self) self.objectNameString = 'OpenSong XML Bible object' self.objectTypeString = 'OpenSong' # Now we can set our object variables self.sourceFolder, self.givenName, self.encoding = sourceFolder, givenName, encoding self.sourceFilepath = os.path.join(self.sourceFolder, self.givenName) self.tree = None # Will hold the XML data # Get the data tables that we need for proper checking #self.ISOLanguages = ISO_639_3_Languages().loadData() self.genericBOS = BibleOrganizationalSystem('GENERIC-KJV-66-ENG') # Do a preliminary check on the readability of our file if not os.access(self.sourceFilepath, os.R_OK): print("OpenSongXMLBible: File {!r} is unreadable".format( self.sourceFilepath)) self.name = self.givenName #if self.name is None: #pass # end of OpenSongXMLBible.__init__ def load(self): """ Load a single source XML file and load book elements. """ if BibleOrgSysGlobals.verbosityLevel > 2: print(_("Loading {}…").format(self.sourceFilepath)) self.tree = ElementTree().parse(self.sourceFilepath) if BibleOrgSysGlobals.debugFlag: assert len( self.tree) # Fail here if we didn't load anything at all # Find the main (bible) container if self.tree.tag == OpenSongXMLBible.treeTag: location = "XML file" BibleOrgSysGlobals.checkXMLNoText(self.tree, location, '4f6h') BibleOrgSysGlobals.checkXMLNoTail(self.tree, location, '1wk8') name = shortName = None for attrib, value in self.tree.items(): if attrib == "n": name = value elif attrib == "sn": shortName = value else: logging.warning( "Unprocessed {!r} attribute ({}) in main element". format(attrib, value)) # Find the submain (book) containers for element in self.tree: if element.tag == OpenSongXMLBible.bookTag: sublocation = "book in " + location BibleOrgSysGlobals.checkXMLNoText(element, sublocation, 'g3g5') BibleOrgSysGlobals.checkXMLNoTail(element, sublocation, 'd3f6') self.__validateAndExtractBook(element) elif element.tag == 'OT': pass elif element.tag == 'NT': pass else: logging.error("Expected to find {!r} but got {!r}".format( OpenSongXMLBible.bookTag, element.tag)) else: logging.error("Expected to load {!r} but got {!r}".format( OpenSongXMLBible.treeTag, self.tree.tag)) self.doPostLoadProcessing() # end of OpenSongXMLBible.load def __validateAndExtractBook(self, book): """ Check/validate and extract book data from the given XML book record finding chapter subelements. """ global BibleBooksNames if BibleOrgSysGlobals.verbosityLevel > 3: print(_("Validating OpenSong XML book…")) # Process the div attributes first BBB = bookName = None for attrib, value in book.items(): if attrib == "n": bookName = value else: logging.warning( "Unprocessed {!r} attribute ({}) in book element".format( attrib, value)) if bookName: BBB = self.genericBOS.getBBBFromText( bookName) # Booknames are usually in English if not BBB: # wasn't English if BibleBooksNames is None: BibleBooksNames = BibleBooksNamesSystems().loadData() BBB = BibleBooksNames.getBBBFromText( bookName) # Try non-English booknames #print( "bookName", bookName, BBB ) if BBB: if BibleOrgSysGlobals.verbosityLevel > 2: print(_("Validating {} {}…").format(BBB, bookName)) thisBook = BibleBook(self, BBB) thisBook.objectNameString = 'OpenSong XML Bible Book object' thisBook.objectTypeString = 'OpenSong' #thisBook.sourceFilepath = self.sourceFilepath USFMAbbreviation = BibleOrgSysGlobals.BibleBooksCodes.getUSFMAbbreviation( BBB) thisBook.addLine( 'id', '{} imported by {}'.format(USFMAbbreviation.upper(), ProgNameVersion)) thisBook.addLine('h', bookName) thisBook.addLine('mt1', bookName) for element in book: if element.tag == OpenSongXMLBible.chapterTag: sublocation = "chapter in {}".format(BBB) BibleOrgSysGlobals.checkXMLNoText( element, sublocation, 'j3jd') BibleOrgSysGlobals.checkXMLNoTail( element, sublocation, 'al1d') self.__validateAndExtractChapter( BBB, thisBook, element) else: logging.error( "Expected to find {!r} but got {!r}".format( OpenSongXMLBible.chapterTag, element.tag)) if BibleOrgSysGlobals.verbosityLevel > 2: print(" Saving {} into results…".format(BBB)) self.stashBook(thisBook) else: logging.error( _("OpenSong load doesn't recognize book name: {!r}"). format(bookName)) # no BBB else: logging.error( _("OpenSong load can't find a book name")) # no bookName # end of OpenSongXMLBible.__validateAndExtractBook def __validateAndExtractChapter(self, BBB, thisBook, chapter): """ Check/validate and extract chapter data from the given XML book record finding and saving chapter numbers and finding and saving verse elements. """ if BibleOrgSysGlobals.verbosityLevel > 3: print(_("Validating XML chapter…")) # Process the div attributes first chapterNumber = numVerses = None for attrib, value in chapter.items(): if attrib == "n": chapterNumber = value elif attrib == "VERSES": numVerses = value else: logging.warning( "Unprocessed {!r} attribute ({}) in chapter element". format(attrib, value)) if chapterNumber: #print( BBB, 'c', chapterNumber ) chapterNumber = chapterNumber.replace( 'of Solomon ', '') # Fix a mistake in the Chinese_SU module thisBook.addLine('c', chapterNumber) else: logging.error( "Missing 'n' attribute in chapter element for {}".format(BBB)) for element in chapter: if element.tag == OpenSongXMLBible.verseTag: sublocation = "verse in {} {}".format(BBB, chapterNumber) BibleOrgSysGlobals.checkXMLNoTail(element, sublocation, 'l5ks') verseNumber = toVerseNumber = None for attrib, value in element.items(): if attrib == "n": verseNumber = value elif attrib == "t": toVerseNumber = value else: logging.warning( "Unprocessed {!r} attribute ({}) in verse element". format(attrib, value)) if BibleOrgSysGlobals.debugFlag: assert verseNumber #thisBook.addLine( 'v', verseNumber ) vText = element.text if element.text else '' for subelement in element: sub2location = "{} in {}".format(subelement.tag, sublocation) BibleOrgSysGlobals.checkXMLNoAttributes( subelement, sub2location, 'ks03') BibleOrgSysGlobals.checkXMLNoSubelements( subelement, sub2location, 'ks05') if subelement.tag == 'i': vText += '\\it {}\\it*{}'.format( subelement.text, subelement.tail) else: logging.error( "Expected to find 'i' but got {!r}".format( subelement.tag)) vText += element.tail if element.tail else '' if not vText: logging.warning("{} {}:{} has no text".format( BBB, chapterNumber, verseNumber)) #print( 'vText1', vText ) if vText: # This is the main text of the verse (follows the verse milestone) #print( "{} {}:{} {!r}".format( BBB, chapterNumber, verseNumber, vText ) ) if '\n' in vText: # This is how they represent poety #print( "vText", repr(vText), repr(element.text) ) for j, textBit in enumerate(vText.split('\n')): if j == 0: thisBook.addLine('q1', '') thisBook.addLine('v', verseNumber + ' ' + textBit) else: thisBook.addLine('q1', textBit) else: # Just one verse line thisBook.addLine('v', verseNumber + ' ' + vText) #print( 'vText2', vText ) else: logging.error("Expected to find {!r} but got {!r}".format( OpenSongXMLBible.verseTag, element.tag))
def load( self ): """ Load a single source file and load book elements. """ if BibleOrgSysGlobals.verbosityLevel > 2: print( _("Loading {}…").format( self.sourceFilepath ) ) global BOS66, BOS81, BOSx if BOS66 is None: BOS66 = BibleOrganizationalSystem( 'GENERIC-KJV-66-ENG' ) if BOS81 is None: BOS81 = BibleOrganizationalSystem( 'GENERIC-KJV-81-ENG' ) if BOSx is None: BOSx = BibleOrganizationalSystem( 'GENERIC-ENG' ) if self.suppliedMetadata is None: self.suppliedMetadata = {} lastLine, lineCount = '', 0 vplType = bookCode = BBB = metadataName = None lastBookCode = lastChapterNumber = lastVerseNumber = -1 lastVText = '' thisBook = None settingsDict = {} with open( self.sourceFilepath, encoding=self.encoding ) as myFile: # Automatically closes the file when done for line in myFile: lineCount += 1 if line[-1]=='\n': line=line[:-1] # Removing trailing newline character if not line: continue # Just discard blank lines if lineCount==1: if self.encoding.lower()=='utf-8' and line[0]==chr(65279): #U+FEFF or \ufeff logging.info( " VPLBible.load: Detected Unicode Byte Order Marker (BOM)" ) line = line[1:] # Remove the Unicode Byte Order Marker (BOM) # Try to identify the VPL type match = re.search( '^(\\w{2,5}?)\\s(\\d{1,3})[:\\.](\\d{1,3})\\s', line ) if match: vplType = 1 else: match = re.search( '^(\\d{8})\\s', line ) if match: vplType = 2 else: match = re.search( '^# language_name:\\s', line ) if match: vplType = 3 #else: #match = re.search( '^; TITLE:\\s', line ) #if match: vplType = 4 if match: if BibleOrgSysGlobals.debugFlag: print( "First line got type #{} {!r} match from {!r}".format( vplType, match.group(0), line ) ) else: if BibleOrgSysGlobals.verbosityLevel > 2: print( "VPLBible.load: (unexpected) first line was {!r} in {}".format( line, self.sourceFilepath ) ) if BibleOrgSysGlobals.debugFlag and debuggingThisModule: halt continue #print( 'vplType', vplType ) #print ( 'VPL file line is "' + line + '"' ) lastLine = line # Process header stuff if vplType == 3: if line.startswith( '# language_name:' ): string = line[16:].strip() if string and string != 'Not available': settingsDict['LanguageName'] = string continue elif line.startswith( '# closest ISO 639-3:' ): string = line[20:].strip() if string and string != 'Not available': settingsDict['ISOLanguageCode'] = string continue elif line.startswith( '# year_short:' ): string = line[13:].strip() if string and string != 'Not available': settingsDict['Year.short'] = string continue elif line.startswith( '# year_long:' ): string = line[12:].strip() if string and string != 'Not available': settingsDict['Year.long'] = string continue elif line.startswith( '# title:' ): string = line[8:].strip() if string and string != 'Not available': settingsDict['WorkTitle'] = string continue elif line.startswith( '# URL:' ): string = line[6:].strip() if string and string != 'Not available': settingsDict['URL'] = string continue elif line.startswith( '# copyright_short:' ): string = line[18:].strip() if string and string != 'Not available': settingsDict['Copyright.short'] = string continue elif line.startswith( '# copyright_long:' ): string = line[17:].strip() if string and string != 'Not available': settingsDict['Copyright.long'] = string continue elif line[0]=='#': logging.warning( "VPLBible.load {} is skipping unknown line: {}".format( vplType, line ) ) continue # Just discard comment lines #elif vplType == 4: #if line.startswith( '; TITLE:' ): #string = line[8:].strip() #if string: settingsDict['TITLE'] = string #continue #elif line.startswith( '; ABBREVIATION:' ): #string = line[15:].strip() #if string: settingsDict['ABBREVIATION'] = string #continue #elif line.startswith( '; HAS ITALICS:' ): #string = line[15:].strip() #if string: settingsDict['HAS_ITALICS'] = string #continue #elif line.startswith( '; HAS FOOTNOTES:' ): #string = line[15:].strip() #if string: settingsDict['HAS_FOOTNOTES'] = string #continue #elif line.startswith( '; HAS FOOTNOTES' ): #string = line[14:].strip() #if string: settingsDict['HAS_FOOTNOTES'] = string #continue #elif line.startswith( '; HAS REDLETTER:' ): #string = line[15:].strip() #if string: settingsDict['HAS_REDLETTER'] = string #continue #elif line[0]==';': #logging.warning( "VPLBible.load{} is skipping unknown header/comment line: {}".format( vplType, line ) ) #continue # Just discard comment lines # Process the main segment if vplType == 1: bits = line.split( ' ', 2 ) #print( self.givenName, BBB, bits ) if len(bits) == 3 and ':' in bits[1]: bookCode, CVString, vText = bits chapterNumberString, verseNumberString = CVString.split( ':' ) else: print( "Unexpected number of bits", self.givenName, BBB, bookCode, chapterNumberString, verseNumberString, len(bits), bits ) if not bookCode and not chapterNumberString and not verseNumberString: print( "Skipping empty line in {} {} {} {}:{}".format( self.givenName, BBB, bookCode, chapterNumberString, verseNumberString ) ) continue if BibleOrgSysGlobals.debugFlag: assert 2 <= len(bookCode) <= 4 if BibleOrgSysGlobals.debugFlag: assert chapterNumberString.isdigit() if not verseNumberString.isdigit(): logging.error( "Invalid verse number field at {}/{} {}:{!r}".format( bookCode, BBB, chapterNumberString, verseNumberString ) ) if BibleOrgSysGlobals.debugFlag and debuggingThisModule: assert verseNumberString.isdigit() continue chapterNumber = int( chapterNumberString ) verseNumber = int( verseNumberString ) if bookCode != lastBookCode: # We've started a new book #if bookCode in ('Ge',): BBB = 'GEN' if bookCode in ('Le',): BBB = 'LEV' elif bookCode in ('Jud',): BBB = 'JDG' #elif bookCode in ('Es',): BBB = 'EST' #elif bookCode in ('Pr',): BBB = 'PRO' elif bookCode in ('So',): BBB = 'SNG' elif bookCode in ('La',): BBB = 'LAM' #elif bookCode in ('Jude',): BBB = 'JDE' else: #BBB = BibleOrgSysGlobals.BibleBooksCodes.getBBBFromText( bookCode ) # Try to guess BBB = BOS66.getBBBFromText( bookCode ) # Try to guess if not BBB: BBB = BOS81.getBBBFromText( bookCode ) # Try to guess if not BBB: BBB = BOSx.getBBBFromText( bookCode ) # Try to guess # Handle special formatting # [square-brackets] are for Italicized words # <angle-brackets> are for the Words of Christ in Red # «chevrons» are for the Titles in the Book of Psalms. vText = vText.replace( '[', '\\add ' ).replace( ']', '\\add*' ) \ .replace( '<', '\\wj ' ).replace( '>', '\\wj*' ) if vText and vText[0]=='«': #print( "Oh!", BBB, chapterNumberString, verseNumberString, repr(vText) ) if BBB=='PSA' and verseNumberString=='1': # Psalm title vBits = vText[1:].split( '»' ) #print( "vBits", vBits ) thisBook.addLine( 'd', vBits[0] ) # Psalm title vText = vBits[1].lstrip() # Handle the verse info #if verseNumber==lastVerseNumber and vText==lastVText: #logging.warning( _("Ignored duplicate verse line in {} {} {} {}:{}").format( self.givenName, BBB, bookCode, chapterNumberString, verseNumberString ) ) #continue if BBB=='PSA' and verseNumberString=='1' and vText.startswith('<') and self.givenName=='basic_english': # Move Psalm titles to verse zero verseNumber = 0 #if verseNumber < lastVerseNumber: #logging.warning( _("Ignored receding verse number (from {} to {}) in {} {} {} {}:{}").format( lastVerseNumber, verseNumber, self.givenName, BBB, bookCode, chapterNumberString, verseNumberString ) ) #elif verseNumber == lastVerseNumber: #if vText == lastVText: #logging.warning( _("Ignored duplicated {} verse in {} {} {} {}:{}").format( verseNumber, self.givenName, BBB, bookCode, chapterNumberString, verseNumberString ) ) #else: #logging.warning( _("Ignored duplicated {} verse number in {} {} {} {}:{}").format( verseNumber, self.givenName, BBB, bookCode, chapterNumberString, verseNumberString ) ) elif vplType in (2,3): bits = line.split( '\t', 1 ) #print( self.givenName, BBB, bits ) bookNumberString, chapterNumberString, verseNumberString = bits[0][:2], bits[0][2:5], bits[0][5:] #print( bookNumberString, chapterNumberString, verseNumberString ) while len(chapterNumberString)>1 and chapterNumberString[0]=='0': chapterNumberString = chapterNumberString[1:] # Remove leading zeroes while len(verseNumberString)>1 and verseNumberString[0]=='0': verseNumberString = verseNumberString[1:] # Remove leading zeroes bookCode, chapterNumber, verseNumber = int( bookNumberString), int(chapterNumberString), int(verseNumberString) vText = bits[1].replace(' ,',',').replace(' .','.').replace(' ;',';').replace(' :',':') \ .replace(' !','!').replace(' )',')').replace(' ]',']').replace(' ”','”') \ .replace('“ ','“').replace('( ','(').replace('[ ','[') #.replace(' !','!') if bookCode != lastBookCode: # We've started a new book bnDict = { 67:'TOB', 68:'JDT', 69:'ESG', 70:'WIS', 71:'SIR', 72:'BAR', 73:'LJE', 74:'PAZ', 75:'SUS', 76:'BEL', 77:'MA1', 78:'MA2', 79:'MA3', 80:'MA4', 81:'ES1', 82:'ES2', 83:'MAN', 84:'PS2', 85:'PSS', 86:'ODE', } if 1 <= bookCode <= 66: BBB = BibleOrgSysGlobals.BibleBooksCodes.getBBBFromReferenceNumber( bookCode ) else: BBB = bnDict[bookCode] #elif vplType == 4: #if line.startswith( '$$ ' ): #if metadataName and metadataContents: #settingsDict[metadataName] = metadataContents #metadataName = None #pointer = line[3:] ##print( "pointer", repr(pointer) ) #if pointer and pointer[0]=='{' and pointer[-1]=='}': #metadataName = pointer[1:-1] #if metadataName: ##print( "metadataName", repr(metadataName) ) #metadataContents = '' #else: # let's assume it's a BCV reference #pointer = pointer.replace( '1 K','1K' ).replace( '2 K','2K' ) \ #.replace( '1 Chr','1Chr' ).replace( '2 Chr','2Chr' ) \ #.replace( '1 Cor','1Cor' ).replace( '2 Cor','2Cor' ) \ #.replace( '1 Thess','1Thess' ).replace( '2 Thess','2Thess' ) \ #.replace( '1 Tim','1Tim' ).replace( '2 Tim','2Tim' ) \ #.replace( '1 Pet','1Pet' ).replace( '2 Pet','2Pet' ) \ #.replace( '1 J','1J' ).replace( '2 J','2J' ).replace( '3 J','3J' ) #B_CV_Bits = pointer.split( ' ', 1 ) #if len(B_CV_Bits) == 2 and ':' in B_CV_Bits[1]: #bookCode, CVString = B_CV_Bits #chapterNumberString, verseNumberString = CVString.split( ':' ) #chapterNumber = int( chapterNumberString ) #verseNumber = int( verseNumberString ) #if bookCode != lastBookCode: # We've started a new book #if bookCode in ('Ge',): BBB = 'GEN' #elif bookCode in ('Le',): BBB = 'LEV' #elif bookCode in ('La',): BBB = 'LAM' #else: ##print( "4BookCode =", repr(bookCode) ) ##BBB = BOS.getBBBFromText( bookCode ) # Try to guess #BBB = BOS66.getBBBFromText( bookCode ) # Try to guess #if not BBB: BBB = BOS81.getBBBFromText( bookCode ) # Try to guess #if not BBB: BBB = BOSx.getBBBFromText( bookCode ) # Try to guess ##print( "4BBB =", repr(BBB) ) #else: print( "Unexpected number of bits", self.givenName, BBB, bookCode, chapterNumberString, verseNumberString, len(bits), bits ) #continue # Just save the pointer information which refers to the text on the next line #else: # it's not a $$ line #text = line ##print( "text", repr(text) ) #if metadataName: #metadataContents += ('\n' if metadataContents else '') + text #continue #else: #vText = text ## Handle bits like (<scripref>Pr 2:7</scripref>) #vText = vText.replace( '(<scripref>', '\\x - \\xt ' ).replace( '</scripref>)', '\\x*' ) #vText = vText.replace( '<scripref>', '\\x - \\xt ' ).replace( '</scripref>', '\\x*' ) ##if '\\' in vText: print( 'VPL vText', repr(vText) ) #if vplType == 4: # Forge for SwordSearcher ##print( BBB, chapterNumber, verseNumber, repr(vText) ) ## Convert {stuff} to footnotes #match = re.search( '\\{(.+?)\\}', vText ) #while match: #footnoteText = '\\f + \\fr {}:{} \\ft {}\\f*'.format( chapterNumber, verseNumber, match.group(1) ) #vText = vText[:match.start()] + footnoteText + vText[match.end():] # Replace this footnote ##print( BBB, chapterNumber, verseNumber, repr(vText) ) #match = re.search( '\\{(.+?)\\}', vText ) ## Convert [stuff] to added fields #match = re.search( '\\[(.+?)\\]', vText ) #while match: #addText = '\\add {}\\add*'.format( match.group(1) ) #vText = vText[:match.start()] + addText + vText[match.end():] # Replace this chunk ##print( BBB, chapterNumber, verseNumber, repr(vText) ) #match = re.search( '\\[(.+?)\\]', vText ) #for badChar in '{}[]': #if badChar in vText: #logging.warning( "Found remaining braces or brackets in SwordSearcher Forge VPL {} {}:{} {!r}".format( BBB, chapterNumberString, verseNumberString, vText ) ) #break else: logging.critical( 'Unknown VPL type {}'.format( vplType ) ) if BibleOrgSysGlobals.debugFlag and debuggingThisModule: halt if bookCode: if bookCode != lastBookCode: # We've started a new book if lastBookCode != -1: # Better save the last book self.stashBook( thisBook ) if BBB: if BBB in self: logging.critical( "Have duplicated {} book in {}".format( self.givenName, BBB ) ) if BibleOrgSysGlobals.debugFlag: assert BBB not in self thisBook = BibleBook( self, BBB ) thisBook.objectNameString = 'VPL Bible Book object' thisBook.objectTypeString = 'VPL' verseList = BOSx.getNumVersesList( BBB ) numChapters, numVerses = len(verseList), verseList[0] lastBookCode = bookCode lastChapterNumber = lastVerseNumber = -1 else: logging.critical( "VPLBible{} could not figure out {!r} book code".format( vplType, bookCode ) ) if BibleOrgSysGlobals.debugFlag: halt if BBB: if chapterNumber != lastChapterNumber: # We've started a new chapter if BibleOrgSysGlobals.debugFlag: assert chapterNumber > lastChapterNumber or BBB=='ESG' # Esther Greek might be an exception if chapterNumber == 0: logging.info( "Have chapter zero in {} {} {} {}:{}".format( self.givenName, BBB, bookCode, chapterNumberString, verseNumberString ) ) elif chapterNumber > numChapters: logging.error( "Have high chapter number in {} {} {} {}:{} (expected max of {})".format( self.givenName, BBB, bookCode, chapterNumberString, verseNumberString, numChapters ) ) thisBook.addLine( 'c', chapterNumberString ) lastChapterNumber = chapterNumber lastVerseNumber = -1 # Handle the verse info if verseNumber==lastVerseNumber and vText==lastVText: logging.warning( _("Ignored duplicate verse line in {} {} {} {}:{}").format( self.givenName, BBB, bookCode, chapterNumberString, verseNumberString ) ) continue if verseNumber < lastVerseNumber: logging.warning( _("Ignored receding verse number (from {} to {}) in {} {} {} {}:{}").format( lastVerseNumber, verseNumber, self.givenName, BBB, bookCode, chapterNumberString, verseNumberString ) ) elif verseNumber == lastVerseNumber: if vText == lastVText: logging.warning( _("Ignored duplicated {} verse in {} {} {} {}:{}").format( verseNumber, self.givenName, BBB, bookCode, chapterNumberString, verseNumberString ) ) else: logging.warning( _("Ignored duplicated {} verse number in {} {} {} {}:{}").format( verseNumber, self.givenName, BBB, bookCode, chapterNumberString, verseNumberString ) ) # Check for paragraph markers if vText and vText[0]=='¶': thisBook.addLine( 'p', '' ) vText = vText[1:].lstrip() #print( '{} {}:{} = {!r}'.format( BBB, chapterNumberString, verseNumberString, vText ) ) thisBook.addLine( 'v', verseNumberString + ' ' + vText ) lastVText = vText lastVerseNumber = verseNumber else: # No bookCode yet logging.warning( "VPLBible.load{} is skipping unknown pre-book line: {}".format( vplType, line ) ) # Save the final book if thisBook is not None: self.stashBook( thisBook ) # Clean up if settingsDict: #print( "VPL settingsDict", settingsDict ) if self.suppliedMetadata is None: self.suppliedMetadata = {} self.suppliedMetadata['VPL'] = settingsDict self.applySuppliedMetadata( 'VPL' ) # Copy some to self.settingsDict self.doPostLoadProcessing()
def load( self ): """ Load a single source file and load book elements. """ if BibleOrgSysGlobals.verbosityLevel > 2: print( _("Loading {}…").format( self.sourceFilepath ) ) global BOS66, BOS81, BOSx if BOS66 is None: BOS66 = BibleOrganizationalSystem( 'GENERIC-KJV-66-ENG' ) if BOS81 is None: BOS81 = BibleOrganizationalSystem( 'GENERIC-KJV-81-ENG' ) if BOSx is None: BOSx = BibleOrganizationalSystem( 'GENERIC-ENG' ) if self.suppliedMetadata is None: self.suppliedMetadata = {} lastLine, lineCount = '', 0 bookCode = BBB = metadataName = None lastBookCode = lastChapterNumber = lastVerseNumber = -1 lastVText = '' thisBook = None settingsDict = {} with open( self.sourceFilepath, encoding=self.encoding ) as myFile: # Automatically closes the file when done for line in myFile: lineCount += 1 if line[-1]=='\n': line=line[:-1] # Removing trailing newline character if not line: continue # Just discard blank lines if lineCount==1: if self.encoding.lower()=='utf-8' and line[0]==chr(65279): #U+FEFF or \ufeff logging.info( " ForgeForSwordSearcherBible.load: Detected Unicode Byte Order Marker (BOM)" ) line = line[1:] # Remove the Unicode Byte Order Marker (BOM) match = re.search( '^; TITLE:\\s', line ) if match: if BibleOrgSysGlobals.debugFlag: print( "First line got type {!r} match from {!r}".format( match.group(0), line ) ) else: if BibleOrgSysGlobals.verbosityLevel > 2: print( "ForgeForSwordSearcherBible.load: (unexpected) first line was {!r} in {}".format( firstLine, thisFilename ) ) if BibleOrgSysGlobals.debugFlag and debuggingThisModule: halt continue #print ( 'ForgeForSwordSearcher file line is "' + line + '"' ) lastLine = line # Process header stuff if line.startswith( '; TITLE:' ): string = line[8:].strip() if string: settingsDict['TITLE'] = string continue elif line.startswith( '; ABBREVIATION:' ): string = line[15:].strip() if string: settingsDict['ABBREVIATION'] = string continue elif line.startswith( '; HAS ITALICS' ): string = line[14:].strip() if string: settingsDict['HAS_ITALICS'] = string continue elif line.startswith( '; HAS FOOTNOTES:' ): string = line[15:].strip() if string: settingsDict['HAS_FOOTNOTES'] = string continue elif line.startswith( '; HAS FOOTNOTES' ): string = line[14:].strip() if string: settingsDict['HAS_FOOTNOTES'] = string continue elif line.startswith( '; HAS REDLETTER' ): string = line[14:].strip() if string: settingsDict['HAS_REDLETTER'] = string continue elif line[0]==';': logging.warning( "ForgeForSwordSearcherBible.load is skipping unknown header/comment line: {}".format( line ) ) continue # Just discard comment lines # Process the main segment if line.startswith( '$$ ' ): if metadataName and metadataContents: settingsDict[metadataName] = metadataContents metadataName = None pointer = line[3:] #print( "pointer", repr(pointer) ) if pointer and pointer[0]=='{' and pointer[-1]=='}': metadataName = pointer[1:-1] if metadataName: #print( "metadataName", repr(metadataName) ) metadataContents = '' else: # let's assume it's a BCV reference pointer = pointer.replace( '1 K','1K' ).replace( '2 K','2K' ) \ .replace( '1 Chr','1Chr' ).replace( '2 Chr','2Chr' ) \ .replace( '1 Cor','1Cor' ).replace( '2 Cor','2Cor' ) \ .replace( '1 Thess','1Thess' ).replace( '2 Thess','2Thess' ) \ .replace( '1 Tim','1Tim' ).replace( '2 Tim','2Tim' ) \ .replace( '1 Pet','1Pet' ).replace( '2 Pet','2Pet' ) \ .replace( '1 J','1J' ).replace( '2 J','2J' ).replace( '3 J','3J' ) B_CV_Bits = pointer.split( ' ', 1 ) if len(B_CV_Bits) == 2 and ':' in B_CV_Bits[1]: bookCode, CVString = B_CV_Bits chapterNumberString, verseNumberString = CVString.split( ':' ) chapterNumber = int( chapterNumberString ) verseNumber = int( verseNumberString ) if bookCode != lastBookCode: # We've started a new book if bookCode in ('Ge',): BBB = 'GEN' elif bookCode in ('Le',): BBB = 'LEV' elif bookCode in ('La',): BBB = 'LAM' ##elif bookCode in ('Es',): BBB = 'EST' ##elif bookCode in ('Pr',): BBB = 'PRO' #elif bookCode in ('So',): BBB = 'SNG' #elif bookCode in ('La',): BBB = 'LAM' #elif bookCode in ('Jude',): BBB = 'JDE' else: #print( "4BookCode =", repr(bookCode) ) #BBB = BOS.getBBBFromText( bookCode ) # Try to guess BBB = BOS66.getBBBFromText( bookCode ) # Try to guess if not BBB: BBB = BOS81.getBBBFromText( bookCode ) # Try to guess if not BBB: BBB = BOSx.getBBBFromText( bookCode ) # Try to guess #print( "4BBB =", repr(BBB) ) else: print( "Unexpected number of bits", self.givenName, BBB, bookCode, chapterNumberString, verseNumberString, len(bits), bits ) continue # Just save the pointer information which refers to the text on the next line else: # it's not a $$ line text = line #print( "text", repr(text) ) if metadataName: metadataContents += ('\n' if metadataContents else '') + text continue else: vText = text # Handle bits like (<scripref>Pr 2:7</scripref>) vText = vText.replace( '(<scripref>', '\\x - \\xt ' ).replace( '</scripref>)', '\\x*' ) vText = vText.replace( '<scripref>', '\\x - \\xt ' ).replace( '</scripref>', '\\x*' ) #if '\\' in vText: print( 'ForgeForSwordSearcher vText', repr(vText) ) #print( BBB, chapterNumber, verseNumber, repr(vText) ) # Convert {stuff} to footnotes match = re.search( '\\{(.+?)\\}', vText ) while match: footnoteText = '\\f + \\fr {}:{} \\ft {}\\f*'.format( chapterNumber, verseNumber, match.group(1) ) vText = vText[:match.start()] + footnoteText + vText[match.end():] # Replace this footnote #print( BBB, chapterNumber, verseNumber, repr(vText) ) match = re.search( '\\{(.+?)\\}', vText ) # Convert [stuff] to added fields match = re.search( '\\[(.+?)\\]', vText ) while match: addText = '\\add {}\\add*'.format( match.group(1) ) vText = vText[:match.start()] + addText + vText[match.end():] # Replace this chunk #print( BBB, chapterNumber, verseNumber, repr(vText) ) match = re.search( '\\[(.+?)\\]', vText ) # Convert +r/This text is red-letter-r/ to wj fields match = re.search( '\\+r/(.+?)-r/', vText ) while match: addText = '\\wj {}\\wj*'.format( match.group(1) ) vText = vText[:match.start()] + addText + vText[match.end():] # Replace this chunk #print( BBB, chapterNumber, verseNumber, repr(vText) ) match = re.search( '\\+r/(.+?)-r/', vText ) # Final check for unexpected remaining formatting for badChar in '{}[]/': if badChar in vText: logging.warning( "Found remaining braces,brackets or slashes in SwordSearcher Forge VPL {} {}:{} {!r}".format( BBB, chapterNumberString, verseNumberString, vText ) ) break if bookCode: if bookCode != lastBookCode: # We've started a new book if lastBookCode != -1: # Better save the last book self.stashBook( thisBook ) if BBB: if BBB in self: logging.critical( "Have duplicated {} book in {}".format( self.givenName, BBB ) ) if BibleOrgSysGlobals.debugFlag: assert BBB not in self thisBook = BibleBook( self, BBB ) thisBook.objectNameString = 'ForgeForSwordSearcher Bible Book object' thisBook.objectTypeString = 'ForgeForSwordSearcher' verseList = BOSx.getNumVersesList( BBB ) numChapters, numVerses = len(verseList), verseList[0] lastBookCode = bookCode lastChapterNumber = lastVerseNumber = -1 else: logging.critical( "ForgeForSwordSearcherBible could not figure out {!r} book code".format( bookCode ) ) if BibleOrgSysGlobals.debugFlag: halt if BBB: if chapterNumber != lastChapterNumber: # We've started a new chapter if BibleOrgSysGlobals.debugFlag: assert chapterNumber > lastChapterNumber or BBB=='ESG' # Esther Greek might be an exception if chapterNumber == 0: logging.info( "Have chapter zero in {} {} {} {}:{}".format( self.givenName, BBB, bookCode, chapterNumberString, verseNumberString ) ) elif chapterNumber > numChapters: logging.error( "Have high chapter number in {} {} {} {}:{} (expected max of {})".format( self.givenName, BBB, bookCode, chapterNumberString, verseNumberString, numChapters ) ) thisBook.addLine( 'c', chapterNumberString ) lastChapterNumber = chapterNumber lastVerseNumber = -1 # Handle the verse info if verseNumber==lastVerseNumber and vText==lastVText: logging.warning( _("Ignored duplicate verse line in {} {} {} {}:{}").format( self.givenName, BBB, bookCode, chapterNumberString, verseNumberString ) ) continue if verseNumber < lastVerseNumber: logging.warning( _("Ignored receding verse number (from {} to {}) in {} {} {} {}:{}").format( lastVerseNumber, verseNumber, self.givenName, BBB, bookCode, chapterNumberString, verseNumberString ) ) elif verseNumber == lastVerseNumber: if vText == lastVText: logging.warning( _("Ignored duplicated {} verse in {} {} {} {}:{}").format( verseNumber, self.givenName, BBB, bookCode, chapterNumberString, verseNumberString ) ) else: logging.warning( _("Ignored duplicated {} verse number in {} {} {} {}:{}").format( verseNumber, self.givenName, BBB, bookCode, chapterNumberString, verseNumberString ) ) # Check for paragraph markers if vText and vText[0]=='¶': thisBook.addLine( 'p', '' ) vText = vText[1:].lstrip() #print( '{} {}:{} = {!r}'.format( BBB, chapterNumberString, verseNumberString, vText ) ) thisBook.addLine( 'v', verseNumberString + ' ' + vText ) lastVText = vText lastVerseNumber = verseNumber else: # No bookCode yet logging.warning( "ForgeForSwordSearcherBible.load is skipping unknown pre-book line: {}".format( line ) ) # Save the final book if thisBook is not None: self.stashBook( thisBook ) # Clean up if settingsDict: #print( "ForgeForSwordSearcher settingsDict", settingsDict ) if self.suppliedMetadata is None: self.suppliedMetadata = {} self.suppliedMetadata['Forge4SS'] = settingsDict self.applySuppliedMetadata( 'Forge4SS' ) # Copy some to self.settingsDict self.doPostLoadProcessing()
class OpenSongXMLBible(Bible): """ Class for reading, validating, and converting OpenSong Bible XML. """ treeTag = 'bible' bookTag = 'b' chapterTag = 'c' verseTag = 'v' def __init__(self, sourceFolder, givenName, encoding='utf-8'): """ Constructor: just sets up the XML Bible file converter object. """ # Setup and initialise the base class first if Globals.debugFlag: print("OpenSongXMLBible( {}, {}, {} )".format( sourceFolder, givenName, encoding)) Bible.__init__(self) self.objectNameString = "OpenSong XML Bible object" self.objectTypeString = "OpenSong" # Now we can set our object variables self.sourceFolder, self.givenName, self.encoding = sourceFolder, givenName, encoding self.sourceFilepath = os.path.join(self.sourceFolder, self.givenName) self.tree = None # Will hold the XML data # Get the data tables that we need for proper checking #self.ISOLanguages = ISO_639_3_Languages().loadData() self.genericBOS = BibleOrganizationalSystem("GENERIC-KJV-66-ENG") # Do a preliminary check on the readability of our file if not os.access(self.sourceFilepath, os.R_OK): print("OpenSongXMLBible: File '{}' is unreadable".format( self.sourceFilepath)) self.name = self.givenName #if self.name is None: #pass # end of OpenSongXMLBible.__init__ def load(self): """ Load a single source XML file and load book elements. """ if Globals.verbosityLevel > 2: print(_("Loading {}...").format(self.sourceFilepath)) self.tree = ElementTree().parse(self.sourceFilepath) if Globals.debugFlag: assert (len(self.tree) ) # Fail here if we didn't load anything at all # Find the main (bible) container if self.tree.tag == OpenSongXMLBible.treeTag: location = "XML file" Globals.checkXMLNoText(self.tree, location, '4f6h') Globals.checkXMLNoTail(self.tree, location, '1wk8') name = shortName = None for attrib, value in self.tree.items(): if attrib == "n": name = value elif attrib == "sn": shortName = value else: logging.warning( "Unprocessed '{}' attribute ({}) in main element". format(attrib, value)) # Find the submain (book) containers for element in self.tree: if element.tag == OpenSongXMLBible.bookTag: sublocation = "book in " + location Globals.checkXMLNoText(element, sublocation, 'g3g5') Globals.checkXMLNoTail(element, sublocation, 'd3f6') self.__validateAndExtractBook(element) elif element.tag == 'OT': pass elif element.tag == 'NT': pass else: logging.error("Expected to find '{}' but got '{}'".format( OpenSongXMLBible.bookTag, element.tag)) else: logging.error("Expected to load '{}' but got '{}'".format( OpenSongXMLBible.treeTag, self.tree.tag)) # end of OpenSongXMLBible.load def __validateAndExtractBook(self, book): """ Check/validate and extract book data from the given XML book record finding chapter subelements. """ if Globals.verbosityLevel > 3: print(_("Validating OpenSong XML book...")) # Process the div attributes first BBB = bookName = None for attrib, value in book.items(): if attrib == "n": bookName = value else: logging.warning( "Unprocessed '{}' attribute ({}) in book element".format( attrib, value)) if bookName: BBB = self.genericBOS.getBBB(bookName) if BBB: if Globals.verbosityLevel > 2: print(_("Validating {} {}...").format(BBB, bookName)) thisBook = BibleBook(self.name, BBB) thisBook.objectNameString = "OpenSong XML Bible Book object" thisBook.objectTypeString = "OpenSong" #thisBook.sourceFilepath = self.sourceFilepath for element in book: if element.tag == OpenSongXMLBible.chapterTag: sublocation = "chapter in {}".format(BBB) Globals.checkXMLNoText(element, sublocation, 'j3jd') Globals.checkXMLNoTail(element, sublocation, 'al1d') self.__validateAndExtractChapter( BBB, thisBook, element) else: logging.error( "Expected to find '{}' but got '{}'".format( OpenSongXMLBible.chapterTag, element.tag)) if Globals.verbosityLevel > 2: print(" Saving {} into results...".format(BBB)) self.saveBook(thisBook) logging.error( _("OpenSong load doesn't recognize book name: '{}'").format( bookName)) logging.error(_("OpenSong load can't find a book name")) # end of OpenSongXMLBible.__validateAndExtractBook def __validateAndExtractChapter(self, BBB, thisBook, chapter): """ Check/validate and extract chapter data from the given XML book record finding and saving chapter numbers and finding and saving verse elements. """ if Globals.verbosityLevel > 3: print(_("Validating XML chapter...")) # Process the div attributes first chapterNumber = numVerses = None for attrib, value in chapter.items(): if attrib == "n": chapterNumber = value elif attrib == "VERSES": numVerses = value else: logging.warning( "Unprocessed '{}' attribute ({}) in chapter element". format(attrib, value)) if chapterNumber: #print( BBB, 'c', chapterNumber ) chapterNumber = chapterNumber.replace( 'of Solomon ', '') # Fix a mistake in the Chinese_SU module thisBook.appendLine('c', chapterNumber) else: logging.error( "Missing 'n' attribute in chapter element for BBB".format(BBB)) for element in chapter: if element.tag == OpenSongXMLBible.verseTag: sublocation = "verse in {} {}".format(BBB, chapterNumber) Globals.checkXMLNoTail(element, sublocation, 'l5ks') Globals.checkXMLNoSubelements(element, sublocation, '5f7h') verseNumber = toVerseNumber = None for attrib, value in element.items(): if attrib == "n": verseNumber = value elif attrib == "t": toVerseNumber = value else: logging.warning( "Unprocessed '{}' attribute ({}) in verse element". format(attrib, value)) if Globals.debugFlag: assert (verseNumber) #thisBook.appendLine( 'v', verseNumber ) vText = element.text if not vText: logging.warning("{} {}:{} has no text".format( BBB, chapterNumber, verseNumber)) if vText: # This is the main text of the verse (follows the verse milestone) #print( "{} {}:{} '{}'".format( BBB, chapterNumber, verseNumber, vText ) ) if '\n' in vText: # This is how they represent poety #print( "vText", repr(vText), repr(element.text) ) for j, textBit in enumerate(vText.split('\n')): if j == 0: thisBook.appendLine('q1', '') thisBook.appendLine( 'v', verseNumber + ' ' + textBit) else: thisBook.appendLine('q1', textBit) else: # Just one verse line thisBook.appendLine('v', verseNumber + ' ' + vText) else: logging.error("Expected to find '{}' but got '{}'".format( OpenSongXMLBible.verseTag, element.tag))
def createMySwordModule(self, outputFolder, controlDict): """ Create a SQLite3 database module for the program MySword. self here is a Bible object with _processedLines """ import tarfile from InternalBibleInternals import BOS_ADDED_NESTING_MARKERS, BOS_NESTING_MARKERS from theWordBible import theWordOTBookLines, theWordNTBookLines, theWordBookLines, theWordHandleIntroduction, theWordComposeVerseLine def writeMSBook(sqlObject, BBB, ourGlobals): """ Writes a book to the MySword sqlObject file. """ nonlocal lineCount bkData = self.books[BBB] if BBB in self.books else None #print( bkData._processedLines ) verseList = BOS.getNumVersesList(BBB) nBBB = BibleOrgSysGlobals.BibleBooksCodes.getReferenceNumber(BBB) numC, numV = len(verseList), verseList[0] ourGlobals['line'], ourGlobals['lastLine'] = '', None ourGlobals['pi1'] = ourGlobals['pi2'] = ourGlobals['pi3'] = ourGlobals[ 'pi4'] = ourGlobals['pi5'] = ourGlobals['pi6'] = ourGlobals[ 'pi7'] = False if bkData: # Write book headings (stuff before chapter 1) ourGlobals['line'] = theWordHandleIntroduction( BBB, bkData, ourGlobals) # Write the verses C = V = 1 ourGlobals['lastLine'] = ourGlobals['lastBCV'] = None while True: verseData = None if bkData: try: result = bkData.getContextVerseData(( BBB, str(C), str(V), )) verseData, context = result except KeyError: # Missing verses logging.warning( "BibleWriter.toMySword: missing source verse at {} {}:{}" .format(BBB, C, V)) # Handle some common versification anomalies if (BBB, C, V) == ('JN3', 1, 14): # Add text for v15 if it exists try: result15 = bkData.getContextVerseData(( 'JN3', '1', '15', )) verseData15, context15 = result15 verseData.extend(verseData15) except KeyError: pass # just ignore it elif (BBB, C, V) == ('REV', 12, 17): # Add text for v15 if it exists try: result18 = bkData.getContextVerseData(( 'REV', '12', '18', )) verseData18, context18 = result18 verseData.extend(verseData18) except KeyError: pass # just ignore it composedLine = '' if verseData: composedLine = theWordComposeVerseLine( BBB, C, V, verseData, ourGlobals) # Stay one line behind (because paragraph indicators get appended to the previous line) if ourGlobals['lastBCV'] is not None \ and ourGlobals['lastLine']: # don't bother writing blank (unfinished?) verses sqlObject.execute( 'INSERT INTO "Bible" VALUES(?,?,?,?)', \ (ourGlobals['lastBCV'][0],ourGlobals['lastBCV'][1],ourGlobals['lastBCV'][2],ourGlobals['lastLine']) ) lineCount += 1 ourGlobals['lastLine'] = composedLine ourGlobals['lastBCV'] = (nBBB, C, V) V += 1 if V > numV: C += 1 if C > numC: break else: # next chapter only numV = verseList[C - 1] V = 1 #assert not ourGlobals['line'] and not ourGlobals['lastLine'] # We should have written everything # Write the last line of the file if ourGlobals[ 'lastLine']: # don't bother writing blank (unfinished?) verses sqlObject.execute( 'INSERT INTO "Bible" VALUES(?,?,?,?)', \ (ourGlobals['lastBCV'][0],ourGlobals['lastBCV'][1],ourGlobals['lastBCV'][2],ourGlobals['lastLine']) ) lineCount += 1 # end of toMySword.writeMSBook # Set-up their Bible reference system BOS = BibleOrganizationalSystem('GENERIC-KJV-66-ENG') #BRL = BibleReferenceList( BOS, BibleObject=None ) # Try to figure out if it's an OT/NT or what (allow for up to 4 extra books like FRT,GLS, etc.) if len(self) <= (39 + 4) and self.containsAnyOT39Books( ) and not self.containsAnyNT27Books(): testament, startBBB, endBBB = 'OT', 'GEN', 'MAL' booksExpected, textLineCountExpected, checkTotals = 39, 23145, theWordOTBookLines elif len(self) <= (27 + 4) and self.containsAnyNT27Books( ) and not self.containsAnyOT39Books(): testament, startBBB, endBBB = 'NT', 'MAT', 'REV' booksExpected, textLineCountExpected, checkTotals = 27, 7957, theWordNTBookLines else: # assume it's an entire Bible testament, startBBB, endBBB = 'BOTH', 'GEN', 'REV' booksExpected, textLineCountExpected, checkTotals = 66, 31102, theWordBookLines extension = '.bbl.mybible' if BibleOrgSysGlobals.verbosityLevel > 2: print(_(" Exporting to MySword format…")) mySettings = {} mySettings['unhandledMarkers'] = set() handledBooks = [] if 'MySwordOutputFilename' in controlDict: filename = controlDict['MySwordOutputFilename'] elif self.sourceFilename: filename = self.sourceFilename elif self.shortName: filename = self.shortName elif self.abbreviation: filename = self.abbreviation elif self.name: filename = self.name else: filename = 'export' if not filename.endswith(extension): filename += extension # Make sure that we have the right file extension filepath = os.path.join(outputFolder, BibleOrgSysGlobals.makeSafeFilename(filename)) if os.path.exists(filepath): os.remove(filepath) if BibleOrgSysGlobals.verbosityLevel > 2: print(" " + _("Writing {!r}…").format(filepath)) conn = sqlite3.connect(filepath) cursor = conn.cursor() # First write the settings Details table exeStr = 'CREATE TABLE Details(Description NVARCHAR(255), Abbreviation NVARCHAR(50), Comments TEXT, Version TEXT, VersionDate DATETIME, PublishDate DATETIME, RightToLeft BOOL, OT BOOL, NT BOOL, Strong BOOL' # incomplete customCSS = self.getSetting('CustomCSS') if customCSS: exeStr += ', CustomCSS TEXT' exeStr += ')' cursor.execute(exeStr) values = [] description = self.getSetting('Description') if not description: description = self.getSetting('description') if not description: description = self.name values.append(description) if self.abbreviation: abbreviation = self.abbreviation else: abbreviation = self.getSetting('WorkAbbreviation') if not abbreviation: abbreviation = self.name[:3].upper() values.append(abbreviation) comments = self.getSetting('Comments') values.append(comments) version = self.getSetting('Version') values.append(version) versionDate = self.getSetting('VersionDate') values.append(versionDate) publishDate = self.getSetting('PublishDate') values.append(publishDate) rightToLeft = self.getSetting('RightToLeft') values.append(rightToLeft) values.append(True if testament == 'OT' or testament == 'BOTH' else False) values.append(True if testament == 'NT' or testament == 'BOTH' else False) Strong = self.getSetting('Strong') values.append(Strong if Strong else False) if customCSS: values.append(customCSS) exeStr = 'INSERT INTO "Details" VALUES(' + '?,' * (len(values) - 1) + '?)' #print( exeStr, values ) cursor.execute(exeStr, values) #if BibleOrgSysGlobals.debugFlag: cursor.execute( exeStr, values ) #else: # Not debugging #try: cursor.execute( exeStr, values ) #except sqlite3.InterfaceError: #logging.critical( "SQLite3 Interface error executing {} with {}".format( exeStr, values ) ) # Now create and fill the Bible table cursor.execute( 'CREATE TABLE Bible(Book INT, Chapter INT, Verse INT, Scripture TEXT, Primary Key(Book,Chapter,Verse))' ) conn.commit() # save (commit) the changes BBB, lineCount = startBBB, 0 while True: # Write each Bible book in the KJV order writeMSBook(cursor, BBB, mySettings) conn.commit() # save (commit) the changes handledBooks.append(BBB) if BBB == endBBB: break BBB = BOS.getNextBookCode(BBB) conn.commit() # save (commit) the changes cursor.close() if mySettings['unhandledMarkers']: logging.warning( "BibleWriter.toMySword: Unhandled markers were {}".format( mySettings['unhandledMarkers'])) if BibleOrgSysGlobals.verbosityLevel > 1: print(" " + _("WARNING: Unhandled toMySword markers were {}").format( mySettings['unhandledMarkers'])) unhandledBooks = [] for BBB in self.getBookList(): if BBB not in handledBooks: unhandledBooks.append(BBB) if unhandledBooks: logging.warning( "toMySword: Unhandled books were {}".format(unhandledBooks)) if BibleOrgSysGlobals.verbosityLevel > 1: print(" " + _("WARNING: Unhandled toMySword books were {}").format( unhandledBooks)) # Now create the gzipped file if BibleOrgSysGlobals.verbosityLevel > 2: print(" Compressing {} MySword file…".format(filename)) tar = tarfile.open(filepath + '.gz', 'w:gz') tar.add(filepath) tar.close() if BibleOrgSysGlobals.verbosityLevel > 0 and BibleOrgSysGlobals.maxProcesses > 1: print(" BibleWriter.toMySword finished successfully.") return True
def createMySwordModule( self, outputFolder, controlDict ): """ Create a SQLite3 database module for the program MySword. self here is a Bible object with _processedLines """ import tarfile from InternalBibleInternals import BOS_ADDED_NESTING_MARKERS, BOS_NESTING_MARKERS from theWordBible import theWordOTBookLines, theWordNTBookLines, theWordBookLines, theWordHandleIntroduction, theWordComposeVerseLine def writeMSBook( sqlObject, BBB, ourGlobals ): """ Writes a book to the MySword sqlObject file. """ nonlocal lineCount bkData = self.books[BBB] if BBB in self.books else None #print( bkData._processedLines ) verseList = BOS.getNumVersesList( BBB ) nBBB = BibleOrgSysGlobals.BibleBooksCodes.getReferenceNumber( BBB ) numC, numV = len(verseList), verseList[0] ourGlobals['line'], ourGlobals['lastLine'] = '', None ourGlobals['pi1'] = ourGlobals['pi2'] = ourGlobals['pi3'] = ourGlobals['pi4'] = ourGlobals['pi5'] = ourGlobals['pi6'] = ourGlobals['pi7'] = False if bkData: # Write book headings (stuff before chapter 1) ourGlobals['line'] = theWordHandleIntroduction( BBB, bkData, ourGlobals ) # Write the verses C = V = 1 ourGlobals['lastLine'] = ourGlobals['lastBCV'] = None while True: verseData = None if bkData: try: result = bkData.getContextVerseData( (BBB,str(C),str(V),) ) verseData, context = result except KeyError: # Missing verses logging.warning( "BibleWriter.toMySword: missing source verse at {} {}:{}".format( BBB, C, V ) ) # Handle some common versification anomalies if (BBB,C,V) == ('JN3',1,14): # Add text for v15 if it exists try: result15 = bkData.getContextVerseData( ('JN3','1','15',) ) verseData15, context15 = result15 verseData.extend( verseData15 ) except KeyError: pass # just ignore it elif (BBB,C,V) == ('REV',12,17): # Add text for v15 if it exists try: result18 = bkData.getContextVerseData( ('REV','12','18',) ) verseData18, context18 = result18 verseData.extend( verseData18 ) except KeyError: pass # just ignore it composedLine = '' if verseData: composedLine = theWordComposeVerseLine( BBB, C, V, verseData, ourGlobals ) # Stay one line behind (because paragraph indicators get appended to the previous line) if ourGlobals['lastBCV'] is not None \ and ourGlobals['lastLine']: # don't bother writing blank (unfinished?) verses sqlObject.execute( 'INSERT INTO "Bible" VALUES(?,?,?,?)', \ (ourGlobals['lastBCV'][0],ourGlobals['lastBCV'][1],ourGlobals['lastBCV'][2],ourGlobals['lastLine']) ) lineCount += 1 ourGlobals['lastLine'] = composedLine ourGlobals['lastBCV'] = (nBBB,C,V) V += 1 if V > numV: C += 1 if C > numC: break else: # next chapter only numV = verseList[C-1] V = 1 #assert not ourGlobals['line'] and not ourGlobals['lastLine'] # We should have written everything # Write the last line of the file if ourGlobals['lastLine']: # don't bother writing blank (unfinished?) verses sqlObject.execute( 'INSERT INTO "Bible" VALUES(?,?,?,?)', \ (ourGlobals['lastBCV'][0],ourGlobals['lastBCV'][1],ourGlobals['lastBCV'][2],ourGlobals['lastLine']) ) lineCount += 1 # end of toMySword.writeMSBook # Set-up their Bible reference system BOS = BibleOrganizationalSystem( 'GENERIC-KJV-66-ENG' ) #BRL = BibleReferenceList( BOS, BibleObject=None ) # Try to figure out if it's an OT/NT or what (allow for up to 4 extra books like FRT,GLS, etc.) if len(self) <= (39+4) and self.containsAnyOT39Books() and not self.containsAnyNT27Books(): testament, startBBB, endBBB = 'OT', 'GEN', 'MAL' booksExpected, textLineCountExpected, checkTotals = 39, 23145, theWordOTBookLines elif len(self) <= (27+4) and self.containsAnyNT27Books() and not self.containsAnyOT39Books(): testament, startBBB, endBBB = 'NT', 'MAT', 'REV' booksExpected, textLineCountExpected, checkTotals = 27, 7957, theWordNTBookLines else: # assume it's an entire Bible testament, startBBB, endBBB = 'BOTH', 'GEN', 'REV' booksExpected, textLineCountExpected, checkTotals = 66, 31102, theWordBookLines extension = '.bbl.mybible' if BibleOrgSysGlobals.verbosityLevel > 2: print( _(" Exporting to MySword format…") ) mySettings = {} mySettings['unhandledMarkers'] = set() handledBooks = [] if 'MySwordOutputFilename' in controlDict: filename = controlDict['MySwordOutputFilename'] elif self.sourceFilename: filename = self.sourceFilename elif self.shortName: filename = self.shortName elif self.abbreviation: filename = self.abbreviation elif self.name: filename = self.name else: filename = 'export' if not filename.endswith( extension ): filename += extension # Make sure that we have the right file extension filepath = os.path.join( outputFolder, BibleOrgSysGlobals.makeSafeFilename( filename ) ) if os.path.exists( filepath ): os.remove( filepath ) if BibleOrgSysGlobals.verbosityLevel > 2: print( " " + _("Writing {!r}…").format( filepath ) ) conn = sqlite3.connect( filepath ) cursor = conn.cursor() # First write the settings Details table exeStr = 'CREATE TABLE Details(Description NVARCHAR(255), Abbreviation NVARCHAR(50), Comments TEXT, Version TEXT, VersionDate DATETIME, PublishDate DATETIME, RightToLeft BOOL, OT BOOL, NT BOOL, Strong BOOL' # incomplete customCSS = self.getSetting( 'CustomCSS' ) if customCSS: exeStr += ', CustomCSS TEXT' exeStr += ')' cursor.execute( exeStr ) values = [] description = self.getSetting( 'Description' ) if not description: description = self.getSetting( 'description' ) if not description: description = self.name values.append( description ) if self.abbreviation: abbreviation = self.abbreviation else: abbreviation = self.getSetting( 'WorkAbbreviation' ) if not abbreviation: abbreviation = self.name[:3].upper() values.append( abbreviation ) comments = self.getSetting( 'Comments' ) values.append( comments ) version = self.getSetting( 'Version' ) values.append( version ) versionDate = self.getSetting( 'VersionDate' ) values.append( versionDate ) publishDate = self.getSetting( 'PublishDate' ) values.append( publishDate ) rightToLeft = self.getSetting( 'RightToLeft' ) values.append( rightToLeft ) values.append( True if testament=='OT' or testament=='BOTH' else False ) values.append( True if testament=='NT' or testament=='BOTH' else False ) Strong = self.getSetting( 'Strong' ) values.append( Strong if Strong else False ) if customCSS: values.append( customCSS ) exeStr = 'INSERT INTO "Details" VALUES(' + '?,'*(len(values)-1) + '?)' #print( exeStr, values ) cursor.execute( exeStr, values ) #if BibleOrgSysGlobals.debugFlag: cursor.execute( exeStr, values ) #else: # Not debugging #try: cursor.execute( exeStr, values ) #except sqlite3.InterfaceError: #logging.critical( "SQLite3 Interface error executing {} with {}".format( exeStr, values ) ) # Now create and fill the Bible table cursor.execute( 'CREATE TABLE Bible(Book INT, Chapter INT, Verse INT, Scripture TEXT, Primary Key(Book,Chapter,Verse))' ) conn.commit() # save (commit) the changes BBB, lineCount = startBBB, 0 while True: # Write each Bible book in the KJV order writeMSBook( cursor, BBB, mySettings ) conn.commit() # save (commit) the changes handledBooks.append( BBB ) if BBB == endBBB: break BBB = BOS.getNextBookCode( BBB ) conn.commit() # save (commit) the changes cursor.close() if mySettings['unhandledMarkers']: logging.warning( "BibleWriter.toMySword: Unhandled markers were {}".format( mySettings['unhandledMarkers'] ) ) if BibleOrgSysGlobals.verbosityLevel > 1: print( " " + _("WARNING: Unhandled toMySword markers were {}").format( mySettings['unhandledMarkers'] ) ) unhandledBooks = [] for BBB in self.getBookList(): if BBB not in handledBooks: unhandledBooks.append( BBB ) if unhandledBooks: logging.warning( "toMySword: Unhandled books were {}".format( unhandledBooks ) ) if BibleOrgSysGlobals.verbosityLevel > 1: print( " " + _("WARNING: Unhandled toMySword books were {}").format( unhandledBooks ) ) # Now create the gzipped file if BibleOrgSysGlobals.verbosityLevel > 2: print( " Compressing {} MySword file…".format( filename ) ) tar = tarfile.open( filepath+'.gz', 'w:gz' ) tar.add( filepath ) tar.close() if BibleOrgSysGlobals.verbosityLevel > 0 and BibleOrgSysGlobals.maxProcesses > 1: print( " BibleWriter.toMySword finished successfully." ) return True
class HaggaiXMLBible( Bible ): """ Class for reading, validating, and converting HaggaiXMLBible XML. """ XMLNameSpace = "{http://www.w3.org/2001/XMLSchema-instance}" treeTag = 'XMLBIBLE' infoTag = 'INFORMATION' bookTag = 'BIBLEBOOK' chapterTag = 'CHAPTER' captionTag = 'CAPTION' paragraphTag = 'PARAGRAPH' verseTag = 'VERSE' noteTag = 'NOTE' styleTag = 'STYLE' breakTag = 'BR' def __init__( self, sourceFolder, givenName, encoding='utf-8' ): """ Constructor: just sets up the Haggai Bible object. """ # Setup and initialise the base class first Bible.__init__( self ) self.objectNameString = 'Haggai XML Bible object' self.objectTypeString = 'Haggai' # Now we can set our object variables self.sourceFolder, self.givenName, self.encoding = sourceFolder, givenName, encoding self.sourceFilepath = os.path.join( self.sourceFolder, self.givenName ) self.tree = self.header = None # Will hold the XML data # Get the data tables that we need for proper checking #self.ISOLanguages = ISO_639_3_Languages().loadData() self.genericBOS = BibleOrganizationalSystem( 'GENERIC-KJV-66-ENG' ) # Do a preliminary check on the readability of our file if not os.access( self.sourceFilepath, os.R_OK ): print( "HaggaiXMLBible: File {!r} is unreadable".format( self.sourceFilepath ) ) self.name = self.givenName #if self.name is None: #pass # end of HaggaiXMLBible.__init__ def load( self ): """ Load a single source XML file and load book elements. """ if BibleOrgSysGlobals.verbosityLevel > 2: print( _("Loading {}…").format( self.sourceFilepath ) ) try: self.tree = ElementTree().parse( self.sourceFilepath ) except ParseError as err: logging.critical( exp("Loader parse error in xml file {}: {} {}").format( self.givenName, sys.exc_info()[0], err ) ) #loadErrors.append( exp("Loader parse error in xml file {}: {} {}").format( self.givenName, sys.exc_info()[0], err ) ) #self.addPriorityError( 100, C, V, _("Loader parse error in xml file {}: {}").format( self.givenName, err ) ) if BibleOrgSysGlobals.debugFlag: assert len ( self.tree ) # Fail here if we didn't load anything at all # Find the main (bible) container if self.tree.tag == HaggaiXMLBible.treeTag: location = "Haggai XML file" BibleOrgSysGlobals.checkXMLNoText( self.tree, location, '4f6h' ) BibleOrgSysGlobals.checkXMLNoTail( self.tree, location, '1wk8' ) schema = name = status = BibleType = revision = version = lgid = None for attrib,value in self.tree.items(): if attrib == HaggaiXMLBible.XMLNameSpace + 'noNamespaceSchemaLocation': schema = value elif attrib == "biblename": name = value elif attrib == "lgid": lgid = value # In italian.xml this is set to "german" elif attrib == "status": status = value elif attrib == "type": BibleType = value elif attrib == "revision": revision = value elif attrib == 'version': version = value else: logging.warning( "Unprocessed {!r} attribute ({}) in main element".format( attrib, value ) ) if name: self.name = name if status: self.status = status if revision: self.revision = revision if version: self.version = version if self.tree[0].tag == 'INFORMATION': self.header = self.tree[0] self.tree.remove( self.header ) self.__validateAndExtractHeader() else: # Handle information records at the END of the file ix = len(self.tree) - 1 if self.tree[ix].tag == 'INFORMATION': self.header = self.tree[ix] self.tree.remove( self.header ) self.__validateAndExtractHeader() # Find the submain (book) containers for element in self.tree: if element.tag == HaggaiXMLBible.bookTag: sublocation = "book in " + location BibleOrgSysGlobals.checkXMLNoText( element, sublocation, 'g3g5' ) BibleOrgSysGlobals.checkXMLNoTail( element, sublocation, 'd3f6' ) self.__validateAndExtractBook( element ) else: logging.error( "Expected to find {!r} but got {!r}".format( HaggaiXMLBible.bookTag, element.tag ) ) else: logging.error( "Expected to load {!r} but got {!r}".format( HaggaiXMLBible.treeTag, self.tree.tag ) ) self.doPostLoadProcessing() # end of HaggaiXMLBible.load def __validateAndExtractHeader( self ): """ Extracts information out of the header record, such as: <INFORMATION> <title>King James Version</title> <creator></creator> <subject>The Holy Bible</subject> <description>In 1604, King James I of England authorized that a new translation of the Bible into English be started. It was finished in 1611, just 85 years after the first translation of the New Testament into English appeared (Tyndale, 1526). The Authorized Version, or King James Version, quickly became the standard for English-speaking Protestants. Its flowing language and prose rhythm has had a profound influence on the literature of the past 300 years.</description> <publisher>FREE BIBLE SOFTWARE GROUP</publisher> <contributors /> <date>2009-01-23</date> <type>Bible</type> <format>Haggai XML Bible Markup Language</format> <identifier>kjv</identifier> <source>http://www.unboundbible.com/zips/index.cfm?lang=English</source> <language>ENG</language> <coverage>provide the Bible to the nations of the world</coverage> <rights>We believe that this Bible is found in the Public Domain.</rights> </INFORMATION> """ if BibleOrgSysGlobals.debugFlag: assert self.header location = 'Header' BibleOrgSysGlobals.checkXMLNoAttributes( self.header, location, 'j4j6' ) BibleOrgSysGlobals.checkXMLNoText( self.header, location, 'sk4l' ) BibleOrgSysGlobals.checkXMLNoTail( self.header, location, 'a2d4' ) # TODO: We probably need to rationalise some of the self.xxx stores for element in self.header: #print( "header", element.tag ) if element.tag == 'title': sublocation = "title in {}".format( location ) BibleOrgSysGlobals.checkXMLNoTail( element, sublocation, 'al1d' ) BibleOrgSysGlobals.checkXMLNoAttributes( element, sublocation, 'j3jd' ) BibleOrgSysGlobals.checkXMLNoSubelements( element, sublocation, '5g78' ) if BibleOrgSysGlobals.debugFlag: assert element.text self.title = element.text elif element.tag == 'creator': sublocation = "creator in {}".format( location ) BibleOrgSysGlobals.checkXMLNoTail( element, sublocation, 'al1d' ) BibleOrgSysGlobals.checkXMLNoAttributes( element, sublocation, 'j3jd' ) BibleOrgSysGlobals.checkXMLNoSubelements( element, sublocation, '5g78' ) if element.text: self.creator = element.text elif element.tag == 'subject': sublocation = "subject in {}".format( location ) BibleOrgSysGlobals.checkXMLNoTail( element, sublocation, 'al1d' ) BibleOrgSysGlobals.checkXMLNoAttributes( element, sublocation, 'j3jd' ) BibleOrgSysGlobals.checkXMLNoSubelements( element, sublocation, '5g78' ) if element.text: self.subject = element.text elif element.tag == 'description': sublocation = "description in {}".format( location ) BibleOrgSysGlobals.checkXMLNoTail( element, sublocation, 'al1d' ) BibleOrgSysGlobals.checkXMLNoAttributes( element, sublocation, 'j3jd' ) BibleOrgSysGlobals.checkXMLNoSubelements( element, sublocation, '5g78' ) if BibleOrgSysGlobals.debugFlag: assert element.text self.description = element.text elif element.tag == 'publisher': sublocation = "publisher in {}".format( location ) BibleOrgSysGlobals.checkXMLNoTail( element, sublocation, 'al1d' ) BibleOrgSysGlobals.checkXMLNoAttributes( element, sublocation, 'j3jd' ) BibleOrgSysGlobals.checkXMLNoSubelements( element, sublocation, '5g78' ) if element.text: self.publisher = element.text elif element.tag == 'contributor': sublocation = "contributor in {}".format( location ) BibleOrgSysGlobals.checkXMLNoTail( element, sublocation, 'alj1d' ) BibleOrgSysGlobals.checkXMLNoAttributes( element, sublocation, 'j3jjd' ) BibleOrgSysGlobals.checkXMLNoSubelements( element, sublocation, '5gk78' ) if element.text: try: self.contributor = [ self.contributor, element.text ] # Put multiples into a list except AttributeError: self.contributor = element.text # Must be the first (and possibly only) one elif element.tag == 'contributors': sublocation = "contributors in {}".format( location ) BibleOrgSysGlobals.checkXMLNoTail( element, sublocation, 'al1d' ) BibleOrgSysGlobals.checkXMLNoAttributes( element, sublocation, 'j3jd' ) BibleOrgSysGlobals.checkXMLNoSubelements( element, sublocation, '5g78' ) if element.text: self.contributors = element.text elif element.tag == 'date': sublocation = "date in {}".format( location ) BibleOrgSysGlobals.checkXMLNoTail( element, sublocation, 'al1d' ) BibleOrgSysGlobals.checkXMLNoAttributes( element, sublocation, 'j3jd' ) BibleOrgSysGlobals.checkXMLNoSubelements( element, sublocation, '5g78' ) if BibleOrgSysGlobals.debugFlag: assert element.text self.date = element.text elif element.tag == 'type': sublocation = "type in {}".format( location ) BibleOrgSysGlobals.checkXMLNoTail( element, sublocation, 'al1d' ) BibleOrgSysGlobals.checkXMLNoAttributes( element, sublocation, 'j3jd' ) BibleOrgSysGlobals.checkXMLNoSubelements( element, sublocation, '5g78' ) if element.text: self.documentType = element.text elif element.tag == 'format': sublocation = "format in {}".format( location ) BibleOrgSysGlobals.checkXMLNoTail( element, sublocation, 'al1d' ) BibleOrgSysGlobals.checkXMLNoAttributes( element, sublocation, 'j3jd' ) BibleOrgSysGlobals.checkXMLNoSubelements( element, sublocation, '5g78' ) if BibleOrgSysGlobals.debugFlag: assert element.text if BibleOrgSysGlobals.debugFlag: assert element.text == 'Haggai XML Bible Markup Language' elif element.tag == 'identifier': sublocation = "identifier in {}".format( location ) BibleOrgSysGlobals.checkXMLNoTail( element, sublocation, 'al1d' ) BibleOrgSysGlobals.checkXMLNoAttributes( element, sublocation, 'j3jd' ) BibleOrgSysGlobals.checkXMLNoSubelements( element, sublocation, '5g78' ) if BibleOrgSysGlobals.debugFlag: assert element.text self.identifier = element.text elif element.tag == 'source': sublocation = "source in {}".format( location ) BibleOrgSysGlobals.checkXMLNoTail( element, sublocation, 'al1d' ) BibleOrgSysGlobals.checkXMLNoAttributes( element, sublocation, 'j3jd' ) BibleOrgSysGlobals.checkXMLNoSubelements( element, sublocation, '5g78' ) if BibleOrgSysGlobals.debugFlag: assert element.text self.source = element.text elif element.tag == 'language': sublocation = "language in {}".format( location ) BibleOrgSysGlobals.checkXMLNoTail( element, sublocation, 'al1d' ) BibleOrgSysGlobals.checkXMLNoAttributes( element, sublocation, 'j3jd' ) BibleOrgSysGlobals.checkXMLNoSubelements( element, sublocation, '5g78' ) if BibleOrgSysGlobals.debugFlag: assert element.text self.language = element.text elif element.tag == 'coverage': sublocation = "coverage in {}".format( location ) BibleOrgSysGlobals.checkXMLNoTail( element, sublocation, 'al1d' ) BibleOrgSysGlobals.checkXMLNoAttributes( element, sublocation, 'j3jd' ) BibleOrgSysGlobals.checkXMLNoSubelements( element, sublocation, '5g78' ) if element.text: self.coverage = element.text elif element.tag == 'rights': sublocation = "rights in {}".format( location ) BibleOrgSysGlobals.checkXMLNoTail( element, sublocation, 'al1d' ) BibleOrgSysGlobals.checkXMLNoAttributes( element, sublocation, 'j3jd' ) BibleOrgSysGlobals.checkXMLNoSubelements( element, sublocation, '5g78' ) if element.text: self.rights = element.text else: logging.error( "Found unexpected {!r} tag in {}".format( element.tag, location ) ) # end of HaggaiXMLBible.__validateAndExtractHeader def __validateAndExtractBook( self, book ): """ Check/validate and extract book data from the given XML book record finding chapter subelements. """ if BibleOrgSysGlobals.verbosityLevel > 3: print( _("Validating XML book…") ) # Process the div attributes first BBB = bookName = bookShortName = bookNumber = None for attrib,value in book.items(): if attrib=="bnumber": bookNumber = value elif attrib=="bname": bookName = value elif attrib=="bsname": bookShortName = value else: logging.warning( "Unprocessed {!r} attribute ({}) in book element".format( attrib, value ) ) if bookNumber: try: BBB = BibleOrgSysGlobals.BibleBooksCodes.getBBBFromReferenceNumber( bookNumber ) except KeyError: logging.warning( "Unable to deduce which book is number={}, name={}, shortName={} -- ignoring it" \ .format( bookNumber, bookName, bookShortName ) ) elif bookName: BBB = self.genericBOS.getBBBFromText( bookName ) if BBB: if BibleOrgSysGlobals.verbosityLevel > 2: print( _("Validating {} {}…").format( BBB, bookName ) ) thisBook = BibleBook( self, BBB ) thisBook.objectNameString = 'Haggai XML Bible Book object' thisBook.objectTypeString = 'Haggai' #thisBook.sourceFilepath = self.sourceFilepath for element in book: if element.tag == HaggaiXMLBible.captionTag: sublocation = "caption in {}".format( BBB ) BibleOrgSysGlobals.checkXMLNoAttributes( element, sublocation, 'jhl6' ) BibleOrgSysGlobals.checkXMLNoSubelements( element, sublocation, 'jk21' ) BibleOrgSysGlobals.checkXMLNoTail( element, sublocation, 'kjh6' ) thisBook.addLine( 'mt', element.text ) elif element.tag == HaggaiXMLBible.chapterTag: sublocation = "chapter in {}".format( BBB ) BibleOrgSysGlobals.checkXMLNoText( element, sublocation, 'j3jd' ) BibleOrgSysGlobals.checkXMLNoTail( element, sublocation, 'al1d' ) self.__validateAndExtractChapter( BBB, thisBook, element ) else: logging.error( "Expected to find {!r} but got {!r}".format( HaggaiXMLBible.chapterTag, element.tag ) ) if BibleOrgSysGlobals.verbosityLevel > 2: print( " Saving {} into results…".format( BBB ) ) self.stashBook( thisBook ) # end of HaggaiXMLBible.__validateAndExtractBook def __validateAndExtractChapter( self, BBB, thisBook, chapter ): """ Check/validate and extract chapter data from the given XML book record finding and saving chapter numbers and finding and saving verse elements. """ if BibleOrgSysGlobals.verbosityLevel > 3: print( _("Validating XML chapter…") ) # Process the chapter attributes first chapterNumber = numVerses = None for attrib,value in chapter.items(): if attrib=="cnumber": chapterNumber = value else: logging.warning( "Unprocessed {!r} attribute ({}) in chapter element".format( attrib, value ) ) if chapterNumber: #print( BBB, 'c', chapterNumber ) thisBook.addLine( 'c', chapterNumber ) else: logging.error( "Missing 'n' attribute in chapter element for {}".format( BBB ) ) for element in chapter: if element.tag == HaggaiXMLBible.paragraphTag: location = "paragraph in {} {}".format( BBB, chapterNumber ) self.__validateAndExtractParagraph( BBB, chapterNumber, thisBook, element ) elif element.tag == HaggaiXMLBible.verseTag+'disabled': location = "verse in {} {}".format( BBB, chapterNumber ) self.__validateAndExtractVerse( BBB, chapterNumber, thisBook, element ) elif element.tag == HaggaiXMLBible.captionTag+'disabled': # Used in Psalms location = "caption in {} {}".format( BBB, chapterNumber ) BibleOrgSysGlobals.checkXMLNoTail( element, location, 'k5k8' ) BibleOrgSysGlobals.checkXMLNoSubelements( element, location, 'd3f5' ) # Handle caption attributes vRef = None for attrib,value in element.items(): if attrib=="vref": vRef = value if BibleOrgSysGlobals.debugFlag: assert vRef == '1' else: logging.warning( "Unprocessed {!r} attribute ({}) in caption element".format( attrib, value ) ) if BibleOrgSysGlobals.debugFlag: assert vRef vText = element.text if not vText: logging.warning( "{} {}:{} has no text".format( BBB, chapterNumber, vRef ) ) if vText: # This is the main text of the caption #print( "{} {}:{} {!r}".format( BBB, chapterNumber, verseNumber, vText ) ) thisBook.addLine( 'v', '0' + ' ' + vText ) # We save it as verse zero else: logging.error( "Expected to find {!r} but got {!r}".format( HaggaiXMLBible.verseTag, element.tag ) ) # end of HaggaiXMLBible.__validateAndExtractChapter def __validateAndExtractParagraph( self, BBB, chapterNumber, thisBook, paragraph ): """ Check/validate and extract paragraph data from the given XML book record finding and saving paragraphs and finding and saving verse elements. """ if BibleOrgSysGlobals.verbosityLevel > 3: print( _("Validating XML paragraph…") ) location = "paragraph in {} {}".format( BBB, chapterNumber ) BibleOrgSysGlobals.checkXMLNoAttributes( paragraph, location, 'brgw3' ) BibleOrgSysGlobals.checkXMLNoText( paragraph, location, 'brgw3' ) BibleOrgSysGlobals.checkXMLNoTail( paragraph, location, 'brgw3' ) thisBook.addLine( 'p', '' ) # Handle verse subelements (verses) for element in paragraph: if element.tag == HaggaiXMLBible.verseTag: location = "verse in {} {}".format( BBB, chapterNumber ) self.__validateAndExtractVerse( BBB, chapterNumber, thisBook, element ) elif element.tag == HaggaiXMLBible.captionTag+'disabled': # Used in Psalms location = "caption in {} {}".format( BBB, chapterNumber ) BibleOrgSysGlobals.checkXMLNoTail( element, location, 'k5k8' ) BibleOrgSysGlobals.checkXMLNoSubelements( element, location, 'd3f5' ) # Handle caption attributes vRef = None for attrib,value in element.items(): if attrib=="vref": vRef = value if BibleOrgSysGlobals.debugFlag: assert vRef == '1' else: logging.warning( "Unprocessed {!r} attribute ({}) in caption element".format( attrib, value ) ) if BibleOrgSysGlobals.debugFlag: assert vRef vText = element.text if not vText: logging.warning( "{} {}:{} has no text".format( BBB, chapterNumber, vRef ) ) if vText: # This is the main text of the caption #print( "{} {}:{} {!r}".format( BBB, chapterNumber, verseNumber, vText ) ) thisBook.addLine( 'v', '0' + ' ' + vText ) # We save it as verse zero else: logging.error( "Expected to find {!r} but got {!r}".format( HaggaiXMLBible.verseTag, element.tag ) ) # end of HaggaiXMLBible.__validateAndExtractParagraph def __validateAndExtractVerse( self, BBB, chapterNumber, thisBook, verse ): """ Check/validate and extract verse data from the given XML book record finding and saving verse elements. """ if BibleOrgSysGlobals.verbosityLevel > 3: print( _("Validating XML verse…") ) location = "verse in {} {}".format( BBB, chapterNumber ) BibleOrgSysGlobals.checkXMLNoTail( verse, location, 'l5ks' ) # Handle verse attributes verseNumber = toVerseNumber = None for attrib,value in verse.items(): if attrib=="vnumber": verseNumber = value else: logging.warning( "Unprocessed {!r} attribute ({}) in verse element".format( attrib, value ) ) if BibleOrgSysGlobals.debugFlag: assert verseNumber location = "{}:{}".format( location, verseNumber ) # Get a better location description #thisBook.addLine( 'v', verseNumber ) vText = '' if verse.text is None else verse.text if vText: vText = vText.strip() #if not vText: # This happens if a verse starts immediately with a style or note #logging.warning( "{} {}:{} has no text".format( BBB, chapterNumber, verseNumber ) ) # Handle verse subelements (notes and styled portions) for subelement in verse: if subelement.tag == HaggaiXMLBible.noteTag: sublocation = "note in " + location noteType = None for attrib,value in subelement.items(): if attrib=="type": noteType = value else: logging.warning( "Unprocessed {!r} attribute ({}) in style subelement".format( attrib, value ) ) if noteType and noteType not in ('variant',): logging.warning( "Unexpected {} note type in {}".format( noteType, BBB ) ) nText, nTail = subelement.text, subelement.tail #print( "note", BBB, chapterNumber, verseNumber, noteType, repr(nText), repr(nTail) ) vText += "\\f + \\fk {} \\ft {}\\f*".format( noteType, nText ) if noteType else "\\f + \\ft {}\\f*".format( nText ) if nTail: if '\n' in nTail: print( "HaggaiXMLBible.__validateAndExtractVerse: nTail {} {}:{} {!r}".format( BBB, chapterNumber, verseNumber, nTail ) ) nTail = nTail.replace( '\n', ' ' ) vText += nTail for subsubelement in subelement: if subsubelement.tag == HaggaiXMLBible.styleTag: subsublocation = "style in " + sublocation BibleOrgSysGlobals.checkXMLNoSubelements( subsubelement, subsublocation, 'fyt4' ) fs = css = idStyle = None for attrib,value in subsubelement.items(): if attrib=='fs': fs = value #elif attrib=="css": css = value #elif attrib=="id": idStyle = value else: logging.warning( "Unprocessed {!r} attribute ({}) in style subsubelement".format( attrib, value ) ) if BibleOrgSysGlobals.debugFlag: assert fs or css or idStyle SFM = None if fs == 'italic': SFM = '\\it' elif fs == 'super': SFM = '\\bdit' elif fs == 'emphasis': SFM = '\\em' else: print( "fs is", fs, "css is", css, "idStyle is", idStyle ); halt #if css == "font-style:italic": SFM = '\\it' #elif css == "font-style:italic;font-weight:bold": SFM = '\\bdit' #elif css == "color:#FF0000": SFM = '\\em' #elif css == "font-size: x-small; color:#8B8378": SFM = '\\add' #elif css is None and idStyle=='cl:divineName': SFM = '\\nd' #else: print( "css is", css, "idStyle is", idStyle ); halt sText, sTail = subsubelement.text.strip(), subsubelement.tail if BibleOrgSysGlobals.debugFlag: assert sText if SFM: vText += SFM+' ' + sText + SFM+'*' else: vText += '\\sc ' + '['+css+']' + sText + '\\sc* ' # Use sc for unknown styles if sTail: vText += sTail.strip() else: logging.error( "Expected to find {} but got {!r} in {}".format( HaggaiXMLBible.styleTag, subsubelement.tag, sublocation ) ) elif subelement.tag == HaggaiXMLBible.styleTag: sublocation = "style in " + location BibleOrgSysGlobals.checkXMLNoSubelements( subelement, sublocation, 'f5gh' ) fs = css = idStyle = None for attrib,value in subelement.items(): if attrib=="fs": fs = value #elif attrib=="css": css = value #elif attrib=="id": idStyle = value else: logging.warning( "Unprocessed {!r} attribute ({}) in style subelement".format( attrib, value ) ) if BibleOrgSysGlobals.debugFlag: assert fs SFM = None if fs == 'super': SFM = '\\bdit' elif fs == 'emphasis': SFM = '\\em' else: print( "fs is", fs, "css is", css, "idStyle is", idStyle ); halt #if css == "font-style:italic": SFM = '\\it' #elif css == "font-style:italic;font-weight:bold": SFM = '\\bdit' #elif css == "color:#FF0000": SFM = '\\em' #elif css == "font-size: x-small; color:#8B8378": SFM = '\\add' #elif css is None and idStyle=='cl:divineName': SFM = '\\nd' #else: print( "css is", css, "idStyle is", idStyle ); halt sText, sTail = subelement.text.strip(), subelement.tail if BibleOrgSysGlobals.debugFlag: assert sText #print( BBB, chapterNumber, sublocation ) if SFM: vText += SFM+' ' + sText + SFM+'*' else: vText += '\\sc ' + '['+css+']' + sText + '\\sc* ' # Use sc for unknown styles if sTail: vText += sTail.strip() elif subelement.tag == HaggaiXMLBible.breakTag: sublocation = "line break in " + location BibleOrgSysGlobals.checkXMLNoText( subelement, sublocation, 'c1d4' ) BibleOrgSysGlobals.checkXMLNoSubelements( subelement, sublocation, 'g4g8' ) art = None for attrib,value in subelement.items(): if attrib=="art": art = value else: logging.warning( "Unprocessed {!r} attribute ({}) in style subelement".format( attrib, value ) ) if BibleOrgSysGlobals.debugFlag: assert art == 'x-nl' #print( BBB, chapterNumber, verseNumber ) #assert vText if vText: thisBook.addLine( 'v', verseNumber + ' ' + vText ); verseNumber = None vText = '' thisBook.addLine( 'm', subelement.tail.strip() if subelement.tail else '' ) #bTail = subelement.tail #if bTail: vText = bTail.strip() else: logging.error( "Expected to find NOTE or STYLE but got {!r} in {}".format( subelement.tag, location ) ) if vText: # This is the main text of the verse (follows the verse milestone) if '\n' in vText: print( "HaggaiXMLBible.__validateAndExtractVerse: vText {} {}:{} {!r}".format( BBB, chapterNumber, verseNumber, vText ) ) vText = vText.replace( '\n', ' ' ) thisBook.addLine( 'v', verseNumber + ' ' + vText ); verseNumber = None
def load( self ): """ Load a single source file and load book elements. """ if BibleOrgSysGlobals.verbosityLevel > 2: print( _("Loading {}...").format( self.sourceFilepath ) ) fileExtensionUpper = self.fileExtension.upper() if fileExtensionUpper not in filenameEndingsToAccept: logging.critical( "{} doesn't appear to be a MySword file".format( self.sourceFilename ) ) elif not self.sourceFilename.upper().endswith( BibleFilenameEndingsToAccept[0] ): logging.critical( "{} doesn't appear to be a MySword Bible file".format( self.sourceFilename ) ) connection = sqlite3.connect( self.sourceFilepath ) connection.row_factory = sqlite3.Row # Enable row names cursor = connection.cursor() # First get the settings cursor.execute( 'select * from Details' ) row = cursor.fetchone() for key in row.keys(): self.settingsDict[key] = row[key] #print( self.settingsDict ); halt if 'Description' in self.settingsDict and len(self.settingsDict['Description'])<40: self.name = self.settingsDict['Description'] if 'Abbreviation' in self.settingsDict: self.abbreviation = self.settingsDict['Abbreviation'] if 'encryption' in self.settingsDict: logging.critical( "{} is encrypted: level {}".format( self.sourceFilename, self.settingsDict['encryption'] ) ) if self.settingsDict['OT'] and self.settingsDict['NT']: testament, BBB = 'BOTH', 'GEN' booksExpected, textLineCountExpected = 66, 31102 elif self.settingsDict['OT']: testament, BBB = 'OT', 'GEN' booksExpected, textLineCountExpected = 39, 23145 elif self.settingsDict['NT']: testament, BBB = 'NT', 'MAT' booksExpected, textLineCountExpected = 27, 7957 BOS = BibleOrganizationalSystem( "GENERIC-KJV-66-ENG" ) # Create the first book thisBook = BibleBook( self, BBB ) thisBook.objectNameString = "MySword Bible Book object" thisBook.objectTypeString = "MySword" verseList = BOS.getNumVersesList( BBB ) numC, numV = len(verseList), verseList[0] nBBB = BibleOrgSysGlobals.BibleBooksCodes.getReferenceNumber( BBB ) C = V = 1 bookCount = 0 ourGlobals = {} continued = ourGlobals['haveParagraph'] = False haveLines = False while True: cursor.execute('select Scripture from Bible where Book=? and Chapter=? and Verse=?', (nBBB,C,V) ) try: row = cursor.fetchone() line = row[0] except TypeError: # This reference is missing (row is None) #print( "something wrong at", BBB, C, V ) #if BibleOrgSysGlobals.debugFlag: halt #print( row ) line = None #print ( nBBB, BBB, C, V, 'MySw file line is "' + line + '"' ) if line is None: logging.warning( "MySwordBible.load: Found missing verse line at {} {}:{}".format( BBB, C, V ) ) else: # line is not None if not isinstance( line, str ): if 'encryption' in self.settingsDict: logging.critical( "MySwordBible.load: Unable to decrypt verse line at {} {}:{} {}".format( BBB, C, V, repr(line) ) ) break else: logging.critical( "MySwordBible.load: Unable to decode verse line at {} {}:{} {} {}".format( BBB, C, V, repr(line), self.settingsDict ) ) elif not line: logging.warning( "MySwordBible.load: Found blank verse line at {} {}:{}".format( BBB, C, V ) ) else: haveLines = True # Some modules end lines with \r\n or have it in the middle! # (We just ignore these for now) while line and line[-1] in '\r\n': line = line[:-1] if '\r' in line or '\n' in line: # (in the middle) logging.warning( "MySwordBible.load: Found CR or LF characters in verse line at {} {}:{}".format( BBB, C, V ) ) line = line.replace( '\r\n', ' ' ).replace( '\r', ' ' ).replace( '\n', ' ' ) #print( "MySword.load", BBB, C, V, repr(line) ) handleLine( self.name, BBB, C, V, line, thisBook, ourGlobals ) V += 1 if V > numV: C += 1 if C > numC: # Save this book now if haveLines: if BibleOrgSysGlobals.verbosityLevel > 3: print( "Saving", BBB, bookCount+1 ) self.saveBook( thisBook ) #else: print( "Not saving", BBB ) bookCount += 1 # Not the number saved but the number we attempted to process if bookCount >= booksExpected: break BBB = BOS.getNextBookCode( BBB ) # Create the next book thisBook = BibleBook( self, BBB ) thisBook.objectNameString = "MySword Bible Book object" thisBook.objectTypeString = "MySword" haveLines = False verseList = BOS.getNumVersesList( BBB ) numC, numV = len(verseList), verseList[0] nBBB = BibleOrgSysGlobals.BibleBooksCodes.getReferenceNumber( BBB ) C = V = 1 #thisBook.addLine( 'c', str(C) ) else: # next chapter only #thisBook.addLine( 'c', str(C) ) numV = verseList[C-1] V = 1 if ourGlobals['haveParagraph']: thisBook.addLine( 'p', '' ) ourGlobals['haveParagraph'] = False cursor.close() self.doPostLoadProcessing()
class BibleReferenceBox( Frame, BibleBox ): """ """ def __init__( self, parentWindow, parentApp, internalBible, referenceObject ): if BibleOrgSysGlobals.debugFlag: print( exp("BibleReferenceBox.__init__( {}, {}, {}, {} )").format( parentWindow, parentApp, internalBible.name, referenceObject ) ) self.parentWindow, self.parentApp, self.internalBible, self.referenceObject = parentWindow, parentApp, internalBible, referenceObject #self.parentApp = self.parentWindow.parentApp Frame.__init__( self, parentWindow ) BibleBox.__init__( self, self.parentApp ) # Set some dummy values required soon self._viewRadioVar, self._groupRadioVar = tk.IntVar(), tk.StringVar() self.groupCode = BIBLE_GROUP_CODES[0] # Put into first/default BCV group self.contextViewMode = DEFAULT self.viewMode = DEFAULT self.currentVerseKey = SimpleVerseKey( 'UNK','1','1' ) # Unknown book if self.contextViewMode == DEFAULT: self.contextViewMode = 'ByVerse' self.parentWindow.viewVersesBefore, self.parentWindow.viewVersesAfter = 2, 6 # Create a title bar titleBar = Frame( self ) Button( titleBar, text=_('Close'), command=self.doClose ).pack( side=tk.RIGHT ) ## Try to get the title width somewhere near correct (if moduleID is a long path) #adjModuleID = moduleID #self.update() # so we can get the geometry #width = parseWindowSize( self.parentWindow.geometry() )[0] - 60 # Allow for above button #if len(adjModuleID)*10 > width: # Note: this doesn't adjust if the window size is changed #print( "BRB here1", len(adjModuleID), width, repr(adjModuleID) ) #x = len(adjModuleID)*100/width # not perfect (too small) for narrow windows #adjModuleID = '…' + adjModuleID[int(x):] #print( "BRB here2", len(adjModuleID), x, repr(adjModuleID) ) #titleText = '{} ({})'.format( adjModuleID, boxType.replace( 'BibleReferenceBox', '' ) ) titleText = self.referenceObject.getShortText() self.titleLabel = tk.Label( titleBar, text=titleText ) self.titleLabel.pack( side=tk.TOP, fill=tk.X ) titleBar.pack( side=tk.TOP, fill=tk.X ) # Create a scroll bar to fill the right-hand side of the window self.vScrollbar = Scrollbar( self ) self.vScrollbar.pack( side=tk.RIGHT, fill=tk.Y ) self.textBox = tk.Text( self, height=4, yscrollcommand=self.vScrollbar.set ) self.textBox['wrap'] = 'word' self.textBox.pack( expand=tk.YES, fill=tk.X ) # Full width self.vScrollbar.config( command=self.textBox.yview ) # link the scrollbar to the text box self.createStandardKeyboardBindings() self.textBox.bind( "<Button-1>", self.setFocus ) # So disabled text box can still do select and copy functions # Set-up our standard Bible styles for USFMKey, styleDict in self.parentApp.stylesheet.getTKStyles().items(): self.textBox.tag_configure( USFMKey, **styleDict ) # Create the style # Add our extra specialised styles self.textBox.tag_configure( 'contextHeader', background='pink', font='helvetica 6 bold' ) self.textBox.tag_configure( 'context', background='pink', font='helvetica 6' ) self.pack( expand=tk.YES, fill=tk.BOTH ) # Pack the frame # Set-up our Bible system and our callables self.BibleOrganisationalSystem = BibleOrganizationalSystem( "GENERIC-KJV-66-ENG" ) # temp self.getNumChapters = self.BibleOrganisationalSystem.getNumChapters self.getNumVerses = lambda b,c: 99 if c=='0' or c==0 else self.BibleOrganisationalSystem.getNumVerses( b, c ) self.isValidBCVRef = self.BibleOrganisationalSystem.isValidBCVRef self.getFirstBookCode = self.BibleOrganisationalSystem.getFirstBookCode self.getPreviousBookCode = self.BibleOrganisationalSystem.getPreviousBookCode self.getNextBookCode = self.BibleOrganisationalSystem.getNextBookCode self.getBBB = self.BibleOrganisationalSystem.getBBB self.getBookName = self.BibleOrganisationalSystem.getBookName self.getBookList = self.BibleOrganisationalSystem.getBookList self.maxChapters, self.maxVerses = 150, 150 # temp self.verseCache = OrderedDict() self.updateShownReferences( self.referenceObject ) # end of BibleReferenceBox.__init__ def createStandardKeyboardBindings( self ): """ Create keyboard bindings for this widget. """ if BibleOrgSysGlobals.debugFlag and debuggingThisModule: print( exp("BibleReferenceBox.createStandardKeyboardBindings()") ) for name,command in ( ('SelectAll',self.doSelectAll), ('Copy',self.doCopy), ('Find',self.doFind), ('Refind',self.doRefind), ('Info',self.doShowInfo), ('Close',self.doClose) ): self.createStandardKeyboardBinding( name, command ) # end of BibleReferenceBox.createStandardKeyboardBindings() def xxxgotoBCV( self, BBB, C, V ): """ """ if BibleOrgSysGlobals.debugFlag: print( exp("BibleReferenceBox.gotoBCV( {} {}:{} from {} )").format( BBB, C, V, self.currentVerseKey ) ) # We really need to convert versification systems here adjBBB, adjC, adjV, adjS = self.BibleOrganisationalSystem.convertToReferenceVersification( BBB, C, V ) self.parentWindow.gotoGroupBCV( self.groupCode, adjBBB, adjC, adjV ) # then the App will update me by calling updateShownBCV # end of BibleReferenceBox.gotoBCV def getContextVerseData( self, verseKey ): """ Fetches and returns the internal Bible data for the given reference. """ if BibleOrgSysGlobals.debugFlag and debuggingThisModule: print( exp("BibleReferenceBox.getContextVerseData( {} )").format( verseKey ) ) if self.internalBible is not None: try: return self.internalBible.getContextVerseData( verseKey ) except KeyError: logging.critical( exp("BibleReferenceBox.getContextVerseData for {} {} got a KeyError!") \ .format( self.boxType, verseKey ) ) # end of BibleReferenceBox.getContextVerseData def XXXgetSwordVerseKey( self, verseKey ): #if BibleOrgSysGlobals.debugFlag and debuggingThisModule: print( exp("getSwordVerseKey( {} )").format( verseKey ) ) BBB, C, V = verseKey.getBCV() return self.parentApp.SwordInterface.makeKey( BBB, C, V ) # end of BibleReferenceBox.getSwordVerseKey def getCachedVerseData( self, verseKey ): """ Checks to see if the requested verse is in our cache, otherwise calls getContextVerseData (from the superclass) to fetch it. The cache keeps the newest or most recently used entries at the end. When it gets too large, it drops the first entry. """ #if BibleOrgSysGlobals.debugFlag and debuggingThisModule: print( exp("getCachedVerseData( {} )").format( verseKey ) ) verseKeyHash = verseKey.makeHash() if verseKeyHash in self.verseCache: #if BibleOrgSysGlobals.debugFlag and debuggingThisModule: print( " " + exp("Retrieved from BibleReferenceBox cache") ) self.verseCache.move_to_end( verseKeyHash ) #print( " returning", self.verseCache[verseKeyHash][0] ) return self.verseCache[verseKeyHash] verseContextData = self.getContextVerseData( verseKey ) self.verseCache[verseKeyHash] = verseContextData if len(self.verseCache) > MAX_CACHED_VERSES: #print( "Removing oldest cached entry", len(self.verseCache) ) self.verseCache.popitem( last=False ) return verseContextData # end of BibleReferenceBox.getCachedVerseData def XXXXgetBeforeAndAfterBibleData( self, newVerseKey ): """ Returns the requested verse, the previous verse, and the next n verses. """ if BibleOrgSysGlobals.debugFlag: print( exp("BibleReferenceBox.getBeforeAndAfterBibleData( {} )").format( newVerseKey ) ) assert( isinstance( newVerseKey, SimpleVerseKey ) ) BBB, C, V = newVerseKey.getBCV() intC, intV = newVerseKey.getChapterNumberInt(), newVerseKey.getVerseNumberInt() prevBBB, prevIntC, prevIntV = BBB, intC, intV previousVersesData = [] for n in range( -self.parentWindow.viewVersesBefore, 0 ): failed = False #print( " getBeforeAndAfterBibleData here with", n, prevIntC, prevIntV ) if prevIntV > 0: prevIntV -= 1 elif prevIntC > 0: prevIntC -= 1 try: prevIntV = self.getNumVerses( prevBBB, prevIntC ) except KeyError: if prevIntC != 0: # we can expect an error for chapter zero logging.critical( exp("getBeforeAndAfterBibleData failed at"), prevBBB, prevIntC ) failed = True #if not failed: #if BibleOrgSysGlobals.debugFlag: print( " Went back to previous chapter", prevIntC, prevIntV, "from", BBB, C, V ) else: prevBBB = self.BibleOrganisationalSystem.getPreviousBookCode( BBB ) if prevBBB is None: failed = True else: prevIntC = self.getNumChapters( prevBBB ) prevIntV = self.getNumVerses( prevBBB, prevIntC ) if BibleOrgSysGlobals.debugFlag: print( " Went back to previous book", prevBBB, prevIntC, prevIntV, "from", BBB, C, V ) if not failed and prevIntV is not None: #print( "getBeforeAndAfterBibleData XXX", repr(prevBBB), repr(prevIntC), repr(prevIntV) ) assert( prevBBB and isinstance(prevBBB, str) ) previousVerseKey = SimpleVerseKey( prevBBB, prevIntC, prevIntV ) previousVerseData = self.getCachedVerseData( previousVerseKey ) if previousVerseData: previousVersesData.insert( 0, (previousVerseKey,previousVerseData,) ) # Put verses in backwards # Determine the next valid verse numbers nextBBB, nextIntC, nextIntV = BBB, intC, intV nextVersesData = [] for n in range( 0, self.parentWindow.viewVersesAfter ): try: numVerses = self.getNumVerses( nextBBB, nextIntC ) except KeyError: numVerses = None # for an invalid BBB nextIntV += 1 if numVerses is None or nextIntV > numVerses: nextIntV = 1 nextIntC += 1 # Need to check................................ nextVerseKey = SimpleVerseKey( nextBBB, nextIntC, nextIntV ) nextVerseData = self.getCachedVerseData( nextVerseKey ) if nextVerseData: nextVersesData.append( (nextVerseKey,nextVerseData,) ) verseData = self.getCachedVerseData( newVerseKey ) return verseData, previousVersesData, nextVersesData # end of BibleReferenceBox.getBeforeAndAfterBibleData def XXXsetCurrentVerseKey( self, newVerseKey ): """ Called to set the current verse key. """ if BibleOrgSysGlobals.debugFlag and debuggingThisModule: print( exp("BibleReferenceBox.setCurrentVerseKey( {} )").format( newVerseKey ) ) self.parentApp.setDebugText( "BRW setCurrentVerseKey..." ) assert( isinstance( newVerseKey, SimpleVerseKey ) ) self.currentVerseKey = newVerseKey BBB = self.currentVerseKey.getBBB() self.maxChapters = self.getNumChapters( BBB ) self.maxVerses = self.getNumVerses( BBB, self.currentVerseKey.getChapterNumber() ) # end of BibleReferenceBox.setCurrentVerseKey def updateShownReferences( self, newReferenceObject ): """ Updates self in various ways depending on the contextViewMode held by the enclosing window. The new verse references are in the reference versification system in one of these objects: SimpleVerseKey (accepts 'GEN_1:1' or 'GEN','1','1') SimpleVersesKey (accepts 'MAT_6:1,4') VerseRangeKey (accepts 'JNA_2:1-7') Leaves the textbox in the disabled state. """ if BibleOrgSysGlobals.debugFlag and debuggingThisModule: print( "BibleReferenceBox.updateShownReferences( {} ) for {}".format( newReferenceObject, self.internalBible.name ) ) assert( isinstance( newReferenceObject, SimpleVerseKey ) or isinstance( newReferenceObject, SimpleVersesKey ) or isinstance( newReferenceObject, VerseRangeKey )) for j, referenceVerse in enumerate( newReferenceObject ): #print( " refVerse", j, referenceVerse ) assert( isinstance( referenceVerse, SimpleVerseKey ) ) refBBB, refC, refV, refS = referenceVerse.getBCVS() BBB, C, V, S = self.BibleOrganisationalSystem.convertFromReferenceVersification( refBBB, refC, refV, refS ) newVerseKey = SimpleVerseKey( BBB, C, V, S ) #print( " newVK", newVerseKey ) # Set firstFlag as False (rather than j==0) so don't get context displayed self.displayAppendVerse( False, newVerseKey, self.getCachedVerseData( newVerseKey ), lastFlag=False ) #self.setCurrentVerseKey( newVerseKey ) #self.clearText() # Leaves the text box enabled #startingFlag = True ## Safety-check in case they edited the settings file #if 'DBP' in self.boxType and self.contextViewMode in ('ByBook','ByChapter',): #print( exp("updateShownReferences: Safety-check converted {} contextViewMode for DBP").format( repr(self.contextViewMode) ) ) #self._viewRadioVar.set( 3 ) # ByVerse #self.changeBibleContextView() #if self.contextViewMode == 'BeforeAndAfter': #bibleData = self.getBeforeAndAfterBibleData( newVerseKey ) #if bibleData: #verseData, previousVerses, nextVerses = bibleData #for verseKey,previousVerseData in previousVerses: #self.displayAppendVerse( startingFlag, verseKey, previousVerseData ) #startingFlag = False #self.displayAppendVerse( startingFlag, newVerseKey, verseData, currentVerse=True ) #for verseKey,nextVerseData in nextVerses: #self.displayAppendVerse( False, verseKey, nextVerseData ) #elif self.contextViewMode == 'ByVerse': #self.displayAppendVerse( True, newVerseKey, self.getCachedVerseData( newVerseKey ), currentVerse=True ) #elif self.contextViewMode == 'BySection': #self.displayAppendVerse( True, newVerseKey, self.getCachedVerseData( newVerseKey ), currentVerse=True ) #BBB, C, V = newVerseKey.getBCV() #intC, intV = newVerseKey.getChapterNumberInt(), newVerseKey.getVerseNumberInt() #print( "\nBySection is not finished yet -- just shows a single verse!\n" ) # XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ##for thisC in range( 0, self.getNumChapters( BBB ) ): ##try: numVerses = self.getNumVerses( BBB, thisC ) ##except KeyError: numVerses = 0 ##for thisV in range( 0, numVerses ): ##thisVerseKey = SimpleVerseKey( BBB, thisC, thisV ) ##thisVerseData = self.getCachedVerseData( thisVerseKey ) ##self.displayAppendVerse( startingFlag, thisVerseKey, thisVerseData, ##currentVerse=thisC==intC and thisV==intV ) ##startingFlag = False #elif self.contextViewMode == 'ByBook': #BBB, C, V = newVerseKey.getBCV() #intC, intV = newVerseKey.getChapterNumberInt(), newVerseKey.getVerseNumberInt() #for thisC in range( 0, self.getNumChapters( BBB ) ): #try: numVerses = self.getNumVerses( BBB, thisC ) #except KeyError: numVerses = 0 #for thisV in range( 0, numVerses ): #thisVerseKey = SimpleVerseKey( BBB, thisC, thisV ) #thisVerseData = self.getCachedVerseData( thisVerseKey ) #self.displayAppendVerse( startingFlag, thisVerseKey, thisVerseData, #currentVerse=thisC==intC and thisV==intV ) #startingFlag = False #elif self.contextViewMode == 'ByChapter': #BBB, C, V = newVerseKey.getBCV() #intV = newVerseKey.getVerseNumberInt() #try: numVerses = self.getNumVerses( BBB, C ) #except KeyError: numVerses = 0 #for thisV in range( 0, numVerses ): #thisVerseKey = SimpleVerseKey( BBB, C, thisV ) #thisVerseData = self.getCachedVerseData( thisVerseKey ) #self.displayAppendVerse( startingFlag, thisVerseKey, thisVerseData, currentVerse=thisV==intV ) #startingFlag = False #else: #logging.critical( exp("BibleReferenceBox.updateShownBCV: Bad context view mode {}").format( self.contextViewMode ) ) #if BibleOrgSysGlobals.debugFlag: halt # Unknown context view mode self.textBox['state'] = tk.DISABLED # Don't allow editing # end of BibleReferenceBox.updateShownReferences def doClose( self, event=None ): """ Called from the GUI. Can be overridden. """ self.closeReferenceBox() # end of BibleReferenceBox.doClose def closeReferenceBox( self ): """ Called to finally and irreversibly remove this box from our list and close it. """ if BibleOrgSysGlobals.debugFlag and debuggingThisModule: print( exp("BibleReferenceBox.closeReferenceBox()") ) if self in self.parentWindow.referenceBoxes: self.parentWindow.referenceBoxes.remove( self ) self.destroy() else: # we might not have finished making our box yet if BibleOrgSysGlobals.debugFlag: print( exp("BibleReferenceBox.closeReferenceBox() for {} wasn't in list").format( self.winType ) ) try: self.destroy() except tk.TclError: pass # never mind if BibleOrgSysGlobals.debugFlag: self.parentApp.setDebugText( "Closed resource box" )
def __init__(self, parentWindow, parentFrame, parentApp, internalBible, referenceObject): """ """ if BibleOrgSysGlobals.debugFlag: print( exp("BibleReferenceBox.__init__( {}, {}. {}, {}, {} )").format( parentWindow, parentFrame, parentApp, internalBible.getAName(), referenceObject)) self.parentWindow, self.parentFrame, self.parentApp, self.referenceObject = parentWindow, parentFrame, parentApp, referenceObject self.internalBible = handleInternalBibles(self.parentApp, internalBible, self) Frame.__init__(self, parentFrame) BibleBox.__init__(self, parentApp) # Set some dummy values required soon #self._contextViewRadioVar, self._formatViewRadioVar, self._groupRadioVar = tk.IntVar(), tk.IntVar(), tk.StringVar() #self._groupCode = BIBLE_GROUP_CODES[0] # Put into first/default BCV group #self._contextViewMode = DEFAULT #self._formatViewMode = DEFAULT self.currentVerseKey = SimpleVerseKey('UNK', '1', '1') # Unknown book #if self._contextViewMode == DEFAULT: #self._contextViewMode = 'ByVerse' #self.parentWindow.viewVersesBefore, self.parentWindow.viewVersesAfter = 2, 6 #if self._formatViewMode == DEFAULT: #self._formatViewMode = 'Formatted' # Create a title bar titleBar = Frame(self) Button(titleBar, text=_('Close'), command=self.doClose).pack(side=tk.RIGHT) ## Try to get the title width somewhere near correct (if moduleID is a long path) #adjModuleID = moduleID #self.update() # so we can get the geometry #width = parseWindowSize( self.parentWindow.winfo_geometry() )[0] - 60 # Allow for above button #if len(adjModuleID)*10 > width: # Note: this doesn't adjust if the window size is changed #print( "BRB here1", len(adjModuleID), width, repr(adjModuleID) ) #x = len(adjModuleID)*100/width # not perfect (too small) for narrow windows #adjModuleID = '…' + adjModuleID[int(x):] #print( "BRB here2", len(adjModuleID), x, repr(adjModuleID) ) #titleText = '{} ({})'.format( adjModuleID, boxType.replace( 'BibleReferenceBox', '' ) ) titleText = self.referenceObject.getShortText() self.titleLabel = tk.Label(titleBar, text=titleText) self.titleLabel.pack(side=tk.TOP, fill=tk.X) titleBar.pack(side=tk.TOP, fill=tk.X) # Create a scroll bar to fill the right-hand side of the window self.vScrollbar = Scrollbar(self) self.vScrollbar.pack(side=tk.RIGHT, fill=tk.Y) self.textBox = BText(self, height=5, yscrollcommand=self.vScrollbar.set) self.textBox.configure(wrap='word') self.textBox.pack(expand=tk.YES, fill=tk.X) # Full width self.vScrollbar.configure( command=self.textBox.yview) # link the scrollbar to the text box self.createStandardBoxKeyboardBindings() self.textBox.bind( '<Button-1>', self.setFocus ) # So disabled text box can still do select and copy functions # Set-up our standard Bible styles for USFMKey, styleDict in self.parentApp.stylesheet.getTKStyles( ).items(): self.textBox.tag_configure(USFMKey, **styleDict) # Create the style # Add our extra specialised styles self.textBox.tag_configure('contextHeader', background='pink', font='helvetica 6 bold') self.textBox.tag_configure('context', background='pink', font='helvetica 6') self.textBox.tag_configure('markersHeader', background='yellow3', font='helvetica 6 bold') self.textBox.tag_configure('markers', background='yellow3', font='helvetica 6') self.pack(expand=tk.YES, fill=tk.BOTH) # Pack the frame # Set-up our Bible system and our callables self.BibleOrganisationalSystem = BibleOrganizationalSystem( 'GENERIC-KJV-81-ENG') # temp self.getNumChapters = self.BibleOrganisationalSystem.getNumChapters self.getNumVerses = lambda b,c: MAX_PSEUDOVERSES if c=='0' or c==0 \ else self.BibleOrganisationalSystem.getNumVerses( b, c ) self.isValidBCVRef = self.BibleOrganisationalSystem.isValidBCVRef self.getFirstBookCode = self.BibleOrganisationalSystem.getFirstBookCode self.getPreviousBookCode = self.BibleOrganisationalSystem.getPreviousBookCode self.getNextBookCode = self.BibleOrganisationalSystem.getNextBookCode self.getBBBFromText = self.BibleOrganisationalSystem.getBBBFromText self.getBookName = self.BibleOrganisationalSystem.getBookName self.getBookList = self.BibleOrganisationalSystem.getBookList self.maxChaptersThisBook, self.maxVersesThisChapter = 150, 150 # temp self.verseCache = OrderedDict() self.updateShownReferences(self.referenceObject)
def load(self): """ Load a single source file and load book elements. """ if BibleOrgSysGlobals.verbosityLevel > 2: print(_("Loading {}…").format(self.sourceFilepath)) global BOS66, BOS81, BOSx if BOS66 is None: BOS66 = BibleOrganizationalSystem('GENERIC-KJV-66-ENG') if BOS81 is None: BOS81 = BibleOrganizationalSystem('GENERIC-KJV-80-ENG') if BOSx is None: BOSx = BibleOrganizationalSystem('GENERIC-ENG') if self.suppliedMetadata is None: self.suppliedMetadata = {} lastLine, lineCount = '', 0 bookCode = BBB = metadataName = None lastBookCode = lastChapterNumber = lastVerseNumber = -1 lastVText = '' thisBook = None settingsDict = {} with open(self.sourceFilepath, encoding=self.encoding ) as myFile: # Automatically closes the file when done for line in myFile: lineCount += 1 if line[-1] == '\n': line = line[:-1] # Removing trailing newline character if not line: continue # Just discard blank lines if lineCount == 1: if self.encoding.lower() == 'utf-8' and line[0] == chr( 65279): #U+FEFF or \ufeff logging.info( " ForgeForSwordSearcherBible.load: Detected Unicode Byte Order Marker (BOM)" ) line = line[ 1:] # Remove the Unicode Byte Order Marker (BOM) match = re.search('^; TITLE:\\s', line) if match: if BibleOrgSysGlobals.debugFlag: print("First line got type {!r} match from {!r}". format(match.group(0), line)) else: if BibleOrgSysGlobals.verbosityLevel > 3: print( "ForgeForSwordSearcherBible.load: (unexpected) first line was {!r} in {}" .format(firstLine, thisFilename)) if BibleOrgSysGlobals.debugFlag and debuggingThisModule: halt continue #print ( 'ForgeForSwordSearcher file line is "' + line + '"' ) lastLine = line # Process header stuff if line.startswith('; TITLE:'): string = line[8:].strip() if string: settingsDict['TITLE'] = string continue elif line.startswith('; ABBREVIATION:'): string = line[15:].strip() if string: settingsDict['ABBREVIATION'] = string continue elif line.startswith('; HAS ITALICS'): string = line[14:].strip() if string: settingsDict['HAS_ITALICS'] = string continue elif line.startswith('; HAS FOOTNOTES:'): string = line[15:].strip() if string: settingsDict['HAS_FOOTNOTES'] = string continue elif line.startswith('; HAS FOOTNOTES'): string = line[14:].strip() if string: settingsDict['HAS_FOOTNOTES'] = string continue elif line.startswith('; HAS REDLETTER'): string = line[14:].strip() if string: settingsDict['HAS_REDLETTER'] = string continue elif line[0] == ';': logging.warning( "ForgeForSwordSearcherBible.load is skipping unknown header/comment line: {}" .format(line)) continue # Just discard comment lines # Process the main segment if line.startswith('$$ '): if metadataName and metadataContents: settingsDict[metadataName] = metadataContents metadataName = None pointer = line[3:] #print( "pointer", repr(pointer) ) if pointer and pointer[0] == '{' and pointer[-1] == '}': metadataName = pointer[1:-1] if metadataName: #print( "metadataName", repr(metadataName) ) metadataContents = '' else: # let's assume it's a BCV reference pointer = pointer.replace( '1 K','1K' ).replace( '2 K','2K' ) \ .replace( '1 Chr','1Chr' ).replace( '2 Chr','2Chr' ) \ .replace( '1 Cor','1Cor' ).replace( '2 Cor','2Cor' ) \ .replace( '1 Thess','1Thess' ).replace( '2 Thess','2Thess' ) \ .replace( '1 Tim','1Tim' ).replace( '2 Tim','2Tim' ) \ .replace( '1 Pet','1Pet' ).replace( '2 Pet','2Pet' ) \ .replace( '1 J','1J' ).replace( '2 J','2J' ).replace( '3 J','3J' ) B_CV_Bits = pointer.split(' ', 1) if len(B_CV_Bits) == 2 and ':' in B_CV_Bits[1]: bookCode, CVString = B_CV_Bits chapterNumberString, verseNumberString = CVString.split( ':') chapterNumber = int(chapterNumberString) verseNumber = int(verseNumberString) if bookCode != lastBookCode: # We've started a new book if bookCode in ('Ge', ): BBB = 'GEN' elif bookCode in ('Le', ): BBB = 'LEV' elif bookCode in ('La', ): BBB = 'LAM' ##elif bookCode in ('Es',): BBB = 'EST' ##elif bookCode in ('Pr',): BBB = 'PRO' #elif bookCode in ('So',): BBB = 'SNG' #elif bookCode in ('La',): BBB = 'LAM' #elif bookCode in ('Jude',): BBB = 'JDE' else: #print( "4BookCode =", repr(bookCode) ) #BBB = BOS.getBBBFromText( bookCode ) # Try to guess BBB = BOS66.getBBBFromText( bookCode) # Try to guess if not BBB: BBB = BOS81.getBBBFromText( bookCode) # Try to guess if not BBB: BBB = BOSx.getBBBFromText( bookCode) # Try to guess #print( "4BBB =", repr(BBB) ) else: print("Unexpected number of bits", self.givenName, BBB, bookCode, chapterNumberString, verseNumberString, len(bits), bits) continue # Just save the pointer information which refers to the text on the next line else: # it's not a $$ line text = line #print( "text", repr(text) ) if metadataName: metadataContents += ('\n' if metadataContents else '') + text continue else: vText = text # Handle bits like (<scripref>Pr 2:7</scripref>) vText = vText.replace('(<scripref>', '\\x - \\xt ').replace( '</scripref>)', '\\x*') vText = vText.replace('<scripref>', '\\x - \\xt ').replace( '</scripref>', '\\x*') #if '\\' in vText: print( 'ForgeForSwordSearcher vText', repr(vText) ) #print( BBB, chapterNumber, verseNumber, repr(vText) ) # Convert {stuff} to footnotes match = re.search('\\{(.+?)\\}', vText) while match: footnoteText = '\\f + \\fr {}:{} \\ft {}\\f*'.format( chapterNumber, verseNumber, match.group(1)) vText = vText[:match.start( )] + footnoteText + vText[ match.end():] # Replace this footnote #print( BBB, chapterNumber, verseNumber, repr(vText) ) match = re.search('\\{(.+?)\\}', vText) # Convert [stuff] to added fields match = re.search('\\[(.+?)\\]', vText) while match: addText = '\\add {}\\add*'.format(match.group(1)) vText = vText[:match.start()] + addText + vText[ match.end():] # Replace this chunk #print( BBB, chapterNumber, verseNumber, repr(vText) ) match = re.search('\\[(.+?)\\]', vText) # Convert +r/This text is red-letter-r/ to wj fields match = re.search('\\+r/(.+?)-r/', vText) while match: addText = '\\wj {}\\wj*'.format(match.group(1)) vText = vText[:match.start()] + addText + vText[ match.end():] # Replace this chunk #print( BBB, chapterNumber, verseNumber, repr(vText) ) match = re.search('\\+r/(.+?)-r/', vText) # Final check for unexpected remaining formatting for badChar in '{}[]/': if badChar in vText: logging.warning( "Found remaining braces,brackets or slashes in SwordSearcher Forge VPL {} {}:{} {!r}" .format(BBB, chapterNumberString, verseNumberString, vText)) break if bookCode: if bookCode != lastBookCode: # We've started a new book if lastBookCode != -1: # Better save the last book self.stashBook(thisBook) if BBB: if BBB in self: logging.critical( "Have duplicated {} book in {}".format( self.givenName, BBB)) if BibleOrgSysGlobals.debugFlag: assert BBB not in self thisBook = BibleBook(self, BBB) thisBook.objectNameString = 'ForgeForSwordSearcher Bible Book object' thisBook.objectTypeString = 'ForgeForSwordSearcher' verseList = BOSx.getNumVersesList(BBB) numChapters, numVerses = len( verseList), verseList[0] lastBookCode = bookCode lastChapterNumber = lastVerseNumber = -1 else: logging.critical( "ForgeForSwordSearcherBible could not figure out {!r} book code" .format(bookCode)) if BibleOrgSysGlobals.debugFlag: halt if BBB: if chapterNumber != lastChapterNumber: # We've started a new chapter if BibleOrgSysGlobals.debugFlag: assert chapterNumber > lastChapterNumber or BBB == 'ESG' # Esther Greek might be an exception if chapterNumber == 0: logging.info( "Have chapter zero in {} {} {} {}:{}". format(self.givenName, BBB, bookCode, chapterNumberString, verseNumberString)) elif chapterNumber > numChapters: logging.error( "Have high chapter number in {} {} {} {}:{} (expected max of {})" .format(self.givenName, BBB, bookCode, chapterNumberString, verseNumberString, numChapters)) thisBook.addLine('c', chapterNumberString) lastChapterNumber = chapterNumber lastVerseNumber = -1 # Handle the verse info if verseNumber == lastVerseNumber and vText == lastVText: logging.warning( _("Ignored duplicate verse line in {} {} {} {}:{}" ).format(self.givenName, BBB, bookCode, chapterNumberString, verseNumberString)) continue if verseNumber < lastVerseNumber: logging.warning( _("Ignored receding verse number (from {} to {}) in {} {} {} {}:{}" ).format(lastVerseNumber, verseNumber, self.givenName, BBB, bookCode, chapterNumberString, verseNumberString)) elif verseNumber == lastVerseNumber: if vText == lastVText: logging.warning( _("Ignored duplicated {} verse in {} {} {} {}:{}" ).format(verseNumber, self.givenName, BBB, bookCode, chapterNumberString, verseNumberString)) else: logging.warning( _("Ignored duplicated {} verse number in {} {} {} {}:{}" ).format(verseNumber, self.givenName, BBB, bookCode, chapterNumberString, verseNumberString)) # Check for paragraph markers if vText and vText[0] == '¶': thisBook.addLine('p', '') vText = vText[1:].lstrip() #print( '{} {}:{} = {!r}'.format( BBB, chapterNumberString, verseNumberString, vText ) ) thisBook.addLine('v', verseNumberString + ' ' + vText) lastVText = vText lastVerseNumber = verseNumber else: # No bookCode yet logging.warning( "ForgeForSwordSearcherBible.load is skipping unknown pre-book line: {}" .format(line)) # Save the final book if thisBook is not None: self.stashBook(thisBook) # Clean up if settingsDict: #print( "ForgeForSwordSearcher settingsDict", settingsDict ) if self.suppliedMetadata is None: self.suppliedMetadata = {} self.suppliedMetadata['Forge4SS'] = settingsDict self.applySuppliedMetadata( 'Forge4SS') # Copy some to self.settingsDict self.doPostLoadProcessing()
class VerseViewXMLBible( Bible ): """ Class for reading, validating, and converting VerseViewXMLBible XML. """ XMLNameSpace = "{http://www.w3.org/2001/XMLSchema-instance}" treeTag = 'bible' filenameTag = 'fname' revisionTag = 'revision' titleTag = 'title' fontTag = 'font' copyrightTag = 'copyright' sizefactorTag = 'sizefactor' bookTag = 'b' chapterTag = 'c' verseTag = 'v' def __init__( self, sourceFolder, givenName, encoding='utf-8' ): """ Constructor: just sets up the VerseView Bible object. """ # Setup and initialise the base class first Bible.__init__( self ) self.objectNameString = 'VerseView XML Bible object' self.objectTypeString = 'VerseView' # Now we can set our object variables self.sourceFolder, self.givenName, self.encoding = sourceFolder, givenName, encoding self.sourceFilepath = os.path.join( self.sourceFolder, self.givenName ) self.tree = self.header = None # Will hold the XML data # Get the data tables that we need for proper checking #self.ISOLanguages = ISO_639_3_Languages().loadData() self.genericBOS = BibleOrganizationalSystem( 'GENERIC-KJV-66-ENG' ) # Do a preliminary check on the readability of our file if not os.access( self.sourceFilepath, os.R_OK ): print( "VerseViewXMLBible: File {!r} is unreadable".format( self.sourceFilepath ) ) self.name = self.givenName #if self.name is None: #pass # end of VerseViewXMLBible.__init__ def load( self ): """ Load a single source XML file and load book elements. """ if BibleOrgSysGlobals.verbosityLevel > 2: print( _("Loading {}…").format( self.sourceFilepath ) ) self.tree = ElementTree().parse( self.sourceFilepath ) if BibleOrgSysGlobals.debugFlag: assert len ( self.tree ) # Fail here if we didn't load anything at all if self.suppliedMetadata is None: self.suppliedMetadata = {} self.suppliedMetadata['VerseView'] = {} # Find the main (bible) container if self.tree.tag == VerseViewXMLBible.treeTag: location = "VerseView XML file" BibleOrgSysGlobals.checkXMLNoText( self.tree, location, '4f6h' ) BibleOrgSysGlobals.checkXMLNoAttributes( self.tree, location, 'js24' ) BibleOrgSysGlobals.checkXMLNoTail( self.tree, location, '1wk8' ) # Find the submain (various info and then book) containers bookNumber = 0 for element in self.tree: if element.tag == VerseViewXMLBible.filenameTag: sublocation = "filename in " + location BibleOrgSysGlobals.checkXMLNoAttributes( element, sublocation, 'jk86' ) BibleOrgSysGlobals.checkXMLNoSubelements( element, sublocation, 'hjk7' ) BibleOrgSysGlobals.checkXMLNoTail( element, sublocation, 'bh09' ) #self.filename = element.text elif element.tag == VerseViewXMLBible.revisionTag: sublocation = "revision in " + location BibleOrgSysGlobals.checkXMLNoAttributes( element, sublocation, 'jk86' ) BibleOrgSysGlobals.checkXMLNoSubelements( element, sublocation, 'hjk7' ) BibleOrgSysGlobals.checkXMLNoTail( element, sublocation, 'bh09' ) self.suppliedMetadata['VerseView']['Revision'] = element.text elif element.tag == VerseViewXMLBible.titleTag: sublocation = "title in " + location BibleOrgSysGlobals.checkXMLNoAttributes( element, sublocation, 'jk86' ) BibleOrgSysGlobals.checkXMLNoSubelements( element, sublocation, 'hjk7' ) BibleOrgSysGlobals.checkXMLNoTail( element, sublocation, 'bh09' ) self.suppliedMetadata['VerseView']['Title'] = element.text elif element.tag == VerseViewXMLBible.fontTag: sublocation = "font in " + location BibleOrgSysGlobals.checkXMLNoAttributes( element, sublocation, 'jk86' ) BibleOrgSysGlobals.checkXMLNoSubelements( element, sublocation, 'hjk7' ) BibleOrgSysGlobals.checkXMLNoTail( element, sublocation, 'bh09' ) self.suppliedMetadata['VerseView']['Font'] = element.text elif element.tag == VerseViewXMLBible.copyrightTag: sublocation = "copyright in " + location BibleOrgSysGlobals.checkXMLNoAttributes( element, sublocation, 'jk86' ) BibleOrgSysGlobals.checkXMLNoSubelements( element, sublocation, 'hjk7' ) BibleOrgSysGlobals.checkXMLNoTail( element, sublocation, 'bh09' ) self.suppliedMetadata['VerseView']['Copyright'] = element.text elif element.tag == VerseViewXMLBible.sizefactorTag: sublocation = "sizefactor in " + location BibleOrgSysGlobals.checkXMLNoAttributes( element, sublocation, 'jk86' ) BibleOrgSysGlobals.checkXMLNoSubelements( element, sublocation, 'hjk7' ) BibleOrgSysGlobals.checkXMLNoTail( element, sublocation, 'bh09' ) if BibleOrgSysGlobals.debugFlag: assert element.text == '1' elif element.tag == VerseViewXMLBible.bookTag: sublocation = "book in " + location BibleOrgSysGlobals.checkXMLNoText( element, sublocation, 'g3g5' ) BibleOrgSysGlobals.checkXMLNoTail( element, sublocation, 'd3f6' ) bookNumber += 1 self.__validateAndExtractBook( element, bookNumber ) else: logging.error( "xk15 Expected to find {!r} but got {!r}".format( VerseViewXMLBible.bookTag, element.tag ) ) else: logging.error( "Expected to load {!r} but got {!r}".format( VerseViewXMLBible.treeTag, self.tree.tag ) ) if BibleOrgSysGlobals.debugFlag or BibleOrgSysGlobals.verbosityLevel > 2: # These are all compulsory so they should all exist #print( "Filename is {!r}".format( self.filename ) ) print( "Revision is {!r}".format( self.suppliedMetadata['VerseView']['Revision'] ) ) print( "Title is {!r}".format( self.suppliedMetadata['VerseView']['Title'] ) ) print( "Font is {!r}".format( self.suppliedMetadata['VerseView']['Font'] ) ) print( "Copyright is {!r}".format( self.suppliedMetadata['VerseView']['Copyright'] ) ) #print( "SizeFactor is {!r}".format( self.sizeFactor ) ) self.applySuppliedMetadata( 'VerseView' ) # Copy some to self.settingsDict self.doPostLoadProcessing() # end of VerseViewXMLBible.load def __validateAndExtractBook( self, book, bookNumber ): """ Check/validate and extract book data from the given XML book record finding chapter subelements. """ if BibleOrgSysGlobals.verbosityLevel > 3: print( _("Validating XML book…") ) # Process the div attributes first BBB = bookName = None for attrib,value in book.items(): if attrib=="n": bookName = value else: logging.warning( "Unprocessed {!r} attribute ({}) in book element".format( attrib, value ) ) if bookName: BBB = self.genericBOS.getBBBFromText( bookName ) if BBB is None: adjustedBookName = BibleOrgSysGlobals.removeAccents( bookName ) if adjustedBookName != bookName: BBB = self.genericBOS.getBBBFromText( adjustedBookName ) BBB2 = BibleOrgSysGlobals.BibleBooksCodes.getBBBFromReferenceNumber( bookNumber ) if BBB2 != BBB: # Just double check using the book number if BibleOrgSysGlobals.debugFlag or BibleOrgSysGlobals.verbosityLevel > 2: print( "Assuming that book {} {!r} is {} (not {})".format( bookNumber, bookName, BBB2, BBB ) ) BBB = BBB2 #print( BBB ); halt if BBB: if BibleOrgSysGlobals.verbosityLevel > 2: print( _("Validating {} {}…").format( BBB, bookName ) ) thisBook = BibleBook( self, BBB ) thisBook.objectNameString = 'VerseView XML Bible Book object' thisBook.objectTypeString = 'VerseView' #thisBook.sourceFilepath = self.sourceFilepath for element in book: if element.tag == VerseViewXMLBible.chapterTag: sublocation = "chapter in {}".format( BBB ) BibleOrgSysGlobals.checkXMLNoText( element, sublocation, 'j3jd' ) BibleOrgSysGlobals.checkXMLNoTail( element, sublocation, 'al1d' ) self.__validateAndExtractChapter( BBB, thisBook, element ) else: logging.error( "vb26 Expected to find {!r} but got {!r}".format( VerseViewXMLBible.chapterTag, element.tag ) ) if BibleOrgSysGlobals.verbosityLevel > 2: print( " Saving {} into results…".format( BBB ) ) self.stashBook( thisBook ) # end of VerseViewXMLBible.__validateAndExtractBook def __validateAndExtractChapter( self, BBB, thisBook, chapter ): """ Check/validate and extract chapter data from the given XML book record finding and saving chapter numbers and finding and saving verse elements. """ if BibleOrgSysGlobals.debugFlag and debuggingThisModule and BibleOrgSysGlobals.verbosityLevel > 3: print( _("Validating XML chapter…") ) # Process the chapter attributes first chapterNumber = numVerses = None for attrib,value in chapter.items(): if attrib=="n": chapterNumber = value else: logging.warning( "Unprocessed {!r} attribute ({}) in chapter element".format( attrib, value ) ) if chapterNumber: #print( BBB, 'c', chapterNumber ) thisBook.addLine( 'c', chapterNumber ) else: logging.error( "Missing 'n' attribute in chapter element for {}".format( BBB ) ) for element in chapter: if element.tag == VerseViewXMLBible.verseTag: location = "verse in {} {}".format( BBB, chapterNumber ) self.__validateAndExtractVerse( BBB, chapterNumber, thisBook, element ) else: logging.error( "sv34 Expected to find {!r} but got {!r}".format( VerseViewXMLBible.verseTag, element.tag ) ) # end of VerseViewXMLBible.__validateAndExtractChapter def __validateAndExtractVerse( self, BBB, chapterNumber, thisBook, verse ): """ Check/validate and extract verse data from the given XML book record finding and saving verse elements. """ if BibleOrgSysGlobals.debugFlag and debuggingThisModule and BibleOrgSysGlobals.verbosityLevel > 3: print( _("Validating XML verse…") ) location = "verse in {} {}".format( BBB, chapterNumber ) BibleOrgSysGlobals.checkXMLNoSubelements( verse, location, 'sg20' ) BibleOrgSysGlobals.checkXMLNoTail( verse, location, 'l5ks' ) # Handle verse attributes verseNumber = toVerseNumber = None for attrib,value in verse.items(): if attrib=="n": verseNumber = value else: logging.warning( "Unprocessed {!r} attribute ({}) in verse element".format( attrib, value ) ) if BibleOrgSysGlobals.debugFlag: assert verseNumber location = "{}:{}".format( location, verseNumber ) # Get a better location description #thisBook.addLine( 'v', verseNumber ) vText = '' if verse.text is None else verse.text if vText: vText = vText.strip() #if not vText: # This happens if a verse starts immediately with a style or note #logging.warning( "{} {}:{} has no text".format( BBB, chapterNumber, verseNumber ) ) ## Handle verse subelements (notes and styled portions) #for subelement in verse: #if subelement.tag == VerseViewXMLBible.noteTag: #sublocation = "note in " + location #noteType = None #for attrib,value in subelement.items(): #if attrib=="type": noteType = value #else: logging.warning( "Unprocessed {!r} attribute ({}) in style subelement".format( attrib, value ) ) #if noteType and noteType not in ('variant',): #logging.warning( "Unexpected {} note type in {}".format( noteType, BBB ) ) #nText, nTail = subelement.text, subelement.tail ##print( "note", BBB, chapterNumber, verseNumber, noteType, repr(nText), repr(nTail) ) #vText += "\\f + \\fk {} \\ft {}\\f*".format( noteType, nText ) if noteType else "\\f + \\ft {}\\f*".format( nText ) #if nTail: #if '\n' in nTail: #print( "VerseViewXMLBible.__validateAndExtractVerse: nTail {} {}:{} {!r}".format( BBB, chapterNumber, verseNumber, nTail ) ) #nTail = nTail.replace( '\n', ' ' ) #vText += nTail #for subsubelement in subelement: #if subsubelement.tag == VerseViewXMLBible.styleTag: #subsublocation = "style in " + sublocation #BibleOrgSysGlobals.checkXMLNoSubelements( subsubelement, subsublocation, 'fyt4' ) #fs = css = idStyle = None #for attrib,value in subsubelement.items(): #if attrib=='fs': fs = value ##elif attrib=="css": css = value ##elif attrib=="id": idStyle = value #else: logging.warning( "Unprocessed {!r} attribute ({}) in style subsubelement".format( attrib, value ) ) #if BibleOrgSysGlobals.debugFlag: assert fs or css or idStyle #SFM = None #if fs == 'italic': SFM = '\\it' #elif fs == 'super': SFM = '\\bdit' #elif fs == 'emphasis': SFM = '\\em' #else: print( "fs is", fs, "css is", css, "idStyle is", idStyle ); halt ##if css == "font-style:italic": SFM = '\\it' ##elif css == "font-style:italic;font-weight:bold": SFM = '\\bdit' ##elif css == "color:#FF0000": SFM = '\\em' ##elif css == "font-size: x-small; color:#8B8378": SFM = '\\add' ##elif css is None and idStyle=='cl:divineName': SFM = '\\nd' ##else: print( "css is", css, "idStyle is", idStyle ); halt #sText, sTail = subsubelement.text.strip(), subsubelement.tail #if BibleOrgSysGlobals.debugFlag: assert sText #if SFM: vText += SFM+' ' + sText + SFM+'*' #else: vText += '\\sc ' + '['+css+']' + sText + '\\sc* ' # Use sc for unknown styles #if sTail: vText += sTail.strip() #else: logging.error( "df20 Expected to find {} but got {!r} in {}".format( VerseViewXMLBible.styleTag, subsubelement.tag, sublocation ) ) #elif subelement.tag == VerseViewXMLBible.styleTag: #sublocation = "style in " + location #BibleOrgSysGlobals.checkXMLNoSubelements( subelement, sublocation, 'f5gh' ) #fs = css = idStyle = None #for attrib,value in subelement.items(): #if attrib=="fs": fs = value ##elif attrib=="css": css = value ##elif attrib=="id": idStyle = value #else: logging.warning( "Unprocessed {!r} attribute ({}) in style subelement".format( attrib, value ) ) #if BibleOrgSysGlobals.debugFlag: assert fs #SFM = None #if fs == 'super': SFM = '\\bdit' #elif fs == 'emphasis': SFM = '\\em' #else: print( "fs is", fs, "css is", css, "idStyle is", idStyle ); halt ##if css == "font-style:italic": SFM = '\\it' ##elif css == "font-style:italic;font-weight:bold": SFM = '\\bdit' ##elif css == "color:#FF0000": SFM = '\\em' ##elif css == "font-size: x-small; color:#8B8378": SFM = '\\add' ##elif css is None and idStyle=='cl:divineName': SFM = '\\nd' ##else: print( "css is", css, "idStyle is", idStyle ); halt #sText, sTail = subelement.text.strip(), subelement.tail #if BibleOrgSysGlobals.debugFlag: assert sText ##print( BBB, chapterNumber, sublocation ) #if SFM: vText += SFM+' ' + sText + SFM+'*' #else: vText += '\\sc ' + '['+css+']' + sText + '\\sc* ' # Use sc for unknown styles #if sTail: vText += sTail.strip() #elif subelement.tag == VerseViewXMLBible.breakTag: #sublocation = "line break in " + location #BibleOrgSysGlobals.checkXMLNoText( subelement, sublocation, 'c1d4' ) #BibleOrgSysGlobals.checkXMLNoSubelements( subelement, sublocation, 'g4g8' ) #art = None #for attrib,value in subelement.items(): #if attrib=="art": #art = value #else: logging.warning( "Unprocessed {!r} attribute ({}) in style subelement".format( attrib, value ) ) #if BibleOrgSysGlobals.debugFlag: assert art == 'x-nl' ##print( BBB, chapterNumber, verseNumber ) ##assert vText #if vText: #thisBook.addLine( 'v', verseNumber + ' ' + vText ); verseNumber = None #vText = '' #thisBook.addLine( 'm', subelement.tail.strip() if subelement.tail else '' ) ##bTail = subelement.tail ##if bTail: vText = bTail.strip() #else: logging.error( "bd47 Expected to find NOTE or STYLE but got {!r} in {}".format( subelement.tag, location ) ) if vText: # This is the main text of the verse (follows the verse milestone) if '\n' in vText: print( "VerseViewXMLBible.__validateAndExtractVerse: vText {} {}:{} {!r}".format( BBB, chapterNumber, verseNumber, vText ) ) vText = vText.replace( '\n', ' ' ) thisBook.addLine( 'v', verseNumber + ' ' + vText ); verseNumber = None
def createOpenSongXML(BibleObject, outputFolder=None, controlDict=None, validationSchema=None): """ Using settings from the given control file, converts the USFM information to a UTF-8 OpenSong XML file. This format is roughly documented at http://de.wikipedia.org/wiki/OpenSong_XML but more fields can be discovered by looking at downloaded files. """ if BibleOrgSysGlobals.verbosityLevel > 1: print("Running createOpenSongXML…") if BibleOrgSysGlobals.debugFlag: assert BibleObject.books ignoredMarkers, unhandledMarkers, unhandledBooks = set(), set(), [] def writeOpenSongBook(writerObject, BBB, bkData): """Writes a book to the OpenSong XML writerObject.""" #print( 'BIBLEBOOK', [('bnumber',BibleOrgSysGlobals.BibleBooksCodes.getReferenceNumber(BBB)), ('bname',BibleOrgSysGlobals.BibleBooksCodes.getEnglishName_NR(BBB)), ('bsname',BibleOrgSysGlobals.BibleBooksCodes.getOSISAbbreviation(BBB))] ) OSISAbbrev = BibleOrgSysGlobals.BibleBooksCodes.getOSISAbbreviation( BBB) if not OSISAbbrev: logging.warning( "toOpenSong: Can't write {} OpenSong book because no OSIS code available" .format(BBB)) unhandledBooks.append(BBB) return writerObject.writeLineOpen('b', ('n', bkData.getAssumedBookNames()[0])) haveOpenChapter, startedFlag, gotVP, accumulator = False, False, None, "" C, V = '-1', '-1' # So first/id line starts at -1:0 for processedBibleEntry in bkData._processedLines: # Process internal Bible data lines marker, text, extras = processedBibleEntry.getMarker( ), processedBibleEntry.getCleanText( ), processedBibleEntry.getExtras() #print( marker, repr(text) ) #if text: assert text[0] != ' ' if '¬' in marker or marker in BOS_ADDED_NESTING_MARKERS: continue # Just ignore added markers -- not needed here if marker in USFM_PRECHAPTER_MARKERS: if debuggingThisModule or BibleOrgSysGlobals.debugFlag or BibleOrgSysGlobals.strictCheckingFlag: assert C == '-1' or marker == 'rem' or marker.startswith( 'mte') V = str(int(V) + 1) if marker in OFTEN_IGNORED_USFM_HEADER_MARKERS or marker in ( 'ie', ): # Just ignore these lines ignoredMarkers.add(marker) elif marker == 'c': if accumulator: writerObject.writeLineOpenClose('v', accumulator, ('n', verseNumberString)) accumulator = '' if haveOpenChapter: writerObject.writeLineClose('c') C, V = text, '0' writerObject.writeLineOpen('c', ('n', text)) haveOpenChapter = True elif marker in ( 'c#', ): # These are the markers that we can safely ignore for this export ignoredMarkers.add(marker) elif marker == 'vp#': # This precedes a v field and has the verse number to be printed gotVP = text # Just remember it for now elif marker == 'v': V = text if gotVP: # this is the verse number to be published text = gotVP gotVP = None startedFlag = True if accumulator: writerObject.writeLineOpenClose('v', accumulator, ('n', verseNumberString)) accumulator = '' #print( "Text {!r}".format( text ) ) if not text: logging.warning("createOpenSongXML: Missing text for v") continue verseNumberString = text.replace('<', '').replace( '>', '' ).replace( '"', '' ) # Used below but remove anything that'll cause a big XML problem later elif marker in ('mt1','mt2','mt3','mt4', 'mte1','mte2','mte3','mte4', 'ms1','ms2','ms3','ms4', ) \ or marker in USFM_INTRODUCTION_MARKERS \ or marker in ('s1','s2','s3','s4', 'r','sr','mr', 'd','sp','cd', 'cl','lit', ): ignoredMarkers.add(marker) elif marker in USFM_BIBLE_PARAGRAPH_MARKERS: if BibleOrgSysGlobals.debugFlag: assert not text and not extras ignoredMarkers.add(marker) elif marker in ( 'b', 'nb', 'ib', ): if BibleOrgSysGlobals.debugFlag: assert not text and not extras ignoredMarkers.add(marker) elif marker in ( 'v~', 'p~', ): if BibleOrgSysGlobals.debugFlag: assert text or extras if not text: # this is an empty (untranslated) verse text = '- - -' # but we'll put in a filler if startedFlag: accumulator += (' ' if accumulator else '') + BibleOrgSysGlobals.makeSafeXML(text) else: if text: logging.warning( "toOpenSong: lost text in {} field in {} {}:{} {!r}". format(marker, BBB, C, V, text)) #if BibleOrgSysGlobals.debugFlag: halt if extras: logging.warning( "toOpenSong: lost extras in {} field in {} {}:{}". format(marker, BBB, C, V)) #if BibleOrgSysGlobals.debugFlag: halt unhandledMarkers.add(marker) if extras and marker not in ( 'v~', 'p~', ) and marker not in ignoredMarkers: logging.critical( "toOpenSong: extras not handled for {} at {} {}:{}".format( marker, BBB, C, V)) if accumulator: writerObject.writeLineOpenClose('v', accumulator, ('n', verseNumberString)) if haveOpenChapter: writerObject.writeLineClose('c') writerObject.writeLineClose('b') # end of createOpenSongXML.writeOpenSongBook # Set-up our Bible reference system if 'PublicationCode' not in controlDict or controlDict[ 'PublicationCode'] == 'GENERIC': BOS = BibleObject.genericBOS BRL = BibleObject.genericBRL else: BOS = BibleOrganizationalSystem(controlDict['PublicationCode']) BRL = BibleReferenceList(BOS, BibleObject=None) if BibleOrgSysGlobals.verbosityLevel > 2: print(_(" Exporting to OpenSong format…")) try: osOFn = controlDict['OpenSongOutputFilename'] except KeyError: osOFn = 'Bible.osong' filename = BibleOrgSysGlobals.makeSafeFilename(osOFn) xw = MLWriter(filename, outputFolder) xw.setHumanReadable() xw.start() xw.writeLineOpen('Bible') for BBB, bookData in BibleObject.books.items(): writeOpenSongBook(xw, BBB, bookData) xw.writeLineClose('Bible') xw.close() if ignoredMarkers: logging.info("createOpenSongXML: Ignored markers were {}".format( ignoredMarkers)) if BibleOrgSysGlobals.verbosityLevel > 2: print(" " + _("WARNING: Ignored createOpenSongXML markers were {}" ).format(ignoredMarkers)) if unhandledMarkers: logging.warning("createOpenSongXML: Unhandled markers were {}".format( unhandledMarkers)) if BibleOrgSysGlobals.verbosityLevel > 1: print(" " + _("WARNING: Unhandled toOpenSong markers were {}").format( unhandledMarkers)) if unhandledBooks: logging.warning("createOpenSongXML: Unhandled books were {}".format( unhandledBooks)) if BibleOrgSysGlobals.verbosityLevel > 1: print(" " + _("WARNING: Unhandled createOpenSongXML books were {}" ).format(unhandledBooks)) # Now create a zipped version filepath = os.path.join(outputFolder, filename) if BibleOrgSysGlobals.verbosityLevel > 2: print(" Zipping {} OpenSong file…".format(filename)) zf = zipfile.ZipFile(filepath + '.zip', 'w', compression=zipfile.ZIP_DEFLATED) zf.write(filepath, filename) zf.close() if validationSchema: return xw.validate(validationSchema) if BibleOrgSysGlobals.verbosityLevel > 0 and BibleOrgSysGlobals.maxProcesses > 1: print(" createOpenSongXML finished successfully.") return True
class BibleReferenceBox( Frame, BibleBoxAddon ): """ """ def __init__( self, parentWindow, parentFrame, parentApp, internalBible, referenceObject ): """ """ if BibleOrgSysGlobals.debugFlag: print( exp("BibleReferenceBox.__init__( {}, {}. {}, {}, {} )").format( parentWindow, parentFrame, parentApp, internalBible.getAName(), referenceObject ) ) self.parentWindow, self.parentFrame, self.parentApp, self.referenceObject = parentWindow, parentFrame, parentApp, referenceObject self.internalBible = handleInternalBibles( self.parentApp, internalBible, self ) Frame.__init__( self, parentFrame ) BibleBoxAddon.__init__( self, parentWindow, 'BibleReferenceBox' ) # Set some dummy values required soon #self._contextViewRadioVar, self._formatViewRadioVar, self._groupRadioVar = tk.IntVar(), tk.IntVar(), tk.StringVar() #self._groupCode = BIBLE_GROUP_CODES[0] # Put into first/default BCV group #self._contextViewMode = DEFAULT #self._formatViewMode = DEFAULT self.currentVerseKey = SimpleVerseKey( 'UNK','1','1' ) # Unknown book #if self._contextViewMode == DEFAULT: #self._contextViewMode = 'ByVerse' #self.parentWindow.viewVersesBefore, self.parentWindow.viewVersesAfter = 2, 6 #if self._formatViewMode == DEFAULT: #self._formatViewMode = 'Formatted' # Create a title bar titleBar = Frame( self ) Button( titleBar, text=_('Close'), command=self.doClose ).pack( side=tk.RIGHT ) ## Try to get the title width somewhere near correct (if moduleID is a long path) #adjModuleID = moduleID #self.update() # so we can get the geometry #width = parseWindowSize( self.parentWindow.winfo_geometry() )[0] - 60 # Allow for above button #if len(adjModuleID)*10 > width: # Note: this doesn't adjust if the window size is changed #print( "BRB here1", len(adjModuleID), width, repr(adjModuleID) ) #x = len(adjModuleID)*100/width # not perfect (too small) for narrow windows #adjModuleID = '…' + adjModuleID[int(x):] #print( "BRB here2", len(adjModuleID), x, repr(adjModuleID) ) #titleText = '{} ({})'.format( adjModuleID, boxType.replace( 'BibleReferenceBox', '' ) ) titleText = self.referenceObject.getShortText() self.titleLabel = tk.Label( titleBar, text=titleText ) self.titleLabel.pack( side=tk.TOP, fill=tk.X ) titleBar.pack( side=tk.TOP, fill=tk.X ) # Create a scroll bar to fill the right-hand side of the window self.vScrollbar = Scrollbar( self ) self.vScrollbar.pack( side=tk.RIGHT, fill=tk.Y ) self.textBox = BText( self, height=5, yscrollcommand=self.vScrollbar.set ) self.textBox.configure( wrap='word' ) self.textBox.pack( expand=tk.YES, fill=tk.X ) # Full width self.vScrollbar.configure( command=self.textBox.yview ) # link the scrollbar to the text box self.createStandardBoxKeyboardBindings() self.textBox.bind( '<Button-1>', self.setFocus ) # So disabled text box can still do select and copy functions # Set-up our standard Bible styles for USFMKey, styleDict in self.parentApp.stylesheet.getTKStyles().items(): self.textBox.tag_configure( USFMKey, **styleDict ) # Create the style # Add our extra specialised styles self.textBox.tag_configure( 'contextHeader', background='pink', font='helvetica 6 bold' ) self.textBox.tag_configure( 'context', background='pink', font='helvetica 6' ) self.textBox.tag_configure( 'markersHeader', background='yellow3', font='helvetica 6 bold' ) self.textBox.tag_configure( 'markers', background='yellow3', font='helvetica 6' ) self.pack( expand=tk.YES, fill=tk.BOTH ) # Pack the frame # Set-up our Bible system and our callables self.BibleOrganisationalSystem = BibleOrganizationalSystem( 'GENERIC-KJV-80-ENG' ) # temp self.getNumChapters = self.BibleOrganisationalSystem.getNumChapters self.getNumVerses = lambda BBB,C: MAX_PSEUDOVERSES if C=='-1' or C==-1 \ else self.BibleOrganisationalSystem.getNumVerses( BBB, C ) self.isValidBCVRef = self.BibleOrganisationalSystem.isValidBCVRef self.getFirstBookCode = self.BibleOrganisationalSystem.getFirstBookCode self.getPreviousBookCode = self.BibleOrganisationalSystem.getPreviousBookCode self.getNextBookCode = self.BibleOrganisationalSystem.getNextBookCode self.getBBBFromText = self.BibleOrganisationalSystem.getBBBFromText self.getBookName = self.BibleOrganisationalSystem.getBookName self.getBookList = self.BibleOrganisationalSystem.getBookList self.maxChaptersThisBook, self.maxVersesThisChapter = 150, 150 # temp self.verseCache = OrderedDict() self.updateShownReferences( self.referenceObject ) # end of BibleReferenceBox.__init__ def createStandardBoxKeyboardBindings( self ): """ Create keyboard bindings for this widget. """ if BibleOrgSysGlobals.debugFlag and debuggingThisModule: print( exp("BibleReferenceBox.createStandardBoxKeyboardBindings()") ) for name,command in ( ('SelectAll',self.doSelectAll), ('Copy',self.doCopy), ('Find',self.doBoxFind), ('Refind',self.doBoxRefind), #('Info',self.doShowInfo), #('ShowMain',self.doShowMainWindow), ('Close',self.doClose), ): self._createStandardBoxKeyboardBinding( name, command ) # end of BibleReferenceBox.createStandardBoxKeyboardBindings() def xxxgotoBCV( self, BBB, C, V ): """ """ if BibleOrgSysGlobals.debugFlag: print( exp("BibleReferenceBox.gotoBCV( {} {}:{} from {} )").format( BBB, C, V, self.currentVerseKey ) ) # We really need to convert versification systems here adjBBB, adjC, adjV, adjS = self.BibleOrganisationalSystem.convertToReferenceVersification( BBB, C, V ) self.parentWindow.gotoGroupBCV( self._groupCode, adjBBB, adjC, adjV ) # then the App will update me by calling updateShownBCV # end of BibleReferenceBox.gotoBCV def getContextVerseData( self, verseKey ): """ Fetches and returns the internal Bible data for the given reference. """ if BibleOrgSysGlobals.debugFlag and debuggingThisModule: print( exp("BibleReferenceBox.getContextVerseData( {} )").format( verseKey ) ) if self.internalBible is not None: try: return self.internalBible.getContextVerseData( verseKey ) except KeyError: # Could be after a verse-bridge ??? if verseKey.getChapterNumber() != '0': logging.error( exp("BibleReferenceBox.getContextVerseData for {} {} got a KeyError") \ .format( self.boxType, verseKey ) ) # end of BibleReferenceBox.getContextVerseData #def XXXgetSwordVerseKey( self, verseKey ): ##if BibleOrgSysGlobals.debugFlag and debuggingThisModule: print( exp("getSwordVerseKey( {} )").format( verseKey ) ) #BBB, C, V = verseKey.getBCV() #return self.parentApp.SwordInterface.makeKey( BBB, C, V ) ## end of BibleReferenceBox.getSwordVerseKey def getCachedVerseData( self, verseKey ): """ Checks to see if the requested verse is in our cache, otherwise calls getContextVerseData (from the superclass) to fetch it. The cache keeps the newest or most recently used entries at the end. When it gets too large, it drops the first entry. """ #if BibleOrgSysGlobals.debugFlag and debuggingThisModule: print( exp("getCachedVerseData( {} )").format( verseKey ) ) verseKeyHash = verseKey.makeHash() if verseKeyHash in self.verseCache: #if BibleOrgSysGlobals.debugFlag and debuggingThisModule: print( " " + exp("Retrieved from BibleReferenceBox cache") ) self.verseCache.move_to_end( verseKeyHash ) #print( " returning", self.verseCache[verseKeyHash][0] ) return self.verseCache[verseKeyHash] verseContextData = self.getContextVerseData( verseKey ) self.verseCache[verseKeyHash] = verseContextData if len(self.verseCache) > MAX_CACHED_VERSES: #print( "Removing oldest cached entry", len(self.verseCache) ) self.verseCache.popitem( last=False ) return verseContextData # end of BibleReferenceBox.getCachedVerseData def updateShownReferences( self, newReferenceObject ): """ Updates self in various ways depending on the contextViewMode held by the enclosing window. The new verse references are in the reference versification system in one of these objects: SimpleVerseKey (accepts 'GEN_1:1' or 'GEN','1','1') SimpleVersesKey (accepts 'MAT_6:1,4') VerseRangeKey (accepts 'JNA_2:1-7') Leaves the textbox in the disabled state. """ if BibleOrgSysGlobals.debugFlag and debuggingThisModule: print( "BibleReferenceBox.updateShownReferences( {} ) for {}".format( newReferenceObject, self.internalBible.getAName() ) ) assert isinstance( newReferenceObject, SimpleVerseKey ) or isinstance( newReferenceObject, SimpleVersesKey ) or isinstance( newReferenceObject, VerseRangeKey ) for j, referenceVerse in enumerate( newReferenceObject ): #print( " refVerse", j, referenceVerse ) assert isinstance( referenceVerse, SimpleVerseKey ) refBBB, refC, refV, refS = referenceVerse.getBCVS() BBB, C, V, S = self.BibleOrganisationalSystem.convertFromReferenceVersification( refBBB, refC, refV, refS ) newVerseKey = SimpleVerseKey( BBB, C, V, S ) #print( " newVK", newVerseKey ) # Set firstFlag as False (rather than j==0) so don't get context displayed self.displayAppendVerse( False, newVerseKey, self.getCachedVerseData( newVerseKey ), lastFlag=False ) self.textBox.configure( state=tk.DISABLED ) # Don't allow editing # end of BibleReferenceBox.updateShownReferences def doClose( self, event=None ): """ Called from the GUI. Can be overridden. """ self.closeReferenceBox() # end of BibleReferenceBox.doClose def closeReferenceBox( self ): """ Called to finally and irreversibly remove this box from our list and close it. """ if BibleOrgSysGlobals.debugFlag and debuggingThisModule: print( exp("BibleReferenceBox.closeReferenceBox()") ) if self in self.parentWindow.referenceBoxes: self.parentWindow.referenceBoxes.remove( self ) self.destroy() else: # we might not have finished making our box yet if BibleOrgSysGlobals.debugFlag: print( exp("BibleReferenceBox.closeReferenceBox() for {} wasn't in list").format( self.windowType ) ) try: self.destroy() except tk.TclError: pass # never mind if BibleOrgSysGlobals.debugFlag: self.parentApp.setDebugText( "Closed resource box" )
def load(self): """ Load a single source file and load book elements. """ if BibleOrgSysGlobals.verbosityLevel > 2: print(_("Loading {}…").format(self.sourceFilepath)) global BOS66, BOS81, BOSx if BOS66 is None: BOS66 = BibleOrganizationalSystem('GENERIC-KJV-66-ENG') if BOS81 is None: BOS81 = BibleOrganizationalSystem('GENERIC-KJV-80-ENG') if BOSx is None: BOSx = BibleOrganizationalSystem('GENERIC-ENG') if self.suppliedMetadata is None: self.suppliedMetadata = {} lastLine, lineCount = '', 0 vplType = bookCodeText = lastBookCodeText = BBB = lastBBB = metadataName = None lastChapterNumber = lastVerseNumber = -1 lastVText = '' thisBook = None settingsDict = {} with open(self.sourceFilepath, encoding=self.encoding ) as myFile: # Automatically closes the file when done for line in myFile: lineCount += 1 if line[-1] == '\n': line = line[:-1] # Removing trailing newline character if not line: continue # Just discard blank lines if lineCount == 1: if self.encoding.lower() == 'utf-8' and line[0] == chr( 65279): #U+FEFF or \ufeff logging.info( " VPLBible.load: Detected Unicode Byte Order Marker (BOM)" ) line = line[ 1:] # Remove the Unicode Byte Order Marker (BOM) # Try to identify the VPL type match = re.search( '^(\\w{2,5}?)\\s(\\d{1,3})[:\\.](\\d{1,3})\\s', line) if match: vplType = 1 else: match = re.search('^(\\d{8})\\s', line) if match: vplType = 2 else: match = re.search('^# language_name:\\s', line) if match: vplType = 3 #else: #match = re.search( '^; TITLE:\\s', line ) #if match: vplType = 4 if match: if BibleOrgSysGlobals.debugFlag: print( "First line got type #{} {!r} match from {!r}". format(vplType, match.group(0), line)) else: if BibleOrgSysGlobals.verbosityLevel > 3: print( "VPLBible.load: (unexpected) first line was {!r} in {}" .format(line, self.sourceFilepath)) if BibleOrgSysGlobals.debugFlag and debuggingThisModule: halt continue #print( 'vplType', vplType ) #print ( 'VPL file line is "' + line + '"' ) lastLine = line # Process header stuff if vplType == 3: if line.startswith('# language_name:'): string = line[16:].strip() if string and string != 'Not available': settingsDict['LanguageName'] = string continue elif line.startswith('# closest ISO 639-3:'): string = line[20:].strip() if string and string != 'Not available': settingsDict['ISOLanguageCode'] = string continue elif line.startswith('# year_short:'): string = line[13:].strip() if string and string != 'Not available': settingsDict['Year.short'] = string continue elif line.startswith('# year_long:'): string = line[12:].strip() if string and string != 'Not available': settingsDict['Year.long'] = string continue elif line.startswith('# title:'): string = line[8:].strip() if string and string != 'Not available': settingsDict['WorkTitle'] = string continue elif line.startswith('# URL:'): string = line[6:].strip() if string and string != 'Not available': settingsDict['URL'] = string continue elif line.startswith('# copyright_short:'): string = line[18:].strip() if string and string != 'Not available': settingsDict['Copyright.short'] = string continue elif line.startswith('# copyright_long:'): string = line[17:].strip() if string and string != 'Not available': settingsDict['Copyright.long'] = string continue elif line[0] == '#': logging.warning( "VPLBible.load {} is skipping unknown line: {}". format(vplType, line)) continue # Just discard comment lines #elif vplType == 4: #if line.startswith( '; TITLE:' ): #string = line[8:].strip() #if string: settingsDict['TITLE'] = string #continue #elif line.startswith( '; ABBREVIATION:' ): #string = line[15:].strip() #if string: settingsDict['ABBREVIATION'] = string #continue #elif line.startswith( '; HAS ITALICS:' ): #string = line[15:].strip() #if string: settingsDict['HAS_ITALICS'] = string #continue #elif line.startswith( '; HAS FOOTNOTES:' ): #string = line[15:].strip() #if string: settingsDict['HAS_FOOTNOTES'] = string #continue #elif line.startswith( '; HAS FOOTNOTES' ): #string = line[14:].strip() #if string: settingsDict['HAS_FOOTNOTES'] = string #continue #elif line.startswith( '; HAS REDLETTER:' ): #string = line[15:].strip() #if string: settingsDict['HAS_REDLETTER'] = string #continue #elif line[0]==';': #logging.warning( "VPLBible.load{} is skipping unknown header/comment line: {}".format( vplType, line ) ) #continue # Just discard comment lines # Process the main segment if vplType == 1: bits = line.split(' ', 2) #print( self.givenName, BBB, bits ) if len(bits) == 3 and ':' in bits[1]: bookCodeText, CVString, vText = bits chapterNumberString, verseNumberString = CVString.split( ':') #print( "{} {} bc={!r} c={!r} v={!r} txt={!r}".format( self.givenName, BBB, bookCodeText, chapterNumberString, verseNumberString, vText ) ) if chapterNumberString == '': chapterNumberString = '1' # Handle a bug in some single chapter books in VPL else: print("Unexpected number of bits", self.givenName, BBB, bookCodeText, chapterNumberString, verseNumberString, len(bits), bits) if not bookCodeText and not chapterNumberString and not verseNumberString: print("Skipping empty line in {} {} {} {}:{}".format( self.givenName, BBB, bookCodeText, chapterNumberString, verseNumberString)) continue if BibleOrgSysGlobals.debugFlag: assert 2 <= len(bookCodeText) <= 4 if BibleOrgSysGlobals.debugFlag: assert chapterNumberString.isdigit() if not verseNumberString.isdigit(): logging.error( "Invalid verse number field at {}/{} {}:{!r}". format(bookCodeText, BBB, chapterNumberString, verseNumberString)) if BibleOrgSysGlobals.debugFlag and debuggingThisModule: assert verseNumberString.isdigit() continue chapterNumber = int(chapterNumberString) verseNumber = int(verseNumberString) if bookCodeText != lastBookCodeText: # We've started a new book lastBBB = BBB #if bookCodeText in ('Ge',): BBB = 'GEN' if bookCodeText == 'Le' and lastBBB == 'GEN': BBB = 'LEV' elif bookCodeText in ('Jud', ) and lastBBB == 'JOS': BBB = 'JDG' #elif bookCodeText in ('Es',): BBB = 'EST' #elif bookCodeText in ('Pr',): BBB = 'PRO' #elif bookCodeText in ('So','SOL') and lastBBB == 'ECC': BBB = 'SNG' #elif bookCodeText in ('La',) and lastBBB == 'JER': BBB = 'LAM' #elif bookCodeText == 'PHI' and lastBBB == 'EPH': BBB = 'PHP' #elif bookCodeText == 'PHI' and self.givenName == "bjp_vpl": BBB = 'PHP' # Hack for incomplete NT #elif bookCodeText in ('Jude',): BBB = 'JDE' #elif bookCodeText == 'PRA' and lastBBB == 'LJE': BBB = 'PAZ' #elif bookCodeText == 'PRM' and lastBBB == 'GES': BBB = 'MAN' else: BBB = BOS66.getBBBFromText( bookCodeText) # Try to guess if not BBB: BBB = BOS81.getBBBFromText( bookCodeText) # Try to guess if not BBB: BBB = BOSx.getBBBFromText( bookCodeText) # Try to guess if not BBB: BBB = BibleOrgSysGlobals.BibleBooksCodes.getBBBFromText( bookCodeText) # Try to guess if not BBB: logging.critical( "VPL Bible: Unable to determine book code from text {!r} after {!r}={}" .format(bookCodeText, lastBookCodeText, lastBBB)) halt # Handle special formatting # [square-brackets] are for Italicized words # <angle-brackets> are for the Words of Christ in Red # «chevrons» are for the Titles in the Book of Psalms. vText = vText.replace( '[', '\\add ' ).replace( ']', '\\add*' ) \ .replace( '<', '\\wj ' ).replace( '>', '\\wj*' ) if vText and vText[0] == '«': #print( "Oh!", BBB, chapterNumberString, verseNumberString, repr(vText) ) if BBB == 'PSA' and verseNumberString == '1': # Psalm title vBits = vText[1:].split('»') #print( "vBits", vBits ) thisBook.addLine('d', vBits[0]) # Psalm title vText = vBits[1].lstrip() # Handle the verse info #if verseNumber==lastVerseNumber and vText==lastVText: #logging.warning( _("Ignored duplicate verse line in {} {} {} {}:{}").format( self.givenName, BBB, bookCodeText, chapterNumberString, verseNumberString ) ) #continue if BBB == 'PSA' and verseNumberString == '1' and vText.startswith( '<') and self.givenName == 'basic_english': # Move Psalm titles to verse zero verseNumber = 0 #if verseNumber < lastVerseNumber: #logging.warning( _("Ignored receding verse number (from {} to {}) in {} {} {} {}:{}").format( lastVerseNumber, verseNumber, self.givenName, BBB, bookCodeText, chapterNumberString, verseNumberString ) ) #elif verseNumber == lastVerseNumber: #if vText == lastVText: #logging.warning( _("Ignored duplicated {} verse in {} {} {} {}:{}").format( verseNumber, self.givenName, BBB, bookCodeText, chapterNumberString, verseNumberString ) ) #else: #logging.warning( _("Ignored duplicated {} verse number in {} {} {} {}:{}").format( verseNumber, self.givenName, BBB, bookCodeText, chapterNumberString, verseNumberString ) ) elif vplType in (2, 3): bits = line.split('\t', 1) #print( self.givenName, BBB, bits ) bookNumberString, chapterNumberString, verseNumberString = bits[ 0][:2], bits[0][2:5], bits[0][5:] #print( bookNumberString, chapterNumberString, verseNumberString ) while len(chapterNumberString ) > 1 and chapterNumberString[0] == '0': chapterNumberString = chapterNumberString[ 1:] # Remove leading zeroes while len(verseNumberString ) > 1 and verseNumberString[0] == '0': verseNumberString = verseNumberString[ 1:] # Remove leading zeroes bookCodeText, chapterNumber, verseNumber = int( bookNumberString), int(chapterNumberString), int( verseNumberString) vText = bits[1].replace(' ,',',').replace(' .','.').replace(' ;',';').replace(' :',':') \ .replace(' !','!').replace(' )',')').replace(' ]',']').replace(' ”','”') \ .replace('“ ','“').replace('( ','(').replace('[ ','[') #.replace(' !','!') if bookCodeText != lastBookCodeText: # We've started a new book lastBBB = BBB bnDict = { 67: 'TOB', 68: 'JDT', 69: 'ESG', 70: 'WIS', 71: 'SIR', 72: 'BAR', 73: 'LJE', 74: 'PAZ', 75: 'SUS', 76: 'BEL', 77: 'MA1', 78: 'MA2', 79: 'MA3', 80: 'MA4', 81: 'ES1', 82: 'ES2', 83: 'MAN', 84: 'PS2', 85: 'PSS', 86: 'ODE', } if 1 <= bookCodeText <= 66: BBB = BibleOrgSysGlobals.BibleBooksCodes.getBBBFromReferenceNumber( bookCodeText) else: BBB = bnDict[bookCodeText] #elif vplType == 4: #if line.startswith( '$$ ' ): #if metadataName and metadataContents: #settingsDict[metadataName] = metadataContents #metadataName = None #pointer = line[3:] ##print( "pointer", repr(pointer) ) #if pointer and pointer[0]=='{' and pointer[-1]=='}': #metadataName = pointer[1:-1] #if metadataName: ##print( "metadataName", repr(metadataName) ) #metadataContents = '' #else: # let's assume it's a BCV reference #pointer = pointer.replace( '1 K','1K' ).replace( '2 K','2K' ) \ #.replace( '1 Chr','1Chr' ).replace( '2 Chr','2Chr' ) \ #.replace( '1 Cor','1Cor' ).replace( '2 Cor','2Cor' ) \ #.replace( '1 Thess','1Thess' ).replace( '2 Thess','2Thess' ) \ #.replace( '1 Tim','1Tim' ).replace( '2 Tim','2Tim' ) \ #.replace( '1 Pet','1Pet' ).replace( '2 Pet','2Pet' ) \ #.replace( '1 J','1J' ).replace( '2 J','2J' ).replace( '3 J','3J' ) #B_CV_Bits = pointer.split( ' ', 1 ) #if len(B_CV_Bits) == 2 and ':' in B_CV_Bits[1]: #bookCodeText, CVString = B_CV_Bits #chapterNumberString, verseNumberString = CVString.split( ':' ) #chapterNumber = int( chapterNumberString ) #verseNumber = int( verseNumberString ) #if bookCodeText != lastBookCodeText: # We've started a new book #if bookCodeText in ('Ge',): BBB = 'GEN' #elif bookCodeText in ('Le',): BBB = 'LEV' #elif bookCodeText in ('La',): BBB = 'LAM' #else: ##print( "4bookCodeText =", repr(bookCodeText) ) ##BBB = BOS.getBBBFromText( bookCodeText ) # Try to guess #BBB = BOS66.getBBBFromText( bookCodeText ) # Try to guess #if not BBB: BBB = BOS81.getBBBFromText( bookCodeText ) # Try to guess #if not BBB: BBB = BOSx.getBBBFromText( bookCodeText ) # Try to guess ##print( "4BBB =", repr(BBB) ) #else: print( "Unexpected number of bits", self.givenName, BBB, bookCodeText, chapterNumberString, verseNumberString, len(bits), bits ) #continue # Just save the pointer information which refers to the text on the next line #else: # it's not a $$ line #text = line ##print( "text", repr(text) ) #if metadataName: #metadataContents += ('\n' if metadataContents else '') + text #continue #else: #vText = text ## Handle bits like (<scripref>Pr 2:7</scripref>) #vText = vText.replace( '(<scripref>', '\\x - \\xt ' ).replace( '</scripref>)', '\\x*' ) #vText = vText.replace( '<scripref>', '\\x - \\xt ' ).replace( '</scripref>', '\\x*' ) ##if '\\' in vText: print( 'VPL vText', repr(vText) ) #if vplType == 4: # Forge for SwordSearcher ##print( BBB, chapterNumber, verseNumber, repr(vText) ) ## Convert {stuff} to footnotes #match = re.search( '\\{(.+?)\\}', vText ) #while match: #footnoteText = '\\f + \\fr {}:{} \\ft {}\\f*'.format( chapterNumber, verseNumber, match.group(1) ) #vText = vText[:match.start()] + footnoteText + vText[match.end():] # Replace this footnote ##print( BBB, chapterNumber, verseNumber, repr(vText) ) #match = re.search( '\\{(.+?)\\}', vText ) ## Convert [stuff] to added fields #match = re.search( '\\[(.+?)\\]', vText ) #while match: #addText = '\\add {}\\add*'.format( match.group(1) ) #vText = vText[:match.start()] + addText + vText[match.end():] # Replace this chunk ##print( BBB, chapterNumber, verseNumber, repr(vText) ) #match = re.search( '\\[(.+?)\\]', vText ) #for badChar in '{}[]': #if badChar in vText: #logging.warning( "Found remaining braces or brackets in SwordSearcher Forge VPL {} {}:{} {!r}".format( BBB, chapterNumberString, verseNumberString, vText ) ) #break else: logging.critical('Unknown VPL type {}'.format(vplType)) if BibleOrgSysGlobals.debugFlag and debuggingThisModule: halt if bookCodeText: if bookCodeText != lastBookCodeText: # We've started a new book if lastBookCodeText is not None: # Better save the last book self.stashBook(thisBook) if BBB: if BBB in self: logging.critical( "Have duplicated {} book in {}".format( self.givenName, BBB)) if BibleOrgSysGlobals.debugFlag: assert BBB not in self thisBook = BibleBook(self, BBB) thisBook.objectNameString = 'VPL Bible Book object' thisBook.objectTypeString = 'VPL' verseList = BOSx.getNumVersesList(BBB) numChapters, numVerses = len( verseList), verseList[0] lastBookCodeText = bookCodeText lastChapterNumber = lastVerseNumber = -1 else: logging.critical( "VPLBible{} could not figure out {!r} book code" .format(vplType, bookCodeText)) if BibleOrgSysGlobals.debugFlag: halt if BBB: if chapterNumber != lastChapterNumber: # We've started a new chapter if BibleOrgSysGlobals.debugFlag: assert chapterNumber > lastChapterNumber or BBB == 'ESG' # Esther Greek might be an exception if chapterNumber == 0: logging.info( "Have chapter zero in {} {} {} {}:{}". format(self.givenName, BBB, bookCodeText, chapterNumberString, verseNumberString)) elif chapterNumber > numChapters: logging.error( "Have high chapter number in {} {} {} {}:{} (expected max of {})" .format(self.givenName, BBB, bookCodeText, chapterNumberString, verseNumberString, numChapters)) thisBook.addLine('c', chapterNumberString) lastChapterNumber = chapterNumber lastVerseNumber = -1 # Handle the verse info if verseNumber == lastVerseNumber and vText == lastVText: logging.warning( _("Ignored duplicate verse line in {} {} {} {}:{}" ).format(self.givenName, BBB, bookCodeText, chapterNumberString, verseNumberString)) continue if verseNumber < lastVerseNumber: logging.warning( _("Ignored receding verse number (from {} to {}) in {} {} {} {}:{}" ).format(lastVerseNumber, verseNumber, self.givenName, BBB, bookCodeText, chapterNumberString, verseNumberString)) elif verseNumber == lastVerseNumber: if vText == lastVText: logging.warning( _("Ignored duplicated {} verse in {} {} {} {}:{}" ).format(verseNumber, self.givenName, BBB, bookCodeText, chapterNumberString, verseNumberString)) else: logging.warning( _("Ignored duplicated {} verse number in {} {} {} {}:{}" ).format(verseNumber, self.givenName, BBB, bookCodeText, chapterNumberString, verseNumberString)) # Check for paragraph markers if vText and vText[0] == '¶': thisBook.addLine('p', '') vText = vText[1:].lstrip() #print( '{} {}:{} = {!r}'.format( BBB, chapterNumberString, verseNumberString, vText ) ) thisBook.addLine('v', verseNumberString + ' ' + vText) lastVText = vText lastVerseNumber = verseNumber else: # No bookCodeText yet logging.warning( "VPLBible.load{} is skipping unknown pre-book line: {}" .format(vplType, line)) # Save the final book if thisBook is not None: self.stashBook(thisBook) # Clean up if settingsDict: #print( "VPL settingsDict", settingsDict ) if self.suppliedMetadata is None: self.suppliedMetadata = {} self.suppliedMetadata['VPL'] = settingsDict self.applySuppliedMetadata('VPL') # Copy some to self.settingsDict self.doPostLoadProcessing()
def __init__( self, parentWindow, parentApp, internalBible, referenceObject ): if BibleOrgSysGlobals.debugFlag: print( exp("BibleReferenceBox.__init__( {}, {}, {}, {} )").format( parentWindow, parentApp, internalBible.name, referenceObject ) ) self.parentWindow, self.parentApp, self.internalBible, self.referenceObject = parentWindow, parentApp, internalBible, referenceObject #self.parentApp = self.parentWindow.parentApp Frame.__init__( self, parentWindow ) BibleBox.__init__( self, self.parentApp ) # Set some dummy values required soon self._viewRadioVar, self._groupRadioVar = tk.IntVar(), tk.StringVar() self.groupCode = BIBLE_GROUP_CODES[0] # Put into first/default BCV group self.contextViewMode = DEFAULT self.viewMode = DEFAULT self.currentVerseKey = SimpleVerseKey( 'UNK','1','1' ) # Unknown book if self.contextViewMode == DEFAULT: self.contextViewMode = 'ByVerse' self.parentWindow.viewVersesBefore, self.parentWindow.viewVersesAfter = 2, 6 # Create a title bar titleBar = Frame( self ) Button( titleBar, text=_('Close'), command=self.doClose ).pack( side=tk.RIGHT ) ## Try to get the title width somewhere near correct (if moduleID is a long path) #adjModuleID = moduleID #self.update() # so we can get the geometry #width = parseWindowSize( self.parentWindow.geometry() )[0] - 60 # Allow for above button #if len(adjModuleID)*10 > width: # Note: this doesn't adjust if the window size is changed #print( "BRB here1", len(adjModuleID), width, repr(adjModuleID) ) #x = len(adjModuleID)*100/width # not perfect (too small) for narrow windows #adjModuleID = '…' + adjModuleID[int(x):] #print( "BRB here2", len(adjModuleID), x, repr(adjModuleID) ) #titleText = '{} ({})'.format( adjModuleID, boxType.replace( 'BibleReferenceBox', '' ) ) titleText = self.referenceObject.getShortText() self.titleLabel = tk.Label( titleBar, text=titleText ) self.titleLabel.pack( side=tk.TOP, fill=tk.X ) titleBar.pack( side=tk.TOP, fill=tk.X ) # Create a scroll bar to fill the right-hand side of the window self.vScrollbar = Scrollbar( self ) self.vScrollbar.pack( side=tk.RIGHT, fill=tk.Y ) self.textBox = tk.Text( self, height=4, yscrollcommand=self.vScrollbar.set ) self.textBox['wrap'] = 'word' self.textBox.pack( expand=tk.YES, fill=tk.X ) # Full width self.vScrollbar.config( command=self.textBox.yview ) # link the scrollbar to the text box self.createStandardKeyboardBindings() self.textBox.bind( "<Button-1>", self.setFocus ) # So disabled text box can still do select and copy functions # Set-up our standard Bible styles for USFMKey, styleDict in self.parentApp.stylesheet.getTKStyles().items(): self.textBox.tag_configure( USFMKey, **styleDict ) # Create the style # Add our extra specialised styles self.textBox.tag_configure( 'contextHeader', background='pink', font='helvetica 6 bold' ) self.textBox.tag_configure( 'context', background='pink', font='helvetica 6' ) self.pack( expand=tk.YES, fill=tk.BOTH ) # Pack the frame # Set-up our Bible system and our callables self.BibleOrganisationalSystem = BibleOrganizationalSystem( "GENERIC-KJV-66-ENG" ) # temp self.getNumChapters = self.BibleOrganisationalSystem.getNumChapters self.getNumVerses = lambda b,c: 99 if c=='0' or c==0 else self.BibleOrganisationalSystem.getNumVerses( b, c ) self.isValidBCVRef = self.BibleOrganisationalSystem.isValidBCVRef self.getFirstBookCode = self.BibleOrganisationalSystem.getFirstBookCode self.getPreviousBookCode = self.BibleOrganisationalSystem.getPreviousBookCode self.getNextBookCode = self.BibleOrganisationalSystem.getNextBookCode self.getBBB = self.BibleOrganisationalSystem.getBBB self.getBookName = self.BibleOrganisationalSystem.getBookName self.getBookList = self.BibleOrganisationalSystem.getBookList self.maxChapters, self.maxVerses = 150, 150 # temp self.verseCache = OrderedDict() self.updateShownReferences( self.referenceObject )
class OpenSongXMLBible( Bible ): """ Class for reading, validating, and converting OpenSong Bible XML. """ treeTag = 'bible' bookTag = 'b' chapterTag = 'c' verseTag = 'v' def __init__( self, sourceFolder, givenName, encoding='utf-8' ): """ Constructor: just sets up the XML Bible file converter object. """ # Setup and initialise the base class first if BibleOrgSysGlobals.debugFlag: print( "OpenSongXMLBible( {}, {}, {} )".format( sourceFolder, givenName, encoding ) ) Bible.__init__( self ) self.objectNameString = "OpenSong XML Bible object" self.objectTypeString = "OpenSong" # Now we can set our object variables self.sourceFolder, self.givenName, self.encoding = sourceFolder, givenName, encoding self.sourceFilepath = os.path.join( self.sourceFolder, self.givenName ) self.tree = None # Will hold the XML data # Get the data tables that we need for proper checking #self.ISOLanguages = ISO_639_3_Languages().loadData() self.genericBOS = BibleOrganizationalSystem( "GENERIC-KJV-66-ENG" ) # Do a preliminary check on the readability of our file if not os.access( self.sourceFilepath, os.R_OK ): print( "OpenSongXMLBible: File {!r} is unreadable".format( self.sourceFilepath ) ) self.name = self.givenName #if self.name is None: #pass # end of OpenSongXMLBible.__init__ def load( self ): """ Load a single source XML file and load book elements. """ if BibleOrgSysGlobals.verbosityLevel > 2: print( _("Loading {}...").format( self.sourceFilepath ) ) self.tree = ElementTree().parse( self.sourceFilepath ) if BibleOrgSysGlobals.debugFlag: assert( len ( self.tree ) ) # Fail here if we didn't load anything at all # Find the main (bible) container if self.tree.tag == OpenSongXMLBible.treeTag: location = "XML file" BibleOrgSysGlobals.checkXMLNoText( self.tree, location, '4f6h' ) BibleOrgSysGlobals.checkXMLNoTail( self.tree, location, '1wk8' ) name = shortName = None for attrib,value in self.tree.items(): if attrib=="n": name = value elif attrib=="sn": shortName = value else: logging.warning( "Unprocessed {!r} attribute ({}) in main element".format( attrib, value ) ) # Find the submain (book) containers for element in self.tree: if element.tag == OpenSongXMLBible.bookTag: sublocation = "book in " + location BibleOrgSysGlobals.checkXMLNoText( element, sublocation, 'g3g5' ) BibleOrgSysGlobals.checkXMLNoTail( element, sublocation, 'd3f6' ) self.__validateAndExtractBook( element ) elif element.tag == 'OT': pass elif element.tag == 'NT': pass else: logging.error( "Expected to find {!r} but got {!r}".format( OpenSongXMLBible.bookTag, element.tag ) ) else: logging.error( "Expected to load {!r} but got {!r}".format( OpenSongXMLBible.treeTag, self.tree.tag ) ) self.doPostLoadProcessing() # end of OpenSongXMLBible.load def __validateAndExtractBook( self, book ): """ Check/validate and extract book data from the given XML book record finding chapter subelements. """ if BibleOrgSysGlobals.verbosityLevel > 3: print( _("Validating OpenSong XML book...") ) # Process the div attributes first BBB = bookName = None for attrib,value in book.items(): if attrib=="n": bookName = value else: logging.warning( "Unprocessed {!r} attribute ({}) in book element".format( attrib, value ) ) if bookName: BBB = self.genericBOS.getBBB( bookName ) # Booknames are in English if BBB: if BibleOrgSysGlobals.verbosityLevel > 2: print( _("Validating {} {}...").format( BBB, bookName ) ) thisBook = BibleBook( self, BBB ) thisBook.objectNameString = "OpenSong XML Bible Book object" thisBook.objectTypeString = "OpenSong" #thisBook.sourceFilepath = self.sourceFilepath USFMAbbreviation = BibleOrgSysGlobals.BibleBooksCodes.getUSFMAbbreviation( BBB ) thisBook.addLine( 'id', '{} imported by {}'.format( USFMAbbreviation.upper(), ProgNameVersion ) ) thisBook.addLine( 'h', bookName ) thisBook.addLine( 'mt1', bookName ) for element in book: if element.tag == OpenSongXMLBible.chapterTag: sublocation = "chapter in {}".format( BBB ) BibleOrgSysGlobals.checkXMLNoText( element, sublocation, 'j3jd' ) BibleOrgSysGlobals.checkXMLNoTail( element, sublocation, 'al1d' ) self.__validateAndExtractChapter( BBB, thisBook, element ) else: logging.error( "Expected to find {!r} but got {!r}".format( OpenSongXMLBible.chapterTag, element.tag ) ) if BibleOrgSysGlobals.verbosityLevel > 2: print( " Saving {} into results...".format( BBB ) ) self.saveBook( thisBook ) else: logging.error( _("OpenSong load doesn't recognize book name: {!r}").format( bookName ) ) # no BBB else: logging.error( _("OpenSong load can't find a book name") ) # no bookName # end of OpenSongXMLBible.__validateAndExtractBook def __validateAndExtractChapter( self, BBB, thisBook, chapter ): """ Check/validate and extract chapter data from the given XML book record finding and saving chapter numbers and finding and saving verse elements. """ if BibleOrgSysGlobals.verbosityLevel > 3: print( _("Validating XML chapter...") ) # Process the div attributes first chapterNumber = numVerses = None for attrib,value in chapter.items(): if attrib=="n": chapterNumber = value elif attrib=="VERSES": numVerses = value else: logging.warning( "Unprocessed {!r} attribute ({}) in chapter element".format( attrib, value ) ) if chapterNumber: #print( BBB, 'c', chapterNumber ) chapterNumber = chapterNumber.replace( 'of Solomon ', '' ) # Fix a mistake in the Chinese_SU module thisBook.addLine( 'c', chapterNumber ) else: logging.error( "Missing 'n' attribute in chapter element for BBB".format( BBB ) ) for element in chapter: if element.tag == OpenSongXMLBible.verseTag: sublocation = "verse in {} {}".format( BBB, chapterNumber ) BibleOrgSysGlobals.checkXMLNoTail( element, sublocation, 'l5ks' ) BibleOrgSysGlobals.checkXMLNoSubelements( element, sublocation, '5f7h' ) verseNumber = toVerseNumber = None for attrib,value in element.items(): if attrib=="n": verseNumber = value elif attrib=="t": toVerseNumber = value else: logging.warning( "Unprocessed {!r} attribute ({}) in verse element".format( attrib, value ) ) if BibleOrgSysGlobals.debugFlag: assert( verseNumber ) #thisBook.addLine( 'v', verseNumber ) vText = element.text if not vText: logging.warning( "{} {}:{} has no text".format( BBB, chapterNumber, verseNumber ) ) if vText: # This is the main text of the verse (follows the verse milestone) #print( "{} {}:{} {!r}".format( BBB, chapterNumber, verseNumber, vText ) ) if '\n' in vText: # This is how they represent poety #print( "vText", repr(vText), repr(element.text) ) for j, textBit in enumerate( vText.split( '\n' ) ): if j==0: thisBook.addLine( 'q1', '' ) thisBook.addLine( 'v', verseNumber + ' ' + textBit ) else: thisBook.addLine( 'q1', textBit ) else: # Just one verse line thisBook.addLine( 'v', verseNumber + ' ' + vText ) else: logging.error( "Expected to find {!r} but got {!r}".format( OpenSongXMLBible.verseTag, element.tag ) )
class ZefaniaXMLBible(Bible): """ Class for reading, validating, and converting ZefaniaXMLBible XML. """ XMLNameSpace = "{http://www.w3.org/2001/XMLSchema-instance}" treeTag = 'XMLBIBLE' infoTag = 'INFORMATION' bookTag = 'BIBLEBOOK' chapterTag = 'CHAPTER' captionTag = 'CAPTION' verseTag = 'VERS' noteTag = 'NOTE' styleTag = 'STYLE' breakTag = 'BR' def __init__(self, sourceFolder, givenName, encoding='utf-8'): """ Constructor: just sets up the Zefania Bible object. """ # Setup and initialise the base class first Bible.__init__(self) self.objectNameString = "Zefania XML Bible object" self.objectTypeString = "Zefania" # Now we can set our object variables self.sourceFolder, self.givenName, self.encoding = sourceFolder, givenName, encoding self.sourceFilepath = os.path.join(self.sourceFolder, self.givenName) self.tree = self.header = None # Will hold the XML data # Get the data tables that we need for proper checking #self.ISOLanguages = ISO_639_3_Languages().loadData() self.genericBOS = BibleOrganizationalSystem("GENERIC-KJV-66-ENG") # Do a preliminary check on the readability of our file if not os.access(self.sourceFilepath, os.R_OK): print("ZefaniaXMLBible: File '{}' is unreadable".format( self.sourceFilepath)) self.name = self.givenName #if self.name is None: #pass # end of ZefaniaXMLBible.__init__ def load(self): """ Load a single source XML file and load book elements. """ if Globals.verbosityLevel > 2: print(_("Loading {}...").format(self.sourceFilepath)) self.tree = ElementTree().parse(self.sourceFilepath) if Globals.debugFlag: assert (len(self.tree) ) # Fail here if we didn't load anything at all # Find the main (bible) container if self.tree.tag == ZefaniaXMLBible.treeTag: location = "Zefania XML file" Globals.checkXMLNoText(self.tree, location, '4f6h') Globals.checkXMLNoTail(self.tree, location, '1wk8') schema = None name = status = BibleType = revision = version = lgid = None for attrib, value in self.tree.items(): if attrib == ZefaniaXMLBible.XMLNameSpace + 'noNamespaceSchemaLocation': schema = value elif attrib == "biblename": name = value elif attrib == "lgid": lgid = value # In italian.xml this is set to "german" elif attrib == "status": status = value elif attrib == "type": BibleType = value elif attrib == "revision": revision = value elif attrib == "version": version = value else: logging.warning( "Unprocessed '{}' attribute ({}) in main element". format(attrib, value)) if name: self.name = name if status: self.status = status if revision: self.revision = revision if version: self.version = version if self.tree[0].tag == 'INFORMATION': self.header = self.tree[0] self.tree.remove(self.header) self.__validateAndExtractHeader() else: # Handle information records at the END of the file ix = len(self.tree) - 1 if self.tree[ix].tag == 'INFORMATION': self.header = self.tree[ix] self.tree.remove(self.header) self.__validateAndExtractHeader() # Find the submain (book) containers for element in self.tree: if element.tag == ZefaniaXMLBible.bookTag: sublocation = "book in " + location Globals.checkXMLNoText(element, sublocation, 'g3g5') Globals.checkXMLNoTail(element, sublocation, 'd3f6') self.__validateAndExtractBook(element) else: logging.error("Expected to find '{}' but got '{}'".format( ZefaniaXMLBible.bookTag, element.tag)) else: logging.error("Expected to load '{}' but got '{}'".format( ZefaniaXMLBible.treeTag, self.tree.tag)) self.doPostLoadProcessing() # end of ZefaniaXMLBible.load def __validateAndExtractHeader(self): """ Extracts information out of the header record, such as: <INFORMATION> <title>King James Version</title> <creator></creator> <subject>The Holy Bible</subject> <description>In 1604, King James I of England authorized that a new translation of the Bible into English be started. It was finished in 1611, just 85 years after the first translation of the New Testament into English appeared (Tyndale, 1526). The Authorized Version, or King James Version, quickly became the standard for English-speaking Protestants. Its flowing language and prose rhythm has had a profound influence on the literature of the past 300 years.</description> <publisher>FREE BIBLE SOFTWARE GROUP</publisher> <contributors /> <date>2009-01-23</date> <type>Bible</type> <format>Zefania XML Bible Markup Language</format> <identifier>kjv</identifier> <source>http://www.unboundbible.com/zips/index.cfm?lang=English</source> <language>ENG</language> <coverage>provide the Bible to the nations of the world</coverage> <rights>We believe that this Bible is found in the Public Domain.</rights> </INFORMATION> """ if Globals.debugFlag: assert (self.header) location = 'Header' Globals.checkXMLNoAttributes(self.header, location, 'j4j6') Globals.checkXMLNoText(self.header, location, 'sk4l') Globals.checkXMLNoTail(self.header, location, 'a2d4') # TODO: We probably need to rationalise some of the self.xxx stores for element in self.header: #print( "header", element.tag ) if element.tag == 'title': sublocation = "title in {}".format(location) Globals.checkXMLNoTail(element, sublocation, 'al1d') Globals.checkXMLNoAttributes(element, sublocation, 'j3jd') Globals.checkXMLNoSubelements(element, sublocation, '5g78') if Globals.debugFlag: assert (element.text) self.title = element.text elif element.tag == 'creator': sublocation = "creator in {}".format(location) Globals.checkXMLNoTail(element, sublocation, 'al1d') Globals.checkXMLNoAttributes(element, sublocation, 'j3jd') Globals.checkXMLNoSubelements(element, sublocation, '5g78') if element.text: self.creator = element.text elif element.tag == 'subject': sublocation = "subject in {}".format(location) Globals.checkXMLNoTail(element, sublocation, 'al1d') Globals.checkXMLNoAttributes(element, sublocation, 'j3jd') Globals.checkXMLNoSubelements(element, sublocation, '5g78') if element.text: self.subject = element.text elif element.tag == 'description': sublocation = "description in {}".format(location) Globals.checkXMLNoTail(element, sublocation, 'al1d') Globals.checkXMLNoAttributes(element, sublocation, 'j3jd') Globals.checkXMLNoSubelements(element, sublocation, '5g78') if Globals.debugFlag: assert (element.text) self.description = element.text elif element.tag == 'publisher': sublocation = "publisher in {}".format(location) Globals.checkXMLNoTail(element, sublocation, 'al1d') Globals.checkXMLNoAttributes(element, sublocation, 'j3jd') Globals.checkXMLNoSubelements(element, sublocation, '5g78') if element.text: self.publisher = element.text elif element.tag == 'contributors': sublocation = "contributors in {}".format(location) Globals.checkXMLNoTail(element, sublocation, 'al1d') Globals.checkXMLNoAttributes(element, sublocation, 'j3jd') Globals.checkXMLNoSubelements(element, sublocation, '5g78') if element.text: self.contributors = element.text elif element.tag == 'date': sublocation = "date in {}".format(location) Globals.checkXMLNoTail(element, sublocation, 'al1d') Globals.checkXMLNoAttributes(element, sublocation, 'j3jd') Globals.checkXMLNoSubelements(element, sublocation, '5g78') if Globals.debugFlag: assert (element.text) self.date = element.text elif element.tag == 'type': sublocation = "type in {}".format(location) Globals.checkXMLNoTail(element, sublocation, 'al1d') Globals.checkXMLNoAttributes(element, sublocation, 'j3jd') Globals.checkXMLNoSubelements(element, sublocation, '5g78') if element.text: self.documentType = element.text elif element.tag == 'format': sublocation = "format in {}".format(location) Globals.checkXMLNoTail(element, sublocation, 'al1d') Globals.checkXMLNoAttributes(element, sublocation, 'j3jd') Globals.checkXMLNoSubelements(element, sublocation, '5g78') if Globals.debugFlag: assert (element.text) if Globals.debugFlag: assert ( element.text == 'Zefania XML Bible Markup Language') elif element.tag == 'identifier': sublocation = "identifier in {}".format(location) Globals.checkXMLNoTail(element, sublocation, 'al1d') Globals.checkXMLNoAttributes(element, sublocation, 'j3jd') Globals.checkXMLNoSubelements(element, sublocation, '5g78') if Globals.debugFlag: assert (element.text) self.identifier = element.text elif element.tag == 'source': sublocation = "source in {}".format(location) Globals.checkXMLNoTail(element, sublocation, 'al1d') Globals.checkXMLNoAttributes(element, sublocation, 'j3jd') Globals.checkXMLNoSubelements(element, sublocation, '5g78') if Globals.debugFlag: assert (element.text) self.source = element.text elif element.tag == 'language': sublocation = "language in {}".format(location) Globals.checkXMLNoTail(element, sublocation, 'al1d') Globals.checkXMLNoAttributes(element, sublocation, 'j3jd') Globals.checkXMLNoSubelements(element, sublocation, '5g78') if Globals.debugFlag: assert (element.text) self.language = element.text elif element.tag == 'coverage': sublocation = "coverage in {}".format(location) Globals.checkXMLNoTail(element, sublocation, 'al1d') Globals.checkXMLNoAttributes(element, sublocation, 'j3jd') Globals.checkXMLNoSubelements(element, sublocation, '5g78') if element.text: self.coverage = element.text elif element.tag == 'rights': sublocation = "rights in {}".format(location) Globals.checkXMLNoTail(element, sublocation, 'al1d') Globals.checkXMLNoAttributes(element, sublocation, 'j3jd') Globals.checkXMLNoSubelements(element, sublocation, '5g78') if element.text: self.rights = element.text else: logging.error("Found unexpected '{}' tag in {}".format( element.tag, location)) # end of ZefaniaXMLBible.__validateAndExtractHeader def __validateAndExtractBook(self, book): """ Check/validate and extract book data from the given XML book record finding chapter subelements. """ if Globals.verbosityLevel > 3: print(_("Validating XML book...")) # Process the div attributes first BBB = bookName = bookShortName = bookNumber = None for attrib, value in book.items(): if attrib == "bnumber": bookNumber = value elif attrib == "bname": bookName = value elif attrib == "bsname": bookShortName = value else: logging.warning( "Unprocessed '{}' attribute ({}) in book element".format( attrib, value)) if bookNumber: try: BBB = Globals.BibleBooksCodes.getBBBFromReferenceNumber( bookNumber) except KeyError: logging.warning( "Unable to deduce which book is number={}, name={}, shortName={} -- ignoring it" \ .format( bookNumber, bookName, bookShortName ) ) elif bookName: BBB = self.genericBOS.getBBB(bookName) if BBB: if Globals.verbosityLevel > 2: print(_("Validating {} {}...").format(BBB, bookName)) thisBook = BibleBook(self.name, BBB) thisBook.objectNameString = "Zefania XML Bible Book object" thisBook.objectTypeString = "Zefania" #thisBook.sourceFilepath = self.sourceFilepath for element in book: if element.tag == ZefaniaXMLBible.chapterTag: sublocation = "chapter in {}".format(BBB) Globals.checkXMLNoText(element, sublocation, 'j3jd') Globals.checkXMLNoTail(element, sublocation, 'al1d') self.__validateAndExtractChapter(BBB, thisBook, element) else: logging.error("Expected to find '{}' but got '{}'".format( ZefaniaXMLBible.chapterTag, element.tag)) if Globals.verbosityLevel > 2: print(" Saving {} into results...".format(BBB)) self.saveBook(thisBook) # end of ZefaniaXMLBible.__validateAndExtractBook def __validateAndExtractChapter(self, BBB, thisBook, chapter): """ Check/validate and extract chapter data from the given XML book record finding and saving chapter numbers and finding and saving verse elements. """ if Globals.verbosityLevel > 3: print(_("Validating XML chapter...")) # Process the chapter attributes first chapterNumber = numVerses = None for attrib, value in chapter.items(): if attrib == "cnumber": chapterNumber = value else: logging.warning( "Unprocessed '{}' attribute ({}) in chapter element". format(attrib, value)) if chapterNumber: #print( BBB, 'c', chapterNumber ) thisBook.appendLine('c', chapterNumber) else: logging.error( "Missing 'n' attribute in chapter element for BBB".format(BBB)) for element in chapter: if element.tag == ZefaniaXMLBible.verseTag: location = "verse in {} {}".format(BBB, chapterNumber) self.__validateAndExtractVerse(BBB, chapterNumber, thisBook, element) elif element.tag == ZefaniaXMLBible.captionTag: # Used in Psalms location = "caption in {} {}".format(BBB, chapterNumber) Globals.checkXMLNoTail(element, location, 'k5k8') Globals.checkXMLNoSubelements(element, location, 'd3f5') # Handle caption attributes vRef = None for attrib, value in element.items(): if attrib == "vref": vRef = value if Globals.debugFlag: assert (vRef == '1') else: logging.warning( "Unprocessed '{}' attribute ({}) in caption element" .format(attrib, value)) if Globals.debugFlag: assert (vRef) vText = element.text if not vText: logging.warning("{} {}:{} has no text".format( BBB, chapterNumber, vRef)) if vText: # This is the main text of the caption #print( "{} {}:{} '{}'".format( BBB, chapterNumber, verseNumber, vText ) ) thisBook.appendLine('v', '0' + ' ' + vText) # We save it as verse zero else: logging.error("Expected to find '{}' but got '{}'".format( ZefaniaXMLBible.verseTag, element.tag)) # end of ZefaniaXMLBible.__validateAndExtractChapter def __validateAndExtractVerse(self, BBB, chapterNumber, thisBook, verse): """ Check/validate and extract chapter data from the given XML book record finding and saving chapter numbers and finding and saving verse elements. """ if Globals.verbosityLevel > 3: print(_("Validating XML verse...")) location = "verse in {} {}".format(BBB, chapterNumber) Globals.checkXMLNoTail(verse, location, 'l5ks') # Handle verse attributes verseNumber = toVerseNumber = None for attrib, value in verse.items(): if attrib == "vnumber": verseNumber = value else: logging.warning( "Unprocessed '{}' attribute ({}) in verse element".format( attrib, value)) if Globals.debugFlag: assert (verseNumber) location = "{}:{}".format( location, verseNumber) # Get a better location description #thisBook.appendLine( 'v', verseNumber ) vText = verse.text if vText: vText = vText.strip() #if not vText: # This happens if a verse starts immediately with a style or note #logging.warning( "{} {}:{} has no text".format( BBB, chapterNumber, verseNumber ) ) # Handle verse subelements (notes and styled portions) for subelement in verse: if subelement.tag == ZefaniaXMLBible.noteTag: sublocation = "note in " + location noteType = None for attrib, value in subelement.items(): if attrib == "type": noteType = value else: logging.warning( "Unprocessed '{}' attribute ({}) in style subelement" .format(attrib, value)) if noteType not in ( 'n-studynote', 'x-studynote', ): logging.warning("Unexpected {} note type in {}".format( noteType, BBB)) if Globals.debugFlag: assert (noteType) nText, nTail = subelement.text, subelement.tail #print( "note", BBB, chapterNumber, verseNumber, noteType, repr(nText), repr(nTail) ) #thisBook.appendLine( 'ST', css ) # XXXXXXXXXXXXXXXXXXXXXXXXXX Losing data here (for now) #thisBook.appendLine( 'ST=', nText ) if nTail: if '\n' in nTail: print( "ZefaniaXMLBible.__validateAndExtractVerse: nTail {} {}:{} '{}'" .format(BBB, chapterNumber, verseNumber, nTail)) nTail = nTail.replace('\n', ' ') thisBook.appendLine('v~', nTail) for subsubelement in subelement: if subsubelement.tag == ZefaniaXMLBible.styleTag: subsublocation = "style in " + sublocation Globals.checkXMLNoSubelements(subsubelement, subsublocation, 'fyt4') css = idStyle = None for attrib, value in subsubelement.items(): if attrib == "css": css = value elif attrib == "id": idStyle = value else: logging.warning( "Unprocessed '{}' attribute ({}) in style subsubelement" .format(attrib, value)) if Globals.debugFlag: assert (css or idStyle) SFM = None if css == "font-style:italic": SFM = '\\it' elif css == "font-style:italic;font-weight:bold": SFM = '\\bdit' elif css == "color:#FF0000": SFM = '\\em' elif css == "font-size: x-small; color:#8B8378": SFM = '\\add' elif css is None and idStyle == 'cl:divineName': SFM = '\\nd' else: print("css is", css, "idStyle is", idStyle) halt sText, sTail = subsubelement.text.strip( ), subsubelement.tail if Globals.debugFlag: assert (sText) if SFM: vText += SFM + ' ' + sText + SFM + '*' else: vText += '\\sc ' + '[' + css + ']' + sText + '\\sc* ' # Use sc for unknown styles if sTail: vText += sTail.strip() else: logging.error( "Expected to find {} but got '{}' in {}".format( ZefaniaXMLBible.styleTag, subsubelement.tag, sublocation)) elif subelement.tag == ZefaniaXMLBible.styleTag: sublocation = "style in " + location Globals.checkXMLNoSubelements(subelement, sublocation, 'f5gh') css = idStyle = None for attrib, value in subelement.items(): if attrib == "css": css = value elif attrib == "id": idStyle = value else: logging.warning( "Unprocessed '{}' attribute ({}) in style subelement" .format(attrib, value)) if Globals.debugFlag: assert (css or idStyle) SFM = None if css == "font-style:italic": SFM = '\\it' elif css == "font-style:italic;font-weight:bold": SFM = '\\bdit' elif css == "color:#FF0000": SFM = '\\em' elif css == "font-size: x-small; color:#8B8378": SFM = '\\add' elif css is None and idStyle == 'cl:divineName': SFM = '\\nd' else: print("css is", css, "idStyle is", idStyle) halt sText, sTail = subelement.text.strip(), subelement.tail if Globals.debugFlag: assert (sText) if SFM: vText += SFM + ' ' + sText + SFM + '*' else: vText += '\\sc ' + '[' + css + ']' + sText + '\\sc* ' # Use sc for unknown styles if sTail: vText += sTail.strip() elif subelement.tag == ZefaniaXMLBible.breakTag: sublocation = "line break in " + location Globals.checkXMLNoText(subelement, sublocation, 'c1d4') Globals.checkXMLNoSubelements(subelement, sublocation, 'g4g8') art = None for attrib, value in subelement.items(): if attrib == "art": art = value else: logging.warning( "Unprocessed '{}' attribute ({}) in style subelement" .format(attrib, value)) if Globals.debugFlag: assert (art == 'x-nl') #print( BBB, chapterNumber, verseNumber ) #assert( vText ) if vText: thisBook.appendLine('v', verseNumber + ' ' + vText) vText = '' thisBook.appendLine( 'm', subelement.tail.strip() if subelement.tail else '') #bTail = subelement.tail #if bTail: vText = bTail.strip() else: logging.error( "Expected to find NOTE or STYLE but got '{}' in {}".format( subelement.tag, location)) if vText: # This is the main text of the verse (follows the verse milestone) if '\n' in vText: print( "ZefaniaXMLBible.__validateAndExtractVerse: vText {} {}:{} '{}'" .format(BBB, chapterNumber, verseNumber, vText)) vText = vText.replace('\n', ' ') thisBook.appendLine('v', verseNumber + ' ' + vText)
class VerseViewXMLBible(Bible): """ Class for reading, validating, and converting VerseViewXMLBible XML. """ XMLNameSpace = "{http://www.w3.org/2001/XMLSchema-instance}" treeTag = 'bible' filenameTag = 'fname' revisionTag = 'revision' titleTag = 'title' fontTag = 'font' copyrightTag = 'copyright' sizefactorTag = 'sizefactor' bookTag = 'b' chapterTag = 'c' verseTag = 'v' def __init__(self, sourceFolder, givenName, encoding='utf-8'): """ Constructor: just sets up the VerseView Bible object. """ # Setup and initialise the base class first Bible.__init__(self) self.objectNameString = 'VerseView XML Bible object' self.objectTypeString = 'VerseView' # Now we can set our object variables self.sourceFolder, self.givenName, self.encoding = sourceFolder, givenName, encoding self.sourceFilepath = os.path.join(self.sourceFolder, self.givenName) self.XMLTree = self.header = None # Will hold the XML data # Get the data tables that we need for proper checking #self.ISOLanguages = ISO_639_3_Languages().loadData() self.genericBOS = BibleOrganizationalSystem('GENERIC-KJV-66-ENG') # Do a preliminary check on the readability of our file if not os.access(self.sourceFilepath, os.R_OK): print("VerseViewXMLBible: File {!r} is unreadable".format( self.sourceFilepath)) self.name = self.givenName #if self.name is None: #pass # end of VerseViewXMLBible.__init__ def load(self): """ Load a single source XML file and load book elements. """ if BibleOrgSysGlobals.verbosityLevel > 2: print(_("Loading {}…").format(self.sourceFilepath)) self.XMLTree = ElementTree().parse(self.sourceFilepath) if BibleOrgSysGlobals.debugFlag: assert len( self.XMLTree) # Fail here if we didn't load anything at all if self.suppliedMetadata is None: self.suppliedMetadata = {} self.suppliedMetadata['VerseView'] = {} # Find the main (bible) container if self.XMLTree.tag == VerseViewXMLBible.treeTag: location = "VerseView XML file" BibleOrgSysGlobals.checkXMLNoText(self.XMLTree, location, '4f6h') BibleOrgSysGlobals.checkXMLNoAttributes(self.XMLTree, location, 'js24') BibleOrgSysGlobals.checkXMLNoTail(self.XMLTree, location, '1wk8') # Find the submain (various info and then book) containers bookNumber = 0 for element in self.XMLTree: if element.tag == VerseViewXMLBible.filenameTag: sublocation = "filename in " + location BibleOrgSysGlobals.checkXMLNoAttributes( element, sublocation, 'jk86') BibleOrgSysGlobals.checkXMLNoSubelements( element, sublocation, 'hjk7') BibleOrgSysGlobals.checkXMLNoTail(element, sublocation, 'bh09') #self.filename = element.text elif element.tag == VerseViewXMLBible.revisionTag: sublocation = "revision in " + location BibleOrgSysGlobals.checkXMLNoAttributes( element, sublocation, 'jk86') BibleOrgSysGlobals.checkXMLNoSubelements( element, sublocation, 'hjk7') BibleOrgSysGlobals.checkXMLNoTail(element, sublocation, 'bh09') self.suppliedMetadata['VerseView'][ 'Revision'] = element.text elif element.tag == VerseViewXMLBible.titleTag: sublocation = "title in " + location BibleOrgSysGlobals.checkXMLNoAttributes( element, sublocation, 'jk86') BibleOrgSysGlobals.checkXMLNoSubelements( element, sublocation, 'hjk7') BibleOrgSysGlobals.checkXMLNoTail(element, sublocation, 'bh09') self.suppliedMetadata['VerseView']['Title'] = element.text elif element.tag == VerseViewXMLBible.fontTag: sublocation = "font in " + location BibleOrgSysGlobals.checkXMLNoAttributes( element, sublocation, 'jk86') BibleOrgSysGlobals.checkXMLNoSubelements( element, sublocation, 'hjk7') BibleOrgSysGlobals.checkXMLNoTail(element, sublocation, 'bh09') self.suppliedMetadata['VerseView']['Font'] = element.text elif element.tag == VerseViewXMLBible.copyrightTag: sublocation = "copyright in " + location BibleOrgSysGlobals.checkXMLNoAttributes( element, sublocation, 'jk86') BibleOrgSysGlobals.checkXMLNoSubelements( element, sublocation, 'hjk7') BibleOrgSysGlobals.checkXMLNoTail(element, sublocation, 'bh09') self.suppliedMetadata['VerseView'][ 'Copyright'] = element.text elif element.tag == VerseViewXMLBible.sizefactorTag: sublocation = "sizefactor in " + location BibleOrgSysGlobals.checkXMLNoAttributes( element, sublocation, 'jk86') BibleOrgSysGlobals.checkXMLNoSubelements( element, sublocation, 'hjk7') BibleOrgSysGlobals.checkXMLNoTail(element, sublocation, 'bh09') if BibleOrgSysGlobals.debugFlag: assert element.text == '1' elif element.tag == VerseViewXMLBible.bookTag: sublocation = "book in " + location BibleOrgSysGlobals.checkXMLNoText(element, sublocation, 'g3g5') BibleOrgSysGlobals.checkXMLNoTail(element, sublocation, 'd3f6') bookNumber += 1 self.__validateAndExtractBook(element, bookNumber) else: logging.error( "xk15 Expected to find {!r} but got {!r}".format( VerseViewXMLBible.bookTag, element.tag)) else: logging.error("Expected to load {!r} but got {!r}".format( VerseViewXMLBible.treeTag, self.XMLTree.tag)) if BibleOrgSysGlobals.debugFlag or BibleOrgSysGlobals.verbosityLevel > 2: # These are all compulsory so they should all exist #print( "Filename is {!r}".format( self.filename ) ) print("Revision is {!r}".format( self.suppliedMetadata['VerseView']['Revision'])) print("Title is {!r}".format( self.suppliedMetadata['VerseView']['Title'])) print("Font is {!r}".format( self.suppliedMetadata['VerseView']['Font'])) print("Copyright is {!r}".format( self.suppliedMetadata['VerseView']['Copyright'])) #print( "SizeFactor is {!r}".format( self.sizeFactor ) ) self.applySuppliedMetadata( 'VerseView') # Copy some to self.settingsDict self.doPostLoadProcessing() # end of VerseViewXMLBible.load def __validateAndExtractBook(self, book, bookNumber): """ Check/validate and extract book data from the given XML book record finding chapter subelements. """ if BibleOrgSysGlobals.verbosityLevel > 3: print(_("Validating XML book…")) # Process the div attributes first BBB = bookName = None for attrib, value in book.items(): if attrib == "n": bookName = value else: logging.warning( "Unprocessed {!r} attribute ({}) in book element".format( attrib, value)) if bookName: BBB = self.genericBOS.getBBBFromText(bookName) if BBB is None: adjustedBookName = BibleOrgSysGlobals.removeAccents(bookName) if adjustedBookName != bookName: BBB = self.genericBOS.getBBBFromText(adjustedBookName) BBB2 = BibleOrgSysGlobals.BibleBooksCodes.getBBBFromReferenceNumber( bookNumber) if BBB2 != BBB: # Just double check using the book number if BibleOrgSysGlobals.debugFlag or BibleOrgSysGlobals.verbosityLevel > 2: print("Assuming that book {} {!r} is {} (not {})".format( bookNumber, bookName, BBB2, BBB)) BBB = BBB2 #print( BBB ); halt if BBB: if BibleOrgSysGlobals.verbosityLevel > 2: print(_("Validating {} {}…").format(BBB, bookName)) thisBook = BibleBook(self, BBB) thisBook.objectNameString = 'VerseView XML Bible Book object' thisBook.objectTypeString = 'VerseView' #thisBook.sourceFilepath = self.sourceFilepath for element in book: if element.tag == VerseViewXMLBible.chapterTag: sublocation = "chapter in {}".format(BBB) BibleOrgSysGlobals.checkXMLNoText(element, sublocation, 'j3jd') BibleOrgSysGlobals.checkXMLNoTail(element, sublocation, 'al1d') self.__validateAndExtractChapter(BBB, thisBook, element) else: logging.error( "vb26 Expected to find {!r} but got {!r}".format( VerseViewXMLBible.chapterTag, element.tag)) if BibleOrgSysGlobals.verbosityLevel > 2: print(" Saving {} into results…".format(BBB)) self.stashBook(thisBook) # end of VerseViewXMLBible.__validateAndExtractBook def __validateAndExtractChapter(self, BBB, thisBook, chapter): """ Check/validate and extract chapter data from the given XML book record finding and saving chapter numbers and finding and saving verse elements. """ if BibleOrgSysGlobals.debugFlag and debuggingThisModule and BibleOrgSysGlobals.verbosityLevel > 3: print(_("Validating XML chapter…")) # Process the chapter attributes first chapterNumber = numVerses = None for attrib, value in chapter.items(): if attrib == "n": chapterNumber = value else: logging.warning( "Unprocessed {!r} attribute ({}) in chapter element". format(attrib, value)) if chapterNumber: #print( BBB, 'c', chapterNumber ) thisBook.addLine('c', chapterNumber) else: logging.error( "Missing 'n' attribute in chapter element for {}".format(BBB)) for element in chapter: if element.tag == VerseViewXMLBible.verseTag: location = "verse in {} {}".format(BBB, chapterNumber) self.__validateAndExtractVerse(BBB, chapterNumber, thisBook, element) else: logging.error("sv34 Expected to find {!r} but got {!r}".format( VerseViewXMLBible.verseTag, element.tag)) # end of VerseViewXMLBible.__validateAndExtractChapter def __validateAndExtractVerse(self, BBB, chapterNumber, thisBook, verse): """ Check/validate and extract verse data from the given XML book record finding and saving verse elements. """ if BibleOrgSysGlobals.debugFlag and debuggingThisModule and BibleOrgSysGlobals.verbosityLevel > 3: print(_("Validating XML verse…")) location = "verse in {} {}".format(BBB, chapterNumber) BibleOrgSysGlobals.checkXMLNoSubelements(verse, location, 'sg20') BibleOrgSysGlobals.checkXMLNoTail(verse, location, 'l5ks') # Handle verse attributes verseNumber = toVerseNumber = None for attrib, value in verse.items(): if attrib == "n": verseNumber = value else: logging.warning( "Unprocessed {!r} attribute ({}) in verse element".format( attrib, value)) if BibleOrgSysGlobals.debugFlag: assert verseNumber location = "{}:{}".format( location, verseNumber) # Get a better location description #thisBook.addLine( 'v', verseNumber ) vText = '' if verse.text is None else verse.text if vText: vText = vText.strip() #if not vText: # This happens if a verse starts immediately with a style or note #logging.warning( "{} {}:{} has no text".format( BBB, chapterNumber, verseNumber ) ) ## Handle verse subelements (notes and styled portions) #for subelement in verse: #if subelement.tag == VerseViewXMLBible.noteTag: #sublocation = "note in " + location #noteType = None #for attrib,value in subelement.items(): #if attrib=="type": noteType = value #else: logging.warning( "Unprocessed {!r} attribute ({}) in style subelement".format( attrib, value ) ) #if noteType and noteType not in ('variant',): #logging.warning( "Unexpected {} note type in {}".format( noteType, BBB ) ) #nText, nTail = subelement.text, subelement.tail ##print( "note", BBB, chapterNumber, verseNumber, noteType, repr(nText), repr(nTail) ) #vText += "\\f + \\fk {} \\ft {}\\f*".format( noteType, nText ) if noteType else "\\f + \\ft {}\\f*".format( nText ) #if nTail: #if '\n' in nTail: #print( "VerseViewXMLBible.__validateAndExtractVerse: nTail {} {}:{} {!r}".format( BBB, chapterNumber, verseNumber, nTail ) ) #nTail = nTail.replace( '\n', ' ' ) #vText += nTail #for sub2element in subelement: #if sub2element.tag == VerseViewXMLBible.styleTag: #sub2location = "style in " + sublocation #BibleOrgSysGlobals.checkXMLNoSubelements( sub2element, sub2location, 'fyt4' ) #fs = css = idStyle = None #for attrib,value in sub2element.items(): #if attrib=='fs': fs = value ##elif attrib=="css": css = value ##elif attrib=="id": idStyle = value #else: logging.warning( "Unprocessed {!r} attribute ({}) in style sub2element".format( attrib, value ) ) #if BibleOrgSysGlobals.debugFlag: assert fs or css or idStyle #SFM = None #if fs == 'italic': SFM = '\\it' #elif fs == 'super': SFM = '\\bdit' #elif fs == 'emphasis': SFM = '\\em' #else: print( "fs is", fs, "css is", css, "idStyle is", idStyle ); halt ##if css == "font-style:italic": SFM = '\\it' ##elif css == "font-style:italic;font-weight:bold": SFM = '\\bdit' ##elif css == "color:#FF0000": SFM = '\\em' ##elif css == "font-size: x-small; color:#8B8378": SFM = '\\add' ##elif css is None and idStyle=='cl:divineName': SFM = '\\nd' ##else: print( "css is", css, "idStyle is", idStyle ); halt #sText, sTail = sub2element.text.strip(), sub2element.tail #if BibleOrgSysGlobals.debugFlag: assert sText #if SFM: vText += SFM+' ' + sText + SFM+'*' #else: vText += '\\sc ' + '['+css+']' + sText + '\\sc* ' # Use sc for unknown styles #if sTail: vText += sTail.strip() #else: logging.error( "df20 Expected to find {} but got {!r} in {}".format( VerseViewXMLBible.styleTag, sub2element.tag, sublocation ) ) #elif subelement.tag == VerseViewXMLBible.styleTag: #sublocation = "style in " + location #BibleOrgSysGlobals.checkXMLNoSubelements( subelement, sublocation, 'f5gh' ) #fs = css = idStyle = None #for attrib,value in subelement.items(): #if attrib=="fs": fs = value ##elif attrib=="css": css = value ##elif attrib=="id": idStyle = value #else: logging.warning( "Unprocessed {!r} attribute ({}) in style subelement".format( attrib, value ) ) #if BibleOrgSysGlobals.debugFlag: assert fs #SFM = None #if fs == 'super': SFM = '\\bdit' #elif fs == 'emphasis': SFM = '\\em' #else: print( "fs is", fs, "css is", css, "idStyle is", idStyle ); halt ##if css == "font-style:italic": SFM = '\\it' ##elif css == "font-style:italic;font-weight:bold": SFM = '\\bdit' ##elif css == "color:#FF0000": SFM = '\\em' ##elif css == "font-size: x-small; color:#8B8378": SFM = '\\add' ##elif css is None and idStyle=='cl:divineName': SFM = '\\nd' ##else: print( "css is", css, "idStyle is", idStyle ); halt #sText, sTail = subelement.text.strip(), subelement.tail #if BibleOrgSysGlobals.debugFlag: assert sText ##print( BBB, chapterNumber, sublocation ) #if SFM: vText += SFM+' ' + sText + SFM+'*' #else: vText += '\\sc ' + '['+css+']' + sText + '\\sc* ' # Use sc for unknown styles #if sTail: vText += sTail.strip() #elif subelement.tag == VerseViewXMLBible.breakTag: #sublocation = "line break in " + location #BibleOrgSysGlobals.checkXMLNoText( subelement, sublocation, 'c1d4' ) #BibleOrgSysGlobals.checkXMLNoSubelements( subelement, sublocation, 'g4g8' ) #art = None #for attrib,value in subelement.items(): #if attrib=="art": #art = value #else: logging.warning( "Unprocessed {!r} attribute ({}) in style subelement".format( attrib, value ) ) #if BibleOrgSysGlobals.debugFlag: assert art == 'x-nl' ##print( BBB, chapterNumber, verseNumber ) ##assert vText #if vText: #thisBook.addLine( 'v', verseNumber + ' ' + vText ); verseNumber = None #vText = '' #thisBook.addLine( 'm', subelement.tail.strip() if subelement.tail else '' ) ##bTail = subelement.tail ##if bTail: vText = bTail.strip() #else: logging.error( "bd47 Expected to find NOTE or STYLE but got {!r} in {}".format( subelement.tag, location ) ) if vText: # This is the main text of the verse (follows the verse milestone) if '\n' in vText: print( "VerseViewXMLBible.__validateAndExtractVerse: vText {} {}:{} {!r}" .format(BBB, chapterNumber, verseNumber, vText)) vText = vText.replace('\n', ' ') thisBook.addLine('v', verseNumber + ' ' + vText) verseNumber = None
def importDataToPython(self): """ Loads (and pivots) the data (not including the header) into suitable Python containers to use in a Python program. (Of course, you can just use the elementTree in self._XMLtree if you prefer.) """ def makeList(parameter1, parameter2): """ Returns a list containing all parameters. Parameter1 may already be a list. """ if isinstance(parameter1, list): #assert( parameter2 not in parameter1 ) parameter1.append(parameter2) return parameter1 else: return [parameter1, parameter2] # end of makeList assert (self._XMLtree) if self.__DataList: # We've already done an import/restructuring -- no need to repeat it return self.__DataList, self.__DataDict # We'll create a number of dictionaries with different elements as the key rawRefLinkList = [] actualLinkCount = 0 for element in self._XMLtree: #print( BibleOrgSysGlobals.elementStr( element ) ) # Get these first for helpful error messages sourceReference = element.find('sourceReference').text sourceComponent = element.find('sourceComponent').text assert (sourceComponent in ( 'Section', 'Verses', 'Verse', )) BibleOrgSysGlobals.checkXMLNoText(element, sourceReference, 'kls1') BibleOrgSysGlobals.checkXMLNoAttributes(element, sourceReference, 'kd21') BibleOrgSysGlobals.checkXMLNoTail(element, sourceReference, 'so20') actualRawLinksList = [] for subelement in element: #print( BibleOrgSysGlobals.elementStr( subelement ) ) if subelement.tag in ( 'sourceReference', 'sourceComponent', ): # already processed these BibleOrgSysGlobals.checkXMLNoAttributes( subelement, sourceReference, 'ls12') BibleOrgSysGlobals.checkXMLNoSubelements( subelement, sourceReference, 'ks02') BibleOrgSysGlobals.checkXMLNoTail(subelement, sourceReference, 'sqw1') elif subelement.tag == 'BibleReferenceLink': BibleOrgSysGlobals.checkXMLNoText(subelement, sourceReference, 'haw9') BibleOrgSysGlobals.checkXMLNoAttributes( subelement, sourceReference, 'hs19') BibleOrgSysGlobals.checkXMLNoTail(subelement, sourceReference, 'jsd9') targetReference = subelement.find('targetReference').text targetComponent = subelement.find('targetComponent').text assert (targetComponent in ( 'Section', 'Verses', 'Verse', )) linkType = subelement.find('linkType').text assert (linkType in ( 'TSK', 'QuotedOTReference', 'AlludedOTReference', 'PossibleOTReference', )) actualRawLinksList.append(( targetReference, targetComponent, linkType, )) actualLinkCount += 1 rawRefLinkList.append(( sourceReference, sourceComponent, actualRawLinksList, )) if BibleOrgSysGlobals.verbosityLevel > 1: print(" {} raw links loaded (with {} actual raw link entries)". format(len(rawRefLinkList), actualLinkCount)) myRefLinkList = [] actualLinkCount = 0 BOS = BibleOrganizationalSystem("GENERIC-KJV-66-ENG") for j, (sourceReference, sourceComponent, actualRawLinksList) in enumerate(rawRefLinkList): # Just do some testing first if sourceComponent == 'Verse': x = SimpleVerseKey(sourceReference) else: flag = False try: x = SimpleVerseKey(sourceReference, ignoreParseErrors=True) flag = True except TypeError: pass # This should happen coz it should fail the SVK if flag: logging.error("{} {!r} failed!".format( sourceComponent, sourceReference)) raise TypeError # Now do the actual parsing parsedSourceReference = FlexibleVersesKey(sourceReference) if BibleOrgSysGlobals.debugFlag and debuggingThisModule: print(j, sourceComponent, sourceReference, parsedSourceReference) #assert( parsedSourceReference.getShortText().replace(' ','_') == sourceReference ) actualLinksList = [] for k, (targetReference, targetComponent, linkType) in enumerate(actualRawLinksList): # Just do some testing first if targetComponent == 'Verse': x = SimpleVerseKey(targetReference) else: flag = False try: x = SimpleVerseKey(targetReference, ignoreParseErrors=True) flag = True except TypeError: pass # This should happen coz it should fail the SVK if flag: logging.error("{} {!r} failed!".format( targetComponent, targetReference)) raise TypeError # Now do the actual parsing try: parsedTargetReference = FlexibleVersesKey(targetReference) except TypeError: print( " Temporarily ignored {!r} (TypeError from FlexibleVersesKey)" .format(targetReference)) parsedTargetReference = None if BibleOrgSysGlobals.debugFlag and debuggingThisModule: print(' ', targetComponent, targetReference, parsedTargetReference) #assert( parsedTargetReference.getShortText().replace(' ','_',1) == targetReference ) actualLinksList.append(( targetReference, targetComponent, parsedTargetReference, linkType, )) actualLinkCount += 1 myRefLinkList.append(( sourceReference, sourceComponent, parsedSourceReference, actualLinksList, )) if BibleOrgSysGlobals.verbosityLevel > 1: print(" {} links processed (with {} actual link entries)".format( len(rawRefLinkList), actualLinkCount)) #print( myRefLinkList ); halt self.__DataList = myRefLinkList # Now put it into my dictionaries for easy access # This part should be customized or added to for however you need to process the data # Create a link dictionary (by verse key) myRefLinkDict = {} for sourceReference, sourceComponent, parsedSourceReference, actualLinksList in myRefLinkList: #print( sourceReference, sourceComponent, parsedSourceReference ) #print( sourceReference, sourceComponent, parsedSourceReference, actualLinksList ) for verseRef in parsedSourceReference.getIncludedVerses(): #print( verseRef ) assert (isinstance(verseRef, SimpleVerseKey)) if verseRef not in myRefLinkDict: myRefLinkDict[verseRef] = [] myRefLinkDict[verseRef].append(( sourceReference, sourceComponent, parsedSourceReference, actualLinksList, )) #print( myRefLinkDict ); halt originalLinks = len(myRefLinkDict) print( " {} verse links added to dictionary (includes filling out spans)" .format(originalLinks)) #print( myRefLinkDict ); halt # Create a reversed link dictionary (by verse key) for sourceReference, sourceComponent, parsedSourceReference, actualLinksList in myRefLinkList: #print( sourceReference, sourceComponent, parsedSourceReference ) #print( sourceReference, sourceComponent, parsedSourceReference, actualLinksList ) for targetReference, targetComponent, parsedTargetReference, linkType in actualLinksList: if parsedTargetReference is not None: for verseRef in parsedTargetReference.getIncludedVerses(): #print( verseRef ) assert (isinstance(verseRef, SimpleVerseKey)) if linkType == 'TSK': reverseLinkType = 'TSKQuoted' elif linkType == 'QuotedOTReference': reverseLinkType = 'OTReferenceQuoted' elif linkType == 'AlludedOTReference': reverseLinkType = 'OTReferenceAlluded' elif linkType == 'PossibleOTReference': reverseLinkType = 'OTReferencePossible' else: halt # Have a new linkType! if verseRef not in myRefLinkDict: myRefLinkDict[verseRef] = [] myRefLinkDict[verseRef].append( (targetReference, targetComponent, parsedTargetReference, [ (sourceReference, sourceComponent, parsedSourceReference, reverseLinkType) ])) #print( myRefLinkDict ); halt totalLinks = len(myRefLinkDict) reverseLinks = totalLinks - originalLinks print(" {} reverse links added to dictionary to give {} total".format( reverseLinks, totalLinks)) #print( myRefLinkDict ); halt self.__DataDict = myRefLinkDict # Let's find the most number of references for a verse mostReferences = totalReferences = 0 for verseRef, entryList in self.__DataDict.items(): numRefs = len(entryList) if numRefs > mostReferences: mostReferences, mostVerseRef = numRefs, verseRef totalReferences += numRefs print(" {} maximum links for any one reference ({})".format( mostReferences, mostVerseRef.getShortText())) print(" {} total links for all references".format(totalReferences)) return self.__DataList, self.__DataDict
def createEasyWorshipBible( BibleObject, outputFolder=None ): """ Write the pseudo USFM out into the compressed EasyWorship format. Since we don't have a specification for the format, and since we don't know the meaning of all the binary pieces of the file, we can't be certain yet that this output will actually work. :-( """ from InternalBibleInternals import BOS_ADDED_NESTING_MARKERS import zipfile # It seems 7-9 give the correct two header bytes ZLIB_COMPRESSION_LEVEL = 9 # -1=default(=6), 0=none, 1=fastest...9=highest compression level if BibleOrgSysGlobals.verbosityLevel > 1: print( "Running createEasyWorshipBible…" ) if BibleOrgSysGlobals.debugFlag: assert BibleObject.books if not BibleObject.doneSetupGeneric: BibleObject.__setupWriter() if not outputFolder: outputFolder = 'OutputFiles/BOS_EasyWorshipBible_Export/' if not os.access( outputFolder, os.F_OK ): os.makedirs( outputFolder ) # Make the empty folder if there wasn't already one there # Set-up their Bible reference system BOS = BibleOrganizationalSystem( 'GENERIC-KJV-66-ENG' ) ignoredMarkers = set() # Before we write the file, let's compress all our books # Books are written as C:V verseText with double-spaced lines compressedDictionary = {} for BBB,bookObject in BibleObject.books.items(): if BBB in ('FRT','INT','BAK','OTH','GLS','XXA','XXB','XXC','XXD','XXE','XXF','XXG',): continue # Ignore these books pseudoESFMData = bookObject._processedLines textBuffer = '' vBridgeStartInt = vBridgeEndInt = None # For printing missing (bridged) verse numbers for entry in pseudoESFMData: marker, text = entry.getMarker(), entry.getCleanText() #print( BBB, marker, text ) if '¬' in marker or marker in BOS_ADDED_NESTING_MARKERS: continue # Just ignore added markers -- not needed here elif marker == 'c': C = int( text ) # Just so we get an error if we have something different V = lastVWritten = '0' elif marker == 'v': #V = text.replace( '–', '-' ).replace( '—', '-' ) # Replace endash, emdash with hyphen V = text for bridgeChar in ('-', '–', '—'): # hyphen, endash, emdash ix = V.find( bridgeChar ) if ix != -1: if debuggingThisModule or BibleOrgSysGlobals.debugFlag or BibleOrgSysGlobals.verbosityLevel>2: print( "createEasyWorshipBible: preparing for verse bridge in {} at {} {}:{}" \ .format( BibleObject.abbreviation, BBB, C, V ) ) # Remove verse bridges vStart = V[:ix].replace( 'a', '' ).replace( 'b', '' ).replace( 'c', '' ) vEnd = V[ix+1:].replace( 'a', '' ).replace( 'b', '' ).replace( 'c', '' ) #print( BBB, repr(vStart), repr(vEnd) ) try: vBridgeStartInt, vBridgeEndInt = int( vStart ), int( vEnd ) except ValueError: print( "createEasyWorshipBible: bridge doesn't seem to be integers in {} {}:{!r}".format( BBB, C, V ) ) vBridgeStartInt = vBridgeEndInt = None # One of them isn't an integer #print( ' ', BBB, repr(vBridgeStartInt), repr(vBridgeEndInt) ) VBridgedText = V V = vStart break elif marker == 'v~': try: if int(V) <= int(lastVWritten): # TODO: Not sure what level the following should be? info/warning/error/critical ???? logging.warning( 'createEasyWorshipBible: Maybe duplicating {} {}:{} after {} with {}'.format( BBB, C, V, lastVWritten, text ) ) #continue except ValueError: pass # had a verse bridge if vBridgeStartInt and vBridgeEndInt: # We had a verse bridge if debuggingThisModule or BibleOrgSysGlobals.debugFlag or BibleOrgSysGlobals.verbosityLevel>2: print( "createEasyWorshipBible: handling verse bridge in {} at {} {}:{}-{}" \ .format( BibleObject.abbreviation, BBB, C, vBridgeStartInt, vBridgeEndInt ) ) if 1: # new code -- copies the bridged text to all verses for vNum in range( vBridgeStartInt, vBridgeEndInt+1 ): # Fill in missing verse numbers textBuffer += ('\r\n\r\n' if textBuffer else '') + '{}:{} ({}) {}'.format( C, vNum, VBridgedText, text ) else: # old code textBuffer += ('\r\n\r\n' if textBuffer else '') + '{}:{} ({}) {}'.format( C, vBridgeStartInt, vBridgeEndInt, text ) for vNum in range( vBridgeStartInt+1, vBridgeEndInt+1 ): # Fill in missing verse numbers textBuffer += '\r\n\r\n{}:{} (-)'.format( C, vNum ) lastVWritten = str( vBridgeEndInt ) vBridgeStartInt = vBridgeEndInt = None else: textBuffer += ('\r\n\r\n' if textBuffer else '') + '{}:{} {}'.format( C, V, text ) lastVWritten = V elif marker == 'p~': if BibleOrgSysGlobals.debugFlag or BibleOrgSysGlobals.strictCheckingFlag: assert textBuffer # This is a continued part of the verse -- failed with this bad source USFM: # \c 1 \v 1 \p These events happened... textBuffer += ' {}'.format( text ) # continuation of the same verse else: ignoredMarkers.add( marker ) #print( BBB, textBuffer ) textBuffer = textBuffer \ .replace( '“', '"' ).replace( '”', '"' ) \ .replace( "‘", "'" ).replace( "’", "'" ) \ .replace( '–', '--' ).replace( '—', '--' ) bookBytes = zlib.compress( textBuffer.encode( 'utf8' ), ZLIB_COMPRESSION_LEVEL ) #print( BBB, hexlify(bookBytes[:20]), bookBytes ) assert bookBytes[0]==0x78 and bookBytes[1]==0xda # Zlib compression header appendage = b'QK\x03\x04' + struct.pack( '<I', len(textBuffer) ) + b'\x08\x00' #print( "appendage", len(appendage), hexlify(appendage), appendage ) assert len(appendage) == 10 compressedDictionary[BBB] = bookBytes + appendage # Work out the "compressed" (osfuscated) module name #name = BibleObject.getAName() ##print( 'sn', repr(BibleObject.shortName) ) #if len(name)>18: #if BibleObject.shortName: name = shortName #elif name.endswith( ' Version' ): name = name[:-8] #name = name.replace( ' ', '' ) #if not name.startswith( 'ezFree' ): name = 'ezFree' + name name = 'ezFree' + ( BibleObject.abbreviation if BibleObject.abbreviation else 'UNK' ) if len(name)>16: name = name[:16] # Shorten encodedNameBytes = zlib.compress( name.encode( 'utf8' ), ZLIB_COMPRESSION_LEVEL ) if BibleOrgSysGlobals.debugFlag: print( 'Name {!r} went from {} to {} bytes'.format( name, len(name), len(encodedNameBytes) ) ) assert encodedNameBytes[0]==0x78 and encodedNameBytes[1]==0xda # Zlib compression header assert len(encodedNameBytes) <= 26 filename = '{}{}'.format( BibleObject.abbreviation, FILENAME_ENDING ).lower() filepath = os.path.join( outputFolder, BibleOrgSysGlobals.makeSafeFilename( filename ) ) if BibleOrgSysGlobals.verbosityLevel > 2: print( ' createEasyWorshipBible: ' + _("Writing {!r}…").format( filepath ) ) bookAddress = startingBookAddress = 14872 + len(name) + 18 + 4 # Name is something like ezFreeXXX vBridgeStartInt = vBridgeEndInt = None # For printing missing (bridged) verse numbers with open( filepath, 'wb' ) as myFile: assert myFile.tell() == 0 # Write the header info to binary file myFile.write( b'EasyWorship Bible Text\x1a\x02<\x00\x00\x00\xe0\x00\x00\x00' ) assert myFile.tell() == 32 nameBytes = ( BibleObject.getAName() ).encode( 'utf8' ) myFile.write( nameBytes + b'\x00' * (56 - len(nameBytes)) ) assert myFile.tell() == 88 # 32 + 56 # Write the numChapters,numVerses info along with the file position and length for BBB in BOS.getBookList(): #bookName = BibleObject.getAssumedBookName( BBB ) try: bookName = BibleObject.books[BBB].shortTOCName except (KeyError,AttributeError): bookName = None # KeyError if no BBB, AttributeError if no shortTOCName #print( len(bookName) if bookName else '', bookName ) assert bookName is None or len(bookName) <= 51 if bookName: bookNameBytes = bookName.encode( 'utf8' ) else: bookNameBytes = b'' # Not compulsory -- will default to English myFile.write( bookNameBytes + b'\x00' * (51 - len(bookNameBytes)) ) numVersesList = BOS.getNumVersesList( BBB ) numChapters = len( numVersesList ) myFile.write( struct.pack( 'B', numChapters ) ) for verseCount in numVersesList: myFile.write( struct.pack( 'B', verseCount ) ) myFile.write( b'\x00' * (157 - numChapters - 1) ) try: bookBytes = compressedDictionary[BBB] # if it exists except KeyError: # Fill in missing books missingString = "1:1 Book not available\r\n\r\n" bookBytes = zlib.compress( missingString.encode( 'utf8' ), ZLIB_COMPRESSION_LEVEL ) assert bookBytes[0]==0x78 and bookBytes[1]==0xda # Zlib compression header appendage = b'QK\x03\x04' + struct.pack( '<I', len(missingString) ) + b'\x08\x00' assert len(appendage) == 10 bookBytes += appendage compressedDictionary[BBB] = bookBytes myFile.write( struct.pack( '<Q', bookAddress ) ) myFile.write( struct.pack( '<Q', len(bookBytes) ) ) bookAddress += len(bookBytes) assert myFile.tell() == 14872 # 32 + 56 + 224*66 # Write the "compressed" (osfuscated) module name myFile.write( struct.pack( '<I', len(name) + 18 ) ) assert myFile.tell() == 14876 # 32 + 56 + 224*66 + 4 myFile.write( encodedNameBytes ) appendage = b'QK\x03\x04' + struct.pack( 'B', len(name) ) + b'\x00' #print( "appendage", len(appendage), hexlify(appendage), appendage ) assert len(appendage) == 6 myFile.write( appendage ) remainderCount = 18 + len(name) - len(encodedNameBytes) - 4 - len(appendage) #print( "remainderCount", remainderCount ) assert remainderCount == 0 #myFile.write( b'\x00' * remainderCount ) myFile.write( b'\x00\x00\x08\x00' ) # Not sure what this means #if debuggingThisModule or BibleOrgSysGlobals.debugFlag: #print( "At", myFile.tell(), 'want', startingBookAddress ) assert myFile.tell() == startingBookAddress # Write the book info to the binary files for BBB in BOS.getBookList(): if BBB in compressedDictionary: myFile.write( compressedDictionary[BBB] ) # Write zlib output elif BibleOrgSysGlobals.verbosityLevel > 2: print( ' Book {} is not available for EasyWorship export'.format( BBB ) ) # Write the end of file stuff myFile.write( b'\x18:\x00\x00\x00\x00\x00\x00ezwBible' ) if ignoredMarkers: logging.info( "createEasyWorshipBible: Ignored markers were {}".format( ignoredMarkers ) ) if BibleOrgSysGlobals.verbosityLevel > 2: print( " " + _("WARNING: Ignored createEasyWorshipBible markers were {}").format( ignoredMarkers ) ) # Now create a zipped version filepath = os.path.join( outputFolder, filename ) if BibleOrgSysGlobals.verbosityLevel > 2: print( " Zipping {} EWB file…".format( filename ) ) zf = zipfile.ZipFile( filepath+'.zip', 'w', compression=zipfile.ZIP_DEFLATED ) zf.write( filepath, filename ) zf.close() if BibleOrgSysGlobals.verbosityLevel > 0 and BibleOrgSysGlobals.maxProcesses > 1: print( " BibleWriter.createEasyWorshipBible finished successfully." ) return True