ddeutil-workflow 0.0.83__tar.gz → 0.0.85__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.
Files changed (64) hide show
  1. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/PKG-INFO +13 -16
  2. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/README.md +12 -15
  3. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/src/ddeutil/workflow/__about__.py +1 -1
  4. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/src/ddeutil/workflow/__init__.py +4 -4
  5. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/src/ddeutil/workflow/audits.py +8 -6
  6. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/src/ddeutil/workflow/conf.py +4 -17
  7. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/src/ddeutil/workflow/errors.py +31 -19
  8. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/src/ddeutil/workflow/job.py +276 -156
  9. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/src/ddeutil/workflow/plugins/providers/az.py +2 -2
  10. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/src/ddeutil/workflow/stages.py +700 -330
  11. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/src/ddeutil/workflow/traces.py +125 -185
  12. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/src/ddeutil/workflow/utils.py +14 -3
  13. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/src/ddeutil/workflow/workflow.py +49 -37
  14. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/src/ddeutil_workflow.egg-info/PKG-INFO +13 -16
  15. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/src/ddeutil_workflow.egg-info/SOURCES.txt +1 -1
  16. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/tests/test_audits.py +0 -1
  17. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/tests/test_conf.py +2 -2
  18. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/tests/test_job_exec.py +55 -11
  19. ddeutil_workflow-0.0.83/tests/test_job_exec_strategy.py → ddeutil_workflow-0.0.85/tests/test_job_process_strategy.py +24 -20
  20. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/tests/test_workflow.py +4 -15
  21. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/tests/test_workflow_release.py +46 -5
  22. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/LICENSE +0 -0
  23. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/pyproject.toml +0 -0
  24. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/setup.cfg +0 -0
  25. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/src/ddeutil/workflow/__cron.py +0 -0
  26. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/src/ddeutil/workflow/__main__.py +0 -0
  27. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/src/ddeutil/workflow/__types.py +0 -0
  28. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/src/ddeutil/workflow/api/__init__.py +0 -0
  29. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/src/ddeutil/workflow/api/log_conf.py +0 -0
  30. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/src/ddeutil/workflow/api/routes/__init__.py +0 -0
  31. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/src/ddeutil/workflow/api/routes/job.py +0 -0
  32. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/src/ddeutil/workflow/api/routes/logs.py +0 -0
  33. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/src/ddeutil/workflow/api/routes/workflows.py +0 -0
  34. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/src/ddeutil/workflow/event.py +0 -0
  35. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/src/ddeutil/workflow/params.py +0 -0
  36. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/src/ddeutil/workflow/plugins/__init__.py +0 -0
  37. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/src/ddeutil/workflow/plugins/providers/__init__.py +0 -0
  38. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/src/ddeutil/workflow/plugins/providers/aws.py +0 -0
  39. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/src/ddeutil/workflow/plugins/providers/container.py +0 -0
  40. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/src/ddeutil/workflow/plugins/providers/gcs.py +0 -0
  41. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/src/ddeutil/workflow/result.py +0 -0
  42. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/src/ddeutil/workflow/reusables.py +0 -0
  43. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/src/ddeutil_workflow.egg-info/dependency_links.txt +0 -0
  44. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/src/ddeutil_workflow.egg-info/entry_points.txt +0 -0
  45. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/src/ddeutil_workflow.egg-info/requires.txt +0 -0
  46. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/src/ddeutil_workflow.egg-info/top_level.txt +0 -0
  47. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/tests/test__cron.py +0 -0
  48. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/tests/test__regex.py +0 -0
  49. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/tests/test_cli.py +0 -0
  50. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/tests/test_errors.py +0 -0
  51. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/tests/test_event.py +0 -0
  52. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/tests/test_job.py +0 -0
  53. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/tests/test_params.py +0 -0
  54. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/tests/test_result.py +0 -0
  55. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/tests/test_reusables_call_tag.py +0 -0
  56. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/tests/test_reusables_func_model.py +0 -0
  57. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/tests/test_reusables_template.py +0 -0
  58. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/tests/test_reusables_template_filter.py +0 -0
  59. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/tests/test_strategy.py +0 -0
  60. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/tests/test_traces.py +0 -0
  61. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/tests/test_utils.py +0 -0
  62. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/tests/test_workflow_exec.py +0 -0
  63. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/tests/test_workflow_exec_job.py +0 -0
  64. {ddeutil_workflow-0.0.83 → ddeutil_workflow-0.0.85}/tests/test_workflow_rerun.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ddeutil-workflow
