vantage6 4.10.1rc1__tar.gz → 4.11.0__tar.gz

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 vantage6 might be problematic. Click here for more details.

Files changed (88) hide show
  1. {vantage6-4.10.1rc1 → vantage6-4.11.0}/PKG-INFO +1 -1
  2. {vantage6-4.10.1rc1 → vantage6-4.11.0}/setup.py +2 -0
  3. vantage6-4.11.0/tests_cli/test_client_script.py +23 -0
  4. vantage6-4.11.0/vantage6/cli/__build__ +1 -0
  5. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/_version.py +1 -1
  6. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/cli.py +2 -0
  7. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/configuration_manager.py +1 -0
  8. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/context/server.py +26 -0
  9. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/dev/create.py +78 -17
  10. vantage6-4.11.0/vantage6/cli/dev/data/km_dataset.csv +2401 -0
  11. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/globals.py +12 -0
  12. vantage6-4.11.0/vantage6/cli/prometheus/monitoring_manager.py +146 -0
  13. vantage6-4.11.0/vantage6/cli/prometheus/prometheus.yml +5 -0
  14. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/server/start.py +58 -2
  15. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/server/stop.py +7 -0
  16. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/template/node_config.j2 +4 -2
  17. vantage6-4.11.0/vantage6/cli/test/algo_test_scripts/algo_test_arguments.py +33 -0
  18. vantage6-4.11.0/vantage6/cli/test/algo_test_scripts/algo_test_script.py +88 -0
  19. vantage6-4.11.0/vantage6/cli/test/client_script.py +150 -0
  20. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6.egg-info/PKG-INFO +1 -1
  21. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6.egg-info/SOURCES.txt +7 -0
  22. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6.egg-info/requires.txt +2 -2
  23. vantage6-4.10.1rc1/vantage6/cli/__build__ +0 -1
  24. {vantage6-4.10.1rc1 → vantage6-4.11.0}/setup.cfg +0 -0
  25. {vantage6-4.10.1rc1 → vantage6-4.11.0}/tests_cli/__init__.py +0 -0
  26. {vantage6-4.10.1rc1 → vantage6-4.11.0}/tests_cli/test_example.py +0 -0
  27. {vantage6-4.10.1rc1 → vantage6-4.11.0}/tests_cli/test_node_cli.py +0 -0
  28. {vantage6-4.10.1rc1 → vantage6-4.11.0}/tests_cli/test_server_cli.py +0 -0
  29. {vantage6-4.10.1rc1 → vantage6-4.11.0}/tests_cli/test_wizard.py +0 -0
  30. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/__init__.py +0 -0
  31. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/algorithm/create.py +0 -0
  32. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/algorithm/update.py +0 -0
  33. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/algostore/attach.py +0 -0
  34. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/algostore/files.py +0 -0
  35. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/algostore/list.py +0 -0
  36. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/algostore/new.py +0 -0
  37. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/algostore/remove.py +0 -0
  38. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/algostore/start.py +0 -0
  39. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/algostore/stop.py +0 -0
  40. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/common/decorator.py +0 -0
  41. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/common/start.py +0 -0
  42. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/common/utils.py +0 -0
  43. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/configuration_wizard.py +0 -0
  44. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/context/__init__.py +0 -0
  45. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/context/algorithm_store.py +0 -0
  46. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/context/base_server.py +0 -0
  47. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/context/node.py +0 -0
  48. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/dev/data/olympic_athletes_2016.csv +0 -0
  49. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/dev/remove.py +0 -0
  50. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/dev/start.py +0 -0
  51. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/dev/stop.py +0 -0
  52. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/dev/utils.py +0 -0
  53. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/node/attach.py +0 -0
  54. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/node/clean.py +0 -0
  55. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/node/common/__init__.py +0 -0
  56. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/node/create_private_key.py +0 -0
  57. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/node/files.py +0 -0
  58. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/node/list.py +0 -0
  59. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/node/new.py +0 -0
  60. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/node/remove.py +0 -0
  61. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/node/restart.py +0 -0
  62. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/node/set_api_key.py +0 -0
  63. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/node/start.py +0 -0
  64. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/node/stop.py +0 -0
  65. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/node/version.py +0 -0
  66. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/rabbitmq/__init__.py +0 -0
  67. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/rabbitmq/definitions.py +0 -0
  68. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/rabbitmq/queue_manager.py +0 -0
  69. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/rabbitmq/rabbitmq.config +0 -0
  70. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/server/attach.py +0 -0
  71. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/server/common/__init__.py +0 -0
  72. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/server/files.py +0 -0
  73. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/server/import_.py +0 -0
  74. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/server/list.py +0 -0
  75. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/server/new.py +0 -0
  76. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/server/remove.py +0 -0
  77. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/server/shell.py +0 -0
  78. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/server/version.py +0 -0
  79. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/template/algo_store_config.j2 +0 -0
  80. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/template/server_config.j2 +0 -0
  81. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/template/server_import_config.j2 +0 -0
  82. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/test/common/diagnostic_runner.py +0 -0
  83. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/test/feature_tester.py +0 -0
  84. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/test/integration_test.py +0 -0
  85. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6/cli/utils.py +0 -0
  86. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6.egg-info/dependency_links.txt +0 -0
  87. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6.egg-info/entry_points.txt +0 -0
  88. {vantage6-4.10.1rc1 → vantage6-4.11.0}/vantage6.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: vantage6
