# This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. 'Commands exposed to commandlines' import logging from optparse import OptionParser, make_option from compare_locales.paths import EnumerateApp from compare_locales.compare import compareApp, compareDirs from compare_locales.webapps import compare_web_app class BaseCommand(object): """Base class for compare-locales commands. This handles command line parsing, and general sugar for setuptools entry_points. """ options = [ make_option('-v', '--verbose', action='count', dest='v', default=0, help='Make more noise'), make_option('-q', '--quiet', action='count', dest='q', default=0, help='Make less noise'), make_option('-m', '--merge', help='''Use this directory to stage merged files, use {ab_CD} to specify a different directory for each locale'''), ] data_option = make_option('--data', choices=['text', 'exhibit', 'json'], default='text', help='''Choose data and format (one of text, exhibit, json); text: (default) Show which files miss which strings, together with warnings and errors. Also prints a summary; json: Serialize the internal tree, useful for tools. Also always succeeds; exhibit: Serialize the summary data in a json useful for Exhibit ''') def __init__(self): self.parser = None def get_parser(self): """Get an OptionParser, with class docstring as usage, and self.options. """ parser = OptionParser() parser.set_usage(self.__doc__) for option in self.options: parser.add_option(option) return parser @classmethod def call(cls): """Entry_point for setuptools. The actual command handling is done in the handle() method of the subclasses. """ cmd = cls() cmd.handle_() def handle_(self): """The instance part of the classmethod call.""" self.parser = self.get_parser() (options, args) = self.parser.parse_args() # log as verbose or quiet as we want, warn by default logging.basicConfig() logging.getLogger().setLevel(logging.WARNING - (options.v - options.q)*10) observer = self.handle(args, options) print observer.serialize(type=options.data).encode('utf-8', 'replace') def handle(self, args, options): """Subclasses need to implement this method for the actual command handling. """ raise NotImplementedError class CompareLocales(BaseCommand): """usage: %prog [options] l10n.ini l10n_base_dir [locale ...] Check the localization status of a gecko application. The first argument is a path to the l10n.ini file for the application, followed by the base directory of the localization repositories. Then you pass in the list of locale codes you want to compare. If there are not locales given, the list of locales will be taken from the all-locales file of the application\'s l10n.ini.""" options = BaseCommand.options + [ make_option('--clobber-merge', action="store_true", default=False, dest='clobber', help="""WARNING: DATALOSS. Use this option with care. If specified, the merge directory will be clobbered for each module. That means, the subdirectory will be completely removed, any files that were there are lost. Be careful to specify the right merge directory when using this option."""), make_option('-r', '--reference', default='en-US', dest='reference', help='Explicitly set the reference ' 'localization. [default: en-US]'), BaseCommand.data_option ] def handle(self, args, options): if len(args) < 2: self.parser.error('Need to pass in list of languages') inipath, l10nbase = args[:2] locales = args[2:] app = EnumerateApp(inipath, l10nbase, locales) app.reference = options.reference try: observer = compareApp(app, merge_stage=options.merge, clobber=options.clobber) except (OSError, IOError), exc: print "FAIL: " + str(exc) self.parser.exit(2) return observer class CompareDirs(BaseCommand): """usage: %prog [options] reference localization Check the localization status of a directory tree. The first argument is a path to the reference data,the second is the localization to be tested.""" options = BaseCommand.options + [ BaseCommand.data_option ] def handle(self, args, options): if len(args) != 2: self.parser.error('Reference and localizatino required') reference, locale = args observer = compareDirs(reference, locale, merge_stage=options.merge) return observer class CompareWebApp(BaseCommand): """usage: %prog [options] webapp [locale locale] Check the localization status of a gaia-style web app. The first argument is the directory of the web app. Following arguments explicitly state the locales to test. If none are given, test all locales in manifest.webapp or files.""" options = BaseCommand.options[:-1] + [ BaseCommand.data_option] def handle(self, args, options): if len(args) < 1: self.parser.error('Webapp directory required') basedir = args[0] locales = args[1:] observer = compare_web_app(basedir, locales) return observer