Skip to content

Commit c11b6d2

Browse files
yoneyfacebook-github-bot
authored andcommitted
Add fbthrift_copy_from to MutableStruct
Summary: Add `fbthrift_copy_from()` to MutableStruct. Reviewed By: ahilger Differential Revision: D67942525 fbshipit-source-id: ffa228460f35d4989f3c71d241b4d9e12081e8e1
1 parent 66f8194 commit c11b6d2

File tree

3 files changed

+87
-0
lines changed

3 files changed

+87
-0
lines changed

third-party/thrift/src/thrift/lib/python/mutable_types.pyi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class MutableStruct(
3535
typing.Iterable[typing.Tuple[str, typing.Any]],
3636
metaclass=MutableStructMeta,
3737
):
38+
def fbthrift_copy_from(self, other: object) -> None: ...
3839
def _to_python(self) -> Struct: ...
3940

4041
class MutableUnion(MutableStructOrUnion, metaclass=MutableUnionMeta): ...

third-party/thrift/src/thrift/lib/python/mutable_types.pyx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,19 @@ cdef class MutableStruct(MutableStructOrUnion):
335335
assert self._fbthrift_has_struct_instance(self._fbthrift_data)
336336
return self._fbthrift_create(copy.deepcopy(self._fbthrift_data[:-1]))
337337

338+
def fbthrift_copy_from(self, other):
339+
"""
340+
Copies the content of `other` into the current struct.
341+
342+
It resets the current struct and then it assigns each field of `other`
343+
to `self`.
344+
"""
345+
if type(self) is not type(other):
346+
raise TypeError(f"Cannot copy from {type(other)} to {type(self)}")
338347

348+
self.fbthrift_reset()
349+
# Last element is the `MutableStruct` instance, do not copy
350+
self._fbthrift_data[:-1] = (<MutableStruct>other)._fbthrift_data[:-1]
339351

340352
cdef _initStructListWithValues(self, kwargs) except *:
341353
"""

third-party/thrift/src/thrift/test/thrift-python/struct_test.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2233,3 +2233,77 @@ def test_match(self) -> None:
22332233
self.assertIsNone(y)
22342234
case _:
22352235
self.fail("Expected match, got none.")
2236+
2237+
def test_fbthrift_copy_from(self) -> None:
2238+
"""
2239+
`lhs.fbthrift_copy_from(rhs)` copies the content of the `rhs` struct
2240+
into the lhs struct. It is semantically equivalent to assigning each
2241+
field of `rhs` to `lhs`."
2242+
"""
2243+
# Struct with primitive fields
2244+
s1 = TestStructAllThriftPrimitiveTypesMutable(
2245+
unqualified_bool=True,
2246+
optional_byte=0,
2247+
unqualified_i16=1,
2248+
optional_i32=2,
2249+
unqualified_i64=3,
2250+
optional_float=4.0,
2251+
unqualified_double=5.0,
2252+
optional_string="abc",
2253+
)
2254+
2255+
s2 = TestStructAllThriftPrimitiveTypesMutable()
2256+
self.assertNotEqual(s1, s2)
2257+
s2.fbthrift_copy_from(s1)
2258+
self.assertEqual(s1, s2)
2259+
2260+
# Struct with container fields
2261+
s3 = TestStructAllThriftContainerTypesMutable(
2262+
unqualified_list_i32=to_thrift_list([1, 2, 3]),
2263+
optional_set_string=to_thrift_set({"a", "b", "c"}),
2264+
unqualified_map_string_i32=to_thrift_map({"a": 1, "b": 2}),
2265+
)
2266+
2267+
s4 = TestStructAllThriftContainerTypesMutable()
2268+
self.assertNotEqual(s3, s4)
2269+
s4.fbthrift_copy_from(s3)
2270+
self.assertEqual(s3, s4)
2271+
2272+
# Container assignment is refernce semantics, after `fbthrift_copy_from()`
2273+
# s3 and s4 container fields are the "same" containers.
2274+
self.assertEqual([1, 2, 3], s3.unqualified_list_i32)
2275+
self.assertEqual([1, 2, 3], s4.unqualified_list_i32)
2276+
2277+
s3.unqualified_list_i32.append(4)
2278+
2279+
self.assertEqual([1, 2, 3, 4], s3.unqualified_list_i32)
2280+
self.assertEqual([1, 2, 3, 4], s4.unqualified_list_i32)
2281+
2282+
# Struct with struct fields
2283+
n2 = TestStructNested_2_Mutable(i32_field=2)
2284+
n1 = TestStructNested_1_Mutable(i32_field=3, nested_2=n2)
2285+
s5 = TestStructNested_0_Mutable(i32_field=5, nested_1=n1)
2286+
2287+
s6 = TestStructNested_0_Mutable()
2288+
self.assertNotEqual(s5, s6)
2289+
s6.fbthrift_copy_from(s5)
2290+
self.assertEqual(s5, s6)
2291+
2292+
# Struct assignment is refernce semantics, after `fbthrift_copy_from()`
2293+
# s5 and s4 struct fields are the "same" structs.
2294+
self.assertEqual(3, s5.nested_1.i32_field)
2295+
self.assertEqual(3, s6.nested_1.i32_field)
2296+
2297+
s5.nested_1.i32_field = 33
2298+
2299+
self.assertEqual(33, s5.nested_1.i32_field)
2300+
self.assertEqual(33, s6.nested_1.i32_field)
2301+
2302+
# `lhs` and `rhs` must be the same type
2303+
s7 = TestStructAllThriftPrimitiveTypesMutable()
2304+
with self.assertRaisesRegex(
2305+
TypeError,
2306+
"Cannot copy from.*TestStructAllThriftContainerTypes.*to"
2307+
".*TestStructAllThriftPrimitiveTypes",
2308+
):
2309+
s7.fbthrift_copy_from(TestStructAllThriftContainerTypesMutable())

0 commit comments

Comments
 (0)