From 688937efb7b6898cd7a756d5ee5218e07da55a22 Mon Sep 17 00:00:00 2001 From: TJ Yin Date: Mon, 25 Nov 2024 00:30:17 -0800 Subject: [PATCH] Expose getStandardImmutableDefaultValueForType to python Summary: The motivation is that in Thrift Patch, we want to be able to ensure a field to the default value. We need a way to get the standard default value in python. Reviewed By: praihan Differential Revision: D66269102 fbshipit-source-id: 0a033a5d2e931bb88f6fc25f978758a67daf5404 --- .../thrift/lib/python/test/typeinfo_test.py | 50 +++++++++++++++++++ .../thrift/src/thrift/lib/python/types.cpp | 10 ++++ .../thrift/src/thrift/lib/python/types.h | 39 +++++++++++++++ .../thrift/src/thrift/lib/python/types.pxd | 3 ++ .../thrift/src/thrift/lib/python/types.pyi | 23 +++++++++ .../thrift/src/thrift/lib/python/types.pyx | 4 ++ 6 files changed, 129 insertions(+) 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]))