def generate(specPath):
    spec = amqp_codegen.AmqpSpec(specPath)

    def genSingleDecode(prefix, cLvalue, unresolved_domain):
        type = spec.resolveDomain(unresolved_domain)
        if type == 'shortstr':
            print(prefix + "%s, offset = data.decode_short_string(encoded, offset)" % cLvalue)
        elif type == 'longstr':
            print(prefix +
                  "length = struct.unpack_from('>I', encoded, offset)[0]")
            print(prefix + "offset += 4")
            print(prefix + "%s = encoded[offset:offset + length]" % cLvalue)
            print(prefix + "try:")
            print(prefix + "    %s = str(%s)" % (cLvalue, cLvalue))
            print(prefix + "except UnicodeEncodeError:")
            print(prefix + "    pass")
            print(prefix + "offset += length")
        elif type == 'octet':
            print(prefix + "%s = struct.unpack_from('B', encoded, offset)[0]" %
                  cLvalue)
            print(prefix + "offset += 1")
        elif type == 'short':
            print(prefix + "%s = struct.unpack_from('>H', encoded, offset)[0]" %
                  cLvalue)
            print(prefix + "offset += 2")
        elif type == 'long':
            print(prefix + "%s = struct.unpack_from('>I', encoded, offset)[0]" %
                  cLvalue)
            print(prefix + "offset += 4")
        elif type == 'longlong':
            print(prefix + "%s = struct.unpack_from('>Q', encoded, offset)[0]" %
                  cLvalue)
            print(prefix + "offset += 8")
        elif type == 'timestamp':
            print(prefix + "%s = struct.unpack_from('>Q', encoded, offset)[0]" %
                  cLvalue)
            print(prefix + "offset += 8")
        elif type == 'bit':
            raise Exception("Can't decode bit in genSingleDecode")
        elif type == 'table':
            print(Exception(prefix + "(%s, offset) = data.decode_table(encoded, offset)" % \
                  cLvalue))
        else:
            raise Exception("Illegal domain in genSingleDecode", type)

    def genSingleEncode(prefix, cValue, unresolved_domain):
        type = spec.resolveDomain(unresolved_domain)
        if type == 'shortstr':
            print(prefix + \
                "assert isinstance(%s, str_or_bytes),\\\n%s       'A non-string value was supplied for %s'" \
                % (cValue, prefix, cValue))
            print(prefix + "data.encode_short_string(pieces, %s)" % cValue)
        elif type == 'longstr':
            print(prefix + \
                "assert isinstance(%s, str_or_bytes),\\\n%s       'A non-string value was supplied for %s'" \
                % (cValue, prefix, cValue))
            print(
                prefix +
                "value = %s.encode('utf-8') if isinstance(%s, unicode_type) else %s"
                % (cValue, cValue, cValue))
            print(prefix + "pieces.append(struct.pack('>I', len(value)))")
            print(prefix + "pieces.append(value)")
        elif type == 'octet':
            print(prefix + "pieces.append(struct.pack('B', %s))" % cValue)
        elif type == 'short':
            print(prefix + "pieces.append(struct.pack('>H', %s))" % cValue)
        elif type == 'long':
            print(prefix + "pieces.append(struct.pack('>I', %s))" % cValue)
        elif type == 'longlong':
            print(prefix + "pieces.append(struct.pack('>Q', %s))" % cValue)
        elif type == 'timestamp':
            print(prefix + "pieces.append(struct.pack('>Q', %s))" % cValue)
        elif type == 'bit':
            raise Exception("Can't encode bit in genSingleEncode")
        elif type == 'table':
            print(Exception(prefix + "data.encode_table(pieces, %s)" % cValue))
        else:
            raise Exception("Illegal domain in genSingleEncode", type)

    def genDecodeMethodFields(m):
        print("        def decode(self, encoded, offset=0):")
        bitindex = None
        for f in m.arguments:
            if spec.resolveDomain(f.domain) == 'bit':
                if bitindex is None:
                    bitindex = 0
                if bitindex >= 8:
                    bitindex = 0
                if not bitindex:
                    print(
                        "            bit_buffer = struct.unpack_from('B', encoded, offset)[0]")
                    print("            offset += 1")
                print("            self.%s = (bit_buffer & (1 << %d)) != 0" % \
                      (pyize(f.name), bitindex))
                bitindex += 1
            else:
                bitindex = None
                genSingleDecode("            ", "self.%s" % (pyize(f.name),),
                                f.domain)
        print("            return self")
        print('')

    def genDecodeProperties(c):
        print("    def decode(self, encoded, offset=0):")
        print("        flags = 0")
        print("        flagword_index = 0")
        print("        while True:")
        print(
            "            partial_flags = struct.unpack_from('>H', encoded, offset)[0]")
        print("            offset += 2")
        print(
            "            flags = flags | (partial_flags << (flagword_index * 16))")
        print("            if not (partial_flags & 1):")
        print("                break")
        print("            flagword_index += 1")
        for f in c.fields:
            if spec.resolveDomain(f.domain) == 'bit':
                print("        self.%s = (flags & %s) != 0" %
                      (pyize(f.name), flagName(c, f)))
            else:
                print("        if flags & %s:" % (flagName(c, f),))
                genSingleDecode("            ", "self.%s" % (pyize(f.name),),
                                f.domain)
                print("        else:")
                print("            self.%s = None" % (pyize(f.name),))
        print("        return self")
        print('')

    def genEncodeMethodFields(m):
        print("        def encode(self):")
        print("            pieces = list()")
        bitindex = None

        def finishBits():
            if bitindex is not None:
                print("            pieces.append(struct.pack('B', bit_buffer))")

        for f in m.arguments:
            if spec.resolveDomain(f.domain) == 'bit':
                if bitindex is None:
                    bitindex = 0
                    print("            bit_buffer = 0")
                if bitindex >= 8:
                    finishBits()
                    print("            bit_buffer = 0")
                    bitindex = 0
                print("            if self.%s:" % pyize(f.name))
                print("                bit_buffer = bit_buffer | (1 << %d)" % \
                    bitindex)
                bitindex += 1
            else:
                finishBits()
                bitindex = None
                genSingleEncode("            ", "self.%s" % (pyize(f.name),),
                                f.domain)
        finishBits()
        print("            return pieces")
        print('')

    def genEncodeProperties(c):
        print("    def encode(self):")
        print("        pieces = list()")
        print("        flags = 0")
        for f in c.fields:
            if spec.resolveDomain(f.domain) == 'bit':
                print("        if self.%s: flags = flags | %s" %
                      (pyize(f.name), flagName(c, f)))
            else:
                print("        if self.%s is not None:" % (pyize(f.name),))
                print("            flags = flags | %s" % (flagName(c, f),))
                genSingleEncode("            ", "self.%s" % (pyize(f.name),),
                                f.domain)
        print("        flag_pieces = list()")
        print("        while True:")
        print("            remainder = flags >> 16")
        print("            partial_flags = flags & 0xFFFE")
        print("            if remainder != 0:")
        print("                partial_flags |= 1")
        print(
            "            flag_pieces.append(struct.pack('>H', partial_flags))")
        print("            flags = remainder")
        print("            if not flags:")
        print("                break")
        print("        return flag_pieces + pieces")
        print('')

    def fieldDeclList(fields):
        return ''.join([", %s=%s" % (pyize(f.name), fieldvalue(f.defaultvalue))
                        for f in fields])

    def fieldInitList(prefix, fields):
        if fields:
            return ''.join(["%sself.%s = %s\n" % (prefix, pyize(f.name), pyize(f.name)) \
                            for f in fields])
        else:
            return '%spass\n' % (prefix,)

    print("""\"\"\"
AMQP Specification
==================
This module implements the constants and classes that comprise AMQP protocol
level constructs. It should rarely be directly referenced outside of Pika's
own internal use.

.. note:: Auto-generated code by codegen.py, do not edit directly. Pull
requests to this file without accompanying ``utils/codegen.py`` changes will be
rejected.

\"\"\"

import struct
from pika import amqp_object
from pika import data
from pika.compat import str_or_bytes, unicode_type

# Python 3 support for str object
str = bytes
""")

    print("PROTOCOL_VERSION = (%d, %d, %d)" % (spec.major, spec.minor,
                                               spec.revision))
    print("PORT = %d" % spec.port)
    print('')

    # Append some constants that arent in the spec json file
    spec.constants.append(('FRAME_MAX_SIZE', 131072, ''))
    spec.constants.append(('FRAME_HEADER_SIZE', 7, ''))
    spec.constants.append(('FRAME_END_SIZE', 1, ''))
    spec.constants.append(('TRANSIENT_DELIVERY_MODE', 1, ''))
    spec.constants.append(('PERSISTENT_DELIVERY_MODE', 2, ''))

    constants = {}
    for c, v, cls in spec.constants:
        constants[constantName(c)] = v

    for key in sorted(constants.keys()):
        print("%s = %s" % (key, constants[key]))
    print('')

    for c in spec.allClasses():
        print('')
        print('class %s(amqp_object.Class):' % (camel(c.name),))
        print('')
        print("    INDEX = 0x%.04X  # %d" % (c.index, c.index))
        print("    NAME = %s" % (fieldvalue(camel(c.name)),))
        print('')

        for m in c.allMethods():
            print('    class %s(amqp_object.Method):' % (camel(m.name),))
            print('')
            methodid = m.klass.index << 16 | m.index
            print("        INDEX = 0x%.08X  # %d, %d; %d" % \
                  (methodid,
                                                                                 m.klass.index,
                                                                                 m.index,
                                                                                 methodid))
            print("        NAME = %s" % (fieldvalue(m.structName(),)))
            print('')
            print("        def __init__(self%s):" %
                  (fieldDeclList(m.arguments),))
            print(fieldInitList('            ', m.arguments))
            print("        @property")
            print("        def synchronous(self):")
            print("            return %s" % m.isSynchronous)
            print('')
            genDecodeMethodFields(m)
            genEncodeMethodFields(m)

    for c in spec.allClasses():
        if c.fields:
            print('')
            print('class %s(amqp_object.Properties):' % (c.structName(),))
            print('')
            print("    CLASS = %s" % (camel(c.name),))
            print("    INDEX = 0x%.04X  # %d" % (c.index, c.index))
            print("    NAME = %s" % (fieldvalue(c.structName(),)))
            print('')

            index = 0
            if c.fields:
                for f in c.fields:
                    if index % 16 == 15:
                        index += 1
                    shortnum = index / 16
                    partialindex = 15 - (index % 16)
                    bitindex = shortnum * 16 + partialindex
                    print('    %s = (1 << %d)' % (flagName(None, f), bitindex))
                    index += 1
                print('')

            print("    def __init__(self%s):" % (fieldDeclList(c.fields),))
            print(fieldInitList('        ', c.fields))
            genDecodeProperties(c)
            genEncodeProperties(c)

    print("methods = {")
    print(',\n'.join(["    0x%08X: %s" % (m.klass.index << 16 | m.index, m.structName()) \
                      for m in spec.allMethods()]))
    print("}")
    print('')

    print("props = {")
    print(',\n'.join(["    0x%04X: %s" % (c.index, c.structName()) \
                      for c in spec.allClasses() \
                      if c.fields]))
    print("}")
    print('')
    print('')

    print("def has_content(methodNumber):")
    print('    return methodNumber in (')
    for m in spec.allMethods():
        if m.hasContent:
            print('        %s.INDEX,' % m.structName())
    print('    )')
