Invalid Enum member names which contain the Enum name
Summary
2.0.0b7 breaks enums with underscores in field names
Reproduction Steps
Test proto definition, in test.proto:
syntax = "proto3";
package hello;
// Greeting represents a message you can tell a user.
message Greeting {
Risk risk = 1;
}
enum Risk {
LOW_RISK = 0;
HIGH_RISK = 1;
}
Protoc compiler invocation:
$ protoc -I . --python_betterproto_out=lib test.proto
Expected Results
2.0.0b6 output (lib/hello/__init__.py):
# Generated by the protocol buffer compiler. DO NOT EDIT!
# sources: test.proto
# plugin: python-betterproto
# This file has been @generated
from dataclasses import dataclass
import betterproto
class Risk(betterproto.Enum):
LOW_RISK = 0
HIGH_RISK = 1
@dataclass(eq=False, repr=False)
class Greeting(betterproto.Message):
"""Greeting represents a message you can tell a user."""
risk: "Risk" = betterproto.enum_field(1)
Actual Results
2.0.0b7 output (lib/hello/__init__.py):
# Generated by the protocol buffer compiler. DO NOT EDIT!
# sources: test.proto
# plugin: python-betterproto
# This file has been @generated
from dataclasses import dataclass
import betterproto
class Risk(betterproto.Enum):
_ = 0
_ = 1
@dataclass(eq=False, repr=False)
class Greeting(betterproto.Message):
"""Greeting represents a message you can tell a user."""
risk: "Risk" = betterproto.enum_field(1)
System Information
- Protoc version: libprotoc 27.3
- Python version: Python 3.11.7
- Betterproto version:
Name: betterproto
Version: 2.0.0b7
Summary: A better Protobuf / gRPC generator & library
Home-page: https://github.com/danielgtaylor/python-betterproto
Author: Daniel G. Taylor
Author-email: [email protected]
License: MIT
Location: /Users/connor/Code/tests/test070/.venv/lib/python3.11/site-packages
Requires: grpclib, python-dateutil, typing-extensions
Required-by:
Checklist
- [X] I have searched the issues for duplicates.
- [X] I have shown the entire traceback, if possible.
- [X] I have verified this issue occurs on the latest prelease of betterproto which can be installed using
pip install -U --pre betterproto, if possible.
Regression caused by the last change to https://github.com/danielgtaylor/python-betterproto/blob/bd7de203e16e949666b2844b3dec1eb7c4ed523c/src/betterproto/compile/naming.py
Would be fixed by #589 though I'll have a think about whether to change the function t ostrip the name
Smart-stripping by default may lead to confusion, and should be mentioned on the homepage/docs.
Tests
def pythonize_enum_member_name(name: str, enum_name: str) -> str:
enum_name = casing.snake_case(enum_name).upper()
find = name.find(enum_name)
if find != -1:
name = name[find + len(enum_name) :].strip("_")
return casing.sanitize_name(name)
>>> pythonize_enum_member_name("UNKNOWN_COLOR", "Color")
'_'
>>> pythonize_enum_member_name("SWIFTUI", "UI")
'_'
>>> pythonize_enum_member_name("MONGODB", "DB")
'_'
>>> pythonize_enum_member_name("BLACKBIRD", "Bird")
'_'
>>> pythonize_enum_member_name("SUNFLOWER", "Flower")
'_'
>>> pythonize_enum_member_name("FOOTBALL", "Ball")
'_'
>>> pythonize_enum_member_name("SOCCER_BALL", "Ball")
'_'
>>> pythonize_enum_member_name("EMPLOYEE_ID_NUMBER", "ID")
'NUMBER'
>>> pythonize_enum_member_name("WIFI_NETWORK", "Net")
'WORK'
>>> pythonize_enum_member_name("OAUTH_LOGIN", "Auth")
'LOGIN'
>>> pythonize_enum_member_name("KEYWORDS", "Word")
'S'
# This one is OK:
>>> pythonize_enum_member_name("X11_METHOD_NONE", "X11Method")
'NONE'
>>> pythonize_enum_member_name("A11Y_METHOD_NONE", "A11YMethod")
'A11Y_METHOD_NONE'
>>> pythonize_enum_member_name("DTYPE_NONE", "DType")
'DTYPE_NONE'
Warnings
Perhaps produce a warning if the input may cause issues or if the output is "_". For example:
Warning: Generated python name "_" from the C++ "{name}" member of enum "{enum_name}".
To avoid confusion, it is recommended to prefix the enum with its snake-case version "{casing.snake_case(enum_name).upper()}".