Esempio n. 1
0
def _build_descriptor(rule=None, __frame=None, __name=None, __proptype=CellAttribute.mkattr, __ruleattr="rule", **kw):
    frame = __frame or sys._getframe(2)
    name = __name
    if isinstance(rule, types.FunctionType):  # only pick up name if a function
        if frame.f_locals.get(rule.__name__) is rule:  # and locally-defined!
            name = name or rule.__name__

    def callback(frame, name, rule, locals):
        kw[__ruleattr] = named_lambda(rule, name)
        return __proptype(__name__=name, **kw)

    if name:
        # Have everything we need, just go for it
        return callback(frame, name, rule, None)
    elif rule is not None:
        # We know everything but the name, so return the rule as-is and trap
        # the assignment...
        try:
            # TODO: check instancemethod/function/(not a lambda)?
            name = rule.__name__
            if name == "<lambda>":
                decorators.decorate_assignment(callback, frame=frame)
                return rule
        #            print name
        except:
            decorators.decorate_assignment(callback, frame=frame)
        else:
            return callback(frame, name, rule, None)
        return rule
    else:
        # We're being used as a decorator, so just decorate.
        return decorators.decorate_assignment(callback, frame=frame)
Esempio n. 2
0
def abstract(func=None):
    """Declare a function to be abstract"""
    if func is None:
        return decorate_assignment(
            lambda f, n, func, old: Dispatching(func).as_abstract())
    else:
        return Dispatching(func).as_abstract()
Esempio n. 3
0
def on(argument_name):
    """Please switch to using @peak.rules.abstract()"""
    def callback(frm, name, value, old_locals):
        import inspect
        funcname = value.__name__
        args, varargs, kwargs, defaults = inspect.getargspec(value)
        if argument_name not in args:
            raise NameError("%r does not have an argument named %r" %
                            (value, argument_name))
        argpos = args.index(argument_name)

        func = value

        def when(cond):
            """Add following function to this GF, using 'cond' as a guard"""
            def callback(frm, name, value, old_locals):
                core.when(func, (object, ) * argpos + (cond, ))(value)
                if old_locals.get(name) is func:
                    return func
                return value

            return decorate_assignment(callback)

        def clone():
            raise AssertionError("PEAK-Rules can't clone() generic functions")

        func.when = when
        func.clone = clone
        return core.abstract(func)

    return decorate_assignment(callback)
Esempio n. 4
0
def nodetype(*mixins, **kw):

    def callback(frame, name, func, old_locals):
        def __new__(cls, *args, **kw):
            result = func(*args, **kw)
            if type(result) is tuple:
                return tuple.__new__(cls, (cls,)+result)
            else:
                return result

        def __repr__(self):
            r = self.__class__.__name__ + tuple.__repr__(self[1:])
            if len(self)==2: return r[:-2]+')'  # nix trailing ','
            return r

        def __call__(self, code):
            return func(*(self[1:]+(code,)))

        import inspect
        args = inspect.getargspec(func)[0]

        d = dict(
            __new__ = __new__, __repr__ = __repr__, __doc__=func.__doc__,
            __module__ = func.__module__, __args__ = args, __slots__ = [],
            __call__ = __call__
        )
        for p,a in enumerate(args[:-1]):    # skip 'code' argument
            if isinstance(a,str):
                d[a] = property(lambda self, p=p+1: self[p])

        d.update(kw)
        return type(name, mixins+(Node,), d)

    return decorate_assignment(callback)
Esempio n. 5
0
def on(argument_name):
    """Please switch to using @peak.rules.abstract()"""

    def callback(frm,name,value,old_locals):
        import inspect
        funcname = value.__name__
        args, varargs, kwargs, defaults = inspect.getargspec(value)
        if argument_name not in args:
            raise NameError("%r does not have an argument named %r"
                % (value, argument_name))
        argpos = args.index(argument_name)

        func = value

        def when(cond):
            """Add following function to this GF, using 'cond' as a guard"""
            def callback(frm,name,value,old_locals):
                core.when(func, (object,)*argpos + (cond,))(value)
                if old_locals.get(name) is func:
                    return func
                return value
            return decorate_assignment(callback)

        def clone():
            raise AssertionError("PEAK-Rules can't clone() generic functions")

        func.when = when
        func.clone = clone
        return core.abstract(func)

    return decorate_assignment(callback)
