Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ def __init__(self, settings= {}):
@rtype: PipelineBuilder
`use_setheader_properties (Bool)` - Whether to add the SetHeaderElement to the pipeline
(default true)
`suppress_process_exceptions (Bool)` - If False (the default) the first error thrown
while processing is re-raised from flow_data.process(); if True, errors are stored on
flow_data.errors and process() returns normally. Recommended True for web apps so a
processing failure degrades gracefully instead of failing the request.
@return: Returns a Pipeline Builder

"""
Expand All @@ -73,6 +77,11 @@ def __init__(self, settings= {}):
else:
self.data_file_update_service = None

if "suppress_process_exceptions" in settings:
self.suppress_process_exceptions = settings["suppress_process_exceptions"]
else:
self.suppress_process_exceptions = False

def get_javascript_elements(self):
"""
Adds the JavaScriptBuilder, JSONBundler and SequenceElement to the pipeline if
Expand Down Expand Up @@ -138,8 +147,8 @@ def build(self):

self.flow_elements.extend(self.get_javascript_elements())
self.flow_elements.extend(self.get_setheader_elements())
return Pipeline(self.flow_elements, logger=self.logger, data_file_update_service=self.data_file_update_service)

return Pipeline(self.flow_elements, logger=self.logger, suppress_process_exceptions=self.suppress_process_exceptions, data_file_update_service=self.data_file_update_service)

def add_logger(self, logger):
"""
Expand Down Expand Up @@ -187,7 +196,40 @@ def build_from_configuration(self, config):
flow_element = flow_element()
flow_elements.append(flow_element)

return Pipeline(flow_elements)
return Pipeline(flow_elements, suppress_process_exceptions=self._get_suppress_process_exceptions(config))

def _get_suppress_process_exceptions(self, config):
"""
Resolve the suppress_process_exceptions setting from a configuration.
Looks under 'PipelineOptions.BuildParameters' (mirrors the .NET/Java
config layout for cross-language consistency), then a direct
'PipelineOptions' key, accepting either snake_case or camelCase, and
finally falls back to the value supplied to the builder constructor
(default False).

@type config: dict
@param config: pipeline configuration
@rtype: bool
@return: whether processing exceptions should be suppressed
"""

options = config.get("PipelineOptions", {})

def lookup(source):
if not isinstance(source, dict):
return None
for key in ("suppress_process_exceptions", "suppressProcessExceptions"):
if key in source:
return source[key]
return None

value = lookup(options.get("BuildParameters"))
if value is None:
value = lookup(options)
if value is None:
return self.suppress_process_exceptions

return value

def _map_properties_names(self, mappings, arguments):
if arguments is None:
Expand Down
61 changes: 61 additions & 0 deletions fiftyone_pipeline_core/tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,64 @@ def test_build_from_config(self):

getValue = fd.get("example1").get("integer")
self.assertTrue(getValue == 5)

# suppress_process_exceptions: default is False from the builder
def test_suppress_process_exceptions_default(self):
pipeline = PipelineBuilder().add(ExampleFlowElement1()).build()
self.assertFalse(pipeline.suppress_process_exceptions)

# suppress_process_exceptions: set via builder settings
def test_suppress_process_exceptions_builder_setting(self):
pipeline = PipelineBuilder({"suppress_process_exceptions": True})\
.add(ExampleFlowElement1())\
.build()
self.assertTrue(pipeline.suppress_process_exceptions)

# suppress_process_exceptions: read from PipelineOptions.BuildParameters
def test_suppress_process_exceptions_from_config_build_parameters(self):
config = {
"PipelineOptions": {
"Elements": [
{
"elementName": "ExampleFlowElement1",
"elementPath": "tests.classes.exampleflowelement1"
}
],
"BuildParameters": {
"suppress_process_exceptions": True
}
}
}
pipeline = PipelineBuilder().build_from_configuration(config)
self.assertTrue(pipeline.suppress_process_exceptions)

# suppress_process_exceptions: read from a direct key (camelCase accepted)
def test_suppress_process_exceptions_from_config_direct(self):
config = {
"PipelineOptions": {
"Elements": [
{
"elementName": "ExampleFlowElement1",
"elementPath": "tests.classes.exampleflowelement1"
}
],
"suppressProcessExceptions": True
}
}
pipeline = PipelineBuilder().build_from_configuration(config)
self.assertTrue(pipeline.suppress_process_exceptions)

# suppress_process_exceptions: defaults to False from configuration
def test_suppress_process_exceptions_from_config_default(self):
config = {
"PipelineOptions": {
"Elements": [
{
"elementName": "ExampleFlowElement1",
"elementPath": "tests.classes.exampleflowelement1"
}
]
}
}
pipeline = PipelineBuilder().build_from_configuration(config)
self.assertFalse(pipeline.suppress_process_exceptions)
Loading