3
- Version: 0.0.83
3
+ Version: 0.0.85
4
4
  Summary: Lightweight workflow orchestration with YAML template
5
5
  Author-email: ddeutils <korawich.anu@gmail.com>
6
6
  License: MIT
@@ -303,21 +303,18 @@ it will use default value and do not raise any error to you.
303
303
  > The config value that you will set on the environment should combine with
304
304
  > prefix, component, and name which is `WORKFLOW_{component}_{name}` (Upper case).
305
305
 
306
- | Name | Component | Default | Description |
307
- |:----------------------------|:---------:|:--------------------------------------------------------------------------------------------------------------------------------|:-------------------------------------------------------------------------------------------------|
308
- | **REGISTRY_CALLER** | CORE | `.` | List of importable string for the call stage. |
309
- | **REGISTRY_FILTER** | CORE | `ddeutil.workflow.templates` | List of importable string for the filter template. |
310
- | **CONF_PATH** | CORE | `./conf` | The config path that keep all template `.yaml` files. |
311
- | **STAGE_DEFAULT_ID** | CORE | `false` | A flag that enable default stage ID that use for catch an execution output. |
312
- | **GENERATE_ID_SIMPLE_MODE** | CORE | `true` | A flog that enable generating ID with `md5` algorithm. |
313
- | **DEBUG_MODE** | LOG | `true` | A flag that enable logging with debug level mode. |
314
- | **TIMEZONE** | LOG | `Asia/Bangkok` | A Timezone string value that will pass to `ZoneInfo` object. |
315
- | **FORMAT** | LOG | `%(asctime)s.%(msecs)03d (%(name)-10s, %(process)-5d,%(thread)-5d) [%(levelname)-7s] %(message)-120s (%(filename)s:%(lineno)s)` | A trace message console format. |
316
- | **FORMAT_FILE** | LOG | `{datetime} ({process:5d}, {thread:5d}) {message:120s} ({filename}:{lineno})` | A trace message format that use to write to target pointer. |
317
- | **DATETIME_FORMAT** | LOG | `%Y-%m-%d %H:%M:%S` | A datetime format of the trace log. |
318
- | **TRACE_HANDLERS** | LOG | `[{"type": "console"}]` | A pointer URL of trace log that use to emit log message. Now uses optimized handler by default. |
319
- | **AUDIT_CONF** | LOG | `{"type": "file", "path": "./audits"}` | A pointer URL of audit log that use to write audit metrix. |
320
- | **AUDIT_ENABLE_WRITE** | LOG | `true` | A flag that enable writing audit log after end execution in the workflow release step. |
306
+ | Name | Component | Default | Description |
307
+ |:----------------------------|:---------:|:---------------------------------------|:---------------------------------------------------------------------------------------|
308
+ | **REGISTRY_CALLER** | CORE | `.` | List of importable string for the call stage. |
309
+ | **REGISTRY_FILTER** | CORE | `ddeutil.workflow.templates` | List of importable string for the filter template. |
310
+ | **CONF_PATH** | CORE | `./conf` | The config path that keep all template `.yaml` files. |
311
+ | **STAGE_DEFAULT_ID** | CORE | `false` | A flag that enable default stage ID that use for catch an execution output. |
312
+ | **GENERATE_ID_SIMPLE_MODE** | CORE | `true` | A flog that enable generating ID with `md5` algorithm. |
313
+ | **DEBUG_MODE** | LOG | `true` | A flag that enable logging with debug level mode. |
314
+ | **TIMEZONE** | LOG | `Asia/Bangkok` | A Timezone string value that will pass to `ZoneInfo` object. |
315
+ | **TRACE_HANDLERS** | LOG | `[{"type": "console"}]` | A Json string of list of trace handler config data that use to emit log message. |
316
+ | **AUDIT_CONF** | LOG | `{"type": "file", "path": "./audits"}` | A Json string of audit config data that use to write audit metrix. |
317
+ | **AUDIT_ENABLE_WRITE** | LOG | `true` | A flag that enable writing audit log after end execution in the workflow release step. |
321
318
 
