python-betterproto icon indicating copy to clipboard operation
python-betterproto copied to clipboard

RecursionError on import when using message with a field named "str"

Open HTK-MBU opened this issue 2 years ago • 0 comments

Hello,

We are using betterproto with the NI-XNET gRPC Server. (For Reference: https://github.com/ni/grpc-device) They use some messages which have a field with name "str". This causes a RecursionError on import of the generated python file. (The recursion happens inside the dataclass library, presumabely since the str builtin gets shadowed.)

Example message spec:

message GetPropertyResponse {
  int32 status = 1;
  oneof property_value {
    uint32 u32_scalar = 2;
    bool bool_scalar = 3;
    string str = 4;
    uint64 u64_scalar = 5;
    int32 i32_scalar = 6;
    double f64_scalar = 7;
  }
}

Generated python code:

@dataclass
class GetPropertyResponse(betterproto.Message):
    status: int = betterproto.int32_field(1)
    u32_scalar: int = betterproto.uint32_field(2, group="property_value")
    bool_scalar: bool = betterproto.bool_field(3, group="property_value")
    str: str = betterproto.string_field(4, group="property_value")
    u64_scalar: int = betterproto.uint64_field(5, group="property_value")
    i32_scalar: int = betterproto.int32_field(6, group="property_value")
    f64_scalar: float = betterproto.double_field(7, group="property_value")

Full Traceback:

Traceback (most recent call last):
  File "C:\...\<file>.py", line 8, in <module>
    from <module> import <CustomClass>
  File "C:\...\<file>.py", line 11, in <module>
    from <module> import nixnet_grpc
  File "C:\...\nixnet_grpc.py", line 1018, in <module>
    class GetPropertyResponse(betterproto.Message):
  File "C:\...\Python\Python39\lib\dataclasses.py", line 1021, in dataclass
    return wrap(cls)
  File "C:\...\Python\Python39\lib\dataclasses.py", line 1013, in wrap
    return _process_class(cls, init, repr, eq, order, unsafe_hash, frozen)
  File "C:\...\Python\Python39\lib\dataclasses.py", line 993, in _process_class
    str(inspect.signature(cls)).replace(' -> None', ''))
  File "C:\...\Python\Python39\lib\inspect.py", line 3087, in __str__
    formatted = str(param)
  File "C:\...\Python\Python39\lib\inspect.py", line 2606, in __str__
    formatannotation(self._annotation))
  File "C:\...\Python\Python39\lib\inspect.py", line 1240, in formatannotation
    return repr(annotation)
  File "C:\...\Python\Python39\lib\dataclasses.py", line 260, in __repr__
    return ('Field('
  File "C:\...\Python\Python39\lib\dataclasses.py", line 260, in __repr__
    return ('Field('
  File "C:\...\Python\Python39\lib\dataclasses.py", line 260, in __repr__
    return ('Field('
  [Previous line repeated 482 more times]
RecursionError: maximum recursion depth exceeded

We are not using this field actively so I was able to resolve the issue temporarily by renaming it to "str_" in the generated files. I have not tested whether this causes issues when actually using the field.

HTK-MBU avatar Mar 29 '23 13:03 HTK-MBU