flwr-nightly 1.11.0.dev20240813__py3-none-any.whl → 1.11.0.dev20240821__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of flwr-nightly might be problematic. Click here for more details.
- flwr/cli/config_utils.py +2 -2
- flwr/cli/install.py +3 -1
- flwr/cli/run/run.py +15 -11
- flwr/client/app.py +132 -14
- flwr/client/clientapp/__init__.py +22 -0
- flwr/client/clientapp/app.py +233 -0
- flwr/client/clientapp/clientappio_servicer.py +244 -0
- flwr/client/clientapp/utils.py +108 -0
- flwr/client/grpc_rere_client/connection.py +9 -1
- flwr/client/node_state.py +17 -4
- flwr/client/rest_client/connection.py +16 -3
- flwr/client/supernode/__init__.py +0 -2
- flwr/client/supernode/app.py +37 -122
- flwr/common/__init__.py +4 -0
- flwr/common/config.py +31 -10
- flwr/common/record/configsrecord.py +49 -15
- flwr/common/record/metricsrecord.py +54 -14
- flwr/common/record/parametersrecord.py +84 -17
- flwr/common/record/recordset.py +80 -8
- flwr/common/record/typeddict.py +20 -58
- flwr/common/recordset_compat.py +6 -6
- flwr/common/serde.py +24 -2
- flwr/common/typing.py +1 -0
- flwr/proto/clientappio_pb2.py +17 -13
- flwr/proto/clientappio_pb2.pyi +24 -2
- flwr/proto/clientappio_pb2_grpc.py +34 -0
- flwr/proto/clientappio_pb2_grpc.pyi +13 -0
- flwr/proto/exec_pb2.py +16 -15
- flwr/proto/exec_pb2.pyi +7 -4
- flwr/proto/message_pb2.py +2 -2
- flwr/proto/message_pb2.pyi +4 -1
- flwr/server/app.py +15 -0
- flwr/server/driver/grpc_driver.py +1 -0
- flwr/server/run_serverapp.py +18 -2
- flwr/server/server.py +3 -1
- flwr/server/superlink/driver/driver_grpc.py +3 -0
- flwr/server/superlink/driver/driver_servicer.py +32 -4
- flwr/server/superlink/ffs/disk_ffs.py +6 -3
- flwr/server/superlink/ffs/ffs.py +3 -3
- flwr/server/superlink/ffs/ffs_factory.py +47 -0
- flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +12 -4
- flwr/server/superlink/fleet/grpc_rere/server_interceptor.py +8 -2
- flwr/server/superlink/fleet/message_handler/message_handler.py +16 -1
- flwr/server/superlink/fleet/vce/backend/raybackend.py +5 -2
- flwr/server/superlink/fleet/vce/vce_api.py +2 -2
- flwr/server/superlink/state/in_memory_state.py +7 -5
- flwr/server/superlink/state/sqlite_state.py +17 -7
- flwr/server/superlink/state/state.py +4 -3
- flwr/server/workflow/default_workflows.py +3 -1
- flwr/simulation/run_simulation.py +5 -67
- flwr/superexec/app.py +3 -3
- flwr/superexec/deployment.py +8 -9
- flwr/superexec/exec_servicer.py +1 -1
- {flwr_nightly-1.11.0.dev20240813.dist-info → flwr_nightly-1.11.0.dev20240821.dist-info}/METADATA +2 -2
- {flwr_nightly-1.11.0.dev20240813.dist-info → flwr_nightly-1.11.0.dev20240821.dist-info}/RECORD +58 -53
- {flwr_nightly-1.11.0.dev20240813.dist-info → flwr_nightly-1.11.0.dev20240821.dist-info}/entry_points.txt +1 -1
- {flwr_nightly-1.11.0.dev20240813.dist-info → flwr_nightly-1.11.0.dev20240821.dist-info}/LICENSE +0 -0
- {flwr_nightly-1.11.0.dev20240813.dist-info → flwr_nightly-1.11.0.dev20240821.dist-info}/WHEEL +0 -0
flwr/common/record/recordset.py
CHANGED
|
@@ -15,8 +15,10 @@
|
|
|
15
15
|
"""RecordSet."""
|
|
16
16
|
|
|
17
17
|
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
18
20
|
from dataclasses import dataclass
|
|
19
|
-
from typing import
|
|
21
|
+
from typing import cast
|
|
20
22
|
|
|
21
23
|
from .configsrecord import ConfigsRecord
|
|
22
24
|
from .metricsrecord import MetricsRecord
|
|
@@ -34,9 +36,9 @@ class RecordSetData:
|
|
|
34
36
|
|
|
35
37
|
def __init__(
|
|
36
38
|
self,
|
|
37
|
-
parameters_records:
|
|
38
|
-
metrics_records:
|
|
39
|
-
configs_records:
|
|
39
|
+
parameters_records: dict[str, ParametersRecord] | None = None,
|
|
40
|
+
metrics_records: dict[str, MetricsRecord] | None = None,
|
|
41
|
+
configs_records: dict[str, ConfigsRecord] | None = None,
|
|
40
42
|
) -> None:
|
|
41
43
|
self.parameters_records = TypedDict[str, ParametersRecord](
|
|
42
44
|
self._check_fn_str, self._check_fn_params
|
|
@@ -84,13 +86,83 @@ class RecordSetData:
|
|
|
84
86
|
|
|
85
87
|
|
|
86
88
|
class RecordSet:
|
|
87
|
-
"""RecordSet stores groups of parameters, metrics and configs.
|
|
89
|
+
"""RecordSet stores groups of parameters, metrics and configs.
|
|
90
|
+
|
|
91
|
+
A :code:`RecordSet` is the unified mechanism by which parameters,
|
|
92
|
+
metrics and configs can be either stored as part of a
|
|
93
|
+
`flwr.common.Context <flwr.common.Context.html>`_ in your apps
|
|
94
|
+
or communicated as part of a
|
|
95
|
+
`flwr.common.Message <flwr.common.Message.html>`_ between your apps.
|
|
96
|
+
|
|
97
|
+
Parameters
|
|
98
|
+
----------
|
|
99
|
+
parameters_records : Optional[Dict[str, ParametersRecord]]
|
|
100
|
+
A dictionary of :code:`ParametersRecords` that can be used to record
|
|
101
|
+
and communicate model parameters and high-dimensional arrays.
|
|
102
|
+
metrics_records : Optional[Dict[str, MetricsRecord]]
|
|
103
|
+
A dictionary of :code:`MetricsRecord` that can be used to record
|
|
104
|
+
and communicate scalar-valued metrics that are the result of performing
|
|
105
|
+
and action, for example, by a :code:`ClientApp`.
|
|
106
|
+
configs_records : Optional[Dict[str, ConfigsRecord]]
|
|
107
|
+
A dictionary of :code:`ConfigsRecord` that can be used to record
|
|
108
|
+
and communicate configuration values to an entity (e.g. to a
|
|
109
|
+
:code:`ClientApp`)
|
|
110
|
+
for it to adjust how an action is performed.
|
|
111
|
+
|
|
112
|
+
Examples
|
|
113
|
+
--------
|
|
114
|
+
A :code:`RecordSet` can hold three types of records, each designed
|
|
115
|
+
with an specific purpose. What is common to all of them is that they
|
|
116
|
+
are Python dictionaries designed to ensure that each key-value pair
|
|
117
|
+
adheres to specified data types.
|
|
118
|
+
|
|
119
|
+
Let's see an example.
|
|
120
|
+
|
|
121
|
+
>>> from flwr.common import RecordSet
|
|
122
|
+
>>> from flwr.common import ConfigsRecords, MetricsRecords, ParametersRecord
|
|
123
|
+
>>>
|
|
124
|
+
>>> # Let's begin with an empty record
|
|
125
|
+
>>> my_recordset = RecordSet()
|
|
126
|
+
>>>
|
|
127
|
+
>>> # We can create a ConfigsRecord
|
|
128
|
+
>>> c_record = ConfigsRecord({"lr": 0.1, "batch-size": 128})
|
|
129
|
+
>>> # Adding it to the record_set would look like this
|
|
130
|
+
>>> my_recordset.configs_records["my_config"] = c_record
|
|
131
|
+
>>>
|
|
132
|
+
>>> # We can create a MetricsRecord following a similar process
|
|
133
|
+
>>> m_record = MetricsRecord({"accuracy": 0.93, "losses": [0.23, 0.1]})
|
|
134
|
+
>>> # Adding it to the record_set would look like this
|
|
135
|
+
>>> my_recordset.metrics_records["my_metrics"] = m_record
|
|
136
|
+
|
|
137
|
+
Adding a :code:`ParametersRecord` follows the same steps as above but first,
|
|
138
|
+
the array needs to be serialized and represented as a :code:`flwr.common.Array`.
|
|
139
|
+
If the array is a :code:`NumPy` array, you can use the built-in utility function
|
|
140
|
+
`array_from_numpy <flwr.common.array_from_numpy.html>`_. It is often possible to
|
|
141
|
+
convert an array first to :code:`NumPy` and then use the aforementioned function.
|
|
142
|
+
|
|
143
|
+
>>> from flwr.common import array_from_numpy
|
|
144
|
+
>>> # Creating a ParametersRecord would look like this
|
|
145
|
+
>>> arr_np = np.random.randn(3, 3)
|
|
146
|
+
>>>
|
|
147
|
+
>>> # You can use the built-in tool to serialize the array
|
|
148
|
+
>>> arr = array_from_numpy(arr_np)
|
|
149
|
+
>>>
|
|
150
|
+
>>> # Finally, create the record
|
|
151
|
+
>>> p_record = ParametersRecord({"my_array": arr})
|
|
152
|
+
>>>
|
|
153
|
+
>>> # Adding it to the record_set would look like this
|
|
154
|
+
>>> my_recordset.configs_records["my_config"] = c_record
|
|
155
|
+
|
|
156
|
+
For additional examples on how to construct each of the records types shown
|
|
157
|
+
above, please refer to the documentation for :code:`ConfigsRecord`,
|
|
158
|
+
:code:`MetricsRecord` and :code:`ParametersRecord`.
|
|
159
|
+
"""
|
|
88
160
|
|
|
89
161
|
def __init__(
|
|
90
162
|
self,
|
|
91
|
-
parameters_records:
|
|
92
|
-
metrics_records:
|
|
93
|
-
configs_records:
|
|
163
|
+
parameters_records: dict[str, ParametersRecord] | None = None,
|
|
164
|
+
metrics_records: dict[str, MetricsRecord] | None = None,
|
|
165
|
+
configs_records: dict[str, ConfigsRecord] | None = None,
|
|
94
166
|
) -> None:
|
|
95
167
|
data = RecordSetData(
|
|
96
168
|
parameters_records=parameters_records,
|
flwr/common/record/typeddict.py
CHANGED
|
@@ -15,99 +15,61 @@
|
|
|
15
15
|
"""Typed dict base class for *Records."""
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
from typing import
|
|
18
|
+
from typing import Callable, Dict, Generic, Iterator, MutableMapping, TypeVar, cast
|
|
19
19
|
|
|
20
20
|
K = TypeVar("K") # Key type
|
|
21
21
|
V = TypeVar("V") # Value type
|
|
22
22
|
|
|
23
23
|
|
|
24
|
-
class TypedDict(Generic[K, V]):
|
|
24
|
+
class TypedDict(MutableMapping[K, V], Generic[K, V]):
|
|
25
25
|
"""Typed dictionary."""
|
|
26
26
|
|
|
27
27
|
def __init__(
|
|
28
28
|
self, check_key_fn: Callable[[K], None], check_value_fn: Callable[[V], None]
|
|
29
29
|
):
|
|
30
|
-
self.
|
|
31
|
-
self.
|
|
32
|
-
self.
|
|
30
|
+
self.__dict__["_check_key_fn"] = check_key_fn
|
|
31
|
+
self.__dict__["_check_value_fn"] = check_value_fn
|
|
32
|
+
self.__dict__["_data"] = {}
|
|
33
33
|
|
|
34
34
|
def __setitem__(self, key: K, value: V) -> None:
|
|
35
35
|
"""Set the given key to the given value after type checking."""
|
|
36
36
|
# Check the types of key and value
|
|
37
|
-
self._check_key_fn(key)
|
|
38
|
-
self._check_value_fn(value)
|
|
37
|
+
cast(Callable[[K], None], self.__dict__["_check_key_fn"])(key)
|
|
38
|
+
cast(Callable[[V], None], self.__dict__["_check_value_fn"])(value)
|
|
39
|
+
|
|
39
40
|
# Set key-value pair
|
|
40
|
-
self._data[key] = value
|
|
41
|
+
cast(Dict[K, V], self.__dict__["_data"])[key] = value
|
|
41
42
|
|
|
42
43
|
def __delitem__(self, key: K) -> None:
|
|
43
44
|
"""Remove the item with the specified key."""
|
|
44
|
-
del self._data[key]
|
|
45
|
+
del cast(Dict[K, V], self.__dict__["_data"])[key]
|
|
45
46
|
|
|
46
47
|
def __getitem__(self, item: K) -> V:
|
|
47
48
|
"""Return the value for the specified key."""
|
|
48
|
-
return self._data[item]
|
|
49
|
+
return cast(Dict[K, V], self.__dict__["_data"])[item]
|
|
49
50
|
|
|
50
51
|
def __iter__(self) -> Iterator[K]:
|
|
51
52
|
"""Yield an iterator over the keys of the dictionary."""
|
|
52
|
-
return iter(self._data)
|
|
53
|
+
return iter(cast(Dict[K, V], self.__dict__["_data"]))
|
|
53
54
|
|
|
54
55
|
def __repr__(self) -> str:
|
|
55
56
|
"""Return a string representation of the dictionary."""
|
|
56
|
-
return self._data.__repr__()
|
|
57
|
+
return cast(Dict[K, V], self.__dict__["_data"]).__repr__()
|
|
57
58
|
|
|
58
59
|
def __len__(self) -> int:
|
|
59
60
|
"""Return the number of items in the dictionary."""
|
|
60
|
-
return len(self._data)
|
|
61
|
+
return len(cast(Dict[K, V], self.__dict__["_data"]))
|
|
61
62
|
|
|
62
|
-
def __contains__(self, key:
|
|
63
|
+
def __contains__(self, key: object) -> bool:
|
|
63
64
|
"""Check if the dictionary contains the specified key."""
|
|
64
|
-
return key in self._data
|
|
65
|
+
return key in cast(Dict[K, V], self.__dict__["_data"])
|
|
65
66
|
|
|
66
67
|
def __eq__(self, other: object) -> bool:
|
|
67
68
|
"""Compare this instance to another dictionary or TypedDict."""
|
|
69
|
+
data = cast(Dict[K, V], self.__dict__["_data"])
|
|
68
70
|
if isinstance(other, TypedDict):
|
|
69
|
-
|
|
71
|
+
other_data = cast(Dict[K, V], other.__dict__["_data"])
|
|
72
|
+
return data == other_data
|
|
70
73
|
if isinstance(other, dict):
|
|
71
|
-
return
|
|
74
|
+
return data == other
|
|
72
75
|
return NotImplemented
|
|
73
|
-
|
|
74
|
-
def items(self) -> Iterator[Tuple[K, V]]:
|
|
75
|
-
"""R.items() -> a set-like object providing a view on R's items."""
|
|
76
|
-
return cast(Iterator[Tuple[K, V]], self._data.items())
|
|
77
|
-
|
|
78
|
-
def keys(self) -> Iterator[K]:
|
|
79
|
-
"""R.keys() -> a set-like object providing a view on R's keys."""
|
|
80
|
-
return cast(Iterator[K], self._data.keys())
|
|
81
|
-
|
|
82
|
-
def values(self) -> Iterator[V]:
|
|
83
|
-
"""R.values() -> an object providing a view on R's values."""
|
|
84
|
-
return cast(Iterator[V], self._data.values())
|
|
85
|
-
|
|
86
|
-
def update(self, *args: Any, **kwargs: Any) -> None:
|
|
87
|
-
"""R.update([E, ]**F) -> None.
|
|
88
|
-
|
|
89
|
-
Update R from dict/iterable E and F.
|
|
90
|
-
"""
|
|
91
|
-
for key, value in dict(*args, **kwargs).items():
|
|
92
|
-
self[key] = value
|
|
93
|
-
|
|
94
|
-
def pop(self, key: K) -> V:
|
|
95
|
-
"""R.pop(k[,d]) -> v, remove specified key and return the corresponding value.
|
|
96
|
-
|
|
97
|
-
If key is not found, d is returned if given, otherwise KeyError is raised.
|
|
98
|
-
"""
|
|
99
|
-
return self._data.pop(key)
|
|
100
|
-
|
|
101
|
-
def get(self, key: K, default: V) -> V:
|
|
102
|
-
"""R.get(k[,d]) -> R[k] if k in R, else d.
|
|
103
|
-
|
|
104
|
-
d defaults to None.
|
|
105
|
-
"""
|
|
106
|
-
return self._data.get(key, default)
|
|
107
|
-
|
|
108
|
-
def clear(self) -> None:
|
|
109
|
-
"""R.clear() -> None.
|
|
110
|
-
|
|
111
|
-
Remove all items from R.
|
|
112
|
-
"""
|
|
113
|
-
self._data.clear()
|
flwr/common/recordset_compat.py
CHANGED
|
@@ -145,7 +145,7 @@ def _recordset_to_fit_or_evaluate_ins_components(
|
|
|
145
145
|
# get config dict
|
|
146
146
|
config_record = recordset.configs_records[f"{ins_str}.config"]
|
|
147
147
|
# pylint: disable-next=protected-access
|
|
148
|
-
config_dict = _check_mapping_from_recordscalartype_to_scalar(config_record
|
|
148
|
+
config_dict = _check_mapping_from_recordscalartype_to_scalar(config_record)
|
|
149
149
|
|
|
150
150
|
return parameters, config_dict
|
|
151
151
|
|
|
@@ -213,7 +213,7 @@ def recordset_to_fitres(recordset: RecordSet, keep_input: bool) -> FitRes:
|
|
|
213
213
|
)
|
|
214
214
|
configs_record = recordset.configs_records[f"{ins_str}.metrics"]
|
|
215
215
|
# pylint: disable-next=protected-access
|
|
216
|
-
metrics = _check_mapping_from_recordscalartype_to_scalar(configs_record
|
|
216
|
+
metrics = _check_mapping_from_recordscalartype_to_scalar(configs_record)
|
|
217
217
|
status = _extract_status_from_recordset(ins_str, recordset)
|
|
218
218
|
|
|
219
219
|
return FitRes(
|
|
@@ -274,7 +274,7 @@ def recordset_to_evaluateres(recordset: RecordSet) -> EvaluateRes:
|
|
|
274
274
|
configs_record = recordset.configs_records[f"{ins_str}.metrics"]
|
|
275
275
|
|
|
276
276
|
# pylint: disable-next=protected-access
|
|
277
|
-
metrics = _check_mapping_from_recordscalartype_to_scalar(configs_record
|
|
277
|
+
metrics = _check_mapping_from_recordscalartype_to_scalar(configs_record)
|
|
278
278
|
status = _extract_status_from_recordset(ins_str, recordset)
|
|
279
279
|
|
|
280
280
|
return EvaluateRes(
|
|
@@ -314,7 +314,7 @@ def recordset_to_getparametersins(recordset: RecordSet) -> GetParametersIns:
|
|
|
314
314
|
"""Derive GetParametersIns from a RecordSet object."""
|
|
315
315
|
config_record = recordset.configs_records["getparametersins.config"]
|
|
316
316
|
# pylint: disable-next=protected-access
|
|
317
|
-
config_dict = _check_mapping_from_recordscalartype_to_scalar(config_record
|
|
317
|
+
config_dict = _check_mapping_from_recordscalartype_to_scalar(config_record)
|
|
318
318
|
|
|
319
319
|
return GetParametersIns(config=config_dict)
|
|
320
320
|
|
|
@@ -365,7 +365,7 @@ def recordset_to_getpropertiesins(recordset: RecordSet) -> GetPropertiesIns:
|
|
|
365
365
|
"""Derive GetPropertiesIns from a RecordSet object."""
|
|
366
366
|
config_record = recordset.configs_records["getpropertiesins.config"]
|
|
367
367
|
# pylint: disable-next=protected-access
|
|
368
|
-
config_dict = _check_mapping_from_recordscalartype_to_scalar(config_record
|
|
368
|
+
config_dict = _check_mapping_from_recordscalartype_to_scalar(config_record)
|
|
369
369
|
|
|
370
370
|
return GetPropertiesIns(config=config_dict)
|
|
371
371
|
|
|
@@ -384,7 +384,7 @@ def recordset_to_getpropertiesres(recordset: RecordSet) -> GetPropertiesRes:
|
|
|
384
384
|
res_str = "getpropertiesres"
|
|
385
385
|
config_record = recordset.configs_records[f"{res_str}.properties"]
|
|
386
386
|
# pylint: disable-next=protected-access
|
|
387
|
-
properties = _check_mapping_from_recordscalartype_to_scalar(config_record
|
|
387
|
+
properties = _check_mapping_from_recordscalartype_to_scalar(config_record)
|
|
388
388
|
|
|
389
389
|
status = _extract_status_from_recordset(res_str, recordset=recordset)
|
|
390
390
|
|
flwr/common/serde.py
CHANGED
|
@@ -22,6 +22,7 @@ from google.protobuf.message import Message as GrpcMessage
|
|
|
22
22
|
# pylint: disable=E0611
|
|
23
23
|
from flwr.proto.clientappio_pb2 import ClientAppOutputCode, ClientAppOutputStatus
|
|
24
24
|
from flwr.proto.error_pb2 import Error as ProtoError
|
|
25
|
+
from flwr.proto.fab_pb2 import Fab as ProtoFab
|
|
25
26
|
from flwr.proto.message_pb2 import Context as ProtoContext
|
|
26
27
|
from flwr.proto.message_pb2 import Message as ProtoMessage
|
|
27
28
|
from flwr.proto.message_pb2 import Metadata as ProtoMetadata
|
|
@@ -686,6 +687,19 @@ def message_from_taskres(taskres: TaskRes) -> Message:
|
|
|
686
687
|
return message
|
|
687
688
|
|
|
688
689
|
|
|
690
|
+
# === FAB ===
|
|
691
|
+
|
|
692
|
+
|
|
693
|
+
def fab_to_proto(fab: typing.Fab) -> ProtoFab:
|
|
694
|
+
"""Create a proto Fab object from a Python Fab."""
|
|
695
|
+
return ProtoFab(hash_str=fab.hash_str, content=fab.content)
|
|
696
|
+
|
|
697
|
+
|
|
698
|
+
def fab_from_proto(fab: ProtoFab) -> typing.Fab:
|
|
699
|
+
"""Create a Python Fab object from a proto Fab."""
|
|
700
|
+
return typing.Fab(fab.hash_str, fab.content)
|
|
701
|
+
|
|
702
|
+
|
|
689
703
|
# === User configs ===
|
|
690
704
|
|
|
691
705
|
|
|
@@ -745,6 +759,7 @@ def metadata_to_proto(metadata: Metadata) -> ProtoMetadata:
|
|
|
745
759
|
group_id=metadata.group_id,
|
|
746
760
|
ttl=metadata.ttl,
|
|
747
761
|
message_type=metadata.message_type,
|
|
762
|
+
created_at=metadata.created_at,
|
|
748
763
|
)
|
|
749
764
|
return proto
|
|
750
765
|
|
|
@@ -771,7 +786,9 @@ def message_to_proto(message: Message) -> ProtoMessage:
|
|
|
771
786
|
"""Serialize `Message` to ProtoBuf."""
|
|
772
787
|
proto = ProtoMessage(
|
|
773
788
|
metadata=metadata_to_proto(message.metadata),
|
|
774
|
-
content=
|
|
789
|
+
content=(
|
|
790
|
+
recordset_to_proto(message.content) if message.has_content() else None
|
|
791
|
+
),
|
|
775
792
|
error=error_to_proto(message.error) if message.has_error() else None,
|
|
776
793
|
)
|
|
777
794
|
return proto
|
|
@@ -779,6 +796,7 @@ def message_to_proto(message: Message) -> ProtoMessage:
|
|
|
779
796
|
|
|
780
797
|
def message_from_proto(message_proto: ProtoMessage) -> Message:
|
|
781
798
|
"""Deserialize `Message` from ProtoBuf."""
|
|
799
|
+
created_at = message_proto.metadata.created_at
|
|
782
800
|
message = Message(
|
|
783
801
|
metadata=metadata_from_proto(message_proto.metadata),
|
|
784
802
|
content=(
|
|
@@ -792,6 +810,9 @@ def message_from_proto(message_proto: ProtoMessage) -> Message:
|
|
|
792
810
|
else None
|
|
793
811
|
),
|
|
794
812
|
)
|
|
813
|
+
# `.created_at` is set upon Message object construction
|
|
814
|
+
# we need to manually set it to the original value
|
|
815
|
+
message.metadata.created_at = created_at
|
|
795
816
|
return message
|
|
796
817
|
|
|
797
818
|
|
|
@@ -829,8 +850,8 @@ def run_to_proto(run: typing.Run) -> ProtoRun:
|
|
|
829
850
|
run_id=run.run_id,
|
|
830
851
|
fab_id=run.fab_id,
|
|
831
852
|
fab_version=run.fab_version,
|
|
853
|
+
fab_hash=run.fab_hash,
|
|
832
854
|
override_config=user_config_to_proto(run.override_config),
|
|
833
|
-
fab_hash="",
|
|
834
855
|
)
|
|
835
856
|
return proto
|
|
836
857
|
|
|
@@ -841,6 +862,7 @@ def run_from_proto(run_proto: ProtoRun) -> typing.Run:
|
|
|
841
862
|
run_id=run_proto.run_id,
|
|
842
863
|
fab_id=run_proto.fab_id,
|
|
843
864
|
fab_version=run_proto.fab_version,
|
|
865
|
+
fab_hash=run_proto.fab_hash,
|
|
844
866
|
override_config=user_config_from_proto(run_proto.override_config),
|
|
845
867
|
)
|
|
846
868
|
return run
|
flwr/common/typing.py
CHANGED
flwr/proto/clientappio_pb2.py
CHANGED
|
@@ -17,25 +17,29 @@ from flwr.proto import run_pb2 as flwr_dot_proto_dot_run__pb2
|
|
|
17
17
|
from flwr.proto import message_pb2 as flwr_dot_proto_dot_message__pb2
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1c\x66lwr/proto/clientappio.proto\x12\nflwr.proto\x1a\x14\x66lwr/proto/fab.proto\x1a\x14\x66lwr/proto/run.proto\x1a\x18\x66lwr/proto/message.proto\"W\n\x15\x43lientAppOutputStatus\x12-\n\x04\x63ode\x18\x01 \x01(\x0e\x32\x1f.flwr.proto.ClientAppOutputCode\x12\x0f\n\x07message\x18\x02 \x01(\t\"+\n\x1aPullClientAppInputsRequest\x12\r\n\x05token\x18\x01 \x01(\x12\"\
|
|
20
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1c\x66lwr/proto/clientappio.proto\x12\nflwr.proto\x1a\x14\x66lwr/proto/fab.proto\x1a\x14\x66lwr/proto/run.proto\x1a\x18\x66lwr/proto/message.proto\"W\n\x15\x43lientAppOutputStatus\x12-\n\x04\x63ode\x18\x01 \x01(\x0e\x32\x1f.flwr.proto.ClientAppOutputCode\x12\x0f\n\x07message\x18\x02 \x01(\t\"\x11\n\x0fGetTokenRequest\"!\n\x10GetTokenResponse\x12\r\n\x05token\x18\x01 \x01(\x12\"+\n\x1aPullClientAppInputsRequest\x12\r\n\x05token\x18\x01 \x01(\x12\"\xa5\x01\n\x1bPullClientAppInputsResponse\x12$\n\x07message\x18\x01 \x01(\x0b\x32\x13.flwr.proto.Message\x12$\n\x07\x63ontext\x18\x02 \x01(\x0b\x32\x13.flwr.proto.Context\x12\x1c\n\x03run\x18\x03 \x01(\x0b\x32\x0f.flwr.proto.Run\x12\x1c\n\x03\x66\x61\x62\x18\x04 \x01(\x0b\x32\x0f.flwr.proto.Fab\"x\n\x1bPushClientAppOutputsRequest\x12\r\n\x05token\x18\x01 \x01(\x12\x12$\n\x07message\x18\x02 \x01(\x0b\x32\x13.flwr.proto.Message\x12$\n\x07\x63ontext\x18\x03 \x01(\x0b\x32\x13.flwr.proto.Context\"Q\n\x1cPushClientAppOutputsResponse\x12\x31\n\x06status\x18\x01 \x01(\x0b\x32!.flwr.proto.ClientAppOutputStatus*L\n\x13\x43lientAppOutputCode\x12\x0b\n\x07SUCCESS\x10\x00\x12\x15\n\x11\x44\x45\x41\x44LINE_EXCEEDED\x10\x01\x12\x11\n\rUNKNOWN_ERROR\x10\x02\x32\xad\x02\n\x0b\x43lientAppIo\x12G\n\x08GetToken\x12\x1b.flwr.proto.GetTokenRequest\x1a\x1c.flwr.proto.GetTokenResponse\"\x00\x12h\n\x13PullClientAppInputs\x12&.flwr.proto.PullClientAppInputsRequest\x1a\'.flwr.proto.PullClientAppInputsResponse\"\x00\x12k\n\x14PushClientAppOutputs\x12\'.flwr.proto.PushClientAppOutputsRequest\x1a(.flwr.proto.PushClientAppOutputsResponse\"\x00\x62\x06proto3')
|
|
21
21
|
|
|
22
22
|
_globals = globals()
|
|
23
23
|
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
|
24
24
|
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'flwr.proto.clientappio_pb2', _globals)
|
|
25
25
|
if _descriptor._USE_C_DESCRIPTORS == False:
|
|
26
26
|
DESCRIPTOR._options = None
|
|
27
|
-
_globals['_CLIENTAPPOUTPUTCODE']._serialized_start=
|
|
28
|
-
_globals['_CLIENTAPPOUTPUTCODE']._serialized_end=
|
|
27
|
+
_globals['_CLIENTAPPOUTPUTCODE']._serialized_start=675
|
|
28
|
+
_globals['_CLIENTAPPOUTPUTCODE']._serialized_end=751
|
|
29
29
|
_globals['_CLIENTAPPOUTPUTSTATUS']._serialized_start=114
|
|
30
30
|
_globals['_CLIENTAPPOUTPUTSTATUS']._serialized_end=201
|
|
31
|
-
_globals['
|
|
32
|
-
_globals['
|
|
33
|
-
_globals['
|
|
34
|
-
_globals['
|
|
35
|
-
_globals['
|
|
36
|
-
_globals['
|
|
37
|
-
_globals['
|
|
38
|
-
_globals['
|
|
39
|
-
_globals['
|
|
40
|
-
_globals['
|
|
31
|
+
_globals['_GETTOKENREQUEST']._serialized_start=203
|
|
32
|
+
_globals['_GETTOKENREQUEST']._serialized_end=220
|
|
33
|
+
_globals['_GETTOKENRESPONSE']._serialized_start=222
|
|
34
|
+
_globals['_GETTOKENRESPONSE']._serialized_end=255
|
|
35
|
+
_globals['_PULLCLIENTAPPINPUTSREQUEST']._serialized_start=257
|
|
36
|
+
_globals['_PULLCLIENTAPPINPUTSREQUEST']._serialized_end=300
|
|
37
|
+
_globals['_PULLCLIENTAPPINPUTSRESPONSE']._serialized_start=303
|
|
38
|
+
_globals['_PULLCLIENTAPPINPUTSRESPONSE']._serialized_end=468
|
|
39
|
+
_globals['_PUSHCLIENTAPPOUTPUTSREQUEST']._serialized_start=470
|
|
40
|
+
_globals['_PUSHCLIENTAPPOUTPUTSREQUEST']._serialized_end=590
|
|
41
|
+
_globals['_PUSHCLIENTAPPOUTPUTSRESPONSE']._serialized_start=592
|
|
42
|
+
_globals['_PUSHCLIENTAPPOUTPUTSRESPONSE']._serialized_end=673
|
|
43
|
+
_globals['_CLIENTAPPIO']._serialized_start=754
|
|
44
|
+
_globals['_CLIENTAPPIO']._serialized_end=1055
|
|
41
45
|
# @@protoc_insertion_point(module_scope)
|
flwr/proto/clientappio_pb2.pyi
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
isort:skip_file
|
|
4
4
|
"""
|
|
5
5
|
import builtins
|
|
6
|
+
import flwr.proto.fab_pb2
|
|
6
7
|
import flwr.proto.message_pb2
|
|
7
8
|
import flwr.proto.run_pb2
|
|
8
9
|
import google.protobuf.descriptor
|
|
@@ -44,6 +45,23 @@ class ClientAppOutputStatus(google.protobuf.message.Message):
|
|
|
44
45
|
def ClearField(self, field_name: typing_extensions.Literal["code",b"code","message",b"message"]) -> None: ...
|
|
45
46
|
global___ClientAppOutputStatus = ClientAppOutputStatus
|
|
46
47
|
|
|
48
|
+
class GetTokenRequest(google.protobuf.message.Message):
|
|
49
|
+
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
|
50
|
+
def __init__(self,
|
|
51
|
+
) -> None: ...
|
|
52
|
+
global___GetTokenRequest = GetTokenRequest
|
|
53
|
+
|
|
54
|
+
class GetTokenResponse(google.protobuf.message.Message):
|
|
55
|
+
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
|
56
|
+
TOKEN_FIELD_NUMBER: builtins.int
|
|
57
|
+
token: builtins.int
|
|
58
|
+
def __init__(self,
|
|
59
|
+
*,
|
|
60
|
+
token: builtins.int = ...,
|
|
61
|
+
) -> None: ...
|
|
62
|
+
def ClearField(self, field_name: typing_extensions.Literal["token",b"token"]) -> None: ...
|
|
63
|
+
global___GetTokenResponse = GetTokenResponse
|
|
64
|
+
|
|
47
65
|
class PullClientAppInputsRequest(google.protobuf.message.Message):
|
|
48
66
|
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
|
49
67
|
TOKEN_FIELD_NUMBER: builtins.int
|
|
@@ -60,20 +78,24 @@ class PullClientAppInputsResponse(google.protobuf.message.Message):
|
|
|
60
78
|
MESSAGE_FIELD_NUMBER: builtins.int
|
|
61
79
|
CONTEXT_FIELD_NUMBER: builtins.int
|
|
62
80
|
RUN_FIELD_NUMBER: builtins.int
|
|
81
|
+
FAB_FIELD_NUMBER: builtins.int
|
|
63
82
|
@property
|
|
64
83
|
def message(self) -> flwr.proto.message_pb2.Message: ...
|
|
65
84
|
@property
|
|
66
85
|
def context(self) -> flwr.proto.message_pb2.Context: ...
|
|
67
86
|
@property
|
|
68
87
|
def run(self) -> flwr.proto.run_pb2.Run: ...
|
|
88
|
+
@property
|
|
89
|
+
def fab(self) -> flwr.proto.fab_pb2.Fab: ...
|
|
69
90
|
def __init__(self,
|
|
70
91
|
*,
|
|
71
92
|
message: typing.Optional[flwr.proto.message_pb2.Message] = ...,
|
|
72
93
|
context: typing.Optional[flwr.proto.message_pb2.Context] = ...,
|
|
73
94
|
run: typing.Optional[flwr.proto.run_pb2.Run] = ...,
|
|
95
|
+
fab: typing.Optional[flwr.proto.fab_pb2.Fab] = ...,
|
|
74
96
|
) -> None: ...
|
|
75
|
-
def HasField(self, field_name: typing_extensions.Literal["context",b"context","message",b"message","run",b"run"]) -> builtins.bool: ...
|
|
76
|
-
def ClearField(self, field_name: typing_extensions.Literal["context",b"context","message",b"message","run",b"run"]) -> None: ...
|
|
97
|
+
def HasField(self, field_name: typing_extensions.Literal["context",b"context","fab",b"fab","message",b"message","run",b"run"]) -> builtins.bool: ...
|
|
98
|
+
def ClearField(self, field_name: typing_extensions.Literal["context",b"context","fab",b"fab","message",b"message","run",b"run"]) -> None: ...
|
|
77
99
|
global___PullClientAppInputsResponse = PullClientAppInputsResponse
|
|
78
100
|
|
|
79
101
|
class PushClientAppOutputsRequest(google.protobuf.message.Message):
|
|
@@ -14,6 +14,11 @@ class ClientAppIoStub(object):
|
|
|
14
14
|
Args:
|
|
15
15
|
channel: A grpc.Channel.
|
|
16
16
|
"""
|
|
17
|
+
self.GetToken = channel.unary_unary(
|
|
18
|
+
'/flwr.proto.ClientAppIo/GetToken',
|
|
19
|
+
request_serializer=flwr_dot_proto_dot_clientappio__pb2.GetTokenRequest.SerializeToString,
|
|
20
|
+
response_deserializer=flwr_dot_proto_dot_clientappio__pb2.GetTokenResponse.FromString,
|
|
21
|
+
)
|
|
17
22
|
self.PullClientAppInputs = channel.unary_unary(
|
|
18
23
|
'/flwr.proto.ClientAppIo/PullClientAppInputs',
|
|
19
24
|
request_serializer=flwr_dot_proto_dot_clientappio__pb2.PullClientAppInputsRequest.SerializeToString,
|
|
@@ -29,6 +34,13 @@ class ClientAppIoStub(object):
|
|
|
29
34
|
class ClientAppIoServicer(object):
|
|
30
35
|
"""Missing associated documentation comment in .proto file."""
|
|
31
36
|
|
|
37
|
+
def GetToken(self, request, context):
|
|
38
|
+
"""Get token
|
|
39
|
+
"""
|
|
40
|
+
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
|
41
|
+
context.set_details('Method not implemented!')
|
|
42
|
+
raise NotImplementedError('Method not implemented!')
|
|
43
|
+
|
|
32
44
|
def PullClientAppInputs(self, request, context):
|
|
33
45
|
"""Get Message, Context, and Run
|
|
34
46
|
"""
|
|
@@ -46,6 +58,11 @@ class ClientAppIoServicer(object):
|
|
|
46
58
|
|
|
47
59
|
def add_ClientAppIoServicer_to_server(servicer, server):
|
|
48
60
|
rpc_method_handlers = {
|
|
61
|
+
'GetToken': grpc.unary_unary_rpc_method_handler(
|
|
62
|
+
servicer.GetToken,
|
|
63
|
+
request_deserializer=flwr_dot_proto_dot_clientappio__pb2.GetTokenRequest.FromString,
|
|
64
|
+
response_serializer=flwr_dot_proto_dot_clientappio__pb2.GetTokenResponse.SerializeToString,
|
|
65
|
+
),
|
|
49
66
|
'PullClientAppInputs': grpc.unary_unary_rpc_method_handler(
|
|
50
67
|
servicer.PullClientAppInputs,
|
|
51
68
|
request_deserializer=flwr_dot_proto_dot_clientappio__pb2.PullClientAppInputsRequest.FromString,
|
|
@@ -66,6 +83,23 @@ def add_ClientAppIoServicer_to_server(servicer, server):
|
|
|
66
83
|
class ClientAppIo(object):
|
|
67
84
|
"""Missing associated documentation comment in .proto file."""
|
|
68
85
|
|
|
86
|
+
@staticmethod
|
|
87
|
+
def GetToken(request,
|
|
88
|
+
target,
|
|
89
|
+
options=(),
|
|
90
|
+
channel_credentials=None,
|
|
91
|
+
call_credentials=None,
|
|
92
|
+
insecure=False,
|
|
93
|
+
compression=None,
|
|
94
|
+
wait_for_ready=None,
|
|
95
|
+
timeout=None,
|
|
96
|
+
metadata=None):
|
|
97
|
+
return grpc.experimental.unary_unary(request, target, '/flwr.proto.ClientAppIo/GetToken',
|
|
98
|
+
flwr_dot_proto_dot_clientappio__pb2.GetTokenRequest.SerializeToString,
|
|
99
|
+
flwr_dot_proto_dot_clientappio__pb2.GetTokenResponse.FromString,
|
|
100
|
+
options, channel_credentials,
|
|
101
|
+
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
|
102
|
+
|
|
69
103
|
@staticmethod
|
|
70
104
|
def PullClientAppInputs(request,
|
|
71
105
|
target,
|
|
@@ -8,6 +8,11 @@ import grpc
|
|
|
8
8
|
|
|
9
9
|
class ClientAppIoStub:
|
|
10
10
|
def __init__(self, channel: grpc.Channel) -> None: ...
|
|
11
|
+
GetToken: grpc.UnaryUnaryMultiCallable[
|
|
12
|
+
flwr.proto.clientappio_pb2.GetTokenRequest,
|
|
13
|
+
flwr.proto.clientappio_pb2.GetTokenResponse]
|
|
14
|
+
"""Get token"""
|
|
15
|
+
|
|
11
16
|
PullClientAppInputs: grpc.UnaryUnaryMultiCallable[
|
|
12
17
|
flwr.proto.clientappio_pb2.PullClientAppInputsRequest,
|
|
13
18
|
flwr.proto.clientappio_pb2.PullClientAppInputsResponse]
|
|
@@ -20,6 +25,14 @@ class ClientAppIoStub:
|
|
|
20
25
|
|
|
21
26
|
|
|
22
27
|
class ClientAppIoServicer(metaclass=abc.ABCMeta):
|
|
28
|
+
@abc.abstractmethod
|
|
29
|
+
def GetToken(self,
|
|
30
|
+
request: flwr.proto.clientappio_pb2.GetTokenRequest,
|
|
31
|
+
context: grpc.ServicerContext,
|
|
32
|
+
) -> flwr.proto.clientappio_pb2.GetTokenResponse:
|
|
33
|
+
"""Get token"""
|
|
34
|
+
pass
|
|
35
|
+
|
|
23
36
|
@abc.abstractmethod
|
|
24
37
|
def PullClientAppInputs(self,
|
|
25
38
|
request: flwr.proto.clientappio_pb2.PullClientAppInputsRequest,
|
flwr/proto/exec_pb2.py
CHANGED
|
@@ -12,10 +12,11 @@ from google.protobuf.internal import builder as _builder
|
|
|
12
12
|
_sym_db = _symbol_database.Default()
|
|
13
13
|
|
|
14
14
|
|
|
15
|
+
from flwr.proto import fab_pb2 as flwr_dot_proto_dot_fab__pb2
|
|
15
16
|
from flwr.proto import transport_pb2 as flwr_dot_proto_dot_transport__pb2
|
|
16
17
|
|
|
17
18
|
|
|
18
|
-
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15\x66lwr/proto/exec.proto\x12\nflwr.proto\x1a\x1a\x66lwr/proto/transport.proto\"\
|
|
19
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15\x66lwr/proto/exec.proto\x12\nflwr.proto\x1a\x14\x66lwr/proto/fab.proto\x1a\x1a\x66lwr/proto/transport.proto\"\xdf\x02\n\x0fStartRunRequest\x12\x1c\n\x03\x66\x61\x62\x18\x01 \x01(\x0b\x32\x0f.flwr.proto.Fab\x12H\n\x0foverride_config\x18\x02 \x03(\x0b\x32/.flwr.proto.StartRunRequest.OverrideConfigEntry\x12L\n\x11\x66\x65\x64\x65ration_config\x18\x03 \x03(\x0b\x32\x31.flwr.proto.StartRunRequest.FederationConfigEntry\x1aI\n\x13OverrideConfigEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12!\n\x05value\x18\x02 \x01(\x0b\x32\x12.flwr.proto.Scalar:\x02\x38\x01\x1aK\n\x15\x46\x65\x64\x65rationConfigEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12!\n\x05value\x18\x02 \x01(\x0b\x32\x12.flwr.proto.Scalar:\x02\x38\x01\"\"\n\x10StartRunResponse\x12\x0e\n\x06run_id\x18\x01 \x01(\x12\"#\n\x11StreamLogsRequest\x12\x0e\n\x06run_id\x18\x01 \x01(\x12\"(\n\x12StreamLogsResponse\x12\x12\n\nlog_output\x18\x01 \x01(\t2\xa0\x01\n\x04\x45xec\x12G\n\x08StartRun\x12\x1b.flwr.proto.StartRunRequest\x1a\x1c.flwr.proto.StartRunResponse\"\x00\x12O\n\nStreamLogs\x12\x1d.flwr.proto.StreamLogsRequest\x1a\x1e.flwr.proto.StreamLogsResponse\"\x00\x30\x01\x62\x06proto3')
|
|
19
20
|
|
|
20
21
|
_globals = globals()
|
|
21
22
|
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
|
@@ -26,18 +27,18 @@ if _descriptor._USE_C_DESCRIPTORS == False:
|
|
|
26
27
|
_globals['_STARTRUNREQUEST_OVERRIDECONFIGENTRY']._serialized_options = b'8\001'
|
|
27
28
|
_globals['_STARTRUNREQUEST_FEDERATIONCONFIGENTRY']._options = None
|
|
28
29
|
_globals['_STARTRUNREQUEST_FEDERATIONCONFIGENTRY']._serialized_options = b'8\001'
|
|
29
|
-
_globals['_STARTRUNREQUEST']._serialized_start=
|
|
30
|
-
_globals['_STARTRUNREQUEST']._serialized_end=
|
|
31
|
-
_globals['_STARTRUNREQUEST_OVERRIDECONFIGENTRY']._serialized_start=
|
|
32
|
-
_globals['_STARTRUNREQUEST_OVERRIDECONFIGENTRY']._serialized_end=
|
|
33
|
-
_globals['_STARTRUNREQUEST_FEDERATIONCONFIGENTRY']._serialized_start=
|
|
34
|
-
_globals['_STARTRUNREQUEST_FEDERATIONCONFIGENTRY']._serialized_end=
|
|
35
|
-
_globals['_STARTRUNRESPONSE']._serialized_start=
|
|
36
|
-
_globals['_STARTRUNRESPONSE']._serialized_end=
|
|
37
|
-
_globals['_STREAMLOGSREQUEST']._serialized_start=
|
|
38
|
-
_globals['_STREAMLOGSREQUEST']._serialized_end=
|
|
39
|
-
_globals['_STREAMLOGSRESPONSE']._serialized_start=
|
|
40
|
-
_globals['_STREAMLOGSRESPONSE']._serialized_end=
|
|
41
|
-
_globals['_EXEC']._serialized_start=
|
|
42
|
-
_globals['_EXEC']._serialized_end=
|
|
30
|
+
_globals['_STARTRUNREQUEST']._serialized_start=88
|
|
31
|
+
_globals['_STARTRUNREQUEST']._serialized_end=439
|
|
32
|
+
_globals['_STARTRUNREQUEST_OVERRIDECONFIGENTRY']._serialized_start=289
|
|
33
|
+
_globals['_STARTRUNREQUEST_OVERRIDECONFIGENTRY']._serialized_end=362
|
|
34
|
+
_globals['_STARTRUNREQUEST_FEDERATIONCONFIGENTRY']._serialized_start=364
|
|
35
|
+
_globals['_STARTRUNREQUEST_FEDERATIONCONFIGENTRY']._serialized_end=439
|
|
36
|
+
_globals['_STARTRUNRESPONSE']._serialized_start=441
|
|
37
|
+
_globals['_STARTRUNRESPONSE']._serialized_end=475
|
|
38
|
+
_globals['_STREAMLOGSREQUEST']._serialized_start=477
|
|
39
|
+
_globals['_STREAMLOGSREQUEST']._serialized_end=512
|
|
40
|
+
_globals['_STREAMLOGSRESPONSE']._serialized_start=514
|
|
41
|
+
_globals['_STREAMLOGSRESPONSE']._serialized_end=554
|
|
42
|
+
_globals['_EXEC']._serialized_start=557
|
|
43
|
+
_globals['_EXEC']._serialized_end=717
|
|
43
44
|
# @@protoc_insertion_point(module_scope)
|