diff --git a/third-party/thrift/src/thrift/lib/python/test/typeinfo_test.py b/third-party/thrift/src/thrift/lib/python/test/typeinfo_test.py index 1edba7af28522..89573f9482d54 100644 --- a/third-party/thrift/src/thrift/lib/python/test/typeinfo_test.py +++ b/third-party/thrift/src/thrift/lib/python/test/typeinfo_test.py @@ -30,6 +30,7 @@ from thrift.python.types import ( AdaptedTypeInfo, EnumTypeInfo, + get_standard_immutable_default_value_for_type, IntegerTypeInfo, IOBufTypeInfo, ListTypeInfo, @@ -38,6 +39,15 @@ StringTypeInfo, StructTypeInfo, TypeInfo, + typeinfo_binary, + typeinfo_bool, + typeinfo_byte, + typeinfo_double, + typeinfo_float, + typeinfo_i16, + typeinfo_i32, + typeinfo_i64, + typeinfo_string, ) # This python file serves as a boilerplate code for executing tests written @@ -125,3 +135,43 @@ def test_MutableMapTypeInfo(self) -> None: def test_MutableStructTypeInfo(self) -> None: CTests(self).test_MutableStructTypeInfo() + + def test_StandardDefaultValue(self) -> None: + self.assertEqual( + get_standard_immutable_default_value_for_type(typeinfo_bool), False + ) + self.assertEqual( + get_standard_immutable_default_value_for_type(typeinfo_byte), 0 + ) + self.assertEqual(get_standard_immutable_default_value_for_type(typeinfo_i16), 0) + self.assertEqual(get_standard_immutable_default_value_for_type(typeinfo_i32), 0) + self.assertEqual(get_standard_immutable_default_value_for_type(typeinfo_i64), 0) + self.assertEqual( + get_standard_immutable_default_value_for_type(typeinfo_float), 0.0 + ) + self.assertEqual( + get_standard_immutable_default_value_for_type(typeinfo_double), 0.0 + ) + self.assertEqual( + get_standard_immutable_default_value_for_type(typeinfo_string), "" + ) + self.assertEqual( + get_standard_immutable_default_value_for_type(typeinfo_binary), b"" + ) + + self.assertEqual( + get_standard_immutable_default_value_for_type( + ListTypeInfo(typeinfo_string) + ), + [], + ) + self.assertEqual( + get_standard_immutable_default_value_for_type(SetTypeInfo(typeinfo_string)), + set(), + ) + self.assertEqual( + get_standard_immutable_default_value_for_type( + MapTypeInfo(typeinfo_string, typeinfo_string) + ), + {}, + ) diff --git a/third-party/thrift/src/thrift/lib/python/types.cpp b/third-party/thrift/src/thrift/lib/python/types.cpp index e38ca7d3763b6..f555d37aac7c0 100644 --- a/third-party/thrift/src/thrift/lib/python/types.cpp +++ b/third-party/thrift/src/thrift/lib/python/types.cpp @@ -1692,6 +1692,16 @@ const detail::TypeInfo iobufTypeInfo{ /* .typeExt */ &ioBufFieldType, }; +PyObject* getStandardImmutableDefaultValuePtrForType( + const detail::TypeInfo& typeInfo) { + auto ret = getStandardImmutableDefaultValueForType(typeInfo); + return std::get<0>(ret).release(); +} +PyObject* getStandardMutableDefaultValuePtrForType( + const detail::TypeInfo& typeInfo) { + auto ret = getStandardMutableDefaultValueForType(typeInfo); + return std::get<0>(ret).release(); +} } // namespace apache::thrift::python namespace apache::thrift::python::capi { diff --git a/third-party/thrift/src/thrift/lib/python/types.h b/third-party/thrift/src/thrift/lib/python/types.h index 955d5ac00a12e..be2067f628625 100644 --- a/third-party/thrift/src/thrift/lib/python/types.h +++ b/third-party/thrift/src/thrift/lib/python/types.h @@ -838,6 +838,45 @@ inline const PyObject* getListObjectItemBase(const void* pyList) { return reinterpret_cast(&PyList_GET_ITEM(pyList, 0)); } +/** + * Returns the appropriate standard immutable default value for the given + * `typeInfo`. + * + * The standard default values are as follows: + * * `0L` for integral numbers. + * * `0d` for floating-point numbers. + * * `false` for booleans. + * * `""` (i.e., the empty string) for strings and `binary` fields (or an + * empty `IOBuf` if applicable). + * * An empty `tuple` for lists and maps. + * * An empty `frozenset` for sets. + * * A recursively default-initialized instance for structs and unions. + * + * @throws if there is no standard default value + */ +PyObject* getStandardImmutableDefaultValuePtrForType( + const detail::TypeInfo& typeInfo); + +/** + * Returns the appropriate standard mutable default value for the given + * `typeInfo`. + * + * The standard default values are as follows: + * * `0L` for integral numbers. + * * `0d` for floating-point numbers. + * * `false` for booleans. + * * `""` (i.e., the empty string) for strings and `binary` fields (or an + * empty `IOBuf` if applicable). + * * An empty `list` for lists. + * * An empty `dict` for maps. + * * An empty `set` for sets. + * * A recursively default-initialized instance for structs and unions. + * + * @throws if there is no standard default value + */ +PyObject* getStandardMutableDefaultValuePtrForType( + const detail::TypeInfo& typeInfo); + } // namespace apache::thrift::python namespace apache::thrift::python::capi { diff --git a/third-party/thrift/src/thrift/lib/python/types.pxd b/third-party/thrift/src/thrift/lib/python/types.pxd index 25cd400fb5e0b..3eb09d0a16c02 100644 --- a/third-party/thrift/src/thrift/lib/python/types.pxd +++ b/third-party/thrift/src/thrift/lib/python/types.pxd @@ -82,6 +82,9 @@ cdef extern from "" namespace "::apache::thrift::pyth const cDynamicStructInfo& structInfo ) except+ cdef void setStructIsset(object, int index, bint set) except+ + cdef object getStandardImmutableDefaultValuePtrForType( + const cTypeInfo& typeInfo + ) except+ cdef const cTypeInfo& boolTypeInfo cdef const cTypeInfo& byteTypeInfo diff --git a/third-party/thrift/src/thrift/lib/python/types.pyi b/third-party/thrift/src/thrift/lib/python/types.pyi index 875c03542c9d7..39f887cdd1128 100644 --- a/third-party/thrift/src/thrift/lib/python/types.pyi +++ b/third-party/thrift/src/thrift/lib/python/types.pyi @@ -16,6 +16,9 @@ import enum import typing +from typing import Never + +from folly.iobuf import IOBuf from thrift.python.adapter import Adapter from thrift.python.exceptions import GeneratedError @@ -197,6 +200,26 @@ def update_nested_field( obj: sT, path_to_values: typing.Mapping[str, typing.Any] ) -> sT: ... +_DefaultFieldValue = typing.Union[ + bool, + int, + float, + str, + bytes, + IOBuf, + Enum, + Struct, + Union, + GeneratedError, + typing.Sequence[Never], + typing.AbstractSet[Never], + typing.Mapping[Never, Never], +] + +def get_standard_immutable_default_value_for_type( + type_info: AnyTypeInfo, +) -> _DefaultFieldValue: ... + class _fbthrift_ResponseStreamResult(Struct, typing.Generic[TChunk]): success: typing.Final[TChunk] diff --git a/third-party/thrift/src/thrift/lib/python/types.pyx b/third-party/thrift/src/thrift/lib/python/types.pyx index 1f7a042d0298a..7563919f0fd07 100644 --- a/third-party/thrift/src/thrift/lib/python/types.pyx +++ b/third-party/thrift/src/thrift/lib/python/types.pyx @@ -2539,3 +2539,7 @@ cdef class ServiceInterface: async def onStopRequested(self): pass + + +def get_standard_immutable_default_value_for_type(TypeInfoBase typeinfo): + return typeinfo.to_python_value(getStandardImmutableDefaultValuePtrForType(typeinfo.get_cTypeInfo()[0]))