mantatech-sdk 0.5b0.dev65__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 (54) hide show
  1. manta/__init__.light.py +22 -0
  2. manta/__init__.py +83 -0
  3. manta/__main__.py +21 -0
  4. manta/apis/__init__.py +7 -0
  5. manta/apis/async_user_api.py +6458 -0
  6. manta/apis/graph.py +498 -0
  7. manta/apis/module.py +316 -0
  8. manta/apis/results.py +251 -0
  9. manta/apis/swarm.py +206 -0
  10. manta/apis/user_api.py +1016 -0
  11. manta/cli/__init__.py +1 -0
  12. manta/cli/commands/__init__.py +1 -0
  13. manta/cli/commands/base_handler.py +229 -0
  14. manta/cli/commands/doc.py +192 -0
  15. manta/cli/commands/install.py +346 -0
  16. manta/cli/commands/sdk.py +9 -0
  17. manta/cli/commands/sdk_cluster.py +211 -0
  18. manta/cli/commands/sdk_config.py +347 -0
  19. manta/cli/commands/sdk_globals.py +280 -0
  20. manta/cli/commands/sdk_logs.py +174 -0
  21. manta/cli/commands/sdk_main.py +167 -0
  22. manta/cli/commands/sdk_module.py +516 -0
  23. manta/cli/commands/sdk_nodes.py +168 -0
  24. manta/cli/commands/sdk_original.py +3873 -0
  25. manta/cli/commands/sdk_results.py +265 -0
  26. manta/cli/commands/sdk_swarm.py +454 -0
  27. manta/cli/commands/sdk_user.py +234 -0
  28. manta/cli/commands/status.py +292 -0
  29. manta/cli/component_detector.py +112 -0
  30. manta/cli/config_manager.py +445 -0
  31. manta/cli/main.py +265 -0
  32. manta/cli/utils/__init__.py +27 -0
  33. manta/cli/utils/converters.py +140 -0
  34. manta/clients/cluster_management_client.py +486 -0
  35. manta/clients/local_client.py +149 -0
  36. manta/clients/module_management_client.py +217 -0
  37. manta/clients/swarm_management_client.py +562 -0
  38. manta/clients/user_management_client.py +395 -0
  39. manta/clients/world_client.py +195 -0
  40. manta/light/__init__.py +31 -0
  41. manta/light/globals.py +245 -0
  42. manta/light/local.py +407 -0
  43. manta/light/logging_config.py +39 -0
  44. manta/light/path.py +116 -0
  45. manta/light/results.py +236 -0
  46. manta/light/task.py +100 -0
  47. manta/light/utils.py +217 -0
  48. manta/light/world.py +177 -0
  49. mantatech_sdk-0.5b0.dev65.dist-info/METADATA +1039 -0
  50. mantatech_sdk-0.5b0.dev65.dist-info/RECORD +54 -0
  51. mantatech_sdk-0.5b0.dev65.dist-info/WHEEL +5 -0
  52. mantatech_sdk-0.5b0.dev65.dist-info/entry_points.txt +2 -0
  53. mantatech_sdk-0.5b0.dev65.dist-info/licenses/LICENSE +683 -0
  54. mantatech_sdk-0.5b0.dev65.dist-info/top_level.txt +1 -0
