Remove broken Python port of wmlxgettext
This commit is contained in:
parent
53e8f54e02
commit
8b59af444d
2 changed files with 2 additions and 256 deletions
|
@ -73,7 +73,8 @@ Version 1.13.0+dev:
|
|||
lobby with music and sound enabled (bug #23633, bug #23599) with libvorbis
|
||||
builds affected by Debian bug #782831.
|
||||
* Moved [role] tag to Lua (fix for bug #23630)
|
||||
|
||||
* Removed broken Python port of wmlxgettext from data/tools/.
|
||||
|
||||
Version 1.13.0:
|
||||
* Security fixes:
|
||||
* Fixed arbitrary file read from WML/Lua API (CVE-2015-0844, bug #23440).
|
||||
|
|
|
@ -1,255 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# wmlxgettext - extract .po files from Wesnoth WML
|
||||
#
|
||||
# WARNING! This file is basically a "proof of concept" and was meant as
|
||||
# replacement for the perl script "utils/wmlxgettext". This script you
|
||||
# are looking at is not used for the extraction of strings in Wesnoth mainline.
|
||||
# During tests it has shown to be significantly slower than the existing
|
||||
# solution so (at least for the moment) that older implementation will be used.
|
||||
# This also means that this script can (partly) be broken and/or not lead to
|
||||
# the results you might expect.
|
||||
|
||||
import sys, os, time, re, getopt
|
||||
from wesnoth.wmltools import *
|
||||
from wesnoth.wmliterator import *
|
||||
|
||||
# Disable the script so people don't accidentally use it and wonder why it doesn't do what they expect
|
||||
sys.stderr.write("""You probably want to use 'utils/wmlxgettext' instead
|
||||
This script was intended as a replacement but is not currently used
|
||||
It does not generate the same results as the perl version anymore\n""")
|
||||
# In case we're called by some big script that either swallows or swamps stderr
|
||||
print "This is not the wmlxgettext script you're looking for"
|
||||
sys.exit(1)
|
||||
|
||||
# Code swiped from wmllint: probably should live in the wesnoth module
|
||||
|
||||
vctypes = (".svn", ".git")
|
||||
|
||||
def cfgfile(fn):
|
||||
"Is a file interesting for translation purposes?"
|
||||
return fn.endswith(".cfg")
|
||||
|
||||
def allcfgfiles(dir):
|
||||
"Get the names of all cfgfile files under dir."
|
||||
datafiles = []
|
||||
if not os.path.isdir(dir):
|
||||
if cfgfile(dir):
|
||||
if not os.path.exists(dir):
|
||||
sys.stderr.write("wmllint: %s does not exist\n" % dir)
|
||||
else:
|
||||
datafiles.append(dir)
|
||||
else:
|
||||
for root, dirs, files in os.walk(dir):
|
||||
for vcsubdir in vctypes:
|
||||
if vcsubdir in dirs:
|
||||
dirs.remove(vcsubdir)
|
||||
for name in files:
|
||||
if cfgfile(os.path.join(root, name)):
|
||||
datafiles.append(os.path.join(root, name))
|
||||
return map(os.path.normpath, datafiles)
|
||||
|
||||
class WmllintIterator(WmlIterator):
|
||||
"Fold an Emacs-compatible error reporter into WmlIterator."
|
||||
def printError(self, *misc):
|
||||
"""Emit an error locator compatible with Emacs compilation mode."""
|
||||
if not hasattr(self, 'lineno') or self.lineno == -1:
|
||||
print >>sys.stderr, '"%s":' % self.fname
|
||||
else:
|
||||
print >>sys.stderr, '"%s", line %d:' % (self.fname, self.lineno+1),
|
||||
for item in misc:
|
||||
print >>sys.stderr, item,
|
||||
print >>sys.stderr #terminate line
|
||||
|
||||
# Swiped code ends here
|
||||
|
||||
def interesting(text):
|
||||
"Is the given text line interesting to render as part of a context?"
|
||||
# Ignore translatables, those are guaranteed to be nearby
|
||||
if re.search('_ *"', text):
|
||||
return False
|
||||
return True
|
||||
|
||||
if __name__ == "__main__":
|
||||
def help():
|
||||
sys.stderr.write("""\
|
||||
Usage: wmlxgettext [options] dirpath
|
||||
Options may be any of these:
|
||||
-h, --help Emit this help message and quit
|
||||
-d dir, --directory=dir operate on specified directory
|
||||
-s dn, --domain=dn Generate only for specified domain
|
||||
-v val. --verbose=val Set warning level
|
||||
Options may be followed by any number of directiories to check. If no
|
||||
directories are given, all files under the current directory are checked.
|
||||
""")
|
||||
|
||||
directory = os.getcwd()
|
||||
|
||||
# Deduce package and version
|
||||
pop_to_top("wmlxgettext")
|
||||
m = re.search(r"#define VERSION\s+(.*)", open("src/wesconfig.h").read())
|
||||
if not m:
|
||||
print >>sys.stderr, "wmlgettext: can't get Wesnoth version."
|
||||
sys.exit(1)
|
||||
else:
|
||||
version = string_strip(m.group(1))
|
||||
|
||||
os.chdir(directory)
|
||||
|
||||
print '''\
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: wesnoth %s\\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.wesnoth.org/\\n"
|
||||
"POT-Creation-Date: %s\\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\\n"
|
||||
"Last-Translator: FULL NAME <EMAIL\@ADDRESS>\\n"
|
||||
"Language-Team: LANGUAGE <LL\@li.org>\\n"
|
||||
"MIME-Version: 1.0\\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\\n"
|
||||
"Content-Transfer-Encoding: 8bit\\n"
|
||||
''' % (version, time.strftime("%Y-%m-%d, %H:%M+0000", time.gmtime()))
|
||||
|
||||
try:
|
||||
domain = None
|
||||
verbose = 0
|
||||
# Process options
|
||||
(options, arguments) = getopt.getopt(sys.argv[1:], "d:h:s:v:",
|
||||
[
|
||||
'directory=',
|
||||
'help',
|
||||
'domain=',
|
||||
'verbose=',
|
||||
])
|
||||
for (switch, val) in options:
|
||||
if switch in ('-d', '--directory'):
|
||||
directory = val
|
||||
elif switch in ('-h', '--help'):
|
||||
help()
|
||||
sys.exit(0)
|
||||
elif switch in ('-s', '--domain'):
|
||||
domain = val
|
||||
elif switch in ('-v', '--verbose'):
|
||||
verbose = int(val)
|
||||
|
||||
if not arguments:
|
||||
arguments = '.'
|
||||
|
||||
os.chdir(directory)
|
||||
|
||||
opener_stack = []
|
||||
attributes_stack = []
|
||||
translatables = []
|
||||
contexts = {}
|
||||
find_translatable = re.compile('_ *"([^"]*)"')
|
||||
|
||||
def get_translatables(nav, fn):
|
||||
"Mine translatable strings "
|
||||
itor = find_translatable.finditer(nav.text)
|
||||
for match in itor:
|
||||
opener_stack.append((nav.element, fn, nav.lineno))
|
||||
translatables.append((match.group(1), opener_stack[:]))
|
||||
opener_stack.pop()
|
||||
|
||||
def inMacroContinuation(nav):
|
||||
return opener_stack and type(opener_stack[-1][0]) == type("") \
|
||||
and opener_stack[-1][0].startswith("{")
|
||||
|
||||
def isInlineMacro(nav):
|
||||
return type(nav.element) == type([]) and nav.element and nav.element[0].startswith("{")
|
||||
|
||||
def handle_element(nav, fn):
|
||||
if isAttribute(nav):
|
||||
if verbose > 1:
|
||||
print "Attribute", nav, "with ancestors", nav.ancestors()
|
||||
attributes_stack[-1].append(nav.text.strip())
|
||||
get_translatables(nav, fn)
|
||||
elif isCloser(nav):
|
||||
if verbose > 1:
|
||||
print "Closing scope", nav
|
||||
contexts[opener_stack.pop()] = attributes_stack.pop()
|
||||
elif isOpener(nav):
|
||||
if verbose > 1:
|
||||
print "Opening scope", nav
|
||||
attributes_stack.append([])
|
||||
opener_stack.append((nav.element, fn, nav.lineno))
|
||||
elif isMacroOpener(nav):
|
||||
if verbose > 1:
|
||||
print "Opening macro scope", nav
|
||||
opener_stack.append((nav.element, fn, nav.lineno))
|
||||
get_translatables(nav, fn)
|
||||
elif isMacroCloser(nav):
|
||||
if verbose > 1:
|
||||
print "Closing macro scope", nav
|
||||
opener_stack.pop()
|
||||
elif inMacroContinuation(nav):
|
||||
if verbose > 1:
|
||||
print "In macro continuation", repr(nav.text)
|
||||
nav.element = "argument"
|
||||
get_translatables(nav, fn)
|
||||
elif isInlineMacro(nav):
|
||||
if verbose > 1:
|
||||
print "Inline macro", nav
|
||||
nav.element = nav.element[0]
|
||||
get_translatables(nav, fn)
|
||||
elif nav.element == "#po":
|
||||
if verbose > 1:
|
||||
print "Passthrough for", nav
|
||||
opener_stack.append((nav.element, fn, nav.lineno))
|
||||
translatables.append((nav.text.lstrip(), opener_stack[:]))
|
||||
opener_stack.pop()
|
||||
elif verbose > 1:
|
||||
print "Unhandled", nav
|
||||
# Gather a list describing the context of every
|
||||
# translatable string.
|
||||
for dir in arguments:
|
||||
seqno = 0
|
||||
for fn in allcfgfiles(dir):
|
||||
if verbose >= 2:
|
||||
print fn + ":"
|
||||
lines = file(fn).readlines()
|
||||
if domain is not None:
|
||||
if lines[0].startswith("#textdomain"):
|
||||
belongs_to = lines[0].split()[1]
|
||||
if belongs_to != domain:
|
||||
if verbose:
|
||||
print "wmlxgettext: skipping %s, wrong domain" % fn
|
||||
continue
|
||||
opener_stack.append(("<toplevel>", fn, 0))
|
||||
attributes_stack.append([])
|
||||
for nav in WmllintIterator(lines, fn):
|
||||
handle_element(nav, fn)
|
||||
opener_stack.pop()
|
||||
|
||||
# Debugging output
|
||||
if verbose:
|
||||
print "Translatables:"
|
||||
for (translatable, context) in translatables:
|
||||
print "%s: %s" % (translatable, context)
|
||||
print "Contexts:"
|
||||
for (key, value) in contexts.items():
|
||||
print key, "->", value
|
||||
# Generate a report from the translatables
|
||||
notes = ""
|
||||
for (translatable, context) in translatables:
|
||||
if translatable.startswith("#po"):
|
||||
notes += translatable.replace("po:", "")
|
||||
continue
|
||||
attribs = ""
|
||||
for (i, (tag, file, line)) in enumerate(context):
|
||||
if i == len(context)-1 or tag.startswith("{"):
|
||||
print "# %s, line %d: %s" % (file, line, tag)
|
||||
else:
|
||||
for (key, value) in contexts.items():
|
||||
value = filter(interesting, value)
|
||||
if key[0] == tag and key[1] == file and key[2] == line:
|
||||
attribs = " has " + ", ".join(value)
|
||||
print "# %s, line %d: %s%s" % (file, line, tag, attribs)
|
||||
if notes:
|
||||
print notes,
|
||||
notes = ""
|
||||
print 'msgid "%s"' % translatable
|
||||
print 'msgstr ""'
|
||||
print ""
|
||||
except KeyboardInterrupt:
|
||||
print >>sys.stderr, "wmlxgettext: aborted."
|
Loading…
Add table
Reference in a new issue