Source code for gf.go

import operator, __builtin__
from types import FunctionType, BuiltinFunctionType
from cStringIO import StringIO
from base import generic, method


def _get_operations():
    """Enumerate all operations to implemented as methods/generics."""
    answer = []
    for name, value in operator.__dict__.iteritems():
        if name.startswith("__") and name.endswith("__") and isinstance(
                value, (FunctionType, BuiltinFunctionType)):
            answer.append((name, value))
    answer.append(("__iter__", iter))
    answer.append(("__divmod__", divmod))
    answer.sort(key=lambda element: element[0])
    return answer

operations = {}
__all__ = []
_reverse_operation_names = (
            "add", "sub", "mul", "div",
            "truediv", "floordiv", "mod", "divmod",
            "pow",
            "lshift", "rshift",
            "and", "xor", "or" )

def _install_operations():
    """Install all the operations as generics in this module."""
    for name, value in _get_operations():
        doc = value.__doc__
        doc += "\n\n"
        doc += ("Called by the :meth:`AbstractObject.%s` special method." %
                name)
        basic_name = name[2:-2]
        if basic_name in _reverse_operation_names:
            doc += "\n"
            doc += "Also called by :meth:`AbstractObject.__r%s__` "\
                   "with arguments reversed." % basic_name
        operations[name] = globals()[name] = generic(name, doc)
        __all__.append(name)

_install_operations()


__init__ = generic("__init__",
""":func:`__init__` Initializes instances instances of AbstractObject and it's subclasses.

It has a multi method for :class:`Object`. This multi-method does not accept any
additional parameters and has no effect.
There is no method for :class:`AbstractObject`, therefore
this class can not be instantiated.""")


[docs]class Writer(object): """A simple wrapper around a file like object. :class:`Writer`'s purpose is to simplify the implementation of the generics :func:`__out__` and :func:`__spy__. `Writer` instances are initialised either with a file_like object or with no arguments. In the later case ab instance of `StringIO` is used. Output is done by simply calling the writer with at least one string object. The first argument acts as a %-template for formating the other arguments. The class is intended to be sub-classed for formatted output."""
[docs] def __init__(self, file_like = None): """Initialize the `Write` with a file like object. :param file_like: An optional file-like object.""" if file_like is None: file_like = StringIO() self.file = file_like
[docs] def __call__(self, text = None, *arguments): """Write text % arguments on the file-like objects. If no arguments are passed write a newline.""" if text is None: self.file.write("\n") else: self.file.write(text % arguments)
[docs] def get_text(self): """Get the text written so far. :Note: This method is only supported if the file-like object implements :class:`StringIO`'s :meth:`getvalue` method.""" return self.file.getvalue()
[docs]class AbstractObject(object): """An abstract (mixin) class that maps all the python magic functions to generics."""
[docs] def __init__(self, *arguments): "Call the :func:`__init__` generic function.""" __init__(self, *arguments)
[docs] def __str__(self): "Answer the objects print-string by calling :func:`as_string`.""" return as_string(self)
[docs] def __repr__(self): "Answer the objects debug-string by calling :func:`spy`.""" return spy(self)
[docs] def __float__(self): """Convert the object to a `float` by calling the :func:`__float__` generic.""" return __float__(self)
[docs] def __int__(self): """Convert the object to an `int` by calling the :func:`__int__` generic.""" return __int__(self)
[docs]class Object(AbstractObject): """Just like `AbstractObject`, but can be created."""
@method(Object)
[docs]def __init__(an_object): """Do nothing for :class:`Object`.""" pass
def _install_operations(): """Install the operations in the class.""" def get_doc(value): try: function = getattr(operator, value.__name__) except AttributeError: function = getattr(__builtin__, value.__name__[2:-2]) return function.__doc__ def generate_operation(value): def operation(*arguments): #d#print "reg:", arguments return value(*arguments) doc = get_doc(value) doc += "\n\n" doc += ("Calls the :func:`%s`-generic with its arguments." % value.__name__) operation.__doc__ = doc return operation def generate_reverse_operation(value): def operation(argument0, argument1): #d#print "rev:", argument0, argument1 return value(argument1, argument0) doc = get_doc(value) doc += "\n\n" doc += ("Calls the :func:`%s`-generic with its arguments reversed." % value.__name__) operation.__doc__ = doc return operation for name, value in _get_operations(): operation = generate_operation(operations[name]) setattr(AbstractObject, name, operation) for name in _reverse_operation_names: operation = generate_reverse_operation(operations["__%s__" % name]) setattr(AbstractObject, "__r%s__" % name, operation) _install_operations() del _install_operations del _get_operations __float__ = generic("__float__", "Convert an :class:`AbstractObject` to a `float`.") __int__ = generic("__int__", "Convert an :class:`AbstractObject` to an `int`.") @generic
[docs]def as_string(self): """Answer an object's print string. This is done by creating a :class:`Writer` instance and calling the :func:`__out__` generic with the object and the writer. The using :meth:`Writer.get_text` to retrieve the text written.""" writer = Writer() __out__(self, writer) return writer.get_text()
__out__ = generic("__out__", "Create a print string of an object using a :class:`Writer`.") @method(object, Writer) def __out__(self, write): """Write a just :func:`str` of self.""" write(str(self)) @method(AbstractObject, Writer)
[docs]def __out__(self, write): """Write a just :func:`str` of self by directly calling :meth:`object.__str__`.""" write(object.__str__(self))
@generic
[docs]def spy(self): """Answer an object's debug string. This is done by creating a :class:`Writer` instance and calling the :func:`__spy__` generic with the object and the writer. The using :meth:`Writer.get_text` to retrieve the text written.""" writer = Writer() __spy__(self, writer) return writer.get_text()
__spy__ = generic("__spy__", "Create a print string of an object using a `Writer`.") @method(object, Writer) def __spy__(self, write): """Write a just :func:`repr` of self.""" write(repr(self)) @method(AbstractObject, Writer)
[docs]def __spy__(self, write): """Write a just :func:`repr` of self by directly calling :meth:`object.__repr__`.""" write(object.__repr__(self))
__all__.extend(( "Writer", "AbstractObject", "Object", "spy", "as_string", "__spy__", "__out__", "__init__", "__float__", "__int__"))