Skip to content

Commit

Permalink
minor fix in Flow
Browse files Browse the repository at this point in the history
wired back performance tests in Type_Safe steps
  • Loading branch information
DinisCruz committed Feb 10, 2025
1 parent 04bcaf8 commit 8bf30af
Show file tree
Hide file tree
Showing 11 changed files with 110 additions and 88 deletions.
32 changes: 18 additions & 14 deletions docs/dev/Python-code-formatting-guidelines.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ class SomeClass:
class SomeClass:
def __init__(self, param_one ,
param_two
) -> None:
)-> None:
self.param_one = param_one
self.param_two = param_two
```
Expand Down Expand Up @@ -149,7 +149,7 @@ from osbot_utils.helpers.Safe_Id import Safe_Id
def method_name(self, first_param : Type1 , # Method purpose comment
second_param : Type2 , # Aligned at column 80
third_param : Type3 = None # Default values align with type
) -> ReturnType: # Return on new line
) -> ReturnType: # Return on new line
```

Key aspects:
Expand All @@ -158,9 +158,11 @@ Key aspects:
- Type hints align in their own column
- Commas align in their own column
- Backslash continuation before return type
- Return type aligns with self variable name
- Return type aligns with the first variable name
- Comments align at column 80
- vertical alignment on : , #
- DON'T use this when there is only one param or when (where are no types or default values being set)
- the format for the return type is ") -> {return type}"

### Parameter Documentation

Expand All @@ -169,7 +171,7 @@ def complex_operation(self, data_input : Dict [str, Any] ,
config_options : Optional[Config ] , # Processing configuration
max_retries : int = 3 , # Maximum retry attempts
timeout_ms : float = 1000.0 # Operation timeout
) -> Tuple[Results, Metrics]: # Returns results and metrics
) -> Tuple[Results, Metrics]: # Returns results and metrics
```

Guidelines:
Expand All @@ -186,26 +188,26 @@ Methods should be grouped by functionality with clear separation:
```python
# Core initialization methods
def __init__(self, config : Config # Initialize with configuration
) -> None:
) -> None:

def setup(self, options: Dict[str, Any] # Configure processing options
) -> bool:
) -> bool:


# Data validation methods
def validate_input(self, data : InputData , # Validate input format
strict_mode : bool = False # Enable strict validation
) -> ValidationResult:
) -> ValidationResult:

def validate_output(self, result : OutputData , # Validate output format
thresholds : Thresholds # Validation thresholds
) -> bool:
) -> bool:


