Skip to content

Commit

Permalink
make update_nested_field forward compatible
Browse files Browse the repository at this point in the history
Summary: We can make the `Struct.update_nested_field` API forward compatible by adding some thrift-python handling logic.

Reviewed By: Filip-F

Differential Revision: D68349566

fbshipit-source-id: ee681cc9bc1239d273027f33137c2040f842857f
  • Loading branch information
ahilger authored and facebook-github-bot committed Jan 22, 2025
1 parent d45a9f1 commit dd8fc71
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 12 deletions.
4 changes: 0 additions & 4 deletions thrift/lib/py3/test/auto_migrate/structs.py
Original file line number Diff line number Diff line change
Expand Up @@ -327,13 +327,11 @@ def test_dir(self) -> None:
self.assertEqual(expected, dir(easy))
self.assertEqual(["__iter__"], dir(Struct))

@brokenInAutoMigrate()
def test_update_nested_fields(self) -> None:
n = Nested1(a=Nested2(b=Nested3(c=easy(val=42, name="foo"))))
n = Struct.update_nested_field(n, {"a.b.c": easy(val=128)})
self.assertEqual(n.a.b.c.val, 128)

@brokenInAutoMigrate()
def test_update_multiple_nested_fields(self) -> None:
n = Nested1(a=Nested2(b=Nested3(c=easy(val=42, name="foo"))))
n = Struct.update_nested_field(
Expand All @@ -346,7 +344,6 @@ def test_update_multiple_nested_fields(self) -> None:
self.assertEqual(n.a.b.c.name, "bar")
self.assertEqual(n.a.b.c.val, 256)

@brokenInAutoMigrate()
def test_update_invalid_nested_fields(self) -> None:
n = Nested1(a=Nested2(b=Nested3(c=easy(val=42, name="foo"))))
with self.assertRaises(ValueError):
Expand All @@ -358,7 +355,6 @@ def test_update_invalid_nested_fields(self) -> None:
with self.assertRaises(ValueError):
Struct.update_nested_field(n, {"a.e.f": 0})

@brokenInAutoMigrate()
def test_update_conflicting_nested_fields(self) -> None:
n = Nested1(a=Nested2(b=Nested3(c=easy(val=42, name="foo"))))
with self.assertRaises(ValueError):
Expand Down
28 changes: 20 additions & 8 deletions thrift/lib/py3/types.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,15 @@ from types import MappingProxyType

from thrift.py3.exceptions cimport GeneratedError
from thrift.py3.serializer import deserialize, serialize
from thrift.python.types cimport BadEnum as _fbthrift_python_BadEnum
from thrift.python.types cimport (
BadEnum as _fbthrift_python_BadEnum,
_fbthrift_struct_update_nested_field as _fbthrift_python_struct_update_nested_field,
)
from thrift.python.types import (
Enum as _fbthrift_python_Enum,
EnumMeta as _fbthrift_python_EnumMeta,
Flag as _fbthrift_python_Flag,
Struct as _fbthrift_python_Struct,
StructOrUnion as _fbthrift_python_StructOrUnion,
)

Expand Down Expand Up @@ -84,19 +88,27 @@ cdef class StructMeta(type):
return struct._fbthrift_isset()

@staticmethod
def update_nested_field(Struct obj, path_to_values):
# There is some optimzation opportunity here for cases like this:
def update_nested_field(obj, path_to_values):
# There is an optimization opportunity here for cases like this:
# { "a.b.c": foo, "a.b.d": var }
try:
obj = _fbthrift_struct_update_nested_field(
obj,
[(p.split("."), v) for p, v in path_to_values.items()]
)
return obj
if isinstance(obj, _fbthrift_python_Struct):
return _fbthrift_python_struct_update_nested_field(
obj,
[(p.split("."), v) for p, v in path_to_values.items()]
)
elif isinstance(obj, Struct):
return _fbthrift_struct_update_nested_field(
obj,
[(p.split("."), v) for p, v in path_to_values.items()]
)
except (AttributeError, TypeError) as e:
# Unify different exception types to ValueError
raise ValueError(e)

# obj is not a py3 or python Struct
raise TypeError("`update_nested_field` requires thrift.py3.Struct or thrift.python.Struct")

# make the __module__ customizable
# this just enables the slot; impl here is ignored
def __module__(cls):
Expand Down
2 changes: 2 additions & 0 deletions thrift/lib/python/types.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,8 @@ cdef class Struct(StructOrUnion):
cdef _fbthrift_fully_populate_cache(Struct self)
cdef _initStructTupleWithValues(Struct self, object kwargs) except *

cdef Struct _fbthrift_struct_update_nested_field(Struct obj, list path_and_vals)

cdef tuple _validate_union_init_kwargs(
object union_class, object fields_enum_type, dict kwargs
)
Expand Down

0 comments on commit dd8fc71

Please sign in to comment.