1# -*- test-case-name: twisted.lore.test.test_lore -*- 2# Copyright (c) Twisted Matrix Laboratories. 3# See LICENSE for details. 4 5# 6import sys, os 7import tree #todo: get rid of this later 8import indexer 9 10class NoProcessorError(Exception): 11 pass 12 13class ProcessingFailure(Exception): 14 pass 15 16cols = 79 17 18def dircount(d): 19 return len([1 for el in d.split("/") if el != '.']) 20 21 22class Walker: 23 24 def __init__(self, df, fext, linkrel): 25 self.df = df 26 self.linkrel = linkrel 27 self.fext = fext 28 self.walked = [] 29 self.failures = [] 30 31 def walkdir(self, topdir, prefix=''): 32 self.basecount = dircount(topdir) 33 os.path.walk(topdir, self.walk, prefix) 34 35 def walk(self, prefix, d, names): 36 linkrel = prefix + '../' * (dircount(d) - self.basecount) 37 for name in names: 38 fullpath = os.path.join(d, name) 39 fext = os.path.splitext(name)[1] 40 if fext == self.fext: 41 self.walked.append((linkrel, fullpath)) 42 43 def generate(self): 44 i = 0 45 indexer.clearEntries() 46 tree.filenum = 0 47 for linkrel, fullpath in self.walked: 48 linkrel = self.linkrel + linkrel 49 i += 1 50 fname = os.path.splitext(fullpath)[0] 51 self.percentdone((float(i) / len(self.walked)), fname) 52 try: 53 self.df(fullpath, linkrel) 54 except ProcessingFailure, e: 55 self.failures.append((fullpath, e)) 56 indexer.generateIndex() 57 self.percentdone(1., None) 58 59 def percentdone(self, percent, fname): 60 # override for neater progress bars 61 proglen = 40 62 hashes = int(percent * proglen) 63 spaces = proglen - hashes 64 progstat = "[%s%s] (%s)" %('#' * hashes, ' ' * spaces,fname or "*Done*") 65 progstat += (cols - len(progstat)) * ' ' 66 progstat += '\r' 67 sys.stdout.write(progstat) 68 sys.stdout.flush() 69 if fname is None: 70 print 71 72class PlainReportingWalker(Walker): 73 74 def percentdone(self, percent, fname): 75 if fname: 76 print fname 77 78class NullReportingWalker(Walker): 79 80 def percentdone(self, percent, fname): 81 pass 82 83def parallelGenerator(originalFileName, outputExtension): 84 return os.path.splitext(originalFileName)[0]+outputExtension 85 86def fooAddingGenerator(originalFileName, outputExtension): 87 return os.path.splitext(originalFileName)[0]+"foo"+outputExtension 88 89def outputdirGenerator(originalFileName, outputExtension, inputdir, outputdir): 90 originalFileName = os.path.abspath(originalFileName) 91 abs_inputdir = os.path.abspath(inputdir) 92 if os.path.commonprefix((originalFileName, abs_inputdir)) != abs_inputdir: 93 raise ValueError("Original file name '" + originalFileName + 94 "' not under input directory '" + abs_inputdir + "'") 95 96 adjustedPath = os.path.join(outputdir, os.path.basename(originalFileName)) 97 return tree.getOutputFileName(adjustedPath, outputExtension) 98 99def getFilenameGenerator(config, outputExt): 100 if config.get('outputdir'): 101 return (lambda originalFileName, outputExtension: 102 outputdirGenerator(originalFileName, outputExtension, 103 os.path.abspath(config.get('inputdir')), 104 os.path.abspath(config.get('outputdir')))) 105 else: 106 return tree.getOutputFileName 107 108def getProcessor(module, output, config): 109 try: 110 m = getattr(module.factory, 'generate_'+output) 111 except AttributeError: 112 raise NoProcessorError("cannot generate "+output+" output") 113 114 if config.get('ext'): 115 ext = config['ext'] 116 else: 117 from default import htmlDefault 118 ext = htmlDefault['ext'] 119 120 return m(config, getFilenameGenerator(config, ext)) 121