Пример #1
0
def _update_fields(proto):
    """更新map中的自定义类型以及检查嵌套message类型是否存在

    Args:
        proto (Protobuf): 解析得到的对象
    """
    for _, message in proto.messages.iteritems():
        for field_name, field in message.fields.iteritems():
            if isinstance(field, MessageField):
                if field_name not in proto.messages:
                    raise ProtoGrammarError(
                        'grammar error: {} not defined'.format(field_name))

                field.message_type = proto.messages[field_name]
            elif isinstance(field, MapField):
                key_type, key_name = field.key_type
                val_type, val_name = field.value_type

                if val_type == FieldType.REF:
                    if val_name not in proto.messages:
                        raise ProtoGrammarError(
                            'grammar error: {} not defined'.format(field_name))

                    field.value_type = MessageField(
                        val_name, 1, 1, 1, proto.messages[val_name])
                else:
                    class_ = field_map[val_name]
                    field.value_type = class_('value', 1, 1, 1)

                class_ = field_map[key_name]
                field.key_type = class_('key', 0, 0, 1)
Пример #2
0
def p_start(p):
    """start : header definition"""
    package, syntax = '', 'proto3'
    for item in p[1]:
        if item[0] == HeaderType.SYNTAX:
            syntax = item[1]
        elif item[0] == HeaderType.PACKAGE:
            package = item[1]

    proto = Protobuf(package, syntax)
    symbols = set()
    for item in p[2]:
        item_name = item.name
        if item_name in symbols:
            raise ProtoGrammarError(
                'grammar error: symbol {} is already defined at line {}'.format(
                    item_name, p.lineno))

        if isinstance(item, Service):
            proto.services[item_name] = item
        elif isinstance(item, Message):
            proto.messages[item_name] = item
        symbols.add(item_name)

    _check_methods(proto)
    _update_fields(proto)
    p[0] = proto
Пример #3
0
def p_map_type(p):
    """map_type : MAP '<' base_type ',' base_type '>'
               | MAP '<' base_type ',' ref_type '>'"""
    if p[3] == 'bytes':
        raise ProtoGrammarError(
            'grammar error at line {}: key type cannot be bytes'.format(p.lineno))
    p[0] = (FieldType.MAP, p[1], p[3], p[5])
Пример #4
0
def p_message(p):
    """message : seen_message '{' field_seq '}'"""
    message = Message(p[1])
    for index, field in enumerate(p[3]):
        optional, type_, name, number = field

        if name in message.fields:
            raise ProtoGrammarError(
                'grammar error: message {} is already defined at line {}'.format(
                    name, p.lineno))

        label = 1
        if optional == 'repeated':
            label = 3

        message_type = None
        if type_[0] == FieldType.BASE:
            class_ = field_map[type_[1]]
            field = class_(name, index, number, label,
                           message_type=message_type)
            if label == 3:
                field.default_value = []
        elif type_[0] == FieldType.MAP:
            label = 3
            field = MapField(name, index, number, label,
                             message_type=message_type,
                             key_type=type_[2],
                             value_type=type_[3])
            field.default_value = []
        else:
            field = MessageField(name, index, number, label,
                                 message_type=type_[1])
        message.fields[name] = field

    p[0] = message
Пример #5
0
def p_service(p):
    """service : SERVICE IDENTIFIER '{' func_seq '}'"""
    service = Service(p[2])
    for method in p[4]:
        if method.name in service.methods:
            raise ProtoGrammarError(
                'grammar error: method {} is already defined at line {}'.format(
                    method.name, p.lineno))
        service.methods[method.name] = method
    p[0] = service
Пример #6
0
def _check_methods(proto):
    """检查serivce中定义方法的传参能否解析

    Args:
        proto (Protobuf): 解析得到的对象
    """
    for _, service in proto.services.iteritems():
        for method_name, method in service.methods.iteritems():
            if method.request_type in proto.messages and \
                            method.response_type in proto.messages:
                continue
            raise ProtoGrammarError(
                'grammar error: {} params not defined'.format(method_name,))
Пример #7
0
def p_syntax(p):
    """syntax : SYNTAX '=' LITERAL"""
    if p[3] != 'proto3':
        raise ProtoGrammarError(
            'grammar error at line {}: syntax must be proto3'.format(p.lineno))
    p[0] = (HeaderType.SYNTAX, p[3])
Пример #8
0
def p_error(p):
    if p is None:
        raise ProtoGrammarError('grammar error at EOF')
    raise ProtoGrammarError('grammar error: {} at line {}'.format(
        p.value, p.lineno))