osbot-utils 2.30.0__py3-none-any.whl → 2.32.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- osbot_utils/{testing → helpers/duration}/Duration.py +14 -26
- osbot_utils/helpers/duration/__init__.py +0 -0
- osbot_utils/helpers/duration/decorators/__init__.py +0 -0
- osbot_utils/helpers/duration/decorators/duration.py +21 -0
- osbot_utils/{context_managers → helpers/duration/decorators}/print_duration.py +1 -1
- osbot_utils/helpers/duration/schemas/Schema__Duration.py +8 -0
- osbot_utils/helpers/duration/schemas/__init__.py +0 -0
- osbot_utils/helpers/flows/Flow.py +24 -16
- osbot_utils/helpers/flows/Task.py +18 -8
- osbot_utils/helpers/flows/actions/Flow__Data.py +0 -1
- osbot_utils/helpers/flows/actions/Flow__Stats__Collector.py +83 -0
- osbot_utils/helpers/flows/actions/Task__Stats__Collector.py +34 -0
- osbot_utils/helpers/flows/schemas/Schema__Flow__Stats.py +16 -0
- osbot_utils/helpers/flows/schemas/Schema__Flow__Status.py +7 -0
- osbot_utils/helpers/flows/schemas/Schema__Task__Stats.py +13 -0
- osbot_utils/helpers/ssh/SCP.py +6 -6
- osbot_utils/helpers/ssh/SSH__Execute.py +10 -10
- osbot_utils/testing/Hook_Method.py +4 -3
- osbot_utils/type_safe/shared/Type_Safe__Shared__Variables.py +5 -1
- osbot_utils/type_safe/steps/Type_Safe__Step__From_Json.py +1 -1
- osbot_utils/version +1 -1
- {osbot_utils-2.30.0.dist-info → osbot_utils-2.32.0.dist-info}/METADATA +2 -2
- {osbot_utils-2.30.0.dist-info → osbot_utils-2.32.0.dist-info}/RECORD +26 -16
- /osbot_utils/{context_managers → helpers/duration/decorators}/capture_duration.py +0 -0
- {osbot_utils-2.30.0.dist-info → osbot_utils-2.32.0.dist-info}/LICENSE +0 -0
- {osbot_utils-2.30.0.dist-info → osbot_utils-2.32.0.dist-info}/WHEEL +0 -0
@@ -1,32 +1,11 @@
|
|
1
|
-
import
|
2
|
-
from datetime import timedelta
|
3
|
-
from functools import wraps
|
1
|
+
from datetime import timedelta
|
4
2
|
|
5
|
-
from osbot_utils.
|
3
|
+
from osbot_utils.helpers.duration.schemas.Schema__Duration import Schema__Duration
|
4
|
+
from osbot_utils.utils.Call_Stack import Call_Stack
|
5
|
+
from osbot_utils.utils.Misc import date_time_now, time_delta_to_str
|
6
6
|
|
7
|
-
from osbot_utils.utils.Misc import date_time_now, time_delta_to_str
|
8
7
|
|
9
|
-
|
10
|
-
def duration(func):
|
11
|
-
if inspect.iscoroutinefunction(func):
|
12
|
-
# It's an async function
|
13
|
-
@wraps(func)
|
14
|
-
async def async_wrapper(*args, **kwargs):
|
15
|
-
with Duration(prefix=f'.{func.__name__} took'):
|
16
|
-
return await func(*args, **kwargs)
|
17
|
-
return async_wrapper
|
18
|
-
else:
|
19
|
-
# It's a regular function
|
20
|
-
@wraps(func)
|
21
|
-
def sync_wrapper(*args, **kwargs):
|
22
|
-
with Duration(prefix=f'.{func.__name__} took'):
|
23
|
-
return func(*args, **kwargs)
|
24
|
-
return sync_wrapper
|
25
|
-
|
26
|
-
class Duration:
|
27
|
-
"""
|
28
|
-
Helper class for to capture time duration
|
29
|
-
"""
|
8
|
+
class Duration: # Helper class for to capture time duration
|
30
9
|
def __init__(self, prefix="\nDuration:", print_result=True, use_utc=True, print_stack=False):
|
31
10
|
self.use_utc = use_utc
|
32
11
|
self.print_result = print_result
|
@@ -47,6 +26,15 @@ class Duration:
|
|
47
26
|
def __exit__(self, exception_type, exception_value, exception_traceback):
|
48
27
|
self.end()
|
49
28
|
|
29
|
+
def data(self) -> Schema__Duration: # Returns the duration data in Schema__Duration format.
|
30
|
+
if not self.duration:
|
31
|
+
raise ValueError("Duration has not been calculated yet. Call end() first.")
|
32
|
+
|
33
|
+
return Schema__Duration( utc = self.use_utc ,
|
34
|
+
timestamp_start = self.start_time.timestamp(),
|
35
|
+
timestamp_end = self.end_time .timestamp(),
|
36
|
+
duration_seconds = self.seconds ())
|
37
|
+
|
50
38
|
def start(self):
|
51
39
|
self.start_time = date_time_now(use_utc=self.use_utc, return_str=False)
|
52
40
|
|
File without changes
|
File without changes
|
@@ -0,0 +1,21 @@
|
|
1
|
+
import inspect
|
2
|
+
from functools import wraps
|
3
|
+
|
4
|
+
from osbot_utils.helpers.duration.Duration import Duration
|
5
|
+
|
6
|
+
|
7
|
+
def duration(func):
|
8
|
+
if inspect.iscoroutinefunction(func):
|
9
|
+
# It's an async function
|
10
|
+
@wraps(func)
|
11
|
+
async def async_wrapper(*args, **kwargs):
|
12
|
+
with Duration(prefix=f'.{func.__name__} took'):
|
13
|
+
return await func(*args, **kwargs)
|
14
|
+
return async_wrapper
|
15
|
+
else:
|
16
|
+
# It's a regular function
|
17
|
+
@wraps(func)
|
18
|
+
def sync_wrapper(*args, **kwargs):
|
19
|
+
with Duration(prefix=f'.{func.__name__} took'):
|
20
|
+
return func(*args, **kwargs)
|
21
|
+
return sync_wrapper
|
File without changes
|
@@ -1,21 +1,21 @@
|
|
1
1
|
import asyncio
|
2
2
|
import logging
|
3
3
|
import typing
|
4
|
-
|
5
|
-
from osbot_utils.helpers.
|
6
|
-
from osbot_utils.helpers.flows.actions.
|
7
|
-
from osbot_utils.helpers.flows.models.Flow_Run__Event
|
8
|
-
from osbot_utils.type_safe.Type_Safe
|
9
|
-
from osbot_utils.helpers.CFormat
|
10
|
-
from osbot_utils.helpers.flows.models.Flow_Run__Config
|
11
|
-
from osbot_utils.helpers.flows.actions.Flow__Events
|
12
|
-
from osbot_utils.helpers.flows.models.Flow_Run__Event_Data
|
13
|
-
from osbot_utils.testing.Stdout
|
14
|
-
from osbot_utils.utils.Dev
|
15
|
-
from osbot_utils.utils.Misc
|
16
|
-
from osbot_utils.utils.Python_Logger
|
17
|
-
from osbot_utils.utils.Str
|
18
|
-
from osbot_utils.utils.Threads
|
4
|
+
from osbot_utils.helpers.Dependency_Manager import Dependency_Manager
|
5
|
+
from osbot_utils.helpers.flows.actions.Flow__Data import Flow__Data
|
6
|
+
from osbot_utils.helpers.flows.actions.Flow__Stats__Collector import Flow__Stats__Collector
|
7
|
+
from osbot_utils.helpers.flows.models.Flow_Run__Event import Flow_Run__Event
|
8
|
+
from osbot_utils.type_safe.Type_Safe import Type_Safe
|
9
|
+
from osbot_utils.helpers.CFormat import CFormat, f_dark_grey, f_magenta, f_bold
|
10
|
+
from osbot_utils.helpers.flows.models.Flow_Run__Config import Flow_Run__Config
|
11
|
+
from osbot_utils.helpers.flows.actions.Flow__Events import flow_events
|
12
|
+
from osbot_utils.helpers.flows.models.Flow_Run__Event_Data import Flow_Run__Event_Data
|
13
|
+
from osbot_utils.testing.Stdout import Stdout
|
14
|
+
from osbot_utils.utils.Dev import pprint
|
15
|
+
from osbot_utils.utils.Misc import random_id, lower, time_now
|
16
|
+
from osbot_utils.utils.Python_Logger import Python_Logger
|
17
|
+
from osbot_utils.utils.Str import ansis_to_texts
|
18
|
+
from osbot_utils.utils.Threads import invoke_in_new_event_loop
|
19
19
|
|
20
20
|
FLOW__RANDOM_ID__PREFIX = 'flow_id__'
|
21
21
|
FLOW__RANDOM_NAME__PREFIX = 'flow_name__'
|
@@ -23,9 +23,10 @@ FLOW__LOGGING__LOG_FORMAT = '%(asctime)s.%(msecs)03d | %(levelname)-8s | %(mess
|
|
23
23
|
FLOW__LOGGING__DATE_FORMAT = '%H:%M:%S'
|
24
24
|
|
25
25
|
|
26
|
-
# todo:
|
26
|
+
# todo: replace the flow_id (and task_id) with either Obj_Id or Safe_Id
|
27
27
|
class Flow(Type_Safe):
|
28
28
|
flow_data : Flow__Data
|
29
|
+
flow_stats : Flow__Stats__Collector
|
29
30
|
captured_exec_logs : list
|
30
31
|
data : dict # dict available to the tasks to add and collect data
|
31
32
|
flow_id : str # rename to flow_run_id (or also capture the flow_run_id)
|
@@ -82,6 +83,7 @@ class Flow(Type_Safe):
|
|
82
83
|
|
83
84
|
def execute_flow(self, flow_run_params=None): # todo: see if it makes more sense to call this start_flow_run
|
84
85
|
self.check_setup()
|
86
|
+
self.flow_stats.start(flow_id=self.flow_id, flow_name=self.flow_name) # start the flow stats collector
|
85
87
|
flow_events.on__flow__start(self.flow_event_data())
|
86
88
|
self.log_debug(f"Created flow run '{self.f__flow_id()}' for flow '{self.f__flow_name()}'")
|
87
89
|
self.set_flow_run_params(flow_run_params)
|
@@ -101,6 +103,7 @@ class Flow(Type_Safe):
|
|
101
103
|
self.log_error(self.cformat.red(f"Error executing flow: {error}"))
|
102
104
|
self.flow_data.set_error(error)
|
103
105
|
|
106
|
+
self.flow_stats.end (self.flow_error)
|
104
107
|
self.log_captured_stdout (stdout)
|
105
108
|
self.print_flow_return_value ()
|
106
109
|
self.print_flow_finished_message()
|
@@ -119,6 +122,11 @@ class Flow(Type_Safe):
|
|
119
122
|
def captured_logs(self):
|
120
123
|
return ansis_to_texts(self.captured_exec_logs)
|
121
124
|
|
125
|
+
def durations(self):
|
126
|
+
return self.flow_stats.durations()
|
127
|
+
|
128
|
+
def durations__with_tasks_status(self):
|
129
|
+
return self.flow_stats.durations__with_tasks_status()
|
122
130
|
|
123
131
|
async def invoke_flow_target__thread(self, flow): # this is a REALLY important method which is used to pin the flow object to the call stack
|
124
132
|
return await flow.flow_target(*flow.resolved_args, **flow.resolved_kwargs) # which is then used by the Task.find_flow method to find it
|
@@ -2,14 +2,15 @@ import inspect
|
|
2
2
|
import traceback
|
3
3
|
import typing
|
4
4
|
|
5
|
-
from osbot_utils.helpers.flows.
|
6
|
-
from osbot_utils.
|
7
|
-
from osbot_utils.
|
8
|
-
from osbot_utils.helpers.
|
9
|
-
from osbot_utils.
|
10
|
-
from osbot_utils.
|
11
|
-
from osbot_utils.
|
12
|
-
from osbot_utils.
|
5
|
+
from osbot_utils.helpers.flows.actions.Task__Stats__Collector import Task__Stats__Collector
|
6
|
+
from osbot_utils.helpers.flows.models.Flow_Run__Event_Data import Flow_Run__Event_Data
|
7
|
+
from osbot_utils.utils.Misc import random_id, lower
|
8
|
+
from osbot_utils.helpers.Dependency_Manager import Dependency_Manager
|
9
|
+
from osbot_utils.helpers.flows.actions.Flow__Events import flow_events
|
10
|
+
from osbot_utils.testing.Stdout import Stdout
|
11
|
+
from osbot_utils.helpers.CFormat import CFormat, f_dark_grey, f_red, f_blue, f_bold
|
12
|
+
from osbot_utils.type_safe.Type_Safe import Type_Safe
|
13
|
+
from osbot_utils.helpers.flows.Flow import Flow
|
13
14
|
|
14
15
|
TASK__RANDOM_ID__PREFIX = 'task_id__'
|
15
16
|
|
@@ -18,6 +19,7 @@ TASK__RANDOM_ID__PREFIX = 'task_id__'
|
|
18
19
|
class Task(Type_Safe):
|
19
20
|
data : dict # dict available to the task to add and collect data
|
20
21
|
task_id : str
|
22
|
+
task_stats : Task__Stats__Collector
|
21
23
|
task_name : str # make this the function mame
|
22
24
|
cformat : CFormat
|
23
25
|
resolved_args : tuple
|
@@ -63,6 +65,9 @@ class Task(Type_Safe):
|
|
63
65
|
if not self.task_id:
|
64
66
|
self.task_id = self.random_task_id()
|
65
67
|
|
68
|
+
execution_order = self.task_flow.flow_stats.get_next_execution_order()
|
69
|
+
self.task_stats.start(flow_id=self.task_flow.flow_id, task_id=self.task_id, task_name=self.task_name, execution_order=execution_order)
|
70
|
+
|
66
71
|
self.on_task_start()
|
67
72
|
flow_events.on__task__start(self.task_event_data())
|
68
73
|
|
@@ -105,6 +110,11 @@ class Task(Type_Safe):
|
|
105
110
|
self.task_flow.log_captured_stdout(stdout)
|
106
111
|
|
107
112
|
def execute__after(self):
|
113
|
+
|
114
|
+
self.task_stats.end(task_error=self.task_error)
|
115
|
+
self.task_flow.flow_stats.add_task_stats(self.task_stats.stats)
|
116
|
+
|
117
|
+
|
108
118
|
self.print_task_return_value()
|
109
119
|
|
110
120
|
if self.task_error:
|
@@ -5,7 +5,6 @@ from osbot_utils.helpers.flows.models.Schema__Flow__Artifact import Schema__F
|
|
5
5
|
from osbot_utils.helpers.flows.models.Schema__Flow__Result import Schema__Flow__Result
|
6
6
|
from osbot_utils.helpers.flows.schemas.Schema__Flow import Schema__Flow
|
7
7
|
from osbot_utils.helpers.flows.schemas.Schema__Flow__Data import Schema__Flow__Data
|
8
|
-
#from osbot_utils.helpers.flows.schemas.Schema__Flow__Event import Schema__Flow__Event
|
9
8
|
from osbot_utils.helpers.flows.schemas.Schema__Flow__Log import Schema__Flow__Log
|
10
9
|
from osbot_utils.helpers.flows.schemas.Schema__Flow__Task__Data import Schema__Flow__Task__Data
|
11
10
|
from osbot_utils.type_safe.Type_Safe import Type_Safe
|
@@ -0,0 +1,83 @@
|
|
1
|
+
from typing import Dict
|
2
|
+
from osbot_utils.helpers.duration.Duration import Duration
|
3
|
+
from osbot_utils.helpers.flows.schemas.Schema__Flow__Status import Schema__Flow__Status
|
4
|
+
from osbot_utils.helpers.flows.schemas.Schema__Task__Stats import Schema__Task__Stats
|
5
|
+
from osbot_utils.helpers.flows.schemas.Schema__Flow__Stats import Schema__Flow__Stats
|
6
|
+
from osbot_utils.type_safe.Type_Safe import Type_Safe
|
7
|
+
|
8
|
+
FLOW__ERROR_MESSAGE__TASK_FAILED = 'At least one task failed'
|
9
|
+
|
10
|
+
class Flow__Stats__Collector(Type_Safe):
|
11
|
+
duration : Duration
|
12
|
+
stats : Schema__Flow__Stats
|
13
|
+
task_execution_counter : int
|
14
|
+
|
15
|
+
def start(self, flow_id: str, flow_name:str):
|
16
|
+
self.duration.print_result = False
|
17
|
+
self.duration.start()
|
18
|
+
self.task_execution_counter = 0
|
19
|
+
with self.stats as _:
|
20
|
+
_.flow_id = flow_id
|
21
|
+
_.flow_name = flow_name
|
22
|
+
_.status = Schema__Flow__Status.RUNNING
|
23
|
+
return self
|
24
|
+
|
25
|
+
def end(self, flow_error:Exception):
|
26
|
+
self.duration.end()
|
27
|
+
with self.stats as _:
|
28
|
+
_.duration = self.duration.data()
|
29
|
+
_.total_tasks = len(self.stats.tasks_stats)
|
30
|
+
_.failed_tasks = sum(1 for task in self.stats.tasks_stats.values() if task.status == Schema__Flow__Status.FAILED)
|
31
|
+
|
32
|
+
if flow_error:
|
33
|
+
_.status = Schema__Flow__Status.FAILED
|
34
|
+
_.error_message = str(flow_error)
|
35
|
+
elif _.failed_tasks:
|
36
|
+
_.status = Schema__Flow__Status.FAILED
|
37
|
+
_.error_message = FLOW__ERROR_MESSAGE__TASK_FAILED
|
38
|
+
else:
|
39
|
+
_.status = Schema__Flow__Status.COMPLETED
|
40
|
+
return self
|
41
|
+
|
42
|
+
def get_next_execution_order(self): # Get the next execution order number and increment the counter."""
|
43
|
+
self.task_execution_counter += 1
|
44
|
+
return self.task_execution_counter
|
45
|
+
|
46
|
+
def add_task_stats(self, task_stats: Schema__Task__Stats): # Add task stats to the collection.
|
47
|
+
self.stats.tasks_stats[task_stats.task_id] = task_stats
|
48
|
+
return self
|
49
|
+
|
50
|
+
def json(self): # Return JSON representation of the stats.
|
51
|
+
return self.stats.json()
|
52
|
+
|
53
|
+
def durations__with_tasks_status(self):
|
54
|
+
with self.stats as _:
|
55
|
+
tasks_durations = dict()
|
56
|
+
flow_durations = dict(flow_name = _.flow_name ,
|
57
|
+
flow_duration = _.duration.duration_seconds,
|
58
|
+
flow_status = _.status.value ,
|
59
|
+
flow_tasks = tasks_durations )
|
60
|
+
|
61
|
+
for task_id, flow_task in self.stats.tasks_stats.items():
|
62
|
+
task_duration = dict(task_name = flow_task.task_name ,
|
63
|
+
task_duration = flow_task.duration.duration_seconds,
|
64
|
+
task_status = flow_task.status.value )
|
65
|
+
execution_order = flow_task.execution_order
|
66
|
+
tasks_durations[execution_order] = task_duration
|
67
|
+
return flow_durations
|
68
|
+
|
69
|
+
def durations(self):
|
70
|
+
with self.stats as _:
|
71
|
+
if _.status is None:
|
72
|
+
flow_durations = dict()
|
73
|
+
else:
|
74
|
+
tasks_durations = dict()
|
75
|
+
flow_durations = dict(flow_name = _.flow_name ,
|
76
|
+
flow_duration = _.duration.duration_seconds,
|
77
|
+
flow_status = _.status.value ,
|
78
|
+
flow_tasks = tasks_durations )
|
79
|
+
|
80
|
+
for task_id, flow_task in self.stats.tasks_stats.items():
|
81
|
+
|
82
|
+
tasks_durations[flow_task.task_name] = flow_task.duration.duration_seconds
|
83
|
+
return flow_durations
|
@@ -0,0 +1,34 @@
|
|
1
|
+
from osbot_utils.helpers.duration.Duration import Duration
|
2
|
+
from osbot_utils.helpers.flows.schemas.Schema__Flow__Status import Schema__Flow__Status
|
3
|
+
from osbot_utils.helpers.flows.schemas.Schema__Task__Stats import Schema__Task__Stats
|
4
|
+
from osbot_utils.type_safe.Type_Safe import Type_Safe
|
5
|
+
|
6
|
+
class Task__Stats__Collector(Type_Safe):
|
7
|
+
duration : Duration
|
8
|
+
stats : Schema__Task__Stats
|
9
|
+
|
10
|
+
def start(self, flow_id: str, task_id: str, task_name: str , execution_order:int):
|
11
|
+
self.duration.print_result = False
|
12
|
+
self.duration.start()
|
13
|
+
with self.stats as _:
|
14
|
+
_.parent_flow_id = flow_id
|
15
|
+
_.execution_order = execution_order
|
16
|
+
_.status = Schema__Flow__Status.RUNNING
|
17
|
+
_.task_id = task_id
|
18
|
+
_.task_name = task_name
|
19
|
+
return self
|
20
|
+
|
21
|
+
def end(self, task_error: Exception):
|
22
|
+
self.duration.end()
|
23
|
+
with self.stats as _:
|
24
|
+
_.duration = self.duration.data()
|
25
|
+
if task_error:
|
26
|
+
_.status = Schema__Flow__Status.FAILED
|
27
|
+
_.error_message = str(task_error)
|
28
|
+
else:
|
29
|
+
_.status = Schema__Flow__Status.COMPLETED
|
30
|
+
return self
|
31
|
+
|
32
|
+
|
33
|
+
def json(self): # Return JSON representation of the stats.
|
34
|
+
return self.stats.json()
|
@@ -0,0 +1,16 @@
|
|
1
|
+
from typing import Dict
|
2
|
+
from osbot_utils.helpers.duration.schemas.Schema__Duration import Schema__Duration
|
3
|
+
from osbot_utils.helpers.flows.schemas.Schema__Flow__Status import Schema__Flow__Status
|
4
|
+
from osbot_utils.helpers.flows.schemas.Schema__Task__Stats import Schema__Task__Stats
|
5
|
+
from osbot_utils.type_safe.Type_Safe import Type_Safe
|
6
|
+
|
7
|
+
|
8
|
+
class Schema__Flow__Stats(Type_Safe):
|
9
|
+
duration : Schema__Duration # How long the flow took to execute
|
10
|
+
error_message: str = None # Error message if flow failed
|
11
|
+
failed_tasks : int # Number of failed tasks
|
12
|
+
flow_id : str # Unique identifier for the flow
|
13
|
+
flow_name : str # Name of the flow
|
14
|
+
status : Schema__Flow__Status # 'completed', 'failed', 'running'
|
15
|
+
tasks_stats : Dict[str, Schema__Task__Stats] # Map of task_id to task stats
|
16
|
+
total_tasks : int # Total number of tasks executed
|
@@ -0,0 +1,13 @@
|
|
1
|
+
from osbot_utils.helpers.duration.schemas.Schema__Duration import Schema__Duration
|
2
|
+
from osbot_utils.helpers.flows.schemas.Schema__Flow__Status import Schema__Flow__Status
|
3
|
+
from osbot_utils.type_safe.Type_Safe import Type_Safe
|
4
|
+
|
5
|
+
|
6
|
+
class Schema__Task__Stats(Type_Safe):
|
7
|
+
task_id : str # Unique identifier for the task
|
8
|
+
task_name : str # Name of the task
|
9
|
+
execution_order: int # Order in which the task was executed
|
10
|
+
duration : Schema__Duration # How long the task took to execute
|
11
|
+
status : Schema__Flow__Status # 'completed', 'failed', 'running'
|
12
|
+
parent_flow_id : str # ID of the flow that contains this task
|
13
|
+
error_message : str = None # Error message if task failed
|
osbot_utils/helpers/ssh/SCP.py
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
-
from osbot_utils.
|
2
|
-
from osbot_utils.helpers.ssh.SSH__Execute
|
3
|
-
from osbot_utils.testing.Temp_Zip
|
4
|
-
from osbot_utils.utils.Files
|
5
|
-
from osbot_utils.utils.Process
|
6
|
-
from osbot_utils.utils.Status
|
1
|
+
from osbot_utils.helpers.duration.decorators.capture_duration import capture_duration
|
2
|
+
from osbot_utils.helpers.ssh.SSH__Execute import SSH__Execute
|
3
|
+
from osbot_utils.testing.Temp_Zip import Temp_Zip
|
4
|
+
from osbot_utils.utils.Files import file_not_exists, file_name
|
5
|
+
from osbot_utils.utils.Process import start_process
|
6
|
+
from osbot_utils.utils.Status import status_error
|
7
7
|
|
8
8
|
|
9
9
|
|
@@ -1,13 +1,13 @@
|
|
1
|
-
from osbot_utils.type_safe.Type_Safe
|
2
|
-
from osbot_utils.
|
3
|
-
from osbot_utils.decorators.lists.group_by
|
4
|
-
from osbot_utils.decorators.lists.index_by
|
5
|
-
from osbot_utils.utils.Dev
|
6
|
-
from osbot_utils.utils.Env
|
7
|
-
from osbot_utils.utils.Http
|
8
|
-
from osbot_utils.utils.Misc
|
9
|
-
from osbot_utils.utils.Process
|
10
|
-
from osbot_utils.utils.Status
|
1
|
+
from osbot_utils.type_safe.Type_Safe import Type_Safe
|
2
|
+
from osbot_utils.helpers.duration.decorators.capture_duration import capture_duration
|
3
|
+
from osbot_utils.decorators.lists.group_by import group_by
|
4
|
+
from osbot_utils.decorators.lists.index_by import index_by
|
5
|
+
from osbot_utils.utils.Dev import pprint
|
6
|
+
from osbot_utils.utils.Env import get_env
|
7
|
+
from osbot_utils.utils.Http import is_port_open
|
8
|
+
from osbot_utils.utils.Misc import str_to_int, str_to_bool
|
9
|
+
from osbot_utils.utils.Process import start_process, run_process
|
10
|
+
from osbot_utils.utils.Status import status_error
|
11
11
|
|
12
12
|
ENV_VAR__SSH__HOST = 'SSH__HOST'
|
13
13
|
ENV_VAR__SSH__PORT = 'SSH__PORT'
|
@@ -1,7 +1,8 @@
|
|
1
|
-
from osbot_utils.helpers.Print_Table
|
2
|
-
from osbot_utils.
|
1
|
+
from osbot_utils.helpers.Print_Table import Print_Table
|
2
|
+
from osbot_utils.helpers.duration.Duration import Duration
|
3
|
+
from osbot_utils.utils.Call_Stack import Call_Stack
|
4
|
+
|
3
5
|
|
4
|
-
from osbot_utils.testing.Duration import Duration
|
5
6
|
|
6
7
|
class Hook_Method:
|
7
8
|
|
@@ -1,4 +1,8 @@
|
|
1
1
|
import types
|
2
2
|
from enum import EnumMeta
|
3
3
|
|
4
|
-
|
4
|
+
from osbot_utils.helpers.Safe_Id import Safe_Id
|
5
|
+
|
6
|
+
IMMUTABLE_TYPES = (bool, int, float, complex, str, bytes, types.NoneType, EnumMeta, type,
|
7
|
+
Safe_Id # ok to add since these classes use str as a base class
|
8
|
+
)
|
@@ -176,7 +176,7 @@ class Type_Safe__Step__From_Json:
|
|
176
176
|
if type(json_data) is str:
|
177
177
|
json_data = json_parse(json_data)
|
178
178
|
if json_data: # if there is no data or is {} then don't create an object (since this could be caused by bad data being provided)
|
179
|
-
return self.deserialize_from_dict(_cls(), json_data,raise_on_not_found=raise_on_not_found)
|
179
|
+
return self.deserialize_from_dict(_cls(), json_data, raise_on_not_found=raise_on_not_found)
|
180
180
|
return _cls()
|
181
181
|
|
182
182
|
type_safe_step_from_json = Type_Safe__Step__From_Json()
|
osbot_utils/version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
v2.
|
1
|
+
v2.32.0
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: osbot_utils
|
3
|
-
Version: 2.
|
3
|
+
Version: 2.32.0
|
4
4
|
Summary: OWASP Security Bot - Utils
|
5
5
|
License: MIT
|
6
6
|
Author: Dinis Cruz
|
@@ -23,7 +23,7 @@ Description-Content-Type: text/markdown
|
|
23
23
|
|
24
24
|
Powerful Python util methods and classes that simplify common apis and tasks.
|
25
25
|
|
26
|
-