3
- Version: 4.10.1rc1
3
+ Version: 4.11.0
4
4
  Summary: vantage6 command line interface
5
5
  Home-page: https://github.com/vantage6/vantage6
6
6
  Requires-Python: >=3.10
@@ -63,6 +63,8 @@ setup(
63
63
  "template/server_import_config.j2",
64
64
  "template/algo_store_config.j2",
65
65
  "dev/data/olympic_athletes_2016.csv",
66
+ "dev/data/km_dataset.csv",
67
+ "prometheus/prometheus.yml",
66
68
  ],
67
69
  },
68
70
  entry_points={
@@ -0,0 +1,23 @@
1
+ from click import UsageError
2
+ from vantage6.cli.test.client_script import cli_test_client_script
3
+
4
+ import click
5
+ import unittest
6
+
7
+
8
+ class TestScriptTest(unittest.TestCase):
9
+ def test_script_incorrect_usage(self):
10
+ ctx = click.Context(cli_test_client_script)
11
+
12
+ with self.assertRaises(UsageError):
13
+ ctx.invoke(
14
+ cli_test_client_script,
15
+ script="path/to/script.py",
16
+ task_arguments="{'my_arg': 1}",
17
+ )
18
+
19
+ with self.assertRaises(UsageError):
20
+ ctx.invoke(
21
+ cli_test_client_script,
22
+ task_arguments="not_a_json",
23
+ )
@@ -0,0 +1 @@
1
+ 0
@@ -7,7 +7,7 @@ with open(os.path.join(here, "__build__")) as fp:
7
7
  __build__ = json.load(fp)
8
8
 
9
9
  # Module version
10
- version_info = (4, 10, 1, "candidate", __build__, 0)
10
+ version_info = (4, 11, 0, "final", __build__, 0)
11
11
 
12
12
  # Module version stage suffix map
13
13
  _specifier_ = {"alpha": "a", "beta": "b", "candidate": "rc", "final": ""}
@@ -28,6 +28,7 @@ from vantage6.cli.dev.start import start_demo_network
28
28
  from vantage6.cli.dev.stop import stop_demo_network
29
29
  from vantage6.cli.algorithm.create import cli_algorithm_create
30
30
  from vantage6.cli.algorithm.update import cli_algorithm_update
31
+ from vantage6.cli.test.client_script import cli_test_client_script
31
32
  from vantage6.cli.test.feature_tester import cli_test_features
32
33
  from vantage6.cli.test.integration_test import cli_test_integration
33
34
  from vantage6.cli.algostore.attach import cli_algo_store_attach
@@ -124,6 +125,7 @@ def cli_test() -> None:
124
125
  # Define the commands for the test group
125
126
  cli_test.add_command(cli_test_features, name="feature-test")
126
127
  cli_test.add_command(cli_test_integration, name="integration-test")
128
+ cli_test.add_command(cli_test_client_script, name="client-script")
127
129
 
128
130
 
129
131
  # Define the algorithm-store group
@@ -52,6 +52,7 @@ class NodeConfiguration(Configuration):
52
52
  Optional("node_extra_env"): dict,
53
53
  Optional("node_extra_mounts"): [str],
54
54
  Optional("node_extra_hosts"): dict,
55
+ Optional("share_algorithm_logs"): Use(bool),
55
56
  }
