Commits

rkruppe  committed 05a71a1

Rename tools/ to bin/ and make scripts executable

  • Participants
  • Parent commits b4033d1

Comments (0)

Files changed (10)

File bin/change-id.py

+#!/usr/bin/env python3.3
+"""
+Load a serialized file, change the ID of some object, then serialize it again.
+Has no semantic impact, but it's an quick way to change an object_id.
+Makes a backup in the same directory by default.
+"""
+import sys
+import argparse
+import ttgx.toolutil as toolutil
+from ttgx.meta import validate
+
+parser = argparse.ArgumentParser(
+    description=__doc__
+)
+parser.add_argument('cls', help='The class stored in the file, '
+                                'including full module path')
+parser.add_argument('file', help='File to manipulate')
+parser.add_argument('oldid', help='old ID of object')
+parser.add_argument('newid', help='new ID of object')
+parser.add_argument('-x', '--inplace', help='Do not make a backup (*.bak)',
+                    dest='backup', action='store_false', default=True)
+
+
+def main():
+    args = parser.parse_args()
+    cls = toolutil.load_cls(args.cls)
+    if args.backup:
+        toolutil.backup(args.file)
+    objs, rctx, vctx = toolutil.load_with_context(cls, args.file)
+    if vctx.errors:
+        err_lines = validate.format_errors(vctx.errors)
+        print("VALIDATION FAILURE:")
+        print(*err_lines, sep='\n')
+        sys.exit(1)
+    try:
+        subobj = ctx.objects[args.oldid]
+    except KeyError:
+        print("No object with ID", repr(args.oldid))
+        sys.exit(2)
+    subobj.object_id = args.newid
+    toolutil.store(objs, args.file)
+
+if __name__ == '__main__':
+    main()
+

File bin/norm-yaml.py

+#!/usr/bin/env python3.3
+"""
+Load a serialized file, then serialize it again.
+Has no semantic impact, but it checks the file for errors andnormalizes
+formatting, indentation, dictionary key order, etc.
+Makes a backup in the same directory by default.
+"""
+import sys
+import argparse
+import shutil
+from ttgx.meta import to_yaml, from_yaml
+import ttgx.toolutil as toolutil
+
+parser = argparse.ArgumentParser(
+    description=__doc__
+)
+parser.add_argument('cls', help='The class stored in the file, '
+                                'including full module path')
+parser.add_argument('file', help='File to normalize')
+parser.add_argument('-x', '--inplace', help='Do not make a backup (*.bak)',
+                    dest='backup', action='store_false', default=True)
+
+
+def main():
+    args = parser.parse_args()
+    cls = toolutil.load_cls(args.cls)
+    objs = toolutil.load_and_exit_if_invalid(cls, args.file, exitcode=1)
+    if args.backup:
+        toolutil.backup(args.file)
+    toolutil.store(objs, args.file)
+
+if __name__ == '__main__':
+    main()
+

File bin/profile.py

+#!/usr/bin/env python3.3
+# Really quick & dirty script to automate some profiling steps
+import sys
+import os
+import subprocess
+import pstats
+import contextlib
+
+
+def write_stats(path, sort, output_filter, output=pstats.Stats.print_stats):
+    with open(path, 'w') as f:
+        st = pstats.Stats('ttg.prof', stream=f)
+        output(st.sort_stats(sort), output_filter)
+
+
+def main():
+    tool_dir = os.path.basename(os.path.normpath(__file__))
+    game_home = os.path.abspath(os.path.join(tool_dir, os.pardir))
+    subprocess.call([
+        'python', '-m', 'cProfile', '-o', 'ttgx.prof',
+        os.path.join(game_home, 'ttgx', 'demo.py'),
+        '--game-home', game_home
+    ])
+
+    write_stats('prof-full-time.txt', 'cumulative', '.*')
+    write_stats('prof-full-calls.txt', 'calls', '.*')
+    write_stats('prof-ttg-time.txt', 'cumulative', '^ttgx')
+    write_stats('prof-ttg-calls.txt', 'calls', '^ttgx')
+    write_stats(
+        'prof-ttg-callers.txt', 'cumulative', '^ttgx',
+        pstats.Stats.print_callers
+    )
+    write_stats(
+        'prof-full-callers.txt', 'cumulative', '.*',
+        pstats.Stats.print_callers
+    )
+
+if __name__ == '__main__':
+    main()
+

