flwr-nightly 1.23.0.dev20251027__py3-none-any.whl → 1.23.0.dev20251029__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/build.py CHANGED
@@ -17,22 +17,25 @@
17
17
 
18
18
  import hashlib
19
19
  import zipfile
20
+ from collections.abc import Iterable
20
21
  from io import BytesIO
21
22
  from pathlib import Path
22
23
  from typing import Annotated, Any, Optional, Union
23
24
 
24
25
  import pathspec
26
+ import tomli
25
27
  import tomli_w
26
28
  import typer
27
29
 
28
30
  from flwr.common.constant import (
29
- FAB_ALLOWED_EXTENSIONS,
31
+ FAB_CONFIG_FILE,
30
32
  FAB_DATE,
33
+ FAB_EXCLUDE_PATTERNS,
31
34
  FAB_HASH_TRUNCATION,
35
+ FAB_INCLUDE_PATTERNS,
32
36
  FAB_MAX_SIZE,
33
37
  )
34
38
 
35
- from .config_utils import load as load_toml
36
39
  from .config_utils import load_and_validate
37
40
  from .utils import is_valid_project_name
38
41
 
@@ -112,7 +115,10 @@ def build(
112
115
  )
113
116
 
114
117
  # Build FAB
115
- fab_bytes, fab_hash, _ = build_fab(app)
118
+ fab_bytes = build_fab_from_disk(app)
119
+
120
+ # Calculate hash for filename
121
+ fab_hash = hashlib.sha256(fab_bytes).hexdigest()
116
122
 
117
123
  # Get the name of the zip file
118
124
  fab_filename = get_fab_filename(config, fab_hash)
@@ -125,11 +131,10 @@ def build(
125
131
  )
126
132
 
127
133
 
128
- def build_fab(app: Path) -> tuple[bytes, str, dict[str, Any]]:
129
- """Build a FAB in memory and return the bytes, hash, and config.
134
+ def build_fab_from_disk(app: Path) -> bytes:
135
+ """Build a FAB from files on disk and return the FAB as bytes.
130
136
 
131
- This function assumes that the provided path points to a valid Flower app and
132
- bundles it into a FAB without performing additional validation.
137
+ This function reads files from disk and bundles them into a FAB.
133
138
 
134
139
  Parameters
135
140
  ----------
@@ -138,18 +143,67 @@ def build_fab(app: Path) -> tuple[bytes, str, dict[str, Any]]:
138
143
 
139
144
  Returns
140
145
  -------