|
27
27
|
[](https://codecov.io/gh/owasp-sbot/OSBot-Utils)
|
28
28
|
|
29
29
|
|
@@ -5,9 +5,7 @@ osbot_utils/base_classes/Kwargs_To_Self.py,sha256=3LRFpxdg9RBuUlIacF1Bwq014NXtJm
|
|
5
5
|
osbot_utils/base_classes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
6
6
|
osbot_utils/context_managers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
7
7
|
osbot_utils/context_managers/async_invoke.py,sha256=-ja3K8orLy8Of54CIYSK-zn443pOIDY2hnFBjVELrXc,829
|
8
|
-
osbot_utils/context_managers/capture_duration.py,sha256=8ObmbP9_qfYtxx30NGXThRE_E1XZ5IXtX9PHWqtLGfs,1240
|
9
8
|
osbot_utils/context_managers/disable_root_loggers.py,sha256=0-zQk11TBqwhTHCN4vNhDApojtJ4oR0oMPRcwclcXZA,960
|
10
|
-
osbot_utils/context_managers/print_duration.py,sha256=jleIYxmz-vbWbcZZPuTWMNavJgxYkATwrVk5H-2SHj4,272
|
11
9
|
osbot_utils/decorators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
12
10
|
osbot_utils/decorators/classes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
13
11
|
osbot_utils/decorators/classes/singleton.py,sha256=ZBYw2W4Qmo0mlHQQqDJyScaXO6pmbftru9YBBdUowjY,332
|
@@ -136,11 +134,21 @@ osbot_utils/helpers/cache_requests/Cache__Requests__Row.py,sha256=Sb7E_zDB-LPlWI
|
|
136
134
|
osbot_utils/helpers/cache_requests/Cache__Requests__Table.py,sha256=BW7tXM0TFYma3Db4M-58IKpx0vevLuFsH7QQeiggPaI,388
|
137
135
|
osbot_utils/helpers/cache_requests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
138
136
|
osbot_utils/helpers/cache_requests/flows/flow__Cache__Requests.py,sha256=xgx_oExxkcvRwQN1UCobimECIMUKGoIX5oGdCmp8Nyw,243
|
139
|
-
osbot_utils/helpers/
|
140
|
-
osbot_utils/helpers/
|
137
|
+
osbot_utils/helpers/duration/Duration.py,sha256=KvHaAB6NWa40DXQl2gC9m98gM-arVP-aYqFrmAyQQzM,2306
|
138
|
+
osbot_utils/helpers/duration/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
139
|
+
osbot_utils/helpers/duration/decorators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
140
|
+
osbot_utils/helpers/duration/decorators/capture_duration.py,sha256=8ObmbP9_qfYtxx30NGXThRE_E1XZ5IXtX9PHWqtLGfs,1240
|
141
|
+
osbot_utils/helpers/duration/decorators/duration.py,sha256=ucJP1fCQEN8ALCDCG9CPzPn1KqojD4ttFc3HLke-nvY,651
|
142
|
+
osbot_utils/helpers/duration/decorators/print_duration.py,sha256=w7k3OPiRkL5KqLv0S5o1NVo2y_TeOOvDOb-51YbJjAc,283
|
143
|
+
osbot_utils/helpers/duration/schemas/Schema__Duration.py,sha256=-h32wBcpiVRkEbc_sZoamnRFNGaQQM4YsxqoVzPGe38,209
|
144
|
+
osbot_utils/helpers/duration/schemas/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
145
|
+
osbot_utils/helpers/flows/Flow.py,sha256=2lsMliabGiNvfUW3S8mpfqt_fy4x0lRXLbn4hN1vUOQ,13828
|
146
|
+
osbot_utils/helpers/flows/Task.py,sha256=RfccOCev5XTsNoKuDJzK1JItF-Lm7P6FGCGZyh9swyY,7116
|
141
147
|
osbot_utils/helpers/flows/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
142
|
-
osbot_utils/helpers/flows/actions/Flow__Data.py,sha256=
|
148
|
+
osbot_utils/helpers/flows/actions/Flow__Data.py,sha256=rgUggQo_z6KLtNa92KfzRG6ORdT_8ic5zJVuhk_st38,5064
|
143
149
|
osbot_utils/helpers/flows/actions/Flow__Events.py,sha256=g7KBafFeA7tV-v31v_m3MT__cZEX63gh8CehnZwRYU0,2840
|
150
|
+
osbot_utils/helpers/flows/actions/Flow__Stats__Collector.py,sha256=GCszqIGj8yVlr283ZXiejDCof-tbDgynjzAdmhEqBWg,4155
|
151
|
+
osbot_utils/helpers/flows/actions/Task__Stats__Collector.py,sha256=rDYABaHpikIAK0Odleu8-dZ9ECJZYDmgFdd0KvsbByI,1462
|
144
152
|
osbot_utils/helpers/flows/actions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
145
153
|
osbot_utils/helpers/flows/decorators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
146
154
|
osbot_utils/helpers/flows/decorators/flow.py,sha256=7wj5TtUO_ffbACnagZtZ6LfFgclmbQSfn2lKkMMrnJI,670
|
@@ -157,7 +165,10 @@ osbot_utils/helpers/flows/schemas/Schema__Flow__Data.py,sha256=cqSreXlumqPnM_DfF
|
|
157
165
|
osbot_utils/helpers/flows/schemas/Schema__Flow__Event.py,sha256=aeoJotmkYgtEsxyLp6YxoblQFscdAzadI5WOsfYG6-s,616
|
158
166
|
osbot_utils/helpers/flows/schemas/Schema__Flow__Event__Data.py,sha256=ugevIeeNIcXiusQiw8BqXikpl_BXvKZrZLZjYg5J9SQ,567
|
159
167
|
osbot_utils/helpers/flows/schemas/Schema__Flow__Log.py,sha256=OUjnExtlHlDZYQ8o2wLl_oRCUBu7rEoAjX_5__yaRI8,392
|
168
|
+
osbot_utils/helpers/flows/schemas/Schema__Flow__Stats.py,sha256=2YeYHTs7rlA5wGt9Jowr0z3b4ZzZF-0GGx_tCSttjOs,1171
|
169
|
+
osbot_utils/helpers/flows/schemas/Schema__Flow__Status.py,sha256=3DSUTPqggnJhpHQAtGhiWj8zT2yRbq6MIQk31ap_5ds,181
|
160
170
|
osbot_utils/helpers/flows/schemas/Schema__Flow__Task__Data.py,sha256=BQQvR02n1YAT59I70GT06MBdJbgaDnZBGhaV9Q90oBQ,657
|
171
|
+
osbot_utils/helpers/flows/schemas/Schema__Task__Stats.py,sha256=DSja48dPeQPBzzJMtKjJrwEEHb4MqBv0nvm2YC_pTpk,858
|
161
172
|
osbot_utils/helpers/flows/schemas/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
162
173
|
osbot_utils/helpers/generators/Generator_Context_Manager.py,sha256=STpCn2Zh5G2TmyYMjeLMjfpkSYUUeU6mzV_O6Hu4g4Q,863
|
163
174
|
osbot_utils/helpers/generators/Generator_Manager.py,sha256=XxE7ZZvziorolEM5FoMq-5yOFUi3yVaWcPB_XWHtm30,11728
|
@@ -233,10 +244,10 @@ osbot_utils/helpers/sqlite/tables/Sqlite__Table__Edges.py,sha256=YwlWj9GYBDeotqD
|
|
233
244
|
osbot_utils/helpers/sqlite/tables/Sqlite__Table__Files.py,sha256=4YguiuqzcfTadPWV67lN4IU_8xJzJF--ZRMqbEyzXqw,3800
|
234
245
|
osbot_utils/helpers/sqlite/tables/Sqlite__Table__Nodes.py,sha256=GT8h3wD4hGvEtqQuBs0sBbcu2ydktRHTi95PEL2ffHQ,1721
|
235
246
|
osbot_utils/helpers/sqlite/tables/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
236
|
-
osbot_utils/helpers/ssh/SCP.py,sha256=
|
247
|
+
osbot_utils/helpers/ssh/SCP.py,sha256=pMrb0S3xTFNrJsGLlTe6OnvAWVXiXgVv3Q5VWs_J52I,3396
|
237
248
|
osbot_utils/helpers/ssh/SSH.py,sha256=KPmIewh-ucGqubrwZoZILhX60MCV9UEw8do8JKrZ91s,1542
|
238
249
|
osbot_utils/helpers/ssh/SSH__Cache__Requests.py,sha256=Dqh4biVcuaXbQVvn3Tx-kSGBGHiF-2wVsgu96EhD6gU,3359
|
239
|
-
osbot_utils/helpers/ssh/SSH__Execute.py,sha256=
|
250
|
+
osbot_utils/helpers/ssh/SSH__Execute.py,sha256=Z0W-cgVxwwSwVTBCrycRe6kyTPz19AgpcWmPVxbAO_w,7090
|
240
251
|
osbot_utils/helpers/ssh/SSH__Health_Check.py,sha256=WDmBD6ejNcBeicXfjpsiNzH-WR3Jejx0re3WfwjSWyQ,2083
|
241
252
|
osbot_utils/helpers/ssh/SSH__Linux.py,sha256=O1uyKcklaj2tHqQZln7dVinzjl9-EI52KzP8ojQr244,4330
|
242
253
|
osbot_utils/helpers/ssh/SSH__Linux__Amazon.py,sha256=ZJFb7LFTvclAuhH5OoOtJ361NoX9ecHTaFX-iSmnzmk,596
|
@@ -269,8 +280,7 @@ osbot_utils/helpers/xml/rss/RSS__Image.py,sha256=13k8K03VTZbP0efeDL07oZF7Lg0CQcc
|
|
269
280
|
osbot_utils/helpers/xml/rss/RSS__Item.py,sha256=K6YF3EVUu6E-_ISke98QXgnJlfOI5YAIO4pBzUZq7gE,608
|
270
281
|
osbot_utils/testing/Catch.py,sha256=HdNoKnrPBjvVj87XYN-Wa1zpo5z3oByURT6TKbd5QpQ,2229
|
271
282
|
osbot_utils/testing/Custom_Handler_For_Http_Tests.py,sha256=LKscFEcuwTQQ9xl4q71PR5FA8U-q8OtfTkCJoIgQIoQ,5358
|
272
|
-
osbot_utils/testing/
|
273
|
-
osbot_utils/testing/Hook_Method.py,sha256=uCpc89ZhMCfWiyt3tFhIGIInXiY6wTuwAZ1I8UQVRuw,4365
|
283
|
+
osbot_utils/testing/Hook_Method.py,sha256=QoxdbxnVLa4-VYrMCMmo66BoR6nR2BP0Q15asaJXacs,4405
|
274
284
|
osbot_utils/testing/Log_To_Queue.py,sha256=pZQ7I1ne-H365a4WLS60oAD-B16pxIZO4suvCdaTW8U,1703
|
275
285
|
osbot_utils/testing/Log_To_String.py,sha256=hkjWsJfV68uqgX9nvVqUN3mVPxZQDb-6UBwsSEbQnkA,1216
|
276
286
|
osbot_utils/testing/Logging.py,sha256=rzO1cCwty1oTucbV1q6U2QBIF87oOcvZoAY_R8SQB8A,3300
|
@@ -313,13 +323,13 @@ osbot_utils/type_safe/shared/Type_Safe__Json_Compressor.py,sha256=TDbot_NNzCPXBQ
|
|
313
323
|
osbot_utils/type_safe/shared/Type_Safe__Json_Compressor__Type_Registry.py,sha256=wYOCg7F1nTrRn8HlnZvrs_8A8WL4gxRYRLnXZpGIiuk,1119
|
314
324
|
osbot_utils/type_safe/shared/Type_Safe__Not_Cached.py,sha256=25FAl6SOLxdStco_rm9tgOYLfuKyBWheGdl7vVa56UU,800
|
315
325
|
osbot_utils/type_safe/shared/Type_Safe__Raise_Exception.py,sha256=pbru8k8CTQMNUfmFBndiJhg2KkqEYzFvJAPcNZHeHfQ,829
|
316
|
-
osbot_utils/type_safe/shared/Type_Safe__Shared__Variables.py,sha256=
|
326
|
+
osbot_utils/type_safe/shared/Type_Safe__Shared__Variables.py,sha256=A2ztu-9EYjkzrW2NqCl7cdr2ivVl0n9nZXCZHWfl8W4,302
|
317
327
|
osbot_utils/type_safe/shared/Type_Safe__Validation.py,sha256=1oamgApW2Pug0vvTqMLPxBLFvtcnp1bFnjSUByfJBrs,19192
|
318
328
|
osbot_utils/type_safe/shared/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
319
329
|
osbot_utils/type_safe/steps/Type_Safe__Step__Class_Kwargs.py,sha256=snoyJKvZ1crgF2fp0zexwNPnV_E63RfyRIsMAZdrKNY,6995
|
320
330
|
osbot_utils/type_safe/steps/Type_Safe__Step__Default_Kwargs.py,sha256=tzKXDUc0HVP5QvCWsmcPuuZodNvQZ9FeMDNI2x00Ngw,1943
|
321
331
|
osbot_utils/type_safe/steps/Type_Safe__Step__Default_Value.py,sha256=K_tkVQyLUbbWYzDnzoPLCgDBAFYyUjAG4VdLsvjzL1g,4485
|
322
|
-
osbot_utils/type_safe/steps/Type_Safe__Step__From_Json.py,sha256=
|
332
|
+
osbot_utils/type_safe/steps/Type_Safe__Step__From_Json.py,sha256=mf0HvluDy-TgNiQy-SCdZcG2v3MXP7GHhmsrgyq8WfM,13043
|
323
333
|
osbot_utils/type_safe/steps/Type_Safe__Step__Init.py,sha256=v4FD7zxQiOFLiOF1Ma8wZMP8aLgRlXwJZnsIfBu2zeg,1266
|
324
334
|
osbot_utils/type_safe/steps/Type_Safe__Step__Set_Attr.py,sha256=VuKHH9QEYlbAL9R4zwQ5dwexx2sFY6wMx52QmF7eqcg,5219
|
325
335
|
osbot_utils/type_safe/steps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -355,8 +365,8 @@ osbot_utils/utils/Toml.py,sha256=Rxl8gx7mni5CvBAK-Ai02EKw-GwtJdd3yeHT2kMloik,166
|
|
355
365
|
osbot_utils/utils/Version.py,sha256=Ww6ChwTxqp1QAcxOnztkTicShlcx6fbNsWX5xausHrg,422
|
356
366
|
osbot_utils/utils/Zip.py,sha256=pR6sKliUY0KZXmqNzKY2frfW-YVQEVbLKiyqQX_lc-8,14052
|
357
367
|
osbot_utils/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
358
|
-
osbot_utils/version,sha256=
|
359
|
-
osbot_utils-2.
|
360
|
-
osbot_utils-2.
|
361
|
-
osbot_utils-2.
|
362
|
-
osbot_utils-2.
|
368
|
+
osbot_utils/version,sha256=Xtxmpk2pLg4RSnFef8ZPZCvLkvPlYukwfufYx4QcYGE,8
|
369
|
+
osbot_utils-2.32.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
370
|
+
osbot_utils-2.32.0.dist-info/METADATA,sha256=PzZ7X2sewild0Lt65T2qSXnyl8ZDW-1BJ4I-BzX5ftU,1329
|
371
|
+
osbot_utils-2.32.0.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
|
372
|
+
osbot_utils-2.32.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|