Skip to content

[Python] generate enums as IntEnum or IntFlag type when requested#8782

Open
jtdavis777 wants to merge 24 commits intogoogle:masterfrom
jtdavis777:feature/python_enum
Open

[Python] generate enums as IntEnum or IntFlag type when requested#8782
jtdavis777 wants to merge 24 commits intogoogle:masterfrom
jtdavis777:feature/python_enum

Conversation

@jtdavis777
Copy link
Collaborator

@jtdavis777 jtdavis777 commented Nov 18, 2025

Fixes #8617 and addresses #5083

This PR has enum types inherit from IntEnum or (IntFlag for bit_flags) directly, instead of just providing this as type hinting, and changes the setter function signatures to require enum types. This code should still be backward and forward compatible on receipt, as ints are still returned by the getters.

This code, chiefly, allows users to go to and from string string values to the enum values, but also provides some runtime type safety (over just type hint safety).

@github-actions github-actions bot added c++ codegen Involving generating code from schema python labels Nov 18, 2025
@fliiiix
Copy link
Contributor

fliiiix commented Nov 18, 2025

Some docs at least in docs/source/flatc.md would be nice for this change

@fliiiix
Copy link
Contributor

fliiiix commented Nov 18, 2025

I played around a bit and it seemed fine, i couldn't integrated it into our main product because this crate was not updated yet rdelfin/flatbuffers-build#30

@jtdavis777 jtdavis777 changed the title [Python] generate enums as IntEnum type when requested [Python] generate enums as IntEnum or IntFlag type when requested Nov 20, 2025
@github-actions github-actions bot added the documentation Documentation label Nov 20, 2025
@jtdavis777 jtdavis777 requested a review from fliiiix November 26, 2025 22:10
Copy link
Contributor

@fliiiix fliiiix left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

@jtdavis777 jtdavis777 requested a review from fliiiix December 6, 2025 01:46
aardappel
aardappel previously approved these changes Dec 7, 2025
@jtdavis777
Copy link
Collaborator Author

You said it was compatible.. do we need this flag at all? Can't we always do the better thing?
so, I think it depends on what we mean by python 3 support. Now that we have dropped python 2 I think this is safe, but I believe technically this is python 3.4. Though TBF the current implementation is not consistent here so I think just doing this as part of --python-typing is fine. Will change to that!

@fliiiix
Copy link
Contributor

fliiiix commented Dec 23, 2025

Will you still updated this MR @jtdavis777 ?

@jtdavis777
Copy link
Collaborator Author

@fliiix yes it is on my list! Thank you for the reminder.

@fliiiix
Copy link
Contributor

fliiiix commented Dec 23, 2025

No hurry, I just finally got some time to look at changes and im running this right now on my version and am still interested to have this at some point on master :)

@fliiiix
Copy link
Contributor

fliiiix commented Jan 13, 2026

Im integrating the latest version right now any updates on this MR? I would still like to use that at some point :)

@jtdavis777
Copy link
Collaborator Author

No updates yet, I want to just fold it into the typing flag. Apologies for the delays!

@jtdavis777
Copy link
Collaborator Author

okay @fliiiix and @aardappel I think this one is ready for another pass - I think we have some work to do to make all the type hints actually consistent, but I don't want to tackle that here. this should generate compliant pyi files and type hints for where they are generated.

@jtdavis777 jtdavis777 requested review from aardappel and fliiiix March 7, 2026 02:45
@jtdavis777 jtdavis777 linked an issue Mar 7, 2026 that may be closed by this pull request
Copy link
Contributor

@fliiiix fliiiix left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks mostly good one small blocking issue everything else seems fine to me and worked in my testing ✨

for (const EnumVal* val : enum_def->Vals()) {
stub << " " << namer_.Variant(*val) << " = cast("
<< ScalarType(enum_def->underlying_type.base_type) << ", ...)\n";
stub << " " << namer_.Variant(*val) << ": Final["
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i don't think this is valid see:

error: Detected enum "EnumType" in a type stub with zero members. There is a chance this is due to a recent change in the semantics of enum membership. If so, use `member = value` to mark an enum member, instead of `member: type`  [misc]

https://typing.python.org/en/latest/spec/enums.html#defining-members

I think the previous:

 stub << "  " << namer_.Variant(*val) << " = cast(" << ScalarType(enum_def->underlying_type.base_type) << ", ...)\n";

is still how we should do it

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think with the change over to enums inheriting from Enum types, it should be

stub << "  " << namer_.Variant(*val) << namer_.Type(*enum_def) << "\n";

to embrace the stronger typing. thoughts?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TL;DR lets try to use the strong types as it seems to be ok for mypy 👍

I think thats not how it works but im struggling to find a good source proving me right or wrong, how i think about it is that the IntEnum is a strong type containing ints.
https://mypy.readthedocs.io/en/stable/literal_types.html#enums

Using the Type of the Enum inside the Enum itself is recursive, but i just tried it on a small scale example:

==> TestEnum.py <==
from enum import IntEnum

class TestEnum(IntEnum):
    A = 1
    B = 2

==> TestEnum.pyi <==
from enum import IntEnum

class TestEnum(IntEnum):
    A = TestEnum
    B = TestEnum

==> Test.py <==
import TestEnum

def function(e: TestEnum.TestEnum):
    ...

And mypy is happy about it 🤷

uv run mypy Test.py                        
Success: no issues found in 1 source file

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

awesome! I left the old way for when typing is off, but I think the file won't generate at all in that case? haha

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

idk seems in my real project mypy is not happy with it im still getting these errors now ->

FluidType.pyi:10: error: Detected enum "FluidType.FluidType" in a type stub with zero members. There is a chance this is due to a recent change in the semantics of enum membership. If so, use `member = value` to mark an enum member, instead of `member: type`  [misc]
FluidType.pyi:10: note: See https://typing.readthedocs.io/en/latest/spec/enums.html#defining-members

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i guess we should switch back to cast(int, ...) at least that seemed to work everywhere :)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yea you are probably right. I can do that

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done!

@jtdavis777 jtdavis777 requested a review from fliiiix March 12, 2026 16:17
@fliiiix
Copy link
Contributor

fliiiix commented Mar 12, 2026

looking at the examples and the code this seems now fine to me 👍 (i also started a build to see but i assume it should be good like this)

@fliiiix
Copy link
Contributor

fliiiix commented Mar 13, 2026

i think you forgot to rerun the generation thats why this job still fails -> https://github.com/google/flatbuffers/actions/runs/23049893282/job/66948134837?pr=8782

I just figured out something broke in my setup so it might be monday until i can give it another try :/

Manually inspecting the .pyi files this should be fine :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c++ codegen Involving generating code from schema documentation Documentation python

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Python] FBS Enums are of underlying type, not of enum type [Python] how to get enum name in python?

3 participants