Files
flatbuffers-bigfoot/tests/MyGame/Example/NestedUnion/Vec3.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

190 lines
5.4 KiB
Python

# automatically generated by the FlatBuffers compiler, do not modify
# namespace: NestedUnion
import flatbuffers
from flatbuffers.compat import import_numpy
from typing import Any
from MyGame.Example.NestedUnion.Test import Test
from typing import Optional
np = import_numpy()
class Vec3(object):
__slots__ = ['_tab']
@classmethod
def GetRootAs(cls, buf, offset: int = 0):
n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
x = Vec3()
x.Init(buf, n + offset)
return x
@classmethod
def GetRootAsVec3(cls, buf, offset=0):
"""This method is deprecated. Please switch to GetRootAs."""
return cls.GetRootAs(buf, offset)
# Vec3
def Init(self, buf: bytes, pos: int):
self._tab = flatbuffers.table.Table(buf, pos)
# Vec3
def X(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 0.0
# Vec3
def Y(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 0.0
# Vec3
def Z(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 0.0
# Vec3
def Test1(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 0.0
# Vec3
def Test2(self):
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
if o != 0:
return self._tab.Get(flatbuffers.number_types.Uint8Flags, o + self._tab.Pos)
return 0
# Vec3
def Test3(self) -> Optional[Test]:
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
if o != 0:
x = o + self._tab.Pos
obj = Test()
obj.Init(self._tab.Bytes, x)
return obj
return None
def Vec3Start(builder: flatbuffers.Builder):
builder.StartObject(6)
def Start(builder: flatbuffers.Builder):
Vec3Start(builder)
def Vec3AddX(builder: flatbuffers.Builder, x: float):
builder.PrependFloat64Slot(0, x, 0.0)
def AddX(builder: flatbuffers.Builder, x: float):
Vec3AddX(builder, x)
def Vec3AddY(builder: flatbuffers.Builder, y: float):
builder.PrependFloat64Slot(1, y, 0.0)
def AddY(builder: flatbuffers.Builder, y: float):
Vec3AddY(builder, y)
def Vec3AddZ(builder: flatbuffers.Builder, z: float):
builder.PrependFloat64Slot(2, z, 0.0)
def AddZ(builder: flatbuffers.Builder, z: float):
Vec3AddZ(builder, z)
def Vec3AddTest1(builder: flatbuffers.Builder, test1: float):
builder.PrependFloat64Slot(3, test1, 0.0)
def AddTest1(builder: flatbuffers.Builder, test1: float):
Vec3AddTest1(builder, test1)
def Vec3AddTest2(builder: flatbuffers.Builder, test2: int):
builder.PrependUint8Slot(4, test2, 0)
def AddTest2(builder: flatbuffers.Builder, test2: int):
Vec3AddTest2(builder, test2)
def Vec3AddTest3(builder: flatbuffers.Builder, test3: Any):
builder.PrependStructSlot(5, flatbuffers.number_types.UOffsetTFlags.py_type(test3), 0)
def AddTest3(builder: flatbuffers.Builder, test3: Any):
Vec3AddTest3(builder, test3)
def Vec3End(builder: flatbuffers.Builder) -> int:
return builder.EndObject()
def End(builder: flatbuffers.Builder) -> int:
return Vec3End(builder)
import MyGame.Example.NestedUnion.Test
try:
from typing import Optional
except:
pass
class Vec3T(object):
# Vec3T
def __init__(
self,
x = 0.0,
y = 0.0,
z = 0.0,
test1 = 0.0,
test2 = 0,
test3 = None,
):
self.x = x # type: float
self.y = y # type: float
self.z = z # type: float
self.test1 = test1 # type: float
self.test2 = test2 # type: int
self.test3 = test3 # type: Optional[MyGame.Example.NestedUnion.Test.TestT]
@classmethod
def InitFromBuf(cls, buf, pos):
vec3 = Vec3()
vec3.Init(buf, pos)
return cls.InitFromObj(vec3)
@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, vec3):
x = Vec3T()
x._UnPack(vec3)
return x
# Vec3T
def _UnPack(self, vec3):
if vec3 is None:
return
self.x = vec3.X()
self.y = vec3.Y()
self.z = vec3.Z()
self.test1 = vec3.Test1()
self.test2 = vec3.Test2()
if vec3.Test3() is not None:
self.test3 = MyGame.Example.NestedUnion.Test.TestT.InitFromObj(vec3.Test3())
# Vec3T
def Pack(self, builder):
Vec3Start(builder)
Vec3AddX(builder, self.x)
Vec3AddY(builder, self.y)
Vec3AddZ(builder, self.z)
Vec3AddTest1(builder, self.test1)
Vec3AddTest2(builder, self.test2)
if self.test3 is not None:
test3 = self.test3.Pack(builder)
Vec3AddTest3(builder, test3)
vec3 = Vec3End(builder)
return vec3