141
- tuple[bytes, str, dict[str, Any]]
142
- A tuple containing:
143
- - the FAB as bytes
144
- - the SHA256 hash of the FAB
145
- - the project configuration (with the 'federations' field removed)
146
+ bytes
147
+ The FAB as bytes.
146
148
  """
147
149
  app = app.resolve()
148
150
 
149
- # Load the pyproject.toml file
150
- config = load_toml(app / "pyproject.toml")
151
- if config is None:
152
- raise ValueError("Project configuration could not be loaded.")
151
+ # Collect all files recursively (including pyproject.toml and .gitignore)
152
+ all_files = [f for f in app.rglob("*") if f.is_file()]
153
+
154
+ # Create dict mapping relative paths to Path objects
155
+ files_dict: dict[str, Union[bytes, Path]] = {
156
+ # Ensure consistent path separators across platforms
157
+ str(file_path.relative_to(app)).replace("\\", "/"): file_path
158
+ for file_path in all_files
159
+ }
160
+
161
+ # Build FAB from the files dict
162
+ return build_fab_from_files(files_dict)
163
+
164
+
165
+ def build_fab_from_files(files: dict[str, Union[bytes, Path]]) -> bytes:
166
+ r"""Build a FAB from in-memory files and return the FAB as bytes.
167
+
168
+ This is the core FAB building function that works with in-memory data.
169
+ It accepts either bytes or Path objects as file contents, applies filtering
170
+ rules (include/exclude patterns), and builds the FAB.
171
+
172
+ Parameters
173
+ ----------
174
+ files : dict[str, Union[bytes, Path]]
175
+ Dictionary mapping relative file paths to their contents.
176
+ - Keys: Relative paths (strings)
177
+ - Values: Either bytes (file contents) or Path (will be read)
178
+ Must include "pyproject.toml" and optionally ".gitignore".
179
+
180
+ Returns
181
+ -------
182
+ bytes
183
+ The FAB as bytes.
184
+
185
+ Examples
186
+ --------
187
+ Build a FAB from in-memory files::
188
+
189
+ files = {
190
+ "pyproject.toml": b"[project]\nname = 'myapp'\n...",
191
+ ".gitignore": b"*.pyc\n__pycache__/\n",
192
+ "src/client.py": Path("/path/to/client.py"),
193
+ "src/server.py": b"print('hello')",
194
+ "README.md": b"# My App\n",
195
+ }
196
+ fab_bytes = build_fab_from_files(files)
197
+ """
198
+
199
+ def to_bytes(content: Union[bytes, Path]) -> bytes:
200
+ return content.read_bytes() if isinstance(content, Path) else content
201
+
202
+ # Extract, load, and parse pyproject.toml
203
+ if FAB_CONFIG_FILE not in files:
204
+ raise ValueError(f"{FAB_CONFIG_FILE} not found in files")
205
+ pyproject_content = to_bytes(files[FAB_CONFIG_FILE])
206
+ config = tomli.loads(pyproject_content.decode("utf-8"))
153
207
 
154
208
  # Remove the 'federations' field if it exists
155
209
  if (
@@ -159,18 +213,22 @@ def build_fab(app: Path) -> tuple[bytes, str, dict[str, Any]]:
159
213
  ):
160
214
  del config["tool"]["flwr"]["federations"]
161
215
 
162
- # Load .gitignore rules if present
163
- ignore_spec = _load_gitignore(app)
216
+ # Extract and load .gitignore if present
217
+ gitignore_content = None
218
+ if ".gitignore" in files:
219
+ gitignore_content = to_bytes(files[".gitignore"])
220
+
221
+ # Get exclude and include specs
222
+ exclude_spec = get_fab_exclude_pathspec(gitignore_content)
223
+ include_spec = get_fab_include_pathspec()
164
224
 
165
- # Search for all files in the app directory
166
- all_files = [
167
- f
168
- for f in app.rglob("*")
169
- if not ignore_spec.match_file(f)
170
- and f.suffix in FAB_ALLOWED_EXTENSIONS
171
- and f.name != "pyproject.toml" # Exclude the original pyproject.toml
225
+ # Filter files based on include/exclude specs
226
+ filtered_paths = [
227
+ path.replace("\\", "/") # Ensure consistent path separators across platforms
228
+ for path in files.keys()
229
+ if include_spec.match_file(path) and not exclude_spec.match_file(path)
172
230
  ]
173
- all_files.sort()
231
+ filtered_paths.sort() # Sort for deterministic output
174
232
 
175
233
  # Create a zip file in memory
176
234
  list_file_content = ""
@@ -178,41 +236,54 @@ def build_fab(app: Path) -> tuple[bytes, str, dict[str, Any]]:
178
236
  fab_buffer = BytesIO()
179
237
  with zipfile.ZipFile(fab_buffer, "w", zipfile.ZIP_DEFLATED) as fab_file:
180
238
  # Add pyproject.toml
181
- write_to_zip(fab_file, "pyproject.toml", tomli_w.dumps(config))
239
+ write_to_zip(fab_file, FAB_CONFIG_FILE, tomli_w.dumps(config))
182
240
 
183
- for file_path in all_files:
184
- # Read the file content manually
185
- file_contents = file_path.read_bytes()
241
+ for file_path in filtered_paths:
186
242
 
187
- archive_path = str(file_path.relative_to(app)).replace("\\", "/")
188
- write_to_zip(fab_file, archive_path, file_contents)
243
+ # Get file contents as bytes
244
+ file_content = to_bytes(files[file_path])
189
245
 
190
- # Calculate file info
191
- sha256_hash = hashlib.sha256(file_contents).hexdigest()
192
- file_size_bits = len(file_contents) * 8 # size in bits
193
- list_file_content += f"{archive_path},{sha256_hash},{file_size_bits}\n"
246
+ # Write file to FAB
247
+ write_to_zip(fab_file, file_path, file_content)
194
248
 
195
- # Add CONTENT and CONTENT.jwt to the zip file
249
+ # Calculate file info for CONTENT manifest
250
+ sha256_hash = hashlib.sha256(file_content).hexdigest()
251
+ file_size_bits = len(file_content) * 8 # size in bits
252
+ list_file_content += f"{file_path},{sha256_hash},{file_size_bits}\n"
253
+
254
+ # Add CONTENT manifest to the zip file
196
255
  write_to_zip(fab_file, ".info/CONTENT", list_file_content)
197
256
 
198
257
  fab_bytes = fab_buffer.getvalue()
258
+
259
+ # Validate FAB size
199
260
  if len(fab_bytes) > FAB_MAX_SIZE:
200
261
  raise ValueError(
201
- f"FAB size exceeds maximum allowed size of {FAB_MAX_SIZE:,} bytes."
262
+ f"FAB size exceeds maximum allowed size of {FAB_MAX_SIZE:,} bytes. "
202
263
  "To reduce the package size, consider ignoring unnecessary files "
203
264
  "via your `.gitignore` file or excluding them from the build."
204
265
  )
205
266
 
206
- fab_hash = hashlib.sha256(fab_bytes).hexdigest()
267
+ return fab_bytes
207
268
 
208
- return fab_bytes, fab_hash, config
209
269
 
270
+ def build_pathspec(patterns: Iterable[str]) -> pathspec.PathSpec:
271
+ """Build a PathSpec from a list of patterns."""
272
+ return pathspec.PathSpec.from_lines("gitwildmatch", patterns)
273
+
274
+
275
+ def get_fab_include_pathspec() -> pathspec.PathSpec:
276
+ """Get the PathSpec for files to include in a FAB."""
277
+ return build_pathspec(FAB_INCLUDE_PATTERNS)
210
278
 
211
- def _load_gitignore(app: Path) -> pathspec.PathSpec:
212
- """Load and parse .gitignore file, returning a pathspec."""
213
- gitignore_path = app / ".gitignore"
214
- patterns = ["__pycache__/"] # Default pattern
215
- if gitignore_path.exists():
216
- with open(gitignore_path, encoding="UTF-8") as file:
217
- patterns.extend(file.readlines())
279
+
280
+ def get_fab_exclude_pathspec(gitignore_content: Optional[bytes]) -> pathspec.PathSpec:
281
+ """Get the PathSpec for files to exclude from a FAB.
282
+
283
+ If gitignore_content is provided, its patterns will be combined with the default
284
+ exclude patterns.
285
+ """
286
+ patterns = list(FAB_EXCLUDE_PATTERNS)
287
+ if gitignore_content:
288
+ patterns += gitignore_content.decode("UTF-8").splitlines()
218
289
  return pathspec.PathSpec.from_lines("gitwildmatch", patterns)
flwr/cli/run/run.py CHANGED
@@ -15,16 +15,18 @@
15
15
  """Flower command line interface `run` command."""
16
16
 
17
17
 
18
+ import hashlib
18
19
  import io
19
20
  import json
20
21
  import subprocess
21
22
  from pathlib import Path
22
- from typing import Annotated, Any, Optional
23
+ from typing import Annotated, Any, Optional, cast
23
24
 
24
25
  import typer
25
26
  from rich.console import Console
26
27
 
27
- from flwr.cli.build import build_fab, get_fab_filename
28
+ from flwr.cli.build import build_fab_from_disk, get_fab_filename
29
+ from flwr.cli.config_utils import load as load_toml
28
30
  from flwr.cli.config_utils import (
29
31
  load_and_validate,
30
32
  process_loaded_project_config,
@@ -37,7 +39,7 @@ from flwr.common.config import (
37
39
  parse_config_args,
38
40
  user_config_to_configrecord,
39
41
  )
40
- from flwr.common.constant import CliOutputFormat
42
+ from flwr.common.constant import FAB_CONFIG_FILE, CliOutputFormat
41
43
  from flwr.common.logger import print_json_error, redirect_output, restore_output
42
44
  from flwr.common.serde import config_record_to_proto, fab_to_proto, user_config_to_proto
43
45
  from flwr.common.typing import Fab
@@ -152,7 +154,9 @@ def _run_with_control_api(
152
154
  channel = init_channel(app, federation_config, auth_plugin)
153
155
  stub = ControlStub(channel)
154
156
 
155
- fab_bytes, fab_hash, config = build_fab(app)
157
+ fab_bytes = build_fab_from_disk(app)
158
+ fab_hash = hashlib.sha256(fab_bytes).hexdigest()
159
+ config = cast(dict[str, Any], load_toml(app / FAB_CONFIG_FILE))
156
160
  fab_id, fab_version = get_metadata_from_config(config)
157
161
 
158
162
  fab = Fab(fab_hash, fab_bytes, {})
@@ -34,14 +34,22 @@ from flwr.common.constant import (
34
34
  from flwr.common.version import package_name, package_version
35
35
  from flwr.proto.fab_pb2 import GetFabRequest, GetFabResponse # pylint: disable=E0611
36
36
  from flwr.proto.fleet_pb2 import ( # pylint: disable=E0611
37
+ ActivateNodeRequest,
38
+ ActivateNodeResponse,
37
39
  CreateNodeRequest,
38
40
  CreateNodeResponse,
41
+ DeactivateNodeRequest,
42
+ DeactivateNodeResponse,
39
43
  DeleteNodeRequest,
40
44
  DeleteNodeResponse,
41
45
  PullMessagesRequest,
42
46
  PullMessagesResponse,
43
47
  PushMessagesRequest,
44
48
  PushMessagesResponse,
49
+ RegisterNodeFleetRequest,
50
+ RegisterNodeFleetResponse,
51
+ UnregisterNodeFleetRequest,
52
+ UnregisterNodeFleetResponse,
45
53
  )
46
54
  from flwr.proto.grpcadapter_pb2 import MessageContainer # pylint: disable=E0611
47
55
  from flwr.proto.grpcadapter_pb2_grpc import GrpcAdapterStub
@@ -130,6 +138,30 @@ class GrpcAdapter:
130
138
  """."""
131
139
  return self._send_and_receive(request, DeleteNodeResponse, **kwargs)
132
140
 
141
+ def RegisterNode( # pylint: disable=C0103
142
+ self, request: RegisterNodeFleetRequest, **kwargs: Any
143
+ ) -> RegisterNodeFleetResponse:
144
+ """."""
145
+ return self._send_and_receive(request, RegisterNodeFleetResponse, **kwargs)
146
+
147
+ def ActivateNode( # pylint: disable=C0103
148
+ self, request: ActivateNodeRequest, **kwargs: Any
149
+ ) -> ActivateNodeResponse:
150
+ """."""
151
+ return self._send_and_receive(request, ActivateNodeResponse, **kwargs)
152
+
153
+ def DeactivateNode( # pylint: disable=C0103
154
+ self, request: DeactivateNodeRequest, **kwargs: Any
155
+ ) -> DeactivateNodeResponse:
156
+ """."""
157
+ return self._send_and_receive(request, DeactivateNodeResponse, **kwargs)
158
+
159
+ def UnregisterNode( # pylint: disable=C0103
160
+ self, request: UnregisterNodeFleetRequest, **kwargs: Any
161
+ ) -> UnregisterNodeFleetResponse:
162
+ """."""
163
+ return self._send_and_receive(request, UnregisterNodeFleetResponse, **kwargs)
164
+
133
165
  def SendNodeHeartbeat( # pylint: disable=C0103
134
166
  self, request: SendNodeHeartbeatRequest, **kwargs: Any
135
167
  ) -> SendNodeHeartbeatResponse:
flwr/common/constant.py CHANGED
@@ -72,13 +72,23 @@ NODE_ID_NUM_BYTES = 8
72
72
 
73
73
  # Constants for FAB
74
74
  APP_DIR = "apps"
75
- FAB_ALLOWED_EXTENSIONS = {".py", ".toml", ".md"}
76
75
  FAB_CONFIG_FILE = "pyproject.toml"
77
76
  FAB_DATE = (2024, 10, 1, 0, 0, 0)
78
77
  FAB_HASH_TRUNCATION = 8
79
78
  FAB_MAX_SIZE = 10 * 1024 * 1024 # 10 MB
80
79
  FLWR_DIR = ".flwr" # The default Flower directory: ~/.flwr/
81
80
  FLWR_HOME = "FLWR_HOME" # If set, override the default Flower directory
81
+ # FAB file include patterns (gitignore-style patterns)
82
+ FAB_INCLUDE_PATTERNS = (
83
+ "**/*.py",
84
+ "**/*.toml",
85
+ "**/*.md",
86
+ )
87
+ # FAB file exclude patterns (gitignore-style patterns)
88
+ FAB_EXCLUDE_PATTERNS = (
89
+ "**/__pycache__/**",
90
+ FAB_CONFIG_FILE, # Exclude the original pyproject.toml
91
+ )
82
92
 
83
93
  # Constant for SuperLink
84
94
  SUPERLINK_NODE_ID = 1
flwr/proto/fleet_pb2.py CHANGED
@@ -19,7 +19,7 @@ from flwr.proto import fab_pb2 as flwr_dot_proto_dot_fab__pb2
19
19
  from flwr.proto import message_pb2 as flwr_dot_proto_dot_message__pb2
20
20
 
21
21
 
22
- DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16\x66lwr/proto/fleet.proto\x12\nflwr.proto\x1a\x1a\x66lwr/proto/heartbeat.proto\x1a\x15\x66lwr/proto/node.proto\x1a\x14\x66lwr/proto/run.proto\x1a\x14\x66lwr/proto/fab.proto\x1a\x18\x66lwr/proto/message.proto\"C\n\x11\x43reateNodeRequest\x12\x12\n\npublic_key\x18\x01 \x01(\x0c\x12\x1a\n\x12heartbeat_interval\x18\x02 \x01(\x01\"4\n\x12\x43reateNodeResponse\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\"3\n\x11\x44\x65leteNodeRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\"\x14\n\x12\x44\x65leteNodeResponse\"J\n\x13PullMessagesRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x13\n\x0bmessage_ids\x18\x02 \x03(\t\"\xa2\x01\n\x14PullMessagesResponse\x12(\n\treconnect\x18\x01 \x01(\x0b\x32\x15.flwr.proto.Reconnect\x12*\n\rmessages_list\x18\x02 \x03(\x0b\x32\x13.flwr.proto.Message\x12\x34\n\x14message_object_trees\x18\x03 \x03(\x0b\x32\x16.flwr.proto.ObjectTree\"\x97\x01\n\x13PushMessagesRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12*\n\rmessages_list\x18\x02 \x03(\x0b\x32\x13.flwr.proto.Message\x12\x34\n\x14message_object_trees\x18\x03 \x03(\x0b\x32\x16.flwr.proto.ObjectTree\"\xc9\x01\n\x14PushMessagesResponse\x12(\n\treconnect\x18\x01 \x01(\x0b\x32\x15.flwr.proto.Reconnect\x12>\n\x07results\x18\x02 \x03(\x0b\x32-.flwr.proto.PushMessagesResponse.ResultsEntry\x12\x17\n\x0fobjects_to_push\x18\x03 \x03(\t\x1a.\n\x0cResultsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\"\x1e\n\tReconnect\x12\x11\n\treconnect\x18\x01 \x01(\x04\x32\xca\x06\n\x05\x46leet\x12M\n\nCreateNode\x12\x1d.flwr.proto.CreateNodeRequest\x1a\x1e.flwr.proto.CreateNodeResponse\"\x00\x12M\n\nDeleteNode\x12\x1d.flwr.proto.DeleteNodeRequest\x1a\x1e.flwr.proto.DeleteNodeResponse\"\x00\x12\x62\n\x11SendNodeHeartbeat\x12$.flwr.proto.SendNodeHeartbeatRequest\x1a%.flwr.proto.SendNodeHeartbeatResponse\"\x00\x12S\n\x0cPullMessages\x12\x1f.flwr.proto.PullMessagesRequest\x1a .flwr.proto.PullMessagesResponse\"\x00\x12S\n\x0cPushMessages\x12\x1f.flwr.proto.PushMessagesRequest\x1a .flwr.proto.PushMessagesResponse\"\x00\x12\x41\n\x06GetRun\x12\x19.flwr.proto.GetRunRequest\x1a\x1a.flwr.proto.GetRunResponse\"\x00\x12\x41\n\x06GetFab\x12\x19.flwr.proto.GetFabRequest\x1a\x1a.flwr.proto.GetFabResponse\"\x00\x12M\n\nPushObject\x12\x1d.flwr.proto.PushObjectRequest\x1a\x1e.flwr.proto.PushObjectResponse\"\x00\x12M\n\nPullObject\x12\x1d.flwr.proto.PullObjectRequest\x1a\x1e.flwr.proto.PullObjectResponse\"\x00\x12q\n\x16\x43onfirmMessageReceived\x12).flwr.proto.ConfirmMessageReceivedRequest\x1a*.flwr.proto.ConfirmMessageReceivedResponse\"\x00\x62\x06proto3')
22
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16\x66lwr/proto/fleet.proto\x12\nflwr.proto\x1a\x1a\x66lwr/proto/heartbeat.proto\x1a\x15\x66lwr/proto/node.proto\x1a\x14\x66lwr/proto/run.proto\x1a\x14\x66lwr/proto/fab.proto\x1a\x18\x66lwr/proto/message.proto\"C\n\x11\x43reateNodeRequest\x12\x12\n\npublic_key\x18\x01 \x01(\x0c\x12\x1a\n\x12heartbeat_interval\x18\x02 \x01(\x01\"4\n\x12\x43reateNodeResponse\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\"3\n\x11\x44\x65leteNodeRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\"\x14\n\x12\x44\x65leteNodeResponse\".\n\x18RegisterNodeFleetRequest\x12\x12\n\npublic_key\x18\x01 \x01(\x0c\"\x1b\n\x19RegisterNodeFleetResponse\"E\n\x13\x41\x63tivateNodeRequest\x12\x12\n\npublic_key\x18\x01 \x01(\x0c\x12\x1a\n\x12heartbeat_interval\x18\x02 \x01(\x01\"\'\n\x14\x41\x63tivateNodeResponse\x12\x0f\n\x07node_id\x18\x01 \x01(\x04\"(\n\x15\x44\x65\x61\x63tivateNodeRequest\x12\x0f\n\x07node_id\x18\x01 \x01(\x04\"\x18\n\x16\x44\x65\x61\x63tivateNodeResponse\"-\n\x1aUnregisterNodeFleetRequest\x12\x0f\n\x07node_id\x18\x01 \x01(\x04\"\x1d\n\x1bUnregisterNodeFleetResponse\"J\n\x13PullMessagesRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12\x13\n\x0bmessage_ids\x18\x02 \x03(\t\"\xa2\x01\n\x14PullMessagesResponse\x12(\n\treconnect\x18\x01 \x01(\x0b\x32\x15.flwr.proto.Reconnect\x12*\n\rmessages_list\x18\x02 \x03(\x0b\x32\x13.flwr.proto.Message\x12\x34\n\x14message_object_trees\x18\x03 \x03(\x0b\x32\x16.flwr.proto.ObjectTree\"\x97\x01\n\x13PushMessagesRequest\x12\x1e\n\x04node\x18\x01 \x01(\x0b\x32\x10.flwr.proto.Node\x12*\n\rmessages_list\x18\x02 \x03(\x0b\x32\x13.flwr.proto.Message\x12\x34\n\x14message_object_trees\x18\x03 \x03(\x0b\x32\x16.flwr.proto.ObjectTree\"\xc9\x01\n\x14PushMessagesResponse\x12(\n\treconnect\x18\x01 \x01(\x0b\x32\x15.flwr.proto.Reconnect\x12>\n\x07results\x18\x02 \x03(\x0b\x32-.flwr.proto.PushMessagesResponse.ResultsEntry\x12\x17\n\x0fobjects_to_push\x18\x03 \x03(\t\x1a.\n\x0cResultsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\"\x1e\n\tReconnect\x12\x11\n\treconnect\x18\x01 \x01(\x04\x32\xbe\t\n\x05\x46leet\x12M\n\nCreateNode\x12\x1d.flwr.proto.CreateNodeRequest\x1a\x1e.flwr.proto.CreateNodeResponse\"\x00\x12M\n\nDeleteNode\x12\x1d.flwr.proto.DeleteNodeRequest\x1a\x1e.flwr.proto.DeleteNodeResponse\"\x00\x12]\n\x0cRegisterNode\x12$.flwr.proto.RegisterNodeFleetRequest\x1a%.flwr.proto.RegisterNodeFleetResponse\"\x00\x12S\n\x0c\x41\x63tivateNode\x12\x1f.flwr.proto.ActivateNodeRequest\x1a .flwr.proto.ActivateNodeResponse\"\x00\x12Y\n\x0e\x44\x65\x61\x63tivateNode\x12!.flwr.proto.DeactivateNodeRequest\x1a\".flwr.proto.DeactivateNodeResponse\"\x00\x12\x63\n\x0eUnregisterNode\x12&.flwr.proto.UnregisterNodeFleetRequest\x1a\'.flwr.proto.UnregisterNodeFleetResponse\"\x00\x12\x62\n\x11SendNodeHeartbeat\x12$.flwr.proto.SendNodeHeartbeatRequest\x1a%.flwr.proto.SendNodeHeartbeatResponse\"\x00\x12S\n\x0cPullMessages\x12\x1f.flwr.proto.PullMessagesRequest\x1a .flwr.proto.PullMessagesResponse\"\x00\x12S\n\x0cPushMessages\x12\x1f.flwr.proto.PushMessagesRequest\x1a .flwr.proto.PushMessagesResponse\"\x00\x12\x41\n\x06GetRun\x12\x19.flwr.proto.GetRunRequest\x1a\x1a.flwr.proto.GetRunResponse\"\x00\x12\x41\n\x06GetFab\x12\x19.flwr.proto.GetFabRequest\x1a\x1a.flwr.proto.GetFabResponse\"\x00\x12M\n\nPushObject\x12\x1d.flwr.proto.PushObjectRequest\x1a\x1e.flwr.proto.PushObjectResponse\"\x00\x12M\n\nPullObject\x12\x1d.flwr.proto.PullObjectRequest\x1a\x1e.flwr.proto.PullObjectResponse\"\x00\x12q\n\x16\x43onfirmMessageReceived\x12).flwr.proto.ConfirmMessageReceivedRequest\x1a*.flwr.proto.ConfirmMessageReceivedResponse\"\x00\x62\x06proto3')
23
23
 
24
24
  _globals = globals()
25
25
  _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -36,18 +36,34 @@ if _descriptor._USE_C_DESCRIPTORS == False:
36
36
  _globals['_DELETENODEREQUEST']._serialized_end=333
37
37
  _globals['_DELETENODERESPONSE']._serialized_start=335
38
38
  _globals['_DELETENODERESPONSE']._serialized_end=355
39
- _globals['_PULLMESSAGESREQUEST']._serialized_start=357
40
- _globals['_PULLMESSAGESREQUEST']._serialized_end=431
41
- _globals['_PULLMESSAGESRESPONSE']._serialized_start=434
42
- _globals['_PULLMESSAGESRESPONSE']._serialized_end=596
43
- _globals['_PUSHMESSAGESREQUEST']._serialized_start=599
44
- _globals['_PUSHMESSAGESREQUEST']._serialized_end=750
45
- _globals['_PUSHMESSAGESRESPONSE']._serialized_start=753
46
- _globals['_PUSHMESSAGESRESPONSE']._serialized_end=954
47
- _globals['_PUSHMESSAGESRESPONSE_RESULTSENTRY']._serialized_start=908
48
- _globals['_PUSHMESSAGESRESPONSE_RESULTSENTRY']._serialized_end=954
49
- _globals['_RECONNECT']._serialized_start=956
50
- _globals['_RECONNECT']._serialized_end=986
51
- _globals['_FLEET']._serialized_start=989
52
- _globals['_FLEET']._serialized_end=1831
39
+ _globals['_REGISTERNODEFLEETREQUEST']._serialized_start=357
40
+ _globals['_REGISTERNODEFLEETREQUEST']._serialized_end=403
41
+ _globals['_REGISTERNODEFLEETRESPONSE']._serialized_start=405
42
+ _globals['_REGISTERNODEFLEETRESPONSE']._serialized_end=432
43
+ _globals['_ACTIVATENODEREQUEST']._serialized_start=434
44
+ _globals['_ACTIVATENODEREQUEST']._serialized_end=503
45
+ _globals['_ACTIVATENODERESPONSE']._serialized_start=505
46
+ _globals['_ACTIVATENODERESPONSE']._serialized_end=544
47
+ _globals['_DEACTIVATENODEREQUEST']._serialized_start=546
48
+ _globals['_DEACTIVATENODEREQUEST']._serialized_end=586
49
+ _globals['_DEACTIVATENODERESPONSE']._serialized_start=588
50
+ _globals['_DEACTIVATENODERESPONSE']._serialized_end=612
51
+ _globals['_UNREGISTERNODEFLEETREQUEST']._serialized_start=614
52
+ _globals['_UNREGISTERNODEFLEETREQUEST']._serialized_end=659
53
+ _globals['_UNREGISTERNODEFLEETRESPONSE']._serialized_start=661
54
+ _globals['_UNREGISTERNODEFLEETRESPONSE']._serialized_end=690
55
+ _globals['_PULLMESSAGESREQUEST']._serialized_start=692
56
+ _globals['_PULLMESSAGESREQUEST']._serialized_end=766
57
+ _globals['_PULLMESSAGESRESPONSE']._serialized_start=769
58
+ _globals['_PULLMESSAGESRESPONSE']._serialized_end=931
59
+ _globals['_PUSHMESSAGESREQUEST']._serialized_start=934
60
+ _globals['_PUSHMESSAGESREQUEST']._serialized_end=1085
61
+ _globals['_PUSHMESSAGESRESPONSE']._serialized_start=1088
62
+ _globals['_PUSHMESSAGESRESPONSE']._serialized_end=1289
63
+ _globals['_PUSHMESSAGESRESPONSE_RESULTSENTRY']._serialized_start=1243
64
+ _globals['_PUSHMESSAGESRESPONSE_RESULTSENTRY']._serialized_end=1289
65
+ _globals['_RECONNECT']._serialized_start=1291
66
+ _globals['_RECONNECT']._serialized_end=1321
67
+ _globals['_FLEET']._serialized_start=1324
68
+ _globals['_FLEET']._serialized_end=2538
53
69
  # @@protoc_insertion_point(module_scope)
flwr/proto/fleet_pb2.pyi CHANGED
@@ -61,6 +61,86 @@ class DeleteNodeResponse(google.protobuf.message.Message):
61
61
  ) -> None: ...
62
62
  global___DeleteNodeResponse = DeleteNodeResponse
63
63
 
64
+ class RegisterNodeFleetRequest(google.protobuf.message.Message):
65
+ """RegisterNode messages (add prefix to avoid name clash)"""
66
+ DESCRIPTOR: google.protobuf.descriptor.Descriptor
67
+ PUBLIC_KEY_FIELD_NUMBER: builtins.int
68
+ public_key: builtins.bytes
69
+ def __init__(self,
70
+ *,
71
+ public_key: builtins.bytes = ...,
72
+ ) -> None: ...
73
+ def ClearField(self, field_name: typing_extensions.Literal["public_key",b"public_key"]) -> None: ...
74
+ global___RegisterNodeFleetRequest = RegisterNodeFleetRequest
75
+
76
+ class RegisterNodeFleetResponse(google.protobuf.message.Message):
77
+ DESCRIPTOR: google.protobuf.descriptor.Descriptor
78
+ def __init__(self,
79
+ ) -> None: ...
80
+ global___RegisterNodeFleetResponse = RegisterNodeFleetResponse
81
+
82
+ class ActivateNodeRequest(google.protobuf.message.Message):
83
+ """ActivateNode messages"""
84
+ DESCRIPTOR: google.protobuf.descriptor.Descriptor
85
+ PUBLIC_KEY_FIELD_NUMBER: builtins.int
86
+ HEARTBEAT_INTERVAL_FIELD_NUMBER: builtins.int
87
+ public_key: builtins.bytes
88
+ heartbeat_interval: builtins.float
89
+ def __init__(self,
90
+ *,
91
+ public_key: builtins.bytes = ...,
92
+ heartbeat_interval: builtins.float = ...,
93
+ ) -> None: ...
94
+ def ClearField(self, field_name: typing_extensions.Literal["heartbeat_interval",b"heartbeat_interval","public_key",b"public_key"]) -> None: ...
95
+ global___ActivateNodeRequest = ActivateNodeRequest
96
+
97
+ class ActivateNodeResponse(google.protobuf.message.Message):
98
+ DESCRIPTOR: google.protobuf.descriptor.Descriptor
99
+ NODE_ID_FIELD_NUMBER: builtins.int
100
+ node_id: builtins.int
101
+ def __init__(self,
102
+ *,
103
+ node_id: builtins.int = ...,
104
+ ) -> None: ...
105
+ def ClearField(self, field_name: typing_extensions.Literal["node_id",b"node_id"]) -> None: ...
106
+ global___ActivateNodeResponse = ActivateNodeResponse
107
+
108
+ class DeactivateNodeRequest(google.protobuf.message.Message):
109
+ """DeactivateNode messages"""
110
+ DESCRIPTOR: google.protobuf.descriptor.Descriptor
111
+ NODE_ID_FIELD_NUMBER: builtins.int
112
+ node_id: builtins.int
113
+ def __init__(self,
114
+ *,
115
+ node_id: builtins.int = ...,
116
+ ) -> None: ...
117
+ def ClearField(self, field_name: typing_extensions.Literal["node_id",b"node_id"]) -> None: ...
118
+ global___DeactivateNodeRequest = DeactivateNodeRequest
119
+
120
+ class DeactivateNodeResponse(google.protobuf.message.Message):
121
+ DESCRIPTOR: google.protobuf.descriptor.Descriptor
122
+ def __init__(self,
123
+ ) -> None: ...
124
+ global___DeactivateNodeResponse = DeactivateNodeResponse
125
+
126
+ class UnregisterNodeFleetRequest(google.protobuf.message.Message):
127
+ """UnregisterNode messages (add prefix to avoid name clash)"""
128
+ DESCRIPTOR: google.protobuf.descriptor.Descriptor
129
+ NODE_ID_FIELD_NUMBER: builtins.int
130
+ node_id: builtins.int
131
+ def __init__(self,
132
+ *,
133
+ node_id: builtins.int = ...,
134
+ ) -> None: ...
135
+ def ClearField(self, field_name: typing_extensions.Literal["node_id",b"node_id"]) -> None: ...
136
+ global___UnregisterNodeFleetRequest = UnregisterNodeFleetRequest
137
+
138
+ class UnregisterNodeFleetResponse(google.protobuf.message.Message):
139
+ DESCRIPTOR: google.protobuf.descriptor.Descriptor
140
+ def __init__(self,
141
+ ) -> None: ...
142
+ global___UnregisterNodeFleetResponse = UnregisterNodeFleetResponse
143
+
64
144
  class PullMessagesRequest(google.protobuf.message.Message):
65
145
  """PullMessages messages"""
66
146
  DESCRIPTOR: google.protobuf.descriptor.Descriptor