wmlunits: More code clean-up

This commit is contained in:
Ignacio R. Morelle 2017-08-12 02:24:07 -04:00
parent fcba9f498d
commit 9db2ed630c
4 changed files with 264 additions and 230 deletions

View file

@ -1,19 +1,21 @@
"""
Various helpers for use by the wmlunits tool.
"""
import sys, os, re, glob, shutil, copy, urllib.request, urllib.error, urllib.parse, subprocess
import sys, os, re, glob, shutil, copy, subprocess
import wesnoth.wmlparser3 as wmlparser3
def get_datadir(wesnoth_exe):
p = subprocess.Popen([wesnoth_exe, "--path"],
stdout = subprocess.PIPE, stderr = subprocess.PIPE)
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
out, err = p.communicate()
return out.strip()
def get_userdir(wesnoth_exe):
p = subprocess.Popen([wesnoth_exe, "--config-path"],
stdout = subprocess.PIPE, stderr = subprocess.PIPE)
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
out, err = p.communicate()
return out.strip()
@ -35,50 +37,52 @@ class ImageCollector:
self.images_by_ipath = {}
self.binary_paths_per_addon = {}
self.datadir = datadir
if not self.datadir:
self.datadir = get_datadir(wesnoth_exe)
self.userdir = userdir
if not self.datadir: self.datadir = get_datadir(wesnoth_exe)
if not self.userdir: self.userdir = get_userdir(wesnoth_exe)
if not self.userdir:
self.userdir = get_userdir(wesnoth_exe)
def add_binary_paths_from_WML(self, addon, WML):
for binpath in WML.get_all(tag = "binary_path"):
for binpath in WML.get_all(tag="binary_path"):
path = binpath.get_text_val("path")
if addon not in self.binary_paths_per_addon:
self.binary_paths_per_addon[addon] = []
self.binary_paths_per_addon[addon].append(path)
def _find_image(self, addon, name):
tilde = name.find("~")
if tilde >= 0:
name = name[:tilde]
bases = [os.path.join(self.datadir, "data/core/images")]
binpaths = self.binary_paths_per_addon.get(addon, [])[:]
binpaths.reverse()
for x in binpaths:
for path in binpaths:
for idir in ["images", "images/units"]:
bases.append(os.path.join(self.datadir, x, idir))
bases.append(os.path.join(self.userdir, x, idir))
bases.append(os.path.join(self.datadir, path, idir))
bases.append(os.path.join(self.userdir, path, idir))
bases = [os.path.join("%s" % base, name) for base in bases]
for ipath in bases:
if os.path.exists(ipath): return ipath, bases
if os.path.exists(ipath):
return ipath, bases
return None, bases
def add_image_check(self, addon, name, no_tc = False):
def add_image_check(self, addon, name, no_tc=False):
if (addon, name) in self.images_by_addon_name:
image = self.images_by_addon_name[(addon, name)]
if addon not in image.addons: image.addons.add(addon)
if addon not in image.addons:
image.addons.add(addon)
return image
ipath, bases = self._find_image(addon, name)
if ipath in self.images_by_ipath:
image = self.images_by_ipath[ipath]
if addon not in image.addons: image.addons.add(addon)
if addon not in image.addons:
image.addons.add(addon)
return image
def make_name(x):
x = x.strip("./ ")
d = options.config_dir.strip("./ ")
@ -90,8 +94,10 @@ class ImageCollector:
x = x.strip("./ ")
y = ""
for c in x:
if c == "/": c = "$"
elif not c.isalnum() and c not in ".+-()[]{}": c = "_"
if c == "/":
c = "$"
elif not c.isalnum() and c not in ".+-()[]{}":
c = "_"
y += c
return y
@ -102,14 +108,14 @@ class ImageCollector:
image = Image(id_name, ipath, bases, no_tc)
image.addons.add(addon)
self.images_by_addon_name[(addon, name)] = image
if ipath:
self.images_by_ipath[ipath] = image
return image
def add_image(self, addon, path, no_tc = False):
def add_image(self, addon, path, no_tc=False):
image = self.add_image_check(addon, path, no_tc)
return image.id_name
@ -122,7 +128,7 @@ class ImageCollector:
pass
no_tc = image.no_tc
ipath = os.path.normpath(image.ipath)
cdir = os.path.normpath(options.config_dir + "/data/add-ons")
if ipath.startswith(cdir):
@ -134,7 +140,7 @@ class ImageCollector:
# We assume TeamColorizer is in the same directory as the
# helpers.py currently executing.
command = os.path.join(os.path.dirname(__file__),
"TeamColorizer")
"TeamColorizer")
p = subprocess.Popen([command, ipath, opath])
p.wait()
else:
@ -160,9 +166,7 @@ class WesnothList:
self.movetype_lookup = {}
self.era_lookup = {}
self.campaign_lookup = {}
self.parser = wmlparser3.Parser(wesnoth_exe, config_dir,
data_dir)
self.parser = wmlparser3.Parser(wesnoth_exe, config_dir, data_dir)
def add_terrains(self):
"""
@ -171,20 +175,21 @@ class WesnothList:
self.parser.parse_text("{core/terrain.cfg}\n")
n = 0
for terrain in self.parser.get_all(tag = "terrain_type"):
for terrain in self.parser.get_all(tag="terrain_type"):
tstring = terrain.get_text_val("string")
self.terrain_lookup[tstring] = terrain
n += 1
return n
def add_languages(self, languages):
"""
Returns a dictionary mapping isocodes to languages.
"""
self.languages_found = {}
parser = wmlparser3.Parser(options.wesnoth, options.config_dir,
options.data_dir)
parser = wmlparser3.Parser(options.wesnoth,
options.config_dir,
options.data_dir)
parser.parse_text("{languages}")
for locale in parser.get_all(tag="locale"):
@ -199,12 +204,14 @@ class WesnothList:
For an era, list all factions and units in it.
"""
eid = era.get_text_val("id")
if not eid: return
if not eid:
return
self.era_lookup[eid] = era
era.faction_lookup = {}
for multiplayer_side in era.get_all(tag = "multiplayer_side"):
for multiplayer_side in era.get_all(tag="multiplayer_side"):
fid = multiplayer_side.get_text_val("id")
if fid == "Random": continue
if fid == "Random":
continue
era.faction_lookup[fid] = multiplayer_side
recruit = multiplayer_side.get_text_val("recruit", "").strip()
leader = multiplayer_side.get_text_val("leader", "").strip()
@ -242,7 +249,7 @@ class WesnothList:
self.parser.parse_text("{multiplayer/eras.cfg}")
n = 0
for era in self.parser.get_all(tag = "era"):
for era in self.parser.get_all(tag="era"):
self.add_era(era)
n += 1
return n
@ -253,29 +260,29 @@ class WesnothList:
we reference them everywhere by this id, and here can add them all to
one big collection.
"""
addunits = self.parser.get_all(tag = "units")
addunits += self.parser.get_all(tag = "+units")
if not addunits: return 0
addunits = self.parser.get_all(tag="units")
addunits += self.parser.get_all(tag="+units")
if not addunits:
return 0
def getall(oftype):
r = []
r = []
res = []
for units in addunits:
r += units.get_all(tag = oftype)
return r
res += units.get_all(tag=oftype)
return res
# Find all unit types.
newunits = getall("unit_type") + getall("unit")
for unit in newunits:
uid = unit.get_text_val("id")
unit.id = uid
if unit.get_text_val("do_not_list", "no") != "no" or\
if unit.get_text_val("do_not_list", "no") not in ["no", "false"] or \
unit.get_text_val("hide_help", "no") not in ["no", "false"]:
unit.hidden = True
unit.hidden = True
else:
unit.hidden = False
if uid in self.unit_lookup:
unit = self.unit_lookup[uid]
# TODO: We might want to compare the two units
@ -283,16 +290,16 @@ class WesnothList:
# to do something clever like rename it...
else:
self.unit_lookup[uid] = unit
if not hasattr(unit, "campaigns"): unit.campaigns = []
if not hasattr(unit, "campaigns"):
unit.campaigns = []
unit.campaigns.append(campaign)
# Find all races.
newraces = getall("race")
for race in newraces:
rid = race.get_text_val("id")
if rid == None:
if rid is None:
rid = race.get_text_val("name")
self.race_lookup[rid] = race
# Find all movetypes.
@ -314,8 +321,10 @@ class WesnothList:
error_message("Warning: No race \"%s\" found (%s).\n" % (
race, unit.get_text_val("id")))
movetype = self.get_unit_value(unit, "movement_type")
try: unit.movetype = self.movetype_lookup[movetype]
except KeyError: unit.movetype = None
try:
unit.movetype = self.movetype_lookup[movetype]
except KeyError:
unit.movetype = None
unit.advance = []
advanceto = unit.get_text_val("advances_to")
@ -326,7 +335,6 @@ class WesnothList:
for advance in advanceto.split(","):
auid = advance.strip()
if auid: unit.advance.append(auid)
# level
try:
level = int(self.get_unit_value(unit, "level"))
@ -343,10 +351,9 @@ class WesnothList:
"""
Once all units have been added, do some checking.
"""
# handle advancefrom tags
for uid, unit in list(self.unit_lookup.items()):
for advancefrom in unit.get_all(tag = "advancefrom"):
for advancefrom in unit.get_all(tag="advancefrom"):
fromid = advancefrom.get_text_val("unit")
if fromid:
try:
@ -363,7 +370,6 @@ class WesnothList:
for unit in list(self.unit_lookup.values()):
unit.factions = []
unit.eras = []
for eid, era in list(self.era_lookup.items()):
for fid, multiplayer_side in list(era.faction_lookup.items()):
for uid in multiplayer_side.units:
@ -372,15 +378,14 @@ class WesnothList:
except KeyError:
error_message(
("Error: Era '%s' faction '%s' references " +
"non-existant unit id '%s'!\n") % (
eid,
fid,
str(uid)))
"non-existant unit id '%s'!\n") % (
eid,
fid,
str(uid)))
continue
if not eid in unit.eras:
unit.eras.append(eid)
unit.factions.append((eid, fid))
# as a special case, add units from this addon but with no faction
for unit in list(self.unit_lookup.values()):
if unit.campaigns[0] == self.cid:
@ -388,25 +393,25 @@ class WesnothList:
if not eid in unit.eras:
unit.eras.append(eid)
unit.factions.append((eid, None))
def get_base_unit(self, unit):
b = unit.get_all(tag = "base_unit")
b = unit.get_all(tag="base_unit")
if b:
b = b[0]
buid = b.get_text_val("id")
try: baseunit = self.unit_lookup[buid]
try:
baseunit = self.unit_lookup[buid]
except KeyError:
error_message(
"Warning: No baseunit \"%s\" for \"%s\".\n" % (
buid, unit.get_text_val("id")))
buid, unit.get_text_val("id")))
return None
return baseunit
return None
def get_unit_value(self, unit, attribute, default = None, translation = None):
def get_unit_value(self, unit, attribute, default=None, translation=None):
value = unit.get_text_val(attribute, None, translation)
if value == None:
if value is None:
baseunit = self.get_base_unit(unit)
if baseunit:
return self.get_unit_value(baseunit, attribute, default, translation)
@ -438,7 +443,8 @@ class UnitForest:
for uid, u in list(self.lookup.items()):
for cid in u.child_ids:
c = self.lookup.get(cid, None)
if not c: continue
if not c:
continue
u.children.append(c)
if not uid in c.parent_ids:
c.parent_ids.append(uid)
@ -458,7 +464,7 @@ class UnitForest:
if c.id in already:
error_message(
("Warning: Unit %s advances to unit %s in a loop.\n" %
(u.id, c.id)) +
(u.id, c.id)) +
(" Removing advancement %s.\n" % c.id))
u.children.remove(c)
for c in u.children:
@ -469,7 +475,6 @@ class UnitForest:
def update(self):
self.create_network()
self.breadth = sum([x.update_breadth() for x in list(self.trees.values())])
return self.breadth

View file

@ -7,11 +7,10 @@ import os
import re
import time
import traceback
import urllib
import urllib.parse
import unit_tree.helpers as helpers
import wesnoth.wmlparser3 as wmlparser3
PICS_LOCATION = "../../pics"
# Icons for mainline terrains used on the unit details page
@ -163,6 +162,7 @@ def error_message(message):
error_only_once[message] = 1
write_error(message)
helpers.error_message = error_message
def reset_errors():
@ -174,6 +174,7 @@ def int_fallback(str_value, int_fallback=0):
except ValueError:
return int_fallback
def cleanurl(url):
"""
Encode the given URL to ensure it only contains valid URL characters
@ -291,6 +292,7 @@ class GroupByRace:
return "None"
return group
class GroupByNothing:
def __init__(self):
pass
@ -304,6 +306,7 @@ class GroupByNothing:
def group_name(self, group):
return "units"
class GroupByFaction:
def __init__(self, wesnoth, era):
self.wesnoth = wesnoth
@ -325,7 +328,9 @@ class GroupByFaction:
name = "factionless"
return name
global_htmlout = None
def T(tag, att):
if not tag:
return "none"
@ -458,8 +463,10 @@ class HTMLOutput:
return len(forest.lookup)
def write_navbar(self, report_type):
def write(x):
self.output.write(x)
def write(line):
self.output.write(line)
def _(msgid, textdomain="wesnoth"):
return self.translate(msgid, textdomain)
all_written_html_files.append((self.isocode, self.output.filename))
@ -539,14 +546,12 @@ class HTMLOutput:
# campaigns/eras navigation.
# Campaigns
x = self.translate("addon_type^Campaign", "wesnoth")
add_menu("campaigns_menu", x)
add_menu("campaigns_menu", _("addon_type^Campaign"))
write(PRE_PLACEHOLDER_CAMPAIGNS)
end_menu()
# Eras
x = self.translate("Era", "wesnoth")
add_menu("eras_menu", x)
add_menu("eras_menu", _("Era"))
write(PRE_PLACEHOLDER_ERAS)
end_menu()
@ -557,10 +562,9 @@ class HTMLOutput:
target = "mainline.html"
if not self.is_era:
x = self.translate("Race", "wesnoth-lib")
add_menu("races_menu", x)
add_menu("races_menu", _("Race", "wesnoth-lib"))
add_menuitem('mainline.html', self.translate('all', 'wesnoth-editor'))
add_menuitem('mainline.html', _("all", "wesnoth-editor"))
r = {}, {}
for u in list(self.wesnoth.unit_lookup.values()):
@ -588,8 +592,7 @@ class HTMLOutput:
add_menuitem(url, racename)
end_menu()
else:
x = self.translate("Factions", "wesnoth-help")
add_menu("races_menu", x)
add_menu("races_menu", _("Factions", "wesnoth-help"))
for row in self.unitgrid:
for column in range(6):
hspan, vspan, un = row[column]
@ -650,8 +653,7 @@ class HTMLOutput:
end_menu()
# Languages
x = self.translate("Language", "wesnoth")
add_menu("languages_menu", x, is_table_container=True)
add_menu("languages_menu", _("Language"), is_table_container=True)
cell = 0
col = 0
colcount = 5
@ -957,7 +959,7 @@ class HTMLOutput:
y = x[0].get_text_val(key, translation=self.translation.translate)
if y:
return True, y
if unit.movetype and mty != None:
if unit.movetype and mty is not None:
return False, mty
return False, "-"
@ -1076,13 +1078,13 @@ class HTMLOutput:
("id", "Id: ")
]
for val, text in attributes:
x = uval(val)
if not x and val in ("jamming", "vision"):
for attr, label in attributes:
value = uval(attr)
if not value and attr in ("jamming", "vision"):
continue
if val == "alignment":
x = _(x)
write('<tr><th>%s</th><td class="val">%s</td></tr>\n' % (cleantext(text, quote=False), cleantext(x, quote=False)))
if attr == "alignment":
value = _(value)
write('<tr><th>%s</th><td class="val">%s</td></tr>\n' % (cleantext(label, quote=False), cleantext(value, quote=False)))
# Write info about abilities.
anames = self.get_abilities(unit)
@ -1330,7 +1332,7 @@ def generate_campaign_report(addon, isocode, campaign, wesnoth):
def generate_era_report(addon, isocode, era, wesnoth):
eid = era.get_text_val("id")
print(("era " + addon + " " + eid + " " + isocode))
print("era " + addon + " " + eid + " " + isocode)
path = os.path.join(options.output, addon, isocode)
if not os.path.isdir(path):
@ -1387,7 +1389,7 @@ def generate_single_unit_reports(addon, isocode, wesnoth):
output.close()
def html_postprocess_file(filename, isocode, batchlist):
print(("postprocessing " + repr(filename)))
print("postprocessing " + repr(filename))
chtml = ""
ehtml = ""