Esempio n. 6
0
    def _decorate(self, cond, qualifier=None, frame=None, depth=2):  # XXX
        frame = frame or sys._getframe(depth)
        cond = self.parseRule(cond, frame=frame) or cond

        def registerMethod(frm, name, value, old_locals):
            if qualifier is None:
                func = value
            else:
                func = qualifier, value

            kind, module, locals_, globals_ = frameinfo(frm)
            if kind == 'class':
                # 'when()' in class body; defer adding the method
                def registerClassSpecificMethod(cls):
                    req = strategy.Signature([(strategy.Argument(0),
                                               ICriterion(cls))])
                    self.addMethod(req & cond, func)
                    return cls

                decorate_class(registerClassSpecificMethod, frame=frm)
            else:
                self.addMethod(cond, func)

            if old_locals.get(name) in (self, self.delegate):
                return self.delegate

            return value

        return decorate_assignment(registerMethod, frame=frame)
Esempio n. 7
0
    def _hook_method(self, methodname, func=None, frame=None):
        if not self.can_connect():
            raise TypeError("%r cannot have a .%sor" % (self, methodname))

        if isinstance(self.rule, AbstractConnector):
            raise TypeError("The rule for %r is itself a Connector" % (self,))

        if getattr(self, methodname) is not None:
            raise TypeError("%r already has a .%sor" % (self, methodname))

        if func is not None:
            setattr(self, methodname, func)
            if getattr(func, "__name__", None) == self.__name__:
                frame = frame or sys._getframe(2)
                if frame.f_locals.get(self.__name__) is self:
                    return self
            return func

        frame = frame or sys._getframe(2)

        def callback(frame, name, func, locals):
            setattr(self, methodname, func)
            if name == self.__name__ and locals.get(name) is self:
                return self
            return func

        return decorators.decorate_assignment(callback, frame=frame)
    def _decorate(self,cond,qualifier=None,frame=None,depth=2):   # XXX
        frame = frame or sys._getframe(depth)
        cond = self.parseRule(cond,frame=frame) or cond

        def registerMethod(frm,name,value,old_locals):
            if qualifier is None:
                func = value
            else:
                func = qualifier,value

            kind,module,locals_,globals_ = frameinfo(frm)
            if kind=='class':
                # 'when()' in class body; defer adding the method
                def registerClassSpecificMethod(cls):
                    req = strategy.Signature(
                        [(strategy.Argument(0),ICriterion(cls))]
                    )
                    self.addMethod(req & cond, func)
                    return cls

                decorate_class(registerClassSpecificMethod,frame=frm)
            else:
                self.addMethod(cond,func)

            if old_locals.get(name) in (self,self.delegate):
                return self.delegate

            return value

        return decorate_assignment(registerMethod,frame=frame)
Esempio n. 9
0
 def when(cond):
     """Add following function to this GF, using 'cond' as a guard"""
     def callback(frm,name,value,old_locals):
         core.when(func, (object,)*argpos + (cond,))(value)
         if old_locals.get(name) is func:
             return func
         return value
     return decorate_assignment(callback)
Esempio n. 10
0
 def when(cond):
     """Add following function to this GF, using 'cond' as a guard"""
     def callback(frm,name,value,old_locals):
         declarePredicate(cond, protocol, lambda ob: (ob,value))
         if old_locals.get(name) is func:
             return func
         return value
     return decorate_assignment(callback)
Esempio n. 11
0
def abstract(func=None):
    """Declare a function to be abstract"""
    if func is None:
        return decorate_assignment(
            lambda f,n,func,old: Dispatching(func).as_abstract()
        )
    else:
        return Dispatching(func).as_abstract()
Esempio n. 12
0
    def when(cond):
        """Add following function to this GF, using 'cond' as a guard"""
        def callback(frm, name, value, old_locals):
            declarePredicate(cond, protocol, lambda ob: (ob, value))
            if old_locals.get(name) is func:
                return func
            return value

        return decorate_assignment(callback)