322
319
  ## :rocket: Deployment
323
320
 
@@ -253,21 +253,18 @@ it will use default value and do not raise any error to you.
253
253
  > The config value that you will set on the environment should combine with
254
254
  > prefix, component, and name which is `WORKFLOW_{component}_{name}` (Upper case).
255
255
 
256
- | Name | Component | Default | Description |
257
- |:----------------------------|:---------:|:--------------------------------------------------------------------------------------------------------------------------------|:-------------------------------------------------------------------------------------------------|
258
- | **REGISTRY_CALLER** | CORE | `.` | List of importable string for the call stage. |
259
- | **REGISTRY_FILTER** | CORE | `ddeutil.workflow.templates` | List of importable string for the filter template. |
260
- | **CONF_PATH** | CORE | `./conf` | The config path that keep all template `.yaml` files. |
261
- | **STAGE_DEFAULT_ID** | CORE | `false` | A flag that enable default stage ID that use for catch an execution output. |
262
- | **GENERATE_ID_SIMPLE_MODE** | CORE | `true` | A flog that enable generating ID with `md5` algorithm. |
263
- | **DEBUG_MODE** | LOG | `true` | A flag that enable logging with debug level mode. |
264
- | **TIMEZONE** | LOG | `Asia/Bangkok` | A Timezone string value that will pass to `ZoneInfo` object. |
265
- | **FORMAT** | LOG | `%(asctime)s.%(msecs)03d (%(name)-10s, %(process)-5d,%(thread)-5d) [%(levelname)-7s] %(message)-120s (%(filename)s:%(lineno)s)` | A trace message console format. |
266
- | **FORMAT_FILE** | LOG | `{datetime} ({process:5d}, {thread:5d}) {message:120s} ({filename}:{lineno})` | A trace message format that use to write to target pointer. |
267
- | **DATETIME_FORMAT** | LOG | `%Y-%m-%d %H:%M:%S` | A datetime format of the trace log. |
268
- | **TRACE_HANDLERS** | LOG | `[{"type": "console"}]` | A pointer URL of trace log that use to emit log message. Now uses optimized handler by default. |
269
- | **AUDIT_CONF** | LOG | `{"type": "file", "path": "./audits"}` | A pointer URL of audit log that use to write audit metrix. |
270
- | **AUDIT_ENABLE_WRITE** | LOG | `true` | A flag that enable writing audit log after end execution in the workflow release step. |
256
+ | Name | Component | Default | Description |
257
+ |:----------------------------|:---------:|:---------------------------------------|:---------------------------------------------------------------------------------------|
258
+ | **REGISTRY_CALLER** | CORE | `.` | List of importable string for the call stage. |
259
+ | **REGISTRY_FILTER** | CORE | `ddeutil.workflow.templates` | List of importable string for the filter template. |
260
+ | **CONF_PATH** | CORE | `./conf` | The config path that keep all template `.yaml` files. |
261
+ | **STAGE_DEFAULT_ID** | CORE | `false` | A flag that enable default stage ID that use for catch an execution output. |
262
+ | **GENERATE_ID_SIMPLE_MODE** | CORE | `true` | A flog that enable generating ID with `md5` algorithm. |
263
+ | **DEBUG_MODE** | LOG | `true` | A flag that enable logging with debug level mode. |
264
+ | **TIMEZONE** | LOG | `Asia/Bangkok` | A Timezone string value that will pass to `ZoneInfo` object. |
265
+ | **TRACE_HANDLERS** | LOG | `[{"type": "console"}]` | A Json string of list of trace handler config data that use to emit log message. |
266
+ | **AUDIT_CONF** | LOG | `{"type": "file", "path": "./audits"}` | A Json string of audit config data that use to write audit metrix. |
267
+ | **AUDIT_ENABLE_WRITE** | LOG | `true` | A flag that enable writing audit log after end execution in the workflow release step. |
271
268
 
