| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- # Copyright (c) 2025-2026 Buf Technologies, Inc.
- #
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- #
- # http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- from __future__ import annotations
- from enum import IntEnum
- from typing import TYPE_CHECKING
- if TYPE_CHECKING:
- from ._descriptors import DescEnum
- class Enum(IntEnum):
- """Base class for protobuf enumeration types.
- Protobuf enumerations are integer-based. This class inherits from `IntEnum`
- so enum values work as integers while maintaining a link to the protobuf
- descriptor.
- Generated enum classes inherit from this base class and define their enum
- values as class attributes.
- Examples:
- ```python
- from protobuf import Enum
- # Generated from:
- # enum Color {
- # COLOR_UNSPECIFIED = 0;
- # COLOR_RED = 1;
- # COLOR_GREEN = 2;
- # }
- class Color(Enum):
- UNSPECIFIED = 0 # Python name (prefix stripped)
- RED = 1
- GREEN = 2
- # Use like a regular int
- color = Color.RED
- print(color) # Prints: RED (Python member name)
- print(repr(color)) # Color.RED (Python qualified name)
- print(int(color)) # 1
- print(color + 1) # 2
- print(color == 1) # True
- # Access the descriptor
- desc = Color.desc()
- print(desc.name) # "Color"
- ```
- """
- if TYPE_CHECKING:
- _desc: DescEnum
- @classmethod
- def _missing_(cls, value: object) -> Enum:
- """Handle unknown enum values.
- Called by the enum metaclass for undefined values. Open enums must
- support unknown values, so this creates a pseudo-member.
- Args:
- value: The integer value to create an enum instance for.
- Returns:
- A new enum instance with the given value.
- Raises:
- TypeError: If the value is not an integer.
- """
- if not isinstance(value, int):
- msg = f"value must be an int, not {type(value).__name__}"
- raise TypeError(msg)
- if not cls._desc.open:
- msg = f"`{value}` is not a valid {cls.__name__}"
- raise ValueError(msg)
- # Create a pseudo-member for unknown values
- pseudo_member = int.__new__(cls, value)
- pseudo_member._name_ = None # type: ignore[attr-defined]
- pseudo_member._value_ = value # type: ignore[attr-defined]
- return pseudo_member # type: ignore[return-value]
- def __str__(self) -> str:
- """Return a string representation of the enum value.
- Returns the Python member name (e.g., "RED") for known values,
- or the integer as a string for unknown values.
- Returns:
- The Python member name if known, otherwise the integer as a string.
- Examples:
- ```python
- str(Color.RED) # 'RED'
- str(Color(99)) # '99'
- ```
- """
- if self._name_ is not None:
- return self._name_
- return str(int(self))
- def __repr__(self) -> str:
- """Return a detailed string representation of the enum value.
- Returns the qualified Python name (e.g., "Color.RED") for known values,
- or "Color(99)" format for unknown values.
- Returns:
- The qualified Python name if known, otherwise the class name with integer.
- Examples:
- ```python
- repr(Color.RED) # 'Color.RED'
- repr(Color(99)) # 'Color(99)'
- ```
- """
- if self._name_ is not None:
- return f"{self.__class__.__qualname__}.{self._name_}"
- return f"{self.__class__.__qualname__}({int(self)})"
- @classmethod
- def desc(cls) -> DescEnum:
- """Get the descriptor for this enumeration type.
- Returns:
- The DescEnum descriptor for this enum.
- Examples:
- ```python
- desc = Color.desc()
- desc.type_name # 'my.package.Color'
- desc.values[0].name # 'COLOR_UNSPECIFIED'
- ```
- """
- return cls._desc
- def enum_is_unknown(value: Enum, /) -> bool:
- """Check if an enum value is unknown (i.e., not defined in the protobuf schema)."""
- return value.name is None
|