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.
Files changed (57) hide show
  1. {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/PKG-INFO +2 -2
  2. {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/README.md +1 -1
  3. {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/__init__.py +1 -1
  4. dotflow-0.9.0.dev1/dotflow/cli/command.py +14 -0
  5. {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/cli/commands/__init__.py +2 -2
  6. dotflow-0.9.0.dev1/dotflow/cli/commands/init.py +19 -0
  7. dotflow-0.9.0.dev1/dotflow/cli/commands/log.py +21 -0
  8. {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/cli/commands/start.py +2 -6
  9. {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/cli/setup.py +21 -19
  10. {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/cli/validators/start.py +1 -1
  11. {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/core/action.py +2 -1
  12. dotflow-0.9.0.dev1/dotflow/core/config.py +21 -0
  13. {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/core/decorators/time.py +1 -1
  14. {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/core/exception.py +18 -4
  15. {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/core/execution.py +4 -4
  16. {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/core/module.py +3 -1
  17. {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/core/task.py +165 -67
  18. dotflow-0.9.0.dev1/dotflow/core/types/__init__.py +10 -0
  19. {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/core/workflow.py +2 -2
  20. dotflow-0.8.2.dev1/dotflow/log.py → dotflow-0.9.0.dev1/dotflow/logging.py +6 -6
  21. dotflow-0.9.0.dev1/dotflow/settings.py +19 -0
  22. dotflow-0.9.0.dev1/dotflow/utils/__init__.py +17 -0
  23. dotflow-0.9.0.dev1/dotflow/utils/tools.py +47 -0
  24. {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/pyproject.toml +2 -2
  25. dotflow-0.8.2.dev1/dotflow/cli/command.py +0 -10
  26. dotflow-0.8.2.dev1/dotflow/cli/commands/init.py +0 -16
  27. dotflow-0.8.2.dev1/dotflow/cli/commands/server.py +0 -9
  28. dotflow-0.8.2.dev1/dotflow/core/config.py +0 -18
  29. dotflow-0.8.2.dev1/dotflow/core/models/__init__.py +0 -10
  30. dotflow-0.8.2.dev1/dotflow/core/utils/__init__.py +0 -15
  31. dotflow-0.8.2.dev1/dotflow/core/utils/tools.py +0 -26
  32. dotflow-0.8.2.dev1/dotflow/settings.py +0 -9
  33. {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/LICENSE +0 -0
  34. {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/abc/__init__.py +0 -0
  35. {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/abc/file.py +0 -0
  36. {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/abc/http.py +0 -0
  37. {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/abc/tcp.py +0 -0
  38. {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/cli/__init__.py +0 -0
  39. {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/cli/validators/__init__.py +0 -0
  40. {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/core/__init__.py +0 -0
  41. {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/core/context.py +0 -0
  42. {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/core/decorators/__init__.py +0 -0
  43. {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/core/decorators/action.py +0 -0
  44. {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/core/decorators/retry.py +0 -0
  45. {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/core/dotflow.py +0 -0
  46. {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/core/serializers/__init__.py +0 -0
  47. {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/core/serializers/task.py +0 -0
  48. {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/core/serializers/transport.py +0 -0
  49. {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/core/serializers/workflow.py +0 -0
  50. {dotflow-0.8.2.dev1/dotflow/core/models → dotflow-0.9.0.dev1/dotflow/core/types}/execution.py +0 -0
  51. {dotflow-0.8.2.dev1/dotflow/core/models → dotflow-0.9.0.dev1/dotflow/core/types}/status.py +0 -0
  52. {dotflow-0.8.2.dev1/dotflow/core/models → dotflow-0.9.0.dev1/dotflow/core/types}/worflow.py +0 -0
  53. {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/main.py +0 -0
  54. {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/providers/__init__.py +0 -0
  55. {dotflow-0.8.2.dev1 → dotflow-0.9.0.dev1}/dotflow/providers/zeromq.py +0 -0
  56. {dotflow-0.8.2.dev1/dotflow/core → dotflow-0.9.0.dev1/dotflow}/utils/basic_functions.py +0 -0
  57. {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.8.2.dev1
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| [cli](https://github.com/dotflow-io/dotflow/blob/master/examples/cli.py) |
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| [cli](https://github.com/dotflow-io/dotflow/blob/master/examples/cli.py) |
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,6 +1,6 @@
1
1
  """Dotflow __init__ module."""
2
2
 
3
- __version__ = "0.8.2.dev1"
3
+ __version__ = "0.9.0.dev1"
4
4
  __description__ = "🎲 Dotflow turns an idea into flow!"
5
5
 
6
6
  from .core.config import Config
@@ -0,0 +1,14 @@
1
+ """Command module"""
2
+
3
+ from abc import ABC, abstractmethod
4
+
5
+
6
+ class Command(ABC):
7
+
8
+ def __init__(self, **kwargs):
9
+ self.params = kwargs.get("arguments")
10
+ self.setup()
11
+
12
+ @abstractmethod
13
+ def setup(self):
14
+ pass
@@ -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.server import ServerCommand
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
- "ServerCommand",
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.models.execution import TypeExecution
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 __init__(self, **kwargs):
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.log import logger
6
+ from dotflow.logging import logger
7
7
  from dotflow.settings import Settings as settings
8
- from dotflow.core.utils.basic_functions import basic_callback
9
- from dotflow.core.models.execution import TypeExecution
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 InitCommand, ServerCommand, StartCommand
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.INITIAL_PATH)
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(message_icon, message_error, err)
87
+ print(settings.WARNING_ALERT, err)
86
88
 
87
89
  except ExecutionModeNotExist as err:
88
- print(message_icon, message_error, err)
90
+ print(settings.WARNING_ALERT, err)
89
91
 
90
92
  except ModuleNotFound as err:
91
- print(message_icon, message_error, err)
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.INITIAL_PATH)
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
- self.params = [param for param in self.func.__init__.__code__.co_varnames]
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)
@@ -7,6 +7,6 @@ def time(func):
7
7
  def inside(*args, **kwargs):
8
8
  start = datetime.now()
9
9
  task = func(*args, **kwargs)
10
- task._set_duration((datetime.now() - start).total_seconds())
10
+ task.duration = (datetime.now() - start).total_seconds()
11
11
  return task
12
12
  return inside
@@ -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, it probably doesn't exist or is wrong."
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.models import TaskStatus
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
- so_this_is_a_class = [
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 so_this_is_a_class:
71
+ if True in object_attributes:
72
72
  current_context = self._execution_with_class(
73
73
  class_instance=current_context.storage
74
74
  )
@@ -30,7 +30,9 @@ class Module:
30
30
  if hasattr(module, cls._get_name(value)):
31
31
  return getattr(module, cls._get_name(value))
32
32
 
33
- raise ModuleNotFound()
33
+ raise ModuleNotFound(
34
+ module=value
35
+ )
34
36
 
35
37
  @classmethod
36
38
  def _get_name(cls, value: str):
@@ -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 dotflow.log import logger
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.models.status import TaskStatus
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.core.utils import basic_callback, traceback_error, message_error, copy_file
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.step = None
23
- self.callback = None
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._previous_context = None
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__(task_id, step, callback, initial_context, workflow_id)
44
- self.config = config
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 status(self):
54
- if not self._status:
55
- return TaskStatus.NOT_STARTED
56
- return self._status
69
+ def step(self):
70
+ return self._step
57
71
 
58
- @status.setter
59
- def status(self, value: TaskStatus) -> None:
60
- self._status = value
72
+ @step.setter
73
+ def step(self, value: Callable):
74
+ new_step = value
61
75
 
62
- logger.info("ID %s - %s - %s", self.workflow_id, self.task_id, value)
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 error(self):
66
- if not self._error:
67
- return TaskError()
68
- return self._error
85
+ def callback(self):
86
+ return self._callback
69
87
 
70
- @error.setter
71
- def error(self, value: Exception) -> None:
72
- task_error = TaskError(value)
73
- self._error = task_error
88
+ @callback.setter
89
+ def callback(self, value: Callable):
90
+ new_callback = value
74
91
 
75
- logger.error(
76
- "ID %s - %s - %s \n %s",
77
- self.workflow_id,
78
- self.task_id,
79
- self.status,
80
- task_error.traceback,
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
- if self.config.output:
104
- logger.info(
105
- "ID %s - %s - Current Context -> %s",
106
- self.workflow_id,
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
- copy_file(source=settings.LOG_PATH, destination=self.config.log_path)
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 initial_context(self):
115
- if not self._initial_context:
116
- return Context()
117
- return self._initial_context
154
+ def error(self):
155
+ if not self._error:
156
+ return TaskError()
157
+ return self._error
118
158
 
119
- @initial_context.setter
120
- def initial_context(self, value: Context):
121
- self._initial_context = Context(value)
159
+ @error.setter
160
+ def error(self, value: Exception) -> None:
161
+ task_error = TaskError(value)
162
+ self._error = task_error
122
163
 
123
- if self.config.output:
124
- logger.info(
125
- "ID %s - %s - Initial Context -> %s",
126
- self.workflow_id,
127
- self.task_id,
128
- str(value),
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
- copy_file(source=settings.LOG_PATH, destination=self.config.log_path)
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__(self, config: Config, workflow_id: UUID = None) -> None:
161
- self.queu: List[Task] = []
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
- step = Module(value=step)
172
-
173
- if step.__module__ != Action.__module__:
174
- raise MissingActionDecorator()
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
+ )
@@ -0,0 +1,10 @@
1
+ """Types __init__ module."""
2
+
3
+ from dotflow.core.types.execution import TypeExecution
4
+ from dotflow.core.types.status import TaskStatus
5
+
6
+
7
+ __all__ = [
8
+ "TypeExecution",
9
+ "TaskStatus"
10
+ ]
@@ -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.models import TypeExecution, TaskStatus
12
+ from dotflow.core.types import TypeExecution, TaskStatus
13
13
  from dotflow.core.task import Task
14
- from dotflow.core.utils import basic_callback
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
- make_dir(path=settings.INITIAL_PATH, show_log=True)
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.DEBUG)
18
+ logger.setLevel(logging.INFO)
19
19
 
20
20
  ch = logging.StreamHandler()
21
- ch.setLevel(logging.DEBUG)
21
+ ch.setLevel(logging.INFO)
22
22
 
23
23
  formatter = logging.Formatter(
24
- '%(asctime)s - %(levelname)s [%(name)s]: %(message)s'
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.8.2.dev1"
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.8.2.dev1"
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,10 +0,0 @@
1
- """Command module"""
2
-
3
-
4
- class Command:
5
-
6
- def __init__(self, **kwargs):
7
- self.params = kwargs.get("arguments")
8
-
9
- if hasattr(self.params, "option"):
10
- getattr(self, self.params.option)()
@@ -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,9 +0,0 @@
1
- """Command server module"""
2
-
3
- from dotflow.cli.command import Command
4
-
5
-
6
- class ServerCommand(Command):
7
-
8
- def __init__(self, *args, **kwargs):
9
- pass
@@ -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,10 +0,0 @@
1
- """Types __init__ module."""
2
-
3
- from dotflow.core.models.execution import TypeExecution
4
- from dotflow.core.models.status import TaskStatus
5
-
6
-
7
- __all__ = [
8
- "TypeExecution",
9
- "TaskStatus"
10
- ]
@@ -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)
@@ -1,9 +0,0 @@
1
- """Settings"""
2
-
3
-
4
- class Settings:
5
-
6
- INITIAL_PATH = ".output"
7
- LOG_PROFILE = "dotflow"
8
- LOG_FILE = "flow.log"
9
- LOG_PATH = ".output/flow.log"
File without changes