flwr-nightly 1.10.0.dev20240707__py3-none-any.whl → 1.11.0.dev20240724__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.

Files changed (99) hide show
  1. flwr/cli/build.py +16 -2
  2. flwr/cli/config_utils.py +47 -27
  3. flwr/cli/install.py +17 -1
  4. flwr/cli/new/new.py +32 -21
  5. flwr/cli/new/templates/app/code/{client.hf.py.tpl → client.huggingface.py.tpl} +15 -5
  6. flwr/cli/new/templates/app/code/client.jax.py.tpl +2 -1
  7. flwr/cli/new/templates/app/code/client.mlx.py.tpl +36 -13
  8. flwr/cli/new/templates/app/code/client.numpy.py.tpl +2 -1
  9. flwr/cli/new/templates/app/code/client.pytorch.py.tpl +16 -5
  10. flwr/cli/new/templates/app/code/client.sklearn.py.tpl +6 -3
  11. flwr/cli/new/templates/app/code/client.tensorflow.py.tpl +25 -5
  12. flwr/cli/new/templates/app/code/flwr_tune/app.py.tpl +22 -19
  13. flwr/cli/new/templates/app/code/flwr_tune/client.py.tpl +5 -3
  14. flwr/cli/new/templates/app/code/flwr_tune/server.py.tpl +1 -1
  15. flwr/cli/new/templates/app/code/server.huggingface.py.tpl +23 -0
  16. flwr/cli/new/templates/app/code/server.jax.py.tpl +16 -8
  17. flwr/cli/new/templates/app/code/server.mlx.py.tpl +12 -7
  18. flwr/cli/new/templates/app/code/server.numpy.py.tpl +16 -8
  19. flwr/cli/new/templates/app/code/server.pytorch.py.tpl +15 -13
  20. flwr/cli/new/templates/app/code/server.sklearn.py.tpl +17 -10
  21. flwr/cli/new/templates/app/code/server.tensorflow.py.tpl +16 -13
  22. flwr/cli/new/templates/app/code/{task.hf.py.tpl → task.huggingface.py.tpl} +14 -2
  23. flwr/cli/new/templates/app/code/task.mlx.py.tpl +14 -2
  24. flwr/cli/new/templates/app/code/task.pytorch.py.tpl +14 -3
  25. flwr/cli/new/templates/app/code/task.tensorflow.py.tpl +13 -1
  26. flwr/cli/new/templates/app/pyproject.flowertune.toml.tpl +9 -12
  27. flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl +38 -0
  28. flwr/cli/new/templates/app/pyproject.jax.toml.tpl +17 -11
  29. flwr/cli/new/templates/app/pyproject.mlx.toml.tpl +17 -12
  30. flwr/cli/new/templates/app/pyproject.numpy.toml.tpl +12 -12
  31. flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl +13 -12
  32. flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl +12 -12
  33. flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl +15 -12
  34. flwr/cli/run/run.py +133 -54
  35. flwr/client/app.py +56 -24
  36. flwr/client/client_app.py +28 -8
  37. flwr/client/grpc_adapter_client/connection.py +3 -2
  38. flwr/client/grpc_client/connection.py +3 -2
  39. flwr/client/grpc_rere_client/connection.py +17 -6
  40. flwr/client/message_handler/message_handler.py +1 -1
  41. flwr/client/node_state.py +59 -12
  42. flwr/client/node_state_tests.py +4 -3
  43. flwr/client/rest_client/connection.py +19 -8
  44. flwr/client/supernode/app.py +39 -39
  45. flwr/client/typing.py +2 -2
  46. flwr/common/config.py +92 -2
  47. flwr/common/constant.py +3 -0
  48. flwr/common/context.py +24 -9
  49. flwr/common/logger.py +25 -0
  50. flwr/common/object_ref.py +84 -21
  51. flwr/common/serde.py +45 -0
  52. flwr/common/telemetry.py +17 -0
  53. flwr/common/typing.py +5 -0
  54. flwr/proto/common_pb2.py +36 -0
  55. flwr/proto/common_pb2.pyi +121 -0
  56. flwr/proto/common_pb2_grpc.py +4 -0
  57. flwr/proto/common_pb2_grpc.pyi +4 -0
  58. flwr/proto/driver_pb2.py +24 -19
  59. flwr/proto/driver_pb2.pyi +21 -1
  60. flwr/proto/exec_pb2.py +20 -11
  61. flwr/proto/exec_pb2.pyi +41 -1
  62. flwr/proto/run_pb2.py +12 -7
  63. flwr/proto/run_pb2.pyi +22 -1
  64. flwr/proto/task_pb2.py +7 -8
  65. flwr/server/__init__.py +2 -0
  66. flwr/server/compat/legacy_context.py +5 -4
  67. flwr/server/driver/grpc_driver.py +82 -140
  68. flwr/server/run_serverapp.py +40 -18
  69. flwr/server/server_app.py +56 -10
  70. flwr/server/serverapp_components.py +52 -0
  71. flwr/server/superlink/driver/driver_servicer.py +18 -3
  72. flwr/server/superlink/fleet/message_handler/message_handler.py +13 -2
  73. flwr/server/superlink/fleet/vce/backend/__init__.py +1 -1
  74. flwr/server/superlink/fleet/vce/backend/backend.py +4 -4
  75. flwr/server/superlink/fleet/vce/backend/raybackend.py +10 -10
  76. flwr/server/superlink/fleet/vce/vce_api.py +149 -117
  77. flwr/server/superlink/state/in_memory_state.py +11 -3
  78. flwr/server/superlink/state/sqlite_state.py +23 -8
  79. flwr/server/superlink/state/state.py +7 -2
  80. flwr/server/typing.py +2 -0
  81. flwr/server/workflow/secure_aggregation/secaggplus_workflow.py +18 -2
  82. flwr/simulation/__init__.py +1 -1
  83. flwr/simulation/app.py +4 -3
  84. flwr/simulation/ray_transport/ray_actor.py +15 -19
  85. flwr/simulation/ray_transport/ray_client_proxy.py +22 -9
  86. flwr/simulation/run_simulation.py +269 -70
  87. flwr/superexec/app.py +17 -11
  88. flwr/superexec/deployment.py +111 -35
  89. flwr/superexec/exec_grpc.py +5 -1
  90. flwr/superexec/exec_servicer.py +6 -1
  91. flwr/superexec/executor.py +21 -0
  92. flwr/superexec/simulation.py +181 -0
  93. {flwr_nightly-1.10.0.dev20240707.dist-info → flwr_nightly-1.11.0.dev20240724.dist-info}/METADATA +3 -2
  94. {flwr_nightly-1.10.0.dev20240707.dist-info → flwr_nightly-1.11.0.dev20240724.dist-info}/RECORD +97 -91
  95. flwr/cli/new/templates/app/code/server.hf.py.tpl +0 -17
  96. flwr/cli/new/templates/app/pyproject.hf.toml.tpl +0 -37
  97. {flwr_nightly-1.10.0.dev20240707.dist-info → flwr_nightly-1.11.0.dev20240724.dist-info}/LICENSE +0 -0
  98. {flwr_nightly-1.10.0.dev20240707.dist-info → flwr_nightly-1.11.0.dev20240724.dist-info}/WHEEL +0 -0
  99. {flwr_nightly-1.10.0.dev20240707.dist-info → flwr_nightly-1.11.0.dev20240724.dist-info}/entry_points.txt +0 -0