Esempio n. 13
0
def as_(*decorators):
    """Please switch to using @peak.util.decorators.decorate"""
    warn("Please use @peak.util.decorators.decorate instead of dispatch.as()",
        DeprecationWarning, 2
    )
    def callback(frame,k,v,old_locals):
        for d in decorators[::-1]: v = d(v)
        return v
    return decorate_assignment(callback)
Esempio n. 14
0
        def when(cond):
            """Add following function to this GF, using 'cond' as a guard"""
            def callback(frm, name, value, old_locals):
                core.when(func, (object, ) * argpos + (cond, ))(value)
                if old_locals.get(name) is func:
                    return func
                return value

            return decorate_assignment(callback)
Esempio n. 15
0
def make_module():
    def callback(frm, name, value, old_locals):
        m = new.module('dispatch.'+name)
        v = value()
        m.__dict__.update(v)
        m.__all__ = list(v)
        sys.modules.setdefault(m.__name__, m)
        sys.modules.setdefault('peak.rules.'+m.__name__, m)        
        return m
    return decorate_assignment(callback)
Esempio n. 16
0
def generic(combiner=None):
    """Use the following function as the skeleton for a generic function

    Decorate a Python function so that it wraps an instance of
    'dispatch.functions.GenericFunction' that has been configured with the
    decorated function's name, docstring, argument signature, and default
    arguments.

    The decorated function will have additional attributes besides those of
    a normal function.  (See 'dispatch.IGenericFunction' for more information
    on these special attributes/methods.)  Most commonly, you will use the
    'when()' method of the decorated function to define "rules" or "methods"
    of the generic function.  For example::

        import dispatch

        @dispatch.generic()
        def someFunction(*args):
            '''This is a generic function'''

        @someFunction.when("len(args)>0")
        def argsPassed(*args):
            print "Arguments were passed!"

        @someFunction.when("len(args)==0")
        def noArgsPassed(*args):
            print "No arguments were passed!"

        someFunction()  # prints "No args passed"
        someFunction(1) # prints "args passed"

    Note that when using older Python versions, you must use
    '[dispatch.generic()]' instead of '@dispatch.generic()'.
    """

    from dispatch.functions import GenericFunction, AbstractGeneric
    from peak.util.decorators import decorate_assignment

    if combiner is None:

        def callback(frm, name, value, old_locals):
            return GenericFunction(value).delegate
    elif isinstance(combiner, _cls) and issubclass(combiner, AbstractGeneric):

        def callback(frm, name, value, old_locals):
            return combiner(value).delegate
    else:

        def callback(frm, name, value, old_locals):
            gf = GenericFunction(value)
            gf.combine = combiner
            return gf.delegate

    return decorate_assignment(callback)
Esempio n. 17
0
def make_module():
    def callback(frm, name, value, old_locals):
        m = types.ModuleType('dispatch.' + name)
        v = value()
        m.__dict__.update(v)
        m.__all__ = list(v)
        sys.modules.setdefault(m.__name__, m)
        sys.modules.setdefault('peak.rules.' + m.__name__, m)
        return m

    return decorate_assignment(callback)
Esempio n. 18
0
def as_(*decorators):
    """Please switch to using @peak.util.decorators.decorate"""
    warn("Please use @peak.util.decorators.decorate instead of dispatch.as()",
         DeprecationWarning, 2)

    def callback(frame, k, v, old_locals):
        for d in decorators[::-1]:
            v = d(v)
        return v

    return decorate_assignment(callback)
Esempio n. 19
0
def generic(combiner=None):
    """Use the following function as the skeleton for a generic function

    Decorate a Python function so that it wraps an instance of
    'dispatch.functions.GenericFunction' that has been configured with the
    decorated function's name, docstring, argument signature, and default
    arguments.

    The decorated function will have additional attributes besides those of
    a normal function.  (See 'dispatch.IGenericFunction' for more information
    on these special attributes/methods.)  Most commonly, you will use the
    'when()' method of the decorated function to define "rules" or "methods"
    of the generic function.  For example::

        import dispatch

        @dispatch.generic()
        def someFunction(*args):
            '''This is a generic function'''

        @someFunction.when("len(args)>0")
        def argsPassed(*args):
            print "Arguments were passed!"

        @someFunction.when("len(args)==0")
        def noArgsPassed(*args):
            print "No arguments were passed!"

        someFunction()  # prints "No args passed"
        someFunction(1) # prints "args passed"

    Note that when using older Python versions, you must use
    '[dispatch.generic()]' instead of '@dispatch.generic()'.
    """

    from dispatch.functions import GenericFunction, AbstractGeneric
    from peak.util.decorators import decorate_assignment




    if combiner is None:
        def callback(frm,name,value,old_locals):
            return GenericFunction(value).delegate
    elif isinstance(combiner,_cls) and issubclass(combiner,AbstractGeneric):
        def callback(frm,name,value,old_locals):
            return combiner(value).delegate
    else:
        def callback(frm,name,value,old_locals):
            gf = GenericFunction(value)
            gf.combine = combiner
            return gf.delegate

    return decorate_assignment(callback)
