def _serialize_struct_type( struct_typed_value: Any, type_spec: computation_types.StructType, ) -> computation_types.StructType: """Serializes a value of tuple type.""" value_structure = structure.from_container(struct_typed_value) if len(value_structure) != len(type_spec): raise TypeError( 'Cannot serialize a struct value of ' f'{len(value_structure)} elements to a struct type ' f'requiring {len(type_spec)} elements. Trying to serialize' f'\n{struct_typed_value!r}\nto\n{type_spec}.') type_elem_iter = structure.iter_elements(type_spec) val_elem_iter = structure.iter_elements(value_structure) elements = [] for (e_name, e_type), (_, e_val) in zip(type_elem_iter, val_elem_iter): e_value, _ = serialize_value(e_val, e_type) if e_name: element = executor_pb2.Value.Struct.Element(name=e_name, value=e_value) else: element = executor_pb2.Value.Struct.Element(value=e_value) elements.append(element) value_proto = executor_pb2.Value(struct=executor_pb2.Value.Struct( element=elements)) return value_proto, type_spec
def serialize_value(value, type_spec=None): """Serializes a value into `executor_pb2.Value`. Args: value: A value to be serialized. type_spec: Optional type spec, a `tff.Type` or something convertible to it. Returns: An instance of `executor_pb2.Value` with the serialized content of `value`. Returns: TypeError: If the arguments are of the wrong types. ValueError: If the value is malformed. """ type_spec = computation_types.to_type(type_spec) if isinstance(value, computation_pb2.Computation): if type_spec is not None: type_utils.reconcile_value_type_with_type_spec( type_serialization.deserialize_type(value.type), type_spec) return executor_pb2.Value(computation=value) elif isinstance(value, computation_impl.ComputationImpl): return serialize_value( computation_impl.ComputationImpl.get_proto(value), type_utils.reconcile_value_with_type_spec(value, type_spec)) elif isinstance(type_spec, computation_types.TensorType): return serialize_tensor_value(value, type_spec) else: raise ValueError( 'Unable to serialize value with Python type {} and {} TFF type.'. format(str(py_typecheck.type_string(type(value))), str(type_spec) if type_spec is not None else 'unknown'))
def test_create_tuple_of_value_sequence(self): datasets = (tf.data.Dataset.range(5), tf.data.Dataset.range(5)) executor = executor_bindings.create_tensorflow_executor() struct_of_sequence_type = StructType([ (None, SequenceType(datasets[0].element_spec)), (None, SequenceType(datasets[0].element_spec)) ]) arg_value_pb, _ = value_serialization.serialize_value( datasets, struct_of_sequence_type) arg = executor.create_value(arg_value_pb) @tensorflow_computation.tf_computation(struct_of_sequence_type) def preprocess(datasets): def double_value(x): return 2 * x @tf.function def add_preprocessing(ds1, ds2): return ds1.map(double_value), ds2.map(double_value) return add_preprocessing(*datasets) comp_pb = executor_pb2.Value( computation=preprocess.get_proto(preprocess)) comp = executor.create_value(comp_pb) result = executor.create_call(comp.ref, arg.ref) output_pb = executor.materialize(result.ref) result, result_type_spec = value_serialization.deserialize_value( output_pb, type_hint=struct_of_sequence_type) type_test_utils.assert_types_identical(result_type_spec, struct_of_sequence_type)
def _serialize_tensor_value( value: Any, type_spec: computation_types.TensorType) -> _SerializeReturnType: """Serializes a tensor value into `executor_pb2.Value`. Args: value: A Numpy array or other object understood by `tf.make_tensor_proto`. type_spec: A `tff.TensorType`. Returns: A tuple `(value_proto, ret_type_spec)` in which `value_proto` is an instance of `executor_pb2.Value` with the serialized content of `value`, and `ret_type_spec` is the type of the serialized value. The `ret_type_spec` is the same as the argument `type_spec` if that argument was not `None`. If the argument was `None`, `ret_type_spec` is a type determined from `value`. Raises: TypeError: If the arguments are of the wrong types. ValueError: If the value is malformed. """ if isinstance(value, tf.Tensor): value = value.numpy() if isinstance(value, np.ndarray): tensor_proto = tf.make_tensor_proto( value, dtype=type_spec.dtype, verify_shape=False) else: tensor_proto = tf.make_tensor_proto( value, dtype=type_spec.dtype, shape=type_spec.shape, verify_shape=True) type_spec.check_assignable_from( computation_types.TensorType( dtype=tf.dtypes.as_dtype(tensor_proto.dtype), shape=tf.TensorShape(tensor_proto.tensor_shape))) any_pb = any_pb2.Any() any_pb.Pack(tensor_proto) return executor_pb2.Value(tensor=any_pb), type_spec
def test_deserialize_federated_value_with_incompatible_member_types_raises( self): x = 10 x_type = computation_types.to_type(tf.int32) int_member_proto, _ = executor_serialization.serialize_value(x, x_type) y = 10. y_type = computation_types.to_type(tf.float32) float_member_proto, _ = executor_serialization.serialize_value(y, y_type) fully_specified_type_at_clients = type_serialization.serialize_type( computation_types.at_clients(tf.int32)) unspecified_member_federated_type = computation_pb2.FederatedType( placement=fully_specified_type_at_clients.federated.placement, all_equal=False) federated_proto = executor_pb2.Value.Federated( type=unspecified_member_federated_type, value=[int_member_proto, float_member_proto]) federated_value_proto = executor_pb2.Value(federated=federated_proto) self.assertIsInstance(int_member_proto, executor_pb2.Value) self.assertIsInstance(float_member_proto, executor_pb2.Value) self.assertIsInstance(federated_value_proto, executor_pb2.Value) with self.assertRaises(TypeError): executor_serialization.deserialize_value(federated_value_proto)
def _serialize_computation( comp: computation_pb2.Computation, type_spec: Optional[computation_types.Type]) -> _SerializeReturnType: """Serializes a TFF computation.""" type_spec = executor_utils.reconcile_value_type_with_type_spec( type_serialization.deserialize_type(comp.type), type_spec) return executor_pb2.Value(computation=comp), type_spec
def serialize_tensor_value(value, type_spec=None): """Serializes a tensor value into `executor_pb2.Value`. Args: value: A Numpy array or other object understood by `tf.make_tensor_proto`. type_spec: An optional type spec, a `tff.TensorType` or something convertible to it. Returns: An instance of `executor_pb2.Value` with the serialized content of `value`. Returns: TypeError: If the arguments are of the wrong types. ValueError: If the value is malformed. """ if type_spec is not None: type_spec = computation_types.to_type(type_spec) py_typecheck.check_type(type_spec, computation_types.TensorType) tensor_proto = tf.make_tensor_proto(value, dtype=type_spec.dtype, shape=type_spec.shape, verify_shape=True) else: tensor_proto = tf.make_tensor_proto(value) any_pb = any_pb2.Any() any_pb.Pack(tensor_proto) return executor_pb2.Value(tensor=any_pb)
def test_deserialize_federated_value_promotes_types(self): x = [10] smaller_type = computation_types.StructType([ (None, computation_types.to_type(tf.int32)) ]) smaller_type_member_proto, _ = value_serialization.serialize_value( x, smaller_type) larger_type = computation_types.StructType([ ('a', computation_types.to_type(tf.int32)) ]) larger_type_member_proto, _ = value_serialization.serialize_value( x, larger_type) type_at_clients = type_serialization.serialize_type( computation_types.at_clients(tf.int32)) unspecified_member_federated_type = computation_pb2.FederatedType( placement=type_at_clients.federated.placement, all_equal=False) federated_proto = executor_pb2.Value.Federated( type=unspecified_member_federated_type, value=[larger_type_member_proto, smaller_type_member_proto]) federated_value_proto = executor_pb2.Value(federated=federated_proto) _, deserialized_type_spec = value_serialization.deserialize_value( federated_value_proto) type_test_utils.assert_types_identical( deserialized_type_spec, computation_types.at_clients(larger_type))
def serialize_value(value, type_spec=None): """Serializes a value into `executor_pb2.Value`. Args: value: A value to be serialized. type_spec: Optional type spec, a `tff.Type` or something convertible to it. Returns: A tuple `(value_proto, ret_type_spec)` where `value_proto` is an instance of `executor_pb2.Value` with the serialized content of `value`, and the returned `ret_type_spec` is an instance of `tff.Type` that represents the TFF type of the serialized value. Raises: TypeError: If the arguments are of the wrong types. ValueError: If the value is malformed. """ type_spec = computation_types.to_type(type_spec) if isinstance(value, computation_pb2.Computation): type_spec = type_utils.reconcile_value_type_with_type_spec( type_serialization.deserialize_type(value.type), type_spec) return executor_pb2.Value(computation=value), type_spec elif isinstance(value, computation_impl.ComputationImpl): return serialize_value( computation_impl.ComputationImpl.get_proto(value), type_utils.reconcile_value_with_type_spec(value, type_spec)) elif isinstance(type_spec, computation_types.TensorType): return serialize_tensor_value(value, type_spec) elif isinstance(type_spec, computation_types.NamedTupleType): type_elements = anonymous_tuple.to_elements(type_spec) val_elements = anonymous_tuple.to_elements( anonymous_tuple.from_container(value)) tup_elems = [] for (e_name, e_type), (_, e_val) in zip(type_elements, val_elements): e_proto, _ = serialize_value(e_val, e_type) tup_elems.append( executor_pb2.Value.Tuple.Element( name=e_name if e_name else None, value=e_proto)) result_proto = (executor_pb2.Value(tuple=executor_pb2.Value.Tuple( element=tup_elems))) return result_proto, type_spec else: raise ValueError( 'Unable to serialize value with Python type {} and {} TFF type.'. format(str(py_typecheck.type_string(type(value))), str(type_spec) if type_spec is not None else 'unknown'))
def _value_proto_for_np_array( value, type_spec: computation_types.Type) -> executor_pb2.Value: """Creates value proto for np array, assumed to be assignable to type_spec.""" tensor_proto = tf.make_tensor_proto(value, dtype=type_spec.dtype, verify_shape=True) any_pb = any_pb2.Any() any_pb.Pack(tensor_proto) return executor_pb2.Value(tensor=any_pb)
def test_call_no_arg(self): executor = executor_bindings.create_tensorflow_executor() @tensorflow_computation.tf_computation def foo(): return tf.constant(123.0) comp_pb = executor_pb2.Value(computation=foo.get_proto(foo)) comp = executor.create_value(comp_pb) result = executor.create_call(comp.ref, None) result_value_pb = executor.materialize(result.ref) result_tensor, _ = value_serialization.deserialize_value( result_value_pb) self.assertEqual(result_tensor, 123.0)
def _serialize_struct_type( struct_typed_value: Any, type_spec: computation_types.StructType) -> _SerializeReturnType: """Serializes a value of tuple type.""" type_elem_iter = structure.iter_elements(type_spec) val_elem_iter = structure.iter_elements( structure.from_container(struct_typed_value)) tup_elems = [] for (e_name, e_type), (_, e_val) in zip(type_elem_iter, val_elem_iter): e_proto, _ = serialize_value(e_val, e_type) tup_elems.append( executor_pb2.Value.Struct.Element(name=e_name if e_name else None, value=e_proto)) result_proto = (executor_pb2.Value(struct=executor_pb2.Value.Struct( element=tup_elems))) return result_proto, type_spec
def _serialize_federated_value( federated_value: Any, type_spec: computation_types.FederatedType ) -> computation_types.FederatedType: """Serializes a value of federated type.""" if type_spec.all_equal: value = [federated_value] else: value = federated_value py_typecheck.check_type(value, list) value_proto = executor_pb2.Value() for v in value: federated_value_proto, it_type = serialize_value(v, type_spec.member) type_spec.member.check_assignable_from(it_type) value_proto.federated.value.append(federated_value_proto) value_proto.federated.type.CopyFrom( type_serialization.serialize_type(type_spec).federated) return value_proto, type_spec
def test_deserialize_federated_all_equal_value_takes_first_element(self): tensor_value_pb, _ = value_serialization.serialize_value( 10, TensorType(tf.int32)) num_clients = 5 value_pb = executor_pb2.Value( federated=executor_pb2.Value.Federated( value=[tensor_value_pb] * num_clients, type=computation_pb2.FederatedType( placement=computation_pb2.PlacementSpec( value=computation_pb2.Placement( uri=placements.CLIENTS.uri))))) all_equal_clients_type_hint = computation_types.FederatedType( tf.int32, placements.CLIENTS, all_equal=True) deserialized_value, deserialized_type = value_serialization.deserialize_value( value_pb, all_equal_clients_type_hint) type_test_utils.assert_types_identical(deserialized_type, all_equal_clients_type_hint) self.assertAllEqual(deserialized_value, 10)
def test_call_with_arg(self): executor = executor_bindings.create_tensorflow_executor() value_pb, _ = value_serialization.serialize_value( tf.constant([1, 2, 3]), TensorType(shape=[3], dtype=tf.int64)) value_ref = executor.create_value(value_pb) arg = executor.create_struct((value_ref.ref, value_ref.ref)) @tensorflow_computation.tf_computation(tf.int64, tf.int64) def foo(a, b): return tf.add(a, b) comp_pb = executor_pb2.Value(computation=foo.get_proto(foo)) comp = executor.create_value(comp_pb) result = executor.create_call(comp.ref, arg.ref) result_value_pb = executor.materialize(result.ref) result_tensor, _ = value_serialization.deserialize_value( result_value_pb) self.assertAllEqual(result_tensor, [2, 4, 6])
def test_compute_returns_result(self, mock_stub): tensor_proto = tf.make_tensor_proto(1) any_pb = any_pb2.Any() any_pb.Pack(tensor_proto) value = executor_pb2.Value(tensor=any_pb) response = executor_pb2.ComputeResponse(value=value) instance = mock_stub.return_value instance.Compute = mock.Mock(side_effect=[response]) loop = asyncio.get_event_loop() executor = create_remote_executor() type_signature = computation_types.FunctionType(None, tf.int32) comp = remote_executor.RemoteValue(executor_pb2.ValueRef(), type_signature, executor) result = loop.run_until_complete(comp.compute()) instance.Compute.assert_called_once() self.assertEqual(result, 1)
def test_compute_returns_result(self, mock_stub): tensor_proto = tf.make_tensor_proto(1) any_pb = any_pb2.Any() any_pb.Pack(tensor_proto) value = executor_pb2.Value(tensor=any_pb) mock_stub.compute.return_value = executor_pb2.ComputeResponse( value=value) executor = remote_executor.RemoteExecutor(mock_stub) _set_cardinalities_with_mock(executor, mock_stub) executor.set_cardinalities({placements.CLIENTS: 3}) type_signature = computation_types.FunctionType(None, tf.int32) comp = remote_executor.RemoteValue(executor_pb2.ValueRef(), type_signature, executor) result = asyncio.run(comp.compute()) mock_stub.compute.assert_called_once() self.assertEqual(result, 1)
def _serialize_federated_value( federated_value: Any, type_spec: computation_types.FederatedType) -> _SerializeReturnType: """Serializes a value of federated type.""" if type_spec.all_equal: value = [federated_value] else: value = federated_value py_typecheck.check_type(value, list) items = [] for v in value: it, it_type = serialize_value(v, type_spec.member) type_spec.member.check_assignable_from(it_type) items.append(it) result_proto = executor_pb2.Value(federated=executor_pb2.Value.Federated( type=type_serialization.serialize_type(type_spec).federated, value=items)) return result_proto, type_spec
def _serialize_sequence_value( value: Union[Union[type_conversions.TF_DATASET_REPRESENTATION_TYPES], List[Any]], type_spec: computation_types.SequenceType ) -> computation_types.SequenceType: """Serializes a `tf.data.Dataset` value into `executor_pb2.Value`. Args: value: A `tf.data.Dataset`, or equivalent list of values convertible to (potentially structures of) tensors. type_spec: A `computation_types.Type` specifying the TFF sequence type of `value.` Returns: A tuple `(value_proto, type_spec)` in which `value_proto` is an instance of `executor_pb2.Value` with the serialized content of `value`, and `type_spec` is the type of the serialized value. """ if isinstance(value, list): value = tensorflow_utils.make_data_set_from_elements( None, value, type_spec.element) if not isinstance(value, type_conversions.TF_DATASET_REPRESENTATION_TYPES): raise TypeError( 'Cannot serialize Python type {!s} as TFF type {!s}.'.format( py_typecheck.type_string(type(value)), type_spec if type_spec is not None else 'unknown')) element_type = computation_types.to_type(value.element_spec) _check_container_compat_with_tf_nest(element_type) value_type = computation_types.SequenceType(element_type) if not type_spec.is_assignable_from(value_type): raise TypeError( 'Cannot serialize dataset with elements of type {!s} as TFF type {!s}.' .format(value_type, type_spec if type_spec is not None else 'unknown')) value_proto = executor_pb2.Value() # TFF must store the type spec here because TF will lose the ordering of the # names for `tf.data.Dataset` that return elements of # `collections.abc.Mapping` type. This allows TFF to preserve and restore the # key ordering upon deserialization. value_proto.sequence.serialized_graph_def = _serialize_dataset(value) value_proto.sequence.element_type.CopyFrom( type_serialization.serialize_type(element_type)) return value_proto, type_spec
def test_compute_returns_result(self, mock_executor_grpc_stub): tensor_proto = tf.make_tensor_proto(1) any_pb = any_pb2.Any() any_pb.Pack(tensor_proto) value = executor_pb2.Value(tensor=any_pb) response = executor_pb2.ComputeResponse(value=value) instance = mock_executor_grpc_stub.return_value instance.Compute = mock.Mock(side_effect=[response]) request = executor_pb2.ComputeRequest( executor=executor_pb2.ExecutorId(), value_ref=executor_pb2.ValueRef()) stub = create_stub() result = stub.compute(request) instance.Compute.assert_called_once() value, _ = value_serialization.deserialize_value(result.value) self.assertEqual(value, 1)
def test_deserialize_federated_value_with_unset_member_type(self): x = 10 x_type = computation_types.to_type(tf.int32) member_proto, _ = value_serialization.serialize_value(x, x_type) fully_specified_type_at_clients = type_serialization.serialize_type( computation_types.at_clients(tf.int32)) unspecified_member_federated_type = computation_pb2.FederatedType( placement=fully_specified_type_at_clients.federated.placement, all_equal=fully_specified_type_at_clients.federated.all_equal) federated_proto = executor_pb2.Value.Federated( type=unspecified_member_federated_type, value=[member_proto]) federated_value_proto = executor_pb2.Value(federated=federated_proto) deserialized_federated_value, deserialized_type_spec = value_serialization.deserialize_value( federated_value_proto) type_test_utils.assert_types_identical( deserialized_type_spec, computation_types.at_clients(tf.int32)) self.assertEqual(deserialized_federated_value, [10])
def serialize_sequence_value(value): """Serializes a `tf.data.Dataset` value into `executor_pb2.Value`. Args: value: A `tf.data.Dataset`, or equivalent. Returns: A tuple `(value_proto, type_spec)` in which `value_proto` is an instance of `executor_pb2.Value` with the serialized content of `value`, and `type_spec` is the type of the serialized value. """ py_typecheck.check_type(value, type_utils.TF_DATASET_REPRESENTATION_TYPES) # TFF must store the type spec here because TF will lose the ordering of the # names for `tf.data.Dataset` that return elements of `collections.Mapping` # type. This allows TFF to preserve and restore the key ordering upon # deserialization. element_type = computation_types.to_type(value.element_spec) return executor_pb2.Value(sequence=executor_pb2.Value.Sequence( zipped_saved_model=tensorflow_serialization.serialize_dataset(value), element_type=type_serialization.serialize_type(element_type)))
def test_create_value_sequence(self, dataset): executor = executor_bindings.create_tensorflow_executor() sequence_type = SequenceType(dataset.element_spec) arg_value_pb, _ = value_serialization.serialize_value( dataset, sequence_type) arg = executor.create_value(arg_value_pb) @tensorflow_computation.tf_computation(sequence_type) def sum_examples(ds): return ds.reduce(tf.constant(0, ds.element_spec.dtype), lambda s, x: s + tf.reduce_sum(x)) comp_pb = executor_pb2.Value( computation=sum_examples.get_proto(sum_examples)) comp = executor.create_value(comp_pb) result = executor.create_call(comp.ref, arg.ref) output_pb = executor.materialize(result.ref) result, result_type_spec = value_serialization.deserialize_value( output_pb) type_test_utils.assert_types_identical( result_type_spec, TensorType(sequence_type.element.dtype)) self.assertEqual(result, sum(range(5)))
def _serialize_sequence_value( value: Union[type_conversions.TF_DATASET_REPRESENTATION_TYPES], type_spec: computation_types.SequenceType) -> _SerializeReturnType: """Serializes a `tf.data.Dataset` value into `executor_pb2.Value`. Args: value: A `tf.data.Dataset`, or equivalent. type_spec: A `computation_types.Type` specifying the TFF sequence type of `value.` Returns: A tuple `(value_proto, type_spec)` in which `value_proto` is an instance of `executor_pb2.Value` with the serialized content of `value`, and `type_spec` is the type of the serialized value. """ if not isinstance(value, type_conversions.TF_DATASET_REPRESENTATION_TYPES): raise TypeError( 'Cannot serialize Python type {!s} as TFF type {!s}.'.format( py_typecheck.type_string(type(value)), type_spec if type_spec is not None else 'unknown')) value_type = computation_types.SequenceType( computation_types.to_type(value.element_spec)) if not type_spec.is_assignable_from(value_type): raise TypeError( 'Cannot serialize dataset with elements of type {!s} as TFF type {!s}.' .format(value_type, type_spec if type_spec is not None else 'unknown')) # TFF must store the type spec here because TF will lose the ordering of the # names for `tf.data.Dataset` that return elements of # `collections.abc.Mapping` type. This allows TFF to preserve and restore the # key ordering upon deserialization. element_type = computation_types.to_type(value.element_spec) return executor_pb2.Value( sequence=executor_pb2.Value.Sequence( zipped_saved_model=_serialize_dataset(value), element_type=type_serialization.serialize_type( element_type))), type_spec
def serialize_tensor_value(value, type_spec=None): """Serializes a tensor value into `executor_pb2.Value`. Args: value: A Numpy array or other object understood by `tf.make_tensor_proto`. type_spec: An optional type spec, a `tff.TensorType` or something convertible to it. Returns: A tuple `(value_proto, ret_type_spec)` in which `value_proto` is an instance of `executor_pb2.Value` with the serialized content of `value`, and `ret_type_spec` is the type of the serialized value. The `ret_type_spec` is the same as the argument `type_spec` if that argument was not `None`. If the argument was `None`, `ret_type_spec` is a type determined from `value`. Raises: TypeError: If the arguments are of the wrong types. ValueError: If the value is malformed. """ if isinstance(value, tf.Tensor): if type_spec is None: type_spec = computation_types.TensorType( dtype=tf.DType(value.dtype), shape=tf.TensorShape(value.shape)) value = value.numpy() if type_spec is not None: type_spec = computation_types.to_type(type_spec) py_typecheck.check_type(type_spec, computation_types.TensorType) tensor_proto = tf.make_tensor_proto( value, dtype=type_spec.dtype, shape=type_spec.shape, verify_shape=True) else: tensor_proto = tf.make_tensor_proto(value) type_spec = computation_types.TensorType( dtype=tf.DType(tensor_proto.dtype), shape=tf.TensorShape(tensor_proto.tensor_shape)) any_pb = any_pb2.Any() any_pb.Pack(tensor_proto) return executor_pb2.Value(tensor=any_pb), type_spec
def serialize_value(value, type_spec=None): """Serializes a value into `executor_pb2.Value`. Args: value: A value to be serialized. type_spec: Optional type spec, a `tff.Type` or something convertible to it. Returns: A tuple `(value_proto, ret_type_spec)` where `value_proto` is an instance of `executor_pb2.Value` with the serialized content of `value`, and the returned `ret_type_spec` is an instance of `tff.Type` that represents the TFF type of the serialized value. Raises: TypeError: If the arguments are of the wrong types. ValueError: If the value is malformed. """ type_spec = computation_types.to_type(type_spec) if isinstance(value, computation_pb2.Computation): type_spec = type_utils.reconcile_value_type_with_type_spec( type_serialization.deserialize_type(value.type), type_spec) return executor_pb2.Value(computation=value), type_spec elif isinstance(value, computation_impl.ComputationImpl): return serialize_value( computation_impl.ComputationImpl.get_proto(value), type_utils.reconcile_value_with_type_spec(value, type_spec)) elif isinstance(type_spec, computation_types.TensorType): return serialize_tensor_value(value, type_spec) elif isinstance(type_spec, computation_types.NamedTupleType): type_elements = anonymous_tuple.to_elements(type_spec) val_elements = anonymous_tuple.to_elements( anonymous_tuple.from_container(value)) tup_elems = [] for (e_name, e_type), (_, e_val) in zip(type_elements, val_elements): e_proto, _ = serialize_value(e_val, e_type) tup_elems.append( executor_pb2.Value.Tuple.Element( name=e_name if e_name else None, value=e_proto)) result_proto = (executor_pb2.Value(tuple=executor_pb2.Value.Tuple( element=tup_elems))) return result_proto, type_spec elif isinstance(type_spec, computation_types.SequenceType): if not isinstance(value, type_conversions.TF_DATASET_REPRESENTATION_TYPES): raise TypeError( 'Cannot serialize Python type {!s} as TFF type {!s}.'.format( py_typecheck.type_string(type(value)), type_spec if type_spec is not None else 'unknown')) value_type = computation_types.SequenceType( computation_types.to_type(value.element_spec)) if not type_analysis.is_assignable_from(type_spec, value_type): raise TypeError( 'Cannot serialize dataset with elements of type {!s} as TFF type {!s}.' .format(value_type, type_spec if type_spec is not None else 'unknown')) return serialize_sequence_value(value), type_spec elif isinstance(type_spec, computation_types.FederatedType): if type_spec.all_equal: value = [value] else: py_typecheck.check_type(value, list) items = [] for v in value: it, it_type = serialize_value(v, type_spec.member) type_analysis.check_assignable_from(type_spec.member, it_type) items.append(it) result_proto = executor_pb2.Value( federated=executor_pb2.Value.Federated( type=type_serialization.serialize_type(type_spec).federated, value=items)) return result_proto, type_spec else: raise ValueError( 'Unable to serialize value with Python type {} and {} TFF type.'. format(str(py_typecheck.type_string(type(value))), str(type_spec) if type_spec is not None else 'unknown'))