class Config (object) : def __init__(self, pid, gid=None) : '''Do the primary initialization for this class.''' self.pid = pid self.gid = gid self.user = UserConfig() self.userConfig = self.user.userConfig self.projHome = os.path.join(os.path.expanduser(self.userConfig['Resources']['projects']), self.pid) self.local = ProjLocal(pid, gid) self.tools = Tools() self.log = ProjLog(pid) # Create config placeholders self.projectConfig = None self.adjustmentConfig = None self.layoutConfig = None self.illustrationConfig = None self.fontConfig = None self.macroConfig = None # Log messages for this module self.errorCodes = { '3100' : ['ERR', 'Macro package: [<<1>>] already exists in the project. Use force (-f) to reinstall.'], '3200' : ['ERR', 'Failed to install macro package: [<<1>>]'], '3300' : ['MSG', 'Install macro package: [<<1>>], Reinitialized [<<2>>]'], '3310' : ['ERR', 'Failed to copy [<<1>>] to folder [<<2>>].'], '3400' : ['MSG', 'Force set to True. Removed macro package configuration file: [<<1>>]'], '3500' : ['MSG', 'Removed macro package [<<1>>] folder and all files contained.'], '3600' : ['MSG', 'Updated macro package [<<1>>]'], '3650' : ['ERR', 'Failed to updated macro package [<<1>>]'] } # Test for gid before trying to finish the init # import pdb; pdb.set_trace() if gid : if not self.projectConfig : self.getProjectConfig() # We need to skip over this if the group doesn't exist try : # Reinitialize local self.cType = self.projectConfig['Groups'][gid]['cType'] self.Ctype = self.cType.capitalize() self.local = ProjLocal(pid, gid, self.cType) except : self.cType = None self.Ctype = None else : self.cType = None self.Ctype = None ############################################################################### ############################# Get Config Functions ############################ ############################################################################### ####################### Error Code Block Series = 0500 ######################## ############################################################################### def getProjectConfig (self) : '''Load/return the project configuation object.''' # import pdb; pdb.set_trace() self.projectConfig = self.tools.loadConfig(self.local.projectConfFile, self.local.projectConfXmlFile) def getAdjustmentConfig (self) : '''Load/return the adjustment configuation object.''' self.adjustmentConfig = self.tools.loadConfig(self.local.adjustmentConfFile, self.local.adjustmentConfXmlFile) def getLayoutConfig (self) : '''Load/return the layout configuation object.''' self.layoutConfig = self.tools.loadConfig(self.local.layoutConfFile, self.local.layoutConfXmlFile) def getIllustrationConfig (self) : '''Load/return the illustration configuation object.''' self.illustrationConfig = self.tools.loadConfig(self.local.illustrationConfFile, self.local.illustrationConfXmlFile) def getFontConfig (self) : '''Load/return the font configuation object.''' self.fontConfig = self.tools.loadConfig(self.local.fontConfFile, self.local.fontConfXmlFile) def getMacroConfig (self) : '''Load/return the macro configuration object.''' self.macroConfig = self.tools.loadConfig(self.local.macroConfFile, self.local.macroConfXmlFile) ############################################################################### ############################ Manager Level Functions ########################## ############################################################################### ####################### Error Code Block Series = 1000 ######################## ############################################################################### def makeNewprojectConf (self, local, pid, cVersion, pmid='book') : '''Create a new project configuration file for a new project.''' self.projectConfig = ConfigObj(self.tools.getXMLSettings(os.path.join(local.rapumaConfigFolder, pmid + '.xml')), encoding='utf-8') # Insert intitial project settings self.projectConfig['ProjectInfo']['projectMediaIDCode'] = pmid self.projectConfig['ProjectInfo']['creatorID'] = self.userConfig['System']['userID'] self.projectConfig['ProjectInfo']['projectCreatorVersion'] = cVersion self.projectConfig['ProjectInfo']['projectCreateDate'] = self.tools.tStamp() self.projectConfig['ProjectInfo']['projectIDCode'] = pid self.projectConfig['Backup']['ownerID'] = self.userConfig['System']['userID'] self.projectConfig['Groups'] = {} # Even though there was no push, we need a time stamp to avoid confusion self.projectConfig['Backup']['lastCloudPush'] = self.tools.fullFileTimeStamp() self.projectConfig.filename = local.projectConfFile self.projectConfig.write() ############################################################################### ######################## Basic Config Handling Functions ###################### ############################################################################### ####################### Error Code Block Series = 2000 ######################## ############################################################################### def processSinglePlaceholder (self, ph, value) : '''Once we are sure we have a single placeholder (noting embedded) this will process it and replace it with the correct value.''' holderType = ph.split(':')[0] try : holderKey = ph.split(':')[1] except : holderKey = '' if self.hasPlaceHolder(value): value = self.processNestedPlaceholders(value, '') result = ph # If nothing matches below, default to returning placeholder unchanged if holderType == 'val' : result = value # A value that needs a measurement unit attached elif holderType == 'mu' : result = self.getMeasureUnit() # A value that is from a configObj elif holderKey and holderType == 'config' : result = self.getConfigValue(holderKey) # A value that is a path elif holderKey and holderType == 'path' : result = getattr(self.local, holderKey) # A value that is from a configObj # FIXME: To work around a circular init problem between Config() and Macro() # the macro package name (UsfmTex) has been hard coded. Not sure how to call # another function in another class that relies on this class to work. # This will break when the time comes that another macro family than UsfmTex # is used to hold the functions needed to process values to be used elif holderKey and holderType == 'function' : # import pdb; pdb.set_trace() fnc = getattr(UsfmTex(self.layoutConfig), holderKey) result = fnc() # A value that is a special character (escaped character) elif holderKey and holderType == 'esc' : result = self.getEscapeCharacter(holderKey) # A value that is a font setting elif holderKey and holderType == 'font' : result = self.getFontSetting(holderKey) # A value that is a path separator character elif holderType == 'pathSep' : result = os.sep # A value that contains a system declared value # Note this only works if the value we are looking for has # been declared above in the module init elif holderType == 'self' : # if holderKey.find('.') >= 0 : # splitKey = holderKey.split('.') # if splitKey[0] == 'local' : # result = getattr(self.local, splitKey[1]) # else : # result = getattr(self, holderKey) result = getattr(self.local, holderKey) return result def getFontSetting (self, value) : '''Get a special font setting if there is one. Otherwise return null.''' # FIXME: This may need to be moved to Fonts, plus it might be a # little brittle. Using primaryFont for a default might be asking # for trouble result = '' if value == 'mapping' : useMapping = self.fontConfig['GeneralSettings']['useMapping'] primaryFont = self.projectConfig['CompTypes'][self.cType.capitalize()]['fontName'] if useMapping : result = ':mapping=' + os.path.join(self.local.projFontFolder, primaryFont, useMapping) elif value == 'renderer' : useRenderingSystem = self.fontConfig['GeneralSettings']['useRenderingSystem'] if useRenderingSystem : result = '/' + useRenderingSystem elif value == 'language' : useLanguage = self.fontConfig['GeneralSettings']['useLanguage'] if useLanguage : result = ':language=' + useLanguage elif value == 'feature' : useFeature = self.fontConfig['GeneralSettings']['useFeature'] if useFeature : result = ':' + useFeature return result def getEscapeCharacter (self, value) : '''Return the character specified by the escape code.''' if value == 'lsBracket' : return '[' elif value == 'rsBracket' : return ']' # Add more as needed... def processNestedPlaceholders (self, line, value = '') : '''Search a string (or line) for a type of Rapuma placeholder and insert the value. This is for building certain kinds of config values.''' result = [] end_of_previous_segment = 0 for (ph_start, ph_end) in self.getPlaceHolder(line) : unchanged_segment = line[end_of_previous_segment:ph_start] result.append(unchanged_segment) ph_text = line[ph_start+1:ph_end] replacement = self.processNestedPlaceholders(ph_text, value) result.append(unicode(replacement)) end_of_previous_segment = ph_end+1 # Skip the closing bracket result.append(line[end_of_previous_segment:]) resultline = "".join(result) result_text = self.processSinglePlaceholder(resultline, value) return result_text def hasPlaceHolder (self, line) : '''Return True if this line has a data place holder in it.''' # If things get more complicated we may need to beef this up a bit if line.find('[') > -1 and line.find(']') > -1 : return True def getPlaceHolder (self, line) : '''Return place holder type and a key if one exists from a TeX setting line. Pass over the line and return (yield) each placeholder found.''' nesting_level = 0 remembered_idx = None for idx, ch in enumerate(line): if ch == '[': nesting_level += 1 if remembered_idx is None: remembered_idx = idx elif ch == ']': nesting_level -= 1 if nesting_level <= 0: found_idx = remembered_idx remembered_idx = None yield (found_idx, idx) def getConfigValue (self, val, default=None) : '''Return the value from a config function or just pass the value through, unchanged.''' keyparts = val.split('|') curval = getattr(self, keyparts[0], None) if curval is None: return default for key in keyparts[1:]: curval = curval.get(key, None) if curval is None: return default return curval def getMeasureUnit (self) : '''Return the value with the specified measurement unit attached.''' return self.layoutConfig['GeneralSettings']['measurementUnit']
class Project (object) : def __init__(self, pid, gid) : '''Instantiate this class.''' self.pid = pid self.gid = gid self.user = UserConfig() self.userConfig = self.user.userConfig self.projHome = os.path.join(os.environ['RAPUMA_PROJECTS'], self.pid) self.config = Config(self.pid) self.config.getProjectConfig() self.projectConfig = self.config.projectConfig self.cType = self.projectConfig['Groups'][self.gid]['cType'] self.Ctype = self.cType.capitalize() self.local = ProjLocal(pid, gid, self.cType) self.log = ProjLog(self.pid) self.tools = Tools() self.groups = {} self.components = {} self.managers = {} self.projectMediaIDCode = self.projectConfig['ProjectInfo']['projectMediaIDCode'] self.projectIDCode = self.projectConfig['ProjectInfo']['projectIDCode'] self.projectName = self.projectConfig['ProjectInfo']['projectTitle'] self.plid = self.projectConfig['ProjectInfo']['languageCode'] self.psid = self.projectConfig['ProjectInfo']['scriptCode'] # The gid cannot generally be set yet but we will make a placeholder # for it here and the functions below will set it. (I'm just say'n) # import pdb; pdb.set_trace() m = import_module('rapuma.manager.' + self.projectMediaIDCode) self.__class__ = getattr(m, self.projectMediaIDCode[0].upper() + self.projectMediaIDCode[1:]) # Update the existing config file with the project type XML file # if needed newXmlDefaults = os.path.join(self.local.rapumaConfigFolder, self.projectMediaIDCode + '.xml') xmlConfig = self.tools.getXMLSettings(newXmlDefaults) newConf = ConfigObj(xmlConfig.dict(), encoding='utf-8').override(self.projectConfig) for s,v in self.projectConfig.items() : if s not in newConf : newConf[s] = v # Replace with new conf if new is different from old # Rem new conf doesn't have a filename, give it one if self.projectConfig != newConf : self.projectConfig = newConf self.projectConfig.filename = self.local.projectConfFile # Log messages for this module self.errorCodes = { 'PROJ-000' : ['MSG', 'Project module messages'], 'PROJ-030' : ['MSG', 'Changed [<<1>>][<<2>>][<<3>>] setting from \"<<4>>\" to \"<<5>>\".'], 'PROJ-040' : ['ERR', 'Problem making setting change. Section [<<1>>] missing from configuration file.'], 'PROJ-050' : ['ERR', 'Component [<<1>>] working text file was not found in the project configuration.'], 'PROJ-060' : ['ERR', 'Component [<<1>>] was not found in the project configuration.'], 'PROJ-070' : ['ERR', 'Source file not found: [<<1>>].'], 'PROJ-080' : ['MSG', 'Successful copy of [<<1>>] to [<<2>>].'], 'PROJ-090' : ['ERR', 'Target file [<<1>>] already exists. Use force (-f) to overwrite.'], '0205' : ['LOG', 'Created the [<<1>>] manager object.'], '0210' : ['LOG', 'Wrote out [<<1>>] settings to the project configuration file.'], '0211' : ['ERR', 'Failed to write out project [<<1>>] settings to the project configuration file.'], '0660' : ['ERR', 'Invalid component ID: [<<1>>].'], } ############################################################################### ############################ Manager Level Functions ########################## ############################################################################### ######################## Error Code Block Series = 200 ######################## ############################################################################### def createManager (self, mType) : '''Check to see if a manager is listed in the config and load it if it is not already.''' fullName = self.cType + '_' + mType.capitalize() if fullName not in self.managers : self.addManager(mType) self.loadManager(mType) self.log.writeToLog(self.errorCodes['0205'], [fullName]) def loadManager (self, mType) : '''Do basic load on a manager.''' fullName = self.cType + '_' + mType.capitalize() cfg = self.projectConfig['Managers'][fullName] module = import_module('rapuma.manager.' + mType) ManagerClass = getattr(module, mType.capitalize()) manobj = ManagerClass(self, cfg, self.cType) self.managers[fullName] = manobj def addManager (self, mType) : '''Create a manager reference in the project config that components will point to.''' # import pdb; pdb.set_trace() fullName = self.cType + '_' + mType.capitalize() managerDefaults = None # Insert the Manager section if it is not already there self.tools.buildConfSection(self.projectConfig, 'Managers') if not self.projectConfig['Managers'].has_key(fullName) : self.tools.buildConfSection(self.projectConfig['Managers'], fullName) # Update settings if needed update = False managerDefaults = self.tools.getXMLSettings(os.path.join(self.local.rapumaConfigFolder, mType + '.xml')) for k, v, in managerDefaults.iteritems() : # Do not overwrite if a value is already there if not self.projectConfig['Managers'][fullName].has_key(k) : self.projectConfig['Managers'][fullName][k] = v # If we are dealing with an empty string, don't bother writing out # Trying to avoid needless conf updating here. Just in case we are # working with a list, we'll use len() if len(v) > 0 : update = True # Update the conf if one or more settings were changed if update : if self.tools.writeConfFile(self.projectConfig) : self.log.writeToLog(self.errorCodes['0210'],[fullName]) else : self.log.writeToLog(self.errorCodes['0211'],[fullName]) ############################################################################### ############################ Group Level Functions ############################ ############################################################################### ####################### Error Code Block Series = 0600 ######################## ############################################################################### def renderGroup (self, cidList = '', pages = '', override = '', save = False) : '''Render a group of subcomponents or any number of components in the group specified in the cidList.''' # import pdb; pdb.set_trace() # If there are any cids listed we need to test them if cidList : self.isValidCidList(cidList) # Otherwise, do a basic test for exsistance and move on if self.projectConfig['Groups'].has_key(self.gid) : # Now create the group and pass the params on self.createGroup().render(self.gid, cidList, pages, override, save) return True def createGroup (self) : '''Create a group object that can be acted on. It is assumed this only happens for one group per session. This group will contain one or more compoenents. The information for each one will be contained in the group object.''' # import pdb; pdb.set_trace() # If the object already exists just return it if self.gid in self.groups: return self.groups[self.gid] cType = self.projectConfig['Groups'][self.gid]['cType'] # Create a special component object if called cfg = self.projectConfig['Groups'][self.gid] module = import_module('rapuma.group.' + cType) ManagerClass = getattr(module, cType.capitalize()) groupObj = ManagerClass(self, cfg) self.groups[self.gid] = groupObj return groupObj def isValidCidList (self, thisCidlist) : '''Check to see if all the components in the list are in the group.''' cidList = self.projectConfig['Groups'][self.gid]['cidList'] for cid in thisCidlist : # If this is not a usfm type we do not need to validate if self.cType == 'usfm' : if not cid in cidList : self.log.writeToLog(self.errorCodes['0660'],[cid]) def listAllComponents (self, cType) : '''Generate a list of valid component IDs and cNames for this cType.''' # Create the component object now with a special component caller ID self.createComponent('usfm_internal_caller') # Get the component info dictionary comps = self.components['usfm_internal_caller'].usfmCidInfo() # List and sort cList = list(comps.keys()) cList.sort() # For now we'll output to terminal but may want to change this later. for c in cList : if c != '_z_' : print c, comps[c][1] ############################################################################### ############################ System Level Functions ########################### ############################################################################### def run (self, command, opts, userConfig) : '''Run a command''' if command in self.commands : self.commands[command].run(opts, self, userConfig) else : self.tools.terminalError('The command: [' + command + '] failed to run with these options: ' + str(opts))
class Macro(object): def __init__(self, pid, cType, gid=None): """Do the primary initialization for this class.""" self.pid = pid self.gid = gid self.cType = cType self.user = UserConfig() self.userConfig = self.user.userConfig self.projHome = os.path.join(os.path.expanduser(self.userConfig["Resources"]["projects"]), self.pid) self.local = ProjLocal(pid, gid, cType) # import pdb; pdb.set_trace() self.proj_config = Config(pid) self.proj_config.getProjectConfig() self.projectConfig = self.proj_config.projectConfig self.layoutConfig = self.proj_config.layoutConfig self.tools = Tools() self.log = ProjLog(pid) # Create config placeholders self.layoutConfig = None self.illustrationConfig = None self.macroConfig = self.tools.loadConfig(self.local.macroConfFile, self.local.macroConfXmlFile) # Log messages for this module self.errorCodes = { "3010": ["ERR", "No macro package is registered for the [<<1>>] component type."], "3020": ["ERR", "Cannot update! No macro package is registered for the [<<1>>] component type."], "3050": ["ERR", "Macro package file not found: [<<1>>]"], "3100": [ "ERR", "Macro package: [<<1>>] already exists in the project. I am not allowed to copy over an existing package.", ], "3200": ["ERR", "Failed to install macro package: [<<1>>]"], "3300": ["MSG", "Installed macro package: [<<1>>], Reinitialized [<<2>>]"], "3310": ["ERR", "Failed to copy [<<1>>] to folder [<<2>>]."], "3400": ["MSG", "Removed macro package configuration settings for: [<<1>>] from the macro.conf file."], "3500": ["MSG", "Removed macro package [<<1>>] folder and all files contained."], "3600": ["MSG", "Updated component type [<<1>>] with macro package [<<2>>]"], "3650": ["ERR", "Failed to updated macro package [<<1>>]"], } ############################################################################### ###################### Macro Package Handling Functions ####################### ############################################################################### ######################## Error Code Block Series = 3000 ####################### ############################################################################### def createMacroFiles(self, macPackId): """Create all the necessary macro file names with their assigned paths.""" self.projMacPackFolder = os.path.join(self.local.projMacPackFolder, macPackId) texFileIds = { "preStyTexExtFile": "preSty-ext.tex", "macSettingsFile": "settings.tex", "extTexFile": "extension.tex", "grpExtTexFile": self.gid + "-extension.tex", "": "", "": "", "": "", "": "", "": "", } styFileIds = { "glbExtStyFile": "extension.sty", "grpExtStyFile": self.gid + "-extension.sty", "": "", "": "", "": "", "": "", "": "", } # <file> # <name>TeX lccode Definition File</name> # <description>The TeX file that contains lccode definitions and is linked with the hypenation exclusions file.</description> # <fileID>lccodeTexFile</fileID> # <fileName>[self:gid]-lccode.tex</fileName> # <filePath>[self:projGidFolder]</filePath> # <depends></depends> # <relies></relies> # <note>This file is located in the component group folder to allow more segregated processing.</note> # </file> # <file> # <name>TeX Group Hyphenation Exclusions File</name> # <description>The file that contains the hypenation words exclusions list for the current group that TeX will use to render the text.</description> # <fileID>grpHyphExcTexFile</fileID> # <fileName>[self:gid]-hyphenation.tex</fileName> # <filePath>[self:projGidFolder]</filePath> # <depends></depends> # <relies></relies> # <note>This file is located in the component group folder to allow more segregated processing.</note> # </file> def getMacPackIdFromFileName(self, fileName): """Return the macPack ID based on the file name""" # File name less ext is the ID parts = len(fileName.split(".")) return ".".join(fileName.split(".")[: parts - 1]) def getMacPackIdFromSource(self, source): """Return the macPack ID based on the complete path and file name.""" # Get the file name from the path fileName = self.tools.fName(source) # Return the ID return self.getMacPackIdFromFileName(fileName) def addMacPack(self, source): """Add a macro package to the project. It will not work if the same package is already present. Remove must be used to get rid of the existing one first.""" # import pdb; pdb.set_trace() macPackId = self.getMacPackIdFromSource(source) confXml = os.path.join(self.local.projMacroFolder, macPackId, macPackId + ".xml") if not os.path.isfile(source): self.log.writeToLog(self.errorCodes["3050"], [source]) # Do not add/install if there seems to be a macro package there already if self.projectConfig["CompTypes"][self.cType.capitalize()]["macroPackage"] and os.path.exists( self.local.macroConfFile ): self.log.writeToLog(self.errorCodes["3100"], [macPackId]) return False # Set the projectConf to the new/same package self.projectConfig["CompTypes"][self.cType.capitalize()]["macroPackage"] = macPackId self.tools.writeConfFile(self.projectConfig) # If we got this far, install the a fresh copy of the macPack self.installMacPackOnly(source) # Move the style files and custom TeX files out of the macPack self.moveMacStyles(macPackId) self.moveMacTex(macPackId) # Create a fresh macro.conf file if it dosn't exist if not os.path.isfile(self.local.macroConfFile): self.macroConfig = self.tools.initNewConfig(self.local.macroConfFile, self.local.macroConfXmlFile) # Inject information from this particular macro package mInfo = self.tools.getXMLSettings(confXml) self.macroConfig["Macros"][macPackId] = mInfo.dict() # Save the settings now self.tools.writeConfFile(self.macroConfig) self.log.writeToLog(self.errorCodes["3300"], [macPackId, self.local.macroConfFileName]) return True def moveMacStyles(self, macPackId): """Move the default macro package styles out of the freshly installed project macro package folder to the project Style folder.""" # import pdb; pdb.set_trace() # Collect the style files to copy for f in self.getMacStyExtFiles(macPackId): source = os.path.join(os.path.join(self.local.projMacroFolder, macPackId, f)) target = os.path.join(self.local.projStyleFolder, f) self.tools.makedirs(self.local.projStyleFolder) # Do not overwrite existing files unless force is used if not os.path.exists(target): shutil.copy(source, target) # Look for default and set to read-only defaultStyFile = os.path.join(self.local.projStyleFolder, macPackId + ".sty") if target == defaultStyFile: self.tools.makeReadOnly(defaultStyFile) # Remove the source to avoid confusion if os.path.exists(target): os.remove(source) else: self.log.writeToLog(self.errorCodes["3310"], [source, self.local.projStyleFolder]) def getMacStyExtFiles(self, macPackId): """Return a list of macro package style extention files.""" sFiles = [] macPackFiles = os.listdir(os.path.join(self.local.projMacroFolder, macPackId)) for f in macPackFiles: if f.split(".")[1].lower() == "sty": sFiles.append(f) return sFiles def moveMacTex(self, macPackId): """Move the custom macro package TeX out of the freshly installed project macro package folder to the project TeX folder.""" # Collect the TeX extention files to copy for f in self.getMacTexExtFiles(macPackId): source = os.path.join(os.path.join(self.local.projMacroFolder, macPackId, f)) target = os.path.join(self.local.projTexFolder, f) self.tools.makedirs(self.local.projTexFolder) # Do not overwrite existing files if not os.path.exists(target): shutil.copy(source, target) # Remove the source to avoid confusion if os.path.exists(target): os.remove(source) else: self.log.writeToLog(self.errorCodes["3310"], [source, self.local.projTexFolder]) def getMacTexExtFiles(self, macPackId): """Return a list of macro package TeX extention files.""" tFiles = [] macPackFiles = os.listdir(os.path.join(self.local.projMacroFolder, macPackId)) for f in macPackFiles: if f.find("ext.tex") > 0: tFiles.append(f) return tFiles def removeMacPack(self): """Remove the macro package from a component type""" # import pdb; pdb.set_trace() if self.projectConfig["CompTypes"][self.cType.capitalize()]["macroPackage"] != "": macPackId = self.projectConfig["CompTypes"][self.cType.capitalize()]["macroPackage"] else: self.log.writeToLog(self.errorCodes["3010"], [self.cType]) # Aquire target to delete target = os.path.join(self.local.projMacroFolder, macPackId) # Remove the macPack settings from the config file if it is there try: del self.macroConfig["Macros"][macPackId] # Save the settings now self.tools.writeConfFile(self.macroConfig) self.log.writeToLog(self.errorCodes["3400"], [macPackId]) except: pass # Now remove the macro folder (with all its contents) if os.path.exists(target): shutil.rmtree(target) self.log.writeToLog(self.errorCodes["3500"], [macPackId]) # Remove any style files associated with the macro styTarget = os.path.join(self.local.projStyleFolder, macPackId + ".sty") self.tools.makeExecutable(styTarget) self.tools.removeFile(styTarget) # Remove the reference for this macro package from the component type # that uses it. Normally that would probably be just be one of them. self.projectConfig["CompTypes"][self.cType.capitalize()]["macroPackage"] = "" self.tools.writeConfFile(self.projectConfig) def updateMacPack(self, source): """Update a macro package with the latest version but do not touch the config file.""" # Do not update if no macro package is registered in the projectConfig if not self.projectConfig["CompTypes"][self.cType.capitalize()]["macroPackage"]: self.log.writeToLog(self.errorCodes["3020"], [self.cType.capitalize()]) return False macPackId = self.getMacPackIdFromSource(source) confXml = os.path.join(self.local.projMacroFolder, macPackId, macPackId + ".xml") oldMacPackId = self.projectConfig["CompTypes"][self.cType.capitalize()]["macroPackage"] oldMacDir = os.path.join(self.local.projMacroFolder, oldMacPackId) newMacDir = os.path.join(self.local.projMacroFolder, macPackId) # Install the new macPack (but use the old settings) if self.installMacPackOnly(source): # The current macro system must have a "master" style file. # This is a version of the ParaText style file. Because # an update might include an update to the style file, # we need to copy that from the macro folder to the Style # folder. We will do that now. The name of the file should # be the macPackId + ".sty", in theory. srcStyleFile = os.path.join(self.local.projMacroFolder, macPackId, macPackId + ".sty") oldStyleFile = os.path.join(self.local.projStyleFolder, oldMacPackId + ".sty") newStyleFile = os.path.join(self.local.projStyleFolder, macPackId + ".sty") # Unlock the old one so it can be deleted. self.tools.makeExecutable(oldStyleFile) self.tools.removeFile(oldStyleFile) # Now copy in the new one. shutil.copy(srcStyleFile, newStyleFile) # The style file should never be edited by the user, relock it self.tools.makeReadOnly(newStyleFile) # Update exsisting extention file names. We never want to loose # any settings that the user may have added to the extention # files so we will rename the existing files to have the # new ID otherwise the system will not find them at render time. oldStyExtFile = os.path.join(self.local.projStyleFolder, oldMacPackId + "_ext.sty") oldTexExtFile = os.path.join(self.local.projTexFolder, oldMacPackId + "_ext.tex") oldTexPreStyExtFile = os.path.join(self.local.projTexFolder, oldMacPackId + "_preSty-ext.tex") newStyExtFile = os.path.join(self.local.projStyleFolder, macPackId + "_ext.sty") newTexExtFile = os.path.join(self.local.projTexFolder, macPackId + "_ext.tex") newTexPreStyExtFile = os.path.join(self.local.projTexFolder, macPackId + "_preSty-ext.tex") # By default, we protect any existing versions if os.path.exists(newStyExtFile): os.remove(oldStyExtFile) else: self.tools.renameFile(oldStyExtFile, newStyExtFile) if os.path.exists(newTexExtFile): os.remove(oldTexExtFile) else: self.tools.renameFile(oldTexExtFile, newTexExtFile) if os.path.exists(newTexPreStyExtFile): os.remove(oldTexPreStyExtFile) else: self.tools.renameFile(oldTexPreStyExtFile, newTexPreStyExtFile) # Remove un-needed sty and tex files from the newMacDir to # avoid confusion. The ext files never are updated because # they could contain custom project code that we don't want # to loose in an update. for f in self.getMacStyExtFiles(macPackId): source = os.path.join(newMacDir, f) if os.path.exists(source): os.remove(source) for f in self.getMacTexExtFiles(macPackId): source = os.path.join(newMacDir, f) if os.path.exists(source): os.remove(source) # Remove the old macPack folder shutil.rmtree(oldMacDir) # Merge new settings into old section (change name to new ID) # When updating, we are assuming the new macro is in the same # family as the old one. As such, settings should be almost # identical, but in case new settings are being added, we will # merge them in now. oldConfSettings = self.macroConfig["Macros"][oldMacPackId] newConfSettings = self.tools.getXMLSettings(confXml) # Now merge newConfSettings.merge(oldConfSettings) # Inject the new section # self.tools.buildConfSection(self.macroConfig, macPackId) self.macroConfig["Macros"][macPackId] = newConfSettings.dict() # Delete the old section del self.macroConfig["Macros"][oldMacPackId] # Save the changes self.tools.writeConfFile(self.macroConfig) # Assuming everything went well we will change the macPackID on the cType self.projectConfig["CompTypes"][self.cType.capitalize()]["macroPackage"] = macPackId self.tools.writeConfFile(self.projectConfig) # Report success self.log.writeToLog(self.errorCodes["3600"], [self.cType.capitalize(), macPackId]) return True # But if the install fails everything stays the same and we report else: self.log.writeToLog(self.errorCodes["3650"], [macPackId]) return False def installMacPackOnly(self, source): """Install the new macro package but only that.""" # import pdb; pdb.set_trace() if self.tools.pkgExtract(source, self.local.projMacroFolder, self.local.macroConfXmlFile): return True else: self.log.writeToLog(self.errorCodes["3200"], [self.tools.fName(source)]) return False
class Macro (object) : def __init__(self, pid, cType, gid=None) : '''Do the primary initialization for this class.''' self.pid = pid self.gid = gid self.cType = cType self.user = UserConfig() self.userConfig = self.user.userConfig self.projHome = os.path.join(os.path.expanduser(os.environ['RAPUMA_PROJECTS']), self.pid) self.local = ProjLocal(pid, gid, cType) # import pdb; pdb.set_trace() self.proj_config = Config(pid) self.proj_config.getProjectConfig() self.projectConfig = self.proj_config.projectConfig self.layoutConfig = self.proj_config.layoutConfig self.tools = Tools() self.log = ProjLog(pid) # Create config placeholders self.layoutConfig = None self.illustrationConfig = None self.macroConfig = self.tools.loadConfig(self.local.macroConfFile, self.local.macroConfXmlFile) # Log messages for this module self.errorCodes = { '3010' : ['ERR', 'No macro package is registered for the [<<1>>] component type.'], '3020' : ['ERR', 'Cannot update! No macro package is registered for the [<<1>>] component type.'], '3050' : ['ERR', 'Macro package file not found: [<<1>>]'], '3100' : ['ERR', 'Macro package: [<<1>>] already exists in the project. I am not allowed to copy over an existing package.'], '3200' : ['ERR', 'Failed to install macro package: [<<1>>]'], '3300' : ['MSG', 'Installed macro package: [<<1>>], Reinitialized [<<2>>]'], '3310' : ['ERR', 'Failed to copy [<<1>>] to folder [<<2>>].'], '3400' : ['MSG', 'Removed macro package configuration settings for: [<<1>>] from the macro.conf file.'], '3500' : ['MSG', 'Removed macro package [<<1>>] folder and all files contained.'], '3600' : ['MSG', 'Updated component type [<<1>>] with macro package [<<2>>]'], '3650' : ['ERR', 'Failed to updated macro package [<<1>>]'] } ############################################################################### ###################### Macro Package Handling Functions ####################### ############################################################################### ######################## Error Code Block Series = 3000 ####################### ############################################################################### def createMacroFiles (self, macPackId) : '''Create all the necessary macro file names with their assigned paths.''' self.projMacPackFolder = os.path.join(self.local.projMacPackFolder, macPackId) texFileIds = {'preStyTexExtFile':'preSty-ext.tex', 'macSettingsFile':'settings.tex', 'extTexFile':'extension.tex', 'grpExtTexFile': self.gid + '-extension.tex', '':'', '':'', '':'', '':'', '':'', } styFileIds = {'glbExtStyFile':'extension.sty', 'grpExtStyFile': self.gid + '-extension.sty', '':'', '':'', '':'', '':'', '':''} def getMacPackIdFromFileName (self, fileName) : '''Return the macPack ID based on the file name''' # File name less ext is the ID parts = len(fileName.split('.')) return '.'.join(fileName.split('.')[:parts-1]) def getMacPackIdFromSource (self, source) : '''Return the macPack ID based on the complete path and file name.''' # Get the file name from the path fileName = self.tools.fName(source) # Return the ID return self.getMacPackIdFromFileName(fileName) def addMacPack (self, source) : '''Add a macro package to the project. It will not work if the same package is already present. Remove must be used to get rid of the existing one first.''' # import pdb; pdb.set_trace() macPackId = self.getMacPackIdFromSource(source) confXml = os.path.join(self.local.projMacroFolder, macPackId, macPackId + '.xml') if not os.path.isfile(source) : self.log.writeToLog(self.errorCodes['3050'], [source]) # Do not add/install if there seems to be a macro package there already if self.projectConfig['CompTypes'][self.cType.capitalize()]['macroPackage'] and os.path.exists(self.local.macroConfFile) : self.log.writeToLog(self.errorCodes['3100'], [macPackId]) return False # Set the projectConf to the new/same package self.projectConfig['CompTypes'][self.cType.capitalize()]['macroPackage'] = macPackId self.tools.writeConfFile(self.projectConfig) # If we got this far, install the a fresh copy of the macPack self.installMacPackOnly(source) # Move the style files and custom TeX files out of the macPack self.moveMacStyles(macPackId) self.moveMacTex(macPackId) # Create a fresh macro.conf file if it dosn't exist if not os.path.isfile(self.local.macroConfFile) : self.macroConfig = self.tools.initNewConfig(self.local.macroConfFile, self.local.macroConfXmlFile) # Inject information from this particular macro package mInfo = self.tools.getXMLSettings(confXml) self.macroConfig['Macros'][macPackId] = mInfo.dict() # Save the settings now self.tools.writeConfFile(self.macroConfig) self.log.writeToLog(self.errorCodes['3300'], [macPackId, self.local.macroConfFileName]) return True def moveMacStyles (self, macPackId) : '''Move the default macro package styles out of the freshly installed project macro package folder to the project Style folder.''' # import pdb; pdb.set_trace() # Collect the style files to copy for f in self.getMacStyExtFiles(macPackId) : source = os.path.join(os.path.join(self.local.projMacroFolder, macPackId, f)) target = os.path.join(self.local.projStyleFolder, f) self.tools.makedirs(self.local.projStyleFolder) # Do not overwrite existing files unless force is used if not os.path.exists(target) : shutil.copy(source, target) # Look for default and set to read-only defaultStyFile = os.path.join(self.local.projStyleFolder, macPackId + '.sty') if target == defaultStyFile : self.tools.makeReadOnly(defaultStyFile) # Remove the source to avoid confusion if os.path.exists(target) : os.remove(source) else : self.log.writeToLog(self.errorCodes['3310'], [source,self.local.projStyleFolder]) def getMacStyExtFiles (self, macPackId) : '''Return a list of macro package style extention files.''' sFiles = [] macPackFiles = os.listdir(os.path.join(self.local.projMacroFolder, macPackId)) for f in macPackFiles : if f.split('.')[1].lower() == 'sty' : sFiles.append(f) return sFiles def moveMacTex (self, macPackId) : '''Move the custom macro package TeX out of the freshly installed project macro package folder to the project TeX folder.''' # Collect the TeX extention files to copy for f in self.getMacTexExtFiles(macPackId) : source = os.path.join(os.path.join(self.local.projMacroFolder, macPackId, f)) target = os.path.join(self.local.projTexFolder, f) self.tools.makedirs(self.local.projTexFolder) # Do not overwrite existing files if not os.path.exists(target) : shutil.copy(source, target) # Remove the source to avoid confusion if os.path.exists(target) : os.remove(source) else : self.log.writeToLog(self.errorCodes['3310'], [source,self.local.projTexFolder]) def getMacTexExtFiles (self, macPackId) : '''Return a list of macro package TeX extention files.''' tFiles = [] macPackFiles = os.listdir(os.path.join(self.local.projMacroFolder, macPackId)) for f in macPackFiles : if f.find('ext.tex') > 0 : tFiles.append(f) return tFiles def removeMacPack (self) : '''Remove the macro package from a component type''' # import pdb; pdb.set_trace() if self.projectConfig['CompTypes'][self.cType.capitalize()]['macroPackage'] != '' : macPackId = self.projectConfig['CompTypes'][self.cType.capitalize()]['macroPackage'] else : self.log.writeToLog(self.errorCodes['3010'], [self.cType]) # Aquire target to delete target = os.path.join(self.local.projMacroFolder, macPackId) # Remove the macPack settings from the config file if it is there try : del self.macroConfig['Macros'][macPackId] # Save the settings now self.tools.writeConfFile(self.macroConfig) self.log.writeToLog(self.errorCodes['3400'], [macPackId]) except : pass # Now remove the macro folder (with all its contents) if os.path.exists(target) : shutil.rmtree(target) self.log.writeToLog(self.errorCodes['3500'], [macPackId]) # Remove any style files associated with the macro styTarget = os.path.join(self.local.projStyleFolder, macPackId + '.sty') self.tools.makeExecutable(styTarget) self.tools.removeFile(styTarget) # Remove the reference for this macro package from the component type # that uses it. Normally that would probably be just be one of them. self.projectConfig['CompTypes'][self.cType.capitalize()]['macroPackage'] = '' self.tools.writeConfFile(self.projectConfig) def updateMacPack (self, source) : '''Update a macro package with the latest version but do not touch the config file.''' # Do not update if no macro package is registered in the projectConfig if not self.projectConfig['CompTypes'][self.cType.capitalize()]['macroPackage'] : self.log.writeToLog(self.errorCodes['3020'], [self.cType.capitalize()]) return False macPackId = self.getMacPackIdFromSource(source) confXml = os.path.join(self.local.projMacroFolder, macPackId, macPackId + '.xml') oldMacPackId = self.projectConfig['CompTypes'][self.cType.capitalize()]['macroPackage'] oldMacDir = os.path.join(self.local.projMacroFolder, oldMacPackId) newMacDir = os.path.join(self.local.projMacroFolder, macPackId) # Install the new macPack (but use the old settings) if self.installMacPackOnly(source) : # The current macro system must have a "master" style file. # This is a version of the ParaText style file. Because # an update might include an update to the style file, # we need to copy that from the macro folder to the Style # folder. We will do that now. The name of the file should # be the macPackId + ".sty", in theory. srcStyleFile = os.path.join(self.local.projMacroFolder, macPackId, macPackId + '.sty') oldStyleFile = os.path.join(self.local.projStyleFolder, oldMacPackId + '.sty') newStyleFile = os.path.join(self.local.projStyleFolder, macPackId + '.sty') # Unlock the old one so it can be deleted. self.tools.makeExecutable(oldStyleFile) self.tools.removeFile(oldStyleFile) # Now copy in the new one. shutil.copy(srcStyleFile, newStyleFile) # The style file should never be edited by the user, relock it self.tools.makeReadOnly(newStyleFile) # Update exsisting extention file names. We never want to loose # any settings that the user may have added to the extention # files so we will rename the existing files to have the # new ID otherwise the system will not find them at render time. oldStyExtFile = os.path.join(self.local.projStyleFolder, oldMacPackId + '_ext.sty') oldTexExtFile = os.path.join(self.local.projTexFolder, oldMacPackId + '_ext.tex') oldTexPreStyExtFile = os.path.join(self.local.projTexFolder, oldMacPackId + '_preSty-ext.tex') newStyExtFile = os.path.join(self.local.projStyleFolder, macPackId + '_ext.sty') newTexExtFile = os.path.join(self.local.projTexFolder, macPackId + '_ext.tex') newTexPreStyExtFile = os.path.join(self.local.projTexFolder, macPackId + '_preSty-ext.tex') # By default, we protect any existing versions if os.path.exists(newStyExtFile) : os.remove(oldStyExtFile) else : self.tools.renameFile(oldStyExtFile, newStyExtFile) if os.path.exists(newTexExtFile) : os.remove(oldTexExtFile) else : self.tools.renameFile(oldTexExtFile, newTexExtFile) if os.path.exists(newTexPreStyExtFile) : os.remove(oldTexPreStyExtFile) else : self.tools.renameFile(oldTexPreStyExtFile, newTexPreStyExtFile) # Remove un-needed sty and tex files from the newMacDir to # avoid confusion. The ext files never are updated because # they could contain custom project code that we don't want # to loose in an update. for f in self.getMacStyExtFiles(macPackId) : source = os.path.join(newMacDir, f) if os.path.exists(source) : os.remove(source) for f in self.getMacTexExtFiles(macPackId) : source = os.path.join(newMacDir, f) if os.path.exists(source) : os.remove(source) # Remove the old macPack folder shutil.rmtree(oldMacDir) # Merge new settings into old section (change name to new ID) # When updating, we are assuming the new macro is in the same # family as the old one. As such, settings should be almost # identical, but in case new settings are being added, we will # merge them in now. oldConfSettings = self.macroConfig['Macros'][oldMacPackId] newConfSettings = self.tools.getXMLSettings(confXml) # Now merge newConfSettings.merge(oldConfSettings) # Inject the new section # self.tools.buildConfSection(self.macroConfig, macPackId) self.macroConfig['Macros'][macPackId] = newConfSettings.dict() # Delete the old section del self.macroConfig['Macros'][oldMacPackId] # Save the changes self.tools.writeConfFile(self.macroConfig) # Assuming everything went well we will change the macPackID on the cType self.projectConfig['CompTypes'][self.cType.capitalize()]['macroPackage'] = macPackId self.tools.writeConfFile(self.projectConfig) # Report success self.log.writeToLog(self.errorCodes['3600'], [self.cType.capitalize(), macPackId]) return True # But if the install fails everything stays the same and we report else : self.log.writeToLog(self.errorCodes['3650'], [macPackId]) return False def installMacPackOnly (self, source) : '''Install the new macro package but only that.''' # import pdb; pdb.set_trace() if self.tools.pkgExtract(source, self.local.projMacroFolder, self.local.macroConfXmlFile) : return True else : self.log.writeToLog(self.errorCodes['3200'], [self.tools.fName(source)]) return False
class ProjFont (object) : def __init__(self, pid) : '''Do the primary initialization for this class.''' self.pid = pid self.tools = Tools() self.user = UserConfig() self.log = ProjLog(pid) self.userConfig = self.user.userConfig self.proj_config = Config(pid) self.proj_config.getProjectConfig() self.projectConfig = self.proj_config.projectConfig self.proj_config.getFontConfig() self.fontConfig = self.proj_config.fontConfig self.local = ProjLocal(pid, self.projectConfig) # Load all font settings for use in this module if self.fontConfig : for k, v in self.fontConfig['GeneralSettings'].iteritems() : setattr(self, k, v) # Log messages for this module self.errorCodes = { 'FONT-000' : ['MSG', 'Font module messages'], 'FONT-005' : ['MSG', 'FONT-005 - Unassigned error message ID.'], 'FONT-015' : ['MSG', 'FONT-015 - Unassigned error message ID.'], 'FONT-020' : ['ERR', 'Failed to find font setting in ParaTExt project (.ssf file). A primary font must be set before this component can be successfully rendered.'], 'FONT-025' : ['ERR', 'No source editor was found for this project. Please enter this setting before continuing.'], 'FONT-042' : ['MSG', 'The [<<1>>] font setup information was added to project config'], 'FONT-050' : ['ERR', 'Halt! [<<1>>] not found. - font.copyInFont()'], 'FONT-070' : ['LOG', 'Copied the [<<1>>] font file into the project. - proj_font.copyInFont()'], 'FONT-100' : ['ERR', 'This function has not been implemented yet!. - proj_font.setGlyphMap()'], '0010' : ['LOG', 'Wrote out new font configuration (font.__init__())'], '1220' : ['ERR', 'The Font bundle file [<<1>>] could not be found. Process halted.'], '1235' : ['MSG', 'Font [<<1>>] has been installed into the project.'], '1237' : ['MSG', 'Font [<<1>>] has been updated.'], '1240' : ['ERR', 'Font bundle file [<<1>>] not found.'], '1241' : ['ERR', 'Font bundle [<<1>>] not found.'], '1245' : ['LOG', '<<1>> font setup information added to project config'], '1250' : ['ERR', 'The [<<1>>] font is apparently part of this project. Please remove before trying to re-add this font.'], '1260' : ['MSG', 'The <<1>> font bundle has been copied into the project font folder.'], '1262' : ['LOG', 'The <<1>> font bundle already exsits in the font folder.'], '1265' : ['ERR', 'Failed to extract the [<<1>>] font bundle into the project. Font install process failed.'], '1267' : ['LOG', 'The <<1>> font bundle has been copied into the project font folder.'], '1280' : ['MSG', 'Failed to install the font: [<<1>>] into the project.'], '1370' : ['LOG', 'Removed [<<1>>] font name from project component type: [<<2>>].'], '1380' : ['MSG', 'Removed the [<<1>>] font from the project.'], '1382' : ['MSG', 'Force switch was set (-f). This process has completely removed the [<<1>>] font and settings from the project. - proj_font.removeFont()'], '1390' : ['LOG', 'Removed the [<<1>>] font package.'], '1395' : ['MSG', 'Could not remove the [<<1>>] font package. It may be used by another group. Use force (-f) to remove the package from the font folder.'] } ############################################################################### ############################ Project Level Functions ########################## ############################################################################### ######################## Error Code Block Series = 1000 ####################### ############################################################################### def setGlyphMap (self, cType, font) : '''If needed, set the glyph map used for this component type font.''' self.log.writeToLog('FONT-100') def getFontIdFromFileName (self, fileName) : '''Return the font ID based on the file name''' # File name less ext is the font ID parts = len(fileName.split('.')) return '.'.join(fileName.split('.')[:parts-1]) def getFontIdFromSource (self, source) : '''Return the font ID based on the complete path and file name.''' # Get the file name from the path fileName = self.tools.fName(source) # Return the font ID return self.getFontIdFromFileName(fileName) def recordFont (self, fontId, cType=None) : '''Check for the exsitance of the specified font in the font folder. Then extract the meta data into the appropreate configurations.''' # import pdb; pdb.set_trace() # Set vars do initial checks metaDataSource = os.path.join(self.local.projFontFolder, fontId, fontId + '.xml') if not os.path.isfile(metaDataSource) : self.log.writeToLog(self.errorCodes['1240'], [fontId + '.xml', 'proj_font.recordFont():1240']) # Build the Fonts section in the config (if needed) self.tools.buildConfSection(self.fontConfig, 'Fonts') # (Re)Inject the font info into the macPack config file. fInfo = self.tools.getXMLSettings(metaDataSource) self.fontConfig['Fonts'][fontId] = fInfo.dict() # Save the settings now self.tools.writeConfFile(self.fontConfig) # If a component type was specified, record that as well if cType : self.projectConfig['CompTypes'][cType.capitalize()]['fontName'] = fontId self.tools.writeConfFile(self.projectConfig) return True def copyInFont (self, source) : '''Copy a font into a project. The font is bundled with other necessary components in a .zip file. If the font folder is already there we assume there is a font there and we do not proceed. The user will be prompted to remove the old one first.''' fontId = self.getFontIdFromSource(source) confXml = os.path.join(self.local.projFontFolder, fontId, fontId + '.xml') if not os.path.isfile(source) : self.log.writeToLog(self.errorCodes['1220'], [source]) # Install new copy if self.tools.pkgExtract(source, self.local.projFontFolder, confXml) : self.log.writeToLog(self.errorCodes['1260'], [self.tools.fName(source)]) return True else : self.log.writeToLog(self.errorCodes['1265'], [fontId]) return False def addFont (self, source, cType=None) : '''It is a three step process to install a font. This will both copy in a font and record it in one call. Do not try to install a substitute font. Path is assumed to exsist and contains the file name too.''' # import pdb; pdb.set_trace() fontId = self.getFontIdFromSource(source) # Check for existance, never copy over if self.isFont(fontId) : self.log.writeToLog(self.errorCodes['1250'], [fontId]) # Now install and record if self.copyInFont(source) and self.recordFont(fontId, cType) : self.log.writeToLog(self.errorCodes['1235'], [fontId]) return True else : self.log.writeToLog(self.errorCodes['1280'], [fontId]) return False def updateFontPack (self, source, cType=None) : '''Update a font package but do not change any of the existing settings. If there are setting issues (changes) it would be best to remove, then reinstall. A potential confusion point is that updating a font normally means changing the ID. Then updating actually becomes just installing a font.''' # import pdb; pdb.set_trace() # Get the font ID fontId = self.getFontIdFromSource(source) # Be sure the font is in the project if self.isFont(fontId) : # Remove old copy if os.path.exists(os.path.join(self.local.projFontFolder, fontId)) : shutil.rmtree(os.path.join(self.local.projFontFolder, fontId)) # Bring in a fresh copy if self.copyInFont(source) : # If a component type was specified, record that as well if cType : self.projectConfig['CompTypes'][cType.capitalize()]['fontName'] = fontId self.tools.writeConfFile(self.projectConfig) self.log.writeToLog(self.errorCodes['1237'], [fontId]) return True def removeFontSettings (self, fontId) : '''Remove the font settings from the project.''' # import pdb; pdb.set_trace() if self.fontConfig.has_key('Fonts') : if self.fontConfig['Fonts'].has_key(fontId) : del self.fontConfig['Fonts'][fontId] # Write out the new settings files self.tools.writeConfFile(self.fontConfig) self.log.writeToLog(self.errorCodes['1380'], [fontId]) # Check to see if this font is listed in any of the cTypes # If so, remove it. found = 0 for cType in self.projectConfig['CompTypes'].keys() : # It might be possible that the cType has no font settings, so we check if self.projectConfig['CompTypes'][cType.capitalize()].has_key('fontName') : if self.projectConfig['CompTypes'][cType.capitalize()]['fontName'] == fontId : self.projectConfig['CompTypes'][cType.capitalize()]['fontName'] = '' self.log.writeToLog(self.errorCodes['1370'], [fontId, cType]) found +=1 if found > 0 : self.tools.writeConfFile(self.projectConfig) return True def removeFontPack (self, fontId) : '''Remove a font from a component type which will virtually disconnect it from the calling component type. However, if the force switch is set, then remove the font, regardless as to if it is used by another component or not. This is useful for purging a font from a project but should be used with care.''' # Purge the font files and folder fontDir = os.path.join(self.local.projFontFolder, fontId) if os.path.exists(fontDir) : shutil.rmtree(fontDir) self.log.writeToLog(self.errorCodes['1390'], [fontId]) if self.removeFontSettings(fontId) : return True ############################################################################### ############################ Font Settings Functions ########################## ############################################################################### ######################## Error Code Block Series = 2000 ####################### ############################################################################### def isFont (self, fontId) : '''Return if it is varified that this font is part of the project.''' # First do a cusory check to see if at least the font folder is there fontDir = os.path.join(self.local.projFontFolder, fontId) if not os.path.exists(fontDir) : return False # If the above passed, check in the font config to see if it is listed if not self.fontConfig['Fonts'].has_key(fontId) : return False # If the two tests above passed it is probably there return True