diff --git a/third-party/thrift/src/thrift/lib/python/mutable_types.pxd b/third-party/thrift/src/thrift/lib/python/mutable_types.pxd index e0990dfce5cbf..ed8b7c9ed33bc 100644 --- a/third-party/thrift/src/thrift/lib/python/mutable_types.pxd +++ b/third-party/thrift/src/thrift/lib/python/mutable_types.pxd @@ -111,6 +111,7 @@ cdef class MutableStruct(MutableStructOrUnion): cdef uint32_t _fbthrift_deserialize( MutableStruct self, IOBuf buf, Protocol proto ) except? 0 + cdef _fbthrift_reset_struct_field_state(MutableStruct self, object kwargs) except * cdef _fbthrift_get_field_value(MutableStruct self, int16_t index) cdef _initStructListWithValues(MutableStruct self, object kwargs) except * cdef _fbthrift_set_field_value(self, int16_t index, object value) except * diff --git a/third-party/thrift/src/thrift/lib/python/mutable_types.pyx b/third-party/thrift/src/thrift/lib/python/mutable_types.pyx index 6a7e8c5cad2f9..b1aa6e2a69e0f 100644 --- a/third-party/thrift/src/thrift/lib/python/mutable_types.pyx +++ b/third-party/thrift/src/thrift/lib/python/mutable_types.pyx @@ -289,20 +289,34 @@ cdef class MutableStruct(MutableStructOrUnion): "Python value" representation, as opposed to "internal data" representation (see `*TypeInfo` classes). """ + self._fbthrift_reset_struct_field_state(kwargs) + + def __init__(self, **kwargs): + pass + + def fbthrift_reset(self): + """ + Resets this Struct instance to its (standard) default values. + + After a call to this method, this instance is equal to a newly initialized + instance of this Struct type (with no initialization argument). + """ + self._fbthrift_reset_struct_field_state(kwargs={}) + + cdef _fbthrift_reset_struct_field_state(self, kwargs) except *: + """ + Resets all state in this Struct instance related to its fields (including + any cached values). + + Args: + kwargs (dict | None): see `__cinit__()`. + """ self._initStructListWithValues(kwargs) cdef MutableStructInfo mutable_struct_info = type(self)._fbthrift_mutable_struct_info self._fbthrift_field_cache = [None] * len(mutable_struct_info.fields) # Append `MutableStruct` instance, see `_fbthrift_has_struct_instance()` self._fbthrift_data.append(self) - def __init__(self, **kwargs): - pass - - def fbthrift_reset(self): - raise NotImplementedError( - "fbthrift_reset() is not (yet) implemented for mutable thrift-python " - "Struct types." - ) def __call__(self, **kwargs): self_copy = copy.deepcopy(self) @@ -321,9 +335,22 @@ cdef class MutableStruct(MutableStructOrUnion): assert self._fbthrift_has_struct_instance(self._fbthrift_data) return self._fbthrift_create(copy.deepcopy(self._fbthrift_data[:-1])) + + cdef _initStructListWithValues(self, kwargs) except *: - cdef MutableStructInfo mutable_struct_info = self._fbthrift_mutable_struct_info + """ + Initializes the underlying "struct data container". + + Assigns `self._fbthrift_data` to a "struct container" with `numFields + 1` + fields (initialized to the "isset" flags and values of the corresponding fields + - either the default ones or the ones provided by `kwargs`). Most notably, it + does NOT hold a reference to this struct instance at the end + (see `_fbthrift_has_struct_instance()`). + Args: + kwargs (dict | None): see `__cinit__()`. + """ + cdef MutableStructInfo mutable_struct_info = type(self)._fbthrift_mutable_struct_info # If no keyword arguments are provided, initialize the Struct with # default values. if not kwargs: diff --git a/third-party/thrift/src/thrift/test/thrift-python/struct_test.py b/third-party/thrift/src/thrift/test/thrift-python/struct_test.py index 3bf19694a7b86..149aea2a7b9ac 100644 --- a/third-party/thrift/src/thrift/test/thrift-python/struct_test.py +++ b/third-party/thrift/src/thrift/test/thrift-python/struct_test.py @@ -496,16 +496,9 @@ def test_reset(self) -> None: w = TestStructWithDefaultValuesMutable(optional_integer=123) self.assertEqual(w.optional_integer, 123) self.assertEqual(w.unqualified_integer, 42) - with self.assertRaisesRegex( - NotImplementedError, - ( - r"fbthrift_reset\(\) is not \(yet\) implemented for mutable " - "thrift-python Struct types." - ), - ): - w.fbthrift_reset() - # self.assertIsNone(w.optional_integer) - # self.assertEqual(w.unqualified_integer, 42) + w.fbthrift_reset() + self.assertIsNone(w.optional_integer) + self.assertEqual(w.unqualified_integer, 42) def test_equality_and_hashability(self) -> None: # Equality