File bin/update-encoding.py

+#!/usr/bin/env python3.3
+"""
+Tool to automatically overcome changes in serialization format of models.
+Translates from old serialization output to new serialization input, thus
+removing the need to keep the parser backwards-compatible.
+It works like this:
+
+- Check out a given older revision (one before the changes)
+- Create a script decoding and pickling the data
+- Run said script with the old revision in its PYTHONPATH (so it can decode)
+- Create a script unpickling and decoding the data
+- Run said script with the current revision in its PYTHONPATH (so it uses the
+  up-to-date encoding)
+
+While this isn't perfect and breaks for (most) changes in the models,
+it should catch pretty much all serialization details.
+"""
+import sys
+import os
+import tempfile
+import subprocess
+import argparse
+
+
+# allow pickling instance methods
+# source: http://stackoverflow.com/q/6583326/395760
+BOILERPLATE = '''
+import copyreg
+import types
+
+def _pickle_method(method):
+    func_name = method.__func__.__name__
+    obj = method.__self__
+    cls = method.__self__.__class__
+    return _unpickle_method, (func_name, obj, cls)
+
+def _unpickle_method(func_name, obj, cls):
+    for cls in cls.mro():
+        try:
+            func = cls.__dict__[func_name]
+        except KeyError:
+            pass
+        else:
+            break
+    return func.__get__(obj, cls)
+
+copyreg.pickle(types.MethodType, _pickle_method, _unpickle_method)
+# XXX Also make pickle find that <type 'method'> in builtins
+# HACK HACK HACK!
+import builtins
+builtins.method = types.MethodType
+
+# also silence logging output
+import logging
+logging.basicConfig(level=logging.ERROR)
+'''
+
+DECODE_SOURCE = BOILERPLATE + '''
+from ttgx.toolutil import load
+import {cls_module} as clsmod
+import pickle
+
+print("Reading old data from", {infile!r})
+objs = load(clsmod.{cls}, {infile!r})
+with open({storage!r}, 'wb') as f:
+    print("Pickling loaded data to", {storage!r})
+    pickle.dump(objs, f)
+'''
+
+ENCODE_SOURCE = BOILERPLATE + '''
+from ttgx.toolutil import store
+import {cls_module} as clsmod
+import pickle
+import os
+
+with open({storage!r}, 'rb') as f:
+    print("Unpickling", {storage!r})
+    objs = pickle.load(f)
+print("Writing re-encoded data to", {outfile!r})
+store(objs, {outfile!r})
+'''
+
+parser = argparse.ArgumentParser(description='Re-encode Tutagx model data')
+parser.add_argument('cls',
+                    help='The class stored in the file, '
+                    'including full module path')
+parser.add_argument('rev', help='Hg revision to use for reading')
+parser.add_argument('infile', help='File to re-encode')
+parser.add_argument('outfile', nargs='?',
+                    help='File to store re-encoded data in '
+                    '(defaults to infile)', default=None)
+
+
+def parse_args():
+    args = parser.parse_args()
+    args.infile = os.path.abspath(args.infile)
+    if args.outfile is None:
+        args.outfile = args.infile
+    else:
+        args.outfile = os.path.abspath(args.outfile)
+    cls_parts = args.cls.split('.')
+    args.cls_module = '.'.join(cls_parts[:-1])
+    args.cls = cls_parts[-1]
+    return args
+
+
+def hg_clone(dest, rev):
+    assert os.path.isabs(dest)
+    print("Cloning to", dest, 'at revision', repr(rev))
+    subprocess.call(['hg', 'clone', '-u', rev, '.', dest])
+
+
+def invoke_decode(args, hg_dir, storage):
+    print("Pickling decoded data to", storage)
+    # modify PYTHONPATH for old version
+    child_env = dict(os.environ)
+    child_env['PYTHONPATH'] = hg_dir
+    with tempfile.NamedTemporaryFile('w') as decode_script:
+        decode_script.write(DECODE_SOURCE.format(
+            cls_module=args.cls_module,
+            cls=args.cls,
+            infile=args.infile,
+            storage=storage,
+        ))
+        decode_script.flush()
+        e = subprocess.call(['python', decode_script.name], env=child_env)
+        if e:
+            sys.exit(1)
+
+
+def invoke_reencode(args, hg_dir, storage):
+    print("Unpickling decoded data from", storage)
+    with tempfile.NamedTemporaryFile('w') as encode_script:
+        encode_script.write(ENCODE_SOURCE.format(
+            cls_module=args.cls_module,
+            cls=args.cls,
+            storage=storage,
+            outfile=args.outfile
+        ))
+        encode_script.flush()
+        e = subprocess.call(['python', encode_script.name])
+        if e:
+            sys.exit(1)
+
+
+def translate_encoding(args, hg_dir):
+    tmp_file = tempfile.NamedTemporaryFile(delete=False)
+    tmp_file_path = tmp_file.name
+    assert os.path.isabs(tmp_file_path)
+    try:
+        invoke_decode(args, hg_dir, tmp_file_path)
+        invoke_reencode(args, hg_dir, tmp_file_path)
+    finally:
+        tmp_file.close()
+        os.remove(tmp_file_path)
+
+
+def main():
+    args = parse_args()
+    with tempfile.TemporaryDirectory(prefix='ttgx-hg-clone') as hg_dir:
+        hg_clone(hg_dir, args.rev)
+        translate_encoding(args, hg_dir)
+
+if __name__ == '__main__':
+    main()
+