Esempio n. 20
0
def meta_function(*stub, **parsers):
    """Declare a meta-function and its argument parsers"""
    stub, = stub
    def callback(frame, name, func, old_locals):
        for name in inspect.getargs(func.func_code)[0]:
            if not isinstance(name, basestring):
                raise TypeError(
                    "Meta-functions cannot have packed-tuple arguments"
                )
        what = func, parsers, inspect.getargspec(func)
        meta_functions[stub] = (
            lambda builder, *args: apply_meta(builder, what, *args)
        )
        return func
    return decorate_assignment(callback)
Esempio n. 21
0
def meta_function(*stub, **parsers):
    """Declare a meta-function and its argument parsers"""
    stub, = stub

    def callback(frame, name, func, old_locals):
        for name in inspect.getargs(func.func_code)[0]:
            if not isinstance(name, basestring):
                raise TypeError(
                    "Meta-functions cannot have packed-tuple arguments")
        what = func, parsers, inspect.getargspec(func)
        meta_functions[stub] = (
            lambda builder, *args: apply_meta(builder, what, *args))
        return func

    return decorate_assignment(callback)
Esempio n. 22
0
def weak_signature_decorator(entangler):
    """Decorate function with entangler and change signature to accept
    arbitrary additional arguments.

    Enables alternative decorator syntax for Python 2.3 as seen in PEAK:

        [my_decorator(foo)]
        def baz():
            pass

    Mind, the decorator needs to be a closure for this syntax to work.
    """
    def callback(frame, k, v, old_locals):
        return decorate(v, entangler(v), make_weak_signature(v))
    return decorate_assignment(callback, 3)
Esempio n. 23
0
def weak_signature_decorator(entangler):
    """Decorate function with entangler and change signature to accept
    arbitrary additional arguments.

    Enables alternative decorator syntax for Python 2.3 as seen in PEAK:

        [my_decorator(foo)]
        def baz():
            pass

    Mind, the decorator needs to be a closure for this syntax to work.
    """
    def callback(frame, k, v, old_locals):
        return decorate(v, entangler(v), make_weak_signature(v))

    return decorate_assignment(callback, 3)
Esempio n. 24
0
def decorator(entangler, signature=None):
    """Decorate function with entangler.

    Use signature as signature or preserve original signature if signature
    is None.

    Enables alternative decorator syntax for Python 2.3 as seen in PEAK:

        [my_decorator(foo)]
        def baz():
            pass

    Mind, the decorator needs to be a closure for this syntax to work.
    """
    def callback(frame, k, v, old_locals):
        return decorate(v, entangler(v), signature)
    return decorate_assignment(callback, 3)
Esempio n. 25
0
def generic(combiner=None):
    """Please switch to using @peak.rules.abstract()"""
    if combiner is not None:
        raise AssertionError(
            "Custom combiners are not supported by the compatibility API;"
            " please use a custom method type instead"
        )
    def callback(frm,name,value,old_locals):
        value.when   = core.when.__get__(value)
        value.around = core.around.__get__(value)
        value.before = core.before.__get__(value)
        value.after  = core.after.__get__(value)
        def clear(): core.rules_for(value).clear()
        value.clear = clear
        return core.abstract(value)

    return decorate_assignment(callback)
