.. image:: https://travis-ci.org/katyukha/extend-me.svg?branch=master
    :target: https://travis-ci.org/katyukha/extend-me


.. image:: https://coveralls.io/repos/katyukha/extend-me/badge.png
    :target: https://coveralls.io/r/katyukha/extend-me


Extend Me - Class based extension/plugin library
================================================

This module provides mechanism of extension of your application
based on 'extension via inheritance'. Under this words I mean
ability to define new extensions of application objects simply
by subclassing of extensible classes of app.

For example we have app with class 'Worker' which we would like
to make extensible (allowing third party modules to extend or
change its behavior). Thinking strait, there are a lot of work
to be done, to impelement mechanism of loading, registering,
end enabling extension, with lot of glue code, which must define
some entry points to connect extension and main app. But why not
make it simpler, supposing that any subclass of 'Worker' will
extend it? And this module provides implementation of this
in two ways:

    - Explicit (by using metaclass *ExtensibleType* directly)
        - When using this way You will heve seperatly Base class
        to be subclassed by extension classes and class getter
        which will construct class based on all defined extensions
        using multiple inhertance

    - Implicit (by using Extensible class which use metaclass
        magic implicitly)
        - *Extensible* class takes care of all metaclass magic
        related to generation objects of correct class


How it Works
------------

Metaclass (*ExtensibleType*) tracks all subclasses of class it
is applied to, and provides method to build class based on all
subclasses of base class, thus using all functionality of all
subclasses. Thus generation of correct class is separate process
which should be used everywhere where extensible class is requred.

To simplify this class *Extensible* was implemented. It has redefined
method *__new__* which automaticaly creates instances of correct class
(class that inherited from base class and all its extensions')


Examples
--------

ExtensibleType
~~~~~~~~~~~~~~

At the begining we should create a metaclass that will automaticaly
gether all information about all extensions, and apply this metaclass
to class we would like to enable extensions for::

    >>> import six  # Used for Python 2/3 compatability
    >>> mc = ExtensibleType._("Object")

    >>> @six.add_metaclass(mc)
    ... class Object(object):
    ...     pass

Not method *_* of *ExtensibleType*. This method is used to create metaclass
for specific object. It receives one argument - string that will be used as
name of class generated by this metaclass

Next we may define extension for this class. It is very simple.
Just subclass previously defined class::

    >>> class ObjectExtension(Object):
    ...     cool_attribute = 1
    ...     def method1(self):
    ...         return "Test"

So... at this momet we have base class and extension. And here is that
core magic occures. Metaclass that was created at the begining automaticaly
collects all subclasses of base class. So it is posible now to create new
class that is subclass of all subclasses of base class using multiple inheritance.
And metaclass *mc* will do it for You::

    >>> cls = mc.get_class()

And now You can use cls for Your needs, instead of base class.
It can do all that base class can, and all that extensions can::

    >>> obj = cls()
    >>> obj.method1()
    'Test'
    >>> obj.cool_attribute
    1


Extensible
~~~~~~~~~~

This class provides one more level of abstraction, allowing to hide all metaclass magic
behide the scene. So, using it You don't need to worry about metaclasses and class
creation process. Just inherit extensions form base class, and use in Your program
instances of base class. Let's see it in example::

    >>> class MyCoolClass(Extensible):
    ...     my_attr_1 = 25
    ...     def my_method1(self, arg1):
    ...         print('Hello, %s' % arg1)

    >>> class MyCoolClassExtension1(MyCoolClass):
    ...     def my_method1(self, arg1):
    ...         super(MyCoolClassExtension1, self).my_method1(arg1.upper())
    ...
    ...     def my_method2(self, arg1):
    ...         print("Good by, %s" % arg1)

And now using simply instances of base class You have all abilities that provided by extensions::

    >>> my_cool_obj = MyCoolClass()
    >>> print(my_cool_obj.my_attr_1)
    25
    >>> my_cool_obj.my_method1('World')
    Hello, WORLD
    >>> my_cool_obj.my_method2('World')
    Good by, World