File bin/verify.py

+#!/usr/bin/env python3.3
+"""
+Attempt to load a serialized file and report errors.
+"""
+import sys
+import argparse
+import ttgx.toolutil as toolutil
+from ttgx.meta import validate
+
+parser = argparse.ArgumentParser(
+    description=__doc__
+)
+parser.add_argument('cls', help='The class stored in the file, '
+                                'including full module path')
+parser.add_argument('file', help='File to check')
+
+
+def main():
+    # This resembles parts of toolutil, but it's necessary as we need
+    # additional logic, such as still giving output if an error occurs in
+    # later steps.
+    args = parser.parse_args()
+    cls = toolutil.load_cls(args.cls)
+    obj, rctx, vctx = toolutil.load_with_context(cls, args.file)
+    err_lines = validate.format_errors(vctx.errors)
+    if err_lines:
+        print(*err_lines, sep='\n')
+        sys.exit(1)
+    else:
+        print("Nothing wrong")
+
+if __name__ == '__main__':
+    main()
+

File tools/change-id.py

-"""
-Load a serialized file, change the ID of some object, then serialize it again.
-Has no semantic impact, but it's an quick way to change an object_id.
-Makes a backup in the same directory by default.
-"""
-import sys
-import argparse
-import ttgx.toolutil as toolutil
-from ttgx.meta import validate
-
-parser = argparse.ArgumentParser(
-    description=__doc__
-)
-parser.add_argument('cls', help='The class stored in the file, '
-                                'including full module path')
-parser.add_argument('file', help='File to manipulate')
-parser.add_argument('oldid', help='old ID of object')
-parser.add_argument('newid', help='new ID of object')
-parser.add_argument('-x', '--inplace', help='Do not make a backup (*.bak)',
-                    dest='backup', action='store_false', default=True)
-
-
-def main():
-    args = parser.parse_args()
-    cls = toolutil.load_cls(args.cls)
-    if args.backup:
-        toolutil.backup(args.file)
-    objs, rctx, vctx = toolutil.load_with_context(cls, args.file)
-    if vctx.errors:
-        err_lines = validate.format_errors(vctx.errors)
-        print("VALIDATION FAILURE:")
-        print(*err_lines, sep='\n')
-        sys.exit(1)
-    try:
-        subobj = ctx.objects[args.oldid]
-    except KeyError:
-        print("No object with ID", repr(args.oldid))
-        sys.exit(2)
-    subobj.object_id = args.newid
-    toolutil.store(objs, args.file)
-
-if __name__ == '__main__':
-    main()
-

File tools/norm-yaml.py

