Innovenergy_trunk/NodeRed/NodeRedFiles/pika-0.13.1/utils/codegen.py

405 lines
15 KiB
Python
Raw Normal View History

2024-06-05 10:33:44 +00:00
"""
codegen.py generates pika/spec.py
"""
from __future__ import nested_scopes
import os
import re
import sys
RABBITMQ_PUBLIC_UMBRELLA = '../../rabbitmq-public-umbrella'
RABBITMQ_CODEGEN = 'rabbitmq-codegen'
PIKA_SPEC = '../pika/spec.py'
CODEGEN_PATH = os.path.realpath('%s/%s' % (RABBITMQ_PUBLIC_UMBRELLA,
RABBITMQ_CODEGEN))
print('codegen-path: %s' % CODEGEN_PATH)
sys.path.append(CODEGEN_PATH)
import amqp_codegen
DRIVER_METHODS = {
"Exchange.Bind": ["Exchange.BindOk"],
"Exchange.Unbind": ["Exchange.UnbindOk"],
"Exchange.Declare": ["Exchange.DeclareOk"],
"Exchange.Delete": ["Exchange.DeleteOk"],
"Queue.Declare": ["Queue.DeclareOk"],
"Queue.Bind": ["Queue.BindOk"],
"Queue.Purge": ["Queue.PurgeOk"],
"Queue.Delete": ["Queue.DeleteOk"],
"Queue.Unbind": ["Queue.UnbindOk"],
"Basic.Qos": ["Basic.QosOk"],
"Basic.Get": ["Basic.GetOk", "Basic.GetEmpty"],
"Basic.Ack": [],
"Basic.Reject": [],
"Basic.Recover": ["Basic.RecoverOk"],
"Basic.RecoverAsync": [],
"Tx.Select": ["Tx.SelectOk"],
"Tx.Commit": ["Tx.CommitOk"],
"Tx.Rollback": ["Tx.RollbackOk"]
}
def fieldvalue(v):
if isinstance(v, unicode):
return repr(v.encode('ascii'))
else:
return repr(v)
def normalize_separators(s):
s = s.replace('-', '_')
s = s.replace(' ', '_')
return s
def pyize(s):
s = normalize_separators(s)
if s in ('global', 'class'):
s += '_'
return s
def camel(s):
return normalize_separators(s).title().replace('_', '')
amqp_codegen.AmqpMethod.structName = lambda m: camel(
m.klass.name) + '.' + camel(m.name)
amqp_codegen.AmqpClass.structName = lambda c: camel(c.name) + "Properties"
def constantName(s):
return '_'.join(re.split('[- ]', s.upper()))
def flagName(c, f):
if c:
return c.structName() + '.' + constantName('flag_' + f.name)
else:
return constantName('flag_' + f.name)
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(' )')
if __name__ == "__main__":
with open(PIKA_SPEC, 'w') as handle:
sys.stdout = handle
generate(['%s/amqp-rabbitmq-0.9.1.json' % CODEGEN_PATH])