Second example. Regular expressions.

During this example, we will show you why you should be stricty accurate using the create_pointcut method.

REMEMBER: Trying to be as clean as possible, we strongly recomend you to create a new aspects.py file and add the Aspects 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.

from aspectify.aop import Aspect
from random import Random

Additionally, we need to define the get_classes method. This method is always needed in order to get all the available classes to add Advices.

def get_classes():
    return [element for element in list(globals().items())]

Aspect definition

In this example, we will define an Aspect called bad_aspect, and it will send a message when the function is being called.

To do so, we add the before advice defined below. Here you can use defined functions or lambda.

bad_aspect = Aspect()
bad_aspect.set_before(lambda *a, **k: print("catched!"))

Now, we create an Advice to define which methods will show this message. As we want to show you what happen when the regular expression is extremely generic, we will use .*\.Random\..*. It will catch all the methods within a Random class, regardless of their modules.

bad_aspect.create_pointcut(get_classes(), ".*\.Random\..*")
Captured method: random.Random.VERSION
Captured method: random.Random._randbelow
Captured method: random.Random._randbelow_with_getrandbits
Captured method: random.Random._randbelow_without_getrandbits
Captured method: random.Random.betavariate
Captured method: random.Random.choice
Captured method: random.Random.choices
Captured method: random.Random.expovariate
Captured method: random.Random.gammavariate
Captured method: random.Random.gauss
Captured method: random.Random.getrandbits
Captured method: random.Random.getstate
Captured method: random.Random.lognormvariate
Captured method: random.Random.normalvariate
Captured method: random.Random.paretovariate
Captured method: random.Random.randint
Captured method: random.Random.random
Captured method: random.Random.randrange
Captured method: random.Random.sample
Captured method: random.Random.seed
Captured method: random.Random.setstate
Captured method: random.Random.shuffle
Captured method: random.Random.triangular
Captured method: random.Random.uniform
Captured method: random.Random.vonmisesvariate
Captured method: random.Random.weibullvariate

All these methods have been catched, so we can call them and see the message.

Results

Now, we can call the randint method.

r = Random()
r.randint(1, 10)
catched!
catched!
catched!
catched!
catched!
catched!
3

Why is it showing five messages if the defined Advice only adds one message? Well, things can get weird here.

As you may suppose, randint will call other Random’s method, also catched by the PointCut, so we are seeing all those messages together.

Random.__init__??
Signature: Random.__init__(self, x=None)
Source:   
    def __init__(self, x=None):
        """Initialize an instance.
        Optional argument x controls seeding, as for Random.seed().
        """
        self.seed(x)
        self.gauss_next = None
File:      /grupoa/config/miniconda3/lib/python3.8/random.py
Type:      function
r.randint??
Signature: r.randint(a, b)
Docstring:
Return random integer in range [a, b], including both end points.
        
Source:   
    def randint(self, a, b):
        """Return random integer in range [a, b], including both end points.
        """
        return self.randrange(a, b+1)
File:      /grupoa/config/miniconda3/lib/python3.8/random.py
Type:      method

Conclusion

In this toy example we can apreciate the potential complexity of the code flow. Indeed, this fact is a little bit controversial and this point is the reason why some reseachers advise against the usage of the AOP.

However, we cannot ignore all the improvements and the non-duplication of the code that AOP brings to us.

In the next example we will explain how to create the advices, which input parameters do we need and how can we apply several PointCuts to the same method.