API

This is the Mamba API documentation.

Mamba Application

Objects for build Mamba Applications

class mamba.Mamba(options=None)

This object is just a global configuration for mamba applications that act as the central object on them and is able to act as a central registry. It inherits from the :class: ~mamba.utils.borg.Borg so you can just instantiate a new object of this class and it will share all the information between instances.

You create an instance of the Mamba class in your main module or in your Twisted tac file:

from mamba import Mamba
app = Mamba({'name': 'MyApp', 'description': 'My App', ...})

Mamba only works in the GNU/Linux operating system (for now).

Parameters:options (dict) – options to initialize the application with
class mamba.ApplicationError

ApplicationError raises when an error occurs

AppStyles

class mamba.AppStyles

Manager for Application Stylesheets

seealso: Stylesheet

get_styles()

Return the mamba.Stylesheet pool

load(filename)

Load a new stylesheet file

lookup(key)

Find and return a stylesheet from the pool

reload(style)

Send a COMET / WebSocket petition to reload a specific CSS file.

Parameters:style (AppStyle) – the CSS file to reload

JavaScript to use:

var queryString = '?reload=' + new Date().getTime();
// ExtJS - Sencha
var el = Ext.get(styleName);
// jQuery
var el = $(styleName);
// LungoJS
var el = $$(styleName);

el.dom.href = el.dom.href.replace(/\?.*|$/, queryString);
setup()

Setup the loader and load the stylesheets

Controllers

class mamba.Controller

Mamba Controller Class define a web accesible resource and its actions.

A controller can (and should) be attached to a twisted.web.resource.Resource as a child or to others Controller.

Unlike twisted.web.resource.Resource, Controller don’t use the Twisted URL dispatching mechanism. The Controller uses Router for URL dispatching through the route() decorator:

@route('/hello_world', method='GET')
def helloworld(self, request, **kwargs):
    return 'Hello World'

seealso: Router, Route

getChild(name, request)

This method is not supposed to be called because we are overriden the full route dispatching mechanism already built in Twisted.

Class variable level isLeaf is supposed to be always True but any users can override it in their Controller implementation so we make sure that the native twisted behavior is never executed.

If you need Twisted native url dispatching in your site you should use Resource class directly in your code.

Parameters:
  • name (string) – ignored
  • request (Request) – a twisted.web.server.Request specifying meta-information about the request that is being made for this child that is ignored at all.
Return type:

Controller

get_register_path()

Return the controller register path for URL Rewritting

prepare_headers(request, code, headers)

Prepare the back response headers

Parameters:
  • request (Request) – the HTTP request
  • code (int) – the HTTP response code
  • headers (dict) – the HTTP headers
render(request)

Render a given resource. see: twisted.web.resource.IResource‘s render method.

I try to render a router response from the routing mechanism.

Parameters:request (twisted.web.server.Request) – the HTTP request
route_dispatch(request)

Dispatch a route if any through the routing dispatcher.

Parameters:request (Request) – the HTTP request
Returns:twisted.internet.defer.Deferred or mamba.web.response.WebResponse
run(port=8080)

This method is used as a helper for testing purposes while you are developing your controllers.

You should never use this in production.

sendback(result, request)

Send back a result to the browser

Parameters:
  • request (Request) – the HTTP request
  • result (dict) – the result for send back to the browser
class mamba.ControllerManager

Uses a ControllerProvider to load, store and reload Mamba Controllers.

_model_store A private attribute that sets the prefix path for the controllers store

get_controllers()

Return the controllers pool

is_valid_file(file_path)

Check if a file is a Mamba controller file

Parameters:file_path (str) – the file path of the file to check
length()

Returns the controller pool length

load(filename)

Loads a Mamba module

Parameters:filename (str) – the module filname
lookup(module)

Find and return a controller from the pool

Parameters:module (str) – the module to lookup
reload(module)

Reload a controller module

Parameters:module (str) – the module to reload
setup()

Setup the loader and load the Mamba plugins

Models

class mamba.Model

All the models in the application should inherit from this class.

We use the new storm.twisted.transact.Transactor present in the 0.19 version of Storm to run transactions that will block the reactor using a twsited.python.threadpool.ThreadPool to execute them in different threads so our reactor will not be blocked.

You must take care of don’t return any Storm object from the methods that interacts with the storm.Store underlying API because those ones are created in a different thread and cannot be used outside.

