nelfin / pylint-protobuf

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

Nested message definitions not handled correctly #24

Closed diana-infinitus-ai closed 3 years ago

diana-infinitus-ai commented 4 years ago

First off, thank you so much for this plugin! I'm setting up pylint for a project that uses protobufs and it'd be close to impossible without it.

The issue I'm seeing is, for a proto definition like this:

message Outer {
  message Inner {
    string inner_field = 1;
  }
  Inner field = 1;
}

I should be able to instantiate an Inner by doing:

inner = Outer.Inner(inner_field="foo")

but this currently throws a protobuf-undefined-attribute error, and I'm not sure how to avoid it at all aside from suppressing the error.

Is this a known issue??

nelfin commented 4 years ago

Hi @diana-infinitus-ai, thanks for the report. Strangely, I thought this issue was fixed in 197349b, which should be released in v0.12. See #16 and #21 for similar reports. I'll double check what's going on here and try to reproduce what you're seeing.

nelfin commented 4 years ago

I'm having trouble reproducing this one:

$ cat nested.proto 
syntax = "proto3";

message Outer {
  message Inner {
    string inner_field = 1;
  }
  Inner field = 1;
}
$ protoc --python_out=. nested.proto
$ cat example.py 
from nested_pb2 import Outer

inner = Outer.Inner(inner_field='foo')
$ ./venv/bin/pylint --load-plugins=pylint_protobuf --disable=all --enable=protobuf-undefined-attribute ./example.py 

--------------------------------------------------------------------
Your code has been rated at 10.00/10 (previous run: 10.00/10, +0.00)
$ ./venv/bin/pip freeze | grep pylint-protobuf
pylint-protobuf==0.12

What version of pylint-protobuf does pip freeze | grep pylint-protobuf report?

diana-infinitus-ai commented 4 years ago

You're right, that particular case works! I think I found a weird edge case!

I am using the latest version:

% pipenv run pip freeze | grep pylint-protobuf           
pylint-protobuf==0.12

It turns out, if you just have an outer and inner message, it works. But, if there's also an inner enum defined inside Outer, then for some reason, using the inner message declaration doesn't work anymore.

% cat nested.proto
syntax = "proto3";

message Outer {
    enum InnerEnum {
        ENUM_VAL = 0;
    }
    message Inner {
        string inner_field = 1;
    }
}
% protoc --python_out=. nested.proto
% cat example.py
from nested_pb2 import Outer

inner = Outer.Inner(inner_field='foo')
% pipenv run pylint ./example.py --load-plugins=pylint_protobuf 
************* Module example
example.py:3:8: E5901: Field 'Inner' does not appear in the declared fields of protobuf-generated class 'nested_pb2.Outer' and will raise AttributeError on access (protobuf-undefined-attribute)

----------------------------------------------------------------------
Your code has been rated at -15.00/10 (previous run: -15.00/10, +0.00)

Thanks for looking into it!

nelfin commented 4 years ago

Cool, good find. I'll take a look and see what's causing this.

nelfin commented 3 years ago

I've confirmed on my end that this is fixed, I'll close this issue in a couple of days if there's no update.