=======================
Documentation of aop.py
=======================

.. contents::
.. sectnum::

Prerequisites
=============

The ``aop`` module for PyPy only requires PyPy. No special translation
options are required, and it should work with all the backends. For
the development of application using AOP, though, it is strongly
advised to use a PyPy interpreter translated with the
``--no-objspace-usepycfiles`` option, which tells the interpreter not
to use byte-compiled modules, otherwise, you will need to manually
remove all the ``.pyc`` files each time the aspects are modified. 

Concepts
========

Aspect
------

An aspect is a representation of a
software design concern which affects a large part of a
program. Cross-cutting aspects are those concerns which have to be
dealt with in a number of unrelated parts of a program, for instance,
logging, synchronisation, persistance, security, value sharing, etc. 

Advice
------

An advice is a piece of code that will be woven in a code base at
specific join points. An aspect is usually implemented as a set of
advices. 

Static advices deal with adding declarative statements in the code,
for instance, adding new methods to a class. Dynamic advices are about
modifying the behaviour of the code, by adding statements to a
method, or replacing the code of a method. 

Point cut
---------

A point cut is a set of join points. 

Join point
----------

A join point is a place in a code base where some advices are to be
woven. Common join points include class definition, method or
function definition and methode calls. 

Weaving
-------

Weaving is the process of inserting an advices at a set of point
cuts. 

Implementation
==============

Overview
--------

Importing the ``aop`` module has several side effects:

* an instance of ``aop.Weaver`` is created and stored in
  ``__builtin__.__aop__``, which makes it globally available in modules
  which will be imported later
* this instance registers one of its methods with
  ``parser.install_compiler_hook`` (see above)

From then on, any module imported will be examined by the ``Weaver``
instance.

The code can define new aspects by using the ``Aspect`` metaclass in
the ``aop`` module. This metaclass can register methods decorated with
one of the advices of the ``aop`` module with the ``Weaver`` when the
``Aspect`` is instantiated. When a module is imported, the ``Weaver``
looks for symbols (classes, functions and methods) which are targets
of registered aspects and weaves the aspect in the function. The
weaving is done by mutating the AST nodes of the module. The mutation
generally involves calling a method on the ``__aop__`` instance with a
unique identifier. The Weaver will use this identifier at run time to
find which advice it should execute.

Aspects
~~~~~~~

Aspects are declared in classes using the ``aop.Aspect``
metaclass. Such classes can have normal methods, and additionally
methods decorated with an advice decorator, and aspect instances will
be registered with the Weaver by the metaclass. These decorators take
a ``PointCut`` as an argument to describe the join points.

Advices
-------

The available advices are:

* ``before``: the advice code will be woven before a dynamic join point
* ``after``: the advice code will be woven after a dynamic join point
* ``around``: the advice code will be woven in replacement of the
  dynamic join  point
* ``introduce``: the advice code will be added to a static join
  point. 

Point cuts
----------

A static point cut is created by instantiating the ``aop.PointCut``
class, passing one, two or three arguments. Each argument is a
regular expression which can match a package/module, a class or a
function/method. 

Point cuts can be combined using the python binary operators & and
\|, which will produce a new PointCut representing respectively the
intersection and the union of the join points of the original point
cuts. 

A dynamic point cut can be obtained from a static point cut by calling
one of the following methods:

=================== ======================================================
method              dynamic pointcut matching
------------------- ------------------------------------------------------  
pc.call()           all the places where the method or
                    function matched by the static pointcut is called
------------------- ------------------------------------------------------
pc.execution()      the execution of the function or method matched by
                    the static point cut
------------------- ------------------------------------------------------
pc.initialization() the initialization of the class matched by the
                    static point cut
------------------- ------------------------------------------------------
pc.destruction()    the destruction of the class matched by the
                    static point cut
=================== ======================================================

Example
=======

The following code can be used to implement a logging aspect::

    in file ``logging_aspect.py``:

     from aop import Aspect, before, PointCut

     class LoggingAspect:
         __metaclass__=Aspect

         # We weave in all methods and functions, except if the name of
         # the method starts with an underscore
         @before(PointCut(module='.*', klass='.*', func='[^_].*').execution())
         def logStartMethod(self, joinpoint):
             print 'in', joinpoint.name()


In the startup code of the application, before all other imports::

 from logging_aspect import LoggingAspect
 log = LoggingAspect()

References
==========

AOP implementations exist for a wide variety of programming languages,
and many languages have several implementations available. A list can
be found on the `aosd.net`_ `tools for developers`_ wiki
page. `aosd.net`_ is also the main resource for AOP programming. 

Other AOP implementations for python include:

* `lightweight aop for Python`_
* `springpython.aop`_
* `logilab.aspects`_

The apy of PyPy's ``aop`` module is strongly inspired by AspectJ_ and `AspectC++`_.

.. _aosd.net: http://aosd.net/

.. _tools for developers: http://aosd.net/wiki/index.php?title=Tools_for_Developers

.. _logilab.aspects: http://www.logilab.org/projects/aspects

.. _lightweight aop for Python: http://www.cs.tut.fi/~ask/aspects/aspects.html

.. _springpython.aop: http://springpython.python-hosting.com/wiki/AspectOrientedProgramming

.. _AspectJ: http://www.eclipse.org/aspectj/

.. _AspectC++: http://www.aspectc.org/