We don’t care about the instantiation of the Storm Store because we use zope.transaction through storm.zope.zstorm.ZStorm that will take care of create different instances of Store per thread for us.

create(*args, **kwargs)

Create a new register in the database

create_table(*args, **kwargs)

Create the table for this model in the underlying database system

delete(*args, **kwargs)

Delete a register from the database

drop_table(*args, **kwargs)

Delete the table for this model in the underlying database system

dump_data()

Dumps the SQL data

dump_references()

Dump SQL references (used by PostgreSQL)

dump_table()

Dumps the SQL command used for create a table with this model

Parameters:schema (str) – the SQL schema, SQLite by default
get_adapter()

Get a valid adapter for this model

get_uri()

Return an URI instance using the uri config for this model

read(*args, **kwargs)

Read a register from the database. The give key (usually ID) should be a primary key.

Parameters:id (int) – the ID to get from the database
update(*args, **kwargs)

Update a register in the database

uri

Returns the database URI for this model

Mamba Core

Core components of the Mamba framework itself.

Interfaces

Interfaces that are part of the Mamba Core, you are supossed to never use those ones unless you are developing new features for the Mamba framework itself.

class mamba.core.interfaces.INotifier

Every Inotifier class will implement this interface

_notify(ignore, file_path, mask)
Parameters:
  • ignore – ignored parameter
  • file_pathtwisted.python.filepath.Filepath on which the event happened
  • mask (int) – inotify event as hexadecimal mask
notifier

A twisted.internet.inotify.INotify instance where to watch a FilePath

class mamba.core.interfaces.IController

Manba Controllers interface.

Every controller will implement this interface

Parameters:
  • name (str) – Controller’s name
  • desc (str) – Controller’s description
  • loaded (bool) – true if the controller has been loaded, otherwise returns False
class mamba.core.interfaces.IDeployer

Mamba Deployers interface.

Every deployer must implement this interface

class mamba.core.interfaces.IResponse

Mamba Web Response interface.

Every web response must implement this interface.

Parameters:
  • code (int) – the HTTP response code
  • body (string) – the HTTP response body
  • headers (dict) – the HTTP response headers

Decorators

mamba.core.decorators.cache(size=16)

Cache the results of the function if the same positional arguments are provided.

We only store the size provided (if any) in MB, after that we should perform FIFO queries until the size of the cache is lower than the provided one.

If the size is 0 then an unlimited cache is provided

Notice

The memory size of the int_cache is just an approximation

mamba.core.decorators.unlimited_cache(func)

Just a wrapper over cache decorator to alias @cache(size=0)()

Http

Mamba Http Headers

class mamba.http.headers.Headers

An object that build the Application page header and returns it as a well formated XHTML/HTML string.

get_description_content()

Returns the Headers description

get_doctype()

Get the configured or default mamba doctype (html by default)

get_favicon_content(media='/media')

Returns the favicon

Parameters:media (str) – a media directory to add, defaults to /media
get_generator_content()

Returns the meta generator content

get_language_content()

Returns the Headers language

get_mamba_content()

Returns mamba specific meta content

Utils

Subpackage containing the modules that implement common utilities

Borg

class mamba.utils.borg.Borg

The Mamba Borg Class.

Every object created using the Borg pattern will share their information, as long as they refer to the same state information. This is a more elegant type of singleton, but, in other hand, Borg objects doesn’t have the same ID, every object have his own ID

Borg objects doesn’t share data between inherited classes. If a class A inherits from Borg and a class B inherits from A then A and B doesn’t share the same namespace

Example:

class LockerManager(borg.Borg):

    def __init__(self):
        super(LockerManager, self).__init__()

Used as:

>>> from managers import LockerManager
>>> manager1 = LockerManager()
>>> manager1.name = 'Locker One'
>>> manager2 = LockerManager()
>>> print(manager2.name)
Locker One
>>>

CamelCase

class mamba.utils.camelcase.CamelCase(camelize)

Stupid class that just offers stupid CamelCase funcionallity

Parameters:camelize (str) – the string to camelize
camelize(union=False)

Camelize and return camelized string

Parameters:union (bool) – if true is will use a space between words

Converter

class mamba.utils.converter.Converter

Object Converter class

static serialize(obj)

Serialize an object and returns it back

config.Database

This class is used to load configuration files in JSON format from the file system. If no config is provided a basic configuration based on SQLite is automatically created for us.

class mamba.utils.config.Database(config_file='config/database.json')

