From: Mark Wooding Date: Fri, 4 Oct 2019 14:43:27 +0000 (+0100) Subject: math/mpgen, symm/multigen: Fix the various build scripts for Python 3. X-Git-Tag: 2.6.0~43 X-Git-Url: https://git.distorted.org.uk/~mdw/catacomb/commitdiff_plain/b8dc834f00b9f209062a4b2982b5a4a92dc76de4 math/mpgen, symm/multigen: Fix the various build scripts for Python 3. * Put parentheses around `print' arguments. * Write `raise EXC(VALUE)' rather than `raise EXC, VALUE' to raise exceptions. * Cope with `xrange' being renamed to `range' in Python 3. * Cope with `long' not being a type name in Python 3. * Cope with `execfile' not being available in Python 3. * Cope with function-object attribute names being renamed in Python 3. * Cope with `StringIO' being in `io' rather than `cStringIO' in Python 3, and with `StringIO.reset' not being available any more. * Cope with `itertools.izip' not being available in Python 3. * Cope with `OBJ.next' not being available in Python 3. * Use an unpleasant hack to inject metaclasses, because the official syntax is so different between the two versions. --- diff --git a/math/mpgen b/math/mpgen index 7d11bfda..c7dbf889 100644 --- a/math/mpgen +++ b/math/mpgen @@ -28,10 +28,9 @@ from __future__ import with_statement import re as RX import optparse as OP +import sys as SYS; stdout = SYS.stdout import types as TY -from sys import stdout - ###-------------------------------------------------------------------------- ### Random utilities. @@ -65,6 +64,22 @@ def fix_name(name): """Replace non-alphanumeric characters in NAME with underscores.""" return R_IDBAD.sub('_', name) +if SYS.version_info >= (3,): + def func_name(func): return func.__name__ + xrange = range + long = int +else: + def func_name(func): return func.func_name + +def with_metaclass(meta, *supers): + return meta('#' % meta.__name__, + supers or (object,), dict()) + +def load(file, mod): + with open(file) as f: text = f.read() + code = compile(text, file, 'exec') + exec(code, mod) + ###-------------------------------------------------------------------------- ### Determining the appropriate types. @@ -83,7 +98,7 @@ class IntClass (type): except AttributeError: pass return c -class BasicIntType (object): +class BasicIntType (with_metaclass(IntClass)): """ A base class for integer-type classes, providing defaults and protocol. @@ -195,7 +210,7 @@ class TypeChoice (object): ## Load the captured type information. me.ti = TY.ModuleType('typeinfo') - execfile(opts.typeinfo, me.ti.__dict__) + load(opts.typeinfo, me.ti.__dict__) ## Build a map of the available types. tymap = {} @@ -226,14 +241,14 @@ class TypeChoice (object): ## Make sure we've not ended up somewhere really silly. if mpwbits < 16: - raise Exception, "`mpw' type is too small: your C environment is weird" + raise Exception("`mpw' type is too small: your C environment is weird") ## Now figure out suitable types for `mpw' and `mpd'. def find_type(bits, what): for ty in byrank: if ty.bits >= bits: return ty - raise Exception, \ - "failed to find suitable %d-bit type, for %s" % (bits, what) + raise Exception \ + ("failed to find suitable %d-bit type, for %s" % (bits, what)) ## Store our decisions. me.mpwbits = mpwbits @@ -327,7 +342,7 @@ def defmode(func): arguments from the command and are expected to write their output to stdout. """ - name = func.func_name + name = func_name(func) if name.startswith('m_'): name = name[2:] MODEMAP[name] = func return func @@ -483,7 +498,7 @@ class GroupTableClass (type): else: MODEMAP[c.mode] = c.run return c -class GroupTable (object): +class GroupTable (with_metaclass(GroupTableClass)): """ Base class for group tables objects. @@ -568,8 +583,6 @@ class GroupTable (object): ## _slotmap A dictionary mapping slot names to their ## descriptions. - __metaclass__ = GroupTableClass - ## Default values. keyword = 'group' slots = [] @@ -644,7 +657,7 @@ class GroupTable (object): if ff[0] == 'alias': ## An alias. Just remember this. - if len(ff) != 3: raise Exception, "wrong number of alias arguments" + if len(ff) != 3: raise Exception("wrong number of alias arguments") me._flush() me._names.append((ff[1], ff[2])) @@ -654,7 +667,7 @@ class GroupTable (object): ## Check the headline syntax. Headline slots may be set here, or ## later by name. if len(ff) < 2 or len(ff) > 2 + len(me._headslots): - raise Exception, "bad number of headline arguments" + raise Exception("bad number of headline arguments") ## Flush out the previous stanza. me._flush() @@ -670,14 +683,14 @@ class GroupTable (object): elif ff[0] in me._slotmap: ## A slot assignment. Get the slot to store a value. if me.st.name is None: - raise Exception, "no group currently being defined" + raise Exception("no group currently being defined") if len(ff) != 2: - raise Exception, "bad number of values for slot `%s'" % ff[0] + raise Exception("bad number of values for slot `%s'" % ff[0]) me._slotmap[ff[0]].set(me.st, ff[1]) else: ## Something incomprehensible. - raise Exception, "unknown keyword `%s'" % ff[0] + raise Exception("unknown keyword `%s'" % ff[0]) ## End of the input. Write out the final stanza. me._flush() @@ -687,7 +700,7 @@ class GroupTable (object): stdout.write("\nconst %s %s[] = {\n" % (me.entry_t, me.tabname)) for a, n in me._names: if n not in me._defs: - raise Exception, "alias `%s' refers to unknown group `%s'" % (a, n) + raise Exception("alias `%s' refers to unknown group `%s'" % (a, n)) stdout.write(' { "%s", &c_%s },\n' % (a, fix_name(n))) stdout.write(" { 0, 0 }\n};\n\n") @@ -747,7 +760,7 @@ class BaseSlot (object): Store a VALUE for the slot. """ if me._allowp and not me._allowp(st, value): - raise Exception, "slot `%s' not allowed here" % me.name + raise Exception("slot `%s' not allowed here" % me.name) st.d[me] = value def setup(me, st): @@ -755,7 +768,7 @@ class BaseSlot (object): Prepare the slot for output, checking its value and so on. """ if me not in st.d and (not me._omitp or not me._omitp(st)): - raise Exception, "missing slot `%s'" % me.name + raise Exception("missing slot `%s'" % me.name) class EnumSlot (BaseSlot): """ @@ -781,7 +794,7 @@ class EnumSlot (BaseSlot): Check that the VALUE is one of the ones we know. """ if value not in me._values: - raise Exception, "invalid %s value `%s'" % (me.name, value) + raise Exception("invalid %s value `%s'" % (me.name, value)) super(EnumSlot, me).set(st, value) def write(me, st): diff --git a/symm/multigen b/symm/multigen index 4115eb41..8af0f108 100755 --- a/symm/multigen +++ b/symm/multigen @@ -30,7 +30,9 @@ import itertools as IT import optparse as OP import os as OS import re as RX -from cStringIO import StringIO +import sys as SYS +if SYS.version_info >= (3,): from io import StringIO +else: from cStringIO import StringIO from sys import argv, exit, stderr ###-------------------------------------------------------------------------- @@ -49,6 +51,16 @@ def indexed(seq): """ return IT.izip(IT.count(), seq) +if SYS.version_info >= (3,): + def func_name(func): return func.__name__ + IT.izip = zip +else: + def func_name(func): return func.func_name + +try: next +except NameError: + def next(obj): return obj.next() + ###-------------------------------------------------------------------------- ### Reading the input values. @@ -461,7 +473,7 @@ class ParseState (object): Sets `curr' to the next line, or to None if the input is exhausted. """ - try: me.curr = me._it.next() + try: me.curr = next(me._it) except StopIteration: me.curr = None else: me._i += 1 @@ -504,7 +516,7 @@ def defop(func): An operator function is given the raw value as an argument and should return the transformed value. """ - name = func.func_name + name = func_name(func) if name.startswith('op_'): name = name[3:] OPMAP[name] = func return func @@ -576,7 +588,7 @@ def parse_text(ps): ## object. l = lit.getvalue() if l: tt.append(LiteralTemplate(l)) - lit.reset() + lit.seek(0) lit.truncate() ## Iterate over the lines of input. @@ -786,7 +798,7 @@ def filenames(filetempl): ## Main dispatch. if opts.mode == 'list': - for file, cs in filenames(filetempl): print file + for file, cs in filenames(filetempl): print(file) elif opts.mode == 'gen': with open(opts.input) as f: templ = RepeatTemplate(compile_template(opts.input, f.read()))