def findOrAddTransform(styleFile, styleList, paths = None): """ Simple dictionary storing XSL Transforms. The key is the given styleFile (which could be a string) """ global _createdTransforms global _xml_parser theKey = ' '.join(styleList) # Get the last modification time of the given file to detect changes. First # filter files because there could be some URLs fileStyleList = [x for x in styleList if os.path.exists(x)] ftime = sys.float_info.max if fileStyleList != []: ftime = max([os.path.getmtime(x) for x in fileStyleList]) (transform, tstamp) = _createdTransforms.get(theKey, (None, None)) if (transform != None) and (ftime <= tstamp): # HIT adagio.logDebug('treecache', None, 'HIT: ' + str(styleFile)) return transform # expand includes and create transformation object try: transform = etree.parse(styleFile, _xml_parser) except etree.XMLSyntaxError, e: print i18n.get('severe_parse_error').format(styleFile) print str(e) sys.exit(1)
def clean(rule, dirObj): """ Clean the files produced by this rule """ adagio.logInfo(rule, dirObj, 'Cleaning') # Get the files to process toProcess = glob.glob(os.path.join(dirObj.current_dir, '*.xcf')) if toProcess == []: adagio.logDebug(rule, dirObj, i18n.get('no_file_to_process')) return # Loop over the source files to see if an execution is needed dstFiles = [] dstDir = dirObj.getProperty(rule, 'src_dir') for datafile in toProcess: # If file not found, terminate if not os.path.isfile(datafile): print i18n.get('file_not_found').format(datafile) sys.exit(1) # Derive the destination file name dstFile = os.path.splitext(os.path.basename(datafile))[0] + '.png' dstFile = os.path.abspath(os.path.join(dstDir, dstFile)) if not os.path.exists(dstFile): continue rules.remove(dstFile) return
def update(dst, srcSet = None, baseDir=None): """ Modifies the graph to reflect the addition of edges from each of the elements in srcSet to dst. If srcSet is empty it only updates the date of dst with the st_mtime value and propagates the result. If baseDir is set, this directory name is used for expanding relative paths while parsing dependencies. Useful for LaTeX, for example. If not set, relative file names take as base the location of fileName. Returns the index of the destination node """ global __FileNameToNodeIDX global __IDXToName global __NodeDate global __NodeOutEdges if srcSet == None: srcSet = set([]) # If a string is given, translate to index if (type(dst) == str) or (type(dst) == unicode): dstIDX = addNode(dst, baseDir=baseDir) else: dstIDX = dst adagio.logDebug('dependency', None, dst) adagio.logDebug('dependency', None, srcSet) # Initialize the mark to the index and date of the destination moreRecentIDX = dstIDX # If the srcSet is empty, update dst with mtime if srcSet == set([]): moreRecentDate = os.path.getmtime(__IDXToName[dstIDX]) else: moreRecentDate = __NodeDate[dstIDX] # Loop over the nodes in the source set for node in srcSet: if type(node) == str or type(node) == unicode: srcIDX = addNode(node, baseDir=baseDir) else: srcIDX = node # Add the edge to the adjacency set __NodeOutEdges[srcIDX].add(dstIDX) # If the new date is more recent, update point if __NodeDate[srcIDX] > moreRecentDate: moreRecentIDX = srcIDX moreRecentDate = __NodeDate[srcIDX] # If the modification needs to propagate go ahead if moreRecentDate > __NodeDate[dstIDX]: __NodeDate[dstIDX] = moreRecentDate for fanoutIDX in __NodeOutEdges[dstIDX]: update(fanoutIDX, set([dstIDX]), baseDir=baseDir) return dstIDX
def getFilesToProcess(rule, dirObj): """ Get the files to process by expanding the expressions in "files" and concatenating the src_dir as prefix. """ # Safety guard, if srcFiles is empty, no need to proceed. Silence. srcFiles = dirObj.getProperty(rule, 'files').split() if srcFiles == []: adagio.logDebug(rule, dirObj, i18n.get('no_file_to_process')) return [] srcDir = dirObj.getProperty(rule, 'src_dir') toProcess = [] for srcFile in srcFiles: found = glob.glob(os.path.join(srcDir, srcFile)) # Something was given in the variable, but nothing was found. Warn the # user but proceed. if found == []: print i18n.get('file_not_found').format(srcFile) # Exiting here sometimes is needed (i.e. when searching for a source # file to process) and sometimes it's ok (i.e. when searching for # files to export). There should be a boolean to select either # behavior # sys.exit(1) toProcess.extend(found) return toProcess
def Execute(rule, dirObj): """ Execute the rule in the given directory """ global has_executable if has_executable == '': has_executable = adagio.findExecutable(rule, dirObj) # If the executable is not present, notify and terminate if not has_executable: print i18n.get('no_executable').format(dirObj.options.get(rule, 'exec')) if dirObj.options.get(rule, 'partial') == '0': sys.exit(1) return # Get the files to process (all *.xcf in the current directory) toProcess = glob.glob(os.path.join(dirObj.current_dir, '*.xcf')) if toProcess == []: adagio.logDebug(rule, dirObj, i18n.get('no_file_to_process')) return scriptFileName = dirObj.getProperty(rule, 'script') if not os.path.isfile(scriptFileName): print i18n.get('file_not_found').format(scriptFileName) sys.exit(1) # Loop over the source files to see if an execution is needed dstFiles = [] dstDir = dirObj.getProperty(rule, 'src_dir') for datafile in toProcess: adagio.logDebug(rule, dirObj, ' EXEC ' + datafile) # If file not found, terminate if not os.path.isfile(datafile): print i18n.get('file_not_found').format(datafile) sys.exit(1) # Derive the destination file name dstFile = os.path.splitext(os.path.basename(datafile))[0] + '.png' dstFile = os.path.abspath(os.path.join(dstDir, dstFile)) # Check for dependencies! try: sources = set([datafile]) sources.update(dirObj.option_files) dependency.update(dstFile, sources) except etree.XMLSyntaxError, e: print i18n.get('severe_parse_error').format(fName) print str(e) sys.exit(1) # If the destination file is up to date, skip the execution if dependency.isUpToDate(dstFile): print i18n.get('file_uptodate').format(os.path.basename(dstFile)) continue # Remember the files to produce dstFiles.append(dstFile)
def doClean(rule, dirObj, toProcess, srcDir, dstDir): """ Function to execute the core of the clean operation. It is in its own function because it is used also by the export rule. """ # Identical source and destination, useless operation if os.path.abspath(srcDir) == os.path.abspath(dstDir): return for datafile in toProcess: adagio.logDebug(rule, dirObj, ' EXEC ' + datafile) # If file not found, terminate if not os.path.exists(datafile): print i18n.get('file_not_found').format(datafile) sys.exit(1) # Remove the srcDir prefix dstFile = datafile.replace(srcDir, '', 1) # If the result has a slash, remove it if dstFile[0] == '/': dstFile = dstFile[1:] # Derive the destination file name dstFile = os.path.abspath(os.path.join(dstDir, dstFile)) # If file is not there, bypass if not os.path.exists(dstFile): continue # Proceed with the cleaning (dump the file name being deleted) rules.remove(dstFile)
def Execute(rule, dirObj): """ Execute the rule in the given directory """ global has_executable if has_executable == '': has_executable = adagio.findExecutable(rule, dirObj) # If the executable is not present, notify and terminate if not has_executable: print i18n.get('no_executable').format(dirObj.options.get(rule, 'exec')) if dirObj.options.get(rule, 'partial') == '0': sys.exit(1) return # Get the files to process, if empty, terminate toProcess = rules.getFilesToProcess(rule, dirObj) if toProcess == []: adagio.logDebug(rule, dirObj, i18n.get('no_file_to_process')) return # Loop over all source files to process executable = dirObj.getProperty(rule, 'exec') extraArgs = dirObj.getProperty(rule, 'extra_arguments') # The command is soffice --nologo --invisible --headless # --convert-to pdf *.doc command = [executable, '--nologo', '--invisible', '--headless', '--convert-to', 'pdf'] command.extend(extraArgs.split()) dstDir = dirObj.getProperty(rule, 'src_dir') for datafile in toProcess: adagio.logDebug(rule, dirObj, ' EXEC ' + datafile) # If file not found, terminate if not os.path.isfile(datafile): print i18n.get('file_not_found').format(datafile) sys.exit(1) # Derive the destination file name dstFileName = os.path.splitext(os.path.basename(datafile))[0] + \ '.pdf' dstFile = os.path.abspath(os.path.join(dstDir, dstFileName)) # Perform the execution command.append(datafile) # command.append('macro:///Tools.MSToPDF.ConvertMSToPDF(' + datafile + ')') rules.doExecution(rule, dirObj, command, datafile, dstFile, stdout = adagio.userLog) command.pop(-1) # End of loop over all src files return
def loadConfigFile(config, filename, aliasDict, includeChain = None): """ Function that receives a set of config options (ConfigParser) and a filename. Parses the file, makes sure all the new config options are present in the first config and adds them to it. The parsing may require, through some options, the inclusion of additional files. The includeChain is a list of files to detect circual includes (and to notify the path to a missing file) Returns a pair (set of files finally loaded, list of rules detected) """ adagio.logDebug('properties', None, 'Parsing ' + filename) # Cannot use empty dictionary as default value in parameter as it # accumulates the values. if includeChain == None: includeChain = [] # If the file to be processed has been processed already, we are in a # "template" chain, terminate if os.path.abspath(filename) in includeChain: commonPrefix = os.path.commonprefix(includeChain) print i18n.get('circular_include') print i18n.get('prefix') + ':', commonPrefix print i18n.get('files') + ':', \ ' '.join(map(lambda x: x.replace(commonPrefix, '', 1), includeChain)) sys.exit(1) # Insert the filename in the includeChain includeChain.append(os.path.normpath(filename)) # If file not found write also the include stack if not os.path.isfile(filename): print i18n.get('cannot_open_file').format(filename) if includeChain[:-1] != []: print i18n.get('included_from') print ' ' + '\n '.join(includeChain[:-1]) sys.exit(1) # Get the ConfigParser for the input file newOptions = getConfigParser(filename) # Move defaults to the original config passing them to a [DEFAULT] rule defaultsIO = StringIO.StringIO() defaultsIO.write('[DEFAULT]\n') for (on, ov) in newOptions.defaults().items(): defaultsIO.write(on + ' = ' + ov + '\n') defaultsIO.seek(0) try: config.readfp(defaultsIO) except ConfigParser.ParsingError, msg: print i18n.get('severe_parse_error').format(filename) print str(msg) defaultsIO.close() sys.exit(1)
def prepareRule(rule, dirObj): """ Obtain the directories to process, calculate the options to set in the remote execution and obtain the remote rules. Return: (list of dirs to process, remote rules, options to set in the remote exec) """ # Get the directories to process from the files option toProcess = [] for srcDir in dirObj.getProperty(rule, 'files').split(): newDirs = glob.glob(srcDir) if newDirs == []: print i18n.get('file_not_found').format(srcDir) sys.exit(1) toProcess.extend(glob.glob(srcDir)) # Add the files included in files_included_from filesIncluded = \ obtainXincludes(dirObj.getProperty(rule, 'files_included_from').split()) # The list of dirs is extended with a set to avoid duplications toProcess.extend(set(map(lambda x: os.path.dirname(x), filesIncluded))) # If there are no files to process stop if toProcess == []: adagio.logDebug(rule, dirObj, i18n.get('no_file_to_process')) return (toProcess, [], None, '') # Translate all paths to absolute paths toProcess = map(lambda x: os.path.abspath(x), toProcess) # Rules to execute in the remote directory remoteRules = dirObj.getProperty(rule, 'rules').split() # Create the option dict for the remote directories optionsToSet = [] newExportDir = dirObj.getProperty(rule, 'export_dst') if newExportDir != '': # If a new dst_dir has been specified, include the options to modify # that variable for each of the rules if remoteRules != []: # If there are some given rules, use them optionsToSet = [x + ' dst_dir ' + newExportDir for x in remoteRules if x.startswith('export')] else: # If no rule is given, leave the option in the export.dst_dir # to its default value default optionsToSet = ['export dst_dir ' + newExportDir] adagio.logInfo(rule, dirObj, 'NEW Options = ' + ', '.join(optionsToSet)) return (toProcess, remoteRules, optionsToSet, newExportDir)
def xsltprocEquivalent(rule, dirObj, styleParams, datafile, dstFile): """ Dump the xsltproc command line equivalent to the given transformation for debugging purposes """ msg = "xsltproc --xinclude" for (a, b) in styleParams.items(): msg += " --stringparam " + '"' + str(a) + '" ' + str(b) msg += " -o " + dstFile msg += " STYLE.xsl" msg += " " + datafile adagio.logDebug(rule, dirObj, "XSLTPROC: " + msg)
def executeFunction(toProcess, rule, dirObj, functionName): """ Execute the given function of the module """ # Translate all the options in the directory to a dictionary scriptOptions = {} for sname in dirObj.options.sections(): for (on, ov) in dirObj.options.items(sname): scriptOptions[sname + '.' + on] = ov # Fold now the default values as well for (on, ov) in dirObj.options.defaults().items(): scriptOptions[on] = ov # Loop over the given source files for datafile in toProcess: adagio.logDebug(rule, dirObj, ' EXEC ' + datafile) (head, tail) = os.path.split(datafile) # Add the source directory to the path to fetch python modules sys.path.insert(0, head) try: module = __import__(tail, fromlist=[]) except ImportError, e: print i18n.get('import_error').format(tail) print str(e) sys.exit(1) # If the file of the import is not what is expected, notify and # terminate. if not module.__file__.startswith(head): print i18n.get('import_collision').format(datafile) sys.exit(1) # Replace argv oldArgv = sys.argv newArgv = dirObj.getProperty(rule, 'arguments') if newArgv != '': sys.argv = [datafile] + newArgv.replace('\n', ' ').split() # If the import has been successfull, go ahead and execute the main try: getattr(sys.modules[tail], functionName)(scriptOptions) except AttributeError, e: print i18n.get('function_error').format(functionName) print str(e) sys.exit(1)
def createParameterDict(rule, dirObj): """ Function that creates the dictionary with all the parameters required to apply the stylesheet. """ # Create the dictionary of stylesheet parameters styleParams = {} styleParams["adagio.home"] = "'" + dirObj.getProperty(adagio.module_prefix, "home") + "'" styleParams["basedir"] = "'" + dirObj.getProperty(adagio.module_prefix, "basedir") + "'" # Calculate adagio.project.home as a relative path with respect to the # project home relProjectHome = os.path.relpath(dirObj.getProperty(adagio.module_prefix, "project_home"), dirObj.current_dir) # Attach always the slash at the end to allow the stylesheets to assume it # and that way, they work in the case of an empty path. relProjectHome = urllib.pathname2url(relProjectHome) + "/" # If the project home is the current one, return the empty string if relProjectHome == "./": relProjectHome = "" adagio.logDebug("Xsltproc", None, "adagio.project.home " + relProjectHome) styleParams["adagio.project.home"] = "'" + relProjectHome + "'" styleParams["adagio.current.datetime"] = "'" + dirObj.getProperty(adagio.module_prefix, "current_datetime") + "'" profileRevision = dirObj.getProperty(adagio.module_prefix, "enabled_profiles").split() if profileRevision != []: styleParams["profile.revision"] = "'" + ";".join(profileRevision) + "'" # Parse the dictionary given in extra_arguments and fold it try: extraDict = eval("{" + dirObj.getProperty(rule, "extra_arguments") + "}") for (k, v) in extraDict.items(): if hasattr(etree.XSLT, "strparam"): # Valid beyond version 2.2 of lxml styleParams[k] = etree.XSLT.strparam(str(v)) else: # If v has quotes, too bad... styleParams[k] = '"' + str(v) + '"' except SyntaxError, e: print i18n.get("error_extra_args").format(rule + ".extra_arguments") print str(e) sys.exit(1)
def getDirectoryObject(path, givenOptions): """ Function that given a path checks if it exists in the createdDirs hash. If so, returns the object. If not, a new object is created. """ global _createdDirs # The key to access the hash is the concatenation of path and givenOptions theKey = path + ''.join(sorted(givenOptions)) dirObj = _createdDirs.get(theKey) if dirObj != None: # Hit in the cache, return adagio.logDebug('Directory', None, 'Directory HIT: ' + path) return dirObj # Create new object dirObj = Directory(path, givenOptions) _createdDirs[theKey] = dirObj return dirObj
def Execute(rule, dirObj): """ Execute the rule in the given directory """ global has_executable if has_executable == '': has_executable = adagio.findExecutable(rule, dirObj) # If the executable is not present, notify and terminate if not has_executable: print i18n.get('no_executable').format(dirObj.options.get(rule, 'exec')) if dirObj.options.get(rule, 'partial') == '0': sys.exit(1) return # Get the directories to synchronize, check if work is needed srcDir = dirObj.getProperty(rule, 'src_dir') dstDir = dirObj.getProperty(rule, 'dst_dir') if srcDir == '' or dstDir == '' or srcDir == dstDir: return # If source directory does not exist, terminate if not os.path.isdir(srcDir): print i18n.get('not_a_directory').format(srcDir) sys.exit(1) # Prepare the command to execute executable = dirObj.getProperty(rule, 'exec') extraArgs = dirObj.getProperty(rule, 'extra_arguments') command = [executable, '-avz'] command.append(srcDir) command.append(dstDir) adagio.logDebug(rule, dirObj, ' EXEC ' + srcDir + ' ' + dstDir) # Perform the execution rules.doExecution(rule, dirObj, command, srcDir, None, adagio.userLog, adagio.userLog) return
def createStyleTransform(styleList, srcDir=None): """ Function that given a list of style sheet files, prepares the style file to be processed. If more than one file is given, a StringIO is created with all of them imported. """ # Prepare style files (locate styles in HOME/Adagio_Styles if needed styles = [] for name in styleList: styles.append(treecache.xml_resolver.resolve_file(name)) # styles.append(dependency.locateFile(name, [srcDir])) if styles[-1] == None: print i18n.get("file_not_found").format(name) sys.exit(1) # If no style is given, terminate if styles == []: return None # If single, leave alone, if multiple, combine in a StringIO using imports if len(styles) == 1: styleFile = styles[0] else: result = StringIO.StringIO( """<?xml version="1.0"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml" xmlns:xi="http://www.w3.org/2001/XInclude" version="1.0" exclude-result-prefixes="xi"> """ ) result.seek(0, os.SEEK_END) for sFile in styles: result.write(""" <xsl:import href="file:""" + urllib.pathname2url(sFile) + """"/>\n""") result.write("</xsl:stylesheet>") result.seek(0) styleFile = result adagio.logDebug("Xsltproc", None, "Applying " + styleFile.getvalue()) # Get the transformation object return treecache.findOrAddTransform(styleFile, styles)
def getConfigParser(fileName): """ Given a set of files, returns the resulting ConfigParser object after being parsed. """ global _configParsers config = _configParsers.get(fileName) if config != None: # Hit in the cache, return adagio.logDebug('properties', None, 'Parser HIT: ' + fileName) return config # Parse the file with a raw parser config = ConfigParser.RawConfigParser({}, ordereddict.OrderedDict) try: config.readfp(codecs.open(fileName, "r", "utf8")) except Exception, msg: print i18n.get('severe_parse_error').format(fileName) print str(msg) sys.exit(1)
def doTransformations(styles, styleTransform, styleParams, toProcess, rule, dirObj, paramDict=None): """ Function that given a style transformation, a set of style parameters, a list of pairs (parameter dicitonaries, suffix), and a list of files to process, applies the transformation to every file, every local dictionary and every language..""" if paramDict == None: paramDict = [({}, "")] # Obtain languages and language prefix/suffix. languages = dirObj.getProperty(rule, "languages").split() language_as = dirObj.getProperty(rule, "language_as").split() # If languages is empty, insert an empty string to force one execution if languages == []: languages = [""] # Remember if the execution is multilingual multilingual = len(languages) > 1 # Make sure the given styles are absolute paths styles = map(lambda x: os.path.abspath(x), styles) # Obtain the file extension to use outputFormat = processOuputFormat(rule, dirObj) # Loop over all source files to process (processing one source file over # several languages gives us a huge speedup because the XML tree of the # source is built only once for all languages. dstDir = dirObj.getProperty(rule, "dst_dir") for datafile in toProcess: adagio.logDebug(rule, dirObj, " EXEC " + datafile) # If file not found, terminate if not os.path.isfile(datafile): print i18n.get("file_not_found").format(datafile) sys.exit(1) # Variable holding the data tree to be processed. Used to recycle the # same tree through the paramDict and language iteration. dataTree = None # Loop over the param dictionaries for (pdict, psuffix) in paramDict: # fold the values of pdict on styleParams, but in a way that they # can be reversed. reverseDict = {} for (n, v) in pdict.items(): reverseDict[n] = styleParams.get(n) styleParams[n] = v # Loop over languages for language in languages: # If processing multilingual, create the appropriate suffix lang_name = "" if multilingual: if language_as == "suffix": lang_name = language + "_" else: lang_name = "_" + language # Insert the appropriate language parameters styleParams["profile.lang"] = "'" + language + "'" styleParams["l10n.gentext.language"] = "'" + language + "'" # Derive the destination file name if language_as == "suffix": dstFile = lang_name + os.path.splitext(os.path.basename(datafile))[0] + psuffix + outputFormat else: dstFile = os.path.splitext(os.path.basename(datafile))[0] + lang_name + psuffix + outputFormat dstFile = os.path.abspath(os.path.join(dstDir, dstFile)) # Apply style and store the result, get the data tree to recycle # it dataTree = singleStyleApplication( datafile, styles, styleTransform, styleParams, dstFile, rule, dirObj, dataTree ) # End of for language loop # Restore the original content of styleParam for (n, v) in reverseDict.items(): if v == None: # Remove the value from the dictionary styleParams.pop(n, None) else: # Replace the value by the old one styleParams[n] = v
def Execute(rule, dirObj): """ Execute the rule in the given directory """ global has_executable if has_executable == '': has_executable = adagio.findExecutable(rule, dirObj) # If the executable is not present, notify and terminate if not has_executable: print i18n.get('no_executable').format(dirObj.options.get(rule, 'exec')) if dirObj.options.get(rule, 'partial') == '0': sys.exit(1) return # Get the files to process, if empty, terminate toProcess = rules.getFilesToProcess(rule, dirObj) if toProcess == []: adagio.logDebug(rule, dirObj, i18n.get('no_file_to_process')) return # Get geometry geometries = dirObj.getProperty(rule, 'geometry').split() if geometries == []: print i18n.get('no_var_value').format('geometry') return # Loop over all source files to process executable = dirObj.getProperty(rule, 'exec') extraArgs = dirObj.getProperty(rule, 'extra_arguments') convertCrop = dirObj.getProperty(rule, 'crop_option') dstDir = dirObj.getProperty(rule, 'dst_dir') for datafile in toProcess: adagio.logDebug(rule, dirObj, ' EXEC ' + datafile) # If file not found, terminate if not os.path.isfile(datafile): print i18n.get('file_not_found').format(datafile) sys.exit(1) # Loop over formats for geometry in geometries: # Derive the destination file name (fn, ext) = os.path.splitext(os.path.basename(datafile)) dstFile = fn + '_' + geometry + ext dstFile = os.path.abspath(os.path.join(dstDir, dstFile)) # Creat the command to execute (slightly non-optimal, because the # following function might NOT execute the process due to # dependencies command = [executable, '-scale', geometry] command.extend(convertCrop.split()) command.extend(extraArgs.split()) command.append(datafile) command.append(dstFile) # Perform the execution rules.doExecution(rule, dirObj, command, datafile, dstFile, adagio.userLog) return
def Execute(rule, dirObj): """ Execute the rule in the given directory """ global has_executable if has_executable == '': has_executable = adagio.findExecutable(rule, dirObj) # If the executable is not present, notify and terminate if not has_executable: print i18n.get('no_executable').format(dirObj.options.get(rule, 'exec')) if dirObj.options.get(rule, 'partial') == '0': sys.exit(1) return # Get the files to process, if empty, terminate toProcess = rules.getFilesToProcess(rule, dirObj) if toProcess == []: return executable = dirObj.getProperty(rule, 'exec') outputFormat = dirObj.getProperty(rule, 'output_format') if not outputFormat in set(['dvi', 'pdf', 'dvipdf']): print i18n.get('program_incorrect_format').format(executable, outputFormat) sys.exit(1) # Prepare the command to execute dstDir = dirObj.getProperty(rule, 'dst_dir') commandPrefix = [executable, '-output-directory=' + dstDir, '-interaction=nonstopmode'] if outputFormat != 'dvipdf': commandPrefix.append('-output-format=' + outputFormat) commandPrefix.extend(dirObj.getProperty(rule, 'extra_arguments').split()) # Loop over all source files to process for datafile in toProcess: adagio.logDebug(rule, dirObj, ' EXEC ' + datafile) # If file not found, terminate if not os.path.isfile(datafile): print i18n.get('file_not_found').format(datafile) sys.exit(1) # Derive the destination file name baseName = os.path.splitext(os.path.basename(datafile))[0] if outputFormat != 'dvipdf': dstFile = baseName + '.' + outputFormat else: dstFile = baseName + '.dvi' pdfFile = baseName + '.pdf' dstFile = os.path.abspath(os.path.join(dstDir, dstFile)) # Add the input file to the command command = commandPrefix + [datafile] # Perform the execution rules.doExecution(rule, dirObj, command, datafile, dstFile, adagio.userLog) if outputFormat == 'dvipdf': rules.doExecution(rule, dirObj, ['dvipdf', dstFile], datafile, pdfFile, adagio.userLog) return
print str(e) sys.exit(1) # If the destination file is up to date, skip the execution if dependency.isUpToDate(dstFile): print i18n.get('file_uptodate').format(os.path.basename(dstFile)) return # Notify the production print i18n.get('producing').format(os.path.basename(dstFile)) else: if datafile != None: print i18n.get('processing').format(os.path.basename(datafile)) else: print i18n.get('processing').format(os.path.basename(dirObj.current_dir)) adagio.logDebug(rule, dirObj, 'Popen: ' + ' '.join(command)) try: pr = subprocess.Popen(command, stdin = stdin, stdout = adagio.userLog, stderr = stderr) pr.wait() except Exception, e: print i18n.get('severe_exec_error').format(command[0]) print i18n.get('exec_line').format(' '.join(command)) print e sys.exit(1) # If dstFile is given, update dependencies if dstFile != None: # If dstFile does not exist, something went wrong if not os.path.exists(dstFile):
def Execute(self, rules = [], pad = ''): """ properties.ddo has been parsed into a ConfigParse. Loop over the rules and execute all of them. """ adagio.logInfo('Directory', self, 'Execute in ' + self.current_dir) # Change directory to the current one self.previous_dir = os.getcwd() os.chdir(self.current_dir) # Print a line flagging the start of the execution showing the maximum # suffix of the current directory up to 80 chars. showCurrentDir = self.current_dir[len(pad) + 3 - 80:] if len(self.current_dir) > (77 - len(pad)): showCurrentDir = '...' + showCurrentDir[3:] print pad + '++ ' + showCurrentDir # Make sure no circular execution is produced if self.executing: print i18n.get('circular_execute_directory').format(self.current_dir) sys.exit(2) self.executing = True # If no rules are given, choose the default ones, that is, ignore: # - adagio # - clean* # - local* # toExecRules = [x for x in self.rule_list if not re.match('^adagio$', x) and not re.match('^clean(\.?\S+)?$', x) and not re.match('^local(\.?\S+)?$', x) and not re.match('^rsync(\.?\S+)?$', x)] # If no rule is given, execute all except the filtered ones if rules == []: rules = toExecRules # If any of the rules is help, vars or clean, expand the current rules # to add them that suffix, otherwise simply accumulate finalRules = [] for rule in rules: if rule == 'deepclean': # Get all the rules finalRules.extend([x + '.deepclean' for x in toExecRules]) finalRules.reverse() elif rule == 'clean': # Get all the rules except the "gotodir" ones finalRules.extend([x + '.clean' for x in toExecRules]) finalRules.reverse() elif rule == 'help': finalRules.append('adagio.help') finalRules.extend([x + '.help' for x in toExecRules]) elif rule == 'vars': finalRules.append('adagio.vars') finalRules.extend([x + '.vars' for x in toExecRules]) elif rule == 'local': finalRules.extend([x for x in toExecRules if not x.startswith('gotodir')]) else: finalRules.append(rule) adagio.logDebug('Directory', self, ' Rules: ' + str(finalRules)) # If after all these preparations, finalRules is empty, help is # needed, hardwire the rule to adagio.help. if finalRules == []: finalRules = ['adagio.help'] adagio.logDebug('Directory', self, ' to execute ' + ' '.join(finalRules)) # Set the XML resolver treecache.setResolver(self.options.get(adagio.module_prefix, 'xml_paths')) # Loop over all the rules and execute them for rule_name in finalRules: # Check the cache to see if rule has already been executed if rule_name in self.executed_rules: adagio.logInfo('Directory', self, 'Rule HIT: ' + self.current_dir + ': ' + \ rule_name) continue # Execute the rule adagio.Execute(rule_name, self, pad) # Insert executed rule in cache self.executed_rules.add(rule_name) self.executing = False adagio.logDebug('Directory', self, ' Executed Rules: ' + str(self.executed_rules)) print pad + '-- ' + showCurrentDir # Change directory to the current one os.chdir(self.previous_dir) return
# Insert the new assignment in options of the directory properties.setProperty(self.options, sn, on, ov) # Compare Adagio versions to see if execution is allowed if not self.isCorrectAdagioVersion(): version = self.options.get(adagio.module_prefix, 'version') adagio.logError('Directory', None, \ 'ERROR: Incorrect Adagio Version (' + version + ')') print i18n.get('incorrect_version').format(version) sys.exit(3) self.current_rule = None # Dump a debug message showing the list of rules detected in the # config file adagio.logDebug('Directory', None, 'Rules: ' + ', '.join(self.rule_list)) return def __del__(self): """ Object no longer needed """ return def isCorrectAdagioVersion(self): """ Method to check if the curren adagio version is within the potentially limited values specified in variables adagio.minimum_version, adagio.maximum_version and adagio.exact_version """
def doCopy(rule, dirObj, toProcess, srcDir, dstDir): """ Effectively perform the copy. The functionality is in this function because it is used also by the export rule. """ # Identical source and destination, useless operation if os.path.abspath(srcDir) == os.path.abspath(dstDir): return # Loop over all source files to process for datafile in toProcess: # Normalize to avoid surprises datafile = os.path.normpath(datafile) # Remember if the source is a directory isDirectory = os.path.isdir(datafile) adagio.logDebug(rule, dirObj, ' EXEC ' + datafile) # If source is not found, terminate if not os.path.exists(datafile): print i18n.get('file_not_found').format(datafile) sys.exit(1) # Remove the srcDir prefix dstFile = datafile.replace(os.path.normpath(srcDir), '', 1) # If the result has a slash (could be a directory to copy or a file with # a directory path), remove it if dstFile[0] == os.sep: dstFile = dstFile[1:] # Derive the destination file name dstFile = os.path.abspath(os.path.join(dstDir, dstFile)) # Check for dependencies! try: sources = set([datafile]) sources.update(dirObj.option_files) dependency.update(dstFile, sources) except etree.XMLSyntaxError, e: print i18n.get('severe_parse_error').format(fName) print str(e) sys.exit(1) # Copying the file/dir adagio.logDebug(rule, dirObj, 'Copy? ' + datafile + ' ' + dstFile) # If the destination file is up to date, skip the execution if (not isDirectory) and dependency.isUpToDate(dstFile): print i18n.get('file_uptodate').format(os.path.basename(dstFile)) continue # Proceed with the execution of copy print i18n.get('copying').format(os.path.basename(dstFile)) # Copying the file/dir adagio.logDebug(rule, dirObj, 'Copy ' + datafile + ' ' + dstFile) if os.path.isdir(datafile): # Copy source tree to dst tree distutils.dir_util.copy_tree(datafile, dstFile) else: # It is a regular file, make sure the dirs leading to it are created dirPrefix = os.path.dirname(dstFile) if not os.path.exists(dirPrefix): os.makedirs(dirPrefix) # Proceed wih the copy shutil.copyfile(datafile, dstFile) # Update the dependencies of the newly created file if not isDirectory: try: dependency.update(dstFile) except etree.XMLSyntaxError, e: print i18n.get('severe_parse_error').format(fName) print str(e) sys.exit(1)