flwr 1.24.0__py3-none-any.whl → 1.26.0__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.
Files changed (204) hide show
  1. flwr/__init__.py +1 -1
  2. flwr/app/__init__.py +4 -1
  3. flwr/app/message_type.py +29 -0
  4. flwr/app/metadata.py +5 -2
  5. flwr/app/user_config.py +19 -0
  6. flwr/cli/app.py +37 -19
  7. flwr/cli/app_cmd/publish.py +25 -75
  8. flwr/cli/app_cmd/review.py +25 -66
  9. flwr/cli/auth_plugin/auth_plugin.py +5 -10
  10. flwr/cli/auth_plugin/noop_auth_plugin.py +1 -2
  11. flwr/cli/auth_plugin/oidc_cli_plugin.py +38 -38
  12. flwr/cli/build.py +15 -28
  13. flwr/cli/config/__init__.py +21 -0
  14. flwr/cli/config/ls.py +71 -0
  15. flwr/cli/config_migration.py +297 -0
  16. flwr/cli/config_utils.py +63 -156
  17. flwr/cli/constant.py +71 -0
  18. flwr/cli/federation/__init__.py +0 -2
  19. flwr/cli/federation/ls.py +256 -64
  20. flwr/cli/flower_config.py +429 -0
  21. flwr/cli/install.py +23 -62
  22. flwr/cli/log.py +23 -37
  23. flwr/cli/login/login.py +29 -63
  24. flwr/cli/ls.py +72 -61
  25. flwr/cli/new/new.py +98 -309
  26. flwr/cli/pull.py +19 -37
  27. flwr/cli/run/run.py +87 -100
  28. flwr/cli/run_utils.py +23 -5
  29. flwr/cli/stop.py +33 -74
  30. flwr/cli/supernode/ls.py +35 -62
  31. flwr/cli/supernode/register.py +31 -80
  32. flwr/cli/supernode/unregister.py +24 -70
  33. flwr/cli/typing.py +200 -0
  34. flwr/cli/utils.py +160 -412
  35. flwr/client/grpc_adapter_client/connection.py +2 -2
  36. flwr/client/grpc_rere_client/connection.py +9 -6
  37. flwr/client/grpc_rere_client/grpc_adapter.py +1 -1
  38. flwr/client/message_handler/message_handler.py +2 -1
  39. flwr/client/mod/centraldp_mods.py +1 -1
  40. flwr/client/mod/localdp_mod.py +1 -1
  41. flwr/client/mod/secure_aggregation/secaggplus_mod.py +1 -1
  42. flwr/client/rest_client/connection.py +6 -4
  43. flwr/client/run_info_store.py +2 -1
  44. flwr/clientapp/client_app.py +2 -1
  45. flwr/common/__init__.py +3 -2
  46. flwr/common/args.py +5 -5
  47. flwr/common/config.py +12 -17
  48. flwr/common/constant.py +3 -16
  49. flwr/common/context.py +2 -1
  50. flwr/common/exit/exit.py +4 -4
  51. flwr/common/exit/exit_code.py +6 -0
  52. flwr/common/grpc.py +2 -1
  53. flwr/common/logger.py +1 -1
  54. flwr/common/message.py +1 -1
  55. flwr/common/retry_invoker.py +13 -5
  56. flwr/common/secure_aggregation/ndarrays_arithmetic.py +5 -2
  57. flwr/common/serde.py +13 -5
  58. flwr/common/telemetry.py +1 -1
  59. flwr/common/typing.py +10 -3
  60. flwr/compat/client/app.py +6 -9
  61. flwr/compat/client/grpc_client/connection.py +2 -1
  62. flwr/compat/common/constant.py +29 -0
  63. flwr/compat/server/app.py +1 -1
  64. flwr/proto/clientappio_pb2.py +2 -2
  65. flwr/proto/clientappio_pb2_grpc.py +104 -88
  66. flwr/proto/clientappio_pb2_grpc.pyi +140 -80
  67. flwr/proto/federation_pb2.py +5 -3
  68. flwr/proto/federation_pb2.pyi +32 -2
  69. flwr/proto/fleet_pb2.py +10 -10
  70. flwr/proto/fleet_pb2.pyi +5 -1
  71. flwr/proto/run_pb2.py +18 -26
  72. flwr/proto/run_pb2.pyi +10 -58
  73. flwr/proto/serverappio_pb2.py +2 -2
  74. flwr/proto/serverappio_pb2_grpc.py +138 -207
  75. flwr/proto/serverappio_pb2_grpc.pyi +189 -155
  76. flwr/proto/simulationio_pb2.py +2 -2
  77. flwr/proto/simulationio_pb2_grpc.py +62 -90
  78. flwr/proto/simulationio_pb2_grpc.pyi +95 -55
  79. flwr/server/app.py +7 -13
  80. flwr/server/compat/grid_client_proxy.py +2 -1
  81. flwr/server/grid/grpc_grid.py +5 -5
  82. flwr/server/serverapp/app.py +11 -4
  83. flwr/server/superlink/fleet/grpc_adapter/grpc_adapter_servicer.py +1 -1
  84. flwr/server/superlink/fleet/grpc_rere/node_auth_server_interceptor.py +13 -12
  85. flwr/server/superlink/fleet/message_handler/message_handler.py +42 -2
  86. flwr/server/superlink/linkstate/__init__.py +2 -2
  87. flwr/server/superlink/linkstate/in_memory_linkstate.py +36 -10
  88. flwr/server/superlink/linkstate/linkstate.py +34 -21
  89. flwr/server/superlink/linkstate/linkstate_factory.py +16 -8
  90. flwr/server/superlink/linkstate/{sqlite_linkstate.py → sql_linkstate.py} +471 -516
  91. flwr/server/superlink/linkstate/utils.py +49 -2
  92. flwr/server/superlink/serverappio/serverappio_servicer.py +1 -33
  93. flwr/server/superlink/simulation/simulationio_servicer.py +0 -19
  94. flwr/server/utils/validator.py +1 -1
  95. flwr/server/workflow/default_workflows.py +2 -1
  96. flwr/server/workflow/secure_aggregation/secaggplus_workflow.py +1 -1
  97. flwr/serverapp/strategy/bulyan.py +7 -1
  98. flwr/serverapp/strategy/dp_fixed_clipping.py +9 -1
  99. flwr/serverapp/strategy/fedavg.py +1 -1
  100. flwr/serverapp/strategy/fedxgb_cyclic.py +1 -1
  101. flwr/simulation/ray_transport/ray_client_proxy.py +2 -6
  102. flwr/simulation/run_simulation.py +3 -12
  103. flwr/simulation/simulationio_connection.py +3 -3
  104. flwr/{common → supercore}/address.py +7 -33
  105. flwr/supercore/app_utils.py +2 -1
  106. flwr/supercore/constant.py +27 -2
  107. flwr/supercore/corestate/{sqlite_corestate.py → sql_corestate.py} +19 -23
  108. flwr/supercore/credential_store/__init__.py +33 -0
  109. flwr/supercore/credential_store/credential_store.py +34 -0
  110. flwr/supercore/credential_store/file_credential_store.py +76 -0
  111. flwr/{common → supercore}/date.py +0 -11
  112. flwr/supercore/ffs/disk_ffs.py +1 -1
  113. flwr/supercore/object_store/object_store_factory.py +14 -6
  114. flwr/supercore/object_store/{sqlite_object_store.py → sql_object_store.py} +115 -117
  115. flwr/supercore/sql_mixin.py +315 -0
  116. flwr/{cli/new/templates → supercore/state}/__init__.py +2 -2
  117. flwr/{cli/new/templates/app/code/flwr_tune → supercore/state/alembic}/__init__.py +2 -2
  118. flwr/supercore/state/alembic/env.py +103 -0
  119. flwr/supercore/state/alembic/script.py.mako +43 -0
  120. flwr/supercore/state/alembic/utils.py +239 -0
  121. flwr/{cli/new/templates/app → supercore/state/alembic/versions}/__init__.py +2 -2
  122. flwr/supercore/state/alembic/versions/rev_2026_01_28_initialize_migration_of_state_tables.py +200 -0
  123. flwr/supercore/state/schema/README.md +121 -0
  124. flwr/{cli/new/templates/app/code → supercore/state/schema}/__init__.py +2 -2
  125. flwr/supercore/state/schema/corestate_tables.py +36 -0
  126. flwr/supercore/state/schema/linkstate_tables.py +152 -0
  127. flwr/supercore/state/schema/objectstore_tables.py +90 -0
  128. flwr/supercore/superexec/run_superexec.py +2 -2
  129. flwr/supercore/utils.py +225 -0
  130. flwr/superlink/federation/federation_manager.py +2 -2
  131. flwr/superlink/federation/noop_federation_manager.py +8 -6
  132. flwr/superlink/servicer/control/control_grpc.py +2 -0
  133. flwr/superlink/servicer/control/control_servicer.py +106 -21
  134. flwr/supernode/cli/flower_supernode.py +2 -1
  135. flwr/supernode/nodestate/in_memory_nodestate.py +62 -1
  136. flwr/supernode/nodestate/nodestate.py +45 -0
  137. flwr/supernode/runtime/run_clientapp.py +14 -14
  138. flwr/supernode/servicer/clientappio/clientappio_servicer.py +13 -5
  139. flwr/supernode/start_client_internal.py +17 -10
  140. {flwr-1.24.0.dist-info → flwr-1.26.0.dist-info}/METADATA +8 -8
  141. {flwr-1.24.0.dist-info → flwr-1.26.0.dist-info}/RECORD +144 -184
  142. flwr/cli/federation/show.py +0 -317
  143. flwr/cli/new/templates/app/.gitignore.tpl +0 -163
  144. flwr/cli/new/templates/app/LICENSE.tpl +0 -202
  145. flwr/cli/new/templates/app/README.baseline.md.tpl +0 -127
  146. flwr/cli/new/templates/app/README.flowertune.md.tpl +0 -68
  147. flwr/cli/new/templates/app/README.md.tpl +0 -37
  148. flwr/cli/new/templates/app/code/__init__.baseline.py.tpl +0 -1
  149. flwr/cli/new/templates/app/code/__init__.py.tpl +0 -1
  150. flwr/cli/new/templates/app/code/__init__.pytorch_legacy_api.py.tpl +0 -1
  151. flwr/cli/new/templates/app/code/client.baseline.py.tpl +0 -75
  152. flwr/cli/new/templates/app/code/client.huggingface.py.tpl +0 -93
  153. flwr/cli/new/templates/app/code/client.jax.py.tpl +0 -71
  154. flwr/cli/new/templates/app/code/client.mlx.py.tpl +0 -102
  155. flwr/cli/new/templates/app/code/client.numpy.py.tpl +0 -46
  156. flwr/cli/new/templates/app/code/client.pytorch.py.tpl +0 -80
  157. flwr/cli/new/templates/app/code/client.pytorch_legacy_api.py.tpl +0 -55
  158. flwr/cli/new/templates/app/code/client.sklearn.py.tpl +0 -108
  159. flwr/cli/new/templates/app/code/client.tensorflow.py.tpl +0 -82
  160. flwr/cli/new/templates/app/code/client.xgboost.py.tpl +0 -110
  161. flwr/cli/new/templates/app/code/dataset.baseline.py.tpl +0 -36
  162. flwr/cli/new/templates/app/code/flwr_tune/client_app.py.tpl +0 -92
  163. flwr/cli/new/templates/app/code/flwr_tune/dataset.py.tpl +0 -87
  164. flwr/cli/new/templates/app/code/flwr_tune/models.py.tpl +0 -56
  165. flwr/cli/new/templates/app/code/flwr_tune/server_app.py.tpl +0 -73
  166. flwr/cli/new/templates/app/code/flwr_tune/strategy.py.tpl +0 -78
  167. flwr/cli/new/templates/app/code/model.baseline.py.tpl +0 -66
  168. flwr/cli/new/templates/app/code/server.baseline.py.tpl +0 -43
  169. flwr/cli/new/templates/app/code/server.huggingface.py.tpl +0 -42
  170. flwr/cli/new/templates/app/code/server.jax.py.tpl +0 -39
  171. flwr/cli/new/templates/app/code/server.mlx.py.tpl +0 -41
  172. flwr/cli/new/templates/app/code/server.numpy.py.tpl +0 -38
  173. flwr/cli/new/templates/app/code/server.pytorch.py.tpl +0 -41
  174. flwr/cli/new/templates/app/code/server.pytorch_legacy_api.py.tpl +0 -31
  175. flwr/cli/new/templates/app/code/server.sklearn.py.tpl +0 -44
  176. flwr/cli/new/templates/app/code/server.tensorflow.py.tpl +0 -38
  177. flwr/cli/new/templates/app/code/server.xgboost.py.tpl +0 -56
  178. flwr/cli/new/templates/app/code/strategy.baseline.py.tpl +0 -1
  179. flwr/cli/new/templates/app/code/task.huggingface.py.tpl +0 -98
  180. flwr/cli/new/templates/app/code/task.jax.py.tpl +0 -57
  181. flwr/cli/new/templates/app/code/task.mlx.py.tpl +0 -102
  182. flwr/cli/new/templates/app/code/task.numpy.py.tpl +0 -7
  183. flwr/cli/new/templates/app/code/task.pytorch.py.tpl +0 -99
  184. flwr/cli/new/templates/app/code/task.pytorch_legacy_api.py.tpl +0 -111
  185. flwr/cli/new/templates/app/code/task.sklearn.py.tpl +0 -67
  186. flwr/cli/new/templates/app/code/task.tensorflow.py.tpl +0 -52
  187. flwr/cli/new/templates/app/code/task.xgboost.py.tpl +0 -67
  188. flwr/cli/new/templates/app/code/utils.baseline.py.tpl +0 -1
  189. flwr/cli/new/templates/app/pyproject.baseline.toml.tpl +0 -146
  190. flwr/cli/new/templates/app/pyproject.flowertune.toml.tpl +0 -80
  191. flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl +0 -65
  192. flwr/cli/new/templates/app/pyproject.jax.toml.tpl +0 -52
  193. flwr/cli/new/templates/app/pyproject.mlx.toml.tpl +0 -56
  194. flwr/cli/new/templates/app/pyproject.numpy.toml.tpl +0 -49
  195. flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl +0 -53
  196. flwr/cli/new/templates/app/pyproject.pytorch_legacy_api.toml.tpl +0 -53
  197. flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl +0 -52
  198. flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl +0 -53
  199. flwr/cli/new/templates/app/pyproject.xgboost.toml.tpl +0 -61
  200. flwr/common/pyproject.py +0 -42
  201. flwr/supercore/sqlite_mixin.py +0 -159
  202. /flwr/{common → supercore}/version.py +0 -0
  203. {flwr-1.24.0.dist-info → flwr-1.26.0.dist-info}/WHEEL +0 -0
  204. {flwr-1.24.0.dist-info → flwr-1.26.0.dist-info}/entry_points.txt +0 -0
