Package: logic-processes-layer
logic_processes_layerThe logic_processes_layer package provides a framework for structuring the logic of your Python programs in a flexible and maintainable way. It allows you to divide your program logic into separate processes, each of which can be easily modified or replaced without affecting the others.FeaturesSeparation of concerns: Each process in your program can be developed and tested independently.Flexibility: Processes can be easily added, removed, or modified without affecting the rest of your program.Ease of testing: By isolating each process, you can write more focused and effective unit tests.InstallationYou can install the logic_processes_layer package via pip:
pip install logic-processes-layerNew FeaturesProcessAsSubprocess: Use any process as a subprocess.InitMapper: Simplifies process initialization with attribute mapping from the context.ProcessAttr: Retrieve attributes from the process context or directly from the process.Examplesof how to use the logic_processes_layer package.Basic UsageHere is a basic example of how to use the logic_processes_layer package:importdataclassesfromlogic_processes_layerimportBaseProcessor,BaseSubprocessorclassMyPreProcess(BaseSubprocessor):def__call__(self):print("This is the pre-run step.")self.context.data['message']="Hello, World!"classMyPostProcess(BaseSubprocessor):allow_context=Truedef__call__(self):print("This is the post-run step.")print(self.context.data['message'])@dataclasses.dataclassclassMyClass(BaseProcessor):pre_run=(MyPreProcess(),)post_run=(MyPostProcess(),)defrun(self):print("This is the run step.")process=MyClass()process()In this example,MyClassis a processor that has a pre-run step, a run step, and a post-run step. The pre-run step is performed byMyPreProcess, which saves a message in the context. The run step is defined inMyClassitself. The post-run step is performed byMyPostProcess, which retrieves the message from the context and prints it.Advanced Example: Processing Data from Multiple APIsThis example demonstrates how to use the logic_processes_layer package to process data from multiple APIs. The process is divided into three steps: pre-run, run, and post-run.Pre-runIn the pre-run step, we have two subprocesses, each making a GET request to a different API. The responses from these requests are stored inself.results.pre_run, and will be used in the main run step.classPreProcess1(BaseSubprocessor):def__call__(self):# Assuming that we are making a GET request to the first APIresponse1=requests.get('http://api1.com')# Return the responsereturnresponse1.json()classPreProcess2(BaseSubprocessor):def__call__(self):# Assuming that we are making a GET request to the second APIresponse2=requests.get('http://api2.com')# Return the responsereturnresponse2.json()RunIn the run step, we process the data from the pre-run step. The results from the two pre-run subprocesses are retrieved fromself.results.pre_run, and we assume that these results are combined in some way by a hypothetical functionprocess_data.defrun(self):# Process the data from the pre_run stepapi1_response=self.results.pre_run[self.pre_run[0]]api2_response=self.results.pre_run[self.pre_run[1]]# Assume that we are combining the data from the two APIs in some wayresult=process_data(api1_response,api2_response)# process_data is a hypothetical function# Return the resultreturnresultPost-runIn the post-run step, we have a subprocess that sends the result from the run step to another API. The response from this POST request is stored inself.results.post_run.classPostProcess(BaseSubprocessor):def__call__(self):result=context.process.results.run# Send the result to another APIresponse3=requests.post('http://api3.com',data=result)# Return the responsereturnresponse3.json()Finally, we create an instance of our class and call it to execute the process:process=MyClass()process()Please note that you need to replace'http://api1.com','http://api2.com', and'http://api3.com'with the actual API URLs, and implement theprocess_datafunction that processes the data from the first two APIs.Advanced Example: ChainPipeline with Custom Mapper and StepsIn this example, we delve deeper into the use oflogic_processes_layerand demonstrate howChainPipeline,AbstractMapper, andAbstractPipelineStepcan be used to create more complex processes.Processors: We have three processors,ProcessorOne,ProcessorTwo, andProcessorThree. Each of these processors performs a certain task and returns a result.Mappers: We then have three mappers,MapperOne,MapperTwo, andMapperThree. These mappers are used to build attribute dictionaries that are passed into the processors.Steps: We then have three steps,StepOne,StepTwo, andStepThree. Each of these steps uses one of the processors and one of the mappers.ChainPipeline: Finally, we have aChainPipelinethat combines all three steps into one sequence.importdataclassesfromlogic_processes_layerimportBaseProcessorfromlogic_processes_layer.abc.abc_chainimportAbstractChainPipelinefromlogic_processes_layer.abc.abc_mapperimportAbstractMapperfromlogic_processes_layer.abc.abc_pipelineimportAbstractPipelineStepfromlogic_processes_layer.structuresimportAttrsData@dataclasses.dataclassclassProcessorOne(BaseProcessor):data_for_init:strdefrun(self):return{"one":1}@dataclasses.dataclassclassProcessorTwo(BaseProcessor):data_for_init:strdata_for_init_two:intdefrun(self):returnNoneclassProcessorThree(BaseProcessor):defrun(self):return"RESULT THREE"classMapperOne(AbstractMapper):defbuild_attrs_strategy(self,prev_results):returnself.start_attrsclassMapperTwo(AbstractMapper):defbuild_attrs_strategy(self,prev_results):returnAttrsData(args=self.start_attrs.args,kwargs={"data_for_init_two":prev_results["one"]})classMapperThree(AbstractMapper):defbuild_attrs_strategy(self,prev_results):returnAttrsData(args=tuple(),kwargs={})classStepOne(AbstractPipelineStep):processor=ProcessorOneattr_mapper_cls=MapperOneclassStepTwo(AbstractPipelineStep):processor=ProcessorTwoattr_mapper_cls=MapperTwoclassStepThree(AbstractPipelineStep):processor=ProcessorThreeattr_mapper_cls=MapperThreeclassChainPipeline(AbstractChainPipeline):step_classes=(StepOne,StepTwo,StepThree)start_attrs=AttrsData(args=("DATA FOR INIT",),kwargs={})pipeline=ChainPipeline()result=pipeline()print(result)In this example, we create an instance ofChainPipelineand call it to execute the whole process.
The result of each step is passed to the next step via the mapper,
allowing each step to use the result of the previous step when building its attributes.