@@ -15,8 +15,8 @@
15
15
  """Deployment engine executor."""
16
16
 
17
17
  import subprocess
18
- import sys
19
18
  from logging import ERROR, INFO
19
+ from pathlib import Path
20
20
  from typing import Optional
21
21
 
22
22
  from typing_extensions import override
@@ -25,6 +25,8 @@ from flwr.cli.config_utils import get_fab_metadata
25
25
  from flwr.cli.install import install_from_fab
26
26
  from flwr.common.grpc import create_channel
27
27
  from flwr.common.logger import log
28
+ from flwr.common.serde import user_config_to_proto
29
+ from flwr.common.typing import UserConfig
28
30
  from flwr.proto.driver_pb2 import CreateRunRequest # pylint: disable=E0611
29
31
  from flwr.proto.driver_pb2_grpc import DriverStub
30
32
  from flwr.server.driver.grpc_driver import DEFAULT_SERVER_ADDRESS_DRIVER
@@ -33,65 +35,139 @@ from .executor import Executor, RunTracker
33
35
 
34
36
 
35
37
  class DeploymentEngine(Executor):
36
- """Deployment engine executor."""
38
+ """Deployment engine executor.
39
+
40
+ Parameters
41
+ ----------
42
+ superlink: str (default: "0.0.0.0:9091")
43
+ Address of the SuperLink to connect to.
44
+ root_certificates: Optional[str] (default: None)
45
+ Specifies the path to the PEM-encoded root certificate file for
46
+ establishing secure HTTPS connections.
47
+ flwr_dir: Optional[str] (default: None)
48
+ The path containing installed Flower Apps.
49
+ """
37
50
 
