Source

amqpev / spec / spec.py

Full commit
from lxml import etree


def decorate_keyword(kw):
    if kw in ['global']:
        return kw + '_'
    else:
        return kw


def build_amqp_methods(filename):
    defs_tree = etree.parse(filename)
    defs = {}
    pack_data = {}

    for packing in defs_tree.xpath("//packing"):
        pd = {'pack': None, 'unpack': None}
        pd.update(packing.attrib)
        pack_data[ pd.pop('type') ] = pd

    for class_ in defs_tree.xpath("//class"):
        class_name = decorate_keyword(class_.attrib['name'])

        md = {}
        defs[class_name] = {
                'id': int(class_.attrib['id']),
                'name': class_name,
                'methods': md }

        for method in class_.xpath("method"):
            fl = []
            method_name = decorate_keyword(method.attrib['name'])
            method_data = {
                    'id': int(method.attrib['id']),
                    'fields': fl,
                    'name': method_name }
            md[method_name] = method_data

            for field in method.xpath("field"):
                field_data = {'name': decorate_keyword(field.attrib['name']) }
                field_data.update(pack_data[ field.attrib['type'] ])
                fl.append(field_data)

        pl = []
        field_list = class_.xpath("field")

        words = len(field_list) // 15
        if words * 15 < len(field_list):
            words += 1
        bit = words * 16

        for i, field in enumerate(class_.xpath("field")):
            bit -= 1
            field_data = {
                    'name': decorate_keyword(field.attrib['name']),
                    'pos': i,
                    'bitmask': 1 << bit }
            field_data.update(pack_data[ field.attrib['type'] ])
            pl.append(field_data)

        if pl:
            md['properties'] = pl
            md['property_flag_words'] = words

    return defs


class _SpecImpl(dict):
    def __init__(self, d):
        for k, v in d.iteritems():
            impl = _ClassImpl(v)
            self[ v['id'] ] = impl
            self.__dict__[k] = impl


class _ClassImpl(dict):
    def __init__(self, d):
        self.id = d['id']
        self.name = d['name']

        for k, v in d['methods'].iteritems():
            if k not in ('properties', 'property_flag_words'):
                v['class_id'] = d['id']
                v['name'] = k
                v['qname'] = d['name'] + '.' + k
                self[ v['id'] ] = v
            self.__dict__[k] = v


import os.path

spec_file = os.path.join(os.path.dirname(__file__), "method_decls_0-8.xml")
AMQP_0_8 = build_amqp_methods(spec_file)
spec_0_8 = _SpecImpl(AMQP_0_8)

spec_file = os.path.join(os.path.dirname(__file__), "method_decls_0-9-1.xml")
AMQP_0_9_1 = build_amqp_methods(spec_file)
spec_0_9_1 = _SpecImpl(AMQP_0_9_1)