Database configuration object

This object load and parses the configuration details for the database access using a JSON configuration file with this format:

{
    'uri': 'sqlite:',
    'min_threads': 5,
    'max_threads': 20,
    'auto_adjust_pool_size': false,
    'create_table_behaviours': {
        'create_if_not_exists': true,
        'drop_table': false
    },
    'drop_table_behaviours': {
        'drop_if_exists': true,
        'restrict': true,
        'cascade': false
    }
}

Where uri is the Storm URI format for create ZStores and min, max threads are the minimum and maximum threads in the thread pool for operate with the database. If auto_adjust_pool_size is True, the size of the thread pool should be adjust dynamically.

For create_table_bevaviour possible values are:

create_if_not_exists
this is the default behaviour and it should add ‘IF DONT EXISTS’ to the table creation scripts
drop_table
this behaviour will always drop a table before try to create it. Be carefull with this behaviour because you can lose all your data if you dont take care of it

If no config_file or invalid config_file is given at first load attempt, then a fallback default settings with a SQLite in memory table are returned back.

If you loaded a valid config file and you instance the database config again with an invalid JSON format file, then a fallback default settings with SQLite in memory URI is returned back in order to preserve your data (if we don’t fallback to a default configuration you can overwrite important data in your previous well configured environment).

If you loaded a valid config file and pass a non existent or a void file in the constructor you get back your previous config so you can use it like a singleton instance:

config.Database('path/to/my_valid/config.json')
...
cfg = config.Database()

If you want to clear your config and return it back to a default state you should pass ‘clean’ or ‘default’ as parameter:

config.Database('default')
Parameters:config_file (str) – the file to load the configuration from, it can (and should) be empty to get back the previous configured data
static write(options)

Write options to the configuration file

Parameters:options (dict) – the options from the mamba-admin commands tool

Web

Subpackage containing the modules that implement web stuff for projects

AsyncJSON

class mamba.web.asyncjson.AsyncJSON(value)

Asynchronous JSON response.

I use a cooperate Twisted task in order to create a producer that send huge amounts of JSON data in an asynchronous way.

If the data being serialized into JSON is huge, the serialization process can take longest than the browser waiting response and can block itself the web server, preventing other requests from being serviced. This class prevents that type of inconveniences.

This class is based on Jean Paul Calderone post at:
http://jcalderone.livejournal.com/55680.html

Page

class mamba.web.Page(app)

This represents a full web page in mamba applications. It’s usually the root page of your web site/application.

Parameters:app (Application) – The Mamba Application that implements this page
add_script(script)

Adds a script to the page

entityType = <InterfaceClass twisted.web.resource.IResource>
getChild(path, request)

If path is an empty string or index, render_GET should be called, if not, we just look at the templates loaded from the view templates directory. If we find a template with the same name than the path then we render that template.

Caution

If there is a controller with the same path than the path then it will be hidden and the template in templates path should be rendered instead

Parameters:
  • path (str) – the path
  • request – the Twisted request object
getChildWithDefault(path, request)

Retrieve a static or dynamically generated child resource from me.

First checks if a resource was added manually by putChild, and then call getChild to check for dynamic resources. Only override if you want to affect behaviour of all child lookups, rather than just dynamic ones.

This will check to see if I have a pre-registered child resource of the given name, and call getChild if I do not.

@see: L{IResource.getChildWithDefault}

insert_scripts()

Insert scripts to the HTML

insert_stylesheets()

Insert stylesheets into the HTML

putChild(path, child)

Register a static child.

You almost certainly don’t want ‘/’ in your path. If you intended to have the root of a folder, e.g. /foo/, you want path to be ‘’.

@see: L{IResource.putChild}

register_controllers()

Add a child for each controller in the ControllerManager

render(request)

Render a given resource. See L{IResource}’s render method.

I delegate to methods of self with the form ‘render_METHOD’ where METHOD is the HTTP that was used to make the request. Examples: render_GET, render_HEAD, render_POST, and so on. Generally you should implement those methods instead of overriding this one.

render_METHOD methods are expected to return a byte string which will be the rendered page, unless the return value is C{server.NOT_DONE_YET}, in which case it is this class’s responsibility to write the results using C{request.write(data)} and then call C{request.finish()}.

Old code that overrides render() directly is likewise expected to return a byte string or NOT_DONE_YET.

@see: L{IResource.render}

render_GET(request)

Renders the index page or other templates of templates directory