38
51
  def __init__(
39
52
  self,
40
- address: str = DEFAULT_SERVER_ADDRESS_DRIVER,
41
- root_certificates: Optional[bytes] = None,
53
+ superlink: str = DEFAULT_SERVER_ADDRESS_DRIVER,
54
+ root_certificates: Optional[str] = None,
55
+ flwr_dir: Optional[str] = None,
42
56
  ) -> None:
43
- self.address = address
44
- self.root_certificates = root_certificates
57
+ self.superlink = superlink
58
+ if root_certificates is None:
59
+ self.root_certificates = None
60
+ self.root_certificates_bytes = None
61
+ else:
62
+ self.root_certificates = root_certificates
63
+ self.root_certificates_bytes = Path(root_certificates).read_bytes()
64
+ self.flwr_dir = flwr_dir
45
65
  self.stub: Optional[DriverStub] = None
46
66
 
47
- def _connect(self) -> None:
48
- if self.stub is None:
49
- channel = create_channel(
50
- server_address=self.address,
51
- insecure=(self.root_certificates is None),
52
- root_certificates=self.root_certificates,
53
- )
54
- self.stub = DriverStub(channel)
67
+ @override
68
+ def set_config(
69
+ self,
70
+ config: UserConfig,
71
+ ) -> None:
72
+ """Set executor config arguments.
73
+
74
+ Parameters
75
+ ----------
76
+ config : UserConfig
77
+ A dictionary for configuration values.
78
+ Supported configuration key/value pairs:
79
+ - "superlink": str
80
+ The address of the SuperLink Driver API.
81
+ - "root-certificates": str
82
+ The path to the root certificates.
83
+ - "flwr-dir": str
84
+ The path to the Flower directory.
85
+ """
86
+ if not config:
87
+ return
88
+ if superlink_address := config.get("superlink"):
89
+ if not isinstance(superlink_address, str):
90
+ raise ValueError("The `superlink` value should be of type `str`.")
91
+ self.superlink = superlink_address
92
+ if root_certificates := config.get("root-certificates"):
93
+ if not isinstance(root_certificates, str):
94
+ raise ValueError(
95
+ "The `root-certificates` value should be of type `str`."
96
+ )
97
+ self.root_certificates = root_certificates
98
+ self.root_certificates_bytes = Path(str(root_certificates)).read_bytes()
99
+ if flwr_dir := config.get("flwr-dir"):
100
+ if not isinstance(flwr_dir, str):
101
+ raise ValueError("The `flwr-dir` value should be of type `str`.")
102
+ self.flwr_dir = str(flwr_dir)
55
103
 
56
- def _create_run(self, fab_id: str, fab_version: str) -> int:
104
+ def _connect(self) -> None:
105
+ if self.stub is not None:
106
+ return
107
+ channel = create_channel(
108
+ server_address=self.superlink,
109
+ insecure=(self.root_certificates_bytes is None),
110
+ root_certificates=self.root_certificates_bytes,
111
+ )
112
+ self.stub = DriverStub(channel)
113
+
114
+ def _create_run(
115
+ self,
116
+ fab_id: str,
117
+ fab_version: str,
118
+ override_config: UserConfig,
119
+ ) -> int:
57
120
  if self.stub is None:
58
121
  self._connect()
59
122
 
60
123
  assert self.stub is not None
61
124
 
62
- req = CreateRunRequest(fab_id=fab_id, fab_version=fab_version)
125
+ req = CreateRunRequest(
126
+ fab_id=fab_id,
127
+ fab_version=fab_version,
128
+ override_config=user_config_to_proto(override_config),
129
+ )
63
130
  res = self.stub.CreateRun(request=req)
64
131
  return int(res.run_id)
65
132
 
66
133
  @override
67
- def start_run(self, fab_file: bytes) -> Optional[RunTracker]:
134
+ def start_run(
135
+ self,
136
+ fab_file: bytes,
137
+ override_config: UserConfig,
138
+ federation_config: UserConfig,
139
+ ) -> Optional[RunTracker]:
68
140
  """Start run using the Flower Deployment Engine."""
69
141
  try:
70
142
  # Install FAB to flwr dir
71
143
  fab_version, fab_id = get_fab_metadata(fab_file)
