Package: pipechain
PipeChainMotivationPipeChain is a utility library for creating functional pipelines.
Let's start with a motivating example.
We have a list of Australian phone numbers from our users.
We need to clean this data before we insert it into the database.
With PipeChain, you can do this whole process in one neat pipeline:frompipechainimportPipeChain,PLACEHOLDERas_nums=["493225813","0491 570 156","55505488","Barry","02 5550 7491","491570156","","1800 975 707"]PipeChain(nums).pipe(# Remove spacesmap,lambdax:x.replace(" ",""),_).pipe(# Remove non-numeric entriesfilter,lambdax:x.isnumeric(),_).pipe(# Add the mobile code to the start of 8-digit numbersmap,lambdax:"04"+xiflen(x)==8elsex,_).pipe(# Add the 0 to the start of 9-digit numbersmap,lambdax:"0"+xiflen(x)==9elsex,_).pipe(# Convert to a set to remove duplicatesset).eval(){'0255507491', '0455505488', '0491570156', '0493225813', '1800975707'}Without PipeChain, we would have to horrifically nest our code, or else use a lot of temporary variables:set(map(lambdax:"0"+xiflen(x)==9elsex,map(lambdax:"04"+xiflen(x)==8elsex,filter(lambdax:x.isnumeric(),map(lambdax:x.replace(" ",""),nums))))){'0255507491', '0455505488', '0491570156', '0493225813', '1800975707'}InstallationpipinstallpipechainUsageBasic UsagePipeChain has only two exports:PipeChain, andPLACEHOLDER.PipeChainis a class that defines a pipeline.
You create an instance of the class, and then call.pipe()to add another function onto the pipeline:frompipechainimportPipeChain,PLACEHOLDERPipeChain(1).pipe(str)PipeChain(arg=1, pipes=[functools.partial(<class 'str'>)])Finally, you call.eval()to run the pipeline and return the result:PipeChain(1).pipe(str).eval()'1'You can "feed" the pipe at either end, either during construction (PipeChain("foo")), or during evaluation.eval("foo"):PipeChain().pipe(str).eval(1)'1'Each call to.pipe()takes a function, and any additional arguments you provide, both positional and keyword, will be forwarded to the function:PipeChain(["b","a","c"]).pipe(sorted,reverse=True).eval()['c', 'b', 'a']Argument PositionBy default, the previous value is passed as the first positional argument to the function:PipeChain(2).pipe(pow,3).eval()8The only magic here is that if you use thePLACEHOLDERvariable as an argument to.pipe(), then the pipeline will replace it with the output of the previous pipe at runtime:PipeChain(2).pipe(pow,3,PLACEHOLDER).eval()9Note that you can renamePLACEHOLDERto something more usable using Python's import statement, e.g.frompipechainimportPLACEHOLDERas_PipeChain(2).pipe(pow,3,_).eval()9MethodsIt might not see like methods will play that well with this pipe convention, but after all, they are just functions.
You should be able to access any object's method as a function by accessing it on that object's parent class.
In the below example,stris the parent class of "":"".join(["a","b","c"])'abc'PipeChain(["a","b","c"]).pipe(str.join,"",_).eval()'abc'OperatorsThe same goes for operators, such as+,*,[]etc.
We just have to use theoperatormodule in the standard library:fromoperatorimportadd,mul,getitemPipeChain(5).pipe(mul,3).eval()15PipeChain(5).pipe(add,3).eval()8PipeChain(["a","b","c"]).pipe(getitem,1).eval()'b'Test SuiteNote, you will need poetry installed.To run the test suite, use:gitclonehttps://github.com/multimeric/PipeChain.gitcdPipeChain
poetryinstall
poetryrunpytesttest/test.py