render_HEAD(request)

Default handling of HEAD method.

I just return self.render_GET(request). When method is HEAD, the framework will handle this correctly.

run(port=8080)

Method to run the application within Twisted reactor

This method exists for testing purposes only and fast controller test-development-test workflow. In production you should use twistd

Parameters:port (number) – the port to listen

Response

class mamba.web.Response(code, subject, headers)

Mamba web request response base dummy object

Parameters:
  • code (int) – the HTML code for the response
  • subject (Response or dict or str) – the subject body of he response
  • headers (dict or a list of dicts) – the HTTP headers to return back in the response to the browser
class mamba.web.Ok(subject='', headers={})

Ok 200 HTTP Response

Parameters:
  • subject (Response or dict or str) – the subject body of he response
  • headers (dict or a list of dicts) – the HTTP headers to return back in the response to the browser
class mamba.web.NotFound(subject, headers={})

Error 404 Not Found HTTP Response

Parameters:
  • subject (Response or dict or str) – the subject body of he response
  • headers (dict or a list of dicts) – the HTTP headers to return back in the response to the browser
class mamba.web.BadRequest(subject='', headers={})

BadRequest 400 HTTP Response

Parameters:
  • subject (Response or dict or str) – the subject body of he response
  • headers (dict or a list of dicts) – the HTTP headers to return back in the response to the browser
class mamba.web.Conflict(subject, value, message='')

Error 409 Conflict found

Parameters:
  • subject (Response or dict or str) – the subject body of he response
  • value – the value of the conflicted operatio
  • message (str) – a customer user messahe for the response
class mamba.web.AlreadyExists(subject, value, message='')

Error 409 Conflict found in POST

Parameters:
  • subject (Response or dict or str) – the subject body of he response
  • value – the value of the conflicted operatio
  • message (str) – a customer user messahe for the response
class mamba.web.NotImplemented(url, message='')

Error 501 Not Implemented

Parameters:
  • url (str) – the URL that is not implemented
  • message (str) – a user custom message describing the problem
class mamba.web.InternalServerError(message)

Error 500 Internal Server Error

Parameters:message (str) – a user custom message with a description of the nature of the error

Routing

class mamba.web.Route(method, url, callback)

I am a Route in the Mamba routing system.

compile()

Compiles the regex matches using the complete URL

validate(dispatcher)

Validate a given path against stored URLs. Returns None if nothing matched itself otherwise

Parameters:dispatcher (RouteDispatcher) – the dispatcher object that containing the information to validate
class mamba.web.Router

I store, lookup, cache and dispatch routes for Mamba

A route is stores as:
[methods][route][Controller.__class__.__name__]
dispatch(*args, **kwargs)

Dispatch a route and return back the appropiate response.

Parameters:
  • controller (Controller) – the mamba controller
  • request (twisted.web.server.Request) – the HTTP request
install_routes(controller)

Install all the routes in a controller.

Parameters:controller (Controller) – the controller where to fid routes
register_route(controller, route)

Decorator that register a route for the given controller

Parameters:
  • controller (Controller) – the controller where to register the route
  • route (Route) – the Route to register
route(url, method='GET')

Register routes for controllers or full REST resources.

class mamba.web.RouteDispatcher(router, controller, request)

Look for a route, compile/process if neccesary and return it

lookup()

I traverse the URLs at router picking up the ones that match the controller name and then process it to validate which ones match by path/arguments to a particular Route

If nothing match just returns None

Stylesheets

class mamba.web.Stylesheet(path='', prefix='styles')

Object that represents an stylesheet or a less script

Parameters:
  • path (str) – the path of the stylesheet
  • prefix (str) – the prefix where the stylesheets reside
class mamba.web.StylesheetError

Generic class for Stylesheet exceptions

class mamba.web.InvalidFile

Fired if a file is lacking the mamba css or less headers

class mamba.web.InvalidFileExtension

Fired if the file has not a valid extension (.css or .less)

class mamba.web.FileDontExists

Raises if the file does not exists

Url Sanitizer

class mamba.web.url_sanitizer.UrlSanitizer

Sanitize URLs for a correct use

Enterprise

This is the package that give you access to Database layers. You can use traditional Open Source SQL solutions as PostgreSQL PostgreSQL, MySQL or SQLite as well as No-SQL Open Source solutions as MongoDB (work in progress).

The SQL database access is performed through Storm with some monkey patching to make possible database creation from the Pthon defined model.