72
- fab_path = install_from_fab(fab_file, None, True)
73
-
74
- # Install FAB Python package
75
- subprocess.check_call(
76
- [sys.executable, "-m", "pip", "install", str(fab_path)],
77
- stdout=subprocess.DEVNULL,
78
- stderr=subprocess.DEVNULL,
79
- )
144
+ install_from_fab(fab_file, None, True)
80
145
 
81
146
  # Call SuperLink to create run
82
- run_id: int = self._create_run(fab_id, fab_version)
147
+ run_id: int = self._create_run(fab_id, fab_version, override_config)
83
148
  log(INFO, "Created run %s", str(run_id))
84
149
 
85
- # Start ServerApp
150
+ command = [
151
+ "flower-server-app",
152
+ "--run-id",
153
+ str(run_id),
154
+ "--superlink",
155
+ str(self.superlink),
156
+ ]
157
+
158
+ if self.flwr_dir:
159
+ command.append("--flwr-dir")
160
+ command.append(self.flwr_dir)
161
+
162
+ if self.root_certificates is None:
163
+ command.append("--insecure")
164
+ else:
165
+ command.append("--root-certificates")
166
+ command.append(self.root_certificates)
167
+
168
+ # Execute the command
86
169
  proc = subprocess.Popen( # pylint: disable=consider-using-with
87
- [
88
- "flower-server-app",
89
- "--run-id",
90
- str(run_id),
91
- "--insecure",
92
- ],
93
- stdout=subprocess.PIPE,
94
- stderr=subprocess.PIPE,
170
+ command,
95
171
  text=True,
96
172
  )
97
173
  log(INFO, "Started run %s", str(run_id))
@@ -21,6 +21,7 @@ import grpc
21
21
 
22
22
  from flwr.common import GRPC_MAX_MESSAGE_LENGTH
23
23
  from flwr.common.logger import log
24
+ from flwr.common.typing import UserConfig
24
25
  from flwr.proto.exec_pb2_grpc import add_ExecServicer_to_server
25
26
  from flwr.server.superlink.fleet.grpc_bidi.grpc_server import generic_create_grpc_server
26
27
 
@@ -32,8 +33,11 @@ def run_superexec_api_grpc(
32
33
  address: str,
33
34
  executor: Executor,
34
35
  certificates: Optional[Tuple[bytes, bytes, bytes]],
36
+ config: UserConfig,
35
37
  ) -> grpc.Server:
36
38
  """Run SuperExec API (gRPC, request-response)."""
39
+ executor.set_config(config)
40
+
37
41
  exec_servicer: grpc.Server = ExecServicer(
38
42
  executor=executor,
39
43
  )
@@ -45,7 +49,7 @@ def run_superexec_api_grpc(
45
49
  certificates=certificates,
46
50
  )
47
51
 
48
- log(INFO, "Flower ECE: Starting SuperExec API (gRPC-rere) on %s", address)
52
+ log(INFO, "Starting Flower SuperExec gRPC server on %s", address)
49
53
  superexec_grpc_server.start()
50
54
 
51
55
  return superexec_grpc_server
@@ -21,6 +21,7 @@ from typing import Any, Dict, Generator
21
21
  import grpc
22
22
 
23
23
  from flwr.common.logger import log
24
+ from flwr.common.serde import user_config_from_proto
24
25
  from flwr.proto import exec_pb2_grpc # pylint: disable=E0611