# Processing methods
def process_item(self, item : DataItem , # Process single data item
settings : Settings # Processing settings
) -> ProcessedItem:
) -> ProcessedItem:
```
Note how the return type name assigns with the variable self, and there is always at least one space before the : and the ,

Expand All @@ -215,11 +217,11 @@ For methods with complex type signatures:

```python
def process_batch(self, items : List[DataItem] , # Batch of items to process
batch_config : BatchConfig , # Batch processing config
error_handler : ErrorHandler , # Handles processing errors
retry_strategy : Optional[Strategy] , # Retry strategy to use
metrics_callback : Callable[[Metrics], None] = None # Metrics reporting callback
) -> BatchResults: # Processed batch results
batch_config : BatchConfig , # Batch processing config
error_handler : ErrorHandler , # Handles processing errors
retry_strategy : Optional[Strategy] , # Retry strategy to use
metrics_callback : Callable[[Metrics], None] = None # Metrics reporting callback
) -> BatchResults: # Processed batch results
```

Guidelines:
Expand Down Expand Up @@ -309,6 +311,8 @@ class test_Schema__MGraph__Node(TestCase):
- Inline documentation should be minimal and descriptive
- Comments explaining test cases should be aligned with the code
- Complex test setups should include explanatory comments
- DON'T add docstrings to methods or classes
- methods or classes can have a comment in the same line as the method return value (column aligned with the other comments on the page)

## Additional Guidelines
- Maximum line length should be reasonable (around 120 characters)
Expand Down
15 changes: 14 additions & 1 deletion osbot_utils/helpers/flows/Flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class Flow(Type_Safe):
executed_tasks : typing.List
resolved_args : tuple
resolved_kwargs : dict
setup_completed : bool

def add_flow_artifact(self, description=None, key=None, data=None, artifact_type=None): # todo: figure out how to make this work since at the moment most are showing an unknown type
event_data = Flow_Run__Event_Data()
Expand All @@ -64,6 +65,10 @@ def add_flow_result(self, key, description):
flow_events.on__new_result(event_data)
self.flow_data.add_result(key, description)

def check_setup(self):
if self.setup_completed is False:
raise ValueError("Error starting Flow, setup has not been called, use .setup(target, *args, **kwargs) to configure it")

def config_logger(self):
with self.logger as _:
_.set_log_level(logging.DEBUG)
Expand All @@ -75,6 +80,7 @@ def execute(self):
return self.execute_flow()

def execute_flow(self, flow_run_params=None): # todo: see if it makes more sense to call this start_flow_run
self.check_setup()
flow_events.on__flow__start(self.flow_event_data())
self.log_debug(f"Created flow run '{self.f__flow_id()}' for flow '{self.f__flow_name()}'")
self.set_flow_run_params(flow_run_params)
Expand Down Expand Up @@ -240,7 +246,13 @@ def set_flow_run_params(self, flow_run_params=None):
self.log_info(f"flow_run_params: {flow_run_params}")
self.add_flow_artifact(description="Data received via FastAPI's request.json()", key='post-data', data=flow_run_params)

def setup(self, target, *args, **kwargs):
def main(self): # method to be overwritten by implementing classes
pass

def setup(self, target=None, *args, **kwargs):
if target is None:
target = self.main

with self as _:
_.cformat.auto_bold = True
_.set_flow_target (target, *args, **kwargs)
Expand All @@ -250,6 +262,7 @@ def setup(self, target, *args, **kwargs):
_.flow_data.set_flow_id (self.flow_id)
_.flow_data.set_flow_name(self.flow_name)
_.add_event_listener()
_.setup_completed = True
return self

def setup_flow_run(self):
Expand Down
12 changes: 12 additions & 0 deletions tests/unit/helpers/flows/test_Flow.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import asyncio
import re

import pytest
from osbot_utils.helpers.flows.models.Flow_Run__Config import Flow_Run__Config
from osbot_utils.helpers.flows.actions.Flow__Events import flow_events
Expand Down Expand Up @@ -210,4 +212,14 @@ def flow_with_error():
assert str(flow_result.flow_error) == "Failed to load current data feed"


def test__flow__execute__raises_exception_if_setup_is_not_called(self):
with Flow() as _:
expected_message = "Error starting Flow, setup has not been called, use .setup(target, *args, **kwargs) to configure it"
with pytest.raises(ValueError, match=re.escape(expected_message)):
_.execute()
_.setup()
_.flow_config.logging_enabled = False
_.execute()



Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class An_Class_6(Type_Safe):

type_safe_cache.skip_cache = False

print()
#print()
with Performance_Measure__Session(assert_enabled=True) as _:
_.measure(str ).print().assert_time(self.time_100_ns , self.time_0_ns )
_.measure(Random_Guid).print().assert_time(self.time_3_kns , self.time_5_kns, self.time_6_kns , self.time_7_kns , self.time_8_kns )
Expand All @@ -63,7 +63,7 @@ class An_Class_6(Type_Safe):
_.measure(An_Class_5 ).print().assert_time(self.time_1_kns , self.time_2_kns , self.time_3_kns , self.time_4_kns , self.time_5_kns , self.time_8_kns , self.time_9_kns ,self.time_10_kns, self.time_20_kns )
_.measure(An_Class_6 ).print().assert_time(self.time_2_kns , self.time_3_kns , self.time_4_kns , self.time_5_kns , self.time_7_kns , self.time_8_kns ,self.time_9_kns , self.time_10_kns, self.time_20_kns )

type_safe_cache.print_cache_hits()
#type_safe_cache.print_cache_hits()

# with no cache (and other changes) the results were:
#
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,13 @@ class ComplexTypes(Type_Safe): # Multip
# nested : NestedType
# items : List[NestedType]

print()
#print()
with self.session as session:
session.measure(ComplexTypes ).print().assert_time(self.time_20_kns, self.time_30_kns, self.time_40_kns)
# session.measure(NestedType ).print().assert_time(self.time_2_kns , self.time_3_kns , self.time_20_kns)
# session.measure(WithNested ).print().assert_time(self.time_20_kns, self.time_40_kns)

type_safe_cache.print_cache_hits()
#type_safe_cache.print_cache_hits()

def test_inheritance_depth(self): # Test inheritance impact
class Base(Type_Safe): # Base class
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/type_safe/steps/test_Type_Safe__Step__Init.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class Class__One_int:
assert one_int.__dict__ == {'an_int': 0}
assert one_int.an_int == 0

@trace_calls(include=['*'], show_internals=True, show_duration=True, duration_padding=80)
#@trace_calls(include=['*'], show_internals=True, show_duration=True, duration_padding=80)
def test_init__class_one_int__with_kwargs(self):
class Class__One_int:
an_int: int
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ class test_perf__Type_Safe__Step__Default_Kwargs(TestCase):

@classmethod
def setUpClass(cls): # Define timing thresholds
pytest.skip('re-enabled once refactoring of Type_Safe is completed')
cls.time_100_ns = 100
cls.time_200_ns = 200
cls.time_300_ns = 300
Expand Down
Loading

0 comments on commit 8bf30af

Please sign in to comment.