View file

@ -1,5 +1,9 @@
#!/usr/bin/env python2
import glob, os, sys, time, re
import glob
import os
import re
import sys
import time
sys.path.append(os.path.join(os.path.dirname(__file__), ".."))
from . import html_output
@ -69,8 +73,10 @@ def main(folder):
total_error_logs = 0
total_lines = 0
for f in sorted(glob.glob(os.path.join(folder, "*"))):
if not os.path.isdir(f): continue
if f.endswith("/pics"): continue
if not os.path.isdir(f):
continue
if f.endswith("/pics"):
continue
error_log = os.path.abspath(os.path.join(f, "error.log"))
error_html = os.path.abspath(os.path.join(f, "error.html"))
@ -104,15 +110,13 @@ def main(folder):
source = []
def postprocess(line):
if line == "WMLError:": return ""
if line == "?": return ""
if line == "Preprocessor error:": return ""
if line.startswith("Automatically found a possible data directory"): return ""
if line.startswith("Overriding data directory with"): return ""
if line == "'SKIP_CORE' defined.": return ""
if re.match("added .* defines.", line): return ""
if line.startswith("skipped 'data/core'"): return ""
if line.startswith("preprocessing specified resource:"): return ""
if line in ("WMLError:", "?", "Preprocessor error:", "'SKIP_CORE' defined.") or \
line.startswith("Automatically found a possible data directory") or \
line.startswith("Overriding data directory with") or \
line.startswith("skipped 'data/core'") or \
line.startswith("preprocessing specified resource:") or \
re.match("added .* defines.", line):
return ""
mo = re.match(r"\d+ /tmp(?:/wmlparser_.*?/|/)(.*\.cfg).*", line)
if mo:

View file

@ -7,12 +7,21 @@ Run without arguments to see usage.
"""
# Makes things faster on 32-bit systems
try: import psyco; psyco.full()
except ImportError: pass
import sys, os, glob, shutil, urllib.request, urllib.error, urllib.parse, argparse, traceback
import subprocess, yaml
import multiprocessing, queue
try:
import psyco
psyco.full()
except ImportError:
pass
import argparse
import os
import shutil
import sys
import traceback
import subprocess
import multiprocessing
import queue
import yaml
import wesnoth.wmlparser3 as wmlparser3
import unit_tree.helpers as helpers
@ -27,14 +36,18 @@ def copy_images():
print("Recolorizing pictures.")
image_collector.copy_and_color_images(options.output)
shutil.copy2(os.path.join(image_collector.datadir,
"data/tools/unit_tree/style.css"), options.output)
"data/tools/unit_tree/style.css"),
options.output)
shutil.copy2(os.path.join(image_collector.datadir,
"data/tools/unit_tree/menu.js"), options.output)
"data/tools/unit_tree/menu.js"),
options.output)
def shell(com):
#print(com)
p = subprocess.Popen(com, stdout = subprocess.PIPE,
stderr = subprocess.PIPE, shell = True)
p = subprocess.Popen(com,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
shell=True)
out, err = p.communicate()
#if out: sys.stdout.write(out)
#if err: sys.stdout.write(err)
@ -43,7 +56,8 @@ def shell(com):
def shell_out(com):
p = subprocess.Popen(com,
stdout = subprocess.PIPE, stderr = subprocess.PIPE)
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
out, err = p.communicate()
return out
@ -58,7 +72,7 @@ def move(f, t, name):
com = "mv " + f + "/" + bash(name) + " " + t + "/"
return shell(com)
_info = {}
def get_info(addon):
global _info
@ -68,12 +82,13 @@ def get_info(addon):
try:
path = options.addons + "/" + addon + "/_info.cfg"
if os.path.exists(path):
parser = wmlparser3.Parser(options.wesnoth, options.config_dir,
options.data_dir)
parser = wmlparser3.Parser(options.wesnoth,
options.config_dir,
options.data_dir)
parser.parse_file(path)
_info[addon] = parser
else:
print(("Cannot find " + path))
print("Cannot find " + path)
except wmlparser3.WMLError as e:
print(e)
return _info[addon]
@ -87,7 +102,7 @@ def get_dependencies(addon):
return _deps[addon]
_deps[addon] = []
try:
info = get_info(addon).get_all(tag = "info")[0]
info = get_info(addon).get_all(tag="info")[0]
row = info.get_text_val("dependencies")
if row:
deps1 = row.split(",")
@ -97,7 +112,7 @@ def get_dependencies(addon):
if d in global_addons:
_deps[addon].append(d)
else:
print(("Missing dependency for " + addon + ": " + d))
print("Missing dependency for " + addon + ": " + d)
except Exception as e:
print(e)
return _deps[addon]
@ -110,8 +125,8 @@ def get_all_dependencies(addon):
check = get_dependencies(addon)[:]
while check:
d = check.pop()
if d == addon: continue
if d in result: continue
if d == addon or d in result:
continue
result.append(d)
check += get_dependencies(d)
return result
@ -131,33 +146,32 @@ def sorted_by_dependencies(addons):
n += 1
continue
if n == 0:
print(("Cannot sort dependencies for these addons: " + str(unsorted)))
sorted += unsorted
break
print("Cannot sort dependencies for these addons: " + str(unsorted))
sorted += unsorted
break
return sorted
def search(batchlist, name):
for info in batchlist:
if info and info["name"] == name: return info
if info and info["name"] == name:
return info
batchlist.append({})
batchlist[-1]["name"] = name
return batchlist[-1]
def list_contents():
class Empty: pass
local = Empty()
class Empty:
pass
local = Empty()
mainline_eras = set()
filename = options.list
def append(info, id, define, c = None, name = None, domain = None):
def append(info, id, define, c=None, name=None, domain=None):
info.append({})
info[-1]["id"]= id
info[-1]["id"] = id
info[-1]["define"] = define
if c:
info[-1]["name"] = c.get_text_val("name")
else:
info[-1]["name"] = name
info[-1]["name"] = c.get_text_val("name") if c else name
info[-1]["units"] = "?"
info[-1]["translations"] = {}
@ -166,7 +180,7 @@ def list_contents():
def translate(string, domain):
return translation.translate(string, domain)
if c:
t = c.get_text_val("name", translation = translate)
t = c.get_text_val("name", translation=translate)
else:
t = translate(name, domain)
if t != info[-1]["name"]:
@ -181,7 +195,7 @@ def list_contents():
return dependency_eras
def list_eras(batchlist, addon):
eras = local.wesnoth.parser.get_all(tag = "era")
eras = local.wesnoth.parser.get_all(tag="era")
if addon != "mainline":
dependency_eras = get_dependency_eras(batchlist, addon)
eras = [x for x in eras if not x.get_text_val("id") in dependency_eras]
@ -190,30 +204,31 @@ def list_contents():
eid = era.get_text_val("id")
if addon == "mainline":
mainline_eras.add(eid)
append(info, eid, "MULTIPLAYER", c = era)
append(info, eid, "MULTIPLAYER", c=era)
return info
def list_campaigns(batchlist, addon):
campaigns = local.wesnoth.parser.get_all(tag = "campaign")
campaigns = local.wesnoth.parser.get_all(tag="campaign")
info = []
for campaign in campaigns:
cid = campaign.get_text_val("id")
d = campaign.get_text_val("define")
d2 = campaign.get_text_val("extra_defines")
if d2: d += "," + d2
if d2:
d += "," + d2
d3 = campaign.get_text_val("difficulties")
if d3:
d += "," + d3.split(",")[0]
else:
difficulty = campaign.get_all(tag = "difficulty")
difficulty = campaign.get_all(tag="difficulty")
if difficulty:
d3 = difficulty[0].get_text_val("define")
if d3:
d += "," + d3
append(info, cid, d, c = campaign)
append(info, cid, d, c=campaign)
return info
@ -232,10 +247,10 @@ def list_contents():
q.put(("e", e))
q = multiprocessing.Queue()
p = multiprocessing.Process(target = f, args = (options, wml, defines, q))
p = multiprocessing.Process(target=f, args=(options, wml, defines, q))
p.start()
try:
s, local.wesnoth = q.get(timeout = TIMEOUT)
s, local.wesnoth = q.get(timeout=TIMEOUT)
except queue.Empty:
p.terminate()
raise
@ -244,15 +259,17 @@ def list_contents():
if s == "e":
remote_exception = local.wesnoth
raise remote_exception
def get_version(addon):
parser = get_info(addon)
if parser:
for info in parser.get_all(tag = "info"):
for info in parser.get_all(tag="info"):
return info.get_text_val("version") + "*" + info.get_text_val("uploads")
try: os.makedirs(options.output + "/mainline")
except OSError: pass
try:
os.makedirs(options.output + "/mainline")
except OSError:
pass
try:
batchlist = yaml.load(open(options.list))
@ -270,8 +287,8 @@ def list_contents():
# Fake mainline campaign to have an overview of the mainline units
info["campaigns"] = []
append(info["campaigns"], "mainline", "", name = "Units", domain = "wesnoth-help")
append(info["campaigns"], "mainline", "", name="Units", domain="wesnoth-help")
if not options.addons_only:
parse("{core}{campaigns}", "SKIP_CORE")
info["campaigns"] += list_campaigns(batchlist, "mainline")
@ -291,7 +308,8 @@ def list_contents():
addons = sorted_by_dependencies(addons)
for i, addon in enumerate(addons):
if not os.path.isdir(options.addons + "/" + addon): continue
if not os.path.isdir(options.addons + "/" + addon):
continue
mem = "? KB"
try:
mem = dict([x.split("\t", 1) for x in open("/proc/self/status").read().split("\n") if x])["VmRSS:"]
@ -301,16 +319,17 @@ def list_contents():
sys.stdout.flush()
d = options.output + "/" + addon
logname = d + "/error.log"
try: os.makedirs(d)
except OSError: pass
try:
os.makedirs(d)
except OSError:
pass
version = get_version(addon)
move(options.addons, options.config_dir + "/data/add-ons", addon)
for d in get_dependencies(addon):
move(options.addons, options.config_dir + "/data/add-ons", d)
try:
info = search(batchlist, addon)
if info.get("version", "") == version and info.get("parsed", False) == True:
if info.get("version", "") == version and info.get("parsed", False) is True:
sys.stdout.write("up to date\n")
continue
info["parsed"] = False
@ -341,18 +360,17 @@ def list_contents():
ef.write("</INTERNAL ERROR>\n")
ef.close()
sys.stdout.write("failed\n")
finally:
move(options.config_dir + "/data/add-ons", options.addons, addon)
for d in get_dependencies(addon):
move(options.config_dir + "/data/add-ons", options.addons, d)
yaml.safe_dump(batchlist, open(filename, "w"),
encoding = "utf-8", default_flow_style = False)
encoding="utf-8", default_flow_style=False)
def process_campaign_or_era(addon, cid, define, batchlist):
n = 0
print(str(addon) + ": " + str(cid) + " " + str(define))
if not define:
@ -365,10 +383,10 @@ def process_campaign_or_era(addon, cid, define, batchlist):
options.transdir)
wesnoth.batchlist = batchlist
wesnoth.cid = cid
wesnoth.parser.parse_text("{core/units.cfg}", "NORMAL")
wesnoth.add_units("mainline")
if define == "MULTIPLAYER":
wesnoth.parser.parse_text("{core}{multiplayer}{multiplayer/eras.cfg}{~add-ons}", "MULTIPLAYER,SKIP_CORE")
wesnoth.add_units(cid)
@ -380,19 +398,19 @@ def process_campaign_or_era(addon, cid, define, batchlist):
else:
wesnoth.parser.parse_text("{core}{~add-ons}", "SKIP_CORE," + define)
wesnoth.add_units(cid)
if addon == "mainline" and cid == "mainline":
write_animation_statistics(wesnoth)
wesnoth.add_binary_paths(addon, image_collector)
if define == "MULTIPLAYER":
eras = wesnoth.parser.get_all(tag = "era")
eras = wesnoth.parser.get_all(tag="era")
for era in eras:
wesnoth.add_era(era)
wesnoth.find_unit_factions()
else:
campaigns = wesnoth.parser.get_all(tag = "campaign")
campaigns = wesnoth.parser.get_all(tag="campaign")
for campaign in campaigns:
wesnoth.add_campaign(campaign)
@ -401,9 +419,8 @@ def process_campaign_or_era(addon, cid, define, batchlist):
wesnoth.check_units()
for isocode in languages:
if addon != "mainline" and isocode != "en_US": continue
if addon != "mainline" and isocode != "en_US":
continue
if define == "MULTIPLAYER":
for era in list(wesnoth.era_lookup.values()):
if era.get_text_val("id") == cid:
@ -417,7 +434,6 @@ def process_campaign_or_era(addon, cid, define, batchlist):
if campaign.get_text_val("id") == cid:
n = html_output.generate_campaign_report(addon, isocode, campaign, wesnoth)
break
html_output.generate_single_unit_reports(addon, isocode, wesnoth)
return n
@ -428,12 +444,13 @@ def batch_process():
for addon in batchlist:
name = addon["name"]
set_dependencies(name, addon.get("dependencies", []))
for addon in batchlist:
name = addon["name"]
if not options.reparse and addon.get("parsed", False) == True: continue
if not options.reparse and addon.get("parsed", False) == True:
continue
if name == "mainline":
worked = True
else:
@ -441,22 +458,24 @@ def batch_process():
for d in addon.get("dependencies", []):
move(options.addons, options.config_dir + "/data/add-ons", d)
d = options.output + "/" + name
try: os.makedirs(d)
except OSError: pass
try:
os.makedirs(d)
except OSError:
pass
logname = d + "/error.log"
def err(mess):
ef = open(logname, "a")
ef.write(str(mess))
ef.close()
html_output.write_error = err
try:
if not worked:
print((name + " not found"))
print(name + " not found")
continue
for era in addon.get("eras", []):
eid = era["id"]
n = process_campaign_or_era(name, eid, era["define"], batchlist)
@ -464,21 +483,23 @@ def batch_process():
for campaign in addon.get("campaigns", []):
cid = campaign["id"]
if cid == None: cid = campaign["define"]
if cid == None: cid = name
if cid is None:
cid = campaign["define"]
if cid is None:
cid = name
n = process_campaign_or_era(name, cid, campaign["define"], batchlist)
campaign["units"] = n
except wmlparser3.WMLError as e:
ef = open(logname, "a")
ef.write("<WML ERROR>\n")
ef.write(str(e))
ef.write("</WML ERROR>\n")
ef.close()
print((" " + name + " failed"))
print(" " + name + " failed")
except Exception as e:
traceback.print_exc()
print((" " + name + " failed"))
print(" " + name + " failed")
ef = open(logname, "a")
ef.write("<INTERNAL ERROR>\n")
ef.write("please report as bug\n")
@ -490,15 +511,15 @@ def batch_process():
move(options.config_dir + "/data/add-ons", options.addons, name)
for d in addon.get("dependencies", []):
move(options.config_dir + "/data/add-ons", options.addons, d)
addon["parsed"] = True
yaml.safe_dump(batchlist, open(options.batch, "w"),
encoding = "utf-8", default_flow_style = False)
encoding="utf-8", default_flow_style=False)
try:
unit_tree.overview.write_addon_overview(os.path.join(options.output,
name), addon)
unit_tree.overview.write_addon_overview(
os.path.join(options.output, name), addon)
except Exception as e:
pass
@ -509,8 +530,9 @@ def write_unit_ids_UNUSED():
uids = list(wesnoth.unit_lookup.keys())
def by_race(u1, u2):
r = cmp(wesnoth.unit_lookup[u1].rid,
wesnoth.unit_lookup[u2].rid)
if r == 0: r = cmp(u1, u2)
wesnoth.unit_lookup[u2].rid)
if r == 0:
r = cmp(u1, u2)
return r
uids.sort(by_race)
race = None
@ -519,7 +541,8 @@ def write_unit_ids_UNUSED():
for uid in uids:
u = wesnoth.unit_lookup[uid]
if u.rid != race:
if race != None: f.write("</ul>")
if race is not None:
f.write("</ul>")
f.write("<p>%s</p>\n" % (u.rid,))
f.write("<ul>")
race = u.rid
@ -535,7 +558,6 @@ def write_animation_statistics(wesnoth):
f.close()
if __name__ == '__main__':
# We change the process name to "wmlunits"
try:
import ctypes
@ -549,41 +571,41 @@ if __name__ == '__main__':
ap = argparse.ArgumentParser()
ap.add_argument("-C", "--config-dir",
help="Specify the user configuration dir (wesnoth --config-path).")
help="Specify the user configuration dir (wesnoth --config-path).")
ap.add_argument("-D", "--data-dir",
help="Specify the wesnoth data dir (wesnoth --path).")
help="Specify the wesnoth data dir (wesnoth --path).")
ap.add_argument("-l", "--language", default="all",
help="Specify a language to use. Else output is produced for all languages.")
help="Specify a language to use. Else output is produced for all languages.")
ap.add_argument("-o", "--output",
help="Specify the output directory.")
help="Specify the output directory.")
ap.add_argument("-n", "--nocopy", action="store_true",
help="No copying of files. By default all images are copied to the output dir.")
help="No copying of files. By default all images are copied to the output dir.")
ap.add_argument("-w", "--wesnoth",
help="Specify the wesnoth executable to use. Whatever data " +
"and config paths that executable is configured for will be " +
"used to find game files and addons.")
help="Specify the wesnoth executable to use. Whatever data " +
"and config paths that executable is configured for will be " +
"used to find game files and addons.")
ap.add_argument("-t", "--transdir",
help="Specify the directory with gettext message catalogues. " +
"Defaults to ./translations.", default="translations")
help="Specify the directory with gettext message catalogues. " +
"Defaults to ./translations.", default="translations")
ap.add_argument("-T", "--timeout",
help="Use the timeout iven in seconds when parsing WML, default is 20 " +
"seconds.")
help="Use the timeout iven in seconds when parsing WML, default is 20 " +
"seconds.")
ap.add_argument("-r", "--reparse", action="store_true",
help="Reparse everything.")
help="Reparse everything.")
ap.add_argument("-a", "--addons",
help="Specify path to a folder with all addons. This should be " +
"outside the user config folder.")
help="Specify path to a folder with all addons. This should be " +
"outside the user config folder.")
ap.add_argument("-L", "--list",
help = "List available eras and campaigns.")
help="List available eras and campaigns.")
ap.add_argument("-B", "--batch",
help = "Batch process the given list.")
ap.add_argument("-A", "--addons-only", action = "store_true",
help = "Do only process addons (for debugging).")
ap.add_argument("-v", "--verbose", action = "store_true")
ap.add_argument("-W", "--wiki", action = "store_true",
help = "write wikified units list to stdout")
help="Batch process the given list.")
ap.add_argument("-A", "--addons-only", action="store_true",
help="Do only process addons (for debugging).")
ap.add_argument("-v", "--verbose", action="store_true")
ap.add_argument("-W", "--wiki", action="store_true",
help="write wikified units list to stdout")
options = ap.parse_args()
html_output.options = options
helpers.options = options
unit_tree.overview.options = options
@ -605,27 +627,29 @@ if __name__ == '__main__':
if not options.data_dir:
options.data_dir = shell_out([options.wesnoth, "--path"]).strip().decode("utf8")
print(("Using " + options.data_dir + " as data dir."))
print("Using " + options.data_dir + " as data dir.")
if not options.config_dir:
options.config_dir = shell_out([options.wesnoth, "--config-path"]).strip().decode("utf8")
print(("Using " + options.config_dir + " as config dir."))
print("Using " + options.config_dir + " as config dir.")
if not options.transdir:
options.transdir = os.getcwd()
if options.wiki:
wiki_output.main()
sys.exit(0)
image_collector = helpers.ImageCollector(options.wesnoth,
options.config_dir, options.data_dir)
options.config_dir,
options.data_dir)
html_output.image_collector = image_collector
if options.language == "all":
languages = []
parser = wmlparser3.Parser(options.wesnoth, options.config_dir,
options.data_dir)
parser = wmlparser3.Parser(options.wesnoth,
options.config_dir,
options.data_dir)
parser.parse_text("{languages}")
for locale in parser.get_all(tag="locale"):
@ -641,22 +665,21 @@ if __name__ == '__main__':
if not options.list and not options.batch:
sys.stderr.write("Need --list or --batch (or both).\n")
sys.exit(-1)
if options.output:
# Generate output dir.
if not os.path.isdir(options.output):
os.mkdir(options.output)
if options.list:
list_contents()
if options.batch:
batch_process()
unit_tree.overview.main(options.output)
if not options.nocopy:
copy_images()
html_output.write_index(options.output)
html_output.write_index(options.output)