Esempio n. 26
0
def decorator(entangler, signature=None):
    """Decorate function with entangler.

    Use signature as signature or preserve original signature if signature
    is None.

    Enables alternative decorator syntax for Python 2.3 as seen in PEAK:

        [my_decorator(foo)]
        def baz():
            pass

    Mind, the decorator needs to be a closure for this syntax to work.
    """
    def callback(frame, k, v, old_locals):
        return decorate(v, entangler(v), signature)

    return decorate_assignment(callback, 3)
Esempio n. 27
0
 def decorate(f, pred=(), depth=2, frame=None):
     def callback(frame, name, func, old_locals):
         assert f is not func    # XXX
         kind, module, locals_, globals_ = frameinfo(frame)
         context = ParseContext(func, maker, locals_, globals_, lineno)
         def register_for_class(cls, f=f):
             _register_rule(f, pred, context, cls)
             return cls
         if kind=='class':
             # 'when()' in class body; defer adding the method
             decorate_class(register_for_class, frame=frame)
         else:
             register_for_class(None)
         if old_locals.get(name) is f:
             return f    # prevent overwriting if name is the same
         return func
     rv = decorate_assignment(callback, depth, frame)
     if frame is None: frame = sys._getframe(depth-1)
     lineno = frame.f_lineno # this isn't valid w/out active trace!
     return rv
Esempio n. 28
0
def generic(combiner=None):
    """Please switch to using @peak.rules.abstract()"""
    if combiner is not None:
        raise AssertionError(
            "Custom combiners are not supported by the compatibility API;"
            " please use a custom method type instead")

    def callback(frm, name, value, old_locals):
        value.when = core.when.__get__(value)
        value.around = core.around.__get__(value)
        value.before = core.before.__get__(value)
        value.after = core.after.__get__(value)

        def clear():
            core.rules_for(value).clear()

        value.clear = clear
        return core.abstract(value)

    return decorate_assignment(callback)
Esempio n. 29
0
 def decorate(f, pred=(), depth=2, frame=None):
     def callback(frame, name, func, old_locals):
         assert f is not func    # XXX
         kind, module, locals_, globals_ = frameinfo(frame)
         context = ParseContext(func, maker, locals_, globals_, lineno)
         def register_for_class(cls, f=f):
             _register_rule(f, pred, context, cls)
             return cls
         if kind=='class':
             # 'when()' in class body; defer adding the method
             decorate_class(register_for_class, frame=frame)
         else:
             register_for_class(None)
         if old_locals.get(name) is f:
             return f    # prevent overwriting if name is the same
         return func
     rv = decorate_assignment(callback, depth, frame)
     if frame is None: frame = sys._getframe(depth-1)
     lineno = frame.f_lineno # this isn't valid w/out active trace!
     return rv
Esempio n. 30
0
def nodetype(*mixins, **kw):
    def callback(frame, name, func, old_locals):
        def __new__(cls, *args, **kw):
            result = func(*args, **kw)
            if type(result) is tuple:
                return tuple.__new__(cls, (cls,) + result)
            else:
                return result

        def __repr__(self):
            r = self.__class__.__name__ + tuple.__repr__(self[1:])
            if len(self) == 2:
                return r[:-2] + ")"  # nix trailing ','
            return r

        def __call__(self, code):
            return func(*(self[1:] + (code,)))

        import inspect

        args = inspect.getargspec(func)[0]

        d = dict(
            __new__=__new__,
            __repr__=__repr__,
            __doc__=func.__doc__,
            __module__=func.__module__,
            __args__=args,
            __slots__=[],
            __call__=__call__,
        )
        for p, a in enumerate(args[:-1]):  # skip 'code' argument
            if isinstance(a, str):
                d[a] = property(lambda self, p=p + 1: self[p])

        d.update(kw)
        return type(name, mixins + (Node,), d)

    return decorate_assignment(callback)