56
57
 
57
58
 
@@ -1,9 +1,11 @@
1
1
  from __future__ import annotations
2
+ from pathlib import Path
2
3
 
3
4
  from vantage6.common.globals import APPNAME, InstanceType
4
5
  from vantage6.cli.configuration_manager import ServerConfigurationManager
5
6
  from vantage6.cli.globals import (
6
7
  DEFAULT_SERVER_SYSTEM_FOLDERS as S_FOL,
8
+ PROMETHEUS_DIR,
7
9
  ServerType,
8
10
  ServerGlobals,
9
11
  )
@@ -57,6 +59,30 @@ class ServerContext(BaseServerContext):
57
59
  """
58
60
  return f"{APPNAME}-{self.name}-{self.scope}-{ServerType.V6SERVER}"
59
61
 
62
+ @property
63
+ def prometheus_container_name(self) -> str:
64
+ """
65
+ Get the name of the Prometheus Docker container for this server.
66
+
67
+ Returns
68
+ -------
69
+ str
70
+ Prometheus container name, unique to this server instance.
71
+ """
72
+ return f"{APPNAME}-{self.name}-{self.scope}-prometheus"
73
+
74
+ @property
75
+ def prometheus_dir(self) -> Path:
76
+ """
77
+ Get the Prometheus directory path.
78
+
79
+ Returns
80
+ -------
81
+ Path
82
+ Path to the Prometheus directory
83
+ """
84
+ return self.data_dir / PROMETHEUS_DIR
85
+
60
86
  @classmethod
61
87
  def from_external_config_file(
62
88
  cls, path: str, system_folders: bool = S_FOL
@@ -12,7 +12,7 @@ from vantage6.common import ensure_config_dir_writable, info, error, generate_ap
12
12
 
13
13
  import vantage6.cli.dev.data as data_dir
14
14
  from vantage6.cli.context.algorithm_store import AlgorithmStoreContext
15
- from vantage6.cli.globals import PACKAGE_FOLDER
15
+ from vantage6.cli.globals import PACKAGE_FOLDER, DefaultDatasets
16
16
  from vantage6.cli.context.server import ServerContext
17
17
  from vantage6.cli.context.node import NodeContext
18
18
  from vantage6.cli.server.common import get_server_context
@@ -20,7 +20,9 @@ from vantage6.cli.server.import_ import cli_server_import
20
20
  from vantage6.cli.utils import prompt_config_name
21
21
 
22
22
 
23
- def create_node_data_files(num_nodes: int, server_name: str) -> list[Path]:
23
+ def create_node_data_files(
24
+ num_nodes: int, server_name: str, dataset: tuple[str, Path]
25
+ ) -> list[tuple[str, Path]]:
24
26
  """Create data files for nodes.
25
27
 
26
28
  Parameters
@@ -29,15 +31,16 @@ def create_node_data_files(num_nodes: int, server_name: str) -> list[Path]:
29
31
  Number of nodes to create data files for.
30
32
  server_name : str
31
33
  Name of the server.
32
-
34
+ dataset : tuple[str, Path]
35
+ Tuple containing the name and the path to the dataset.
33
36
  Returns
34
37
  -------
