Files
flatbuffers/tests/MyGame/MonsterExtra.py
Łukasz Kurowski c526cb640b [Python] Enhance object API __init__ with typed keyword arguments (#8615)
This commit significantly improves the developer experience for the Python Object-Based API by overhauling the generated `__init__` method for `T`-suffixed classes.

Previously, `T` objects had to be instantiated with an empty constructor, and their fields had to be populated manually one by one. This was verbose and not idiomatic Python.

This change modifies the Python code generator (`GenInitialize`) to produce `__init__` methods that are:

1.  **Keyword-Argument-Friendly**: The constructor now accepts all table/struct fields as keyword arguments, allowing for concise, single-line object creation.

2.  **Fully Typed**: The signature of the `__init__` method is now annotated with Python type hints. This provides immediate benefits for static analysis tools (like Mypy) and IDEs, enabling better autocompletion and type checking.

3.  **Correctly Optional**: The generator now correctly wraps types in `Optional[...]` if their default value is `None`. This applies to strings, vectors, and other nullable fields, ensuring strict type safety.

The new approach remains **fully backward-compatible**, as all arguments have default values. Existing code that uses the empty constructor will continue to work without modification.

#### Example of a Generated `__init__`

**Before:**

```python
class KeyValueT(object):
    def __init__(self):
        self.key = None  # type: str
        self.value = None  # type: str
```

**After:**

```python
class KeyValueT(object):
    def __init__(self, key: Optional[str] = None, value: Optional[str] = None):
        self.key = key
        self.value = value
```

#### Example of User Code

**Before:**

```python
# Old, verbose way
kv = KeyValueT()
kv.key = "instrument"
kv.value = "EUR/USD"
```

**After:**

```python
# New, Pythonic way
kv = KeyValueT(key="instrument", value="EUR/USD")
```
2025-07-22 23:57:39 -07:00

348 lines
12 KiB
Python

# automatically generated by the FlatBuffers compiler, do not modify
# namespace: MyGame
import flatbuffers
from flatbuffers.compat import import_numpy
from typing import Any
np = import_numpy()
class MonsterExtra(object):
__slots__ = ['_tab']
@classmethod
def GetRootAs(cls, buf, offset: int = 0):
n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
x = MonsterExtra()
x.Init(buf, n + offset)
return x
@classmethod
def GetRootAsMonsterExtra(cls, buf, offset=0):
"""This method is deprecated. Please switch to GetRootAs."""
return cls.GetRootAs(buf, offset)
@classmethod
def MonsterExtraBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
return flatbuffers.util.BufferHasIdentifier(buf, offset, b"\x4D\x4F\x4E\x45", size_prefixed=size_prefixed)
# MonsterExtra
def Init(self, buf: bytes, pos: int):
self._tab = flatbuffers.table.Table(buf, pos)
# MonsterExtra
def D0(self):
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
if o != 0:
return self._tab.Get(flatbuffers.number_types.Float64Flags, o + self._tab.Pos)
return float('nan')
# MonsterExtra
def D1(self):
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
if o != 0:
return self._tab.Get(flatbuffers.number_types.Float64Flags, o + self._tab.Pos)
return float('nan')
# MonsterExtra
def D2(self):
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
if o != 0:
return self._tab.Get(flatbuffers.number_types.Float64Flags, o + self._tab.Pos)
return float('inf')
# MonsterExtra
def D3(self):
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
if o != 0:
return self._tab.Get(flatbuffers.number_types.Float64Flags, o + self._tab.Pos)
return float('-inf')
# MonsterExtra
def F0(self):
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
if o != 0:
return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos)
return float('nan')
# MonsterExtra
def F1(self):
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
if o != 0:
return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos)
return float('nan')
# MonsterExtra
def F2(self):
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(16))
if o != 0:
return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos)
return float('inf')
# MonsterExtra
def F3(self):
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(18))
if o != 0:
return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos)
return float('-inf')
# MonsterExtra
def Dvec(self, j: int):
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(20))
if o != 0:
a = self._tab.Vector(o)
return self._tab.Get(flatbuffers.number_types.Float64Flags, a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 8))
return 0
# MonsterExtra
def DvecAsNumpy(self):
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(20))
if o != 0:
return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Float64Flags, o)
return 0
# MonsterExtra
def DvecLength(self) -> int:
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(20))
if o != 0:
return self._tab.VectorLen(o)
return 0
# MonsterExtra
def DvecIsNone(self) -> bool:
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(20))
return o == 0
# MonsterExtra
def Fvec(self, j: int):
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(22))
if o != 0:
a = self._tab.Vector(o)
return self._tab.Get(flatbuffers.number_types.Float32Flags, a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 4))
return 0
# MonsterExtra
def FvecAsNumpy(self):
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(22))
if o != 0:
return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Float32Flags, o)
return 0
# MonsterExtra
def FvecLength(self) -> int:
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(22))
if o != 0:
return self._tab.VectorLen(o)
return 0
# MonsterExtra
def FvecIsNone(self) -> bool:
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(22))
return o == 0
def MonsterExtraStart(builder: flatbuffers.Builder):
builder.StartObject(11)
def Start(builder: flatbuffers.Builder):
MonsterExtraStart(builder)
def MonsterExtraAddD0(builder: flatbuffers.Builder, d0: float):
builder.PrependFloat64Slot(0, d0, float('nan'))
def AddD0(builder: flatbuffers.Builder, d0: float):
MonsterExtraAddD0(builder, d0)
def MonsterExtraAddD1(builder: flatbuffers.Builder, d1: float):
builder.PrependFloat64Slot(1, d1, float('nan'))
def AddD1(builder: flatbuffers.Builder, d1: float):
MonsterExtraAddD1(builder, d1)
def MonsterExtraAddD2(builder: flatbuffers.Builder, d2: float):
builder.PrependFloat64Slot(2, d2, float('inf'))
def AddD2(builder: flatbuffers.Builder, d2: float):
MonsterExtraAddD2(builder, d2)
def MonsterExtraAddD3(builder: flatbuffers.Builder, d3: float):
builder.PrependFloat64Slot(3, d3, float('-inf'))
def AddD3(builder: flatbuffers.Builder, d3: float):
MonsterExtraAddD3(builder, d3)
def MonsterExtraAddF0(builder: flatbuffers.Builder, f0: float):
builder.PrependFloat32Slot(4, f0, float('nan'))
def AddF0(builder: flatbuffers.Builder, f0: float):
MonsterExtraAddF0(builder, f0)
def MonsterExtraAddF1(builder: flatbuffers.Builder, f1: float):
builder.PrependFloat32Slot(5, f1, float('nan'))
def AddF1(builder: flatbuffers.Builder, f1: float):
MonsterExtraAddF1(builder, f1)
def MonsterExtraAddF2(builder: flatbuffers.Builder, f2: float):
builder.PrependFloat32Slot(6, f2, float('inf'))
def AddF2(builder: flatbuffers.Builder, f2: float):
MonsterExtraAddF2(builder, f2)
def MonsterExtraAddF3(builder: flatbuffers.Builder, f3: float):
builder.PrependFloat32Slot(7, f3, float('-inf'))
def AddF3(builder: flatbuffers.Builder, f3: float):
MonsterExtraAddF3(builder, f3)
def MonsterExtraAddDvec(builder: flatbuffers.Builder, dvec: int):
builder.PrependUOffsetTRelativeSlot(8, flatbuffers.number_types.UOffsetTFlags.py_type(dvec), 0)
def AddDvec(builder: flatbuffers.Builder, dvec: int):
MonsterExtraAddDvec(builder, dvec)
def MonsterExtraStartDvecVector(builder, numElems: int) -> int:
return builder.StartVector(8, numElems, 8)
def StartDvecVector(builder, numElems: int) -> int:
return MonsterExtraStartDvecVector(builder, numElems)
def MonsterExtraAddFvec(builder: flatbuffers.Builder, fvec: int):
builder.PrependUOffsetTRelativeSlot(9, flatbuffers.number_types.UOffsetTFlags.py_type(fvec), 0)
def AddFvec(builder: flatbuffers.Builder, fvec: int):
MonsterExtraAddFvec(builder, fvec)
def MonsterExtraStartFvecVector(builder, numElems: int) -> int:
return builder.StartVector(4, numElems, 4)
def StartFvecVector(builder, numElems: int) -> int:
return MonsterExtraStartFvecVector(builder, numElems)
def MonsterExtraEnd(builder: flatbuffers.Builder) -> int:
return builder.EndObject()
def End(builder: flatbuffers.Builder) -> int:
return MonsterExtraEnd(builder)
try:
from typing import List
except:
pass
class MonsterExtraT(object):
# MonsterExtraT
def __init__(
self,
d0 = float('nan'),
d1 = float('nan'),
d2 = float('inf'),
d3 = float('-inf'),
f0 = float('nan'),
f1 = float('nan'),
f2 = float('inf'),
f3 = float('-inf'),
dvec = None,
fvec = None,
):
self.d0 = d0 # type: float
self.d1 = d1 # type: float
self.d2 = d2 # type: float
self.d3 = d3 # type: float
self.f0 = f0 # type: float
self.f1 = f1 # type: float
self.f2 = f2 # type: float
self.f3 = f3 # type: float
self.dvec = dvec # type: Optional[List[float]]
self.fvec = fvec # type: Optional[List[float]]
@classmethod
def InitFromBuf(cls, buf, pos):
monsterExtra = MonsterExtra()
monsterExtra.Init(buf, pos)
return cls.InitFromObj(monsterExtra)
@classmethod
def InitFromPackedBuf(cls, buf, pos=0):
n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
return cls.InitFromBuf(buf, pos+n)
@classmethod
def InitFromObj(cls, monsterExtra):
x = MonsterExtraT()
x._UnPack(monsterExtra)
return x
def __eq__(self, other):
return type(self) == type(other) and \
self.d0 == other.d0 and \
self.d1 == other.d1 and \
self.d2 == other.d2 and \
self.d3 == other.d3 and \
self.f0 == other.f0 and \
self.f1 == other.f1 and \
self.f2 == other.f2 and \
self.f3 == other.f3 and \
self.dvec == other.dvec and \
self.fvec == other.fvec
# MonsterExtraT
def _UnPack(self, monsterExtra):
if monsterExtra is None:
return
self.d0 = monsterExtra.D0()
self.d1 = monsterExtra.D1()
self.d2 = monsterExtra.D2()
self.d3 = monsterExtra.D3()
self.f0 = monsterExtra.F0()
self.f1 = monsterExtra.F1()
self.f2 = monsterExtra.F2()
self.f3 = monsterExtra.F3()
if not monsterExtra.DvecIsNone():
if np is None:
self.dvec = []
for i in range(monsterExtra.DvecLength()):
self.dvec.append(monsterExtra.Dvec(i))
else:
self.dvec = monsterExtra.DvecAsNumpy()
if not monsterExtra.FvecIsNone():
if np is None:
self.fvec = []
for i in range(monsterExtra.FvecLength()):
self.fvec.append(monsterExtra.Fvec(i))
else:
self.fvec = monsterExtra.FvecAsNumpy()
# MonsterExtraT
def Pack(self, builder):
if self.dvec is not None:
if np is not None and type(self.dvec) is np.ndarray:
dvec = builder.CreateNumpyVector(self.dvec)
else:
MonsterExtraStartDvecVector(builder, len(self.dvec))
for i in reversed(range(len(self.dvec))):
builder.PrependFloat64(self.dvec[i])
dvec = builder.EndVector()
if self.fvec is not None:
if np is not None and type(self.fvec) is np.ndarray:
fvec = builder.CreateNumpyVector(self.fvec)
else:
MonsterExtraStartFvecVector(builder, len(self.fvec))
for i in reversed(range(len(self.fvec))):
builder.PrependFloat32(self.fvec[i])
fvec = builder.EndVector()
MonsterExtraStart(builder)
MonsterExtraAddD0(builder, self.d0)
MonsterExtraAddD1(builder, self.d1)
MonsterExtraAddD2(builder, self.d2)
MonsterExtraAddD3(builder, self.d3)
MonsterExtraAddF0(builder, self.f0)
MonsterExtraAddF1(builder, self.f1)
MonsterExtraAddF2(builder, self.f2)
MonsterExtraAddF3(builder, self.f3)
if self.dvec is not None:
MonsterExtraAddDvec(builder, dvec)
if self.fvec is not None:
MonsterExtraAddFvec(builder, fvec)
monsterExtra = MonsterExtraEnd(builder)
return monsterExtra