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__.sver, 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 try: 139 import psyco 140 except Exception: 141 return 142 psycomodes = ["none", "full", "profile"] 143 psycooption = optparse.Option(None, "--psyco", dest="psyco", default=None, 144 choices=psycomodes, metavar="MODE", 145 help="use psyco to speed up the operation, modes: %s" % (", ".join(psycomodes))) 146 self.define_option(psycooption)
147
148 - def usepsyco(self, options):
149 # options.psyco == None means the default, which is "full", but don't give a warning... 150 # options.psyco == "none" means don't use psyco at all... 151 if getattr(options, "psyco", "none") == "none": 152 return 153 try: 154 import psyco 155 except Exception: 156 if options.psyco is not None: 157 self.warning("psyco unavailable", options, sys.exc_info()) 158 return 159 if options.psyco is None: 160 options.psyco = "full" 161 if options.psyco == "full": 162 psyco.full() 163 elif options.psyco == "profile": 164 psyco.profile() 165 # tell psyco the functions it cannot compile, to prevent warnings 166 import encodings 167 psyco.cannotcompile(encodings.search_function)
168
169 - def set_usage(self, usage=None):
170 """sets the usage string - if usage not given, uses getusagestring for each option""" 171 if usage is None: 172 self.usage = "%prog " + " ".join([self.getusagestring(option) for option in self.option_list]) 173 else: 174 super(RecursiveOptionParser, self).set_usage(usage)
175
176 - def warning(self, msg, options=None, exc_info=None):
177 """Print a warning message incorporating 'msg' to stderr and exit.""" 178 if options: 179 if options.errorlevel == "traceback": 180 errorinfo = "\n".join(traceback.format_exception(exc_info[0], exc_info[1], exc_info[2])) 181 elif options.errorlevel == "exception": 182 errorinfo = "\n".join(traceback.format_exception_only(exc_info[0], exc_info[1])) 183 elif options.errorlevel == "message": 184 errorinfo = str(exc_info[1]) 185 else: 186 errorinfo = "" 187 if errorinfo: 188 msg += ": " + errorinfo 189 print >> sys.stderr, "\n%s: warning: %s" % (self.get_prog_name(), msg)
190
191 - def getusagestring(self, option):
192 """returns the usage string for the given option""" 193 optionstring = "|".join(option._short_opts + option._long_opts) 194 if getattr(option, "optionalswitch", False): 195 optionstring = "[%s]" % optionstring 196 if option.metavar: 197 optionstring += " " + option.metavar 198 if getattr(option, "required", False): 199 return optionstring 200 else: 201 return "[%s]" % optionstring
202
203 - def getusageman(self, option):
204 """returns the usage string for the given option""" 205 optionstring = "\\fR|\\fP".join(option._short_opts + option._long_opts) 206 if getattr(option, "optionalswitch", False): 207 optionstring = "\\fR[\\fP%s\\fR]\\fP" % optionstring 208 if option.metavar: 209 optionstring += " \\fI%s\\fP" % option.metavar 210 if getattr(option, "required", False): 211 return optionstring 212 else: 213 return "\\fR[\\fP%s\\fR]\\fP" % optionstring
214
215 - def define_option(self, option):
216 """defines the given option, replacing an existing one of the same short name if neccessary...""" 217 for short_opt in option._short_opts: 218 if self.has_option(short_opt): 219 self.remove_option(short_opt) 220 for long_opt in option._long_opts: 221 if self.has_option(long_opt): 222 self.remove_option(long_opt) 223 self.add_option(option)
224
225 - def setformats(self, formats, usetemplates):
226 """Sets the format options using the given format dictionary. 227 228 @type formats: Dictionary 229 @param formats: The dictionary I{keys} should be: 230 - single strings (or 1-tuples) containing an input format (if not usetemplates) 231 - tuples containing an input format and template format (if usetemplates) 232 - formats can be None to indicate what to do with standard input 233 The dictionary I{values} should be tuples of outputformat (string) and processor method. 234 235 """ 236 237 inputformats = [] 238 outputformats = [] 239 templateformats = [] 240 self.outputoptions = {} 241 self.usetemplates = usetemplates 242 for formatgroup, outputoptions in formats.iteritems(): 243 if isinstance(formatgroup, (str, unicode)) or formatgroup is None: 244 formatgroup = (formatgroup, ) 245 if not isinstance(formatgroup, tuple): 246 raise ValueError("formatgroups must be tuples or None/str/unicode") 247 if len(formatgroup) < 1 or len(formatgroup) > 2: 248 raise ValueError("formatgroups must be tuples of length 1 or 2") 249 if len(formatgroup) == 1: 250 formatgroup += (None, ) 251 inputformat, templateformat = formatgroup 252 if not isinstance(outputoptions, tuple) or len(outputoptions) != 2: 253 raise ValueError("output options must be tuples of length 2") 254 outputformat, processor = outputoptions 255 if not inputformat in inputformats: 256 inputformats.append(inputformat) 257 if not outputformat in outputformats: 258 outputformats.append(outputformat) 259 if not templateformat in templateformats: 260 templateformats.append(templateformat) 261 self.outputoptions[(inputformat, templateformat)] = (outputformat, processor) 262 self.inputformats = inputformats 263 inputformathelp = self.getformathelp(inputformats) 264 inputoption = optparse.Option("-i", "--input", dest="input", default=None, metavar="INPUT", 265 help="read from INPUT in %s" % (inputformathelp)) 266 inputoption.optionalswitch = True 267 inputoption.required = True 268 self.define_option(inputoption) 269 excludeoption = optparse.Option("-x", "--exclude", dest="exclude", action="append", 270 type="string", default=["CVS", ".svn", "_darcs", ".git", ".hg", ".bzr"], metavar="EXCLUDE", 271 help="exclude names matching EXCLUDE from input paths") 272 self.define_option(excludeoption) 273 outputformathelp = self.getformathelp(outputformats) 274 outputoption = optparse.Option("-o", "--output", dest="output", default=None, metavar="OUTPUT", 275 help="write to OUTPUT in %s" % (outputformathelp)) 276 outputoption.optionalswitch = True 277 outputoption.required = True 278 self.define_option(outputoption) 279 if self.usetemplates: 280 self.templateformats = templateformats 281 templateformathelp = self.getformathelp(self.templateformats) 282 templateoption = optparse.Option("-t", "--template", dest="template", default=None, metavar="TEMPLATE", 283 help="read from TEMPLATE in %s" % (templateformathelp)) 284 self.define_option(templateoption)
285
286 - def setprogressoptions(self):
287 """sets the progress options""" 288 self.progresstypes = { 289 "none": progressbar.NoProgressBar, 290 "bar": progressbar.HashProgressBar, 291 "dots": progressbar.DotsProgressBar, 292 "names": progressbar.MessageProgressBar, 293 "verbose": progressbar.VerboseProgressBar 294 } 295 progressoption = optparse.Option(None, "--progress", dest="progress", default="bar", 296 choices = self.progresstypes.keys(), metavar="PROGRESS", 297 help="show progress as: %s" % (", ".join(self.progresstypes))) 298 self.define_option(progressoption)
299
300 - def seterrorleveloptions(self):
301 """sets the errorlevel options""" 302 self.errorleveltypes = ["none", "message", "exception", "traceback"] 303 errorleveloption = optparse.Option(None, "--errorlevel", dest="errorlevel", default="message", 304 choices = self.errorleveltypes, metavar="ERRORLEVEL", 305 help="show errorlevel as: %s" % (", ".join(self.errorleveltypes))) 306 self.define_option(errorleveloption)
307
308 - def getformathelp(self, formats):
309 """make a nice help string for describing formats...""" 310 if None in formats: 311 formats = filter(lambda format: format is not None, formats) 312 if len(formats) == 0: 313 return "" 314 elif len(formats) == 1: 315 return "%s format" % (", ".join(formats)) 316 else: 317 return "%s formats" % (", ".join(formats))
318
319 - def isrecursive(self, fileoption, filepurpose='input'):
320 """checks if fileoption is a recursive file""" 321 if fileoption is None: 322 return False 323 elif isinstance(fileoption, list): 324 return True 325 else: 326 return os.path.isdir(fileoption)
327
328 - def parse_args(self, args=None, values=None):
329 """parses the command line options, handling implicit input/output args""" 330 (options, args) = super(RecursiveOptionParser, self).parse_args(args, values) 331 # some intelligent as to what reasonable people might give on the command line 332 if args and not options.input: 333 if len(args) > 1: 334 options.input = args[:-1] 335 args = args[-1:] 336 else: 337 options.input = args[0] 338 args = [] 339 if args and not options.output: 340 options.output = args[-1] 341 args = args[:-1] 342 if args: 343 self.error("You have used an invalid combination of --input, --output and freestanding args") 344 if isinstance(options.input, list) and len(options.input) == 1: 345 options.input = options.input[0] 346 if options.input is None: 347 self.error("You need to give an inputfile or use - for stdin ; use --help for full usage instructions") 348 elif options.input == '-': 349 options.input = None 350 return (options, args)
351
352 - def getpassthroughoptions(self, options):
353 """get the options required to pass to the filtermethod...""" 354 passthroughoptions = {} 355 for optionname in dir(options): 356 if optionname in self.passthrough: 357 passthroughoptions[optionname] = getattr(options, optionname) 358 return passthroughoptions
359
360 - def getoutputoptions(self, options, inputpath, templatepath):
361 """works out which output format and processor method to use...""" 362 if inputpath: 363 inputbase, inputext = self.splitinputext(inputpath) 364 else: 365 inputext = None 366 if templatepath: 367 templatebase, templateext = self.splittemplateext(templatepath) 368 else: 369 templateext = None 370 if (inputext, templateext) in options.outputoptions: 371 return options.outputoptions[inputext, templateext] 372 elif (inputext, "*") in options.outputoptions: 373 outputformat, fileprocessor = options.outputoptions[inputext, "*"] 374 elif ("*", templateext) in options.outputoptions: 375 outputformat, fileprocessor = options.outputoptions["*", templateext] 376 elif ("*", "*") in options.outputoptions: 377 outputformat, fileprocessor = options.outputoptions["*", "*"] 378 elif (inputext, None) in options.outputoptions: 379 return options.outputoptions[inputext, None] 380 elif (None, templateext) in options.outputoptions: 381 return options.outputoptions[None, templateext] 382 elif ("*", None) in options.outputoptions: 383 outputformat, fileprocessor = options.outputoptions["*", None] 384 elif (None, "*") in options.outputoptions: 385 outputformat, fileprocessor = options.outputoptions[None, "*"] 386 else: 387 if self.usetemplates: 388 if inputext is None: 389 raise ValueError("don't know what to do with input format (no file extension), no template file") 390 elif templateext is None: 391 raise ValueError("don't know what to do with input format %s, no template file" % (os.extsep + inputext)) 392 else: 393 raise ValueError("don't know what to do with input format %s, template format %s" % (os.extsep + inputext, os.extsep + templateext)) 394 else: 395 raise ValueError("don't know what to do with input format %s" % os.extsep + inputext) 396 if outputformat == "*": 397 if inputext: 398 outputformat = inputext 399 elif templateext: 400 outputformat = templateext 401 elif ("*", "*") in options.outputoptions: 402 outputformat = None 403 else: 404 if self.usetemplates: 405 if templateext is None: 406 raise ValueError("don't know what to do with input format %s, no template file" % (os.extsep + inputext)) 407 else: 408 raise ValueError("don't know what to do with input format %s, template format %s" % (os.extsep + inputext, os.extsep + templateext)) 409 else: 410 raise ValueError("don't know what to do with input format %s" % os.extsep + inputext) 411 return outputformat, fileprocessor
412
413 - def initprogressbar(self, allfiles, options):
414 """sets up a progress bar appropriate to the options and files""" 415 if options.progress in ('bar', 'verbose'): 416 self.progressbar = self.progresstypes[options.progress](0, len(allfiles)) 417 print >> sys.stderr, "processing %d files..." % len(allfiles) 418 else: 419 self.progressbar = self.progresstypes[options.progress]()
420
421 - def getfullinputpath(self, options, inputpath):
422 """gets the absolute path to an input file""" 423 if options.input: 424 return os.path.join(options.input, inputpath) 425 else: 426 return inputpath
427
428 - def getfulloutputpath(self, options, outputpath):
429 """gets the absolute path to an output file""" 430 if options.recursiveoutput and options.output: 431 return os.path.join(options.output, outputpath) 432 else: 433 return outputpath
434
435 - def getfulltemplatepath(self, options, templatepath):
436 """gets the absolute path to a template file""" 437 if not options.recursivetemplate: 438 return templatepath 439 elif templatepath is not None and self.usetemplates and options.template: 440 return os.path.join(options.template, templatepath) 441 else: 442 return None
443
444 - def run(self):
445 """parses the arguments, and runs recursiveprocess with the resulting options...""" 446 (options, args) = self.parse_args() 447 # this is so derived classes can modify the inputformats etc based on the options 448 options.inputformats = self.inputformats 449 options.outputoptions = self.outputoptions 450 self.usepsyco(options) 451 self.recursiveprocess(options)
452
453 - def recursiveprocess(self, options):
454 """recurse through directories and process files""" 455 if self.isrecursive(options.input, 'input') and getattr(options, "allowrecursiveinput", True): 456 if not self.isrecursive(options.output, 'output'): 457 try: 458 self.warning("Output directory does not exist. Attempting to create") 459 os.mkdir(options.output) 460 except IOError, e: 461 self.error(optparse.OptionValueError("Output directory does not exist, attempt to create failed")) 462 if isinstance(options.input, list): 463 inputfiles = self.recurseinputfilelist(options) 464 else: 465 inputfiles = self.recurseinputfiles(options) 466 else: 467 if options.input: 468 inputfiles = [os.path.basename(options.input)] 469 options.input = os.path.dirname(options.input) 470 else: 471 inputfiles = [options.input] 472 options.recursiveoutput = self.isrecursive(options.output, 'output') and getattr(options, "allowrecursiveoutput", True) 473 options.recursivetemplate = self.usetemplates and self.isrecursive(options.template, 'template') and getattr(options, "allowrecursivetemplate", True) 474 self.initprogressbar(inputfiles, options) 475 for inputpath in inputfiles: 476 try: 477 templatepath = self.gettemplatename(options, inputpath) 478 # If we have a recursive template, but the template doesn't have this 479 # input file, let's drop it. 480 if options.recursivetemplate and templatepath is None and not self.allowmissingtemplate: 481 self.warning("No template at %s. Skipping %s." % (templatepath, inputpath)) 482 continue 483 outputformat, fileprocessor = self.getoutputoptions(options, inputpath, templatepath) 484 fullinputpath = self.getfullinputpath(options, inputpath) 485 fulltemplatepath = self.getfulltemplatepath(options, templatepath) 486 outputpath = self.getoutputname(options, inputpath, outputformat) 487 fulloutputpath = self.getfulloutputpath(options, outputpath) 488 if options.recursiveoutput and outputpath: 489 self.checkoutputsubdir(options, os.path.dirname(outputpath)) 490 except Exception, error: 491 if isinstance(error, KeyboardInterrupt): 492 raise 493 self.warning("Couldn't handle input file %s" % inputpath, options, sys.exc_info()) 494 continue 495 try: 496 success = self.processfile(fileprocessor, options, fullinputpath, fulloutputpath, fulltemplatepath) 497 except Exception, error: 498 if isinstance(error, KeyboardInterrupt): 499 raise 500 self.warning("Error processing: input %s, output %s, template %s" % (fullinputpath, fulloutputpath, fulltemplatepath), options, sys.exc_info()) 501 success = False 502 self.reportprogress(inputpath, success) 503 del self.progressbar
504
505 - def openinputfile(self, options, fullinputpath):
506 """opens the input file""" 507 if fullinputpath is None: 508 return sys.stdin 509 return open(fullinputpath, 'r')
510
511 - def openoutputfile(self, options, fulloutputpath):
512 """opens the output file""" 513 if fulloutputpath is None: 514 return sys.stdout 515 return open(fulloutputpath, 'w')
516
517 - def opentempoutputfile(self, options, fulloutputpath):
518 """opens a temporary output file""" 519 return StringIO()
520
521 - def finalizetempoutputfile(self, options, outputfile, fulloutputpath):
522 """write the temp outputfile to its final destination""" 523 outputfile.reset() 524 outputstring = outputfile.read() 525 outputfile = self.openoutputfile(options, fulloutputpath) 526 outputfile.write(outputstring) 527 outputfile.close()
528
529 - def opentemplatefile(self, options, fulltemplatepath):
530 """opens the template file (if required)""" 531 if fulltemplatepath is not None: 532 if os.path.isfile(fulltemplatepath): 533 return open(fulltemplatepath, 'r') 534 else: 535 self.warning("missing template file %s" % fulltemplatepath) 536 return None
537
538 - def processfile(self, fileprocessor, options, fullinputpath, fulloutputpath, fulltemplatepath):
539 """process an individual file""" 540 inputfile = self.openinputfile(options, fullinputpath) 541 if fulloutputpath and fulloutputpath in (fullinputpath, fulltemplatepath): 542 outputfile = self.opentempoutputfile(options, fulloutputpath) 543 tempoutput = True 544 else: 545 outputfile = self.openoutputfile(options, fulloutputpath) 546 tempoutput = False 547 templatefile = self.opentemplatefile(options, fulltemplatepath) 548 passthroughoptions = self.getpassthroughoptions(options) 549 if fileprocessor(inputfile, outputfile, templatefile, **passthroughoptions): 550 if tempoutput: 551 self.warning("writing to temporary output...") 552 self.finalizetempoutputfile(options, outputfile, fulloutputpath) 553 return True 554 else: 555 # remove the file if it is a file (could be stdout etc) 556 if fulloutputpath and os.path.isfile(fulloutputpath): 557 outputfile.close() 558 os.unlink(fulloutputpath) 559 return False
560
561 - def reportprogress(self, filename, success):
562 """shows that we are progressing...""" 563 self.progressbar.amount += 1 564 self.progressbar.show(filename)
565
566 - def mkdir(self, parent, subdir):
567 """makes a subdirectory (recursively if neccessary)""" 568 if not os.path.isdir(parent): 569 raise ValueError("cannot make child directory %r if parent %r does not exist" % (subdir, parent)) 570 currentpath = parent 571 subparts = subdir.split(os.sep) 572 for part in subparts: 573 currentpath = os.path.join(currentpath, part) 574 if not os.path.isdir(currentpath): 575 os.mkdir(currentpath)
576
577 - def checkoutputsubdir(self, options, subdir):
578 """checks to see if subdir under options.output needs to be created, creates if neccessary""" 579 fullpath = os.path.join(options.output, subdir) 580 if not os.path.isdir(fullpath): 581 self.mkdir(options.output, subdir)
582
583 - def isexcluded(self, options, inputpath):
584 """checks if this path has been excluded""" 585 basename = os.path.basename(inputpath) 586 for excludename in options.exclude: 587 if fnmatch.fnmatch(basename, excludename): 588 return True 589 return False
590
591 - def recurseinputfilelist(self, options):
592 """use a list of files, and find a common base directory for them""" 593 # find a common base directory for the files to do everything relative to 594 commondir = os.path.dirname(os.path.commonprefix(options.input)) 595 inputfiles = [] 596 for inputfile in options.input: 597 if self.isexcluded(options, inputfile): 598 continue 599 if inputfile.startswith(commondir+os.sep): 600 inputfiles.append(inputfile.replace(commondir+os.sep, "", 1)) 601 else: 602 inputfiles.append(inputfile.replace(commondir, "", 1)) 603 options.input = commondir 604 return inputfiles
605
606 - def recurseinputfiles(self, options):
607 """recurse through directories and return files to be processed...""" 608 dirstack = [''] 609 join = os.path.join 610 inputfiles = [] 611 while dirstack: 612 top = dirstack.pop(-1) 613 names = os.listdir(join(options.input, top)) 614 dirs = [] 615 for name in names: 616 inputpath = join(top, name) 617 if self.isexcluded(options, inputpath): 618 continue 619 fullinputpath = self.getfullinputpath(options, inputpath) 620 # handle directories... 621 if os.path.isdir(fullinputpath): 622 dirs.append(inputpath) 623 elif os.path.isfile(fullinputpath): 624 if not self.isvalidinputname(options, name): 625 # only handle names that match recognized input file extensions 626 continue 627 inputfiles.append(inputpath) 628 # make sure the directories are processed next time round... 629 dirs.reverse() 630 dirstack.extend(dirs) 631 return inputfiles
632
633 - def splitext(self, pathname):
634 """Splits L{pathname} into name and ext, and removes the extsep 635 636 @param pathname: A file path 637 @type pathname: string 638 @return: root, ext 639 @rtype: tuple 640 """ 641 root, ext = os.path.splitext(pathname) 642 ext = ext.replace(os.extsep, "", 1) 643 return (root, ext)
644
645 - def splitinputext(self, inputpath):
646 """splits an inputpath into name and extension""" 647 return self.splitext(inputpath)
648
649 - def splittemplateext(self, templatepath):
650 """splits a templatepath into name and extension""" 651 return self.splitext(templatepath)
652
653 - def templateexists(self, options, templatepath):
654 """returns whether the given template exists...""" 655 fulltemplatepath = self.getfulltemplatepath(options, templatepath) 656 return os.path.isfile(fulltemplatepath)
657
658 - def gettemplatename(self, options, inputname):
659 """gets an output filename based on the input filename""" 660 if not self.usetemplates: 661 return None 662 if not inputname or not options.recursivetemplate: 663 return options.template 664 inputbase, inputext = self.splitinputext(inputname) 665 if options.template: 666 for inputext1, templateext1 in options.outputoptions: 667 if inputext == inputext1: 668 if templateext1: 669 templatepath = inputbase + os.extsep + templateext1 670 if self.templateexists(options, templatepath): 671 return templatepath 672 if "*" in options.inputformats: 673 for inputext1, templateext1 in options.outputoptions: 674 if (inputext == inputext1) or (inputext1 == "*"): 675 if templateext1 == "*": 676 templatepath = inputname 677 if self.templateexists(options, templatepath): 678 return templatepath 679 elif templateext1: 680 templatepath = inputbase + os.extsep + templateext1 681 if self.templateexists(options, templatepath): 682 return templatepath 683 return None
684
685 - def getoutputname(self, options, inputname, outputformat):
686 """gets an output filename based on the input filename""" 687 if not inputname or not options.recursiveoutput: 688 return options.output 689 inputbase, inputext = self.splitinputext(inputname) 690 outputname = inputbase 691 if outputformat: 692 outputname += os.extsep + outputformat 693 return outputname
694
695 - def isvalidinputname(self, options, inputname):
696 """checks if this is a valid input filename""" 697 inputbase, inputext = self.splitinputext(inputname) 698 return (inputext in options.inputformats) or ("*" in options.inputformats)
699