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