@@ -1,53 +0,0 @@
1
- # =====================================================================
2
- # For a full TOML configuration guide, check the Flower docs:
3
- # https://flower.ai/docs/framework/how-to-configure-pyproject-toml.html
4
- # =====================================================================
5
-
6
- [build-system]
7
- requires = ["hatchling"]
8
- build-backend = "hatchling.build"
9
-
10
- [project]
11
- name = "$package_name"
12
- version = "1.0.0"
13
- description = ""
14
- license = "Apache-2.0"
15
- # Dependencies for your Flower App
16
- dependencies = [
17
- "flwr[simulation]>=1.24.0",
18
- "flwr-datasets[vision]>=0.5.0",
19
- "tensorflow>=2.18.0",
20
- ]
21
-
22
- [tool.hatch.build.targets.wheel]
23
- packages = ["."]
24
-
25
- [tool.flwr.app]
26
- publisher = "$username"
27
-
28
- # Point to your ServerApp and ClientApp objects
29
- # Format: "<module>:<object>"
30
- [tool.flwr.app.components]
31
- serverapp = "$import_name.server_app:app"
32
- clientapp = "$import_name.client_app:app"
33
-
34
- # Custom config values accessible via `context.run_config`
35
- [tool.flwr.app.config]
36
- num-server-rounds = 3
37
- local-epochs = 1
38
- batch-size = 32
39
- verbose = false
40
-
41
- # Default federation to use when running the app
42
- [tool.flwr.federations]
43
- default = "local-simulation"
44
-
45
- # Local simulation federation with 10 virtual SuperNodes
46
- [tool.flwr.federations.local-simulation]
47
- options.num-supernodes = 10
48
-
49
- # Remote federation example for use with SuperLink
50
- [tool.flwr.federations.remote-federation]
51
- address = "<SUPERLINK-ADDRESS>:<PORT>"
52
- insecure = true # Remove this line to enable TLS
53
- # root-certificates = "<PATH/TO/ca.crt>" # For TLS setup
@@ -1,61 +0,0 @@
1
- # =====================================================================
2
- # For a full TOML configuration guide, check the Flower docs:
3
- # https://flower.ai/docs/framework/how-to-configure-pyproject-toml.html
4
- # =====================================================================
5
-
6
- [build-system]
7
- requires = ["hatchling"]
8
- build-backend = "hatchling.build"
9
-
10
- [project]
11
- name = "$package_name"
12
- version = "1.0.0"
13
- description = ""
14
- license = "Apache-2.0"
15
- # Dependencies for your Flower App
16
- dependencies = [
17
- "flwr[simulation]>=1.24.0",
18
- "flwr-datasets>=0.5.0",
19
- "xgboost>=2.0.0",
20
- ]
21
-
22
- [tool.hatch.build.targets.wheel]
23
- packages = ["."]
24
-
25
- [tool.flwr.app]
26
- publisher = "$username"
27
-
28
- [tool.flwr.app.components]
29
- serverapp = "$import_name.server_app:app"
30
- clientapp = "$import_name.client_app:app"
31
-
32
- # Custom config values accessible via `context.run_config`
33
- [tool.flwr.app.config]
34
- num-server-rounds = 3
35
- fraction-train = 0.1
36
- fraction-evaluate = 0.1
37
- local-epochs = 1
38
-
39
- # XGBoost parameters
40
- params.objective = "binary:logistic"
41
- params.eta = 0.1 # Learning rate
42
- params.max-depth = 8
43
- params.eval-metric = "auc"
44
- params.nthread = 16
45
- params.num-parallel-tree = 1
46
- params.subsample = 1
47
- params.tree-method = "hist"
48
-
49
- # Default federation to use when running the app
50
- [tool.flwr.federations]
51
- default = "local-simulation"
52
-
53
- # Local simulation federation with 10 virtual SuperNodes
54
- [tool.flwr.federations.local-simulation]
55
- options.num-supernodes = 10
56
-
57
- # Remote federation example for use with SuperLink
58
- [tool.flwr.federations.remote-federation]
59
- address = "<SUPERLINK-ADDRESS>:<PORT>"
60
- insecure = true # Remove this line to enable TLS
61
- # root-certificates = "<PATH/TO/ca.crt>" # For TLS setup
flwr/common/pyproject.py DELETED
@@ -1,42 +0,0 @@
1
- # Copyright 2025 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
- """Validates the project's name property."""
16
-
17
-
18
- import re
19
-
20
-
21
- def validate_project_name(name: str) -> bool:
22
- """Validate the project name against PEP 621 and PEP 503 specifications.
23
-
24
- Conventions at a glance:
25
- - Must be lowercase
26
- - Must not contain special characters
27
- - Must use hyphens(recommended) or underscores. No spaces.
28
- - Recommended to be no more than 40 characters long (But it can be)
29
-
30
- Parameters
31
- ----------
32
- name : str
33
- The project name to validate.
34
-
35
- Returns
36
- -------
37
- bool
38
- True if the name is valid, False otherwise.
39
- """
40
- if not name or len(name) > 40 or not re.match(r"^[a-z0-9-_]+$", name):
41
- return False
42
- return True
@@ -1,159 +0,0 @@
1
- # Copyright 2025 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
- """Mixin providing common SQLite connection and initialization logic."""
16
-
17
-
18
- import re
19
- import sqlite3
20
- from abc import ABC
21
- from collections.abc import Sequence
22
- from logging import DEBUG, ERROR
23
- from typing import Any
24
-
25
- from flwr.common.logger import log
26
-
27
- DictOrTuple = tuple[Any, ...] | dict[str, Any]
28
-
29
-
30
- class SqliteMixin(ABC):
31
- """Mixin providing common SQLite connection and initialization logic."""
32
-
33
- def __init__(self, database_path: str) -> None:
34
- self.database_path = database_path
35
- self._conn: sqlite3.Connection | None = None
36
-
37
- @property
38
- def conn(self) -> sqlite3.Connection:
39
- """Get the SQLite connection."""
40
- if self._conn is None:
41
- raise AttributeError("Database not initialized. Call initialize() first.")
42
- return self._conn
43
-
44
- def get_sql_statements(self) -> tuple[str, ...]:
45
- """Return SQL statements for this class.
46
-
47
- Subclasses can override this to provide their SQL CREATE statements.
48
- The base implementation returns an empty tuple.
49
-
50
- Returns
51
- -------
52
- tuple[str, ...]
53
- SQL CREATE TABLE/INDEX statements for this class.
54
- """
55
- return ()
56
-
57
- def initialize(self, log_queries: bool = False) -> list[tuple[str]]:
58
- """Connect to the DB, enable FK support, and create tables if needed.
59
-
60
- This method executes SQL statements returned by `get_sql_statements()`.
61
-
62
- Parameters
63
- ----------
64
- log_queries : bool
65
- Log each query which is executed.
66
-
67
- Returns
68
- -------
69
- list[tuple[str]]
70
- The list of all tables in the DB.
71
-
72
- Examples
73
- --------
74
- Override `get_sql_statements()` in your subclass:
75
-
76
- .. code:: python
77
-
78
- def get_sql_statements(self) -> tuple[str, ...]:
79
- return (
80
- SQL_CREATE_TABLE_FOO,
81
- SQL_CREATE_TABLE_BAR,
82
- )
83
-
84
- To include parent SQL statements, call super():
85
-
86
- .. code:: python
87
-
88
- def get_sql_statements(self) -> tuple[str, ...]:
89
- return super().get_sql_statements() + (
90
- SQL_CREATE_TABLE_FOO,
91
- SQL_CREATE_TABLE_BAR,
92
- )
93
- """
94
- self._conn = sqlite3.connect(self.database_path)
95
- # Enable Write-Ahead Logging (WAL) for better concurrency
96
- self._conn.execute("PRAGMA journal_mode = WAL;")
97
- self._conn.execute("PRAGMA synchronous = NORMAL;")
98
- self._conn.execute("PRAGMA foreign_keys = ON;")
99
- self._conn.execute("PRAGMA cache_size = -64000;") # 64MB cache
100
- self._conn.execute("PRAGMA temp_store = MEMORY;") # In-memory temp tables
101
- self._conn.execute("PRAGMA mmap_size = 268435456;") # 256MB memory-mapped I/O
102
- self._conn.row_factory = dict_factory
103
-
104
- if log_queries:
105
- self._conn.set_trace_callback(lambda q: log(DEBUG, q))
106
-
107
- # Create tables and indexes
108
- cur = self._conn.cursor()
109
- for sql in self.get_sql_statements():
110
- cur.execute(sql)
111
- res = cur.execute("SELECT name FROM sqlite_schema;")
112
- return res.fetchall()
113
-
114
- def query(
115
- self,
116
- query: str,
117
- data: Sequence[DictOrTuple] | DictOrTuple | None = None,
118
- ) -> list[dict[str, Any]]:
119
- """Execute a SQL query and return the results as list of dicts."""
120
- if self._conn is None:
121
- raise AttributeError("LinkState is not initialized.")
122
-
123
- if data is None:
124
- data = []
125
-
126
- # Clean up whitespace to make the logs nicer
127
- query = re.sub(r"\s+", " ", query)
128
-
129
- try:
130
- with self._conn:
131
- if (
132
- len(data) > 0
133
- and isinstance(data, (tuple | list))
134
- and isinstance(data[0], (tuple | dict))
135
- ):
136
- rows = self._conn.executemany(query, data)
137
- else:
138
- rows = self._conn.execute(query, data)
139
-
140
- # Extract results before committing to support
141
- # INSERT/UPDATE ... RETURNING
142
- # style queries
143
- result = rows.fetchall()
144
- except KeyError as exc:
145
- log(ERROR, {"query": query, "data": data, "exception": exc})
146
-
147
- return result
148
-
149
-
150
- def dict_factory(
151
- cursor: sqlite3.Cursor,
152
- row: sqlite3.Row,
153
- ) -> dict[str, Any]:
154
- """Turn SQLite results into dicts.
155
-
156
- Less efficent for retrival of large amounts of data but easier to use.
157
- """
158
- fields = [column[0] for column in cursor.description]
159
- return dict(zip(fields, row, strict=True))
File without changes
File without changes