diff --git a/python/flatbuffers/builder.py b/python/flatbuffers/builder.py index 02358d6d9..9bdf116ce 100644 --- a/python/flatbuffers/builder.py +++ b/python/flatbuffers/builder.py @@ -578,9 +578,11 @@ class Builder(object): self.Place(off, flags) def PrependSlot(self, flags, o, x, d): - N.enforce_number(x, flags) - N.enforce_number(d, flags) - if x != d or self.forceDefaults: + if x is not None: + N.enforce_number(x, flags) + if d is not None: + N.enforce_number(d, flags) + if x != d or (self.forceDefaults and d is not None): self.Prepend(flags, x) self.Slot(o) diff --git a/scripts/generate_code.py b/scripts/generate_code.py index 73c858466..f5df98e5a 100755 --- a/scripts/generate_code.py +++ b/scripts/generate_code.py @@ -350,7 +350,7 @@ flatc( optional_scalars_schema = "optional_scalars.fbs" flatc(["--java", "--kotlin", "--lobster", "--ts"], schema=optional_scalars_schema) -flatc(["--csharp", "--gen-object-api"], schema=optional_scalars_schema) +flatc(["--csharp", "--python", "--gen-object-api"], schema=optional_scalars_schema) flatc(RUST_OPTS, prefix="optional_scalars", schema=optional_scalars_schema) diff --git a/src/idl_gen_python.cpp b/src/idl_gen_python.cpp index 999a0d0a3..b7170b4c2 100644 --- a/src/idl_gen_python.cpp +++ b/src/idl_gen_python.cpp @@ -207,7 +207,9 @@ class PythonGenerator : public BaseGenerator { if (is_bool) { getter = "bool(" + getter + ")"; } code += Indent + Indent + Indent + "return " + getter + "\n"; std::string default_value; - if (is_bool) { + if (field.IsScalarOptional()) { + default_value = "None"; + } else if (is_bool) { default_value = field.value.constant == "0" ? "False" : "True"; } else { default_value = IsFloat(field.value.type.base_type) @@ -593,9 +595,13 @@ class PythonGenerator : public BaseGenerator { code += field_var; } code += ", "; - code += IsFloat(field.value.type.base_type) - ? float_const_gen_.GenFloatConstant(field) - : field.value.constant; + if (field.IsScalarOptional()) { + code += "None"; + } else if (IsFloat(field.value.type.base_type)) { + code += float_const_gen_.GenFloatConstant(field); + } else { + code += field.value.constant; + } code += ")\n"; if (!parser_.opts.one_file) { @@ -868,7 +874,9 @@ class PythonGenerator : public BaseGenerator { std::string GetDefaultValue(const FieldDef &field) const { BaseType base_type = field.value.type.base_type; - if (IsBool(base_type)) { + if (field.IsScalarOptional()) { + return "None"; + } else if (IsBool(base_type)) { return field.value.constant == "0" ? "False" : "True"; } else if (IsFloat(base_type)) { return float_const_gen_.GenFloatConstant(field); @@ -991,6 +999,9 @@ class PythonGenerator : public BaseGenerator { default: // Scalar or sting fields. field_type = GetBasePythonTypeForScalarAndString(base_type); + if (field.IsScalarOptional()) { + field_type = "Optional[" + field_type + "]"; + } break; } diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp index 323c6e5c2..8dcec894b 100644 --- a/src/idl_parser.cpp +++ b/src/idl_parser.cpp @@ -2469,7 +2469,7 @@ bool Parser::SupportsOptionalScalars(const flatbuffers::IDLOptions &opts) { IDLOptions::kRust | IDLOptions::kSwift | IDLOptions::kLobster | IDLOptions::kKotlin | IDLOptions::kCpp | IDLOptions::kJava | IDLOptions::kCSharp | IDLOptions::kTs | IDLOptions::kBinary | - IDLOptions::kGo; + IDLOptions::kGo | IDLOptions::kPython; unsigned long langs = opts.lang_to_generate; return (langs > 0 && langs < IDLOptions::kMAX) && !(langs & ~supported_langs); } diff --git a/tests/optional_scalars/OptionalByte.py b/tests/optional_scalars/OptionalByte.py new file mode 100644 index 000000000..5e7df8b6b --- /dev/null +++ b/tests/optional_scalars/OptionalByte.py @@ -0,0 +1,8 @@ +# automatically generated by the FlatBuffers compiler, do not modify + +# namespace: optional_scalars + +class OptionalByte(object): + None_ = 0 + One = 1 + Two = 2 diff --git a/tests/optional_scalars/ScalarStuff.py b/tests/optional_scalars/ScalarStuff.py new file mode 100644 index 000000000..4dea123be --- /dev/null +++ b/tests/optional_scalars/ScalarStuff.py @@ -0,0 +1,532 @@ +# automatically generated by the FlatBuffers compiler, do not modify + +# namespace: optional_scalars + +import flatbuffers +from flatbuffers.compat import import_numpy +np = import_numpy() + +class ScalarStuff(object): + __slots__ = ['_tab'] + + @classmethod + def GetRootAs(cls, buf, offset=0): + n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset) + x = ScalarStuff() + x.Init(buf, n + offset) + return x + + @classmethod + def GetRootAsScalarStuff(cls, buf, offset=0): + """This method is deprecated. Please switch to GetRootAs.""" + return cls.GetRootAs(buf, offset) + @classmethod + def ScalarStuffBufferHasIdentifier(cls, buf, offset, size_prefixed=False): + return flatbuffers.util.BufferHasIdentifier(buf, offset, b"\x4E\x55\x4C\x4C", size_prefixed=size_prefixed) + + # ScalarStuff + def Init(self, buf, pos): + self._tab = flatbuffers.table.Table(buf, pos) + + # ScalarStuff + def JustI8(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos) + return 0 + + # ScalarStuff + def MaybeI8(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos) + return None + + # ScalarStuff + def DefaultI8(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos) + return 42 + + # ScalarStuff + def JustU8(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Uint8Flags, o + self._tab.Pos) + return 0 + + # ScalarStuff + def MaybeU8(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 None + + # ScalarStuff + def DefaultU8(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Uint8Flags, o + self._tab.Pos) + return 42 + + # ScalarStuff + def JustI16(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(16)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Int16Flags, o + self._tab.Pos) + return 0 + + # ScalarStuff + def MaybeI16(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(18)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Int16Flags, o + self._tab.Pos) + return None + + # ScalarStuff + def DefaultI16(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(20)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Int16Flags, o + self._tab.Pos) + return 42 + + # ScalarStuff + def JustU16(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(22)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Uint16Flags, o + self._tab.Pos) + return 0 + + # ScalarStuff + def MaybeU16(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(24)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Uint16Flags, o + self._tab.Pos) + return None + + # ScalarStuff + def DefaultU16(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(26)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Uint16Flags, o + self._tab.Pos) + return 42 + + # ScalarStuff + def JustI32(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(28)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos) + return 0 + + # ScalarStuff + def MaybeI32(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(30)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos) + return None + + # ScalarStuff + def DefaultI32(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(32)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos) + return 42 + + # ScalarStuff + def JustU32(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(34)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Uint32Flags, o + self._tab.Pos) + return 0 + + # ScalarStuff + def MaybeU32(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(36)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Uint32Flags, o + self._tab.Pos) + return None + + # ScalarStuff + def DefaultU32(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(38)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Uint32Flags, o + self._tab.Pos) + return 42 + + # ScalarStuff + def JustI64(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(40)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Int64Flags, o + self._tab.Pos) + return 0 + + # ScalarStuff + def MaybeI64(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(42)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Int64Flags, o + self._tab.Pos) + return None + + # ScalarStuff + def DefaultI64(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(44)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Int64Flags, o + self._tab.Pos) + return 42 + + # ScalarStuff + def JustU64(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(46)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Uint64Flags, o + self._tab.Pos) + return 0 + + # ScalarStuff + def MaybeU64(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(48)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Uint64Flags, o + self._tab.Pos) + return None + + # ScalarStuff + def DefaultU64(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(50)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Uint64Flags, o + self._tab.Pos) + return 42 + + # ScalarStuff + def JustF32(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(52)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos) + return 0.0 + + # ScalarStuff + def MaybeF32(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(54)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos) + return None + + # ScalarStuff + def DefaultF32(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(56)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos) + return 42.0 + + # ScalarStuff + def JustF64(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(58)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Float64Flags, o + self._tab.Pos) + return 0.0 + + # ScalarStuff + def MaybeF64(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(60)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Float64Flags, o + self._tab.Pos) + return None + + # ScalarStuff + def DefaultF64(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(62)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Float64Flags, o + self._tab.Pos) + return 42.0 + + # ScalarStuff + def JustBool(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(64)) + if o != 0: + return bool(self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos)) + return False + + # ScalarStuff + def MaybeBool(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(66)) + if o != 0: + return bool(self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos)) + return None + + # ScalarStuff + def DefaultBool(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(68)) + if o != 0: + return bool(self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos)) + return True + + # ScalarStuff + def JustEnum(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(70)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos) + return 0 + + # ScalarStuff + def MaybeEnum(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(72)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos) + return None + + # ScalarStuff + def DefaultEnum(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(74)) + if o != 0: + return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos) + return 1 + +def ScalarStuffStart(builder): builder.StartObject(36) +def Start(builder): + return ScalarStuffStart(builder) +def ScalarStuffAddJustI8(builder, justI8): builder.PrependInt8Slot(0, justI8, 0) +def AddJustI8(builder, justI8): + return ScalarStuffAddJustI8(builder, justI8) +def ScalarStuffAddMaybeI8(builder, maybeI8): builder.PrependInt8Slot(1, maybeI8, None) +def AddMaybeI8(builder, maybeI8): + return ScalarStuffAddMaybeI8(builder, maybeI8) +def ScalarStuffAddDefaultI8(builder, defaultI8): builder.PrependInt8Slot(2, defaultI8, 42) +def AddDefaultI8(builder, defaultI8): + return ScalarStuffAddDefaultI8(builder, defaultI8) +def ScalarStuffAddJustU8(builder, justU8): builder.PrependUint8Slot(3, justU8, 0) +def AddJustU8(builder, justU8): + return ScalarStuffAddJustU8(builder, justU8) +def ScalarStuffAddMaybeU8(builder, maybeU8): builder.PrependUint8Slot(4, maybeU8, None) +def AddMaybeU8(builder, maybeU8): + return ScalarStuffAddMaybeU8(builder, maybeU8) +def ScalarStuffAddDefaultU8(builder, defaultU8): builder.PrependUint8Slot(5, defaultU8, 42) +def AddDefaultU8(builder, defaultU8): + return ScalarStuffAddDefaultU8(builder, defaultU8) +def ScalarStuffAddJustI16(builder, justI16): builder.PrependInt16Slot(6, justI16, 0) +def AddJustI16(builder, justI16): + return ScalarStuffAddJustI16(builder, justI16) +def ScalarStuffAddMaybeI16(builder, maybeI16): builder.PrependInt16Slot(7, maybeI16, None) +def AddMaybeI16(builder, maybeI16): + return ScalarStuffAddMaybeI16(builder, maybeI16) +def ScalarStuffAddDefaultI16(builder, defaultI16): builder.PrependInt16Slot(8, defaultI16, 42) +def AddDefaultI16(builder, defaultI16): + return ScalarStuffAddDefaultI16(builder, defaultI16) +def ScalarStuffAddJustU16(builder, justU16): builder.PrependUint16Slot(9, justU16, 0) +def AddJustU16(builder, justU16): + return ScalarStuffAddJustU16(builder, justU16) +def ScalarStuffAddMaybeU16(builder, maybeU16): builder.PrependUint16Slot(10, maybeU16, None) +def AddMaybeU16(builder, maybeU16): + return ScalarStuffAddMaybeU16(builder, maybeU16) +def ScalarStuffAddDefaultU16(builder, defaultU16): builder.PrependUint16Slot(11, defaultU16, 42) +def AddDefaultU16(builder, defaultU16): + return ScalarStuffAddDefaultU16(builder, defaultU16) +def ScalarStuffAddJustI32(builder, justI32): builder.PrependInt32Slot(12, justI32, 0) +def AddJustI32(builder, justI32): + return ScalarStuffAddJustI32(builder, justI32) +def ScalarStuffAddMaybeI32(builder, maybeI32): builder.PrependInt32Slot(13, maybeI32, None) +def AddMaybeI32(builder, maybeI32): + return ScalarStuffAddMaybeI32(builder, maybeI32) +def ScalarStuffAddDefaultI32(builder, defaultI32): builder.PrependInt32Slot(14, defaultI32, 42) +def AddDefaultI32(builder, defaultI32): + return ScalarStuffAddDefaultI32(builder, defaultI32) +def ScalarStuffAddJustU32(builder, justU32): builder.PrependUint32Slot(15, justU32, 0) +def AddJustU32(builder, justU32): + return ScalarStuffAddJustU32(builder, justU32) +def ScalarStuffAddMaybeU32(builder, maybeU32): builder.PrependUint32Slot(16, maybeU32, None) +def AddMaybeU32(builder, maybeU32): + return ScalarStuffAddMaybeU32(builder, maybeU32) +def ScalarStuffAddDefaultU32(builder, defaultU32): builder.PrependUint32Slot(17, defaultU32, 42) +def AddDefaultU32(builder, defaultU32): + return ScalarStuffAddDefaultU32(builder, defaultU32) +def ScalarStuffAddJustI64(builder, justI64): builder.PrependInt64Slot(18, justI64, 0) +def AddJustI64(builder, justI64): + return ScalarStuffAddJustI64(builder, justI64) +def ScalarStuffAddMaybeI64(builder, maybeI64): builder.PrependInt64Slot(19, maybeI64, None) +def AddMaybeI64(builder, maybeI64): + return ScalarStuffAddMaybeI64(builder, maybeI64) +def ScalarStuffAddDefaultI64(builder, defaultI64): builder.PrependInt64Slot(20, defaultI64, 42) +def AddDefaultI64(builder, defaultI64): + return ScalarStuffAddDefaultI64(builder, defaultI64) +def ScalarStuffAddJustU64(builder, justU64): builder.PrependUint64Slot(21, justU64, 0) +def AddJustU64(builder, justU64): + return ScalarStuffAddJustU64(builder, justU64) +def ScalarStuffAddMaybeU64(builder, maybeU64): builder.PrependUint64Slot(22, maybeU64, None) +def AddMaybeU64(builder, maybeU64): + return ScalarStuffAddMaybeU64(builder, maybeU64) +def ScalarStuffAddDefaultU64(builder, defaultU64): builder.PrependUint64Slot(23, defaultU64, 42) +def AddDefaultU64(builder, defaultU64): + return ScalarStuffAddDefaultU64(builder, defaultU64) +def ScalarStuffAddJustF32(builder, justF32): builder.PrependFloat32Slot(24, justF32, 0.0) +def AddJustF32(builder, justF32): + return ScalarStuffAddJustF32(builder, justF32) +def ScalarStuffAddMaybeF32(builder, maybeF32): builder.PrependFloat32Slot(25, maybeF32, None) +def AddMaybeF32(builder, maybeF32): + return ScalarStuffAddMaybeF32(builder, maybeF32) +def ScalarStuffAddDefaultF32(builder, defaultF32): builder.PrependFloat32Slot(26, defaultF32, 42.0) +def AddDefaultF32(builder, defaultF32): + return ScalarStuffAddDefaultF32(builder, defaultF32) +def ScalarStuffAddJustF64(builder, justF64): builder.PrependFloat64Slot(27, justF64, 0.0) +def AddJustF64(builder, justF64): + return ScalarStuffAddJustF64(builder, justF64) +def ScalarStuffAddMaybeF64(builder, maybeF64): builder.PrependFloat64Slot(28, maybeF64, None) +def AddMaybeF64(builder, maybeF64): + return ScalarStuffAddMaybeF64(builder, maybeF64) +def ScalarStuffAddDefaultF64(builder, defaultF64): builder.PrependFloat64Slot(29, defaultF64, 42.0) +def AddDefaultF64(builder, defaultF64): + return ScalarStuffAddDefaultF64(builder, defaultF64) +def ScalarStuffAddJustBool(builder, justBool): builder.PrependBoolSlot(30, justBool, 0) +def AddJustBool(builder, justBool): + return ScalarStuffAddJustBool(builder, justBool) +def ScalarStuffAddMaybeBool(builder, maybeBool): builder.PrependBoolSlot(31, maybeBool, None) +def AddMaybeBool(builder, maybeBool): + return ScalarStuffAddMaybeBool(builder, maybeBool) +def ScalarStuffAddDefaultBool(builder, defaultBool): builder.PrependBoolSlot(32, defaultBool, 1) +def AddDefaultBool(builder, defaultBool): + return ScalarStuffAddDefaultBool(builder, defaultBool) +def ScalarStuffAddJustEnum(builder, justEnum): builder.PrependInt8Slot(33, justEnum, 0) +def AddJustEnum(builder, justEnum): + return ScalarStuffAddJustEnum(builder, justEnum) +def ScalarStuffAddMaybeEnum(builder, maybeEnum): builder.PrependInt8Slot(34, maybeEnum, None) +def AddMaybeEnum(builder, maybeEnum): + return ScalarStuffAddMaybeEnum(builder, maybeEnum) +def ScalarStuffAddDefaultEnum(builder, defaultEnum): builder.PrependInt8Slot(35, defaultEnum, 1) +def AddDefaultEnum(builder, defaultEnum): + return ScalarStuffAddDefaultEnum(builder, defaultEnum) +def ScalarStuffEnd(builder): return builder.EndObject() +def End(builder): + return ScalarStuffEnd(builder) + +class ScalarStuffT(object): + + # ScalarStuffT + def __init__(self): + self.justI8 = 0 # type: int + self.maybeI8 = None # type: Optional[int] + self.defaultI8 = 42 # type: int + self.justU8 = 0 # type: int + self.maybeU8 = None # type: Optional[int] + self.defaultU8 = 42 # type: int + self.justI16 = 0 # type: int + self.maybeI16 = None # type: Optional[int] + self.defaultI16 = 42 # type: int + self.justU16 = 0 # type: int + self.maybeU16 = None # type: Optional[int] + self.defaultU16 = 42 # type: int + self.justI32 = 0 # type: int + self.maybeI32 = None # type: Optional[int] + self.defaultI32 = 42 # type: int + self.justU32 = 0 # type: int + self.maybeU32 = None # type: Optional[int] + self.defaultU32 = 42 # type: int + self.justI64 = 0 # type: int + self.maybeI64 = None # type: Optional[int] + self.defaultI64 = 42 # type: int + self.justU64 = 0 # type: int + self.maybeU64 = None # type: Optional[int] + self.defaultU64 = 42 # type: int + self.justF32 = 0.0 # type: float + self.maybeF32 = None # type: Optional[float] + self.defaultF32 = 42.0 # type: float + self.justF64 = 0.0 # type: float + self.maybeF64 = None # type: Optional[float] + self.defaultF64 = 42.0 # type: float + self.justBool = False # type: bool + self.maybeBool = None # type: Optional[bool] + self.defaultBool = True # type: bool + self.justEnum = 0 # type: int + self.maybeEnum = None # type: Optional[int] + self.defaultEnum = 1 # type: int + + @classmethod + def InitFromBuf(cls, buf, pos): + scalarStuff = ScalarStuff() + scalarStuff.Init(buf, pos) + return cls.InitFromObj(scalarStuff) + + @classmethod + def InitFromObj(cls, scalarStuff): + x = ScalarStuffT() + x._UnPack(scalarStuff) + return x + + # ScalarStuffT + def _UnPack(self, scalarStuff): + if scalarStuff is None: + return + self.justI8 = scalarStuff.JustI8() + self.maybeI8 = scalarStuff.MaybeI8() + self.defaultI8 = scalarStuff.DefaultI8() + self.justU8 = scalarStuff.JustU8() + self.maybeU8 = scalarStuff.MaybeU8() + self.defaultU8 = scalarStuff.DefaultU8() + self.justI16 = scalarStuff.JustI16() + self.maybeI16 = scalarStuff.MaybeI16() + self.defaultI16 = scalarStuff.DefaultI16() + self.justU16 = scalarStuff.JustU16() + self.maybeU16 = scalarStuff.MaybeU16() + self.defaultU16 = scalarStuff.DefaultU16() + self.justI32 = scalarStuff.JustI32() + self.maybeI32 = scalarStuff.MaybeI32() + self.defaultI32 = scalarStuff.DefaultI32() + self.justU32 = scalarStuff.JustU32() + self.maybeU32 = scalarStuff.MaybeU32() + self.defaultU32 = scalarStuff.DefaultU32() + self.justI64 = scalarStuff.JustI64() + self.maybeI64 = scalarStuff.MaybeI64() + self.defaultI64 = scalarStuff.DefaultI64() + self.justU64 = scalarStuff.JustU64() + self.maybeU64 = scalarStuff.MaybeU64() + self.defaultU64 = scalarStuff.DefaultU64() + self.justF32 = scalarStuff.JustF32() + self.maybeF32 = scalarStuff.MaybeF32() + self.defaultF32 = scalarStuff.DefaultF32() + self.justF64 = scalarStuff.JustF64() + self.maybeF64 = scalarStuff.MaybeF64() + self.defaultF64 = scalarStuff.DefaultF64() + self.justBool = scalarStuff.JustBool() + self.maybeBool = scalarStuff.MaybeBool() + self.defaultBool = scalarStuff.DefaultBool() + self.justEnum = scalarStuff.JustEnum() + self.maybeEnum = scalarStuff.MaybeEnum() + self.defaultEnum = scalarStuff.DefaultEnum() + + # ScalarStuffT + def Pack(self, builder): + ScalarStuffStart(builder) + ScalarStuffAddJustI8(builder, self.justI8) + ScalarStuffAddMaybeI8(builder, self.maybeI8) + ScalarStuffAddDefaultI8(builder, self.defaultI8) + ScalarStuffAddJustU8(builder, self.justU8) + ScalarStuffAddMaybeU8(builder, self.maybeU8) + ScalarStuffAddDefaultU8(builder, self.defaultU8) + ScalarStuffAddJustI16(builder, self.justI16) + ScalarStuffAddMaybeI16(builder, self.maybeI16) + ScalarStuffAddDefaultI16(builder, self.defaultI16) + ScalarStuffAddJustU16(builder, self.justU16) + ScalarStuffAddMaybeU16(builder, self.maybeU16) + ScalarStuffAddDefaultU16(builder, self.defaultU16) + ScalarStuffAddJustI32(builder, self.justI32) + ScalarStuffAddMaybeI32(builder, self.maybeI32) + ScalarStuffAddDefaultI32(builder, self.defaultI32) + ScalarStuffAddJustU32(builder, self.justU32) + ScalarStuffAddMaybeU32(builder, self.maybeU32) + ScalarStuffAddDefaultU32(builder, self.defaultU32) + ScalarStuffAddJustI64(builder, self.justI64) + ScalarStuffAddMaybeI64(builder, self.maybeI64) + ScalarStuffAddDefaultI64(builder, self.defaultI64) + ScalarStuffAddJustU64(builder, self.justU64) + ScalarStuffAddMaybeU64(builder, self.maybeU64) + ScalarStuffAddDefaultU64(builder, self.defaultU64) + ScalarStuffAddJustF32(builder, self.justF32) + ScalarStuffAddMaybeF32(builder, self.maybeF32) + ScalarStuffAddDefaultF32(builder, self.defaultF32) + ScalarStuffAddJustF64(builder, self.justF64) + ScalarStuffAddMaybeF64(builder, self.maybeF64) + ScalarStuffAddDefaultF64(builder, self.defaultF64) + ScalarStuffAddJustBool(builder, self.justBool) + ScalarStuffAddMaybeBool(builder, self.maybeBool) + ScalarStuffAddDefaultBool(builder, self.defaultBool) + ScalarStuffAddJustEnum(builder, self.justEnum) + ScalarStuffAddMaybeEnum(builder, self.maybeEnum) + ScalarStuffAddDefaultEnum(builder, self.defaultEnum) + scalarStuff = ScalarStuffEnd(builder) + return scalarStuff diff --git a/tests/optional_scalars/__init__.py b/tests/optional_scalars/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/py_test.py b/tests/py_test.py index ed966d51d..5e3c54735 100644 --- a/tests/py_test.py +++ b/tests/py_test.py @@ -48,6 +48,8 @@ import MyGame.Example.ArrayStruct # refers to generated code import MyGame.Example.NestedStruct # refers to generated code import MyGame.Example.TestEnum # refers to generated code import monster_test_generated # the one-file version +import optional_scalars +import optional_scalars.ScalarStuff def create_namespace_shortcut(is_onefile): @@ -274,6 +276,35 @@ class TestObjectBasedAPI(unittest.TestCase): self.assertEqual(monster2.VectorOfEnumsLength(), 0) self.assertTrue(monster2.VectorOfEnumsIsNone()) + def test_optional_scalars_with_pack_and_unpack(self): + """ Serializes and deserializes between a buffer with optional values (no + specific values are filled when the buffer is created) and its python + object. + """ + # Creates a flatbuffer with optional values. + b1 = flatbuffers.Builder(0) + optional_scalars.ScalarStuff.ScalarStuffStart(b1) + gen_opt = optional_scalars.ScalarStuff.ScalarStuffEnd(b1) + b1.Finish(gen_opt) + + # Converts the flatbuffer into the object class. + opts1 = optional_scalars.ScalarStuff.ScalarStuff.GetRootAs(b1.Bytes, b1.Head()) + optsT1 = optional_scalars.ScalarStuff.ScalarStuffT.InitFromObj(opts1) + + # Packs the object class into another flatbuffer. + b2 = flatbuffers.Builder(0) + b2.Finish(optsT1.Pack(b2)) + opts2 = optional_scalars.ScalarStuff.ScalarStuff.GetRootAs(b2.Bytes, b2.Head()) + optsT2 = optional_scalars.ScalarStuff.ScalarStuffT.InitFromObj(opts2) + # Checks the default values. + self.assertTrue(opts2.JustI8() == 0) + self.assertTrue(opts2.MaybeF32() is None) + self.assertTrue(opts2.DefaultBool() is True) + self.assertTrue(optsT2.justU16 == 0) + self.assertTrue(optsT2.maybeEnum is None) + self.assertTrue(optsT2.defaultU64 == 42) + + class TestAllMutableCodePathsOfExampleSchema(unittest.TestCase): """ Tests the object API generated for monster_test.fbs for mutation