示例#2
0
def generate(specPath):
    spec = amqp_codegen.AmqpSpec(specPath)

    def genSingleDecode(prefix, cLvalue, unresolved_domain):
        type = spec.resolveDomain(unresolved_domain)
        if type == 'shortstr':
            print prefix + "length = struct.unpack_from('B', encoded, offset)[0]"
            print prefix + "offset += 1"
            print prefix + "%s = encoded[offset:offset + length].decode('utf8')" % cLvalue
            print prefix + "try:"
            print prefix + "    %s = str(%s)" % (cLvalue, cLvalue)
            print prefix + "except UnicodeEncodeError:"
            print prefix + "    pass"
            print prefix + "offset += length"
        elif type == 'longstr':
            print prefix + "length = struct.unpack_from('>I', encoded, offset)[0]"
            print prefix + "offset += 4"
            print prefix + "%s = encoded[offset:offset + length].decode('utf8')" % cLvalue
            print prefix + "try:"
            print prefix + "    %s = str(%s)" % (cLvalue, cLvalue)
            print prefix + "except UnicodeEncodeError:"
            print prefix + "    pass"
            print prefix + "offset += length"
        elif type == 'octet':
            print prefix + "%s = struct.unpack_from('B', encoded, offset)[0]" % cLvalue
            print prefix + "offset += 1"
        elif type == 'short':
            print prefix + "%s = struct.unpack_from('>H', encoded, offset)[0]" % cLvalue
            print prefix + "offset += 2"
        elif type == 'long':
            print prefix + "%s = struct.unpack_from('>I', encoded, offset)[0]" % cLvalue
            print prefix + "offset += 4"
        elif type == 'longlong':
            print prefix + "%s = struct.unpack_from('>Q', encoded, offset)[0]" % cLvalue
            print prefix + "offset += 8"
        elif type == 'timestamp':
            print prefix + "%s = struct.unpack_from('>Q', encoded, offset)[0]" % cLvalue
            print prefix + "offset += 8"
        elif type == 'bit':
            raise Exception("Can't decode bit in genSingleDecode")
        elif type == 'table':
            print Exception(prefix + "(%s, offset) = data.decode_table(encoded, offset)" % \
                  cLvalue)
        else:
            raise Exception("Illegal domain in genSingleDecode", type)

    def genSingleEncode(prefix, cValue, unresolved_domain):
        type = spec.resolveDomain(unresolved_domain)
        if type == 'shortstr':
            print prefix + \
                "assert isinstance(%s, basestring),\\\n%s       'A non-bytestring value was supplied for %s'" \
                % (cValue, prefix, cValue)
            print prefix + "value = %s.encode('utf-8') if isinstance(%s, unicode) else %s" % (
                cValue, cValue, cValue)
            print prefix + "pieces.append(struct.pack('B', len(value)))"
            print prefix + "pieces.append(value)"
        elif type == 'longstr':
            print prefix + \
                "assert isinstance(%s, basestring),\\\n%s       'A non-bytestring value was supplied for %s'" \
                % (cValue, prefix ,cValue)
            print prefix + "value = %s.encode('utf-8') if isinstance(%s, unicode) else %s" % (
                cValue, cValue, cValue)
            print prefix + "pieces.append(struct.pack('>I', len(value)))"
            print prefix + "pieces.append(value)"
        elif type == 'octet':
            print prefix + "pieces.append(struct.pack('B', %s))" % cValue
        elif type == 'short':
            print prefix + "pieces.append(struct.pack('>H', %s))" % cValue
        elif type == 'long':
            print prefix + "pieces.append(struct.pack('>I', %s))" % cValue
        elif type == 'longlong':
            print prefix + "pieces.append(struct.pack('>Q', %s))" % cValue
        elif type == 'timestamp':
            print prefix + "pieces.append(struct.pack('>Q', %s))" % cValue
        elif type == 'bit':
            raise Exception("Can't encode bit in genSingleEncode")
        elif type == 'table':
            print Exception(prefix + "data.encode_table(pieces, %s)" % cValue)
        else:
            raise Exception("Illegal domain in genSingleEncode", type)

    def genDecodeMethodFields(m):
        print "        def decode(self, encoded, offset=0):"
        bitindex = None
        for f in m.arguments:
            if spec.resolveDomain(f.domain) == 'bit':
                if bitindex is None:
                    bitindex = 0
                if bitindex >= 8:
                    bitindex = 0
                if not bitindex:
                    print "            bit_buffer = struct.unpack_from('B', encoded, offset)[0]"
                    print "            offset += 1"
                print "            self.%s = (bit_buffer & (1 << %d)) != 0" % \
                      (pyize(f.name), bitindex)
                bitindex += 1
            else:
                bitindex = None
                genSingleDecode("            ", "self.%s" % (pyize(f.name), ),
                                f.domain)
        print "            return self"
        print

    def genDecodeProperties(c):
        print "    def decode(self, encoded, offset=0):"
        print "        flags = 0"
        print "        flagword_index = 0"
        print "        while True:"
        print "            partial_flags = struct.unpack_from('>H', encoded, offset)[0]"
        print "            offset += 2"
        print "            flags = flags | (partial_flags << (flagword_index * 16))"
        print "            if not (partial_flags & 1):"
        print "                break"
        print "            flagword_index += 1"
        for f in c.fields:
            if spec.resolveDomain(f.domain) == 'bit':
                print "        self.%s = (flags & %s) != 0" % (pyize(
                    f.name), flagName(c, f))
            else:
                print "        if flags & %s:" % (flagName(c, f), )
                genSingleDecode("            ", "self.%s" % (pyize(f.name), ),
                                f.domain)
                print "        else:"
                print "            self.%s = None" % (pyize(f.name), )
        print "        return self"
        print

    def genEncodeMethodFields(m):
        print "        def encode(self):"
        print "            pieces = list()"
        bitindex = None

        def finishBits():
            if bitindex is not None:
                print "            pieces.append(struct.pack('B', bit_buffer))"

        for f in m.arguments:
            if spec.resolveDomain(f.domain) == 'bit':
                if bitindex is None:
                    bitindex = 0
                    print "            bit_buffer = 0"
                if bitindex >= 8:
                    finishBits()
                    print "            bit_buffer = 0"
                    bitindex = 0
                print "            if self.%s:" % pyize(f.name)
                print "                bit_buffer = bit_buffer | (1 << %d)" % \
                    bitindex
                bitindex += 1
            else:
                finishBits()
                bitindex = None
                genSingleEncode("            ", "self.%s" % (pyize(f.name), ),
                                f.domain)
        finishBits()
        print "            return pieces"
        print

    def genEncodeProperties(c):
        print "    def encode(self):"
        print "        pieces = list()"
        print "        flags = 0"
        for f in c.fields:
            if spec.resolveDomain(f.domain) == 'bit':
                print "        if self.%s: flags = flags | %s" % (pyize(
                    f.name), flagName(c, f))
            else:
                print "        if self.%s is not None:" % (pyize(f.name), )
                print "            flags = flags | %s" % (flagName(c, f), )
                genSingleEncode("            ", "self.%s" % (pyize(f.name), ),
                                f.domain)
        print "        flag_pieces = list()"
        print "        while True:"
        print "            remainder = flags >> 16"
        print "            partial_flags = flags & 0xFFFE"
        print "            if remainder != 0:"
        print "                partial_flags |= 1"
        print "            flag_pieces.append(struct.pack('>H', partial_flags))"
        print "            flags = remainder"
        print "            if not flags:"
        print "                break"
        print "        return flag_pieces + pieces"
        print

    def fieldDeclList(fields):
        return ''.join([
            ", %s=%s" % (pyize(f.name), fieldvalue(f.defaultvalue))
            for f in fields
        ])

    def fieldInitList(prefix, fields):
        if fields:
            return ''.join(["%sself.%s = %s\n" % (prefix, pyize(f.name), pyize(f.name)) \
                            for f in fields])
        else:
            return '%spass\n' % (prefix, )

    print """# ***** BEGIN LICENSE BLOCK *****
#
# For copyright and licensing please refer to COPYING.
#
# ***** END LICENSE BLOCK *****

# NOTE: Autogenerated code by codegen.py, do not edit

import struct
from pika import amqp_object
from pika import data

"""

    print "PROTOCOL_VERSION = (%d, %d, %d)" % (spec.major, spec.minor,
                                               spec.revision)
    print "PORT = %d" % spec.port
    print

    # Append some constants that arent in the spec json file
    spec.constants.append(('FRAME_MAX_SIZE', 131072, ''))
    spec.constants.append(('FRAME_HEADER_SIZE', 7, ''))
    spec.constants.append(('FRAME_END_SIZE', 1, ''))

    constants = {}
    for c, v, cls in spec.constants:
        constants[constantName(c)] = v

    for key in sorted(constants.iterkeys()):
        print "%s = %s" % (key, constants[key])
    print

    for c in spec.allClasses():
        print
        print 'class %s(amqp_object.Class):' % (camel(c.name), )
        print
        print "    INDEX = 0x%.04X  # %d" % (c.index, c.index)
        print "    NAME = %s" % (fieldvalue(camel(c.name)), )
        print

        for m in c.allMethods():
            print '    class %s(amqp_object.Method):' % (camel(m.name), )
            print
            methodid = m.klass.index << 16 | m.index
            print "        INDEX = 0x%.08X  # %d, %d; %d" % \
                  (methodid,
                   m.klass.index,
                   m.index,
                   methodid)
            print "        NAME = %s" % (fieldvalue(m.structName(), ))
            print
            print "        def __init__(self%s):" % (fieldDeclList(
                m.arguments), )
            print fieldInitList('            ', m.arguments)
            print "        @property"
            print "        def synchronous(self):"
            print "            return %s" % m.isSynchronous
            print
            genDecodeMethodFields(m)
            genEncodeMethodFields(m)

    for c in spec.allClasses():
        if c.fields:
            print
            print 'class %s(amqp_object.Properties):' % (c.structName(), )
            print
            print "    CLASS = %s" % (camel(c.name), )
            print "    INDEX = 0x%.04X  # %d" % (c.index, c.index)
            print "    NAME = %s" % (fieldvalue(c.structName(), ))
            print

            index = 0
            if c.fields:
                for f in c.fields:
                    if index % 16 == 15:
                        index += 1
                    shortnum = index / 16
                    partialindex = 15 - (index % 16)
                    bitindex = shortnum * 16 + partialindex
                    print '    %s = (1 << %d)' % (flagName(None, f), bitindex)
                    index += 1
                print

            print "    def __init__(self%s):" % (fieldDeclList(c.fields), )
            print fieldInitList('        ', c.fields)
            genDecodeProperties(c)
            genEncodeProperties(c)

    print "methods = {"
    print ',\n'.join(["    0x%08X: %s" % (m.klass.index << 16 | m.index, m.structName()) \
                      for m in spec.allMethods()])
    print "}"
    print

    print "props = {"
    print ',\n'.join(["    0x%04X: %s" % (c.index, c.structName()) \
                      for c in spec.allClasses() \
                      if c.fields])
    print "}"
    print
    print

    print "def has_content(methodNumber):"
    print
    for m in spec.allMethods():
        if m.hasContent:
            print '    if methodNumber == %s.INDEX:' % m.structName()
            print '        return True'
    print "    return False"
    print