Skip to main content

Apply Aspect Oriented Programming to your Python code

Project description

aspectify

Aspect Oriented Programming is a programming paradigm that allows the user to separate some cross-cutting content from the main code, such as the logging or a database connection.

As it may be known, other programming languages has some functionallity (implemented or plugged in) to use this paradigm as an additional abstract layer to the core application. AspectJ (used in Java), can sound familiar to the reader.

In order to bring this amazing and powerful functionality to Python (which, in addition, will allow us to add it dynamically instead of using a weaver –as it is done in Java–), we have defined Aspectify, a Python library to manage AOP.

Background concepts

Before introducing the library, it is important to define some concepts used in AOP. Those are: - Aspect (what): a cross-cutting concept. In fact, an Aspect will group some functionalies. These, which will modify the natural behaviour of a method, are called Advices. - PointCut (when): the time at which the new behaviuor must occur. Originally, only three points in time were defined (before, around and after), but nowadays new points in time are defined, such as “after throwing an exception”. - Advice (what to do): as mentioned above, the code fragment to execute when the PointCut occurs.

Installation

In order to install the library, it is only needed to execute the pypi comand that follows:

pip install aspectify

ADVICE: You should use a virtual environment to install the packages associated with your proyect.

How to use Aspectify

Once the background is defined and the library installed, we can start to create the AOP layer to our projects.

The core project

In order to use the library, we need a project. For example, here is a Calculator program, that will apply the basic operators to two values entered by keyboard.

class Calculator():
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def add(self):
        return self.a + self.b

    def subtract(self):
        return self.a - self.b

    def multiply(self):
        return self.a * self.b

    def divide(self):
        return self.a / self.b

Now, we can use it to operate some integers.

a = 10
b = 20
operator = "+"
calculator = Calculator(a, b)

if operator == "+":
    print(calculator.add())
elif operator == "-":
    print(calculator.subtract())
elif operator == "*":
    print(calculator.multiply())
elif operator == "/":
    print(calculator.divide())
30

A bit rudimentary, but it works.

Now, let us suppose that this Calculator program is a library. In addition, let us suppose that we did not write it, and we did not have the access to they parts: we just know that a Calculator class exists and it has four methods: add, subtract, multiply and divide.

AOP: definition

At this moment, we want to modify, let us say, the add method behaviour to add the following message: “Adding some numbers”. We can use the library to create an Aspect.

ADVICE: Trying to be as clean as possible, we strongly recomend you to create a new .py file and add the Aspects to this file.

First of all, we need to import to the Aspects file (aspects.py from now on) the libraries and modules that will be used. In this case, the Calculator.

# aspects.py file

# import Calculator
from aspectify.aop import Aspect, is_detectable

First of all, we need to define a method to gather all the classes loaded in the aspects.py file, in order to modify their behaviour dynamically. This method will be always be the same:

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

At this point, we can define our first Aspect. We will call it “add-message”, and it will show a message before the addition is done.

add_message_aspect = Aspect("add-message")
add_message_aspect.set_before(lambda: print("Adding some numbers"))

Finally, we will create a PointCut that will define which methods will show this message. We will use the regular expression .*add.

add_message_aspect.create_pointcut(get_classes(), ".*add")
Captured method: __main__.Calculator.add
[WARNING]: If executed in a notebook, the cell is shown being executed, but this message proves that the execution is finished.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

aspectify-0.0.3.tar.gz (10.9 kB view hashes)

Uploaded Source

Built Distribution

aspectify-0.0.3-py3-none-any.whl (9.5 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page