-"""
-Load a serialized file, then serialize it again.
-Has no semantic impact, but it checks the file for errors andnormalizes
-formatting, indentation, dictionary key order, etc.
-Makes a backup in the same directory by default.
-"""
-import sys
-import argparse
-import shutil
-from ttgx.meta import to_yaml, from_yaml
-import ttgx.toolutil as toolutil
-
-parser = argparse.ArgumentParser(
-    description=__doc__
-)
-parser.add_argument('cls', help='The class stored in the file, '
-                                'including full module path')
-parser.add_argument('file', help='File to normalize')
-parser.add_argument('-x', '--inplace', help='Do not make a backup (*.bak)',
-                    dest='backup', action='store_false', default=True)
-
-
-def main():
-    args = parser.parse_args()
-    cls = toolutil.load_cls(args.cls)
-    objs = toolutil.load_and_exit_if_invalid(cls, args.file, exitcode=1)
-    if args.backup:
-        toolutil.backup(args.file)
-    toolutil.store(objs, args.file)
-
-if __name__ == '__main__':
-    main()
-

File tools/profile.py

-# Really quick & dirty script to automate some profiling steps
-import sys
-import os
-import subprocess
-import pstats
-import contextlib
-
-
-def write_stats(path, sort, output_filter, output=pstats.Stats.print_stats):
-    with open(path, 'w') as f:
-        st = pstats.Stats('ttg.prof', stream=f)
-        output(st.sort_stats(sort), output_filter)
-
-
-def main():
-    tool_dir = os.path.basename(os.path.normpath(__file__))
-    game_home = os.path.abspath(os.path.join(tool_dir, os.pardir))
-    subprocess.call([
-        'python', '-m', 'cProfile', '-o', 'ttgx.prof',
-        os.path.join(game_home, 'ttgx', 'demo.py'),
-        '--game-home', game_home
-    ])
-
-    write_stats('prof-full-time.txt', 'cumulative', '.*')
-    write_stats('prof-full-calls.txt', 'calls', '.*')
-    write_stats('prof-ttg-time.txt', 'cumulative', '^ttgx')
-    write_stats('prof-ttg-calls.txt', 'calls', '^ttgx')
-    write_stats(
-        'prof-ttg-callers.txt', 'cumulative', '^ttgx',
-        pstats.Stats.print_callers
-    )
-    write_stats(
-        'prof-full-callers.txt', 'cumulative', '.*',
-        pstats.Stats.print_callers
-    )
-
-if __name__ == '__main__':
-    main()
-

File tools/update-encoding.py

