flwr-nightly 1.11.0.dev20240827__py3-none-any.whl → 1.11.0.dev20240829__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/new/new.py +19 -0
- flwr/cli/new/templates/app/LICENSE.tpl +202 -0
- flwr/cli/new/templates/app/README.baseline.md.tpl +127 -0
- flwr/cli/new/templates/app/code/__init__.baseline.py.tpl +1 -0
- flwr/cli/new/templates/app/code/client.baseline.py.tpl +58 -0
- flwr/cli/new/templates/app/code/dataset.baseline.py.tpl +36 -0
- flwr/cli/new/templates/app/code/model.baseline.py.tpl +80 -0
- flwr/cli/new/templates/app/code/server.baseline.py.tpl +46 -0
- flwr/cli/new/templates/app/code/strategy.baseline.py.tpl +1 -0
- flwr/cli/new/templates/app/code/utils.baseline.py.tpl +1 -0
- flwr/cli/new/templates/app/pyproject.baseline.toml.tpl +138 -0
- flwr/client/__init__.py +0 -4
- flwr/client/grpc_rere_client/client_interceptor.py +13 -4
- flwr/client/supernode/app.py +3 -1
- flwr/common/config.py +14 -11
- flwr/common/telemetry.py +36 -30
- flwr/server/__init__.py +0 -4
- flwr/server/compat/app.py +0 -5
- flwr/server/driver/grpc_driver.py +1 -3
- flwr/simulation/run_simulation.py +23 -6
- flwr/superexec/__init__.py +0 -6
- {flwr_nightly-1.11.0.dev20240827.dist-info → flwr_nightly-1.11.0.dev20240829.dist-info}/METADATA +1 -1
- {flwr_nightly-1.11.0.dev20240827.dist-info → flwr_nightly-1.11.0.dev20240829.dist-info}/RECORD +26 -16
- flwr_nightly-1.11.0.dev20240829.dist-info/entry_points.txt +10 -0
- flwr_nightly-1.11.0.dev20240827.dist-info/entry_points.txt +0 -10
- {flwr_nightly-1.11.0.dev20240827.dist-info → flwr_nightly-1.11.0.dev20240829.dist-info}/LICENSE +0 -0
- {flwr_nightly-1.11.0.dev20240827.dist-info → flwr_nightly-1.11.0.dev20240829.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "$package_name"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = ""
|
|
9
|
+
license = "Apache-2.0"
|
|
10
|
+
dependencies = [
|
|
11
|
+
"flwr[simulation]>=1.11.0",
|
|
12
|
+
"flwr-datasets[vision]>=0.3.0",
|
|
13
|
+
"torch==2.2.1",
|
|
14
|
+
"torchvision==0.17.1",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
[tool.hatch.metadata]
|
|
18
|
+
allow-direct-references = true
|
|
19
|
+
|
|
20
|
+
[project.optional-dependencies]
|
|
21
|
+
dev = [
|
|
22
|
+
"isort==5.13.2",
|
|
23
|
+
"black==24.2.0",
|
|
24
|
+
"docformatter==1.7.5",
|
|
25
|
+
"mypy==1.8.0",
|
|
26
|
+
"pylint==3.2.6",
|
|
27
|
+
"flake8==5.0.4",
|
|
28
|
+
"pytest==6.2.4",
|
|
29
|
+
"pytest-watch==4.2.0",
|
|
30
|
+
"ruff==0.1.9",
|
|
31
|
+
"types-requests==2.31.0.20240125",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
[tool.isort]
|
|
35
|
+
profile = "black"
|
|
36
|
+
known_first_party = ["flwr"]
|
|
37
|
+
|
|
38
|
+
[tool.black]
|
|
39
|
+
line-length = 88
|
|
40
|
+
target-version = ["py38", "py39", "py310", "py311"]
|
|
41
|
+
|
|
42
|
+
[tool.pytest.ini_options]
|
|
43
|
+
minversion = "6.2"
|
|
44
|
+
addopts = "-qq"
|
|
45
|
+
testpaths = [
|
|
46
|
+
"flwr_baselines",
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
[tool.mypy]
|
|
50
|
+
ignore_missing_imports = true
|
|
51
|
+
strict = false
|
|
52
|
+
plugins = "numpy.typing.mypy_plugin"
|
|
53
|
+
|
|
54
|
+
[tool.pylint."MESSAGES CONTROL"]
|
|
55
|
+
disable = "duplicate-code,too-few-public-methods,useless-import-alias"
|
|
56
|
+
good-names = "i,j,k,_,x,y,X,Y,K,N"
|
|
57
|
+
max-args = 10
|
|
58
|
+
max-attributes = 15
|
|
59
|
+
max-locals = 36
|
|
60
|
+
max-branches = 20
|
|
61
|
+
max-statements = 55
|
|
62
|
+
|
|
63
|
+
[tool.pylint.typecheck]
|
|
64
|
+
generated-members = "numpy.*, torch.*, tensorflow.*"
|
|
65
|
+
|
|
66
|
+
[[tool.mypy.overrides]]
|
|
67
|
+
module = [
|
|
68
|
+
"importlib.metadata.*",
|
|
69
|
+
"importlib_metadata.*",
|
|
70
|
+
]
|
|
71
|
+
follow_imports = "skip"
|
|
72
|
+
follow_imports_for_stubs = true
|
|
73
|
+
disallow_untyped_calls = false
|
|
74
|
+
|
|
75
|
+
[[tool.mypy.overrides]]
|
|
76
|
+
module = "torch.*"
|
|
77
|
+
follow_imports = "skip"
|
|
78
|
+
follow_imports_for_stubs = true
|
|
79
|
+
|
|
80
|
+
[tool.docformatter]
|
|
81
|
+
wrap-summaries = 88
|
|
82
|
+
wrap-descriptions = 88
|
|
83
|
+
|
|
84
|
+
[tool.ruff]
|
|
85
|
+
target-version = "py38"
|
|
86
|
+
line-length = 88
|
|
87
|
+
select = ["D", "E", "F", "W", "B", "ISC", "C4"]
|
|
88
|
+
fixable = ["D", "E", "F", "W", "B", "ISC", "C4"]
|
|
89
|
+
ignore = ["B024", "B027"]
|
|
90
|
+
exclude = [
|
|
91
|
+
".bzr",
|
|
92
|
+
".direnv",
|
|
93
|
+
".eggs",
|
|
94
|
+
".git",
|
|
95
|
+
".hg",
|
|
96
|
+
".mypy_cache",
|
|
97
|
+
".nox",
|
|
98
|
+
".pants.d",
|
|
99
|
+
".pytype",
|
|
100
|
+
".ruff_cache",
|
|
101
|
+
".svn",
|
|
102
|
+
".tox",
|
|
103
|
+
".venv",
|
|
104
|
+
"__pypackages__",
|
|
105
|
+
"_build",
|
|
106
|
+
"buck-out",
|
|
107
|
+
"build",
|
|
108
|
+
"dist",
|
|
109
|
+
"node_modules",
|
|
110
|
+
"venv",
|
|
111
|
+
"proto",
|
|
112
|
+
]
|
|
113
|
+
|
|
114
|
+
[tool.ruff.pydocstyle]
|
|
115
|
+
convention = "numpy"
|
|
116
|
+
|
|
117
|
+
[tool.hatch.build.targets.wheel]
|
|
118
|
+
packages = ["."]
|
|
119
|
+
|
|
120
|
+
[tool.flwr.app]
|
|
121
|
+
publisher = "$username"
|
|
122
|
+
|
|
123
|
+
[tool.flwr.app.components]
|
|
124
|
+
serverapp = "$import_name.server_app:app"
|
|
125
|
+
clientapp = "$import_name.client_app:app"
|
|
126
|
+
|
|
127
|
+
[tool.flwr.app.config]
|
|
128
|
+
num-server-rounds = 3
|
|
129
|
+
fraction-fit = 0.5
|
|
130
|
+
local-epochs = 1
|
|
131
|
+
|
|
132
|
+
[tool.flwr.federations]
|
|
133
|
+
default = "local-simulation"
|
|
134
|
+
|
|
135
|
+
[tool.flwr.federations.local-simulation]
|
|
136
|
+
options.num-supernodes = 10
|
|
137
|
+
options.backend.client-resources.num-cpus = 2
|
|
138
|
+
options.backend.client-resources.num-gpus = 0.0
|
flwr/client/__init__.py
CHANGED
|
@@ -20,8 +20,6 @@ from .app import start_numpy_client as start_numpy_client
|
|
|
20
20
|
from .client import Client as Client
|
|
21
21
|
from .client_app import ClientApp as ClientApp
|
|
22
22
|
from .numpy_client import NumPyClient as NumPyClient
|
|
23
|
-
from .supernode import run_client_app as run_client_app
|
|
24
|
-
from .supernode import run_supernode as run_supernode
|
|
25
23
|
from .typing import ClientFn as ClientFn
|
|
26
24
|
from .typing import ClientFnExt as ClientFnExt
|
|
27
25
|
|
|
@@ -32,8 +30,6 @@ __all__ = [
|
|
|
32
30
|
"ClientFnExt",
|
|
33
31
|
"NumPyClient",
|
|
34
32
|
"mod",
|
|
35
|
-
"run_client_app",
|
|
36
|
-
"run_supernode",
|
|
37
33
|
"start_client",
|
|
38
34
|
"start_numpy_client",
|
|
39
35
|
]
|
|
@@ -17,11 +17,13 @@
|
|
|
17
17
|
|
|
18
18
|
import base64
|
|
19
19
|
import collections
|
|
20
|
+
from logging import WARNING
|
|
20
21
|
from typing import Any, Callable, Optional, Sequence, Tuple, Union
|
|
21
22
|
|
|
22
23
|
import grpc
|
|
23
24
|
from cryptography.hazmat.primitives.asymmetric import ec
|
|
24
25
|
|
|
26
|
+
from flwr.common.logger import log
|
|
25
27
|
from flwr.common.secure_aggregation.crypto.symmetric_encryption import (
|
|
26
28
|
bytes_to_public_key,
|
|
27
29
|
compute_hmac,
|
|
@@ -151,8 +153,15 @@ class AuthenticateClientInterceptor(grpc.UnaryUnaryClientInterceptor): # type:
|
|
|
151
153
|
server_public_key_bytes = base64.urlsafe_b64decode(
|
|
152
154
|
_get_value_from_tuples(_PUBLIC_KEY_HEADER, response.initial_metadata())
|
|
153
155
|
)
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
self.
|
|
157
|
-
|
|
156
|
+
|
|
157
|
+
if server_public_key_bytes != b"":
|
|
158
|
+
self.server_public_key = bytes_to_public_key(server_public_key_bytes)
|
|
159
|
+
else:
|
|
160
|
+
log(WARNING, "Can't get server public key, SuperLink may be offline")
|
|
161
|
+
|
|
162
|
+
if self.server_public_key is not None:
|
|
163
|
+
self.shared_secret = generate_shared_key(
|
|
164
|
+
self.private_key, self.server_public_key
|
|
165
|
+
)
|
|
166
|
+
|
|
158
167
|
return response
|
flwr/client/supernode/app.py
CHANGED
|
@@ -77,7 +77,9 @@ def run_supernode() -> None:
|
|
|
77
77
|
authentication_keys=authentication_keys,
|
|
78
78
|
max_retries=args.max_retries,
|
|
79
79
|
max_wait_time=args.max_wait_time,
|
|
80
|
-
node_config=parse_config_args(
|
|
80
|
+
node_config=parse_config_args(
|
|
81
|
+
[args.node_config] if args.node_config else args.node_config
|
|
82
|
+
),
|
|
81
83
|
isolation=args.isolation,
|
|
82
84
|
supernode_address=args.supernode_address,
|
|
83
85
|
)
|
flwr/common/config.py
CHANGED
|
@@ -185,23 +185,26 @@ def parse_config_args(
|
|
|
185
185
|
if config is None:
|
|
186
186
|
return overrides
|
|
187
187
|
|
|
188
|
+
# Handle if .toml file is passed
|
|
189
|
+
if len(config) == 1 and config[0].endswith(".toml"):
|
|
190
|
+
with Path(config[0]).open("rb") as config_file:
|
|
191
|
+
overrides = flatten_dict(tomli.load(config_file))
|
|
192
|
+
return overrides
|
|
193
|
+
|
|
188
194
|
# Regular expression to capture key-value pairs with possible quoted values
|
|
189
195
|
pattern = re.compile(r"(\S+?)=(\'[^\']*\'|\"[^\"]*\"|\S+)")
|
|
190
196
|
|
|
191
197
|
for config_line in config:
|
|
192
198
|
if config_line:
|
|
193
|
-
|
|
199
|
+
# .toml files aren't allowed alongside other configs
|
|
200
|
+
if config_line.endswith(".toml"):
|
|
201
|
+
raise ValueError(
|
|
202
|
+
"TOML files cannot be passed alongside key-value pairs."
|
|
203
|
+
)
|
|
194
204
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
and matches[0][0].endswith(".toml")
|
|
199
|
-
):
|
|
200
|
-
with Path(matches[0][0]).open("rb") as config_file:
|
|
201
|
-
overrides = flatten_dict(tomli.load(config_file))
|
|
202
|
-
else:
|
|
203
|
-
toml_str = "\n".join(f"{k} = {v}" for k, v in matches)
|
|
204
|
-
overrides.update(tomli.loads(toml_str))
|
|
205
|
+
matches = pattern.findall(config_line)
|
|
206
|
+
toml_str = "\n".join(f"{k} = {v}" for k, v in matches)
|
|
207
|
+
overrides.update(tomli.loads(toml_str))
|
|
205
208
|
|
|
206
209
|
return overrides
|
|
207
210
|
|
flwr/common/telemetry.py
CHANGED
|
@@ -132,53 +132,59 @@ class EventType(str, Enum):
|
|
|
132
132
|
# Ping
|
|
133
133
|
PING = auto()
|
|
134
134
|
|
|
135
|
-
#
|
|
135
|
+
# --- LEGACY FUNCTIONS -------------------------------------------------------------
|
|
136
|
+
|
|
137
|
+
# Legacy: `start_client` function
|
|
136
138
|
START_CLIENT_ENTER = auto()
|
|
137
139
|
START_CLIENT_LEAVE = auto()
|
|
138
140
|
|
|
139
|
-
#
|
|
141
|
+
# Legacy: `start_server` function
|
|
140
142
|
START_SERVER_ENTER = auto()
|
|
141
143
|
START_SERVER_LEAVE = auto()
|
|
142
144
|
|
|
143
|
-
#
|
|
144
|
-
|
|
145
|
-
|
|
145
|
+
# Legacy: `start_simulation` function
|
|
146
|
+
START_SIMULATION_ENTER = auto()
|
|
147
|
+
START_SIMULATION_LEAVE = auto()
|
|
146
148
|
|
|
147
|
-
#
|
|
148
|
-
RUN_FLEET_API_ENTER = auto()
|
|
149
|
-
RUN_FLEET_API_LEAVE = auto()
|
|
149
|
+
# --- `flwr` CLI -------------------------------------------------------------------
|
|
150
150
|
|
|
151
|
-
#
|
|
152
|
-
RUN_SUPERLINK_ENTER = auto()
|
|
153
|
-
RUN_SUPERLINK_LEAVE = auto()
|
|
151
|
+
# Not yet implemented
|
|
154
152
|
|
|
155
|
-
#
|
|
156
|
-
START_SIMULATION_ENTER = auto()
|
|
157
|
-
START_SIMULATION_LEAVE = auto()
|
|
153
|
+
# --- SuperExec --------------------------------------------------------------------
|
|
158
154
|
|
|
159
|
-
#
|
|
160
|
-
|
|
161
|
-
|
|
155
|
+
# SuperExec
|
|
156
|
+
RUN_SUPEREXEC_ENTER = auto()
|
|
157
|
+
RUN_SUPEREXEC_LEAVE = auto()
|
|
162
158
|
|
|
163
|
-
#
|
|
164
|
-
START_DRIVER_ENTER = auto()
|
|
165
|
-
START_DRIVER_LEAVE = auto()
|
|
159
|
+
# --- Simulation Engine ------------------------------------------------------------
|
|
166
160
|
|
|
167
|
-
# flower-
|
|
168
|
-
|
|
169
|
-
|
|
161
|
+
# CLI: flower-simulation
|
|
162
|
+
CLI_FLOWER_SIMULATION_ENTER = auto()
|
|
163
|
+
CLI_FLOWER_SIMULATION_LEAVE = auto()
|
|
170
164
|
|
|
171
|
-
#
|
|
172
|
-
|
|
173
|
-
|
|
165
|
+
# Python API: `run_simulation`
|
|
166
|
+
PYTHON_API_RUN_SIMULATION_ENTER = auto()
|
|
167
|
+
PYTHON_API_RUN_SIMULATION_LEAVE = auto()
|
|
174
168
|
|
|
175
|
-
#
|
|
169
|
+
# --- Deployment Engine ------------------------------------------------------------
|
|
170
|
+
|
|
171
|
+
# CLI: `flower-superlink`
|
|
172
|
+
RUN_SUPERLINK_ENTER = auto()
|
|
173
|
+
RUN_SUPERLINK_LEAVE = auto()
|
|
174
|
+
|
|
175
|
+
# CLI: `flower-supernode`
|
|
176
176
|
RUN_SUPERNODE_ENTER = auto()
|
|
177
177
|
RUN_SUPERNODE_LEAVE = auto()
|
|
178
178
|
|
|
179
|
-
#
|
|
180
|
-
|
|
181
|
-
|
|
179
|
+
# CLI: `flower-server-app`
|
|
180
|
+
RUN_SERVER_APP_ENTER = auto()
|
|
181
|
+
RUN_SERVER_APP_LEAVE = auto()
|
|
182
|
+
|
|
183
|
+
# --- DEPRECATED -------------------------------------------------------------------
|
|
184
|
+
|
|
185
|
+
# [DEPRECATED] CLI: `flower-client-app`
|
|
186
|
+
RUN_CLIENT_APP_ENTER = auto()
|
|
187
|
+
RUN_CLIENT_APP_LEAVE = auto()
|
|
182
188
|
|
|
183
189
|
|
|
184
190
|
# Use the ThreadPoolExecutor with max_workers=1 to have a queue
|
flwr/server/__init__.py
CHANGED
|
@@ -17,14 +17,12 @@
|
|
|
17
17
|
|
|
18
18
|
from . import strategy
|
|
19
19
|
from . import workflow as workflow
|
|
20
|
-
from .app import run_superlink as run_superlink
|
|
21
20
|
from .app import start_server as start_server
|
|
22
21
|
from .client_manager import ClientManager as ClientManager
|
|
23
22
|
from .client_manager import SimpleClientManager as SimpleClientManager
|
|
24
23
|
from .compat import LegacyContext as LegacyContext
|
|
25
24
|
from .driver import Driver as Driver
|
|
26
25
|
from .history import History as History
|
|
27
|
-
from .run_serverapp import run_server_app as run_server_app
|
|
28
26
|
from .server import Server as Server
|
|
29
27
|
from .server_app import ServerApp as ServerApp
|
|
30
28
|
from .server_config import ServerConfig as ServerConfig
|
|
@@ -40,8 +38,6 @@ __all__ = [
|
|
|
40
38
|
"ServerAppComponents",
|
|
41
39
|
"ServerConfig",
|
|
42
40
|
"SimpleClientManager",
|
|
43
|
-
"run_server_app",
|
|
44
|
-
"run_superlink",
|
|
45
41
|
"start_server",
|
|
46
42
|
"strategy",
|
|
47
43
|
"workflow",
|
flwr/server/compat/app.py
CHANGED
|
@@ -18,7 +18,6 @@
|
|
|
18
18
|
from logging import INFO
|
|
19
19
|
from typing import Optional
|
|
20
20
|
|
|
21
|
-
from flwr.common import EventType, event
|
|
22
21
|
from flwr.common.logger import log
|
|
23
22
|
from flwr.server.client_manager import ClientManager
|
|
24
23
|
from flwr.server.history import History
|
|
@@ -65,8 +64,6 @@ def start_driver( # pylint: disable=too-many-arguments, too-many-locals
|
|
|
65
64
|
hist : flwr.server.history.History
|
|
66
65
|
Object containing training and evaluation metrics.
|
|
67
66
|
"""
|
|
68
|
-
event(EventType.START_DRIVER_ENTER)
|
|
69
|
-
|
|
70
67
|
# Initialize the Driver API server and config
|
|
71
68
|
initialized_server, initialized_config = init_defaults(
|
|
72
69
|
server=server,
|
|
@@ -96,6 +93,4 @@ def start_driver( # pylint: disable=too-many-arguments, too-many-locals
|
|
|
96
93
|
f_stop.set()
|
|
97
94
|
thread.join()
|
|
98
95
|
|
|
99
|
-
event(EventType.START_SERVER_LEAVE)
|
|
100
|
-
|
|
101
96
|
return hist
|
|
@@ -21,7 +21,7 @@ from typing import Iterable, List, Optional, cast
|
|
|
21
21
|
|
|
22
22
|
import grpc
|
|
23
23
|
|
|
24
|
-
from flwr.common import DEFAULT_TTL,
|
|
24
|
+
from flwr.common import DEFAULT_TTL, Message, Metadata, RecordSet
|
|
25
25
|
from flwr.common.grpc import create_channel
|
|
26
26
|
from flwr.common.logger import log
|
|
27
27
|
from flwr.common.serde import (
|
|
@@ -94,7 +94,6 @@ class GrpcDriver(Driver):
|
|
|
94
94
|
|
|
95
95
|
This will not call GetRun.
|
|
96
96
|
"""
|
|
97
|
-
event(EventType.DRIVER_CONNECT)
|
|
98
97
|
if self._is_connected:
|
|
99
98
|
log(WARNING, "Already connected")
|
|
100
99
|
return
|
|
@@ -108,7 +107,6 @@ class GrpcDriver(Driver):
|
|
|
108
107
|
|
|
109
108
|
def _disconnect(self) -> None:
|
|
110
109
|
"""Disconnect from the Driver API."""
|
|
111
|
-
event(EventType.DRIVER_DISCONNECT)
|
|
112
110
|
if not self._is_connected:
|
|
113
111
|
log(DEBUG, "Already disconnected")
|
|
114
112
|
return
|
|
@@ -109,6 +109,11 @@ def run_simulation_from_cli() -> None:
|
|
|
109
109
|
"""Run Simulation Engine from the CLI."""
|
|
110
110
|
args = _parse_args_run_simulation().parse_args()
|
|
111
111
|
|
|
112
|
+
event(
|
|
113
|
+
EventType.CLI_FLOWER_SIMULATION_ENTER,
|
|
114
|
+
event_details={"backend": args.backend, "num-supernodes": args.num_supernodes},
|
|
115
|
+
)
|
|
116
|
+
|
|
112
117
|
# Add warnings for deprecated server_app and client_app arguments
|
|
113
118
|
if args.server_app:
|
|
114
119
|
warn_deprecated_feature(
|
|
@@ -177,7 +182,9 @@ def run_simulation_from_cli() -> None:
|
|
|
177
182
|
client_app_attr = app_components["clientapp"]
|
|
178
183
|
server_app_attr = app_components["serverapp"]
|
|
179
184
|
|
|
180
|
-
override_config = parse_config_args(
|
|
185
|
+
override_config = parse_config_args(
|
|
186
|
+
[args.run_config] if args.run_config else args.run_config
|
|
187
|
+
)
|
|
181
188
|
fused_config = get_fused_config_from_dir(app_path, override_config)
|
|
182
189
|
app_dir = args.app
|
|
183
190
|
is_app = True
|
|
@@ -212,6 +219,7 @@ def run_simulation_from_cli() -> None:
|
|
|
212
219
|
verbose_logging=args.verbose,
|
|
213
220
|
server_app_run_config=fused_config,
|
|
214
221
|
is_app=is_app,
|
|
222
|
+
exit_event=EventType.CLI_FLOWER_SIMULATION_LEAVE,
|
|
215
223
|
)
|
|
216
224
|
|
|
217
225
|
|
|
@@ -265,6 +273,11 @@ def run_simulation(
|
|
|
265
273
|
When disabled, only INFO, WARNING and ERROR log messages will be shown. If
|
|
266
274
|
enabled, DEBUG-level logs will be displayed.
|
|
267
275
|
"""
|
|
276
|
+
event(
|
|
277
|
+
EventType.PYTHON_API_RUN_SIMULATION_ENTER,
|
|
278
|
+
event_details={"backend": backend_name, "num-supernodes": num_supernodes},
|
|
279
|
+
)
|
|
280
|
+
|
|
268
281
|
if enable_tf_gpu_growth:
|
|
269
282
|
warn_deprecated_feature_with_example(
|
|
270
283
|
"Passing `enable_tf_gpu_growth=True` is deprecated.",
|
|
@@ -282,6 +295,7 @@ def run_simulation(
|
|
|
282
295
|
backend_config=backend_config,
|
|
283
296
|
enable_tf_gpu_growth=enable_tf_gpu_growth,
|
|
284
297
|
verbose_logging=verbose_logging,
|
|
298
|
+
exit_event=EventType.PYTHON_API_RUN_SIMULATION_LEAVE,
|
|
285
299
|
)
|
|
286
300
|
|
|
287
301
|
|
|
@@ -365,6 +379,7 @@ def _main_loop(
|
|
|
365
379
|
is_app: bool,
|
|
366
380
|
enable_tf_gpu_growth: bool,
|
|
367
381
|
run: Run,
|
|
382
|
+
exit_event: EventType,
|
|
368
383
|
flwr_dir: Optional[str] = None,
|
|
369
384
|
client_app: Optional[ClientApp] = None,
|
|
370
385
|
client_app_attr: Optional[str] = None,
|
|
@@ -372,7 +387,7 @@ def _main_loop(
|
|
|
372
387
|
server_app_attr: Optional[str] = None,
|
|
373
388
|
server_app_run_config: Optional[UserConfig] = None,
|
|
374
389
|
) -> None:
|
|
375
|
-
"""
|
|
390
|
+
"""Start ServerApp on a separate thread, then launch Simulation Engine."""
|
|
376
391
|
# Initialize StateFactory
|
|
377
392
|
state_factory = StateFactory(":flwr-in-memory-state:")
|
|
378
393
|
|
|
@@ -380,6 +395,7 @@ def _main_loop(
|
|
|
380
395
|
# A Threading event to indicate if an exception was raised in the ServerApp thread
|
|
381
396
|
server_app_thread_has_exception = threading.Event()
|
|
382
397
|
serverapp_th = None
|
|
398
|
+
success = True
|
|
383
399
|
try:
|
|
384
400
|
# Register run
|
|
385
401
|
log(DEBUG, "Pre-registering run with id %s", run.run_id)
|
|
@@ -403,8 +419,7 @@ def _main_loop(
|
|
|
403
419
|
enable_tf_gpu_growth=enable_tf_gpu_growth,
|
|
404
420
|
)
|
|
405
421
|
|
|
406
|
-
#
|
|
407
|
-
event(EventType.RUN_SUPERLINK_ENTER)
|
|
422
|
+
# Start Simulation Engine
|
|
408
423
|
vce.start_vce(
|
|
409
424
|
num_supernodes=num_supernodes,
|
|
410
425
|
client_app_attr=client_app_attr,
|
|
@@ -422,13 +437,13 @@ def _main_loop(
|
|
|
422
437
|
except Exception as ex:
|
|
423
438
|
log(ERROR, "An exception occurred !! %s", ex)
|
|
424
439
|
log(ERROR, traceback.format_exc())
|
|
440
|
+
success = False
|
|
425
441
|
raise RuntimeError("An error was encountered. Ending simulation.") from ex
|
|
426
442
|
|
|
427
443
|
finally:
|
|
428
444
|
# Trigger stop event
|
|
429
445
|
f_stop.set()
|
|
430
|
-
|
|
431
|
-
event(EventType.RUN_SUPERLINK_LEAVE)
|
|
446
|
+
event(exit_event, event_details={"success": success})
|
|
432
447
|
if serverapp_th:
|
|
433
448
|
serverapp_th.join()
|
|
434
449
|
if server_app_thread_has_exception.is_set():
|
|
@@ -440,6 +455,7 @@ def _main_loop(
|
|
|
440
455
|
# pylint: disable=too-many-arguments,too-many-locals
|
|
441
456
|
def _run_simulation(
|
|
442
457
|
num_supernodes: int,
|
|
458
|
+
exit_event: EventType,
|
|
443
459
|
client_app: Optional[ClientApp] = None,
|
|
444
460
|
server_app: Optional[ServerApp] = None,
|
|
445
461
|
backend_name: str = "ray",
|
|
@@ -506,6 +522,7 @@ def _run_simulation(
|
|
|
506
522
|
is_app,
|
|
507
523
|
enable_tf_gpu_growth,
|
|
508
524
|
run,
|
|
525
|
+
exit_event,
|
|
509
526
|
flwr_dir,
|
|
510
527
|
client_app,
|
|
511
528
|
client_app_attr,
|
flwr/superexec/__init__.py
CHANGED