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:
functionmethodobject: theadviceis attached to all methods of the objectclass: theadviceis attached to all methods of the classmodule: theadviceis 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 ajoinpointafter: exectuted after ajoinpointaround: executed before and after ajoinpointerror: executed when ajoinpointraises 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
erroris raised and anerror_adviceexists, theerror_adviceis 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
funcinaround_adviceis not the actualjoinpoint, but it is a wrapper. - When attaching an
adviceto ajoinpoint,aspectpreplaces thejoinpointwith a special function that wraps thejoinpoint
Metadata
Release files for aspectp 1.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| aspectp-1.0.1.tar.gz | 17.7 kB | Without provenance | Details for aspectp-1.0.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| aspectp-1.0.1-py3-none-any.whl | Python 3 | none | any | Details for aspectp-1.0.1-py3-none-any.whl |
Total release size: 34.0 kB
Release files / aspectp-1.0.1.tar.gz
| Download URL | aspectp-1.0.1.tar.gz |
|---|---|
| Size | 17.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
fe8d45a6c879d7bc6ced19ceb01a8a703bde573a8844ea9c5426528fa3a92412
|
|
BLAKE2b-256 checksum How to use checksums |
a82f6b5f82413a16fcebac4794e7ce8d28796772584178c3f8a73903c716cdee
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/4.0.2 CPython/3.11.0
|
Release files / aspectp-1.0.1-py3-none-any.whl
| Download URL | aspectp-1.0.1-py3-none-any.whl |
|---|---|
| Size | 16.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1791a16a1b88ceb437e541ad5ab3bfcc75f8594b3044858b2003d4ac7707c523
|
|
BLAKE2b-256 checksum How to use checksums |
2108eb19fbdc60b2787c6a345fcc14aa1f55fadb37e653a9c2a900eaa3dc7425
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/4.0.2 CPython/3.11.0
|
Security for aspectp 1.0.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.