def test_can_execute_transformation_process(self): def fn_pre_mutable(element, meta) -> Element: return element def fn_transform(inp, out, met) -> dict: return inp def fn_post_mutable(element, meta) -> Element: return element result = Process(selector=Selector( chains=[Chain(ordered_events=[ Mutable(fn=fn_pre_mutable, ), ], )]), ).append_subprocess( Process(selector=Selector(chains=[ Chain(ordered_events=[Transformer(fn=fn_transform, )]), ], ), )).append_subprocess( Process(selector=Selector(chains=[ Chain(ordered_events=[ Mutable(fn=fn_post_mutable, ), ], ), ], ), )).run([ Element( input={"a": 1}, tag=None, ), ]) self.assertEqual(len(result.elements), 1) self.assertEqual(len(result.notices), 0)
def test_can_compose_process(self): def mut_fn_fail(e, m) -> Element: raise Exception("Oops!") def mut_fn(e, m) -> Element: return e def trans_fn(i, o, m) -> list: return [] def trans_fn_fail(i, o, m) -> list: raise Exception("Oops!") result = Process(selector=Selector(chains=[ AllChain(ordered_events=[ Selector(chains=[ AllChain(ordered_events=[ Mutable(fn=mut_fn), Transformer(fn=trans_fn), ], ), AllChain( ordered_events=[ Mutable(fn=mut_fn_fail), ], tag=0, ), ], ) ]), AllChain( ordered_events=[ Selector(chains=[ AnyChain(ordered_events=[ Transformer(fn=trans_fn_fail), Transformer(fn=trans_fn), ]) ]) ], tag=99, ) ])).run(elements=[ Element( input={}, tag=99, ), Element( input={}, tag=0, # Should fail ), Element(input={}, ), ]) self.assertEqual(len(result.outputs(filter=lambda x: x is None)), 1) self.assertEqual(len(result.outputs(filter=lambda x: x is not None)), 2)
async def test_process_run_async_will_succeed(self): process = Process(selector=Selector(chains=[ AnyChain(ordered_events=[ Transformer(fn=transform), ], ), ], ), ) try: result = await process.run_async(elements=[ Element(input={ "a": 0, "b": 1 }), Element(input={ "c": 0, "y": 1 }), Element(input={ "d": 1, "b": 0 }), ]) self.assertEqual(["b"], result.elements[0].output) self.assertEqual(["y"], result.elements[1].output) self.assertEqual(["d"], result.elements[2].output) except Exception as e: self.fail(e)
def test_special_case_one(self): logger = FakeLogger() process = Process( selector=Selector( chains=[ AllChain(ordered_events=[ Mutable(fn=mute_components_to_strings, ), Transformer(fn=transform_generic, ), Mutable(fn=mute_set_config_meta, ) ], ), ], logger=logger, ), meta=ConfigGeneralMeta, ) elements = self.helper_get_elements() if elements: result = process.run(elements=elements, ) for element in result.elements: self.assertFalse(element.output is None and len(element.notices) == 0)
def __init__(self, logger=None): super(ConfigurationTransformationProcess, self).__init__( selector=Selector( chains=[ Chain(ordered_events=[ Mutable(fn=mute_old_types, ), Mutable(fn=mute_old_types, ), Mutable(fn=mute_old_types, ), ], ), Chain(ordered_events=[ Mutable(fn=mute_old_types, ), Mutable(fn=mute_old_types, ), ], ), Chain( ordered_events=[Mutable(fn=mute_old_types, )], tag="AT_LEAST", ), ], logger=logger, ), meta=ConfigurationMeta, ) self.append_subprocess( Process( selector=Selector(chains=[ AnyChain( ordered_events=[ Verifier( changeable=Transformer( fn=transform_exactly_one, ), verifier_fn=verify_transformed_elements, ), Verifier( changeable=Transformer(fn=transform_generic, ), verifier_fn=verify_transformed_elements, ), ], tag="EXACTLY_ONE", ), ], ), meta=ConfigurationMeta, ))
def test_special_case_two(self): fake_logger = FakeLogger() elements = self.helper_get_elements() if elements: pre_result = Process( selector=Selector( chains=[ AllChain( ordered_events=[ Mutable( fn=mute_price_rule_components_to_strings, ), Transformer( fn=transform_price_rule_to_constraints, ), Mutable(fn=mute_set_id, ) ], id="price-rule-conv-chain", ) ], logger=fake_logger, ), meta=ConfigGeneralMeta, ).run(elements=elements, ) self.assertEqual(len(pre_result.notices), 0) post_process = Process( selector=Selector(chains=[ AllChain(ordered_events=[ Transformer(fn=transform_package_price, ) ]) ]), meta=PreProcessMeta(config_rules={'X': [ "Y", "Z", ]}, prices=pre_result.outputs( filter=lambda x: x is not None, )), ).run(pre_result.filter(fn=lambda x: x.output is None, )) not_none_outputs = post_process.outputs(filter=lambda x: x is None) self.assertGreater(len(not_none_outputs), 0)
async def test_process_run_async_with_timeout(self): chars = list("abcdefghijklmno") process = Process(selector=Selector(chains=[ AnyChain(ordered_events=[ Transformer(fn=transform), ], ), ], ), ) try: await process.run_async( elements=[ Element(input={ np.random.choice(chars): np.random.randint(0, 2) for _ in range(np.random.randint(1, 10)) }, ) for _ in range(10000) ], timeout=0.1, ) except Exception as e: self.assertEqual(type(e), multiprocessing.TimeoutError)
def test_tags_can_be_functions_or_objects(self): def mut(e, t) -> Element: return e elements = [ Element( input={"tag_attr": 0}, tag=lambda x: x.input['tag_attr'], ), Element( input={}, tag=0, ), # Infected element Element( input={}, tag=lambda x: x['tag_attr'], ), # Infected element Element( input={"tag_attr": 0}, tag=lambda: 0, ) ] result = Process(selector=Selector(chains=[ Chain( ordered_events=[ Mutable(fn=mut), ], tag=0, ), ], ), ).run(elements=elements, ) self.assertEqual( len([e for e in result.elements if len(e.notices) == 0]), 2) self.assertEqual( len([e for e in result.elements if len(e.notices) > 0]), 2)
def test_will_not_halt(self): """ There has been problem with Process executing forever. Last case was when return type was declared as e.g. [dict] """ def trans_infected_def(i, o, m) -> [dict]: return [{}] result = Process(selector=Selector(chains=[ AllChain(ordered_events=[ AllChain(ordered_events=[ Transformer(fn=trans_infected_def), ]), Selector(chains=[ AnyChain( ordered_events=[ Transformer(fn=trans_infected_def), Transformer(fn=trans_infected_def), ], tag=99, ), ]), AllChain(ordered_events=[ Transformer(fn=trans_infected_def), ]) ], ), ], ), ).run(elements=[ Element( input={}, tag=99, ), Element( input={}, tag=0, # Should fail ), Element(input={}, ), ])