Flatbuffers: [Python] how to get enum name in python?

Created on 6 Dec 2018  路  7Comments  路  Source: google/flatbuffers

in java, FlatBuffers will generate name() method for enums, which is very helpful.

  public static final String[] names = { "SUCCESS", "TIME_OUT", "UNKNOWN_ERROR", };

  public static String name(int e) { return names[e]; }

so does it in c++

inline const char **EnumNamesResultCode() {

  static const char *names[] = { "SUCCESS", "TIME_OUT", "UNKNOWN_ERROR", nullptr };

  return names;

}

inline const char *EnumNameResultCode(ResultCode e) { return EnumNamesResultCode()[static_cast<int>(e)]; }

but in python, there is no such method. it just generate a pure class with some constants.

class ResultCode(object):

    SUCCESS = 0

    TIME_OUT = 1

    UNKNOWN_ERROR = 2

how to generate name() method in python?

in other words, how can I get enum names in python?

stale

Most helpful comment

@wlx65003

For the following class ResultCode

class ResultCode(object):

    SUCCESS = 0

    TIME_OUT = 1

    UNKNOWN_ERROR = 2

You can use:
```python
def result_code_to_name(code):
for name, value in ResultCode.__dict__.items():
if value == code:
return name
return None

All 7 comments

Duplicate from here: https://stackoverflow.com/questions/53646959/flatbuffers-how-to-generate-name-method-in-python

Looks like we'll need to add names to the generator.
@rw

I don't think there's a way to add a staticmethod to a generated enum class that couldn't possibly collide with an enum's entry? Correct me if I'm wrong... maybe there are some constraints on flatbuffer enum names that would allow for it.

I guess if we want to keep getattr syntax for Enum values we could use getitem syntax to avoid any potential name collision?

Fully dynamically we could go for something like this:

def create_enum(**kwargs):
    """
    Generates a class with a __getitem__ definition for fetching an enum's name from a value.
    Returns an instance of that class, with members for fetching an enum's value from a name.
    """
    names  = {kwargs[k]: k for k in kwargs}
    def __getitem__(self, value):
        return names[value]
    cls = type('FlatbuffersEnumBase', (object,), {'__getitem__': __getitem__})
    obj = cls()
    obj.__dict__.update(kwargs)
    return obj

Which can be used like this:

ResultCode = flatbuffers.create_enum(
    SUCCESS = 0,
    TIME_OUT = 1,
    UNKNOWN_ERROR = 2
)
>>> ResultCode[1]
'TIME_OUT'
>>> ResultCode.TIME_OUT
1

_That might confuse some IDEs though..._

I can't immediately think of another performant way to achieve that interface without any namespace pollution.

That being said something as clear an obvious as this would be nice...

class ResultCode(object):
    SUCCESS = 0
    TIME_OUT = 1
    UNKNOWN_ERROR = 2
    names = {
        0: "SUCCESS",
        1: "TIME_OUT",
        2: "UNKNOWN_ERROR",
    }
    def __getitem__(self, value):
        return self.names[value]

I'd just loath to create the dictionary in the __getitem__ method.

Perhaps the generator could mangle the names entry if and only if it conflicts with an enum's name?

Why can't the generator output a Python Enum?

from enum import Enum

class ResultCode(Enum):
    SUCCESS = 0
    TIME_OUT = 1
    UNKNOWN_ERROR = 2

@iiSeymour that certainly would make sense.. but I guess we are supporting older Pythons still.

Do we have any 3.x specific codegen in the generator?

@wlx65003

For the following class ResultCode

class ResultCode(object):

    SUCCESS = 0

    TIME_OUT = 1

    UNKNOWN_ERROR = 2

You can use:
```python
def result_code_to_name(code):
for name, value in ResultCode.__dict__.items():
if value == code:
return name
return None

This issue is stale because it has been open 6 months with no activity. Please comment or this will be closed in 14 days.

Was this page helpful?
0 / 5 - 0 ratings