from unicode import latin1_to_ascii import json import pdb import re import os import sys import time import glob import shutil from pprint import pprint, pformat import gzip import csv import platform import inspect from functools import partial import os.path #Globals currOS = platform.platform() if currOS.find('Windows') == 0: LOCALBASE = 'D:/website/' #LOCALBASE = 'A:/test/' else: LOCALBASE = '/mnt/d/website/' # LOCALBASE = '/ssd/home/sarge/prog/python/fron' TEMPLATE = LOCALBASE + 'templates/template.ft3' ERRFILE = LOCALBASE + 'ft3form/temperr.txt' def join_with_fslash(s1, s2): return(s1 + '/' + s2) # end join_with_fslash startTime = int(time.time()) #Data/input files contained in local website base CONTRIBDIR = LOCALBASE + "contributors" # For converting RTF files to latin1 and vice versa RTFPREFIX = "{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang1033{\\fonttbl{\\f0\\fnil\\fcharset0 MS Shell\r\nDlg;}}\r\n\\viewkind4\\uc1\\pard\\f0\\fs-22 "; RTFSUFFIX = "\\par\r\n}\r\n"; IMAGETYPES = ('.png', '.tif', '.pdf', '.jpg') # Compiled regular expressions #use re.DOTALL to match \n as well # = number in a series; % = arbitrary number to make source unique reUnicode = re.compile('(\\\\u.... )') reSplitAndOr = re.compile('(..*) (?:and|or) (..*)') reGetDate = re.compile('\D\((>?c?a?\.? ?[1-2][0-9]{3})\)', re.DOTALL) #reGetDate = re.compile('\D\((c?a?\.? ?[1-2][0-9]{3})\)', re.DOTALL) reApproxDate = re.compile('(ca?\.? ?)[1-2][0-9]{3}', re.DOTALL) reParenContents = re.compile('^([^(]*)\(([^)]+)\)(.*)', re.DOTALL) reEntabulated = re.compile('([IiEe]ntabulated)', re.DOTALL) reEncoded = re.compile('[Ee](ncoded)', re.DOTALL) reEdited = re.compile('[Ee](dited)', re.DOTALL) reEnc = re.compile(r'[Ee](nc\.)', 1) reEd = re.compile(r'[Ee](d\.)', 1) reInfo = re.compile('^(...).*?: *(..*)$', re.DOTALL) reKey = re.compile('^[A-G][b#]*[Mm]$',re.DOTALL) reGetDictItem = re.compile('"([^"]*)"[^"]*"([^"]*)"') reDeLang = re.compile(r'(\\lang[0-9]{4)}') # These are for error messages # for current func name, specify n = 0 or no argument. # for name of caller of current func, specify 1. # for name of caller of caller of current func, specify 2. etc. funcName = lambda n=1: sys._getframe(n + 1).f_code.co_name callerName = lambda n=2: sys._getframe(n + 1).f_code.co_name lineNo = lambda n=1: sys._getframe(n + 1).f_lineno # insert a string into another string at a specific location def insert_str(stInsert, str, index): return str[:index] + strInsert + str[index:] def at_eof(f): return f.tell() == os.fstat(f.fileno()).st_size def show_tuple(t): for item in t: print("%s, " % item, end = "") print("") difficulties = ["??", "Beginner", "Easy", "Medium", "Challenge", "Difficult", "Virtuoso"] field_map = [ ("Title", "title"), ("Subtitle", "subtitle"), ("Composer", "composer"), ("Orig. composer", "composer0"), ("Footnote", "footnote"), ("Source", "Source"), ("Document", "document"), ("Volume", "volume"), ("Date", "date"), ("Page", "page"), ("Editor", "editor"), ("Encoder", "encoder"), ("Arranger", "arranger"), ("Intabulator", "intabulator"), ("Concordances", "concordances"), ("Contributor", "contributor"), ("Info", "info"), ("Piece", "piece"), ("Section", "section"), ("Type", "type"), ("Key", "key"), ("Difficulty", "difficulty"), ("Ensemble", "ensemble"), ("Part", "part"), ("Remarks", "remarks"), ("Recording", "recurl"), ("Facsimile", "facurl"), ("Fronimo", "stFile"), ("PDF", "stPdf"), ("Midi", "stMidi"), ("Modified", "mtime"), ("Created", "ctime"), ] key_order = [ # for dumping "title", "subtitle", "composer", "composer0", "footnote", "source", "document", "volume", "date", "page", "editor", "encoder", "arranger", "intabulator", "contributor", "concordances", "info", "piece", "section", "type", "key", "difficulty", "ensemble", "part", "remarks","recurl", "facurl", "stFile", "stPdf", "stMidi", "ctime", "mtime", ] #Creates fronimo object from file with name stIn class Fronimo: def __init__(self, stIn = TEMPLATE): # set all attributes to empty string for col,att in field_map: setattr(self, att, "") self.base = LOCALBASE self.currProg = '' self.credits = '' self.begText = '' self.endText = '' self.performance = False self.simple = False self.ornamented = False self.footnote = "" #input file name set from argument stIn self.stFile = stIn self.stFron = '' self.flFron = None self.flOut = None self.flErr = None self.offset = None self.oldOffset = None self.volume = "" self.info = "" self.recurl = "" self.facurl = "" #keep track of padding of the last dir contacted that contains numerical pages #self.lastPageDir = ["", 0] # Creates self.stFron from fronimo file: self.stFile if self.read_and_unzip_file() == False: # marker for failure of class instantiation self.start_offset = -1 else: self.start_offset = self.get_start_offset() if self.start_offset > 0: # Fills in other values of fronimo object. if self.populate() == False: self.start_offset = -1 # end of __init___ # Open error file @classmethod def open_error(kls, errfile): errfile = ERRFILE try: kls.flErr = open(errfile, "w", encoding = 'latin1') except OSError: print("OSError: Cannot open error File ", errfile, " for writing.", file=sys.stderr) return False except: print("Other error: Cannot open error File ", errfile, " for writing.", file=sys.stderr) return False return True # End open_error @classmethod def open_file(kls, fl, mode): try: flName = open(fl, mode, encoding='latin1') except OSError: err= "OSError: Cannot open file %s in mode %s." % (fl, mode) kls.print_error(fl, err) return None except: err= "Other error: Cannot open file %s in mode %s." % (fl, mode) kls.print_error(fl, err) return None return flName # end of openFile # open and read all needed fronimo-related files @classmethod def open_files(kls): pass # end open_files # for future use @classmethod def make_contrib_dir(kls): s= self.contributor.casefold() s = s.replace('.', '') s - s.replace(' ', '_') self.contribDir = join_with_fslash(CONTRIBDIR, s) if not os.path.exists(self.contribDir): os.makedirs(self.contribDir) # print helpful error message @classmethod def print_error(kls, currFile, errMsg): kls.currProg = 'load.py' print("In %s; caller:%s; line:%d of %s\nfile:'%s'; %s." % (funcName(), callerName(), lineNo(), kls.currProg, currFile, errMsg), file=kls.flErr) kls.flErr.flush() # Get starting offset for reading/writing a fronimo file def get_start_offset(self): if (self.stFron[4] == '\x15') or (self.stFron[4] == '\x14'): return 364 elif self.stFron[4] == '\x16': return 368 else: val = hex(ord(self.stFron[4])) msg = "stFron[4] = %s (not \\x15 or \\x16), so starting offset is unknown" % (val) Fronimo.print_error(self.stFile, msg) return -1 # end get_start_offset # read and unzip a fronimo file: self.flFile into self.stFron # Fronimo files are zipped def read_and_unzip_file(self): self.flFron = gzip.open(self.stFile) if self.flFron == None: Fronimo.print_error(self.stFile, 'Cannot open and unzip fronimo file.') return False # Read entire file into a global byte array btFron = self.flFron.read() if len(btFron) < 100: Fronimo.print_error(self.stFile, 'Cannot read fronimo file.') return False self.stFron = btFron.decode("latin1") if len(self.stFron) < 100: Fronimo.print_error(self.stFile, 'Cannot decode fronimo file.') return False return True # end of read_and_unzip_file # get x number of chars from string. Updates offset value def _get(self, numChars): if numChars == 0: return "" oldOffset = self.offset self.offset += numChars if (self.offset) > len(self.stFron): errMsg = "Cannot get %d chars starting at offset %d" % (numChars, oldOffset) Fronimo.print_error(self.stFile, errMsg) return "" return self.stFron[oldOffset:self.offset] # Get two bytes of info def _getWord(self, fSigned): inCh = self._get(1) if inCh == "": errMsg = "No first byte in stFron at offset %d" % (self.offset) Fronimo.print_error(self.stFile, errMsg) return -1 word1 = ord(inCh) inCh = self._get(1) if inCh == "": errMsg = "No 2nd byte in stFron at offset %d" % (self.offset) Fronimo.print_error(self.stFile, errMsg) return -1 word2 = 256 * ord(inCh) word = word1 + word2 if (fSigned and word > 32768): word -= 65536 return word # Get a fronimo-formatted string def _getBstr(self): # first byte is string length if < 255 firstByte = self._get(1) if firstByte == False: errMsg = "No first byte in stFron at offset %d" % (self.offset) Fronimo.print_error(self.stFile, errMsg) return "" length = ord(firstByte) if length == 0: return "" # First char 255 means a long string. # Next 2 chars determine string length as an unsigned integer if length == 255: length = self._getWord(False) if length == -1: errMsg = "Zero string length from _getWord, offset %d" % (self.offset) Fronimo.print_error(self.stFile, errMsg) return "" stOut = self._get(length) if stOut == "": errMsg = "Result of get(length) is "", at offset %d" % (self.offset) Fronimo.print_error(self.stFile, errMsg) return "" return stOut def _put(self, stNew): # Assumes new string is RTF'd, if necessary, but not in fronimo string format, # with leading length indicator # Find length of old fronimo string ch = self._get(1) if ch == '\xFF': # means next 2 chars determine length byte1 = self._get(1) if byte1 == "": errMsg = "No first byte in stFron at offset %d" % (self.offset) Fronimo.print_error(self.stFile, errMsg) return False word1 = ord(byte1) byte2 = self._get(1) if byte2 == "": errMsg = "No second byte in stFron at offset %d" % (self.offset) Fronimo.print_error(self.stFile, errMsg) return False # second byte is higher order word2 = 256 * ord(byte2) # Length of actual string + 3 bytes to specify the length length = word1 + word2 + 3 # reset offset to compensate for 3 _get(1)'s self.offset -= 3 else: # Length of actual string + 1 byte to specify the length length = ord(ch) + 1 # reset offset to compensate for 1 _get(1) self.offset -= 1 # find length of new string newLen = len(stNew) if newLen < 255: stInsert = chr(newLen) # We will add one length indicator to the head of the string newLen += 1 else: stInsert = chr(255) + chr(newLen % 256) + chr(int(newLen / 256)) # We will add three length indicators to the head of the string newLen += 3 # Add leading length indicator stNew = stInsert + stNew # splice in the new string stOut = self.stFron[:self.offset] + stNew + self.stFron[self.offset + length:] # set new offset self.offset += newLen self.stFron = stOut return True # end _put def latin2rtf(self, stIn): stOut = "" for i in range (len(stIn)): s = stIn[i] if ord(s) >= 127: # hex value of latin1 char --> last 2 chars of rtf code hexchars = hex(ord(s)) hexchars = hexchars.replace('0x', '') s = "\\\'" + hexchars elif s == '|': s = '\\par\r\n' stOut += s return RTFPREFIX + stOut + RTFSUFFIX def replace_rtf_codes(self, stIn): accentLoc = stIn.find('\\\'') while accentLoc >= 0: # Get last 2 characters of string \'xx = hex char value rtfCode = stIn[accentLoc + 2:accentLoc + 4] # convert to latin1 character latin1 = chr(int(rtfCode, 16)) if latin1: stIn = stIn.replace(rtfCode, latin1, 1) stIn = stIn.replace("\\'", '', 1) accentLoc = stIn.find('\\\'') stIn = stIn.replace('\\par', '|') stIn = stIn.replace('\\cf1', '') stIn = stIn.replace('\\cf0', '') stIn = re.sub(r'\\lang[0-9]*', '', stIn) stIn = stIn.replace(' ', ' ') # KLUDGE to handle unicode weirdness val = reUnicode.search(stIn) if val: uni = val.group(2) # lop off final character from unicode sequence stIn = stIn.replace(uni, uni[:-1]) return(stIn) def rtf2latin(self, stRtf): if stRtf.find('{\\rtf', 0) != 0: return stRtf if len(stRtf) < 100: return stRtf start = stRtf.find('\\f0\\fs', 0) if start == -1: return stRtf start += 9 end = stRtf.find('\\par\r\n}\r\n', start + 1) if end == -1: return stRtf stOut = stRtf[start:end] stOut = stOut.replace('\\par\r\n', '\n') stOut = stOut.replace('\\{', '{') stOut = stOut.replace('\\}', '}') # KLUDGE to get rid of \langxxxx peculiarity that sometimes shows up # Might want to reinstate this if we can figure out what it means val = reDeLang.search(stOut) if val: lang1234 = val.group(1) stOut = stOut.replace(lang1234, "") stOut = stOut.strip(' \t') stOut = self.replace_rtf_codes(stOut) return stOut def get_composer0(self): if self.subtitle == '': return '' #Leave subtitle intact but mine for composer0 pcont = reParenContents.search(self.subtitle) if pcont: inParen = pcont.group(2) hyphenIndex = inParen.find(' - ') if hyphenIndex != -1: inParen = inParen[hyphenIndex + 3:] else: return '' return inParen def parse_document(self, doc): if doc == "": Fronimo.print_error(self.stFile, "No document") return False val = reGetDate.search(doc) # We have a date if val: self.date = val.group(1) self.date = self.date.strip() val = reApproxDate.search(self.date) if val: caMark = val.group(1) if caMark != "": self.date = self.date.replace(caMark, "") self.date = "c." + self.date val = re.search('\(\>?c?a?\.? ?[0-9]{4}\), *([fp#%]{1,2}\.* *[^.]*)\.?$', doc, re.DOTALL) if val: self.page = val.group(1) self.page = self.page.replace(" ", "") else: self.page = "" # this is not really an error, per se. # Fronimo.print_error(self.stFile, "No page # in %s" % doc) else: self.date = "" Fronimo.print_error(self.stFile, "Cannot get date from %s" % doc) # Look for a page anyway (unlikely) val = re.search(', *([fp#%]{1,2}\.* *.*)\.$', doc, re.DOTALL) if val: self.page = val.group(1) else: self.page = "" Fronimo.print_error(self.stFile, "No page # in %s" % doc) # Get document without date and page val = re.search(' ?\(\>?c?a?\.? ?[12][0-9]{3}\)', doc) if val: end = val.span()[0] self.document = doc[:end] else: self.document = doc self.document = self.document.strip() val = re.search("([^,][^,]*), *v[. ] *([^,]+)", self.document) if val == None: self.volume = '' else: self.document = val.group(1) self.volume = val.group(2) return True #end of parse document def parse_credits(self, cred): # expand abbreviations [Ee]d. [Ee]nc, and & cred = cred.replace(' & ', ' and ') cred = re.sub('\.$', '', cred) if reEd.search(cred): cred = cred.replace('d.', 'dited', 1) if reEnc.search(cred): cred = cred.replace('nc.', 'ncoded', 1) # Change [IiEe]ntabulated to Encoded val = reEntabulated.search(cred) if val: src = val.group(1) cred = cred.replace(src, "Encoded") #Handle "by", "and", and ";" in credits string val = re.search('[Ee](?:dited|ncoded) and [Ee](?:dited|ncoded) by (..*)$', cred, re.DOTALL) if val: if val.group(1) == 'S.Gerbode': self.editor = self.encoder = 'Sarge Gerbode' else: self.encoder = val.group(1) self.encoder = self.encoder.replace('S.Gerbode','Sarge Gerbode') self.editor = self.encoder return True val = re.search('(E(?:ncoded|dited)) by (..+) ?(?:[;.]|and) ([Ee](?:dited|ncoded)) by (..*)$', cred, re.DOTALL) if val: type1 = val.group(1) cred1 = val.group(2) type2 = val.group(3) cred2 = val.group(4) if type1 == "Edited": self.editor = cred1.strip() self.encoder= cred2.strip() else: self.encoder = cred1.strip() self.editor = cred2.strip() self.editor = self.editor.replace('S.Gerbode', 'Sarge Gerbode') self.encoder = self.encoder.replace('S.Gerbode', 'Sarge Gerbode') return True self.editor = self.encoder = "" return False # End parse_credits def parse_footnote(self): self.source = self.document = self.volume = self.date = self.page = self.encoder = self.editor = "" if self.footnote == "": return lsParts = re.split(' +', self.footnote) numParts = len(lsParts) if numParts < 2 or numParts > 3: stErr = "Footnote \"%s\" has wrong # of parts (%d)" % (self.footnote, numParts) Fronimo.print_error(self.stFile, stErr) return False if numParts == 2: # source == ''; later, source will = composer doc, cred = lsParts else: self.source, doc, cred = lsParts # return False if not self.parse_document(doc): Fronimo.print_error(self.stFile, "Cannot parse document:%s" % doc) return False if not self.parse_credits(cred): Fronimo.print_error(self.stFile, "Cannot parse credits: %s." % cred) return True # End parse_footnote def parse_info(self): # initialize with existing values global instCount global partCount lsInfo = re.split('\n', self.info) isRemark = False remarks = "" for datum in lsInfo: datum = datum.strip() # Ignore blank lnes if datum == "": continue if isRemark: if remarks: remarks = remarks + '|' + datum else: remarks = datum else: isRemark = (datum.find('--') == 0) if isRemark: # everything after line stating with '--' is a remark continue if datum.find(':') == -1: continue # so it is a field # decode it reItem = reInfo.search(datum) if reItem: field = reItem.group(1) value = reItem.group(2) value = value.strip() field = field.lower() if field in ["tra", "rea", "arr"]: self.arranger = value elif field in ["lib", "sou", "pub" ]: self.source = value elif field in["ins", "ens" ]: self.ensemble = value elif field in ["doc"]: self.document = value elif field in ["ori", "co0"]: self.composer0 = value elif field == "tit": self.title = value elif field == "sub": self.subtitle = value elif field == "com": self.composer = value elif field == "doc": self.document = value elif field == "pag": self.page = value elif field == "edi": self.editor = value elif field == "enc": self.encoder = value elif field == "int": self.intabulator = value elif field == "con": self.concordances = value elif field == "ctr": self.contributor = value elif field == "pie": self.piece = value elif field == "fac": self.facurl = value elif field == "rec": self.recurl = value elif field == "sec": self.section = value elif field == "typ": self.type = value elif field == "key": self.key = value elif field == "dif": self.difficulty = self.get_diff_val(value) elif field == "par": self.part = value else: stErr = "Info field \"%s\ ""not found" %(field) Fronimo.print_error(self.stFile, stErr) else: continue self.remarks = remarks # checking to see of all parts list items are in the ensemble list. # first collect all items in the ensemble, including tags ensList = self.ensemble.split(",") insList = [] ensItems = [] for ens in ensList: ens = ens.strip() ens = ens.lower() if ens.find(":") > 0: instag = ens.split(":") # Include tags for part check but not for instrument check ensItems.append(instag[0].strip()) ensItems.append(instag[1].strip()) insList.append(instag[1].strip()) else: insList.append(ens) ensItems.append(ens) # Then check part list item against them if self.part != "": partList = self.part.split(",") for ins in partList: ins = ins.strip() ins = ins.lower() if ins == "score": continue if not ins in ensItems: stErr = "Part \"%s\" not in ensemble list" % (ins) partCount += 1 Fronimo.print_error(self.stFile, stErr) for ins in insList: found = False ins = ins.strip() ins = ins.lower() for item in Fronimo.instList: # if item[0] == ins: if item[1] == ins: found = True break if not found: instCount += 1 stErr = "Inst. \"%s\" not found in \"%s\"." % (ins, self.stFile) print(stErr, file=Fronimo.flNewInsts) Fronimo.flNewInsts.flush() # end of for datum in lsInfo return True # end of parse_info # starts with an uncompressed fronimo string (stFron) and reads values into # an instance of a fronimo class object. def populate(self): global facCount #Assume we can parse footnote unless proven otherwise. fFootnote = True self.offset = self.start_offset pg = self._getBstr() # Skip page number string self.footnote = self._getBstr() self.footnote = self.footnote.strip() if not self.parse_footnote(): Fronimo.print_error(self.stFile, "Cannot parse footnote:\n%s" % self.footnote) fFootnote = False newPos = self.stFron.find('CPiece') # This is very unlikely to happen if newPos == -1: Fronimo.print_error(self.stFile, "Cannot find pattern 'CPiece'") return False self.offset = newPos + 14 self.title = self._getBstr() self.title = self.title.strip(' \t') self.title = self.rtf2latin(self.title) self.subtitle = self._getBstr() self.subtitle = self.subtitle.strip('[\t ]') self.subtitle = self.rtf2latin(self.subtitle) self.subtitle = self.subtitle.replace('\n', '|') self.composer0 = self.get_composer0() self.composer = self._getBstr() self.composer = self.composer.strip('[\t ]') self.composer = self.rtf2latin(self.composer) if self.source == "": self.source = self.composer.replace('?', '') if self.source == 'Anonymous': self.source = 'Unknown' self._getBstr() # Discard text at beginning and end of section self._getBstr() self.info = self._getBstr() self.info = self.info.strip() self.info = self.info.replace ('\r', '') # Skip key field; will get key from info field # offset = stFron.find('CBAR',offset) + 10 # keyNum = self._getWord(True) self.composer = self.composer.replace('Anon.', 'Anonymous') self.composer0 = self.composer0.replace('Anon.', 'Anonymous') #test to see if facsimile file exists #only if footnote parse ws OK. if fFootnote: self.facurl = self.get_facurl() if not self.facurl: facCount += 1 if self.info: if not self.parse_info(): Fronimo.print_error(self.stFile, "Cannot parse info string.") else: Fronimo.print_error(self.stFile, "No info data.") self.mtime = int(os.path.getmtime(self.stFile)) self.ctime = int(os.path.getctime(self.stFile)) self.stMidi = self.find_file("midi") self.stMidi = self.stMidi.replace(LOCALBASE, self.base, 1) self.stPdf = self.find_file("pdf") self.stPdf = self.stPdf.replace(LOCALBASE, self.base, 1) return True # End Populate def find_file(self, type): fronDir = os.path.dirname(self.stFile) fronDir = fronDir.replace('\\', '/') fronType = os.path.basename(self.stFile) fronType = fronType.replace('\\', '/') if type == "midi": fronType= fronType.replace('.ft3', '.mid') elif type == 'pdf': fronType = fronType.replace('.ft3', '.pdf') else: fronType = fronType.replace('.ft3', '.tab') typeDir = join_with_fslash(fronDir, type) stFl = join_with_fslash(typeDir, fronType) if not os.path.exists(stFl): return("") else: stFl.replace('\\', '/') return(stFl) # End find_file # Takes data from a fronimo class instance and inserts it into existing stFron def depopulate(self): self.offset = self.start_offset # throw away page number string and update offset pg = self._getBstr() self._put(self.footnote) newPos = self.stFron.find('CPiece') # This is very unlikely to happen if newPos == -1: Fronimo.print_error(self.stFile, "Cannot find pattern 'CPiece'") return False self.offset = newPos + 14 title = self.latin2rtf(self.title) self._put(title) self.subtitle = self.subtitle.replace('\|', '\r\n') self.subtitle = self.latin2rtf(self.subtitle) self._put(self.subtitle) composer = self.latin2rtf(self.composer) self._put(composer) # Discard text at beginning and end of section self._getBstr() self._getBstr() info = self.info info = info.replace('|', '\r\n') self._put(info) return True # end depopulate # If from a template, prompts where to write it to. # If from an existing file, writes to that file # Maybe with a backup file, until all is known to be kosher def write_file(self, fPrompt): flOut = None btFron = bytes(self.stFron, 'latin1') if not fPrompt: stInput = self.stFile else: if self.stFile == TEMPLATE: stFlOut = "" else: stFlOut = self.stFile while flOut == None: if stFlOut: stInput = input("Write file to (%s): " % stFlOut) if stInput == "": stInput = stFlOut if stInput[-4:] != ".ft3": stInput += '.ft3' else: stInput = "" while stInput == "": stInput = input("Write file to: ") if stInput[-4:] != ".ft3": stInput += '.ft3' flOut = gzip.open(stInput, "wb") if flOut.write(btFron) != len(btFron): return False return True def make_changes(self, form): self.title = form.title.data self.subtitle = form.subtitle.data self.section = form.section.data self.composer = form.composer.data self.composer0 = form.orig_composer.data self.ensemble = form.ensemble.data self.mkey = form.mkey.data self.difficulty = form.difficulty.data self.mtype = form.mtype.data self.Source = form.source.data self.document = form.document.data self.volume = form.volume.data self.page = form.page.data self.editor = form.editor.data self.encoder = form.encoder.data self.arranger = form.arranger.data self.intabulator = form.intabulator.data self.contributor = form.contributor.data self.remarks = form.remarks.data self.part = form.part.data self.footnote = self.make_footnote() self.info = self.make_info() def make_info(self): # diDifficulty = {0: 'beginner', 1: 'easy', 2: 'medium', 3: 'challenging', 4: 'hard', 5: 'virtuoso'} stInfo = 'key:' + self.mkey + '\n' + 'type:' + self.mtype + \ 'dif:' + '\n' + self.difficulty + '\n' + \ 'ens:' + '\n' + self.ensemble if self.section: stInfo = stInfo + '\n' + 'section:' + self.section if self.part: stInfo = stInfo + '\n' + 'part:' + self.part if self.concordances: stInfo = stInfo + '\n' + 'con:' + self.concordances if self.recurl: stInfo = stInfo + '\n' + 'rec:' + self.recurl if self.contributor: stInfo = stInfo + '\n' + 'ctr:' + self.contributor if self.remarks: stInfo = stInfo + '\n' + '--' + '\n' + self.remarks return stInfo def make_footnote(self): if self.source != self.composer: stFootnote = self.source + ' ' stFootnote = stFootnote + self.document + ', ' if self.volume >= 1: stFootnote = stFootnote + 'v.' + str(self.volume) + ', ' stFootnote = stFootnote + self.page + '. ' if self.intabulator == self.editor: stFootnote = stFootnote + 'Encoded and edited by ' + self.editor else: stFootnote = stFootnote + 'Encoded by ' + self.encoder +\ ' and edited by ' + 'self. editor' stFootnote = stFootnote + '.' return stFootnote # end of write_file # end of class Fronimo def process_form(form): if not Fronimo.open_error(ERRFILE): print("Cannot open error file.") return stIn = form.inputfile.data #Read in template file into a string and populate Fronimo object print('B4 fronimo = Fronimo(stIn), Fronimo.stFile = ', Fronimo.stFile) input() fronimo = Fronimo(stIn) print('af fronimo = Fronimo(stIn), fronimo.stFile = ', fronimo.stFile) input() #make changes to fronimo class from form fronimo.make_changes(form) #depopulate fronimo class into a string fronimo.write_file("Write to:") #compress string and write to output fronimo file in contributor's directory