nelfin / pylint-protobuf

A plugin for making Pylint aware of the fields of protobuf-generated classes
MIT License
29 stars 12 forks source link

Module unrecognized by the plug-in and reports E1101 no-member error #27

Closed 2shpatz closed 3 years ago

2shpatz commented 4 years ago

Hi, we have an issue with the protobuf plug-in, for some reason one of our modules is unrecognized by it. here is the code after compile: (se_types_pb2.py)

deleted

An example file that calls the module:

deleted

and the output:

criticaldata.py,18,E1101,"no-member, CriticalDataGetAvailableSpace.run",Instance of 'SETypes' has no 'validation' member
criticaldata.py,18,E5901,"protobuf-undefined-attribute, CriticalDataGetAvailableSpace.run",Field 'VALIDATION_CMD_GET_AVAILABLE_SPACE' does not appear in the declared fields of protobuf-generated class

I hope that I gave you enough information.

Note: we have some other complied files in the same directory that the plugin do recognize

Thanks.

nelfin commented 4 years ago

Hi @2shpatz, it was a bit tricky to read your issue as the code formatting didn't quite work out. In GitHub's flavour or markdown, blocks of code are separated by three back-ticks ```, a single back-tick ` only works on the same line, e.g.

`only one line`

```
a block
```

Anyway, I believe this is two separate issues you are seeing.

I can't be sure of this as I can't see the definition of validation_pb2.Cmd but I assume that if it looks like something like this:

message Cmd {
  enum Reason {
    VALIDATION_CMD_STORE_BACKUP_DATA = 123
    # ...
  }
}

then that would be the case.

Sorry about the wait on this.

2shpatz commented 4 years ago

Hi, actually you've responded pretty quickly I fixed the issue format as required. (sorry about that)

Please, pay attention to the second error that you've mentioned.

"Instance of 'SETypes' has no 'validation' member" is due to #10 (see also #25)

it seems that when we're calling the protobuf class from other class like in here:

class CriticalDataGetLocalData(Msg):
    def __init__(self):
        super().__init__()
        self.message = se_types_pb2.SETypes()

    def run(self):
        self.message.validation.cmd.empty_cmd = validation_pb2.Cmd.VALIDATION_CMD_GET_LOCAL_DATA
        reply = execute_core_cmd(self.serialize())
        ret_msg = validation_pb2.CriticalData.DataStruct()
        ret_msg.CopyFrom(reply.validation.resp.critical_data.local)

        return ret_msg.SerializeToString()

the plugin doesn't excepts well the: self.message... line

or maybe there is a different issue. tell me if you need more info, thanks again.

2shpatz commented 4 years ago

in addition, maybe the problem is with "oneof" messages, can the plugin deal with "oneof" messages?

תודה

2shpatz commented 4 years ago

Hi, We've discovered another bug apparently. when declaring a module in a class with "self" an error will appear when calling it: self.message = se_types_pb2.SETypes() **self.message**.validation.cmd.empty_cmd

output: criticaldata.py,18,E1101,"no-member, CriticalDataGetAvailableSpace.run",Instance of 'SETypes' has no 'validation' member

and when removing "self" no error will appear. message = se_types_pb2.SETypes() **message**.validation.cmd.empty_cmd

BTW, another interesting stuff, we've encountered this function in prase_pb2.py:

def parse_message_type(node):
    try:
        outer = node.expr.value.expr.name
        field = node.expr.slice.value.value
    except AttributeError:
        return None
    try:
        inner = node.parent.value.name
    except AttributeError:
        try:
            inner = node.parent.value.expr.name
        except AttributeError:
            return None
    else:
        return outer, field, inner

is there an situation that the function will return None? maybe you should consider removing the "else"

def parse_message_type(node):
    try:
        outer = node.expr.value.expr.name
        field = node.expr.slice.value.value
    except AttributeError:
        return None
    try:
        inner = node.parent.value.name
    except AttributeError:
        try:
            inner = node.parent.value.expr.name
        except AttributeError:
            return None
    return outer, field, inner

thanks

nelfin commented 4 years ago

in addition, maybe the problem is with "oneof" messages, can the plugin deal with "oneof" messages?

oneof messages are not supported yet.

is there an situation that the function will return None? maybe you should consider removing the "else"

def parse_message_type(node):
    try:
        outer = node.expr.value.expr.name
        field = node.expr.slice.value.value
    except AttributeError:
        return None
    try:
        inner = node.parent.value.name
    except AttributeError:
        try:
            inner = node.parent.value.expr.name
        except AttributeError:
            return None
    return outer, field, inner

I think I see what you mean

    try:
        inner = node.parent.value.name
    except AttributeError:
        try:
            inner = node.parent.value.expr.name
        except AttributeError:
            return None
        # <-- this case
    else:
        return outer, field, inner
    # <-- will branch to here

I'll see about writing a test to check this behaviour and fixing this function.

2shpatz commented 4 years ago

oneof messages are not supported yet.

Hi, are you planning to support oneof messages soon?

nelfin commented 3 years ago

I'm going to close this issue as it's no longer clear what problems are present. Issues #10, #16, and #25 referenced above are no longer outstanding issues, the code path in https://github.com/nelfin/pylint-protobuf/issues/27#issuecomment-645213098 no longer exists, and oneof messages are currently supported.