from aspectify.aop import Aspect
from random import RandomFourth Example. Dynamically input arguments modification.
Sometimes you just need to get access to the input parameters of a function to show or to modify them. This level of customization must be carefully used, but AOP allow us to tackle it using a before PointCut.
During this example, we will explain how to dynamically modify the input paramers of any function.
REMEMBER: Trying to be as clean as possible, we strongly recomend you to create a new
aspects.pyfile and add theAspects to this file.
Library import
First of all, we need to import to the Aspects file the libraries and modules that will be used. In this case, random.
Additionally, we need to define the get_classes method.
def get_classes():
return [element for element in list(globals().items())]advice definition: RELU
In this example, we will define an Aspect called modified_aspect, and we will modify it behaviour during the example.
modified_aspect = Aspect()As previously seen, we can add a before advice, just using the set_before method.
modified_aspect.set_before(lambda *a, **k: [max(0, a) for a in a])As we can see, the used lambda has two input parameters, *a and **k, representing all the parameters that the original method can have.
REMEMBER: We can access to the parameters used in the original call of the catched method.
In this case, we change the input paramets: we apply the RELU function (max(0, a)) for each secuential argument (inside *a). Thus, the original method will be called with positive or 0 integers.
Finally, we catch the randint method from random.
modified_aspect.create_pointcut(get_classes(), "random.Random.randint")Captured method: random.Random.randint
Results
Now, we can call the randint method, which will return a random number in [a,b]
r = Random()
r.randint(-5, 7)WARNING:root:Args changed from [<random.Random object>, -5, 7] to [<random.Random object>, 0, 7]
6
advice definition: TO INT
We can also modify the parameters to set new preconditions.
For example, it is known that getrandbits waits for an int argument. We can stablish this precondition with a before PointCut if the original auther did not. In order to do that, we only know to take the input parameters and transform them into integers (or raise an exception if any of them is, for example, a float).
First of all, let us see what happend when we call this method using a float argument.
r = Random()
r.getrandbits(8.15)TypeError: integer argument expected, got float
Let us define the aspect and try the method with it.
modified_aspect = Aspect()
modified_aspect.set_before(lambda *a, **k: [int(a) for a in a])
modified_aspect.create_pointcut(get_classes(), "random.Random.getrandbits")Captured method: random.Random.getrandbits
Results
r = Random()
r.getrandbits(8.15)WARNING:root:Args changed from [<random.Random object>, 8.15] to [<random.Random object>, 8]
68
Conclusion
During this example we have explained how to use a before PointCut to modify the precondition of a method (how to adjust input parameters). This can be used in several situations. For example, we can stablish default parameters or partial functions using this.
In fact, we will show how to do that in the next example.