35
- list[Path]
36
- List of paths to the created data files.
38
+ list[tuple[str, Path]]
39
+ List of the label and paths to the created data files.
37
40
  """
38
41
  info(f"Creating data files for {num_nodes} nodes.")
39
42
  data_files = []
40
- full_df = pd.read_csv(impresources.files(data_dir) / "olympic_athletes_2016.csv")
43
+ full_df = pd.read_csv(dataset[1])
41
44
  length_df = len(full_df)
42
45
  for i in range(num_nodes):
43
46
  node_name = f"{server_name}_node_{i + 1}"
@@ -49,16 +52,20 @@ def create_node_data_files(num_nodes: int, server_name: str) -> list[Path]:
49
52
  start = i * length_df // num_nodes
50
53
  end = (i + 1) * length_df // num_nodes
51
54
  data = full_df[start:end]
52
- data_file = data_folder / f"df_{node_name}.csv"
55
+ data_file = data_folder / f"df_{dataset[0]}_{node_name}.csv"
53
56
 
54
57
  # write data to file
55
58
  data.to_csv(data_file, index=False)
56
- data_files.append(data_file)
59
+ data_files.append((dataset[0], data_file))
57
60
  return data_files
58
61
 
59
62
 
60
63
  def create_node_config_file(
61
- server_url: str, port: int, config: dict, server_name: str, datafile: Path
64
+ server_url: str,
65
+ port: int,
66
+ config: dict,
67
+ server_name: str,
68
+ datasets: list[tuple[str, Path]] = (),
62
69
  ) -> None:
63
70
  """Create a node configuration file (YAML).
64
71
 
