Package translate :: Package misc :: Module optrecurse
[hide private]
[frames] | no frames]

Source Code for Module translate.misc.optrecurse

  1  #!/usr/bin/env python 
  2  # -*- coding: utf-8 -*- 
  3  #  
  4  # Copyright 2002-2006 Zuza Software Foundation 
  5  #  
  6  # This file is part of translate. 
  7  # 
  8  # translate is free software; you can redistribute it and/or modify 
  9  # it under the terms of the GNU General Public License as published by 
 10  # the Free Software Foundation; either version 2 of the License, or 
 11  # (at your option) any later version. 
 12  #  
 13  # translate is distributed in the hope that it will be useful, 
 14  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 15  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 16  # GNU General Public License for more details. 
 17  # 
 18  # You should have received a copy of the GNU General Public License 
 19  # along with translate; if not, write to the Free Software 
 20  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 21   
 22  import sys 
 23  import os.path 
 24  import fnmatch 
 25  import traceback 
 26  import optparse 
 27  from translate.misc import progressbar 
 28  from translate import __version__ 
 29  try: 
 30    from cStringIO import StringIO 
 31  except ImportError: 
 32    from StringIO import StringIO 
 33   
34 -class ManPageOption(optparse.Option, object):
35 ACTIONS = optparse.Option.ACTIONS + ("manpage",) 36
37 - def take_action(self, action, dest, opt, value, values, parser):
38 """take_action that can handle manpage as well as standard actions""" 39 if action == "manpage": 40 parser.print_manpage() 41 sys.exit(0) 42 return super(ManPageOption, self).take_action(action, dest, opt, value, values, parser)
43
44 -class ManHelpFormatter (optparse.HelpFormatter):
45 - def __init__ (self, 46 indent_increment=0, 47 max_help_position=0, 48 width=80, 49 short_first=1):
50 optparse.HelpFormatter.__init__( 51 self, indent_increment, max_help_position, width, short_first)
52
53 - def format_option_strings (self, option):
54 """Return a comma-separated list of option strings & metavariables.""" 55 if option.takes_value(): 56 metavar = option.metavar or option.dest.upper() 57 metavar = '\\fI%s\\fP'%metavar 58 short_opts = [sopt + metavar for sopt in option._short_opts] 59 long_opts = [lopt + "\\fR=\\fP" + metavar for lopt in option._long_opts] 60 else: 61 short_opts = option._short_opts 62 long_opts = option._long_opts 63 64 if self.short_first: 65 opts = short_opts + long_opts 66 else: 67 opts = long_opts + short_opts 68 69 return '\\fB%s\\fP'%("\\fR, \\fP".join(opts))
70
71 -class RecursiveOptionParser(optparse.OptionParser, object):
72 """A specialized Option Parser for recursing through directories.""" 73
74 - def __init__(self, formats, usetemplates=False, allowmissingtemplate=False, description=None):
75 """Construct the specialized Option Parser. 76 77 @type formats: Dictionary 78 @param formats: See L{setformats()} for an explanation of the formats parameter. 79 80 """ 81 82 optparse.OptionParser.__init__(self, version="%prog "+__version__.ver, description=description) 83 self.setmanpageoption() 84 self.setprogressoptions() 85 self.seterrorleveloptions() 86 self.setformats(formats, usetemplates) 87 self.setpsycooption() 88 self.passthrough = [] 89 self.allowmissingtemplate = allowmissingtemplate
90
91 - def get_prog_name(self):
92 return os.path.basename(sys.argv[0])
93
94 - def setmanpageoption(self):
95 """creates a manpage option that allows the optionparser to generate a manpage""" 96 manpageoption = ManPageOption(None, "--manpage", dest="manpage", default=False, action="manpage", 97 help="output a manpage based on the help") 98 self.define_option(manpageoption)
99
100 - def format_manpage(self):
101 """returns a formatted manpage""" 102 result = [] 103 prog = self.get_prog_name() 104 formatprog = lambda x: x.replace("%prog", prog) 105 formatToolkit = lambda x: x.replace("%prog", "Translate Toolkit") 106 result.append('.\\" Autogenerated manpage\n') 107 result.append('.TH %s 1 "%s" "" "%s"\n' % (prog, 108 formatToolkit(self.version), 109 formatToolkit(self.version))) 110 result.append('.SH NAME\n') 111 result.append('%s \\- %s\n' % (self.get_prog_name(), self.description.split('\n\n')[0])) 112 result.append('.SH SYNOPSIS\n') 113 result.append('.PP\n') 114 usage = "\\fB%prog " 115 usage += " ".join([self.getusageman(option) for option in self.option_list]) 116 usage += "\\fP" 117 result.append('%s\n' % formatprog(usage)) 118 description_lines = self.description.split('\n\n')[1:] 119 if description_lines: 120 result.append('.SH DESCRIPTION\n') 121 result.append('\n'.join(description_lines)) 122 result.append('.SH OPTIONS\n') 123 ManHelpFormatter().store_option_strings(self) 124 result.append('.PP\n') 125 for option in self.option_list: 126 result.append('.TP\n') 127 result.append('%s\n'%option) 128 result.append('%s\n'%option.help) 129 return "".join(result)
130
131 - def print_manpage(self, file=None):
132 """outputs a manpage for the program using the help information""" 133 if file is None: 134 file = sys.stdout 135 file.write(self.format_manpage())
136
137 - def setpsycooption(self):
138 psycomodes = ["none", "full", "profile"] 139 psycooption = optparse.Option(None, "--psyco", dest="psyco", default=None, 140 choices=psycomodes, metavar="MODE", 141 help="use psyco to speed up the operation, modes: %s" % (", ".join(psycomodes))) 142 self.define_option(psycooption)
143
144 - def usepsyco(self, options):
145 # options.psyco == None means the default, which is "full", but don't give a warning... 146 # options.psyco == "none" means don't use psyco at all... 147 if options.psyco == "none": 148 return 149 try: 150 import psyco 151 except Exception: 152 if options.psyco is not None: 153 self.warning("psyco unavailable", options, sys.exc_info()) 154 return 155 if options.psyco is None: 156 options.psyco = "full" 157 if options.psyco == "full": 158 psyco.full() 159 elif options.psyco == "profile": 160 psyco.profile() 161 # tell psyco the functions it cannot compile, to prevent warnings 162 import encodings 163 psyco.cannotcompile(encodings.search_function)
164
165 - def set_usage(self, usage=None):
166 """sets the usage string - if usage not given, uses getusagestring for each option""" 167 if usage is None: 168 self.usage = "%prog " + " ".join([self.getusagestring(option) for option in self.option_list]) 169 else: 170 super(RecursiveOptionParser, self).set_usage(usage)
171
172 - def warning(self, msg, options=None, exc_info=None):
173 """Print a warning message incorporating 'msg' to stderr and exit.""" 174 if options: 175 if options.errorlevel == "traceback": 176 errorinfo = "\n".join(traceback.format_exception(exc_info[0], exc_info[1], exc_info[2])) 177 elif options.errorlevel == "exception": 178 errorinfo = "\n".join(traceback.format_exception_only(exc_info[0], exc_info[1])) 179 elif options.errorlevel == "message": 180 errorinfo = str(exc_info[1]) 181 else: 182 errorinfo = "" 183 if errorinfo: 184 msg += ": " + errorinfo 185 print >> sys.stderr, "\n%s: warning: %s" % (self.get_prog_name(), msg)
186
187 - def getusagestring(self, option):
188 """returns the usage string for the given option""" 189 optionstring = "|".join(option._short_opts + option._long_opts) 190 if getattr(option, "optionalswitch", False): 191 optionstring = "[%s]" % optionstring 192 if option.metavar: 193 optionstring += " " + option.metavar 194 if getattr(option, "required", False): 195 return optionstring 196 else: 197 return "[%s]" % optionstring
198
199 - def getusageman(self, option):
200 """returns the usage string for the given option""" 201 optionstring = "\\fR|\\fP".join(option._short_opts + option._long_opts) 202 if getattr(option, "optionalswitch", False): 203 optionstring = "\\fR[\\fP%s\\fR]\\fP" % optionstring 204 if option.metavar: 205 optionstring += " \\fI%s\\fP" % option.metavar 206 if getattr(option, "required", False): 207 return optionstring 208 else: 209 return "\\fR[\\fP%s\\fR]\\fP" % optionstring
210
211 - def define_option(self, option):
212 """defines the given option, replacing an existing one of the same short name if neccessary...""" 213 for short_opt in option._short_opts: 214 if self.has_option(short_opt): 215 self.remove_option(short_opt) 216 for long_opt in option._long_opts: 217 if self.has_option(long_opt): 218 self.remove_option(long_opt) 219 self.add_option(option)
220
221 - def setformats(self, formats, usetemplates):
222 """Sets the format options using the given format dictionary. 223 224 @type formats: Dictionary 225 @param formats: The dictionary I{keys} should be: 226 - single strings (or 1-tuples) containing an input format (if not usetemplates) 227 - tuples containing an input format and template format (if usetemplates) 228 - formats can be None to indicate what to do with standard input 229 The dictionary I{values} should be tuples of outputformat (string) and processor method. 230 231 """ 232 233 inputformats = [] 234 outputformats = [] 235 templateformats = [] 236 self.outputoptions = {} 237 self.usetemplates = usetemplates 238 for formatgroup, outputoptions in formats.iteritems(): 239 if isinstance(formatgroup, (str, unicode)) or formatgroup is None: 240 formatgroup = (formatgroup, ) 241 if not isinstance(formatgroup, tuple): 242 raise ValueError("formatgroups must be tuples or None/str/unicode") 243 if len(formatgroup) < 1 or len(formatgroup) > 2: 244 raise ValueError("formatgroups must be tuples of length 1 or 2") 245 if len(formatgroup) == 1: 246 formatgroup += (None, ) 247 inputformat, templateformat = formatgroup 248 if not isinstance(outputoptions, tuple) or len(outputoptions) != 2: 249 raise ValueError("output options must be tuples of length 2") 250 outputformat, processor = outputoptions 251 if not inputformat in inputformats: inputformats.append(inputformat) 252 if not outputformat in outputformats: outputformats.append(outputformat) 253 if not templateformat in templateformats: templateformats.append(templateformat) 254 self.outputoptions[(inputformat, templateformat)] = (outputformat, processor) 255 self.inputformats = inputformats 256 inputformathelp = self.getformathelp(inputformats) 257 inputoption = optparse.Option("-i", "--input", dest="input", default=None, metavar="INPUT", 258 help="read from INPUT in %s" % (inputformathelp)) 259 inputoption.optionalswitch = True 260 inputoption.required = True 261 self.define_option(inputoption) 262 excludeoption = optparse.Option("-x", "--exclude", dest="exclude", action="append", 263 type="string", default=["CVS", ".svn", "_darcs"], metavar="EXCLUDE", 264 help="exclude names matching EXCLUDE from input paths") 265 self.define_option(excludeoption) 266 outputformathelp = self.getformathelp(outputformats) 267 outputoption = optparse.Option("-o", "--output", dest="output", default=None, metavar="OUTPUT", 268 help="write to OUTPUT in %s" % (outputformathelp)) 269 outputoption.optionalswitch = True 270 outputoption.required = True 271 self.define_option(outputoption) 272 if self.usetemplates: 273 self.templateformats = templateformats 274 templateformathelp = self.getformathelp(self.templateformats) 275 templateoption = optparse.Option("-t", "--template", dest="template", default=None, metavar="TEMPLATE", 276 help="read from TEMPLATE in %s" % (templateformathelp)) 277 self.define_option(templateoption)
278
279 - def setprogressoptions(self):
280 """sets the progress options""" 281 self.progresstypes = {"none": progressbar.NoProgressBar, 282 "bar": progressbar.HashProgressBar, 283 "dots": progressbar.DotsProgressBar, 284 "names": progressbar.MessageProgressBar, 285 "verbose": progressbar.VerboseProgressBar} 286 progressoption = optparse.Option(None, "--progress", dest="progress", default="bar", 287 choices = self.progresstypes.keys(), metavar="PROGRESS", 288 help="show progress as: %s" % (", ".join(self.progresstypes))) 289 self.define_option(progressoption)
290
291 - def seterrorleveloptions(self):
292 """sets the errorlevel options""" 293 self.errorleveltypes = ["none", "message", "exception", "traceback"] 294 errorleveloption = optparse.Option(None, "--errorlevel", dest="errorlevel", default="message", 295 choices = self.errorleveltypes, metavar="ERRORLEVEL", 296 help="show errorlevel as: %s" % (", ".join(self.errorleveltypes))) 297 self.define_option(errorleveloption)
298
299 - def getformathelp(self, formats):
300 """make a nice help string for describing formats...""" 301 if None in formats: 302 formats = filter(lambda format: format is not None, formats) 303 if len(formats) == 0: 304 return "" 305 elif len(formats) == 1: 306 return "%s format" % (", ".join(formats)) 307 else: 308 return "%s formats" % (", ".join(formats))
309
310 - def isrecursive(self, fileoption, filepurpose='input'):
311 """checks if fileoption is a recursive file""" 312 if fileoption is None: 313 return False 314 elif isinstance(fileoption, list): 315 return True 316 else: 317 return os.path.isdir(fileoption)
318
319 - def parse_args(self, args=None, values=None):
320 """parses the command line options, handling implicit input/output args""" 321 (options, args) = super(RecursiveOptionParser, self).parse_args(args, values) 322 # some intelligent as to what reasonable people might give on the command line 323 if args and not options.input: 324 if len(args) > 1: 325 options.input = args[:-1] 326 args = args[-1:] 327 else: 328 options.input = args[0] 329 args = [] 330 if args and not options.output: 331 options.output = args[-1] 332 args = args[:-1] 333 if args: 334 self.error("You have used an invalid combination of --input, --output and freestanding args") 335 if isinstance(options.input, list) and len(options.input) == 1: 336 options.input = options.input[0] 337 if options.input is None: 338 self.error("You need to give an inputfile or use - for stdin ; use --help for full usage instructions") 339 elif options.input == '-': 340 options.input = None 341 return (options, args)
342
343 - def getpassthroughoptions(self, options):
344 """get the options required to pass to the filtermethod...""" 345 passthroughoptions = {} 346 for optionname in dir(options): 347 if optionname in self.passthrough: 348 passthroughoptions[optionname] = getattr(options, optionname) 349 return passthroughoptions
350
351 - def getoutputoptions(self, options, inputpath, templatepath):
352 """works out which output format and processor method to use...""" 353 if inputpath: 354 inputbase, inputext = self.splitinputext(inputpath) 355 else: 356 inputext = None 357 if templatepath: 358 templatebase, templateext = self.splittemplateext(templatepath) 359 else: 360 templateext = None 361 if (inputext, templateext) in options.outputoptions: 362 return options.outputoptions[inputext, templateext] 363 elif (inputext, "*") in options.outputoptions: 364 outputformat, fileprocessor = options.outputoptions[inputext, "*"] 365 elif ("*", templateext) in options.outputoptions: 366 outputformat, fileprocessor = options.outputoptions["*", templateext] 367 elif ("*", "*") in options.outputoptions: 368 outputformat, fileprocessor = options.outputoptions["*", "*"] 369 elif (inputext, None) in options.outputoptions: 370 return options.outputoptions[inputext, None] 371 elif (None, templateext) in options.outputoptions: 372 return options.outputoptions[None, templateext] 373 elif ("*", None) in options.outputoptions: 374 outputformat, fileprocessor = options.outputoptions["*", None] 375 elif (None, "*") in options.outputoptions: 376 outputformat, fileprocessor = options.outputoptions[None, "*"] 377 else: 378 if self.usetemplates: 379 if inputext is None: 380 raise ValueError("don't know what to do with input format (no file extension), no template file") 381 elif templateext is None: 382 raise ValueError("don't know what to do with input format %s, no template file" % (os.extsep + inputext)) 383 else: 384 raise ValueError("don't know what to do with input format %s, template format %s" % (os.extsep + inputext, os.extsep + templateext)) 385 else: 386 raise ValueError("don't know what to do with input format %s" % os.extsep + inputext) 387 if outputformat == "*": 388 if inputext: 389 outputformat = inputext 390 elif templateext: 391 outputformat = templateext 392 elif ("*", "*") in options.outputoptions: 393 outputformat = None 394 else: 395 if self.usetemplates: 396 if templateext is None: 397 raise ValueError("don't know what to do with input format %s, no template file" % (os.extsep + inputext)) 398 else: 399 raise ValueError("don't know what to do with input format %s, template format %s" % (os.extsep + inputext, os.extsep + templateext)) 400 else: 401 raise ValueError("don't know what to do with input format %s" % os.extsep + inputext) 402 return outputformat, fileprocessor
403
404 - def initprogressbar(self, allfiles, options):
405 """sets up a progress bar appropriate to the options and files""" 406 if options.progress in ('bar', 'verbose'): 407 self.progressbar = self.progresstypes[options.progress](0, len(allfiles)) 408 print >> sys.stderr, "processing %d files..." % len(allfiles) 409 else: 410 self.progressbar = self.progresstypes[options.progress]()
411
412 - def getfullinputpath(self, options, inputpath):
413 """gets the absolute path to an input file""" 414 if options.input: 415 return os.path.join(options.input, inputpath) 416 else: 417 return inputpath
418
419 - def getfulloutputpath(self, options, outputpath):
420 """gets the absolute path to an output file""" 421 if options.recursiveoutput and options.output: 422 return os.path.join(options.output, outputpath) 423 else: 424 return outputpath
425
426 - def getfulltemplatepath(self, options, templatepath):
427 """gets the absolute path to a template file""" 428 if not options.recursivetemplate: 429 return templatepath 430 elif templatepath is not None and self.usetemplates and options.template: 431 return os.path.join(options.template, templatepath) 432 else: 433 return None
434
435 - def run(self):
436 """parses the arguments, and runs recursiveprocess with the resulting options...""" 437 (options, args) = self.parse_args() 438 # this is so derived classes can modify the inputformats etc based on the options 439 options.inputformats = self.inputformats 440 options.outputoptions = self.outputoptions 441 self.usepsyco(options) 442 self.recursiveprocess(options)
443
444 - def recursiveprocess(self, options):
445 """recurse through directories and process files""" 446 if self.isrecursive(options.input, 'input') and getattr(options, "allowrecursiveinput", True): 447 if not self.isrecursive(options.output, 'output'): 448 try: 449 self.warning("Output directory does not exist. Attempting to create") 450 os.mkdir(options.output) 451 except IOError, e: 452 self.error(optparse.OptionValueError("Output directory does not exist, attempt to create failed")) 453 if isinstance(options.input, list): 454 inputfiles = self.recurseinputfilelist(options) 455 else: 456 inputfiles = self.recurseinputfiles(options) 457 else: 458 if options.input: 459 inputfiles = [os.path.basename(options.input)] 460 options.input = os.path.dirname(options.input) 461 else: 462 inputfiles = [options.input] 463 options.recursiveoutput = self.isrecursive(options.output, 'output') and getattr(options, "allowrecursiveoutput", True) 464 options.recursivetemplate = self.usetemplates and self.isrecursive(options.template, 'template') and getattr(options, "allowrecursivetemplate", True) 465 self.initprogressbar(inputfiles, options) 466 for inputpath in inputfiles: 467 try: 468 templatepath = self.gettemplatename(options, inputpath) 469 # If we have a recursive template, but the template doesn't have this 470 # input file, let's drop it. 471 if options.recursivetemplate and templatepath is None and not self.allowmissingtemplate: 472 self.warning("No template at %s. Skipping %s." % (templatepath, inputpath)) 473 continue 474 outputformat, fileprocessor = self.getoutputoptions(options, inputpath, templatepath) 475 fullinputpath = self.getfullinputpath(options, inputpath) 476 fulltemplatepath = self.getfulltemplatepath(options, templatepath) 477 outputpath = self.getoutputname(options, inputpath, outputformat) 478 fulloutputpath = self.getfulloutputpath(options, outputpath) 479 if options.recursiveoutput and outputpath: 480 self.checkoutputsubdir(options, os.path.dirname(outputpath)) 481 except Exception, error: 482 if isinstance(error, KeyboardInterrupt): 483 raise 484 self.warning("Couldn't handle input file %s" % inputpath, options, sys.exc_info()) 485 continue 486 try: 487 success = self.processfile(fileprocessor, options, fullinputpath, fulloutputpath, fulltemplatepath) 488 except Exception, error: 489 if isinstance(error, KeyboardInterrupt): 490 raise 491 self.warning("Error processing: input %s, output %s, template %s" % (fullinputpath, fulloutputpath, fulltemplatepath), options, sys.exc_info()) 492 success = False 493 self.reportprogress(inputpath, success) 494 del self.progressbar
495
496 - def openinputfile(self, options, fullinputpath):
497 """opens the input file""" 498 if fullinputpath is None: 499 return sys.stdin 500 return open(fullinputpath, 'r')
501
502 - def openoutputfile(self, options, fulloutputpath):
503 """opens the output file""" 504 if fulloutputpath is None: 505 return sys.stdout 506 return open(fulloutputpath, 'w')
507
508 - def opentempoutputfile(self, options, fulloutputpath):
509 """opens a temporary output file""" 510 return StringIO()
511
512 - def finalizetempoutputfile(self, options, outputfile, fulloutputpath):
513 """write the temp outputfile to its final destination""" 514 outputfile.reset() 515 outputstring = outputfile.read() 516 outputfile = self.openoutputfile(options, fulloutputpath) 517 outputfile.write(outputstring) 518 outputfile.close()
519
520 - def opentemplatefile(self, options, fulltemplatepath):
521 """opens the template file (if required)""" 522 if fulltemplatepath is not None: 523 if os.path.isfile(fulltemplatepath): 524 return open(fulltemplatepath, 'r') 525 else: 526 self.warning("missing template file %s" % fulltemplatepath) 527 return None
528
529 - def processfile(self, fileprocessor, options, fullinputpath, fulloutputpath, fulltemplatepath):
530 """process an individual file""" 531 inputfile = self.openinputfile(options, fullinputpath) 532 if fulloutputpath and fulloutputpath in (fullinputpath, fulltemplatepath): 533 outputfile = self.opentempoutputfile(options, fulloutputpath) 534 tempoutput = True 535 else: 536 outputfile = self.openoutputfile(options, fulloutputpath) 537 tempoutput = False 538 templatefile = self.opentemplatefile(options, fulltemplatepath) 539 passthroughoptions = self.getpassthroughoptions(options) 540 if fileprocessor(inputfile, outputfile, templatefile, **passthroughoptions): 541 if tempoutput: 542 self.warning("writing to temporary output...") 543 self.finalizetempoutputfile(options, outputfile, fulloutputpath) 544 return True 545 else: 546 # remove the file if it is a file (could be stdout etc) 547 if fulloutputpath and os.path.isfile(fulloutputpath): 548 outputfile.close() 549 os.unlink(fulloutputpath) 550 return False
551
552 - def reportprogress(self, filename, success):
553 """shows that we are progressing...""" 554 self.progressbar.amount += 1 555 self.progressbar.show(filename)
556
557 - def mkdir(self, parent, subdir):
558 """makes a subdirectory (recursively if neccessary)""" 559 if not os.path.isdir(parent): 560 raise ValueError("cannot make child directory %r if parent %r does not exist" % (subdir, parent)) 561 currentpath = parent 562 subparts = subdir.split(os.sep) 563 for part in subparts: 564 currentpath = os.path.join(currentpath, part) 565 if not os.path.isdir(currentpath): 566 os.mkdir(currentpath)
567
568 - def checkoutputsubdir(self, options, subdir):
569 """checks to see if subdir under options.output needs to be created, creates if neccessary""" 570 fullpath = os.path.join(options.output, subdir) 571 if not os.path.isdir(fullpath): 572 self.mkdir(options.output, subdir)
573
574 - def isexcluded(self, options, inputpath):
575 """checks if this path has been excluded""" 576 basename = os.path.basename(inputpath) 577 for excludename in options.exclude: 578 if fnmatch.fnmatch(basename, excludename): 579 return True 580 return False
581
582 - def recurseinputfilelist(self, options):
583 """use a list of files, and find a common base directory for them""" 584 # find a common base directory for the files to do everything relative to 585 commondir = os.path.dirname(os.path.commonprefix(options.input)) 586 inputfiles = [] 587 for inputfile in options.input: 588 if self.isexcluded(options, inputfile): 589 continue 590 if inputfile.startswith(commondir+os.sep): 591 inputfiles.append(inputfile.replace(commondir+os.sep, "", 1)) 592 else: 593 inputfiles.append(inputfile.replace(commondir, "", 1)) 594 options.input = commondir 595 return inputfiles
596
597 - def recurseinputfiles(self, options):
598 """recurse through directories and return files to be processed...""" 599 dirstack = [''] 600 join = os.path.join 601 inputfiles = [] 602 while dirstack: 603 top = dirstack.pop(-1) 604 names = os.listdir(join(options.input, top)) 605 dirs = [] 606 for name in names: 607 inputpath = join(top, name) 608 if self.isexcluded(options, inputpath): 609 continue 610 fullinputpath = self.getfullinputpath(options, inputpath) 611 # handle directories... 612 if os.path.isdir(fullinputpath): 613 dirs.append(inputpath) 614 elif os.path.isfile(fullinputpath): 615 if not self.isvalidinputname(options, name): 616 # only handle names that match recognized input file extensions 617 continue 618 inputfiles.append(inputpath) 619 # make sure the directories are processed next time round... 620 dirs.reverse() 621 dirstack.extend(dirs) 622 return inputfiles
623
624 - def splitext(self, pathname):
625 """splits into name and ext, and removes the extsep""" 626 root, ext = os.path.splitext(pathname) 627 ext = ext.replace(os.extsep, "", 1) 628 return (root, ext)
629
630 - def splitinputext(self, inputpath):
631 """splits an inputpath into name and extension""" 632 return self.splitext(inputpath)
633
634 - def splittemplateext(self, templatepath):
635 """splits a templatepath into name and extension""" 636 return self.splitext(templatepath)
637
638 - def templateexists(self, options, templatepath):
639 """returns whether the given template exists...""" 640 fulltemplatepath = self.getfulltemplatepath(options, templatepath) 641 return os.path.isfile(fulltemplatepath)
642
643 - def gettemplatename(self, options, inputname):
644 """gets an output filename based on the input filename""" 645 if not self.usetemplates: return None 646 if not inputname or not options.recursivetemplate: return options.template 647 inputbase, inputext = self.splitinputext(inputname) 648 if options.template: 649 for inputext1, templateext1 in options.outputoptions: 650 if inputext == inputext1: 651 if templateext1: 652 templatepath = inputbase + os.extsep + templateext1 653 if self.templateexists(options, templatepath): 654 return templatepath 655 if "*" in options.inputformats: 656 for inputext1, templateext1 in options.outputoptions: 657 if (inputext == inputext1) or (inputext1 == "*"): 658 if templateext1 == "*": 659 templatepath = inputname 660 if self.templateexists(options, templatepath): 661 return templatepath 662 elif templateext1: 663 templatepath = inputbase + os.extsep + templateext1 664 if self.templateexists(options, templatepath): 665 return templatepath 666 return None
667
668 - def getoutputname(self, options, inputname, outputformat):
669 """gets an output filename based on the input filename""" 670 if not inputname or not options.recursiveoutput: return options.output 671 inputbase, inputext = self.splitinputext(inputname) 672 outputname = inputbase 673 if outputformat: 674 outputname += os.extsep + outputformat 675 return outputname
676
677 - def isvalidinputname(self, options, inputname):
678 """checks if this is a valid input filename""" 679 inputbase, inputext = self.splitinputext(inputname) 680 return (inputext in options.inputformats) or ("*" in options.inputformats)
681