25
26
  from flwr.proto.exec_pb2 import ( # pylint: disable=E0611
26
27
  StartRunRequest,
@@ -45,7 +46,11 @@ class ExecServicer(exec_pb2_grpc.ExecServicer):
45
46
  """Create run ID."""
46
47
  log(INFO, "ExecServicer.StartRun")
47
48
 
48
- run = self.executor.start_run(request.fab_file)
49
+ run = self.executor.start_run(
50
+ request.fab_file,
51
+ user_config_from_proto(request.override_config),
52
+ user_config_from_proto(request.federation_config),
53
+ )
49
54
 
50
55
  if run is None:
51
56
  log(ERROR, "Executor failed to start run")
@@ -19,6 +19,8 @@ from dataclasses import dataclass
19
19
  from subprocess import Popen
20
20
  from typing import Optional
21
21
 
22
+ from flwr.common.typing import UserConfig
23
+
22
24
 
23
25
  @dataclass
24
26
  class RunTracker:
@@ -31,10 +33,25 @@ class RunTracker:
31
33
  class Executor(ABC):
32
34
  """Execute and monitor a Flower run."""
33
35
 
36
+ @abstractmethod
37
+ def set_config(
38
+ self,
39
+ config: UserConfig,
40
+ ) -> None:
41
+ """Register provided config as class attributes.
42
+
43
+ Parameters
44
+ ----------
45
+ config : UserConfig
46
+ A dictionary for configuration values.
47
+ """
48
+
34
49
  @abstractmethod
35
50
  def start_run(
36
51
  self,
37
52
  fab_file: bytes,
53
+ override_config: UserConfig,
54
+ federation_config: UserConfig,
38
55
  ) -> Optional[RunTracker]:
39
56
  """Start a run using the given Flower FAB ID and version.
40
57
 
@@ -45,6 +62,10 @@ class Executor(ABC):
45
62
  ----------
46
63
  fab_file : bytes
47
64
  The Flower App Bundle file bytes.
65
+ override_config: UserConfig
66
+ The config overrides dict sent by the user (using `flwr run`).
67
+ federation_config: UserConfig
68
+ The federation options dict sent by the user (using `flwr run`).
48
69
 
49
70
  Returns
50
71
  -------
@@ -0,0 +1,181 @@
1
+ # Copyright 2024 Flower Labs GmbH. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # ==============================================================================
15
+ """Simulation engine executor."""
16
+
17
+
18
+ import subprocess
19
+ import sys
20
+ from logging import ERROR, INFO, WARN
21
+ from typing import Optional
22
+
23
+ from typing_extensions import override
24
+
25
+ from flwr.cli.config_utils import load_and_validate
26
+ from flwr.cli.install import install_from_fab
27
+ from flwr.common.constant import RUN_ID_NUM_BYTES
28
+ from flwr.common.logger import log
29
+ from flwr.common.typing import UserConfig
30
+ from flwr.server.superlink.state.utils import generate_rand_int_from_bytes
31
+
32
+ from .executor import Executor, RunTracker
33
+
34
+
35
+ def _user_config_to_str(user_config: UserConfig) -> str:
36
+ """Convert override user config to string."""
37
+ user_config_list_str = []
38
+ for key, value in user_config.items():
39
+ if isinstance(value, bool):
40
+ user_config_list_str.append(f"{key}={str(value).lower()}")
41
+ elif isinstance(value, (int, float)):
42
+ user_config_list_str.append(f"{key}={value}")
43
+ elif isinstance(value, str):
44
+ user_config_list_str.append(f'{key}="{value}"')
45
+ else:
46
+ raise ValueError(
47
+ "Only types `bool`, `float`, `int` and `str` are supported"
48
+ )
49
+
50
+ user_config_str = ",".join(user_config_list_str)
51
+ return user_config_str
52
+
53
+
54
+ class SimulationEngine(Executor):
55
+ """Simulation engine executor.
56
+
57
+ Parameters
58
+ ----------
59
+ num_supernodes: Opitonal[str] (default: None)
60
+ Total number of nodes to involve in the simulation.
61
+ """
62
+
63
+ def __init__(
64
+ self,
65
+ num_supernodes: Optional[int] = None,
66
+ ) -> None:
67
+ self.num_supernodes = num_supernodes
68
+
69
+ @override
70
+ def set_config(
71
+ self,
72
+ config: UserConfig,
73
+ ) -> None:
74
+ """Set executor config arguments.
75
+
76
+ Parameters
77
+ ----------
78
+ config : UserConfig
79
+ A dictionary for configuration values.
80
+ Supported configuration key/value pairs:
81
+ - "num-supernodes": int
82
+ Number of nodes to register for the simulation.
83
+ """
84
+ if num_supernodes := config.get("num-supernodes"):
85
+ if not isinstance(num_supernodes, int):
86
+ raise ValueError("The `num-supernodes` value should be of type `int`.")
87
+ self.num_supernodes = num_supernodes
88
+ elif self.num_supernodes is None:
89
+ log(
90
+ ERROR,
91
+ "To start a run with the simulation plugin, please specify "
92
+ "the number of SuperNodes. This can be done by using the "
93
+ "`--executor-config` argument when launching the SuperExec.",
94
+ )
95
+ raise ValueError(
96
+ "`num-supernodes` must not be `None`, it must be a valid "
97
+ "positive integer."
98
+ )
99
+
100
+ @override
101
+ def start_run(
102
+ self,
103
+ fab_file: bytes,
104
+ override_config: UserConfig,
105
+ federation_config: UserConfig,
106
+ ) -> Optional[RunTracker]:
107
+ """Start run using the Flower Simulation Engine."""
108
+ if self.num_supernodes is None:
109
+ raise ValueError(
110
+ "Error in `SuperExec` (`SimulationEngine` executor):\n\n"
111
+ "`num-supernodes` must not be `None`, it must be a valid "
112
+ "positive integer. In order to start this simulation executor "
113
+ "with a specified number of `SuperNodes`, you can either provide "
114
+ "a `--executor` that has been initialized with a number of nodes "
115
+ "to the `flower-superexec` CLI, or `--executor-config num-supernodes=N`"
116
+ "to the `flower-superexec` CLI."
117
+ )
118
+ try:
119
+
120
+ # Install FAB to flwr dir
121
+ fab_path = install_from_fab(fab_file, None, True)
122
+
123
+ # Install FAB Python package
124
+ subprocess.check_call(
125
+ [sys.executable, "-m", "pip", "install", "--no-deps", str(fab_path)],
126
+ stdout=subprocess.DEVNULL,
127
+ stderr=subprocess.DEVNULL,
128
+ )
129
+
130
+ # Load and validate config
131
+ config, errors, warnings = load_and_validate(fab_path / "pyproject.toml")
132
+ if errors:
133
+ raise ValueError(errors)
134
+
135
+ if warnings:
136
+ log(WARN, warnings)
137
+
138
+ if config is None:
139
+ raise ValueError(
140
+ "Config extracted from FAB's pyproject.toml is not valid"
141
+ )
142
+
143
+ # In Simulation there is no SuperLink, still we create a run_id
144
+ run_id = generate_rand_int_from_bytes(RUN_ID_NUM_BYTES)
145
+ log(INFO, "Created run %s", str(run_id))
146
+
147
+ # Prepare commnand
148
+ command = [
149
+ "flower-simulation",
150
+ "--app",
151
+ f"{str(fab_path)}",
152
+ "--num-supernodes",
153
+ f"{federation_config.get('num-supernodes', self.num_supernodes)}",
154
+ "--run-id",
155
+ str(run_id),
156
+ ]
157
+
158
+ if override_config:
159
+ override_config_str = _user_config_to_str(override_config)
160
+ command.extend(["--run-config", f"{override_config_str}"])
161
+
162
+ # Start Simulation
163
+ proc = subprocess.Popen( # pylint: disable=consider-using-with
164
+ command,
165
+ text=True,
166
+ )
167
+
168
+ log(INFO, "Started run %s", str(run_id))
169
+
170
+ return RunTracker(
171
+ run_id=run_id,
172
+ proc=proc,
173
+ )
174
+
175
+ # pylint: disable-next=broad-except
176
+ except Exception as e:
177
+ log(ERROR, "Could not start run: %s", str(e))
178
+ return None
179
+
180
+
181
+ executor = SimulationEngine()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: flwr-nightly
3
- Version: 1.10.0.dev20240707
3
+ Version: 1.11.0.dev20240724
4
4
  Summary: Flower: A Friendly Federated Learning Framework
5
5
  Home-page: https://flower.ai
6
6
  License: Apache-2.0
@@ -33,7 +33,7 @@ Classifier: Typing :: Typed
33
33
  Provides-Extra: rest
34
34
  Provides-Extra: simulation
35
35
  Requires-Dist: cryptography (>=42.0.4,<43.0.0)
36
- Requires-Dist: grpcio (>=1.60.0,<2.0.0)
36
+ Requires-Dist: grpcio (>=1.60.0,<2.0.0,!=1.64.2,!=1.65.1)
37
37
  Requires-Dist: iterators (>=0.0.2,<0.0.3)
38
38
  Requires-Dist: numpy (>=1.21.0,<2.0.0)
39
39
  Requires-Dist: pathspec (>=0.12.1,<0.13.0)
@@ -43,6 +43,7 @@ Requires-Dist: ray (==2.10.0) ; (python_version >= "3.8" and python_version < "3
43
43
  Requires-Dist: requests (>=2.31.0,<3.0.0) ; extra == "rest"
44
44
  Requires-Dist: starlette (>=0.31.0,<0.32.0) ; extra == "rest"
45
45
  Requires-Dist: tomli (>=2.0.1,<3.0.0)
46
+ Requires-Dist: tomli-w (>=1.0.0,<2.0.0)
46
47
  Requires-Dist: typer[all] (>=0.9.0,<0.10.0)
47
48
  Requires-Dist: uvicorn[standard] (>=0.23.0,<0.24.0) ; extra == "rest"
48
49
  Project-URL: Documentation, https://flower.ai