Mamba is supossed to work fine with Storm since revision 223 of the bazaar repository in Storm-0.12 but we only tested it with version 0.19.

SQL through Storm

class mamba.Database(pool=None, testing=False)

Storm ORM database provider for Mamba.

Parameters:pool (twisted.python.threadpool.ThreadPool) – the thrad pool for this database
adjust_poolsize(min_threads=None, max_threads=None)

Adjusts the underlying threadpool size

Parameters:
  • min (int) – minimum number of threads
  • max (int) – maximum number of threads
backend

Return the type of backend this databse is using

database

Return the database name we are using

dump(model_manager, full=False)

Dumps the full database

Parameters:
  • model_manager (ModelManager) – the model manager from mamba application
  • full (bool) – should be dumped full?
host

Return the hostname this database is using

reset(model_manager)

Delete all the data in the database and return it to primitive state

Parameters:model_manager (ModelManager) – the model manager from mamba application
start()

Starts the Database (and the threadpool)

stop()

Stops the Database (and the threadpool)

store()

Returns a Store per-thread through storm.zope.zstorm.ZStorm

class mamba.Model

All the models in the application should inherit from this class.

We use the new storm.twisted.transact.Transactor present in the 0.19 version of Storm to run transactions that will block the reactor using a twsited.python.threadpool.ThreadPool to execute them in different threads so our reactor will not be blocked.

You must take care of don’t return any Storm object from the methods that interacts with the storm.Store underlying API because those ones are created in a different thread and cannot be used outside.

We don’t care about the instantiation of the Storm Store because we use zope.transaction through storm.zope.zstorm.ZStorm that will take care of create different instances of Store per thread for us.

create(*args, **kwargs)

Create a new register in the database

create_table(*args, **kwargs)

Create the table for this model in the underlying database system

delete(*args, **kwargs)

Delete a register from the database

drop_table(*args, **kwargs)

Delete the table for this model in the underlying database system

dump_data()

Dumps the SQL data

dump_references()

Dump SQL references (used by PostgreSQL)

dump_table()

Dumps the SQL command used for create a table with this model

Parameters:schema (str) – the SQL schema, SQLite by default
get_adapter()

Get a valid adapter for this model

get_uri()

Return an URI instance using the uri config for this model

read(*args, **kwargs)

Read a register from the database. The give key (usually ID) should be a primary key.

Parameters:id (int) – the ID to get from the database
update(*args, **kwargs)

Update a register in the database

uri

Returns the database URI for this model

Specific SQL Backends and Adaptors (used internally by Mamba)

It’s probable that you never use those ones by yourself

class mamba.enterprise.sqlite.SQLite(model)

This class implements the SQLite syntax layer for mamba

Parameters:module (Model) – the module to generate SQLite syntax for
create_table()

Return the SQLite syntax for create a table with this model

detect_primary_key()

Detect the primary key for the model and return it back with the correct SQLite syntax

Returns:a string with the correct SQLite syntax
Return type:str
Raises:SQLiteMissingPrimaryKey on missing primary key
drop_table()

Return SQLite syntax for drop this model table

insert_data()

Return the SQL syntax needed to insert the data already present in the table.

parse_column(column)

Parse a Storm column to the correct SQLite value type. For example, if we pass a column of type storm.variable.IntVariable with name amount we get back:

amount INTEGER
Parameters:column (storm.properties) – the Storm properties column to parse
parse_references()

Just skips because SQLite doen’t know anything about foreign keys

static register()

Register this component

class mamba.enterprise.mysql.MySQL(model)

This class implements the MySQL syntax layer for mamba

Parameters:module (Model) – the module to generate MySQL syntax for
create_table()

Return the MySQL syntax for create a table with this model

detect_primary_key()

Detect the primary key for the model and return it back with the correct MySQL syntax, Example:

PRIMARY KEY(id)
Returns:a string with the correct MySQL syntax
Return type:str
Raises:MySQLMissingPrimaryKey on missing primary key
drop_table()

Return MySQL syntax for drop this model table

engine

Return back the type of engine defined for this MySQL table, if no engnine has been configured use InnoDB as default

insert_data()

Return the SQL syntax needed to insert the data already present in the table.

parse_column(column)

Parse a Storm column to the correct MySQL value type. For example, if we pass a column of type SmallIntVariable with name amount we get back:

