capnproto / pycapnp

Cap'n Proto serialization/RPC system - Python bindings
BSD 2-Clause "Simplified" License
470 stars 124 forks source link

Provide an enum for union element names #247

Closed jayvdb closed 3 years ago

jayvdb commented 3 years ago

Currently https://capnproto.github.io/pycapnp/quickstart.html#reading-unions recommends the user compared .which() to strings that match union member names defined in the .capnp file.

It would be nice if those strings could be provided in an enum, so that the example could be

which = person.employment.which()

if which == person.employment.union_enum.unemployed:
    print('unemployed')
elif which == person.employment.union_enum.employer:
    print('employer:', person.employment.employer)
elif which == person.employment.union_enum.school:
    print('student at:', person.employment.school)
elif which == person.employment.union_enum.self_employed:
    print('self employed')

union_enum would be dynamically built to be like

class EmploymentMembers(str, Enum):
    unemployed = "unemployed"
    employer = "employer"
    school = "school"
    self_employed = "self_employed"
jayvdb commented 3 years ago

I notice that there is code which sounds like it might be doing this, under a confusing & private name _which

https://github.com/capnproto/pycapnp/blob/125e9713caaefd1c2bd04e15d6e1c8625a37e9a5/capnp/lib/capnp.pyx#L1055

And there is as_enum everywhere, but I keep getting "Tried to use non-enum schema as an enum" or "Tried to get() a union member which is not currently initialized" or similar.

jayvdb commented 3 years ago

Ok, that is a bad example, because the union is a named member of the struct, and there is a capnp.lib.capnp._StructModuleWhich at addressbook.Person.Employment.

As a result, it is already possible to do

alice.employment.which == addressbook.Person.Employment.school

The case I am interested in is

struct ConnectRequest {
    ...
}
struct Status {
    ...
}

struct Message {
    union {
        connectRequest @0 :ConnectRequest;
        status @2 :Status;
        ...
    }
}

For that case, there is no named spot to mount a _StructModuleWhich. Suggestions on how to proceed?