def run(self): mappings = self._get_mappings() outfile = open(self.output_file, "wb") try: catalog = Catalog( project=self.distribution.get_name(), version=self.distribution.get_version(), msgid_bugs_address=self.msgid_bugs_address, copyright_holder=self.copyright_holder, charset=self.charset, ) for dirname, (method_map, options_map) in mappings.items(): def callback(filename, method, options): if method == "ignore": return filepath = os.path.normpath(os.path.join(dirname, filename)) optstr = "" if options: optstr = " (%s)" % ", ".join(['%s="%s"' % (k, v) for k, v in options.items()]) log.info("extracting messages from %s%s", filepath, optstr) extracted = extract_from_dir( dirname, method_map, options_map, keywords=self._keywords, comment_tags=self._add_comments, callback=callback, strip_comment_tags=self.strip_comments, ) for filename, lineno, message, comments, context in extracted: filepath = os.path.normpath(os.path.join(dirname, filename)) catalog.add(message, None, [(filepath, lineno)], auto_comments=comments, context=context) log.info("writing PO template file to %s" % self.output_file) write_po( outfile, catalog, width=self.width, no_location=self.no_location, omit_header=self.omit_header, sort_output=self.sort_output, sort_by_file=self.sort_by_file, ) finally: outfile.close()
def extract(self, argv): """Subcommand for extracting messages from source files and generating a POT file. :param argv: the command arguments """ parser = OptionParser(usage=self.usage % ("extract", "dir1 <dir2> ..."), description=self.commands["extract"]) parser.add_option("--charset", dest="charset", help="charset to use in the output (default " '"%default")') parser.add_option( "-k", "--keyword", dest="keywords", action="append", help="keywords to look for in addition to the " "defaults. You can specify multiple -k flags on " "the command line.", ) parser.add_option( "--no-default-keywords", dest="no_default_keywords", action="store_true", help="do not include the default keywords", ) parser.add_option("--mapping", "-F", dest="mapping_file", help="path to the extraction mapping file") parser.add_option( "--no-location", dest="no_location", action="store_true", help="do not include location comments with filename " "and line number", ) parser.add_option( "--omit-header", dest="omit_header", action="store_true", help='do not include msgid "" entry in header' ) parser.add_option("-o", "--output", dest="output", help="path to the output POT file") parser.add_option("-w", "--width", dest="width", type="int", help="set output line width (default 76)") parser.add_option( "--no-wrap", dest="no_wrap", action="store_true", help="do not break long message lines, longer than " "the output line width, into several lines", ) parser.add_option( "--sort-output", dest="sort_output", action="store_true", help="generate sorted output (default False)" ) parser.add_option( "--sort-by-file", dest="sort_by_file", action="store_true", help="sort output by file location (default False)", ) parser.add_option( "--msgid-bugs-address", dest="msgid_bugs_address", metavar="EMAIL@ADDRESS", help="set report address for msgid", ) parser.add_option("--copyright-holder", dest="copyright_holder", help="set copyright holder in output") parser.add_option("--project", dest="project", help="set project name in output") parser.add_option("--version", dest="version", help="set project version in output") parser.add_option( "--add-comments", "-c", dest="comment_tags", metavar="TAG", action="append", help="place comment block with TAG (or those " "preceding keyword lines) in output file. One " "TAG per argument call", ) parser.add_option( "--strip-comment-tags", "-s", dest="strip_comment_tags", action="store_true", help="Strip the comment tags from the comments.", ) parser.set_defaults( charset="utf-8", keywords=[], no_default_keywords=False, no_location=False, omit_header=False, width=None, no_wrap=False, sort_output=False, sort_by_file=False, comment_tags=[], strip_comment_tags=False, ) options, args = parser.parse_args(argv) if not args: parser.error("incorrect number of arguments") keywords = DEFAULT_KEYWORDS.copy() if options.no_default_keywords: if not options.keywords: parser.error("you must specify new keywords if you disable the " "default ones") keywords = {} if options.keywords: keywords.update(parse_keywords(options.keywords)) if options.mapping_file: fileobj = open(options.mapping_file, "U") try: method_map, options_map = parse_mapping(fileobj) finally: fileobj.close() else: method_map = DEFAULT_MAPPING options_map = {} if options.width and options.no_wrap: parser.error("'--no-wrap' and '--width' are mutually exclusive.") elif not options.width and not options.no_wrap: options.width = 76 if options.sort_output and options.sort_by_file: parser.error("'--sort-output' and '--sort-by-file' are mutually " "exclusive") catalog = Catalog( project=options.project, version=options.version, msgid_bugs_address=options.msgid_bugs_address, copyright_holder=options.copyright_holder, charset=options.charset, ) for dirname in args: if not os.path.isdir(dirname): parser.error("%r is not a directory" % dirname) def callback(filename, method, options): if method == "ignore": return filepath = os.path.normpath(os.path.join(dirname, filename)) optstr = "" if options: optstr = " (%s)" % ", ".join(['%s="%s"' % (k, v) for k, v in options.items()]) self.log.info("extracting messages from %s%s", filepath, optstr) extracted = extract_from_dir( dirname, method_map, options_map, keywords, options.comment_tags, callback=callback, strip_comment_tags=options.strip_comment_tags, ) for filename, lineno, message, comments, context in extracted: filepath = os.path.normpath(os.path.join(dirname, filename)) catalog.add(message, None, [(filepath, lineno)], auto_comments=comments, context=context) catalog_charset = catalog.charset if options.output not in (None, "-"): self.log.info("writing PO template file to %s" % options.output) outfile = open(options.output, "wb") close_output = True else: outfile = sys.stdout # This is a bit of a hack on Python 3. stdout is a text stream so # we need to find the underlying file when we write the PO. In # later versions of Babel we want the write_po function to accept # text or binary streams and automatically adjust the encoding. if not PY2 and hasattr(outfile, "buffer"): catalog.charset = outfile.encoding outfile = outfile.buffer.raw close_output = False try: write_po( outfile, catalog, width=options.width, no_location=options.no_location, omit_header=options.omit_header, sort_output=options.sort_output, sort_by_file=options.sort_by_file, ) finally: if close_output: outfile.close() catalog.charset = catalog_charset