Package: aspectp
aspectpAspect Oriented Programming in Python.Aspect-Oriented Programming (AOP) is a programming paradigm that separates cross-cutting concerns, like logging or security, from the main code to improve modularity and code organization, making it easier to manage and maintain complex software systems.Intallationpip install aspectpExampleimportaspectpimportmathdefadd_one(result):returnresult+1print(math.pow(2,2))# 4.0aspectp.after(math.pow,add_one)print(math.pow(2,2))# 5.0BackgroundAspectAnaspectis a modular unit that encapsulates a specific cross-cutting concern. Cross-cutting concerns are features or behaviors that span across multiple parts of a program, such as logging, error handling, or transaction management. Aspects allow these concerns to be added to existing code without modifying the code itself.JoinpointAjoinpointis a point in the execution of the program, such as a function/method call, or an exception being thrown. Ajoinpointis the place where anadviceis attached. The following joinpoints are supported:functionmethodobject: theadviceis attached to all methods of the objectclass: theadviceis attached to all methods of the classmodule: theadviceis attached to all functions in the moduleAdviceAnadviceis the action taken by anaspectat a specificjoinpoint. There are 4 kinds of advices:before: executed before ajoinpointafter: exectuted after ajoinpointaround: executed before and after ajoinpointerror: executed when ajoinpointraises anerrorUsageBeforeTo attach before ajoinpointexecution use:aspectp.before(joinpoint,before_advice)Wherebefore_adviceis a function with the following signature:defbefore_advice(args,kwargs):# Do stuffreturnargs,kwargsbefore_advicecan read and modify the arguments that will be passed tojoinpoint.before_advicecan also throw an exception to preventjoinpointfrom being executed.Here is an example ofaspectp.before:importaspectpimportmathdefincrease_exponent(args,kwargs):return(args[0],args[1]+1),kwargsprint(math.pow(2,2))# 4.0aspectp.before(math.pow,increase_exponenet)print(math.pow(2,2))# 8.0AfterTo attach after ajoinpointexecution use:aspectp.after(joinpoint,after_advice)Whereafter_adviceis a function with the following signature:defafter_advice(result):# Do stuffreturnresultafter_advicecan read and modify the result returned byjoinpoint.after_advicecan also throw an exception to preventresultfrom being returned.Here is an example ofaspectp.after:importaspectpimportmathdefincrease_result(result):returnresult+1print(math.pow(2,2))# 4.0aspectp.after(math.pow,increase_result)print(math.pow(2,2))# 5.0AroundAttaching around ajoinpointis similar to attaching before and after ajoinpoint. To attach around ajoinpointexecution use:aspectp.around(joinpoint,around_advice)Wherearound_adviceis a function with the following signature:defaround_advice(func,args,kwargs):# Do stuffresult=func(args,kwargs)# Do stuffreturnresultaround_adviceis responsible for callingfunc, which will execute thejoinpoint.around_advicecan read and modify the arguments.around_advicecan preventjoinpointfrom being executed by not callingfunc.around_advicecan read and modify the result.Here is an example ofaspectp.around:importaspectpimportmathdefincrease_exponent_and_result(func,args,kwargs):result=func((args[0],args[1]+1),kwargs)returnresult+1print(math.pow(2,2))# 4.0aspectp.around(math.pow,increase_exponent_and_result)print(math.pow(2,2))# 9.0ErrorTo attach after ajoinpointraises anerroruse:aspectp.error(joinpoint,error_advice)Whereerror_adviceis a function with the following signature:deferror_advice(error):# Do stuffreturnerrorerror_advicecan handle theerrorraised byjoinpoint.error_advicedoes not need to returnerror.Here is an example ofaspectp.error:importaspectpimportmathdefreturn_zero_on_error(error):return0.0try:math.sqrt(-1)exceptValueErrorase:print(e)# math domain erroraspectp.error(math.sqrt,return_zero_on_error)print(math.sqrt(-1))# 0.0RemoveTo remove all advices from ajoinpointuse:aspectp.remove(joinpoint)To remove a single advice from ajoinpointuse:id=aspectp.before(joinpoint,before_advice)# Do stuffaspectp.remove(joinpoint,id)NotesThe order in which advices are executed is:before_advice,around_advice,after_adviceAt any point, if anerroris raised and anerror_adviceexists, theerror_adviceis calledMultiple advices of the same kind can be attached to the samejoinpoint, and they are executed in the orther that they are definedThe argumentfuncinaround_adviceis not the actualjoinpoint, but it is a wrapper.When attaching anadviceto ajoinpoint,aspectpreplaces thejoinpointwith a special function that wraps thejoinpoint