Esempio n. 31
0
def on(argument_name):
    """Decorate the following function as a single-dispatch generic function

    Single-dispatch generic functions may have a slight speed advantage over
    predicate-dispatch generic functions when you only need to dispatch based
    on a single argument's type or protocol, and do not need arbitrary
    predicates.

    Also, single-dispatch functions do not require you to adapt the dispatch
    argument when dispatching based on protocol or interface, and if the
    dispatch argument has a '__conform__' method, it will attempt to use it,
    rather than simply dispatching based on class information the way
    predicate dispatch functions do.

    The created generic function will use the documentation from the supplied
    function as its docstring.  And, it will dispatch methods based on the
    argument named by 'argument_name', and otherwise keeping the same argument
    signature, defaults, etc.  For example::

        @dispatch.on('y')
        def doSomething(x,y,z):
            '''Doc for 'doSomething()' generic function goes here'''

        @doSomething.when([SomeClass,OtherClass])
        def doSomething(x,y,z):
            # do something when 'isinstance(y,(SomeClass,OtherClass))'

        @doSomething.when(IFoo)
        def doSomething(x,y,z):
            # do something to a 'y' that has been adapted to 'IFoo'
    """

    def callback(frm,name,value,old_locals):
        return _mkGeneric(value,argument_name)

    from dispatch.functions import _mkGeneric
    from peak.util.decorators import decorate_assignment
    return decorate_assignment(callback)
Esempio n. 32
0
def on(argument_name):
    """Decorate the following function as a single-dispatch generic function

    Single-dispatch generic functions may have a slight speed advantage over
    predicate-dispatch generic functions when you only need to dispatch based
    on a single argument's type or protocol, and do not need arbitrary
    predicates.

    Also, single-dispatch functions do not require you to adapt the dispatch
    argument when dispatching based on protocol or interface, and if the
    dispatch argument has a '__conform__' method, it will attempt to use it,
    rather than simply dispatching based on class information the way
    predicate dispatch functions do.

    The created generic function will use the documentation from the supplied
    function as its docstring.  And, it will dispatch methods based on the
    argument named by 'argument_name', and otherwise keeping the same argument
    signature, defaults, etc.  For example::

        @dispatch.on('y')
        def doSomething(x,y,z):
            '''Doc for 'doSomething()' generic function goes here'''

        @doSomething.when([SomeClass,OtherClass])
        def doSomething(x,y,z):
            # do something when 'isinstance(y,(SomeClass,OtherClass))'

        @doSomething.when(IFoo)
        def doSomething(x,y,z):
            # do something to a 'y' that has been adapted to 'IFoo'
    """
    def callback(frm, name, value, old_locals):
        return _mkGeneric(value, argument_name)

    from dispatch.functions import _mkGeneric
    from peak.util.decorators import decorate_assignment
    return decorate_assignment(callback)
Esempio n. 33
0
def dispatch_as(*decorators):
    """Use Python 2.4 decorators w/Python 2.2+

    Example:

        import dispatch

        class Foo(object):
            [dispatch.as(classmethod)]
            def something(cls,etc):
                \"""This is a classmethod\"""
    """

    if len(decorators) > 1:
        decorators = list(decorators)
        decorators.reverse()

    def callback(frame, k, v, old_locals):
        for d in decorators:
            v = d(v)
        return v

    from peak.util.decorators import decorate_assignment
    return decorate_assignment(callback)
Esempio n. 34
0
def dispatch_as(*decorators):
    """Use Python 2.4 decorators w/Python 2.2+

    Example:

        import dispatch

        class Foo(object):
            [dispatch.as(classmethod)]
            def something(cls,etc):
                \"""This is a classmethod\"""
    """

    if len(decorators)>1:
        decorators = list(decorators)
        decorators.reverse()

    def callback(frame,k,v,old_locals):
        for d in decorators:
            v = d(v)
        return v

    from peak.util.decorators import decorate_assignment
    return decorate_assignment(callback)
Esempio n. 35
0
def add_assignment_advisor(callback,depth=2,frame=None):
    "protocols.advice.add_assignment_advisor is deprecated, please use"
    " peak.util.decorators.decorate_assignment instead"
    from warnings import warn
    warn(add_assignment_advisor.__doc__, DeprecationWarning, 2)
    return decorators.decorate_assignment(callback, (depth or 0)+1, frame)
Esempio n. 36
0
def add_assignment_advisor(callback, depth=2, frame=None):
    "protocols.advice.add_assignment_advisor is deprecated, please use"
    " peak.util.decorators.decorate_assignment instead"
    from warnings import warn
    warn(add_assignment_advisor.__doc__, DeprecationWarning, 2)
    return decorators.decorate_assignment(callback, (depth or 0) + 1, frame)