272
269
  ## :rocket: Deployment
273
270
 
@@ -1,2 +1,2 @@
1
- __version__: str = "0.0.83"
1
+ __version__: str = "0.0.85"
2
2
  __python_version__: str = "3.9"
@@ -107,10 +107,10 @@ from .job import (
107
107
  Rule,
108
108
  RunsOnModel,
109
109
  Strategy,
110
- docker_execution,
111
- local_execute,
112
- local_execute_strategy,
113
- self_hosted_execute,
110
+ docker_process,
111
+ local_process,
112
+ local_process_strategy,
113
+ self_hosted_process,
114
114
  )
115
115
  from .params import (
116
116
  ArrayParam,
@@ -60,7 +60,7 @@ from typing_extensions import Self
60
60
 
61
61
  from .__types import DictData
62
62
  from .conf import dynamic
63
- from .traces import Trace, get_trace, set_logging
63
+ from .traces import Trace, get_trace
64
64
 
65
65
  logger = logging.getLogger("ddeutil.workflow")
66
66
 
@@ -129,7 +129,6 @@ class BaseAudit(BaseModel, ABC):
129
129
  """
130
130
 
131
131
  type: Literal["base"] = "base"
132
- logging_name: str = "ddeutil.workflow"
133
132
  extras: DictData = Field(
134
133
  default_factory=dict,
135
134
  description="An extras parameter that want to override core config",
@@ -152,9 +151,6 @@ class BaseAudit(BaseModel, ABC):
152
151
  """
153
152
  if dynamic("enable_write_audit", extras=self.extras):
154
153
  self.do_before()
155
-
156
- # NOTE: Start setting log config in this line with cache.
157
- set_logging(self.logging_name)
158
154
  return self
159
155
 
160
156
  @abstractmethod
@@ -795,7 +791,13 @@ Audit = Annotated[
795
791
  LocalFileAudit,
796
792
  LocalSQLiteAudit,
797
793
  ],
798
- Field(discriminator="type"),
794
+ Field(
795
+ discriminator="type",
796
+ description=(
797
+ "An union of supported Audit model that have inherited from "
798
+ "BaseAudit."
799
+ ),
800
+ ),
799
801
  ]
800
802
 
801
803
 
@@ -101,7 +101,8 @@ class Config: # pragma: no cov
101
101
  """Register Filter that is a list of importable string for the filter
102
102
  template.
103
103
 
104
- :rtype: list[str]
104
+ Returns:
105
+ list[str]: A list of module import string.
105
106
  """
