# vim:sw=4:et """build_pot Build a PO template (for i18n) and update the .po files to reflect the last changes. """ from distutils.core import Command from commands import getstatus import sys, os.path import pygettext # from pygettext.main(): class Options: # constants GNU = 1 SOLARIS = 2 # defaults extractall = 0 # FIXME: currently this option has no effect at all. keywords = [] writelocations = 1 locationstyle = GNU verbose = 0 width = 78 excludefilename = '' docstrings = 0 nodocstrings = {} toexclude = [] class build_pot(Command): description="Generate a .po template file (.pot) from python source files" user_options = [('msgmerge=', None, 'location of the msgmerge program'), ('extract-all', 'a', ''), ('default-domain=', 'd', ''), ('escape', 'E', ''), ('docstrings', 'D', ''), ('keyword=', 'k', 'Comma separated list of keywords'), ('no-default-keywords', 'K', ''), ('add-location', 'n', ''), ('no-location', None, ''), ('style=', 'S', 'POT file style "gnu" or "solaris"'), ('output=', 'o', ''), ('output-dir=', 'p', ''), ('width=', 'w', ''), ('exclude-file=', 'x', ''), ('all-linguas=', None, ''), #('no-docstrings=', 'X', ''), ] boolean_options = [ 'extract-all', 'escape', 'docstrings', 'no-default-keywords', 'add-location', 'no-location', 'no-docstrings' ] # constants GNU = 1 SOLARIS = 2 def initialize_options(self): self.podir = 'po' self.msgmerge = 'msgmerge' self.options = Options() # defaults for variable parsing: self.escape = 0 self.width = 78 self.extract_all = 0 # doesn't do anything yet self.default_domain = None self.keyword = None self.no_default_keywords = 0 self.no_location = 0 self.style = None self.output = None self.output_dir = None self.docstrings = 0 self.exclude_file = None #self.no_docstrings = None self.all_linguas = [] def finalize_options(self): options = self.options self.name = self.distribution.get_name() # Build default options for the TokenEater if self.default_domain: self.output = self.default_domain + '.pot' if self.keyword: options.keywords.extend(self.keyword.split(',')) if self.no_default_keywords: options.keywords = [ ] if self.no_location: options.writelocations = 0 if self.style: if self.style == 'gnu': options.locationstyle = self.GNU elif self.style == 'solaris': options.locationstyle = self.SOLARIS else: raise SystemExit, 'Invalid value for --style: %s' % self.style if not self.output: self.output = self.distribution.get_name() + '.pot' if not self.output_dir: self.output_dir = self.podir if self.docstrings: options.docstrings = 1 options.width = int(self.width) if self.exclude_file: try: fp = open(self.exclude_file) options.toexclude = fp.readlines() fp.close() except IOError: raise SystemExit, "Can't read --exclude-file: %s" % self.exclude_file # skip: self.no_docstrings if self.all_linguas: self.all_linguas = self.all_linguas.split(',') # calculate escapes pygettext.make_escapes(self.escape) # calculate all keywords options.keywords.append('_') if self.output_dir: self.output = os.path.join(self.output_dir, self.output) self.packages = self.distribution.packages #self.all_linguas = self.distribution.get_all_linguas() #self.all_linguas = self.distribution.options['po']['all_linguas'] def run(self): self.create_pot_file() self.merge_files() def create_pot_file(self): """ Create a new .pot file. This is basically a rework of the main function of pygettext. """ import glob import tokenize source_files = [] for p in self.packages: pathlist = p.split('.') path = apply(os.path.join, pathlist) source_files.extend(glob.glob(os.path.join(path, '*.py'))) # slurp through all the files eater = pygettext.TokenEater(self.options) for filename in source_files: if self.verbose: print 'Working on %s' % filename fp = open(filename) try: eater.set_filename(filename) try: tokenize.tokenize(fp.readline, eater) except tokenize.TokenError, e: print '%s: %s, line %d, column %d' % ( e[0], filename, e[1][0], e[1][1]) finally: fp.close() # write the output if self.output == '-': fp = sys.stdout else: fp = open(self.output, 'w') try: eater.write(fp) finally: if fp is not sys.stdout: fp.close() def merge_files(self): if not self.all_linguas: return for lingua in self.all_linguas: d = { 'msgmerge': self.msgmerge, 'po': os.path.join(self.output_dir, lingua + '.po'), 'pot': self.output } if self.verbose: sys.stdout.write('Merging %(pot)s and %(po)s ' % d) sys.stdout.flush() res = os.system('%(msgmerge)s %(po)s %(pot)s -o %(po)s' % d) if res: SystemExit, 'error while running msgmerge.'