def make_match_group (names, negatable=False, orlinked=False): names_negs = [(x, False) for x in names] if negatable: names_negs.extend([(x, True) for x in names]) matchers = [] for name, neg in names_negs: nname = name if neg: nname = "n" + name values = getattr(params, nname) if values is None: # parameter not given continue if not isinstance(values, list): values = [values] for value in values: try: if name == "fexpr": m = make_msg_matcher(value, params) else: m = make_matcher(name, value, [], params, neg) except ExprError, e: raise SieveError(str_to_unicode(str(e))) matchers.append(m)
def _main(): locale.setlocale(locale.LC_ALL, "") usage = _("@info command usage", "%(cmd)s [OPTIONS] VCS [POPATHS...]", cmd="%prog") desc = _("@info command description", "Obtains a list of proper words from the message text ") ver = _("@info command version", u"%(cmd)s (Pology) %(version)s\n" u"Copyright © 2011 " u"Javier Viñal <%(email)s>", cmd="%prog", version=version(), email="*****@*****.**") opars = ColorOptionParser(usage=usage, description=desc, version=ver) add_cmdopt_filesfrom(opars) (options, free_args) = opars.parse_args(str_to_unicode(sys.argv[1:])) # Collect PO files in given paths. popaths = collect_paths_cmdline(rawpaths=free_args, filesfrom=options.files_from, elsecwd=True, respathf=collect_catalogs, abort=True) dict_en = enchant.Dict("en") dict_local = enchant.Dict("es") for path in popaths: extract_proper_words(path, dict_en, dict_local) dict_en.close() for word in sorted(dict_local.session_dict()): print word dict_local.session_dict(clear=True) dict_local.close()
def main (): locale.setlocale(locale.LC_ALL, "") # Get defaults for command line options from global config. cfgsec = pology_config.section("poediff") def_do_merge = cfgsec.boolean("merge", True) # Setup options and parse the command line. usage = _("@info command usage", "%(cmd)s [OPTIONS] FILE1 FILE2\n" "%(cmd)s [OPTIONS] DIR1 DIR2\n" "%(cmd)s -c VCS [OPTIONS] [PATHS...]", cmd="%prog") desc = _("@info command description", "Create embedded diffs of PO files.") ver = _("@info command version", u"%(cmd)s (Pology) %(version)s\n" u"Copyright © 2009, 2010 " u"Chusslove Illich (Часлав Илић) <%(email)s>", cmd="%prog", version=version(), email="*****@*****.**") showvcs = list(set(available_vcs()).difference(["none"])) showvcs.sort() opars = ColorOptionParser(usage=usage, description=desc, version=ver) opars.add_option( "-b", "--skip-obsolete", action="store_true", dest="skip_obsolete", default=False, help=_("@info command line option description", "Do not diff obsolete messages.")) opars.add_option( "-c", "--vcs", metavar=_("@info command line value placeholder", "VCS"), dest="version_control", help=_("@info command line option description", "Paths are under version control by given VCS; " "can be one of: %(vcslist)s.", vcslist=format_item_list(showvcs))) opars.add_option( "--list-options", action="store_true", dest="list_options", default=False, help=_("@info command line option description", "List the names of available options.")) opars.add_option( "--list-vcs", action="store_true", dest="list_vcs", default=False, help=_("@info command line option description", "List the keywords of known version control systems.")) opars.add_option( "-n", "--no-merge", action="store_false", dest="do_merge", default=def_do_merge, help=_("@info command line option description", "Do not try to indirectly pair messages by merging catalogs.")) opars.add_option( "-o", "--output", metavar=_("@info command line value placeholder", "POFILE"), dest="output", help=_("@info command line option description", "Output diff catalog to a file instead of stdout.")) opars.add_option( "-p", "--paired-only", action="store_true", dest="paired_only", default=False, help=_("@info command line option description", "When two directories are diffed, ignore catalogs which " "are not present in both directories.")) opars.add_option( "-q", "--quiet", action="store_true", dest="quiet", default=False, help=_("@info command line option description", "Do not display any progress info.")) opars.add_option( "-Q", "--quick", action="store_true", dest="quick", default=False, help=_("@info command line option description", "Equivalent to %(opt)s.", opt="-bns")) opars.add_option( "-r", "--revision", metavar=_("@info command line value placeholder", "REV1[:REV2]"), dest="revision", help=_("@info command line option description", "Revision from which to diff to current working copy, " "or from first to second revision (if VCS is given).")) opars.add_option( "-s", "--strip-headers", action="store_true", dest="strip_headers", default=False, help=_("@info command line option description", "Do not diff headers and do not write out the top header " "(resulting output cannot be used as patch).")) opars.add_option( "-U", "--update-effort", action="store_true", dest="update_effort", default=False, help=_("@info command line option description", "Instead of outputting the diff, calculate and output " "an estimate of the effort that was needed to update " "the translation from old to new paths. " "Ignores %(opt1)s and %(opt1)s options.", opt1="-b", opt2="-n")) add_cmdopt_colors(opars) (op, free_args) = opars.parse_args(str_to_unicode(sys.argv[1:])) if op.list_options: report(list_options(opars)) sys.exit(0) if op.list_vcs: report("\n".join(showvcs)) sys.exit(0) # Could use some speedup. try: import psyco psyco.full() except ImportError: pass set_coloring_globals(ctype=op.coloring_type, outdep=(not op.raw_colors)) if op.quick: op.do_merge = False op.skip_obsolete = True op.strip_headers = True # Create VCS. vcs = None if op.version_control: if op.version_control not in available_vcs(flat=True): error_wcl(_("@info", "Unknown VCS '%(vcs)s' selected.", vcs=op.version_control)) vcs = make_vcs(op.version_control) # Sanity checks on paths. paths = free_args if not vcs: if len(paths) != 2: error_wcl(_("@info", "Exactly two paths are needed for diffing.")) for path in paths: if not os.path.exists(path): error_wcl("path does not exist: %s" % path) p1, p2 = paths if (not ( (os.path.isfile(p1) and (os.path.isfile(p2))) or (os.path.isdir(p1) and (os.path.isdir(p2)))) ): error_wcl(_("@info", "Both paths must be either files or directories.")) else: # Default to current working dir if no paths given. paths = paths or ["."] for path in paths: if not os.path.exists(path): error_wcl(_("@info", "Path '%(path)s' does not exist.", path=path)) if not vcs.is_versioned(path): error_wcl(_("@info", "Path '%(path)s' is not under version control.", path=path)) # Collect and pair PO files in given paths. # Each pair specification is in the form of # ((path1, path2), (vpath1, vpath2)) # where path* are the real paths, and vpath* the visual paths to be # presented in diff output. if not vcs: fpairs = collect_file_pairs(paths[0], paths[1], op.paired_only) pspecs = [(x, x) for x in fpairs] else: lst = op.revision and op.revision.split(":", 1) or [] if len(lst) > 2: error_wcl(_("@info", "Too many revisions given: %(revlist)s.", revspec=format_item_list(lst))) elif len(lst) == 2: revs = lst # diff between revisions elif len(lst) == 1: revs = [lst[0], None] # diff from revision to working copy else: revs = ["", None] # diff from head to working copy # Replace original paths with modified/added catalogs. paths_nc = [] for path in paths: for path in vcs.to_commit(path): if path.endswith(".po") or path.endswith(".pot"): paths_nc.append(path) paths = paths_nc paths.sort() pspecs = collect_pspecs_from_vcs(vcs, paths, revs, op.paired_only) if not op.update_effort: ecat, ndiffed = diff_pairs(pspecs, op.do_merge, colorize=(not op.output), shdr=op.strip_headers, noobs=op.skip_obsolete, quiet=op.quiet) if ndiffed > 0: hmsgctxt = ecat.header.get_field_value(EDST.hmsgctxt_field) lines = [] msgs = list(ecat) if not op.strip_headers: msgs.insert(0, ecat.header.to_msg()) for msg in msgs: if op.strip_headers and msg.msgctxt == hmsgctxt: sepl = [] sepl += [msg.manual_comment[0]] sepl += msg.msgid.split("\n")[:2] lines.extend(["# %s\n" % x for x in sepl]) lines.append("\n") else: lines.extend(msg.to_lines(force=True, wrapf=ecat.wrapf())) diffstr = cjoin(lines)[:-1] # remove last newline if op.output: file = open(op.output, "w") file.write(diffstr.encode(ecat.encoding())) file.close() else: report(diffstr) else: updeff = pairs_update_effort(pspecs, quiet=op.quiet) ls = [] for kw, desc, val, fmtval in updeff: ls.append(_("@info", "%(quantity)s: %(value)s", quantity=desc, value=fmtval)) report("\n".join(ls)) # Clean up. cleanup_tmppaths()
def _main(): locale.setlocale(locale.LC_ALL, "") usage = _("@info command usage", "%(cmd)s [OPTIONS] VCS [POPATHS...]", cmd="%prog") desc = _( "@info command description", "Compose hybridized Ijekavian-Ekavian translation out of " "translation modified from Ekavian to Ijekavian or vice-versa.") ver = _("@info command version", u"%(cmd)s (Pology) %(version)s\n" u"Copyright © 2009, 2010 " u"Chusslove Illich (Часлав Илић) <%(email)s>", cmd="%prog", version=version(), email="*****@*****.**") opars = ColorOptionParser(usage=usage, description=desc, version=ver) opars.add_option( "-a", "--accept-changes", action="store_true", dest="accept_changes", default=False, help=_( "@info command line option description", "Accept messages which have some changes between base " "and reconstructed base text.")) opars.add_option("-r", "--base-revision", metavar=_("@info command line value placeholder", "REVISION"), action="store", dest="base_revision", default=None, help=_( "@info command line option description", "Use the given revision as base for hybridization, " "instead of local latest revision.")) add_cmdopt_filesfrom(opars) (options, free_args) = opars.parse_args(str_to_unicode(sys.argv[1:])) try: import psyco psyco.full() except ImportError: pass # Create VCS. if len(free_args) < 1: showvcs = list(set(available_vcs()).difference(["none"])) showvcs.sort() error( _("@info", "Version control system not given " "(can be one of: %(vcslist)s).", vcslist=format_item_list(showvcs))) vcskey = free_args.pop(0) if vcskey not in available_vcs(flat=True): error( _("@info", "Unknown version control system '%(vcs)s'.", vcs=vcskey)) vcs = make_vcs(vcskey) # Collect PO files in given paths. popaths = collect_paths_cmdline(rawpaths=free_args, filesfrom=options.files_from, elsecwd=True, respathf=collect_catalogs, abort=True) # Catalogs must be under version control. for path in popaths: if not vcs.is_versioned(path): error( _("@info", "Catalog '%(file)s' is not under version control.", file=path)) # Go by modified PO file and hybridize it. for path in popaths: # Extract local head counterpart. tmpf = NamedTemporaryFile(prefix="pohybdl-export-", suffix=".po") if not vcs.export(path, options.base_revision, tmpf.name): error( _("@info", "Version control system cannot export file '%(file)s'.", file=path)) # Hybridize by comparing local head and modified file. hybdl(path, tmpf.name, options.accept_changes)
@type abort: bool @return: matcher function @rtype: (msgf, msg, cat, hl=[])->bool """ mopts = _prep_attrobj(mopts, dict(case=False, )) try: expr, p = _build_expr_r(exprstr, 0, len(exprstr), mopts) if p < len(exprstr): raise ExprError(exprstr, _("@item:intext", "premature end of expression")) except ExprError, e: if abort: error(str_to_unicode(str(e))) else: raise return expr def make_msg_fmatcher(exprstr, mopts=None, accels=None, filters=[], abort=False): """ Build expression matcher for messages, with filtering. Like L{make_msg_matcher}, except that matchers built by this function do their own filtering, and so omit the first argument.
def _main (): locale.setlocale(locale.LC_ALL, "") usage= _("@info command usage", "%(cmd)s [OPTIONS] [DKEY|SRCPATH|:SRCNAME]...", cmd="%prog") desc = _("@info command description", "Check validity and expand derivations from internal trapnakron.") ver = _("@info command version", u"%(cmd)s (Pology) %(version)s\n" u"Copyright © 2009, 2010 " u"Chusslove Illich (Часлав Илић) <%(email)s>", cmd="%prog", version=version(), email="*****@*****.**") opars = ColorOptionParser(usage=usage, description=desc, version=ver) opars.add_option( "-e", "--expansion-sample", action="store_true", dest="demoexp", default=False, help=_("@info command line option description", "Show a sample of expanded properties for " "each valid derivation.")) opars.add_option( "-k", "--show-keys", action="store_true", dest="expwkeys", default=False, help=_("@info command line option description", "When expanding, also show all derivation keys by derivation.")) opars.add_option( "-m", "--modified", action="store_true", dest="modified", default=False, help=_("@info command line option description", "Validate or expand only modified derivations.")) opars.add_option( "-r", "--regex", action="store_true", dest="regex", default=False, help=_("@info command line option description", "Source names and derivation keys given in command line " "are regular expressions.")) opars.add_option( "-s", "--statistics", action="store_true", dest="statistics", default=False, help=_("@info command line option description", "Show statistics.")) (options, free_args) = opars.parse_args(str_to_unicode(sys.argv[1:])) try: import psyco psyco.full() except ImportError: pass onlysrcs = set() onlykeys = set() sksep = ":" for arg in free_args: if os.path.isfile(arg): test = os.path.splitext(arg.split(os.path.sep)[-1])[0] onlysrcs.add(test) elif arg.startswith(sksep): test = arg[len(sksep):] if options.regex: test = _Wre(test) onlysrcs.add(test) else: if options.regex: arg = _Wre(arg) else: arg = identify(arg) onlykeys.add(arg) onlysrcs = onlysrcs or None onlykeys = onlykeys or None # Create and validate the trapnakron. tp = trapnakron_ui() if options.modified: onlysrcs, onlykeys = _collect_mod_dkeys(tp, onlysrcs, onlykeys) validate(tp, onlysrcs, onlykeys, options.demoexp, options.expwkeys) if options.statistics: _statistics(tp, onlysrcs, onlykeys)
def validate (tp, onlysrcs=None, onlykeys=None, demoexp=False, expwkeys=False): needed_pkeys = set() nom_pkeys = ( [u"н"], [u"нм", u"нж", u"нс", u"ну"], ) needed_pkeys.update(sum(nom_pkeys, [])) gender_pkey = u"_род" needed_pkeys.add(gender_pkey) known_genders = set((u"м", u"ж", u"с", u"у")) known_genders.update(map(ctol, known_genders)) known_alts = [ ("_s", u"сист"), ("_a", u"алт"), ("_a2", u"алт2"), ("_a3", u"алт3"), ] base_envs = [u"", u"л", u"иј", u"ијл"] all_envs = set(base_envs) for aenv in [x[1] for x in known_alts]: all_envs.update(x + aenv for x in base_envs) if demoexp: demoexp_pkeys = [u"н", u"г", u"д", u"а", u"в", u"и", u"нк", u"гк", u"дк", u"ак", u"вк", u"нм", u"нмп"] needed_pkeys.update(demoexp_pkeys) dkeys_by_rtkey = {} # Sort keys such that derivations are checked by file and position. dkeys = tp.dkeys(single=onlykeys is None) def sortkey (x): path, lno, cno = tp.source_pos(x) return path.count(os.path.sep), path, lno, cno dkeys = sorted(dkeys, key=sortkey) nproblems = 0 unmatched_srcs = set(onlysrcs) if onlysrcs is not None else None unmatched_keys = set(onlykeys) if onlykeys is not None else None reported_fmtexps = set() for dkey in dkeys: srcname = tp.source_name(dkey) path, lno, cno = tp.source_pos(dkey) cnproblems = 0 if ( ( onlysrcs is not None and not _match_text(srcname, onlysrcs, unmatched_srcs)) or ( onlykeys is not None and not _match_text(dkey, onlykeys, unmatched_keys)) ): continue try: aprops = [] seenesuffs = set() cenvs = tp.envs(dkey) for cenv in cenvs: if cenv != "": envmatched = False for ksuff, esuff in known_alts: if cenv in all_envs and cenv.endswith(esuff): envmatched = True break else: envmatched = True ksuff, esuff = "", "" if envmatched and esuff not in seenesuffs: dkeym = dkey + ksuff props = dict([(x, tp.get2(dkeym, norm_pkey(x))) for x in needed_pkeys]) aprops.append((esuff, props)) seenesuffs.add(esuff) elif cenv not in all_envs: warning(_("@info", "Derivation at %(file)s:%(line)d:%(col)d " "defines unknown environment '%(env)s'.", file=path, line=lno, col=cno, env=cenv)) cnproblems += 1 except Exception, e: warning(str_to_unicode(str(e))) cnproblems += 1 continue for esuff, props in aprops: # Assure all nominative forms are unique. for pkeys in nom_pkeys: # select first nominative set by priority pvals = [props.get(x) for x in pkeys] noms = filter(lambda x: x is not None, pvals) if noms: break if noms: rtkeys = map(norm_rtkey, noms) for rtkey in rtkeys: odkey = dkeys_by_rtkey.get(rtkey) if odkey is not None and tp.props(dkey) != tp.props(odkey): opath, olno, ocno = tp.source_pos(odkey) warning(_("@info", "Derivation at %(file1)s:%(line1)d:%(col1)d " "has normalized nominative equal to " "derivation at %(file2)s:%(line2)d:%(col2)d; " "consider adding a disambiguation marker " "(%(dchar)s).", file1=path, line1=lno, col1=cno, file2=opath, line2=olno, col2=ocno, dchar=_disamb_marker)) cnproblems += 1 for rtkey in rtkeys: # must be in new loop dkeys_by_rtkey[rtkey] = dkey # Assure presence of gender on noun derivations. if props.get(nom_pkeys[0][0]) is not None: gender = props.get(gender_pkey) if gender is None: warning(_("@info", "Derivation at %(file)s:%(line)d:%(col)d " "does not define gender.", file=path, line=lno, col=cno)) cnproblems += 1 else: for gender in hictoall(gender): if gender not in known_genders: warning(_("@info", "Derivation at %(file)s:%(line)d:%(col)d " "defines unknown gender '%(gen)s'.", file=path, line=lno, col=cno, gen=gender)) cnproblems += 1 # Show selection of expanded properties if requested. if demoexp and not cnproblems: demoprops = [(x, props.get(x)) for x in demoexp_pkeys] demoprops = filter(lambda x: x[1] is not None, demoprops) fmtprops = ["%s=%s" % (x[0], _escape_pval(x[1])) for x in demoprops] fmtsyns = ["%s" % _escape_syn(x) for x in tp.syns(dkey)] fmtexp = ", ".join(fmtsyns) + ": " + ", ".join(fmtprops) if expwkeys: fmtdkeys = ", ".join(sorted(tp.altdkeys(dkey))) fmtexp = "# " + fmtdkeys + "\n" + fmtexp if fmtexp not in reported_fmtexps: if not esuff: report(fmtexp) reported_fmtexps.add(fmtexp) else: afmtexp = " @" + esuff + ": " + ", ".join(fmtprops) report(afmtexp) nproblems += cnproblems tp.empty_pcache()
def main(): locale.setlocale(locale.LC_ALL, "") # Get defaults for command line options from global config. cfgsec = pology_config.section("posieve") def_do_skip = cfgsec.boolean("skip-on-error", True) def_msgfmt_check = cfgsec.boolean("msgfmt-check", False) def_skip_obsolete = cfgsec.boolean("skip-obsolete", False) # Setup options and parse the command line. usage = _("@info command usage", "%(cmd)s [OPTIONS] SIEVE [POPATHS...]", cmd="%prog") desc = _( "@info command description", "Apply sieves to PO paths, which may be either single PO files or " "directories to search recursively for PO files. " "Some of the sieves only examine PO files, while others " "modify them as well. " "The first non-option argument is the sieve name; " "a list of several comma-separated sieves can be given too.") ver = _("@info command version", u"%(cmd)s (Pology) %(version)s\n" u"Copyright © 2007, 2008, 2009, 2010 " u"Chusslove Illich (Часлав Илић) <%(email)s>", cmd="%prog", version=version(), email="*****@*****.**") opars = ColorOptionParser(usage=usage, description=desc, version=ver) opars.add_option( "-a", "--announce-entry", action="store_true", dest="announce_entry", default=False, help=_("@info command line option description", "Announce that header or message is just about to be sieved.")) opars.add_option("-b", "--skip-obsolete", action="store_true", dest="skip_obsolete", default=def_skip_obsolete, help=_("@info command line option description", "Do not sieve obsolete messages.")) opars.add_option( "-c", "--msgfmt-check", action="store_true", dest="msgfmt_check", default=def_msgfmt_check, help=_("@info command line option description", "Check catalogs by %(cmd)s and skip those which do not pass.", cmd="msgfmt -c")) opars.add_option("-u", "--single-entry", metavar=_("@info command line value placeholder", "ENTRY_NUMBER"), action="store", dest="single_entry", default=0, help=_("@info command line option description", "Only perform the check on this ENTRY_NUMBER.")) opars.add_option( "--force-sync", action="store_true", dest="force_sync", default=False, help=_("@info command line option description", "Force rewriting of all messages, whether modified or not.")) opars.add_option("-H", "--help-sieves", action="store_true", dest="help_sieves", default=False, help=_("@info command line option description", "Show help for applied sieves.")) opars.add_option("--issued-params", action="store_true", dest="issued_params", default=False, help=_( "@info command line option description", "Show all issued sieve parameters " "(from command line and user configuration).")) opars.add_option("-l", "--list-sieves", action="store_true", dest="list_sieves", default=False, help=_("@info command line option description", "List available internal sieves.")) opars.add_option("--list-options", action="store_true", dest="list_options", default=False, help=_("@info command line option description", "List the names of available options.")) opars.add_option("--list-sieve-names", action="store_true", dest="list_sieve_names", default=False, help=_("@info command line option description", "List the names of available internal sieves.")) opars.add_option("--list-sieve-params", action="store_true", dest="list_sieve_params", default=False, help=_("@info command line option description", "List the parameters known to issued sieves.")) opars.add_option("-m", "--output-modified", metavar=_("@info command line value placeholder", "FILE"), action="store", dest="output_modified", default=None, help=_("@info command line option description", "Output names of modified files into FILE.")) opars.add_option("--no-skip", action="store_false", dest="do_skip", default=def_do_skip, help=_( "@info command line option description", "Do not try to skip catalogs which signal errors.")) opars.add_option("--no-sync", action="store_false", dest="do_sync", default=True, help=_("@info command line option description", "Do not write any modifications to catalogs.")) opars.add_option("-q", "--quiet", action="store_true", dest="quiet", default=False, help=_( "@info command line option description", "Do not display any progress info " "(does not influence sieves themselves).")) opars.add_option("-s", metavar=_("@info command line value placeholder", "NAME[:VALUE]"), action="append", dest="sieve_params", default=[], help=_("@info command line option description", "Pass a parameter to sieves.")) opars.add_option( "-S", metavar=_("@info command line value placeholder", "NAME[:VALUE]"), action="append", dest="sieve_no_params", default=[], help=_( "@info command line option description", "Remove a parameter to sieves " "(e.g. if it was issued through user configuration).")) opars.add_option("-v", "--verbose", action="store_true", dest="verbose", default=False, help=_("@info command line option description", "Output more detailed progress information.")) add_cmdopt_filesfrom(opars) add_cmdopt_incexc(opars) add_cmdopt_colors(opars) (op, free_args) = opars.parse_args(str_to_unicode(sys.argv[1:])) if op.list_options: report(list_options(opars)) sys.exit(0) if len(free_args) < 1 and not (op.list_sieves or op.list_sieve_names): error(_("@info", "No sieve to apply given.")) op.raw_sieves = [] op.raw_paths = [] if len(free_args) > 2 and op.single_entry != 0: error( _("@info", "With single entry mode, you can only give one input file.")) if len(free_args) >= 1: op.raw_sieves = free_args[0] op.raw_paths = free_args[1:] # Could use some speedup. try: import psyco psyco.full() except ImportError: pass set_coloring_globals(ctype=op.coloring_type, outdep=(not op.raw_colors)) # Dummy-set all internal sieves as requested if sieve listing required. sieves_requested = [] if op.list_sieves or op.list_sieve_names: # Global sieves. modpaths = glob.glob(os.path.join(datadir(), "sieve", "[a-z]*.py")) modpaths.sort() for modpath in modpaths: sname = os.path.basename(modpath)[:-3] # minus .py sname = sname.replace("_", "-") sieves_requested.append(sname) # Language-specific sieves. modpaths = glob.glob( os.path.join(datadir(), "lang", "*", "sieve", "[a-z]*.py")) modpaths.sort() for modpath in modpaths: sname = os.path.basename(modpath)[:-3] # minus .py sname = sname.replace("_", "-") lang = os.path.basename(os.path.dirname(os.path.dirname(modpath))) sieves_requested.append(lang + ":" + sname) # No need to load and setup sieves if only listing sieve names requested. if op.list_sieve_names: report("\n".join(sieves_requested)) sys.exit(0) # Load sieve modules from supplied names in the command line. if not sieves_requested: sieves_requested = op.raw_sieves.split(",") sieve_modules = [] for sieve_name in sieves_requested: # Resolve sieve file. if not sieve_name.endswith(".py"): # One of internal sieves. if ":" in sieve_name: # Language-specific internal sieve. lang, name = sieve_name.split(":") sieve_path_base = os.path.join("lang", lang, "sieve", name) else: sieve_path_base = os.path.join("sieve", sieve_name) sieve_path_base = sieve_path_base.replace("-", "_") + ".py" sieve_path = os.path.join(datadir(), sieve_path_base) else: # Sieve name is its path. sieve_path = sieve_name try: sieve_file = open(unicode_to_str(sieve_path)) # ...unicode_to_str because of exec below. except IOError: error(_("@info", "Cannot load sieve '%(file)s'.", file=sieve_path)) # Load file into new module. sieve_mod_name = "sieve_" + str(len(sieve_modules)) sieve_mod = imp.new_module(sieve_mod_name) exec sieve_file in sieve_mod.__dict__ sieve_file.close() sys.modules[sieve_mod_name] = sieve_mod # to avoid garbage collection sieve_modules.append((sieve_name, sieve_mod)) if not hasattr(sieve_mod, "Sieve"): error( _("@info", "Module '%(file)s' does not define %(classname)s class.", file=sieve_path, classname="Sieve")) # Setup sieves (description, known parameters...) pp = ParamParser() snames = [] for name, mod in sieve_modules: scview = pp.add_subcmd(name) if hasattr(mod, "setup_sieve"): mod.setup_sieve(scview) snames.append(name) # If info on sieves requested, report and exit. if op.list_sieves: report(_("@info", "Available internal sieves:")) report(pp.listcmd(snames)) sys.exit(0) elif op.list_sieve_params: params = set() for scview in pp.cmdviews(): params.update(scview.params(addcol=True)) report("\n".join(sorted(params))) sys.exit(0) elif op.help_sieves: report(_("@info", "Help for sieves:")) report("") report(pp.help(snames)) sys.exit(0) # Prepare sieve parameters for parsing. sieve_params = list(op.sieve_params) # - append paramaters according to configuration sieve_params.extend(read_config_params(pp.cmdviews(), sieve_params)) # - remove paramaters according to command line if op.sieve_no_params: sieve_params_mod = [] for parspec in sieve_params: if parspec.split(":", 1)[0] not in op.sieve_no_params: sieve_params_mod.append(parspec) sieve_params = sieve_params_mod # If assembly of issued parameters requested, report and exit. if op.issued_params: escparams = [] for parspec in sieve_params: if ":" in parspec: param, value = parspec.split(":", 1) escparam = "%s:%s" % (param, escape_sh(value)) else: escparam = parspec escparams.append(escparam) fmtparams = " ".join(["-s%s" % x for x in sorted(escparams)]) if fmtparams: report(fmtparams) sys.exit(0) # Parse sieve parameters. sparams, nacc_params = pp.parse(sieve_params, snames) if nacc_params: error( _("@info", "Parameters not accepted by any of issued subcommands: " "%(paramlist)s.", paramlist=format_item_list(nacc_params))) # ======================================== # FIXME: Think of something less ugly. # Add as special parameter to each sieve: # - root paths from which the catalogs are collected # - whether destination independent coloring is in effect # - test function for catalog selection root_paths = [] if op.raw_paths: root_paths.extend(op.raw_paths) if op.files_from: for ffpath in op.files_from: root_paths.extend(collect_paths_from_file(ffpath)) if not op.raw_paths and not op.files_from: root_paths = ["."] is_cat_included = build_path_selector(incnames=op.include_names, incpaths=op.include_paths, excnames=op.exclude_names, excpaths=op.exclude_paths) for p in sparams.values(): p.root_paths = root_paths p.raw_colors = op.raw_colors p.is_cat_included = is_cat_included # ======================================== # Create sieves. sieves = [] for name, mod in sieve_modules: sieves.append(mod.Sieve(sparams[name])) # Get the message monitoring indicator from the sieves. # Monitor unless all sieves have requested otherwise. use_monitored = False for sieve in sieves: if getattr(sieve, "caller_monitored", True): use_monitored = True break if op.verbose and not use_monitored: report(_("@info:progress", "--> Not monitoring messages.")) # Get the sync indicator from the sieves. # Sync unless all sieves have requested otherwise, # and unless syncing is disabled globally in command line. do_sync = False for sieve in sieves: if getattr(sieve, "caller_sync", True): do_sync = True break if not op.do_sync: do_sync = False if op.verbose and not do_sync: report(_("@info:progress", "--> Not syncing after sieving.")) # Open in header-only mode if no sieve has message processor. # Categorize sieves by the presence of message/header processors. use_headonly = True header_sieves = [] header_sieves_last = [] message_sieves = [] for sieve in sieves: if hasattr(sieve, "process"): use_headonly = False message_sieves.append(sieve) if hasattr(sieve, "process_header"): header_sieves.append(sieve) if hasattr(sieve, "process_header_last"): header_sieves_last.append(sieve) if op.verbose and use_headonly: report(_("@info:progress", "--> Opening catalogs in header-only mode.")) # Collect catalog paths. fnames = collect_paths_cmdline(rawpaths=op.raw_paths, incnames=op.include_names, incpaths=op.include_paths, excnames=op.exclude_names, excpaths=op.exclude_paths, filesfrom=op.files_from, elsecwd=True, respathf=collect_catalogs, abort=True) if op.do_skip: errwarn = warning errwarn_on_msg = warning_on_msg else: errwarn = error errwarn_on_msg = error_on_msg # Prepare inline progress indicator. if not op.quiet: update_progress = init_file_progress(fnames, addfmt=t_("@info:progress", "Sieving: %(file)s")) # Sieve catalogs. modified_files = [] for fname in fnames: if op.verbose: report(_("@info:progress", "Sieving %(file)s...", file=fname)) elif not op.quiet: update_progress(fname) if op.msgfmt_check: d1, oerr, ret = collect_system( ["msgfmt", "-o", "/dev/null", "-c", fname]) if ret != 0: oerr = oerr.strip() errwarn( _("@info:progress", "%(file)s: %(cmd)s check failed:\n" "%(msg)s", file=fname, cmd="msgfmt -c", msg=oerr)) warning( _("@info:progress", "Skipping catalog due to syntax check failure.")) continue try: cat = Catalog(fname, monitored=use_monitored, headonly=use_headonly, single_entry=int(op.single_entry)) except CatalogSyntaxError, e: errwarn( _("@info:progress", "%(file)s: Parsing failed: %(msg)s", file=fname, msg=e)) warning( _("@info:progress", "Skipping catalog due to parsing failure.")) continue skip = False # First run all header sieves. if header_sieves and op.announce_entry: report( _("@info:progress", "Sieving header of %(file)s...", file=fname)) for sieve in header_sieves: try: ret = sieve.process_header(cat.header, cat) except SieveCatalogError, e: errwarn( _("@info:progress", "%(file)s:header: Sieving failed: %(msg)s", file=fname, msg=e)) skip = True break if ret not in (None, 0): break
def main(): locale.setlocale(locale.LC_ALL, "") # Get defaults for command line options from global config. cfgsec = pology_config.section("poepatch") def_do_merge = cfgsec.boolean("merge", True) # Setup options and parse the command line. usage = _("@info command usage", "%(cmd)s [OPTIONS] [OPTIONS] < EDIFF\n" "%(cmd)s -u [OPTIONS] PATHS...", cmd="%prog") desc = _("@info command description", "Apply embedded diff of PO files as patch.") ver = _("@info command version", u"%(cmd)s (Pology) %(version)s\n" u"Copyright © 2009, 2010 " u"Chusslove Illich (Часлав Илић) <%(email)s>", cmd="%prog", version=version(), email="*****@*****.**") opars = ColorOptionParser(usage=usage, description=desc, version=ver) opars.add_option( "-a", "--aggressive", action="store_true", dest="aggressive", default=False, help=_( "@info command line option description", "Apply every message to its paired message in the target file, " "irrespective of whether its non-pairing parts match too.")) opars.add_option( "-d", "--directory", metavar=_("@info command line value placeholder", "DIR"), dest="directory", help=_( "@info command line option description", "Prepend this directory path to any resolved target file path.")) opars.add_option( "-e", "--embed", action="store_true", dest="embed", default=False, help=_( "@info command line option description", "Instead of applying resolved newer version of the message, " "add the full embedded diff into the target file.")) opars.add_option( "-i", "--input", metavar=_("@info command line value placeholder", "FILE"), dest="input", help=_( "@info command line option description", "Read the patch from the given file instead of standard input.")) opars.add_option( "-n", "--no-merge", action="store_false", dest="do_merge", default=def_do_merge, help=_("@info command line option description", "Do not try to indirectly pair messages by merging catalogs.")) opars.add_option( "-p", "--strip", metavar=_("@info command line value placeholder", "NUM"), dest="strip", help=_( "@info command line option description", "Strip the smallest prefix containing NUM leading slashes from " "each file name found in the ediff file (like in patch(1)). " "If not given, only the base name of each file is taken.")) opars.add_option( "-u", "--unembed", action="store_true", dest="unembed", default=False, help=_( "@info command line option description", "Instead of applying a patch, resolve all embedded differences " "in given paths to newer versions of messages.")) (op, free_args) = opars.parse_args(str_to_unicode(sys.argv[1:])) # Could use some speedup. try: import psyco psyco.full() except ImportError: pass if not op.unembed: if free_args: error( _("@info", "Too many arguments in command line: %(argspec)s", argspec=" ".join(free_args))) if op.strip and not op.strip.isdigit(): error( _("@info", "Option %(opt)s expects a positive integer value.", opt="--strip")) apply_ediff(op) else: paths = [] for path in free_args: if not os.path.exists(path): warning( _("@info", "Path '%(path)s' does not exist.", path=path)) if os.path.isdir(path): paths.extend(collect_catalogs(path)) else: paths.append(path) for path in paths: unembed_ediff(path)
def process (self, msg, cat): if not msg.translated or msg.obsolete: return if msg.msgid_plural is not None: return # Parse property map entries from the message. psep, kvsep = None, None ekeys = set() props = {} for i in range(len(msg.manual_comment)): ind = i + 1 manc = (msg.manual_comment[i]).strip() if manc.startswith(self.p.pmhead): # Parse and check consistency of separators. espec = manc[len(self.p.pmhead):].lstrip() lkvsep, lpsep = espec[:2] if lkvsep.isalnum() or lpsep.isalnum(): warning_on_msg(_("@info", "An alphanumeric separator is used for " "property map entry in comment " "no. %(ord)d.", ord=ind), msg, cat) return if not psep: psep, kvsep = lpsep, lkvsep elif (psep, kvsep) != (lpsep, lkvsep): warning_on_msg(_("@info", "Inconsistent separators for " "continued property map entry in comment " "no. %(ord)d.", ord=ind), msg, cat) return # Remove leading and trailing separators. respec = espec[2:] if respec.endswith(psep + psep): respec = respec[:-2] elif respec.endswith(psep): respec = respec[:-1] else: warning_on_msg(_("@info", "Missing terminating separator for " "property map entry in comment " "no. %(ord)d.", ord=ind), msg, cat) return # Parse entry keys and key-value pairs. for elspec in respec.split(psep): if kvsep in elspec: pkey, pval = elspec.split(kvsep, 1) props[pkey] = pval else: ekey = elspec if not self.p.extrakeys: warning_on_msg(_("@info", "Additional entry key '%(key)s' " "is defined but not allowed for " "property map entry in comment " "no. %(ord)d.", key=ekey, ord=ind), msg, cat) return ekeys.add(ekey) elif manc.startswith(self.p.sdhead): sddef = manc[len(self.p.sdhead):].lstrip() sdkey = str(self.sdord) sdexpr = sdkey + ":" + sddef if self.p.derivs: sdexpr = ">" + self.p.derivs + "\n" + sdexpr try: self.synder.import_string(sdexpr) cprops = self.synder.props(sdkey) except Exception, e: errmsg = str_to_unicode(str(e)) warning_on_msg(_("@info", "Invalid derivation '%(deriv)s':\n" "%(msg)s", deriv=sddef, msg=errmsg), msg, cat) return jumble = "".join(["".join(x) for x in cprops.items()]) if not psep: psep = self._pick_sep(jumble, u"/|¦") kvsep = self._pick_sep(jumble, u"=:→") if not psep or not kvsep: warning_on_msg(_("@info", "No known separator are applicable " "to keys and values derived from " "'%(deriv)s'.", deriv=sddef), msg, cat) return else: if psep in jumble or kvsep in jumble: warning_on_msg(_("@info", "Previously selected separators " "are not applicable to " "keys and values derived from " "'%(deriv)s'.", deriv=sddef), msg, cat) return props.update(cprops)
def main(): locale.setlocale(locale.LC_ALL, "") # Get defaults for command line options from global config. cfgsec = pology_config.section("pomtrans") showservs = list() showservs.sort() # Setup options and parse the command line. usage = _("@info command usage", "%(cmd)s [OPTIONS] TRANSERV PATHS...", cmd="%prog") desc = _("@info command description", "Perform machine translation of PO files.") ver = _("@info command version", u"%(cmd)s (Pology) %(version)s\n" u"Copyright © 2009, 2010 " u"Chusslove Illich (Часлав Илић) <%(email)s>", cmd="%prog", version=version(), email="*****@*****.**") opars = ColorOptionParser(usage=usage, description=desc, version=ver) opars.add_option("-a", "--accelerator", dest="accel", metavar=_("@info command line value placeholder", "CHAR"), help=_( "@info command line option description", "Accelerator marker character used in messages. " "Detected from catalogs if not given.")) opars.add_option("-c", "--parallel-compendium", dest="parcomp", metavar=_("@info command line value placeholder", "FILE"), help=_( "@info command line option description", "Translate from translation to another language, " "found in compendium file at the given path.")) opars.add_option("-l", "--list-transervs", action="store_true", dest="list_transervs", default=False, help="List available translation services.") opars.add_option("-m", "--flag-%s" % _flag_mtrans, action="store_true", dest="flag_mtrans", default=False, help=_("@info command line option description", "Add '%(flag)s' flag to translated messages.", flag=_flag_mtrans)) opars.add_option( "-M", "--translation-mode", dest="tmode", metavar=_("@info command line value placeholder", "MODE"), help=_( "@info command line option description", "Translation mode for the chosen translation service. " "Overrides the default translation mode constructed " "based on source and target language. " "Mode string format is translation service dependent.")) opars.add_option("-n", "--no-fuzzy-flag", action="store_false", dest="flag_fuzzy", default=True, help=_( "@info command line option description", "Do not add '%(flag)s' flag to translated messages.", flag="fuzzy")) opars.add_option( "-p", "--parallel-catalogs", dest="parcats", metavar=_("@info command line value placeholder", "SEARCH:REPLACE"), help=_( "@info command line option description", "Translate from translation to another language " "found in parallel catalogs. " "For given target catalog path, the path to parallel catalog " "is constructed by replacing once SEARCH with REPLACE.")) opars.add_option("-s", "--source-lang", dest="slang", metavar=_("@info command line value placeholder", "LANG"), help=_( "@info command line option description", "Source language code. " "Detected from catalogs if not given.")) opars.add_option("-t", "--target-lang", dest="tlang", metavar=_("@info command line value placeholder", "LANG"), help=_( "@info command line option description", "Target language code. " "Detected from catalogs if not given.")) opars.add_option("-T", "--transerv-bin", dest="transerv_bin", metavar=_("@info command line value placeholder", "PATH"), help=_( "@info command line option description", "Custom path to translation service executable " "(where applicable).")) opars.add_option( "-d", "--data-directory", dest="data_directory", metavar=_("@info command line value placeholder", "FOLDER"), help=_( "@info command line option description", "Custom path to a translation data directory (where applicable).")) (op, free_args) = opars.parse_args(str_to_unicode(sys.argv[1:])) # Could use some speedup. try: import psyco psyco.full() except ImportError: pass if op.list_transervs: report("\n".join(sorted(_known_transervs.keys()))) sys.exit(0) if len(free_args) < 1: error(_("@info", "Translation service not specified.")) transervkey = free_args.pop(0) if transervkey not in _known_transervs: error( _("@info", "Translation service '%(serv)s' not known.", serv=transervkey)) tsbuilder_wopts = _known_transervs[transervkey] tsbuilder = lambda slang, tlang: tsbuilder_wopts(slang, tlang, op) paths = free_args if not op.parcomp and not op.parcats: translate_direct(paths, tsbuilder, op) else: translate_parallel(paths, tsbuilder, op)