106
107
  regis_filter_str: str = env(
107
108
  "CORE_REGISTRY_FILTER", "ddeutil.workflow.templates"
@@ -130,17 +131,6 @@ class Config: # pragma: no cov
130
131
  """
131
132
  return ZoneInfo(env("LOG_TIMEZONE", "UTC"))
132
133
 
133
- @property
134
- def log_format(self) -> str:
135
- return env(
136
- "LOG_FORMAT",
137
- (
138
- "%(asctime)s.%(msecs)03d (%(process)-5d, "
139
- "%(thread)-5d) [%(levelname)-7s] (%(cut_id)s) %(message)-120s "
140
- "(%(filename)s:%(lineno)s) (%(name)-10s)"
141
- ),
142
- )
143
-
144
134
  @property
145
135
  def audit_conf(self) -> dict[str, Any]:
146
136
  return json.loads(
@@ -151,10 +141,6 @@ class Config: # pragma: no cov
151
141
  def enable_write_audit(self) -> bool:
152
142
  return str2bool(env("LOG_AUDIT_ENABLE_WRITE", "false"))
153
143
 
154
- @property
155
- def log_datetime_format(self) -> str:
156
- return env("LOG_DATETIME_FORMAT", "%Y-%m-%d %H:%M:%S")
157
-
158
144
  @property
159
145
  def stage_default_id(self) -> bool:
160
146
  return str2bool(env("CORE_STAGE_DEFAULT_ID", "false"))
@@ -441,7 +427,8 @@ class YamlParser:
441
427
  """Return object of string type which implement on any registry. The
442
428
  object type.
443
429
 
444
- :rtype: str
430
+ Returns:
431
+ str: A type that get from config data.
445
432
  """
446
433
  if _typ := self.data.get("type"):
447
434
  return _typ
@@ -8,17 +8,6 @@
8
8
  This module provides a comprehensive exception hierarchy for the workflow system.
9
9
  The exceptions are designed to be lightweight while providing sufficient context
10
10
  for error handling and debugging.
11
-
12
- Classes:
13
- BaseError: Base exception class with context support
14
- StageError: Exceptions related to stage execution
15
- JobError: Exceptions related to job execution
16
- WorkflowError: Exceptions related to workflow execution
17
- ParamError: Exceptions related to parameter validation
18
- ResultError: Exceptions related to result processing
19
-
20
- Functions:
21
- to_dict: Convert exception instances to dictionary format
22
11
  """
23
12
  from __future__ import annotations
24
13
 
@@ -58,11 +47,13 @@ def to_dict(exception: Exception, **kwargs) -> ErrorData: # pragma: no cov
58
47
  Example:
59
48
  >>> try:
60
49
  >>> raise ValueError("Something went wrong")
61
- >>> except Exception as e:
62
- >>> error_data = to_dict(e, context="workflow_execution")
63
- >>> # Returns: {
64
- >>> # "name": "ValueError", "message": "Something went wrong", "context": "workflow_execution"
65
- >>> # }
50
+ >>> except Exception as err:
51
+ >>> error_data = to_dict(err, context="workflow_execution")
52
+ {
53
+ "name": "ValueError",
54
+ "message": "Something went wrong",
55
+ "context": "workflow_execution",
56
+ }
66
57
  """
67
58
  return {
68
59
  "name": exception.__class__.__name__,
@@ -71,6 +62,20 @@ def to_dict(exception: Exception, **kwargs) -> ErrorData: # pragma: no cov
71
62
  }
72
63
 
73
64
 
65
+ def mark_errors(context: DictData, error: JobError) -> None:
66
+ """Make the errors context result with the refs value depends on the nested
67
+ execute func.
68
+
69
+ Args:
70
+ context (DictData): A context data.
71
+ error (JobError): A stage exception object.
72
+ """
73
+ if "errors" in context:
74
+ context["errors"][error.refs] = error.to_dict()
75
+ else:
76
+ context["errors"] = error.to_dict(with_refs=True)
77
+
78
+
74
79
  class BaseError(Exception):
75
80
  """Base exception class for all workflow-related errors.
76
81
 
@@ -80,9 +85,14 @@ class BaseError(Exception):
80
85
  for debugging purposes.
81
86
 
82
87
  Attributes:
83
- refs: Optional reference identifier for error correlation
84
- context: Additional context data related to the error
85
- params: Parameter data that was being processed when error occurred
88
+ refs (str | int, default None): Optional reference identifier for error
89
+ correlation
90
+ context (DictData, default None): Additional context data related to the
91
+ error
92
+ params (DictData, default None): Parameter data that was being processed
93
+ when error occurred
94
+ allow_traceback (bool, default True): A flag for printing traceback
95
+ after it catch this object.
86
96
 
87
97
  Example:
88
98
  >>> try:
@@ -100,11 +110,13 @@ class BaseError(Exception):
100
110
  refs: Optional[StrOrInt] = None,
101
111
  context: Optional[DictData] = None,
102
112
  params: Optional[DictData] = None,
113
+ allow_traceback: bool = True,
103
114
  ) -> None:
104
115
  super().__init__(message)
105
116
  self.refs: Optional[str] = refs
106
117
  self.context: DictData = context or {}
107
118
  self.params: DictData = params or {}
119
+ self.allow_traceback: bool = allow_traceback
108
120
 
109
121
  @overload
110
122
  def to_dict(