protocolbuffers / protocolbuffers/protobuf

Python enum types are still annotated incorrectly

Open
#29,010 1 comment 0 reactions 1 assignee View on GitHub

@jguamie is already working on this.

Since Aug 11, 2026.

bug python
Dominant language
C++
Stars
72k
Forks
16.3k
Avg merge
1d 17h
Merged PRs (30d)
140

Description

What version of protobuf and what language are you using?

Version: commit dd9d2ad02 / protobuf 7.35.1
Language: Python

What supported operating system version are you using (e.g. Linux, Windows) ?

The Python support matrix doesn't indicate any specific OS version requirements.

What supported runtime / compiler version are you using (e.g. python version, gcc version)

Python 3.12.8 w/ mypy 2.1.0

What did you do?

repro.py:

"""protoc-generated enum stubs are inconsistent with EnumTypeWrapper."""

import addressbook_pb2


def phone_number_for(kind: str) -> addressbook_pb2.Person.PhoneNumber:
    # PhoneType.Value is stubbed as returning int (EnumTypeWrapper is
    # _EnumTypeWrapper[int] in google-stubs)...
    phone_type = addressbook_pb2.Person.PhoneType.Value(kind)
    # ...but the generated PhoneNumber.__init__ stub expects Person.PhoneType:
    #
    #   error: Argument "type" to "PhoneNumber" has incompatible type "int";
    #          expected "PhoneType | str | None"  [arg-type]
    return addressbook_pb2.Person.PhoneNumber(number="555-1234", type=phone_type)


# The generated stub presents PhoneType as a class (an int subclass), but at
# runtime it is an EnumTypeWrapper instance and is not callable:
#
#   TypeError: 'EnumTypeWrapper' object is not callable
addressbook_pb2.Person.PhoneType(1)

Steps to reproduce the behavior:

pip install grpcio-tools==1.78.0 types-protobuf mypy
curl -sO https://raw.githubusercontent.com/protocolbuffers/protobuf/main/examples/addressbook.proto
python -m grpc_tools.protoc -I. --python_out=. --pyi_out=. addressbook.proto
python -m mypy repro.py
python repro.py

What did you expect to see

  1. mypy should not report errors for using the return value from Value() as the enum type.
  2. Explicitly converting a raw integer type to an enum type should succeed, as if it were an ordinary Python NewType declaration.

What did you see instead?

$ python -m mypy repro.py
repro.py:18: error: Argument "type" to "PhoneNumber" has incompatible type "int"; expected "PhoneType | str | None"  [arg-type]

$ python repro.py
TypeError: 'EnumTypeWrapper' object is not callable

Make sure you include information that can help us debug (protos, full error
message, exception listing, stack trace, logs).

Anything else we should know about your project / environment

This is fundamentally the same issue as #10240, which was auto-closed by a bot without being fixed.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.