Aspect Oriented Programming in Python
Project description
aspectp
Aspect 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.
Intallation
pip install aspectp
Example
import aspectp
import math
def add_one(result):
return result + 1
print(math.pow(2, 2)) # 4.0
aspectp.after(math.pow, add_one)
print(math.pow(2, 2)) # 5.0
Background
Aspect
An aspect
is 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.
Joinpoint
A joinpoint
is a point in the execution of the program, such as a function/method call, or an exception being thrown. A joinpoint
is the place where an advice
is attached. The following joinpoints are supported:
function
method
object
: theadvice
is attached to all methods of the objectclass
: theadvice
is attached to all methods of the classmodule
: theadvice
is attached to all functions in the module
Advice
An advice
is the action taken by an aspect
at a specific joinpoint
. There are 4 kinds of advices:
before
: executed before ajoinpoint
after
: exectuted after ajoinpoint
around
: executed before and after ajoinpoint
error
: executed when ajoinpoint
raises anerror
Usage
Before
To attach before a joinpoint
execution use:
aspectp.before(joinpoint, before_advice)
Where before_advice
is a function with the following signature:
def before_advice(args, kwargs):
# Do stuff
return args, kwargs
before_advice
can read and modify the arguments that will be passed to joinpoint
. before_advice
can also throw an exception to prevent joinpoint
from being executed.
Here is an example of aspectp.before
:
import aspectp
import math
def increase_exponent(args, kwargs):
return (args[0], args[1] + 1), kwargs
print(math.pow(2, 2)) # 4.0
aspectp.before(math.pow, increase_exponenet)
print(math.pow(2, 2)) # 8.0
After
To attach after a joinpoint
execution use:
aspectp.after(joinpoint, after_advice)
Where after_advice
is a function with the following signature:
def after_advice(result):
# Do stuff
return result
after_advice
can read and modify the result returned by joinpoint
. after_advice
can also throw an exception to prevent result
from being returned.
Here is an example of aspectp.after
:
import aspectp
import math
def increase_result(result):
return result + 1
print(math.pow(2, 2)) # 4.0
aspectp.after(math.pow, increase_result)
print(math.pow(2, 2)) # 5.0
Around
Attaching around a joinpoint
is similar to attaching before and after a joinpoint
. To attach around a joinpoint
execution use:
aspectp.around(joinpoint, around_advice)
Where around_advice
is a function with the following signature:
def around_advice(func, args, kwargs):
# Do stuff
result = func(args, kwargs)
# Do stuff
return result
around_advice
is responsible for calling func
, which will execute the joinpoint
. around_advice
can read and modify the arguments. around_advice
can prevent joinpoint
from being executed by not calling func
. around_advice
can read and modify the result.
Here is an example of aspectp.around
:
import aspectp
import math
def increase_exponent_and_result(func, args, kwargs):
result = func((args[0], args[1] + 1), kwargs)
return result + 1
print(math.pow(2, 2)) # 4.0
aspectp.around(math.pow, increase_exponent_and_result)
print(math.pow(2, 2)) # 9.0
Error
To attach after a joinpoint
raises an error
use:
aspectp.error(joinpoint, error_advice)
Where error_advice
is a function with the following signature:
def error_advice(error):
# Do stuff
return error
error_advice
can handle the error
raised by joinpoint
. error_advice
does not need to return error
.
Here is an example of aspectp.error
:
import aspectp
import math
def return_zero_on_error(error):
return 0.0
try:
math.sqrt(-1)
except ValueError as e:
print(e) # math domain error
aspectp.error(math.sqrt, return_zero_on_error)
print(math.sqrt(-1)) # 0.0
Remove
To remove all advices from a joinpoint
use:
aspectp.remove(joinpoint)
To remove a single advice from a joinpoint
use:
id = aspectp.before(joinpoint, before_advice)
# Do stuff
aspectp.remove(joinpoint, id)
Notes
- The order in which advices are executed is:
before_advice
,around_advice
,after_advice
- At any point, if an
error
is raised and anerror_advice
exists, theerror_advice
is called - Multiple advices of the same kind can be attached to the same
joinpoint
, and they are executed in the orther that they are defined - The argument
func
inaround_advice
is not the actualjoinpoint
, but it is a wrapper. - When attaching an
advice
to ajoinpoint
,aspectp
replaces thejoinpoint
with a special function that wraps thejoinpoint
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file aspectp-1.0.1.tar.gz
.
File metadata
- Download URL: aspectp-1.0.1.tar.gz
- Upload date:
- Size: 17.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.11.0
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | fe8d45a6c879d7bc6ced19ceb01a8a703bde573a8844ea9c5426528fa3a92412 |
|
MD5 | 4bf9691f55bb8ccf245061916f0f43bb |
|
BLAKE2b-256 | a82f6b5f82413a16fcebac4794e7ce8d28796772584178c3f8a73903c716cdee |
File details
Details for the file aspectp-1.0.1-py3-none-any.whl
.
File metadata
- Download URL: aspectp-1.0.1-py3-none-any.whl
- Upload date:
- Size: 16.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.11.0
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 1791a16a1b88ceb437e541ad5ab3bfcc75f8594b3044858b2003d4ac7707c523 |
|
MD5 | 421bf46cc6e57f545a41a42153bc18eb |
|
BLAKE2b-256 | 2108eb19fbdc60b2787c6a345fcc14aa1f55fadb37e653a9c2a900eaa3dc7425 |