dotflow 0.8.2.dev1__tar.gz → 0.9.0.dev1__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.
- {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/PKG-INFO +2 -2
- {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/README.md +1 -1
- {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/__init__.py +1 -1
- dotflow-0.9.0.dev1/dotflow/cli/command.py +14 -0
- {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/cli/commands/__init__.py +2 -2
- dotflow-0.9.0.dev1/dotflow/cli/commands/init.py +19 -0
- dotflow-0.9.0.dev1/dotflow/cli/commands/log.py +21 -0
- {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/cli/commands/start.py +2 -6
- {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/cli/setup.py +21 -19
- {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/cli/validators/start.py +1 -1
- {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/core/action.py +2 -1
- dotflow-0.9.0.dev1/dotflow/core/config.py +21 -0
- {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/core/decorators/time.py +1 -1
- {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/core/exception.py +18 -4
- {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/core/execution.py +4 -4
- {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/core/module.py +3 -1
- {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/core/task.py +165 -67
- dotflow-0.9.0.dev1/dotflow/core/types/__init__.py +10 -0
- {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/core/workflow.py +2 -2
- dotflow-0.8.2.dev1/dotflow/log.py → dotflow-0.9.0.dev1/dotflow/logging.py +6 -6
- dotflow-0.9.0.dev1/dotflow/settings.py +19 -0
- dotflow-0.9.0.dev1/dotflow/utils/__init__.py +17 -0
- dotflow-0.9.0.dev1/dotflow/utils/tools.py +47 -0
- {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/pyproject.toml +2 -2
- dotflow-0.8.2.dev1/dotflow/cli/command.py +0 -10
- dotflow-0.8.2.dev1/dotflow/cli/commands/init.py +0 -16
- dotflow-0.8.2.dev1/dotflow/cli/commands/server.py +0 -9
- dotflow-0.8.2.dev1/dotflow/core/config.py +0 -18
- dotflow-0.8.2.dev1/dotflow/core/models/__init__.py +0 -10
- dotflow-0.8.2.dev1/dotflow/core/utils/__init__.py +0 -15
- dotflow-0.8.2.dev1/dotflow/core/utils/tools.py +0 -26
- dotflow-0.8.2.dev1/dotflow/settings.py +0 -9
- {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/LICENSE +0 -0
- {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/abc/__init__.py +0 -0
- {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/abc/file.py +0 -0
- {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/abc/http.py +0 -0
- {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/abc/tcp.py +0 -0
- {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/cli/__init__.py +0 -0
- {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/cli/validators/__init__.py +0 -0
- {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/core/__init__.py +0 -0
- {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/core/context.py +0 -0
- {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/core/decorators/__init__.py +0 -0
- {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/core/decorators/action.py +0 -0
- {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/core/decorators/retry.py +0 -0
- {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/core/dotflow.py +0 -0
- {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/core/serializers/__init__.py +0 -0
- {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/core/serializers/task.py +0 -0
- {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/core/serializers/transport.py +0 -0
- {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/core/serializers/workflow.py +0 -0
- {dotflow-0.8.2.dev1/dotflow/core/models → dotflow-0.9.0.dev1/dotflow/core/types}/execution.py +0 -0
- {dotflow-0.8.2.dev1/dotflow/core/models → dotflow-0.9.0.dev1/dotflow/core/types}/status.py +0 -0
- {dotflow-0.8.2.dev1/dotflow/core/models → dotflow-0.9.0.dev1/dotflow/core/types}/worflow.py +0 -0
- {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/main.py +0 -0
- {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/providers/__init__.py +0 -0
- {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/providers/zeromq.py +0 -0
- {dotflow-0.8.2.dev1/dotflow/core → dotflow-0.9.0.dev1/dotflow}/utils/basic_functions.py +0 -0
- {dotflow-0.8.2.dev1/dotflow/core → dotflow-0.9.0.dev1/dotflow}/utils/error_handler.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: dotflow
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.9.0.dev1
|
|
4
4
|
Summary: 🎲 Dotflow turns an idea into flow!
|
|
5
5
|
License: MIT License
|
|
6
6
|
|
|
@@ -164,7 +164,7 @@ workflow.start()
|
|
|
164
164
|
|03| [cli_with_mode](https://github.com/dotflow-io/dotflow/blob/master/examples/cli_with_mode.py) |
|
|
165
165
|
|04| [cli_with_output_context](https://github.com/dotflow-io/dotflow/blob/master/examples/cli_with_output_context.py) |
|
|
166
166
|
|05| [cli_with_path](https://github.com/dotflow-io/dotflow/blob/master/examples/cli_with_path.py) |
|
|
167
|
-
|06| [
|
|
167
|
+
|06| [simple_cli](https://github.com/dotflow-io/dotflow/blob/master/examples/simple_cli.py) |
|
|
168
168
|
|07| [simple_class_workflow](https://github.com/dotflow-io/dotflow/blob/master/examples/simple_class_workflow.py) |
|
|
169
169
|
|08| [simple_function_workflow_with_error](https://github.com/dotflow-io/dotflow/blob/master/examples/simple_function_workflow_with_error.py) |
|
|
170
170
|
|09| [simple_function_workflow](https://github.com/dotflow-io/dotflow/blob/master/examples/simple_function_workflow.py) |
|
|
@@ -120,7 +120,7 @@ workflow.start()
|
|
|
120
120
|
|03| [cli_with_mode](https://github.com/dotflow-io/dotflow/blob/master/examples/cli_with_mode.py) |
|
|
121
121
|
|04| [cli_with_output_context](https://github.com/dotflow-io/dotflow/blob/master/examples/cli_with_output_context.py) |
|
|
122
122
|
|05| [cli_with_path](https://github.com/dotflow-io/dotflow/blob/master/examples/cli_with_path.py) |
|
|
123
|
-
|06| [
|
|
123
|
+
|06| [simple_cli](https://github.com/dotflow-io/dotflow/blob/master/examples/simple_cli.py) |
|
|
124
124
|
|07| [simple_class_workflow](https://github.com/dotflow-io/dotflow/blob/master/examples/simple_class_workflow.py) |
|
|
125
125
|
|08| [simple_function_workflow_with_error](https://github.com/dotflow-io/dotflow/blob/master/examples/simple_function_workflow_with_error.py) |
|
|
126
126
|
|09| [simple_function_workflow](https://github.com/dotflow-io/dotflow/blob/master/examples/simple_function_workflow.py) |
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
"""Commands __init__ module."""
|
|
2
2
|
|
|
3
3
|
from dotflow.cli.commands.init import InitCommand
|
|
4
|
-
from dotflow.cli.commands.
|
|
4
|
+
from dotflow.cli.commands.log import LogCommand
|
|
5
5
|
from dotflow.cli.commands.start import StartCommand
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
__all__ = [
|
|
9
9
|
"InitCommand",
|
|
10
|
-
"
|
|
10
|
+
"LogCommand",
|
|
11
11
|
"StartCommand"
|
|
12
12
|
]
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""Command init module"""
|
|
2
|
+
|
|
3
|
+
from os import system
|
|
4
|
+
|
|
5
|
+
from rich import print # type: ignore
|
|
6
|
+
|
|
7
|
+
from dotflow.settings import Settings as settings
|
|
8
|
+
from dotflow.cli.command import Command
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class InitCommand(Command):
|
|
12
|
+
|
|
13
|
+
def setup(self):
|
|
14
|
+
if settings.GITIGNORE.exists():
|
|
15
|
+
system("echo '\n\n# Dotflow\n.output' >> .gitignore")
|
|
16
|
+
print(
|
|
17
|
+
settings.INFO_ALERT,
|
|
18
|
+
f"Installation complete! The ({settings.GITIGNORE.resolve()}) file has been modified."
|
|
19
|
+
)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""Command log module"""
|
|
2
|
+
|
|
3
|
+
from rich import print # type: ignore
|
|
4
|
+
|
|
5
|
+
from dotflow.utils import read_file
|
|
6
|
+
from dotflow.settings import Settings as settings
|
|
7
|
+
from dotflow.cli.command import Command
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class LogCommand(Command):
|
|
11
|
+
|
|
12
|
+
def setup(self):
|
|
13
|
+
if settings.LOG_PATH.exists():
|
|
14
|
+
print(read_file(path=settings.LOG_PATH))
|
|
15
|
+
|
|
16
|
+
print(
|
|
17
|
+
settings.INFO_ALERT,
|
|
18
|
+
f"To access all logs, open the file ({settings.LOG_PATH.resolve()})."
|
|
19
|
+
)
|
|
20
|
+
else:
|
|
21
|
+
print(settings.WARNING_ALERT, "Log file not found.")
|
|
@@ -3,17 +3,13 @@
|
|
|
3
3
|
from os import system
|
|
4
4
|
|
|
5
5
|
from dotflow import DotFlow, Config
|
|
6
|
-
from dotflow.core.
|
|
6
|
+
from dotflow.core.types.execution import TypeExecution
|
|
7
7
|
from dotflow.cli.command import Command
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class StartCommand(Command):
|
|
11
11
|
|
|
12
|
-
def
|
|
13
|
-
self.params = kwargs.get("arguments")
|
|
14
|
-
self.start()
|
|
15
|
-
|
|
16
|
-
def start(self):
|
|
12
|
+
def setup(self):
|
|
17
13
|
workflow = DotFlow(
|
|
18
14
|
config=Config(
|
|
19
15
|
path=self.params.path,
|
|
@@ -3,17 +3,21 @@
|
|
|
3
3
|
from rich import print # type: ignore
|
|
4
4
|
|
|
5
5
|
from dotflow import __version__, __description__
|
|
6
|
-
from dotflow.
|
|
6
|
+
from dotflow.logging import logger
|
|
7
7
|
from dotflow.settings import Settings as settings
|
|
8
|
-
from dotflow.
|
|
9
|
-
from dotflow.core.
|
|
8
|
+
from dotflow.utils.basic_functions import basic_callback
|
|
9
|
+
from dotflow.core.types.execution import TypeExecution
|
|
10
10
|
from dotflow.core.exception import (
|
|
11
11
|
MissingActionDecorator,
|
|
12
12
|
ExecutionModeNotExist,
|
|
13
13
|
ModuleNotFound,
|
|
14
14
|
MESSAGE_UNKNOWN_ERROR,
|
|
15
15
|
)
|
|
16
|
-
from dotflow.cli.commands import
|
|
16
|
+
from dotflow.cli.commands import (
|
|
17
|
+
InitCommand,
|
|
18
|
+
LogCommand,
|
|
19
|
+
StartCommand
|
|
20
|
+
)
|
|
17
21
|
|
|
18
22
|
|
|
19
23
|
class Command:
|
|
@@ -32,16 +36,10 @@ class Command:
|
|
|
32
36
|
)
|
|
33
37
|
|
|
34
38
|
self.setup_init()
|
|
39
|
+
self.setup_logs()
|
|
35
40
|
self.setup_start()
|
|
36
41
|
self.command()
|
|
37
42
|
|
|
38
|
-
def setup_server(self):
|
|
39
|
-
self.cmd_server = self.subparsers.add_parser("server", help="Server")
|
|
40
|
-
self.cmd_server = self.cmd_server.add_argument_group(
|
|
41
|
-
"Usage: dotflow server [OPTIONS]"
|
|
42
|
-
)
|
|
43
|
-
self.cmd_server.set_defaults(exec=ServerCommand)
|
|
44
|
-
|
|
45
43
|
def setup_init(self):
|
|
46
44
|
self.cmd_init = self.subparsers.add_parser("init", help="Init")
|
|
47
45
|
self.cmd_init = self.cmd_init.add_argument_group(
|
|
@@ -61,7 +59,7 @@ class Command:
|
|
|
61
59
|
self.cmd_start.add_argument(
|
|
62
60
|
"-o", "--output-context", default=False, action="store_true"
|
|
63
61
|
)
|
|
64
|
-
self.cmd_start.add_argument("-p", "--path", default=settings.
|
|
62
|
+
self.cmd_start.add_argument("-p", "--path", default=settings.START_PATH)
|
|
65
63
|
self.cmd_start.add_argument(
|
|
66
64
|
"-m",
|
|
67
65
|
"--mode",
|
|
@@ -71,10 +69,14 @@ class Command:
|
|
|
71
69
|
|
|
72
70
|
self.cmd_start.set_defaults(exec=StartCommand)
|
|
73
71
|
|
|
72
|
+
def setup_logs(self):
|
|
73
|
+
self.cmd_logs = self.subparsers.add_parser("logs", help="Logs")
|
|
74
|
+
self.cmd_logs = self.cmd_logs.add_argument_group(
|
|
75
|
+
"Usage: dotflow log [OPTIONS]"
|
|
76
|
+
)
|
|
77
|
+
self.cmd_logs.set_defaults(exec=LogCommand)
|
|
78
|
+
|
|
74
79
|
def command(self):
|
|
75
|
-
message_icon = ":game_die:"
|
|
76
|
-
message_error = "[bold red]Error:[/bold red]"
|
|
77
|
-
|
|
78
80
|
try:
|
|
79
81
|
arguments = self.parser.parse_args()
|
|
80
82
|
if hasattr(arguments, "exec"):
|
|
@@ -82,14 +84,14 @@ class Command:
|
|
|
82
84
|
else:
|
|
83
85
|
print(__description__)
|
|
84
86
|
except MissingActionDecorator as err:
|
|
85
|
-
print(
|
|
87
|
+
print(settings.WARNING_ALERT, err)
|
|
86
88
|
|
|
87
89
|
except ExecutionModeNotExist as err:
|
|
88
|
-
print(
|
|
90
|
+
print(settings.WARNING_ALERT, err)
|
|
89
91
|
|
|
90
92
|
except ModuleNotFound as err:
|
|
91
|
-
print(
|
|
93
|
+
print(settings.WARNING_ALERT, err)
|
|
92
94
|
|
|
93
95
|
except Exception as err:
|
|
94
|
-
print(message_icon, message_error, MESSAGE_UNKNOWN_ERROR)
|
|
95
96
|
logger.error(err)
|
|
97
|
+
print(settings.ERROR_ALERT, MESSAGE_UNKNOWN_ERROR)
|
|
@@ -13,4 +13,4 @@ class StartValidator(BaseModel):
|
|
|
13
13
|
callable: Optional[str] = Field(default=None)
|
|
14
14
|
initial_context: Optional[str] = Field(default=None)
|
|
15
15
|
output: Optional[bool] = Field(default=True)
|
|
16
|
-
path: Optional[str] = Field(default=settings.
|
|
16
|
+
path: Optional[str] = Field(default=settings.START_PATH)
|
|
@@ -56,7 +56,8 @@ class Action(object):
|
|
|
56
56
|
|
|
57
57
|
if type(self.func) is type:
|
|
58
58
|
if hasattr(self.func, "__init__"):
|
|
59
|
-
|
|
59
|
+
if hasattr(self.func.__init__, "__code__"):
|
|
60
|
+
self.params = [param for param in self.func.__init__.__code__.co_varnames]
|
|
60
61
|
|
|
61
62
|
def _get_context(self, kwargs: Dict):
|
|
62
63
|
context = {}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""Config module"""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from dotflow.settings import Settings as settings
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Config:
|
|
9
|
+
|
|
10
|
+
def __init__(
|
|
11
|
+
self,
|
|
12
|
+
path: str = settings.START_PATH,
|
|
13
|
+
output: bool = False
|
|
14
|
+
) -> None:
|
|
15
|
+
self.path = Path(path)
|
|
16
|
+
self.task_path = Path(path, "tasks")
|
|
17
|
+
self.log_path = Path(path, settings.LOG_FILE_NAME)
|
|
18
|
+
self.output = output
|
|
19
|
+
|
|
20
|
+
self.path.mkdir(parents=True, exist_ok=True)
|
|
21
|
+
self.task_path.mkdir(parents=True, exist_ok=True)
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"""Exception module"""
|
|
2
2
|
|
|
3
3
|
MESSAGE_UNKNOWN_ERROR = "Unknown error, please check logs for more information."
|
|
4
|
-
MESSAGE_MISSING_STEP_DECORATOR = "A step function necessarily needs an 'action' decorator to circulate in the workflow. For more implementation details, access the documentation: https://dotflow-io.github.io/dotflow/nav/getting-started/#3-task-function."
|
|
4
|
+
MESSAGE_MISSING_STEP_DECORATOR = "A step function necessarily needs an '@action' decorator to circulate in the workflow. For more implementation details, access the documentation: https://dotflow-io.github.io/dotflow/nav/getting-started/#3-task-function."
|
|
5
|
+
MESSAGE_NOT_CALLABLE_OBJECT = "Problem validating the '{name}' object type; this is not a callable object"
|
|
5
6
|
MESSAGE_EXECUTION_NOT_EXIST = "The execution mode does not exist. Allowed parameter is 'sequential' and 'background'."
|
|
6
|
-
MESSAGE_MODULE_NOT_FOUND = "Problem importing the python module
|
|
7
|
+
MESSAGE_MODULE_NOT_FOUND = "Problem importing the python module '{module}'."
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
class MissingActionDecorator(Exception):
|
|
@@ -24,7 +25,20 @@ class ExecutionModeNotExist(Exception):
|
|
|
24
25
|
|
|
25
26
|
class ModuleNotFound(Exception):
|
|
26
27
|
|
|
27
|
-
def __init__(self):
|
|
28
|
+
def __init__(self, module: str):
|
|
28
29
|
super(ModuleNotFound, self).__init__(
|
|
29
|
-
MESSAGE_MODULE_NOT_FOUND
|
|
30
|
+
MESSAGE_MODULE_NOT_FOUND.format(
|
|
31
|
+
module=module
|
|
32
|
+
)
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class NotCallableObject(Exception):
|
|
37
|
+
|
|
38
|
+
def __init__(self, name: str):
|
|
39
|
+
super(NotCallableObject, self).__init__(
|
|
40
|
+
MESSAGE_NOT_CALLABLE_OBJECT.format(
|
|
41
|
+
name=name
|
|
42
|
+
)
|
|
30
43
|
)
|
|
44
|
+
|
|
@@ -6,7 +6,7 @@ from typing import Callable
|
|
|
6
6
|
from dotflow.core.action import Action
|
|
7
7
|
from dotflow.core.context import Context
|
|
8
8
|
from dotflow.core.task import Task
|
|
9
|
-
from dotflow.core.
|
|
9
|
+
from dotflow.core.types import TaskStatus
|
|
10
10
|
|
|
11
11
|
from dotflow.core.decorators import time
|
|
12
12
|
|
|
@@ -21,8 +21,8 @@ class Execution:
|
|
|
21
21
|
) -> None:
|
|
22
22
|
self.task = task
|
|
23
23
|
self.task.status = TaskStatus.IN_PROGRESS
|
|
24
|
-
self.task._set_workflow_id(workflow_id)
|
|
25
24
|
self.task.previous_context = previous_context
|
|
25
|
+
self.task.workflow_id = workflow_id
|
|
26
26
|
|
|
27
27
|
self._excution()
|
|
28
28
|
|
|
@@ -63,12 +63,12 @@ class Execution:
|
|
|
63
63
|
previous_context=self.task.previous_context,
|
|
64
64
|
)
|
|
65
65
|
|
|
66
|
-
|
|
66
|
+
object_attributes = [
|
|
67
67
|
type(getattr(current_context.storage, param)) is Action
|
|
68
68
|
for param in dir(current_context.storage)
|
|
69
69
|
]
|
|
70
70
|
|
|
71
|
-
if True in
|
|
71
|
+
if True in object_attributes:
|
|
72
72
|
current_context = self._execution_with_class(
|
|
73
73
|
class_instance=current_context.storage
|
|
74
74
|
)
|
|
@@ -2,16 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
from uuid import UUID
|
|
4
4
|
from typing import Any, Callable, List
|
|
5
|
+
from time import strftime, localtime
|
|
5
6
|
|
|
6
|
-
from
|
|
7
|
+
from rich.console import Console # type: ignore
|
|
8
|
+
|
|
9
|
+
from dotflow.logging import logger
|
|
7
10
|
from dotflow.core.config import Config
|
|
8
11
|
from dotflow.core.action import Action
|
|
9
12
|
from dotflow.core.context import Context
|
|
10
13
|
from dotflow.core.module import Module
|
|
11
|
-
from dotflow.core.exception import MissingActionDecorator
|
|
12
|
-
from dotflow.core.
|
|
14
|
+
from dotflow.core.exception import MissingActionDecorator, NotCallableObject
|
|
15
|
+
from dotflow.core.types.status import TaskStatus
|
|
13
16
|
from dotflow.settings import Settings as settings
|
|
14
|
-
from dotflow.
|
|
17
|
+
from dotflow.utils import (
|
|
18
|
+
basic_callback,
|
|
19
|
+
traceback_error,
|
|
20
|
+
message_error,
|
|
21
|
+
write_file,
|
|
22
|
+
copy_file
|
|
23
|
+
)
|
|
15
24
|
|
|
16
25
|
|
|
17
26
|
class TaskInstance:
|
|
@@ -19,11 +28,12 @@ class TaskInstance:
|
|
|
19
28
|
def __init__(self, *args, **kwargs) -> None:
|
|
20
29
|
self.task_id = None
|
|
21
30
|
self.workflow_id = None
|
|
22
|
-
self.
|
|
23
|
-
self.
|
|
31
|
+
self._step = None
|
|
32
|
+
self._callback = None
|
|
33
|
+
self._previous_context = None
|
|
24
34
|
self._initial_context = None
|
|
25
35
|
self._current_context = None
|
|
26
|
-
self.
|
|
36
|
+
self._duration = None
|
|
27
37
|
self._error = None
|
|
28
38
|
self._status = None
|
|
29
39
|
self._config = None
|
|
@@ -40,45 +50,52 @@ class Task(TaskInstance):
|
|
|
40
50
|
workflow_id: UUID = None,
|
|
41
51
|
config: Config = None,
|
|
42
52
|
) -> None:
|
|
43
|
-
super().__init__(
|
|
44
|
-
|
|
53
|
+
super().__init__(
|
|
54
|
+
task_id,
|
|
55
|
+
step,
|
|
56
|
+
callback,
|
|
57
|
+
initial_context,
|
|
58
|
+
workflow_id
|
|
59
|
+
)
|
|
45
60
|
self.task_id = task_id
|
|
46
61
|
self.workflow_id = workflow_id
|
|
47
62
|
self.step = step
|
|
48
63
|
self.callback = callback
|
|
49
64
|
self.initial_context = initial_context
|
|
50
65
|
self.status = TaskStatus.NOT_STARTED
|
|
66
|
+
self.config = config
|
|
51
67
|
|
|
52
68
|
@property
|
|
53
|
-
def
|
|
54
|
-
|
|
55
|
-
return TaskStatus.NOT_STARTED
|
|
56
|
-
return self._status
|
|
69
|
+
def step(self):
|
|
70
|
+
return self._step
|
|
57
71
|
|
|
58
|
-
@
|
|
59
|
-
def
|
|
60
|
-
|
|
72
|
+
@step.setter
|
|
73
|
+
def step(self, value: Callable):
|
|
74
|
+
new_step = value
|
|
61
75
|
|
|
62
|
-
|
|
76
|
+
if isinstance(value, str):
|
|
77
|
+
new_step = Module(value=value)
|
|
78
|
+
|
|
79
|
+
if new_step.__module__ != Action.__module__:
|
|
80
|
+
raise MissingActionDecorator()
|
|
81
|
+
|
|
82
|
+
self._step = new_step
|
|
63
83
|
|
|
64
84
|
@property
|
|
65
|
-
def
|
|
66
|
-
|
|
67
|
-
return TaskError()
|
|
68
|
-
return self._error
|
|
85
|
+
def callback(self):
|
|
86
|
+
return self._callback
|
|
69
87
|
|
|
70
|
-
@
|
|
71
|
-
def
|
|
72
|
-
|
|
73
|
-
self._error = task_error
|
|
88
|
+
@callback.setter
|
|
89
|
+
def callback(self, value: Callable):
|
|
90
|
+
new_callback = value
|
|
74
91
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
92
|
+
if isinstance(value, str):
|
|
93
|
+
new_callback = Module(value=value)
|
|
94
|
+
|
|
95
|
+
if not isinstance(new_callback, Callable):
|
|
96
|
+
raise NotCallableObject(name=str(new_callback))
|
|
97
|
+
|
|
98
|
+
self._callback = new_callback
|
|
82
99
|
|
|
83
100
|
@property
|
|
84
101
|
def previous_context(self):
|
|
@@ -90,6 +107,26 @@ class Task(TaskInstance):
|
|
|
90
107
|
def previous_context(self, value: Context):
|
|
91
108
|
self._previous_context = Context(value)
|
|
92
109
|
|
|
110
|
+
TaskController(task=self).controller_output_context(
|
|
111
|
+
content=self.previous_context.storage,
|
|
112
|
+
context_name="previous_context"
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
@property
|
|
116
|
+
def initial_context(self):
|
|
117
|
+
if not self._initial_context:
|
|
118
|
+
return Context()
|
|
119
|
+
return self._initial_context
|
|
120
|
+
|
|
121
|
+
@initial_context.setter
|
|
122
|
+
def initial_context(self, value: Context):
|
|
123
|
+
self._initial_context = Context(value)
|
|
124
|
+
|
|
125
|
+
TaskController(task=self).controller_output_context(
|
|
126
|
+
content=self.initial_context.storage,
|
|
127
|
+
context_name="initial_context"
|
|
128
|
+
)
|
|
129
|
+
|
|
93
130
|
@property
|
|
94
131
|
def current_context(self):
|
|
95
132
|
if not self._current_context:
|
|
@@ -100,35 +137,52 @@ class Task(TaskInstance):
|
|
|
100
137
|
def current_context(self, value: Context):
|
|
101
138
|
self._current_context = Context(value)
|
|
102
139
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
self.task_id,
|
|
108
|
-
str(value.storage),
|
|
109
|
-
)
|
|
140
|
+
TaskController(task=self).controller_output_context(
|
|
141
|
+
content=self.current_context.storage,
|
|
142
|
+
context_name="current_context"
|
|
143
|
+
)
|
|
110
144
|
|
|
111
|
-
|
|
145
|
+
@property
|
|
146
|
+
def duration(self):
|
|
147
|
+
return self._duration
|
|
148
|
+
|
|
149
|
+
@duration.setter
|
|
150
|
+
def duration(self, value: float):
|
|
151
|
+
self._duration = value
|
|
112
152
|
|
|
113
153
|
@property
|
|
114
|
-
def
|
|
115
|
-
if not self.
|
|
116
|
-
return
|
|
117
|
-
return self.
|
|
154
|
+
def error(self):
|
|
155
|
+
if not self._error:
|
|
156
|
+
return TaskError()
|
|
157
|
+
return self._error
|
|
118
158
|
|
|
119
|
-
@
|
|
120
|
-
def
|
|
121
|
-
|
|
159
|
+
@error.setter
|
|
160
|
+
def error(self, value: Exception) -> None:
|
|
161
|
+
task_error = TaskError(value)
|
|
162
|
+
self._error = task_error
|
|
122
163
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
164
|
+
logger.error(
|
|
165
|
+
"ID %s - %s - %s \n %s",
|
|
166
|
+
self.workflow_id,
|
|
167
|
+
self.task_id,
|
|
168
|
+
self.status,
|
|
169
|
+
task_error.traceback,
|
|
170
|
+
)
|
|
130
171
|
|
|
131
|
-
|
|
172
|
+
console = Console()
|
|
173
|
+
console.print_exception(show_locals=True)
|
|
174
|
+
|
|
175
|
+
@property
|
|
176
|
+
def status(self):
|
|
177
|
+
if not self._status:
|
|
178
|
+
return TaskStatus.NOT_STARTED
|
|
179
|
+
return self._status
|
|
180
|
+
|
|
181
|
+
@status.setter
|
|
182
|
+
def status(self, value: TaskStatus) -> None:
|
|
183
|
+
self._status = value
|
|
184
|
+
|
|
185
|
+
TaskController(task=self).controller_logger()
|
|
132
186
|
|
|
133
187
|
@property
|
|
134
188
|
def config(self):
|
|
@@ -140,12 +194,6 @@ class Task(TaskInstance):
|
|
|
140
194
|
def config(self, value: Config):
|
|
141
195
|
self._config = value
|
|
142
196
|
|
|
143
|
-
def _set_duration(self, value: float) -> None:
|
|
144
|
-
self.duration = value
|
|
145
|
-
|
|
146
|
-
def _set_workflow_id(self, value: UUID) -> None:
|
|
147
|
-
self.workflow_id = value
|
|
148
|
-
|
|
149
197
|
|
|
150
198
|
class TaskError:
|
|
151
199
|
|
|
@@ -157,8 +205,12 @@ class TaskError:
|
|
|
157
205
|
|
|
158
206
|
class TaskBuilder:
|
|
159
207
|
|
|
160
|
-
def __init__(
|
|
161
|
-
|
|
208
|
+
def __init__(
|
|
209
|
+
self,
|
|
210
|
+
config: Config,
|
|
211
|
+
workflow_id: UUID = None
|
|
212
|
+
) -> None:
|
|
213
|
+
self.queu: List[Callable] = []
|
|
162
214
|
self.workflow_id = workflow_id
|
|
163
215
|
self.config = config
|
|
164
216
|
|
|
@@ -168,10 +220,14 @@ class TaskBuilder:
|
|
|
168
220
|
callback: Callable = basic_callback,
|
|
169
221
|
initial_context: Any = None,
|
|
170
222
|
) -> None:
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
223
|
+
if isinstance(step, list):
|
|
224
|
+
for inside_step in step:
|
|
225
|
+
self.add(
|
|
226
|
+
step=inside_step,
|
|
227
|
+
callback=callback,
|
|
228
|
+
initial_context=initial_context
|
|
229
|
+
)
|
|
230
|
+
return self
|
|
175
231
|
|
|
176
232
|
self.queu.append(
|
|
177
233
|
Task(
|
|
@@ -191,3 +247,45 @@ class TaskBuilder:
|
|
|
191
247
|
|
|
192
248
|
def clear(self) -> None:
|
|
193
249
|
self.queu.clear()
|
|
250
|
+
|
|
251
|
+
def reverse(self) -> None:
|
|
252
|
+
self.queu.reverse()
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
class TaskController:
|
|
256
|
+
|
|
257
|
+
def __init__(self, task: Task):
|
|
258
|
+
self.task = task
|
|
259
|
+
self.default_time_format = "%Y-%m-%d %H:%M:%S"
|
|
260
|
+
|
|
261
|
+
def _get_body(self):
|
|
262
|
+
return "{time} ID: {workflow_id} - {task_id} - {task_status}".format(
|
|
263
|
+
time=strftime(self.default_time_format, localtime()),
|
|
264
|
+
workflow_id=self.task.workflow_id,
|
|
265
|
+
task_id=self.task.task_id,
|
|
266
|
+
task_status=self.task.status
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
def controller_logger(self):
|
|
270
|
+
logger.info(
|
|
271
|
+
"ID %s - %s - %s",
|
|
272
|
+
self.task.workflow_id,
|
|
273
|
+
self.task.task_id,
|
|
274
|
+
self.task.status,
|
|
275
|
+
)
|
|
276
|
+
copy_file(
|
|
277
|
+
source=settings.LOG_PATH,
|
|
278
|
+
destination=self.task.config.log_path
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
def controller_output_context(self, content: Any, context_name: str) -> None:
|
|
282
|
+
if self.task.config.output:
|
|
283
|
+
file_name = "{workflow_id}-{task_id}-{context_name}".format(
|
|
284
|
+
workflow_id=self.task.workflow_id.hex,
|
|
285
|
+
task_id=self.task.task_id,
|
|
286
|
+
context_name=context_name
|
|
287
|
+
)
|
|
288
|
+
write_file(
|
|
289
|
+
path=self.task.config.task_path.joinpath(file_name),
|
|
290
|
+
content=str(content)
|
|
291
|
+
)
|
|
@@ -9,9 +9,9 @@ from typing import Callable, List
|
|
|
9
9
|
from dotflow.core.context import Context
|
|
10
10
|
from dotflow.core.execution import Execution
|
|
11
11
|
from dotflow.core.exception import ExecutionModeNotExist
|
|
12
|
-
from dotflow.core.
|
|
12
|
+
from dotflow.core.types import TypeExecution, TaskStatus
|
|
13
13
|
from dotflow.core.task import Task
|
|
14
|
-
from dotflow.
|
|
14
|
+
from dotflow.utils import basic_callback
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
class Workflow:
|
|
@@ -3,25 +3,25 @@
|
|
|
3
3
|
import logging
|
|
4
4
|
import logging.config
|
|
5
5
|
|
|
6
|
-
from dotflow.core.utils import make_dir
|
|
7
6
|
from dotflow.settings import Settings as settings
|
|
8
7
|
|
|
9
|
-
|
|
8
|
+
settings.START_PATH.mkdir(parents=True, exist_ok=True)
|
|
10
9
|
|
|
11
10
|
logging.basicConfig(
|
|
12
11
|
filename=settings.LOG_PATH,
|
|
12
|
+
format=settings.LOG_FORMAT,
|
|
13
13
|
level=logging.INFO,
|
|
14
|
-
filemode="a"
|
|
14
|
+
filemode="a",
|
|
15
15
|
)
|
|
16
16
|
|
|
17
17
|
logger = logging.getLogger(settings.LOG_PROFILE)
|
|
18
|
-
logger.setLevel(logging.
|
|
18
|
+
logger.setLevel(logging.INFO)
|
|
19
19
|
|
|
20
20
|
ch = logging.StreamHandler()
|
|
21
|
-
ch.setLevel(logging.
|
|
21
|
+
ch.setLevel(logging.INFO)
|
|
22
22
|
|
|
23
23
|
formatter = logging.Formatter(
|
|
24
|
-
|
|
24
|
+
settings.LOG_FORMAT
|
|
25
25
|
)
|
|
26
26
|
|
|
27
27
|
ch.setFormatter(formatter)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""Settings"""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Settings:
|
|
7
|
+
|
|
8
|
+
START_PATH = Path(".output")
|
|
9
|
+
GITIGNORE = Path(".gitignore")
|
|
10
|
+
|
|
11
|
+
LOG_PROFILE = "dotflow"
|
|
12
|
+
LOG_FILE_NAME = Path("flow.log")
|
|
13
|
+
LOG_PATH = Path(".output/flow.log")
|
|
14
|
+
LOG_FORMAT = "%(asctime)s - %(levelname)s [%(name)s]: %(message)s"
|
|
15
|
+
|
|
16
|
+
ICON = ":game_die:"
|
|
17
|
+
ERROR_ALERT = f"{ICON} [bold red]Error:[/bold red]"
|
|
18
|
+
INFO_ALERT = f"{ICON} [bold blue]Info:[/bold blue]"
|
|
19
|
+
WARNING_ALERT = f"{ICON} [bold yellow]Warning:[/bold yellow]"
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Utils __init__ module."""
|
|
2
|
+
|
|
3
|
+
from dotflow.utils.error_handler import traceback_error, message_error
|
|
4
|
+
from dotflow.utils.basic_functions import basic_function, basic_callback
|
|
5
|
+
from dotflow.utils.tools import make_dir, copy_file, write_file, read_file
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
"traceback_error",
|
|
10
|
+
"message_error",
|
|
11
|
+
"basic_function",
|
|
12
|
+
"basic_callback",
|
|
13
|
+
"make_dir",
|
|
14
|
+
"copy_file",
|
|
15
|
+
"write_file",
|
|
16
|
+
"read_file"
|
|
17
|
+
]
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""Tools"""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import logging
|
|
5
|
+
|
|
6
|
+
from os import makedirs, system
|
|
7
|
+
from shutil import copy
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def make_dir(path: str, show_log: bool = False):
|
|
11
|
+
try:
|
|
12
|
+
makedirs(name=path, exist_ok=True)
|
|
13
|
+
except Exception as err:
|
|
14
|
+
if show_log:
|
|
15
|
+
logging.error(err)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def copy_file(
|
|
19
|
+
source: str,
|
|
20
|
+
destination: str,
|
|
21
|
+
show_log: bool = False
|
|
22
|
+
) -> None:
|
|
23
|
+
try:
|
|
24
|
+
copy(src=source, dst=destination)
|
|
25
|
+
except Exception as err:
|
|
26
|
+
if show_log:
|
|
27
|
+
logging.error(err)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def write_file(
|
|
31
|
+
path: str,
|
|
32
|
+
content: str,
|
|
33
|
+
mode: str = "w"
|
|
34
|
+
) -> None:
|
|
35
|
+
if isinstance(content, dict) or isinstance(content, list):
|
|
36
|
+
content = json.dumps(content)
|
|
37
|
+
|
|
38
|
+
try:
|
|
39
|
+
with open(file=path, mode=mode, encoding="utf-8") as file:
|
|
40
|
+
file.write(content)
|
|
41
|
+
except Exception:
|
|
42
|
+
system(f"echo '{content}' > {path}")
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def read_file(path: str) -> str:
|
|
46
|
+
with open(file=path) as file:
|
|
47
|
+
return file.read()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "dotflow"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.9.0.dev1"
|
|
4
4
|
authors = [
|
|
5
5
|
{ name="Fernando Celmer", email="email@fernandocelmer.com" },
|
|
6
6
|
]
|
|
@@ -31,7 +31,7 @@ Documentation = "https://github.com/dotflow-io/dotflow/blob/master/README.md"
|
|
|
31
31
|
|
|
32
32
|
[tool.poetry]
|
|
33
33
|
name = "dotflow"
|
|
34
|
-
version = "0.
|
|
34
|
+
version = "0.9.0.dev1"
|
|
35
35
|
description = "🎲 Dotflow turns an idea into flow!"
|
|
36
36
|
authors = ["Fernando Celmer <email@fernandocelmer.com>"]
|
|
37
37
|
readme = "README.md"
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
"""Command init module"""
|
|
2
|
-
|
|
3
|
-
from os import system, path
|
|
4
|
-
|
|
5
|
-
from dotflow.cli.command import Command
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class InitCommand(Command):
|
|
9
|
-
|
|
10
|
-
def __init__(self, **kwargs):
|
|
11
|
-
self.params = kwargs.get("arguments")
|
|
12
|
-
self.init()
|
|
13
|
-
|
|
14
|
-
def init(self):
|
|
15
|
-
if path.isfile(".gitignore"):
|
|
16
|
-
system("echo '\n\n# Dotflow\n.output' >> .gitignore")
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
"""Config module"""
|
|
2
|
-
|
|
3
|
-
from dotflow.core.utils import make_dir
|
|
4
|
-
from dotflow.settings import Settings as settings
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class Config:
|
|
8
|
-
|
|
9
|
-
def __init__(
|
|
10
|
-
self,
|
|
11
|
-
path: str = settings.INITIAL_PATH,
|
|
12
|
-
output: bool = False
|
|
13
|
-
) -> None:
|
|
14
|
-
self.path = path
|
|
15
|
-
self.log_path = f"{path}/{settings.LOG_FILE}"
|
|
16
|
-
self.output = output
|
|
17
|
-
|
|
18
|
-
make_dir(path=self.path, show_log=True)
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
"""Utils __init__ module."""
|
|
2
|
-
|
|
3
|
-
from dotflow.core.utils.error_handler import traceback_error, message_error
|
|
4
|
-
from dotflow.core.utils.basic_functions import basic_function, basic_callback
|
|
5
|
-
from dotflow.core.utils.tools import make_dir, copy_file
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
__all__ = [
|
|
9
|
-
"traceback_error",
|
|
10
|
-
"message_error",
|
|
11
|
-
"basic_function",
|
|
12
|
-
"basic_callback",
|
|
13
|
-
"make_dir",
|
|
14
|
-
"copy_file"
|
|
15
|
-
]
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
"""Tools"""
|
|
2
|
-
|
|
3
|
-
import logging
|
|
4
|
-
|
|
5
|
-
from os import makedirs
|
|
6
|
-
from shutil import copy
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
def make_dir(path: str, show_log: bool = False):
|
|
10
|
-
try:
|
|
11
|
-
makedirs(name=path, exist_ok=True)
|
|
12
|
-
except Exception as err:
|
|
13
|
-
if show_log:
|
|
14
|
-
logging.error(err)
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def copy_file(
|
|
18
|
-
source: str,
|
|
19
|
-
destination: str,
|
|
20
|
-
show_log: bool = False
|
|
21
|
-
) -> None:
|
|
22
|
-
try:
|
|
23
|
-
copy(src=source, dst=destination)
|
|
24
|
-
except Exception as err:
|
|
25
|
-
if show_log:
|
|
26
|
-
logging.error(err)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dotflow-0.8.2.dev1/dotflow/core/models → dotflow-0.9.0.dev1/dotflow/core/types}/execution.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|