Source code for pyamp.patterns.interfaces.interface
# Copyright 2012 Brett Ponsler
# This file is part of pyamp.
#
# pyamp is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# pyamp is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with pyamp. If not, see <http://www.gnu.org/licenses/>.
'''The interface module provides a base class which provides a function to
decorate functions in order to label specific functions as *interface*
functions.
The :class:`PassThrough' class is an implementation of the :class:`Interface`
class which provides the ability to connect a child :class:`PassThrough` object
to a parent :class:`PassThrough` object so that any time the child's interface
functions are called, the call is instead redirected to the parent's function
of the same name.
'''
__all__ = ["Interface", "PassThrough"]
[docs]class Interface:
'''The Interface class provides to ability to identify specific class
functions to be 'interface' functions.
This class contains a class property called InterfaceProperty which defines
the name of the property used to identify interface functions.
This class provides a :func:`interface` function which uses the
InterfaceProperty property to create an implementation specific decorator
which can be used to decorate functions that should identified as interface
functions.
Example::
class Example(Interface):
InterfaceProperty = "ExampleInterfaceProperty"
@Example.interface
def testPrint(self, message):
print "Message:", message
This the above example the :func:`testPrint` function has been decorated
and is thus an interface function.
'''
@classmethod
[docs] def interface(cls, function):
'''A decorator for functions to make them interface functions for
this Interface instance.
* function -- The function to decorate
'''
setattr(function, cls.InterfaceProperty, True)
return function
[docs] def getInterfaceFunctions(self):
'''Get a dictionary of the interface function names mapped
to the actual functions.
'''
functions = {}
# Traverse all of the class attributes
for attrName in dir(self):
attr = getattr(self, attrName, None)
# Only deal with existing functions
if attr is not None and hasattr(attr, "__call__"):
# Determine if the function is allowed to pass through
if hasattr(attr, self.InterfaceProperty):
functions[attrName] = attr
return functions
[docs] def connect(self, parent):
'''Connect to a parent's interface methods.
Note: This should be overriden by concrete Interfaces
* parent -- The parent interface object
'''
pass
@classmethod
[docs] def isInterface(cls, obj):
'''Determine if the given object is an instance of the interface.
* obj -- The object
'''
return isinstance(obj, cls)
[docs]class PassThrough(Interface):
'''The PassThrough :class:`Interface` provides the ability for a child
PassThrough object to connect functions of the same name to the parent's
:class:`Interface` functions.
When a child class connects to the parent's interface functions, all calls
to the child's interface functions are instead redirected to the parent's
functions of the same name.
Example::
class Parent(PassThrough):
@PassThrough.interface
def testPrint(self, message):
print "Parent message:", message
class Child(PassThrough):
pass
parent = Parent()
child = Child()
child.connect(parent)
# Prints:
# "Parent message:", this is a message
child.testPrint("this is a message")
'''
InterfaceProperty = "PassThroughFunction"
[docs] def connect(self, parent):
'''Connect the child to the parent's interface functions.
* parent -- The parent Interface
'''
# Make sure the parent implements the interface
if not PassThrough.isInterface(parent):
raise Exception("Parent [%s] must implement the " \
"PassThrough interface!" % parent)
# Duplicate each of our parent's interface functions for our
# own use, to pass the calls straight through
for name, function in parent.getInterfaceFunctions().iteritems():
setattr(self, name, function)
if __name__ == '__main__':
class Parent(PassThrough):
'''Class for testing the pass through interface.'''
@PassThrough.interface
def testPrint(self, message):
'''Function for testing the pass through interface.'''
print "Parent message:", message
class Child(PassThrough):
'''Class for testing the pass through interface.'''
pass
testParent = Parent()
testChild = Child()
testChild.connect(testParent)
testChild.testPrint("this is a message")