Package: pysyphe
Helps you create and manage your own rollbackable transactions.Installation$pipinstallpysypheTestsTests should be run under python 2.7 and python 3.6 to tests everything$pipinstalltox$tox-epy27,py36Coverage reports will be the merge of the coverage for py27 and py36.FeaturesRollbackable ActionsCreate actions and chain them in a pipeline:>>>frompysyphe.actionsimportActionsPipeline,Action>>>defhello_world():...print("Hello world!")...>>>defim_alive():...print("I'm Alive!!!")...>>>action1=Action(hello_world)>>>action1.do()Helloworld!>>>action2=Action(im_alive)>>>pipeline=ActionsPipeline([action1,action2])>>>pipeline.do()Helloworld!I'm Alive!!!Create rollback for your actions:>>>defhello_world():...print("Hello world!")...>>>defgoodbye_world():...print("Goodbye world!")...>>>action=Action(hello_world,goodbye_world)>>>action.do()Helloworld!>>>action.undo()Goodbyeworld!Rollback pipelines:>>>defhello_world():...print("Hello world!")...>>>defgoodbye_world():...print("Goodbye world!")...>>>defim_alive():...print("I'm Alive!!!")...>>>defim_dead():...print("I'm Dead!!!")...>>>pipeline=ActionsPipeline([...Action(im_alive,im_dead),...Action(hello_world,goodbye_world)])>>>pipeline.undo()# Nothing to rollback>>>pipeline.do()I'm Alive!!!Helloworld!>>>pipeline.undo()# Will be done in reverse order.Goodbyeworld!I'm Dead!!!Rollback only what have been done:>>>defhello_world():...print("Hello world!")...>>>defgoodbye_world():...print("Goodbye world!")...>>>defim_alive():...print("I'm Alive!!!")...>>>defim_dead():...print("I'm Dead!!!")...>>>deffailure():...raiseException("I broke your pipeline, what are you gonna do?")...>>>pipeline=ActionsPipeline([...Action(hello_world,goodbye_world),...Action(failure,lambda:None),# rollback will be an empty function...Action(im_alive,im_dead)])>>>try:...pipeline.do()...exceptException:...pipeline.undo()...Helloworld!Goodbyeworld!Define actions with a state:>>>frompysyphe.actionsimportstatefull_action>>>@statefull_action(["name"])...defhello(state):...print("Hello{}".format(state["name"]))...state["name"]="Dear "+state["name"]...>>>@hello.rollback_action()...defgoodbye(state):...print("Goodbye{}".format(state["name"]))...>>>action=hello.get_prepared_action(name="reader")# It must be prepared for state to be inialised>>>action.do()Helloreader>>>action.undo()GoodbyeDearreader>>>action.do()HelloDearreader>>>action.do()HelloDearDearreaderChain actions with a state:>>>@statefull_action(["name"])...defhello(state):...print("Hello{}".format(state["name"]))...state["name"]="Dear "+state["name"]...>>>@hello.rollback_action()...defgoodbye(state):...print("Goodbye{}".format(state["name"]))...>>>action=hello.get_prepared_action(name="reader")>>>action2=hello.get_prepared_action(name=action.state.ref_to("name"))# We can access the state of a previous action but read only !>>>action3=hello.get_prepared_action(name=action2.state.ref_to("name"))>>>pipeline=ActionsPipeline([action,action2,action3)])>>>pipeline.do()HelloreaderHelloDearreaderHelloDearDearreader>>>pipeline.undo()GoodbyeDearDearDearreaderGoodbyeDearDearreaderGoodbyeDearreader>>>pipeline.do()HelloDearreaderHelloDearDearreaderHelloDearDearDearreader>>>pipeline.undo()GoodbyeDearDearDearDearreaderGoodbyeDearDearDearreaderGoodbyeDearDearreaderTransactionsCreate transaction handlers and manage them:>>>frompysyphe.transactionsimportTransactionHandler,TransactionsManager>>>classLoggingTransactionHandler(TransactionHandler):...def__init__(self,name,will_fail):...self.name=name...self.will_fail=will_fail...defbegin(self):...print("BEGIN{}!".format(self.name))...defexecute(self):...ifself.will_fail:...raiseException("Your transaction failed, what are you gonna do?")...defcommit(self):...print("COMMIT{}!".format(self.name))...defrollback(self):...print("ROLLBACK{}!".format(self.name))...>>>tran_success=LoggingTransactionHandler("first",will_fail=False)>>>tran_fail=LoggingTransactionHandler("second",will_fail=True)>>>manager=TransactionsManager()>>>manager.add_transaction_handler(tran_success)>>>withmanager.begin():...manager.execute()...manager.commit()...BEGINfirst!COMMITfirst!>>>manager=TransactionsManager()>>>manager.add_transaction_handler(tran_success)>>>manager.add_transaction_handler(tran_fail)>>>withmanager.begin():# The transaction manager will rollback all transactions if an exception occurs....manager.execute()...manager.commit()...BEGINfirst!BEGINsecond!ROLLBACKfirst!ROLLBACKsecond!Traceback(mostrecentcalllast):File"<stdin>",line-,in<module>File".../pysyphe/transactions.py",line-,inexecutetransaction_handler.execute()File"<stdin>",line-,inexecuteException:Yourtransactionfailed,whatareyougonnado?TODOsGenerate the documentationAdd a “How-To correctly write unit actions to get the most out of pysyphe” into the documentation