@@ -77,8 +84,8 @@ def create_node_config_file(
77
84
  additional user_defined_config.
78
85
  server_name : str
79
86
  Configuration name of the dummy server.
80
- datafile : Path
81
- Path to the data file for the node to use.
87
+ datasets : list[tuple[str, Path]]
88
+ List of tuples containing the labels and the paths to the datasets
82
89
  """
83
90
  environment = Environment(
84
91
  loader=FileSystemLoader(PACKAGE_FOLDER / APPNAME / "cli" / "template"),
@@ -102,10 +109,12 @@ def create_node_config_file(
102
109
  error(f"Node configuration file already exists: {full_path}")
103
110
  exit(1)
104
111
 
112
+ databases = [{dataset[0]: dataset[1]} for dataset in datasets]
113
+
105
114
  node_config = template.render(
106
115
  {
107
116
  "api_key": config["api_key"],
108
- "databases": {"default": datafile},
117
+ "databases": databases,
109
118
  "logging": {"file": f"{node_name}.log"},
110
119
  "port": port,
111
120
  "server_url": server_url,
@@ -124,8 +133,7 @@ def create_node_config_file(
124
133
  f.write(node_config)
125
134
 
126
135
  info(
127
- f"Spawned node for organization {Fore.GREEN}{config['org_id']}"
128
- f"{Style.RESET_ALL}"
136
+ f"Spawned node for organization {Fore.GREEN}{config['org_id']}{Style.RESET_ALL}"
129
137
  )
130
138
 
131
139
 
@@ -156,6 +164,7 @@ def generate_node_configs(
156
164
  port: int,
157
165
  server_name: str,
158
166
  extra_node_config: Path | None,
167
+ extra_datasets: list[tuple[str, Path]],
159
168
  ) -> list[dict]:
160
169
  """Generates ``num_nodes`` node configuration files.
161
170
 
@@ -171,6 +180,8 @@ def generate_node_configs(
171
180
  Configuration name of the dummy server.
172
181
  extra_node_config : Path | None
173
182
  Path to file with additional node configuration.
183
+ extra_datasets : list[tuple[str, Path]]
184
+ List of tuples containing the labels and the paths to extra datasets
174
185
 
175
186
  Returns
176
187
  -------
@@ -178,8 +189,36 @@ def generate_node_configs(
178
189
  List of dictionaries containing node configurations.
179
190
  """
180
191
  configs = []
192
+ node_data_files = []
181
193
  extra_config = _read_extra_config_file(extra_node_config)
182
- node_data_files = create_node_data_files(num_nodes, server_name)
194
+
195
+ data_directory = impresources.files(data_dir)
196
+
197
+ # Add default datasets to the list of dataset provided
198
+ for default_dataset in DefaultDatasets:
199
+ extra_datasets.append(
200
+ (default_dataset.name.lower(), data_directory / default_dataset.value)
201
+ )
202
+
203
+ # Check for duplicate dataset labels
204
+ seen_labels = set()
205
+ duplicates = [
206
+ label
207
+ for label in [dataset[0] for dataset in extra_datasets]
208
+ if (label in seen_labels or seen_labels.add(label))
209
+ ]
210
+
211
+ if len(duplicates) > 0:
212
+ error(
213
+ f"Duplicate dataset labels found: {duplicates}. "
214
+ f"Please make sure all dataset labels are unique."
215
+ )
216
+ exit(1)
217
+
218
+ # create the data files for the nodes and get the path and label for each dataset
219
+ for dataset in extra_datasets:
220
+ node_data_files.append(create_node_data_files(num_nodes, server_name, dataset))
221
+
183
222
  for i in range(num_nodes):
184
223
  config = {
185
224
  "org_id": i + 1,
@@ -188,7 +227,11 @@ def generate_node_configs(
188
227
  "user_defined_config": extra_config,
189
228
  }
190
229
  create_node_config_file(
191
- server_url, port, config, server_name, node_data_files[i]
230
+ server_url,
231
+ port,
232
+ config,
233
+ server_name,
234
+ [files[i] for files in node_data_files],
192
235
  )
193
236
  configs.append(config)
194
237
 
@@ -422,6 +465,7 @@ def demo_network(
422
465
  ui_image: str,
423
466
  ui_port: int,
424
467
  algorithm_store_port: int,
468
+ extra_datasets: list[tuple[str, Path]],
425
469
  ) -> tuple[list[dict], Path, Path]:
426
470
  """Generates the demo network.
427
471
 
@@ -448,6 +492,8 @@ def demo_network(
448
492
  Port to run the UI on.
449
493
  algorithm_store_port : int
450
494
  Port to run the algorithm store on.
495
+ extra_datasets : list[tuple[str, Path]]
496
+ List of tuples containing the labels and the paths to extra datasets
451
497
 
452
498
  Returns
453
499
  -------
@@ -455,7 +501,12 @@ def demo_network(
455
501
  Tuple containing node, server import and server configurations.
456
502
  """
457
503
  node_configs = generate_node_configs(
458
- num_nodes, server_url, server_port, server_name, extra_node_config
504
+ num_nodes,
505
+ server_url,
506
+ server_port,
507
+ server_name,
508
+ extra_node_config,
509
+ extra_datasets,
459
510
  )
460
511
  server_import_config = create_vserver_import_config(node_configs, server_name)
461
512
  server_config = create_vserver_config(
@@ -549,6 +600,14 @@ def demo_network(
549
600
  help="YAML File with additional algorithm store configuration. This will be"
550
601
  " appended to the algorithm store configuration file",
551
602
  )
603
+ @click.option(
604
+ "--add-dataset",
605
+ type=(str, click.Path()),
606
+ default=(),
607
+ multiple=True,
608
+ help="Add a dataset to the nodes. The first argument is the label of the database, "
609
+ "the second is the path to the dataset file.",
610
+ )
552
611
  @click.pass_context
553
612
  def create_demo_network(
554
613
  click_ctx: click.Context,
@@ -563,6 +622,7 @@ def create_demo_network(
563
622
  extra_server_config: Path = None,
564
623
  extra_node_config: Path = None,
565
624
  extra_store_config: Path = None,
625
+ add_dataset: list[tuple[str, Path]] = (),
566
626
  ) -> dict:
567
627
  """Creates a demo network.
568
628
 
@@ -584,6 +644,7 @@ def create_demo_network(
584
644
  ui_image,
585
645
  ui_port,
586
646
  algorithm_store_port,
647
+ list(add_dataset),
587
648
  )
588
649
  info(
589
650
  f"Created {Fore.GREEN}{len(demo[0])}{Style.RESET_ALL} node "