-"""
-Tool to automatically overcome changes in serialization format of models.
-Translates from old serialization output to new serialization input, thus
-removing the need to keep the parser backwards-compatible.
-It works like this:
-
-- Check out a given older revision (one before the changes)
-- Create a script decoding and pickling the data
-- Run said script with the old revision in its PYTHONPATH (so it can decode)
-- Create a script unpickling and decoding the data
-- Run said script with the current revision in its PYTHONPATH (so it uses the
-  up-to-date encoding)
-
-While this isn't perfect and breaks for (most) changes in the models,
-it should catch pretty much all serialization details.
-"""
-import sys
-import os
-import tempfile
-import subprocess
-import argparse
-
-
-# allow pickling instance methods
-# source: http://stackoverflow.com/q/6583326/395760
-BOILERPLATE = '''
-import copyreg
-import types
-
-def _pickle_method(method):
-    func_name = method.__func__.__name__
-    obj = method.__self__
-    cls = method.__self__.__class__
-    return _unpickle_method, (func_name, obj, cls)
-
-def _unpickle_method(func_name, obj, cls):
-    for cls in cls.mro():
-        try:
-            func = cls.__dict__[func_name]
-        except KeyError:
-            pass
-        else:
-            break
-    return func.__get__(obj, cls)
-
-copyreg.pickle(types.MethodType, _pickle_method, _unpickle_method)
-# XXX Also make pickle find that <type 'method'> in builtins
-# HACK HACK HACK!
-import builtins
-builtins.method = types.MethodType
-
-# also silence logging output
-import logging
-logging.basicConfig(level=logging.ERROR)
-'''
-
-DECODE_SOURCE = BOILERPLATE + '''
-from ttgx.toolutil import load
-import {cls_module} as clsmod
-import pickle
-
-print("Reading old data from", {infile!r})
-objs = load(clsmod.{cls}, {infile!r})
-with open({storage!r}, 'wb') as f:
-    print("Pickling loaded data to", {storage!r})
-    pickle.dump(objs, f)
-'''
-
-ENCODE_SOURCE = BOILERPLATE + '''
-from ttgx.toolutil import store
-import {cls_module} as clsmod
-import pickle
-import os
-
-with open({storage!r}, 'rb') as f:
-    print("Unpickling", {storage!r})
-    objs = pickle.load(f)
-print("Writing re-encoded data to", {outfile!r})
-store(objs, {outfile!r})
-'''
-
-parser = argparse.ArgumentParser(description='Re-encode Tutagx model data')
-parser.add_argument('cls',
-                    help='The class stored in the file, '
-                    'including full module path')
-parser.add_argument('rev', help='Hg revision to use for reading')
-parser.add_argument('infile', help='File to re-encode')
-parser.add_argument('outfile', nargs='?',
-                    help='File to store re-encoded data in '
-                    '(defaults to infile)', default=None)
-
-
-def parse_args():
-    args = parser.parse_args()
-    args.infile = os.path.abspath(args.infile)
-    if args.outfile is None:
-        args.outfile = args.infile
-    else:
-        args.outfile = os.path.abspath(args.outfile)
-    cls_parts = args.cls.split('.')
-    args.cls_module = '.'.join(cls_parts[:-1])
-    args.cls = cls_parts[-1]
-    return args
-
-
-def hg_clone(dest, rev):
-    assert os.path.isabs(dest)
-    print("Cloning to", dest, 'at revision', repr(rev))
-    subprocess.call(['hg', 'clone', '-u', rev, '.', dest])
-
-
-def invoke_decode(args, hg_dir, storage):
-    print("Pickling decoded data to", storage)
-    # modify PYTHONPATH for old version
-    child_env = dict(os.environ)
-    child_env['PYTHONPATH'] = hg_dir
-    with tempfile.NamedTemporaryFile('w') as decode_script:
-        decode_script.write(DECODE_SOURCE.format(
-            cls_module=args.cls_module,
-            cls=args.cls,
-            infile=args.infile,
-            storage=storage,
-        ))
-        decode_script.flush()
-        e = subprocess.call(['python', decode_script.name], env=child_env)
-        if e:
-            sys.exit(1)
-
-
-def invoke_reencode(args, hg_dir, storage):
-    print("Unpickling decoded data from", storage)
-    with tempfile.NamedTemporaryFile('w') as encode_script:
-        encode_script.write(ENCODE_SOURCE.format(
-            cls_module=args.cls_module,
-            cls=args.cls,
-            storage=storage,
-            outfile=args.outfile
-        ))
-        encode_script.flush()
-        e = subprocess.call(['python', encode_script.name])
-        if e:
-            sys.exit(1)
-
-
-def translate_encoding(args, hg_dir):
-    tmp_file = tempfile.NamedTemporaryFile(delete=False)
-    tmp_file_path = tmp_file.name
-    assert os.path.isabs(tmp_file_path)
-    try:
-        invoke_decode(args, hg_dir, tmp_file_path)
-        invoke_reencode(args, hg_dir, tmp_file_path)
-    finally:
-        tmp_file.close()
-        os.remove(tmp_file_path)
-
-
-def main():
-    args = parse_args()
-    with tempfile.TemporaryDirectory(prefix='ttgx-hg-clone') as hg_dir:
-        hg_clone(hg_dir, args.rev)
-        translate_encoding(args, hg_dir)
-
-if __name__ == '__main__':
-    main()
-

File tools/verify.py

-"""
-Attempt to load a serialized file and report errors.
-"""
-import sys
-import argparse
-import ttgx.toolutil as toolutil
-from ttgx.meta import validate
-
-parser = argparse.ArgumentParser(
-    description=__doc__
-)
-parser.add_argument('cls', help='The class stored in the file, '
-                                'including full module path')
-parser.add_argument('file', help='File to check')
-
-
-def main():
-    # This resembles parts of toolutil, but it's necessary as we need
-    # additional logic, such as still giving output if an error occurs in
-    # later steps.
-    args = parser.parse_args()
-    cls = toolutil.load_cls(args.cls)
-    obj, rctx, vctx = toolutil.load_with_context(cls, args.file)
-    err_lines = validate.format_errors(vctx.errors)
-    if err_lines:
-        print(*err_lines, sep='\n')
-        sys.exit(1)
-    else:
-        print("Nothing wrong")
-
-if __name__ == '__main__':
-    main()
-