amount smallint
Parameters:column (storm.properties) – the Storm properties column to parse
parse_enum(column)
parse_references()

Get all the storm.references.Reference and create foreign keys for the SQL creation script

If we are using references we should define our classes in a correct way. If we have a model that have a relation of many to one, we should define a many-to-one Storm relationship in that object but we must create a one-to-many relation in the related model. That means if for example we have a Customer model and an Adress model and we need to relate them as one Customer may have several addresses (in a real application address may have a relation many-to-many with customer) we should define a relation with Reference from Address to Customer using a property like Address.customer_id and a ReferenceSet from Customer to Address like:

Customer.addresses = ReferenceSet(Customer.id, Address.id)

In the case of many-to-many relationships, mamba create the relation tables by itself so you dont need to take care of yourself.

static register()

Register this component

class mamba.enterprise.postgres.PostgreSQL(model)

This class implements the PostgreSQL syntax layer for mamba

Parameters:module (Model) – the module to generate PostgreSQL syntax for
create_table()

Return the PostgreSQL syntax for create a table with this model

detect_primary_key()

Detect the primary key for the model and return it back with the correct PostgreSQL syntax, Example:

PRIMARY KEY(‘id’)
Returns:a string with the correct PostgreSQL syntax
Return type:str
Raises:PostgreSQLMissingPrimaryKey on missing primary key
drop_table()

Return PostgreSQL syntax for drop this model table

insert_data()

Return the SQL syntax needed to insert the data already present in the table.

parse_column(column)

Parse a Storm column to the correct PostgreSQL value type. For example, if we pass a column of type storm.variable.IntVariable with name amount we get back:

‘amount’ integer
Parameters:column (storm.properties) – the Storm properties column to parse
parse_enum(column)

Parses an enumeration column type. In PostgreSQL enumerations are created using CREATE TYPE <name> AS ENUM (<values>); format so we need to parse it separeted from regular column parsing.

Parameters:column (storm.properties) – the Storm properties column to parse
parse_references()

Get all the storm.references.Reference and create foreign keys for the SQL creation script

If we are using references we should define our classes in a correct way. If we have a model that have a relation of many to one, we should define a many-to-one Storm relationship in that object but we must create a one-to-many relation in the related model. That means if for example we have a Customer model and an Adress model and we need to relate them as one Customer may have several addresses (in a real application address may have a relation many-to-many with customer) we should define a relation with Reference from Address to Customer using a property like Address.customer_id and a ReferenceSet from Customer to Address like:

Customer.addresses = ReferenceSet(Customer.id, Address.id)

In the case of many-to-many relationships, mamba create the relation tables by itself so you dont need to take care of yourself.

static register()

Register this component

class mamba.enterprise.database.AdapterFactory(scheme, model)

This is a factory which produces SQL Adapters.

Parameters:
  • scheme (str) – the database scheme (one of PostgreSQL, MySQL, SQLite)
  • model (Model) – the model to use with this adapter

Monkey Patches

class mamba.enterprise.database.PropertyColumnMambaPatch(prop, cls, attr, name, primary, variable_class, variable_kwargs)

We need to monkey patch part of Storm to can use size, unsigned and auto_increment named values in Properties.

I’am supossed to work well with Storm since rev 223 (v0.12)

Extension Point

class mamba.ExtensionPoint(mcs, name, bases, attrs)

Extensions mount point

This class serves 3 purposes:

  1. A way to declare a mount point for plugins or extensions point.
  2. A way to register a plugin in a particular mount point.
  3. A way to retrieve the plugins that have been registered.

The system works by declaring classes that serves as mount points. Since I subclass type I can be used as a metaclass, for example:

class ShareProvider:
    '''
    Mount point for plugins which refer to share services that can
    be used.

    Plugins implementing this reference should provide the
    following attributes:

    =========== ===================================================
    name        Share service name
    url         The URL to connect with the service
    username    The username which connect to the service
    password    The user password
    API_key     The API Key to use with the service
    =========== ===================================================

    '''
    __metaclass__ = ExtensionPoint

Then we can subclass those mount points in order to define plugins. As the plugin will also inherits from the metaclass, they will be auto registered just for subclassing the provider:

class Twitter(ShareProvider):
    name = 'Twitter'
    url = 'http://api.twitter.com/'
    ...

We can register any Share provider plugin just subclassing from the ShareProvider class and then use it to share our contents:

for share_service in ShareProvider.plugins:
    share_service().share(SharedObject)