manta/light/globals.py ADDED
@@ -0,0 +1,245 @@
1
+ import io
2
+ import logging
3
+ import os
4
+ from typing import AsyncIterable, Optional
5
+
6
+ import grpclib.exceptions
7
+
8
+ from ..clients.world_client import WorldClient
9
+ from manta_common.build.node.light_service import GetGlobalRequest, SetGlobalRequest
10
+ from manta_common.const import CHUNK_SIZE
11
+ from manta_common.conversions import ID
12
+ from manta_common.event_loop import EventLoopManager
13
+ from .utils import bytes_to_dict, dict_to_bytes
14
+
15
+ __all__ = ["Globals"]
16
+
17
+
18
+ class Globals:
19
+ """
20
+ Class which deals with global manipulation (getter and setter)
21
+
22
+ Parameters
23
+ ----------
24
+ host : str
25
+ Manager host
26
+ port : int
27
+ Manager port
28
+ task_id : ID
29
+ Task ID
30
+ swarm_id : ID
31
+ Swarm ID
32
+ chunk_size : int
33
+ Chunk size
34
+ """
35
+
36
+ __slots__ = [
37
+ "world_client",
38
+ "swarm_id",
39
+ "task_id",
40
+ "logger",
41
+ "chunk_size",
42
+ "_loop",
43
+ "_loop_lock",
44
+ "loop_manager",
45
+ ]
46
+
47
+ def __init__(
48
+ self,
49
+ world_client: Optional[WorldClient] = None,
50
+ host: Optional[str] = None,
51
+ port: Optional[int] = None,
52
+ swarm_id: Optional[ID] = None,
53
+ task_id: Optional[ID] = None,
54
+ chunk_size: int = CHUNK_SIZE,
55
+ ):
56
+ # Retrieve env variables for RPC host and port
57
+ if world_client is None:
58
+ self.world_client = WorldClient(
59
+ host=host or os.getenv("RPC_HOST", "host.docker.internal"),
60
+ port=int(port or os.getenv("RPC_PORT", 50051)),
61
+ )
62
+ else:
63
+ self.world_client = world_client
64
+
65
+ self.task_id: ID = task_id or ID(os.getenv("TASK_ID"))
66
+ self.swarm_id: ID = swarm_id or ID(os.getenv("SWARM_ID"))
67
+
68
+ self.chunk_size = chunk_size
69
+
70
+ self.logger = logging.getLogger(__name__)
71
+
72
+ self.loop_manager = EventLoopManager.get_instance()
73
+
74
+ def __getitem__(self, tag: str):
75
+ """
76
+ Get the results of a Task
77
+
78
+ Parameters
79
+ ----------
80
+ tag : str
81
+ The tag of the result to get
82
+
83
+ Returns
84
+ -------
85
+ dict
86
+ The response from the world service
87
+
88
+ Examples
89
+ --------
90
+
91
+ Inside a :class:`Task <manta_light.task.Task>` class, you can
92
+ access globals defined by a :class:`Swarm <manta.swarm.Swarm>`
93
+ by using the attribute :code:`self.world` automatically defined
94
+ by :class:`Task <manta_light.task.Task>`:
95
+
96
+ >>> weights = self.world.globals["global_model_params"]
97
+ """
98
+ return self.loop_manager.run_coroutine(self.async_get(tag))
99
+
100
+ def __setitem__(self, tag: str, result: dict):
101
+ """
102
+ Set a result of a task
103
+
104
+ Parameters
105
+ ----------
106
+ tag : str
107
+ The tag of the result to set
108
+ result : dict
109
+ The result to set
110
+
111
+ Examples
112
+ --------
113
+
114
+ Inside a :class:`Task <manta_light.task.Task>` class, you can
115
+ change globals defined by a :class:`Swarm <manta.swarm.Swarm>`
116
+ by using the attribute :code:`self.world` automatically defined
117
+ by :class:`Task <manta_light.task.Task>`:
118
+
119
+ >>> self.world.globals["global_model_params"] = new_weights
120
+ """
121
+ self.loop_manager.run_coroutine(self.async_set(tag, result))
122
+
123
+ def __str__(self): # pragma: no cover
124
+ return f"Globals(host={self.world_client.host}, port={self.world_client.port}, swarm_id={self.swarm_id}, task_id={self.task_id})"
125
+
126
+ def __repr__(self): # pragma: no cover
127
+ return str(self)
128
+
129
+ # Asynchonous methods
130
+
131
+ async def async_get(self, tag: str):
132
+ """
133
+ Get the results of tasks
134
+
135
+ Parameters
136
+ ----------
137
+ tag : str
138
+ The tag of the result to get
139
+
140
+ Returns
141
+ -------
142
+ dict
143
+ The response from the world service
144
+
145
+ Examples
146
+ --------
147
+
148
+ Same as :meth:`__getitem__ <manta_light.globals.Globals.__getitem__>`
149
+ but asynchronous.
150
+
151
+ >>> weights = await self.world.globals.async_get(
152
+ ... "global_model_params"
153
+ ... )
154
+ """
155
+ # Initialize a buffer to accumulate chunks
156
+ buffer = io.BytesIO()
157
+
158
+ self.logger.info(
159
+ f"Getting global '{tag}' for task {self.task_id} and swarm {self.swarm_id}"
160
+ )
161
+ try:
162
+ # Iterate over the chunks
163
+ async for chunk in self.world_client.get_global(
164
+ GetGlobalRequest(
165
+ task_id=self.task_id.oid, swarm_id=self.swarm_id.oid, tag=tag
166
+ )
167
+ ):
168
+ self.logger.debug(
169
+ f"Received chunk for global '{tag}' of size {len(chunk.data)}"
170
+ )
171
+ # Append the chunk to the buffer
172
+ buffer.write(chunk.data)
173
+
174
+ self.logger.info(f"Successfully received all chunks for global '{tag}'")
175
+ return bytes_to_dict(buffer.getvalue())
176
+ except grpclib.exceptions.GRPCError as e:
177
+ self.logger.error(
178
+ f"GRPC error while getting global '{tag}': {e!r}", exc_info=True
179
+ )
180
+ raise # Re-raise the original gRPC error
181
+ except Exception as e:
182
+ # This catches other potential errors, e.g., from bytes_to_dict if the stream was successful
183
+ # but data was malformed, or other unexpected errors within this block.
184
+ self.logger.error(
185
+ f"Failed to process global '{tag}' after fetching: {e!r}", exc_info=True
186
+ )
187
+ raise
188
+
189
+ async def chunked_global_update(
190
+ self, request: SetGlobalRequest
191
+ ) -> AsyncIterable[SetGlobalRequest]:
192
+ """
193
+ This function chunks the data into smaller pieces and yields GlobalUpdate messages.
194
+
195
+ Parameters
196
+ ----------
197
+ request : SetGlobalRequest
198
+ Set global request
199
+
200
+ Returns
201
+ -------
202
+ AsyncIterable[SetGlobalRequest]
203
+ Async iterable of SetGlobalRequest messages
204
+ """
205
+ data_stream = io.BytesIO(request.data)
206
+ while chunk := data_stream.read(self.chunk_size):
207
+ yield SetGlobalRequest(
208
+ task_id=request.task_id,
209
+ swarm_id=request.swarm_id,
210
+ tag=request.tag,
211
+ data=chunk,
212
+ )
213
+
214
+ async def async_set(self, tag: str, result: dict):
215
+ """
216
+ Set a result of a task
217
+
218
+ Parameters
219
+ ----------
220
+ tag : str
221
+ The tag of the result to set
222
+ result : dict
223
+ The result to set
224
+
225
+ Examples
226
+ --------
227
+
228
+ Same as :meth:`__setitem__ <manta_light.globals.Globals.__setitem__>`
229
+ but asynchronous.
230
+
231
+ >>> await self.world.globals.async_set(
232
+ ... "global_model_params",
233
+ ... new_weights
234
+ ... )
235
+ """
236
+ await self.world_client.set_global(
237
+ self.chunked_global_update(
238
+ SetGlobalRequest(
239
+ task_id=self.task_id.oid,
240
+ swarm_id=self.swarm_id.oid,
241
+ tag=tag,
242
+ data=dict_to_bytes(result),
243
+ )
244
+ )
245
+ )
manta/light/local.py ADDED
@@ -0,0 +1,407 @@
1
+ import io
2
+ import logging
3
+ import os
4
+ from typing import TYPE_CHECKING, Optional, Union
5
+
6
+ if TYPE_CHECKING:
7
+ import numpy
8
+
9
+ from ..clients.local_client import LocalClient
10
+ from manta_common.build.node.light_service import (
11
+ DataRequest,
12
+ DirRequest,
13
+ ListDirResponse,
14
+ ProtoPath,
15
+ ReadText,
16
+ )
17
+ from manta_common.conversions import ID
18
+ from manta_common.event_loop import EventLoopManager
19
+ from .logging_config import configure_logging
20
+
21
+ __all__ = ["Local"]
22
+
23
+ configure_logging()
24
+
25
+
26
+ class Local:
27
+ """
28
+ Local service for accessing local data securely
29
+
30
+ The :code:`Local` service allows the user to get local data.
31
+
32
+ Parameters should not be fulfill manually. Instead, it is managed during the
33
+ deployment of the task by the :code:`Node`.
34
+
35
+ Parameters
36
+ ----------
37
+ host : Optional[str]
38
+ Manager host
39
+ port : Optional[int]
40
+ Manager port
41
+ swarm_id : Optional[ID]
42
+ Swarm ID
43
+ task_id : Optional[ID]
44
+ Task ID
45
+ """
46
+
47
+ __slots__ = ["swarm_id", "task_id", "logger", "local_client", "loop_manager"]
48
+
49
+ def __init__(
50
+ self,
51
+ host: Optional[str] = None,
52
+ port: Optional[int] = None,
53
+ swarm_id: Optional[ID] = None,
54
+ task_id: Optional[ID] = None,
55
+ ):
56
+ # Retrieve env variables for RPC host and port
57
+ self.task_id: ID = task_id or ID(os.getenv("TASK_ID"))
58
+ self.swarm_id: ID = swarm_id or ID(os.getenv("SWARM_ID"))
59
+
60
+ self.loop_manager = EventLoopManager.get_instance()
61
+ self.local_client = LocalClient(
62
+ host=host or os.getenv("RPC_HOST", "host.docker.internal"),
63
+ port=int(port or os.getenv("RPC_PORT", 50051)),
64
+ )
65
+
66
+ self.logger = logging.getLogger(__name__)
67
+
68
+ self.logger.info(
69
+ f"Local configured with Host: {self.local_client.host}, Port: {self.local_client.port},"
70
+ f" Task ID: {self.task_id.xid},"
71
+ f" Swarm ID: {self.swarm_id.xid}"
72
+ )
73
+
74
+ def get_numpy_data(self, dataset_name: Union[str, ProtoPath]) -> "numpy.ndarray": # type: ignore
75
+ """
76
+ Get the numpy data
77
+
78
+ Parameters
79
+ ----------
80
+ dataset_name : Union[str, ProtoPath]
81
+ The name of the dataset to get
82
+
83
+ Returns
84
+ -------
85
+ numpy.ndarray
86
+ The numpy data
87
+
88
+ Examples
89
+ --------
90
+
91
+ Inside a :class:`Task <manta_light.task.Task>` class, you can
92
+ access to local data by using the attribute :code:`self.local`
93
+ automatically created by :class:`Task <manta_light.task.Task>`:
94
+
95
+ >>> mnist_data = self.local.get_numpy_data("mnist.npz")
96
+ """
97
+ return self.loop_manager.run_coroutine(self.async_get_numpy_data(dataset_name))
98
+
99
+ def get_binary_data(self, dataset_name: Union[str, ProtoPath]) -> io.BytesIO:
100
+ """
101
+ Get the binary data
102
+
103
+ Parameters
104
+ ----------
105
+ dataset_name : Union[str, ProtoPath]
106
+ The name of the dataset to get
107
+
108
+ Returns
109
+ -------
110
+ io.BytesIO
111
+ The binary data
112
+
113
+ Examples
114
+ --------
115
+
116
+ Inside a :class:`Task <manta_light.task.Task>` class, you can
117
+ access to local data by using the attribute :code:`self.local`
118
+ automatically created by :class:`Task <manta_light.task.Task>`:
119
+
120
+ >>> mnist_data = self.local.get_binary_data("mnist.npz")
121
+ >>> data = np.load(mnist_data)
122
+ """
123
+ return self.loop_manager.run_coroutine(self.async_get_binary_data(dataset_name))
124
+
125
+ def list_dir(self, directory: Union[str, ProtoPath]) -> ListDirResponse:
126
+ """
127
+ List directories
128
+
129
+ Parameters
130
+ ----------
131
+ directory : Union[str, ProtoPath]
132
+ Directory name
133
+
134
+ Returns
135
+ -------
136
+ ListDirResponse
137
+ List of directories
138
+
139
+ Examples
140
+ --------
141
+
142
+ Inside a :class:`Task <manta_light.task.Task>` class, you can
143
+ access to local data by using the attribute :code:`self.local`
144
+ automatically created by :class:`Task <manta_light.task.Task>`:
145
+
146
+ >>> images = self.local.list_dir("images")
147
+ >>> print(images)
148
+ >>> ListDirResponse(
149
+ >>> paths=[ProtoPath("image1.jpg", is_file=True), ProtoPath("image2.jpg", is_file=True)]
150
+ >>> )
151
+ """
152
+ if isinstance(directory, str):
153
+ proto_path = ProtoPath(name=directory, value="")
154
+ else:
155
+ proto_path = directory
156
+ return self.loop_manager.run_coroutine(self.async_list_dir(proto_path))
157
+
158
+ def read_file_lines(
159
+ self,
160
+ file_name: Union[str, ProtoPath],
161
+ encoding: Optional[str] = None,
162
+ errors: Optional[str] = None,
163
+ newline: Optional[str] = None,
164
+ ) -> io.StringIO:
165
+ """
166
+ Read file lines
167
+
168
+ Parameters
169
+ ----------
170
+ file_name : Union[str, ProtoPath]
171
+ File name
172
+ encoding : str, optional
173
+ Encoding, by default None
174
+ errors : str, optional
175
+ Errors, by default None
176
+ newline : str, optional
177
+ Newline, by default None
178
+
179
+ Returns
180
+ -------
181
+ io.StringIO
182
+ String data
183
+
184
+ Examples
185
+ --------
186
+
187
+ Inside a :class:`Task <manta_light.task.Task>` class, you can
188
+ access to local data by using the attribute :code:`self.local`
189
+ automatically created by :class:`Task <manta_light.task.Task>`:
190
+
191
+ >>> text = self.local.read_file_lines("text.txt")
192
+ >>> print(text)
193
+ >>> io.StringIO("Hello world")
194
+ """
195
+ if isinstance(file_name, str):
196
+ proto_path = ProtoPath(name=file_name, value="")
197
+ else:
198
+ proto_path = file_name
199
+ return self.loop_manager.run_coroutine(
200
+ self.async_read_file_lines(proto_path, encoding, errors, newline)
201
+ )
202
+
203
+ def exists(self, file_name: Union[str, ProtoPath]) -> bool:
204
+ """
205
+ Check if a file exists
206
+
207
+ Parameters
208
+ ----------
209
+ file_name : Union[str, ProtoPath]
210
+ File name
211
+
212
+ Returns
213
+ -------
214
+ bool
215
+ True if the file exists, False otherwise
216
+
217
+ Examples
218
+ --------
219
+
220
+ Inside a :class:`Task <manta_light.task.Task>` class, you can
221
+ access to local data by using the attribute :code:`self.local`
222
+ automatically created by :class:`Task <manta_light.task.Task>`:
223
+
224
+ >>> if self.local.exists("text.txt"):
225
+ >>> print("File exists")
226
+ >>> else:
227
+ >>> print("File does not exist")
228
+ """
229
+ if isinstance(file_name, str):
230
+ proto_path = ProtoPath(name=file_name, value="")
231
+ else:
232
+ proto_path = file_name
233
+ return self.loop_manager.run_coroutine(self.async_exists(proto_path))
234
+
235
+ def __str__(self): # pragma: no cover
236
+ return f"Local(host={self.local_client.host}, port={self.local_client.port}, task_id={self.task_id}, swarm_id={self.swarm_id})"
237
+
238
+ def __repr__(self): # pragma: no cover
239
+ return str(self)
240
+
241
+ # Asynchronous methods
242
+
243
+ async def async_get_numpy_data(
244
+ self, dataset_name: Union[str, ProtoPath]
245
+ ) -> "numpy.ndarray": # type: ignore
246
+ """
247
+ Get Numpy Data
248
+
249
+ Parameters
250
+ ----------
251
+ dataset_name : Union[str, ProtoPath]
252
+ Dataset name
253
+
254
+ Returns
255
+ -------
256
+ numpy.ndarray
257
+ Numpy data
258
+
259
+ Examples
260
+ --------
261
+
262
+ Same as :meth:`get_numpy_data <manta_light.local.Local.get_numpy_data>`
263
+ but asynchronous:
264
+
265
+ >>> mnist_data = await self.local.async_get_numpy_data("mnist.npz")
266
+ """
267
+ try:
268
+ import numpy as np
269
+ except ImportError:
270
+ raise ImportError("numpy is not installed")
271
+
272
+ buffer = await self.async_get_binary_data(dataset_name)
273
+ return np.load(buffer)
274
+
275
+ async def async_get_binary_data(
276
+ self, dataset_name: Union[str, ProtoPath]
277
+ ) -> io.BytesIO:
278
+ """
279
+ Asynchronously get binary data
280
+
281
+ Parameters
282
+ ----------
283
+ dataset_name : Union[str, ProtoPath]
284
+ Dataset name
285
+
286
+ Returns
287
+ -------
288
+ io.BytesIO
289
+ Binary data
290
+
291
+ Examples
292
+ --------
293
+
294
+ Same as :meth:`get_binary_data <manta_light.local.Local.get_binary_data>`
295
+ but asynchronous:
296
+
297
+ >>> mnist_data = await self.local.async_get_binary_data("mnist.npz")
298
+ >>> data = np.load(mnist_data)
299
+ """
300
+ if isinstance(dataset_name, str):
301
+ name = dataset_name
302
+ else:
303
+ name = dataset_name.name
304
+
305
+ # Get binary data and convert to BytesIO for numpy.load
306
+ buffer = io.BytesIO()
307
+ async for chunk in self.local_client.get_binary_data(
308
+ DataRequest(
309
+ task_id=self.task_id.oid, swarm_id=self.swarm_id.oid, name=name
310
+ ),
311
+ ):
312
+ buffer.write(chunk.content)
313
+ buffer.seek(0)
314
+ return buffer
315
+
316
+ async def async_list_dir(self, directory: ProtoPath) -> ListDirResponse:
317
+ """
318
+ List directories
319
+
320
+ Parameters
321
+ ----------
322
+ directory : ProtoPath
323
+ Directory name
324
+
325
+ Returns
326
+ -------
327
+ ListDirResponse
328
+ List of directories
329
+ """
330
+ return await self.local_client.list_dir(
331
+ DirRequest(
332
+ data_request=DataRequest(
333
+ task_id=self.task_id.oid,
334
+ swarm_id=self.swarm_id.oid,
335
+ name=directory.name,
336
+ ),
337
+ path=directory.value,
338
+ ),
339
+ )
340
+
341
+ async def async_read_file_lines(
342
+ self,
343
+ file_name: ProtoPath,
344
+ encoding: Optional[str] = None,
345
+ errors: Optional[str] = None,
346
+ newline: Optional[str] = None,
347
+ ) -> io.StringIO:
348
+ """
349
+ Read file lines
350
+
351
+ Parameters
352
+ ----------
353
+ file_name : ProtoPath
354
+ File name
355
+ encoding : Optional[str], optional
356
+ Encoding, by default None
357
+ errors : Optional[str], optional
358
+ Errors, by default None
359
+ newline : Optional[str], optional
360
+ Newline, by default None
361
+
362
+ Returns
363
+ -------
364
+ io.StringIO
365
+ String data
366
+ """
367
+ buffer = io.StringIO()
368
+ async for chunk in self.local_client.read_file_lines(
369
+ ReadText(
370
+ data_request=DataRequest(
371
+ task_id=self.task_id.oid,
372
+ swarm_id=self.swarm_id.oid,
373
+ name=file_name.name,
374
+ ),
375
+ path=file_name,
376
+ encoding="" if encoding is None else encoding,
377
+ errors="" if errors is None else errors,
378
+ newline="" if newline is None else newline,
379
+ ),
380
+ ):
381
+ buffer.write(chunk.content.decode())
382
+ buffer.seek(0)
383
+ return buffer
384
+
385
+ async def async_exists(self, path: ProtoPath) -> bool:
386
+ """
387
+ Check if a file exists
388
+
389
+ Parameters
390
+ ----------
391
+ path : ProtoPath
392
+ Path
393
+
394
+ Returns
395
+ -------
396
+ bool
397
+ True if exists
398
+ """
399
+ response = await self.local_client.exists(
400
+ DirRequest(
401
+ data_request=DataRequest(
402
+ task_id=self.task_id.oid, swarm_id=self.swarm_id.oid, name=path.name
403
+ ),
404
+ path=path.value,
405
+ ),
406
+ )
407
+ return response.value
@@ -0,0 +1,39 @@
1
+ import logging
2
+ import logging.config
3
+
4
+ FORMAT = (
5
+ "%(asctime)s - %(name)s - %(levelname)s - %(message)s (%(filename)s:%(lineno)d)"
6
+ )
7
+
8
+ MANTA_LOGGING_CONFIG = {
9
+ "version": 1,
10
+ "disable_existing_loggers": False,
11
+ "formatters": {
12
+ "standard": {"format": FORMAT},
13
+ },
14
+ "filters": {
15
+ "warnings_and_below": {
16
+ "()": "manta_common.logging_config.filter_maker",
17
+ "level": "WARNING",
18
+ },
19
+ "manta_filter": {
20
+ "()": "manta_common.logging_config.filter_manta",
21
+ "level": "INFO",
22
+ },
23
+ },
24
+ "handlers": {
25
+ "default": {
26
+ "class": "logging.StreamHandler",
27
+ "level": "INFO",
28
+ "formatter": "standard",
29
+ },
30
+ },
31
+ "root": {
32
+ "level": "DEBUG",
33
+ "handlers": ["default"],
34
+ },
35
+ }
36
+
37
+
38
+ def configure_logging():
39
+ logging.config.dictConfig(MANTA_LOGGING_CONFIG)