I'll combine my replies to Josian and Talin:

On 8/11/06, Josiah Carlson <[EMAIL PROTECTED]> wrote:
Let us say that I have two metadata interpters.  One that believes that
the metadata is types and wants to verify type on function call.  The
other believes that the metadata is documentation.  Both were written
without regards to the other.  Please describe to me (in code preferably)
how I would be able to use both of them without having a defined
metadata interpretation chaining semantic.

On 8/11/06, Talin <[EMAIL PROTECTED]> wrote:
Say I want to annotate a specific argument with two pieces of
information, a type and a docstring. I have two metadata interpreters,
one which uses the type information to restrict the kinds of arguments
that can be passed in, and another which uses the docstring to enhance
the generated documentation.

[snipped: the rise of a defacto annotation-sharing standard]

What this means is that, despite the statements that annotations have no
defined format or meaning, the fact is that they now do: The defacto A&B
sharing convention. The sharing convention tells metadata interpreters
how to distinguish between metadata that they can interpret, and how to
skip over other metadata.

What Josiah is hinting at -- and what Talin describes more explicitly
-- is the problem of how exactly "chaining" annotation interpreters
will work.

The case I've thought out the most completely is that of using
decorators to analyse/utilise the annotations:

1) Each decorator should be written with the assumption that it is the
only decorator that will be applied to a given function (with respect
to annotations).

2) Chaining will be accomplished by maintaining this illusion for each
decorator. For example, if our annotation-sharing convention is that
annotations will be n-tuples (n == number of annotation-interpreting
decorators), where t[i] is the annotation the i-th decorator should
care about, the following chain() function will do the trick (a full
demo script is attached):

def chain(*decorators):
    assert len(decorators) >= 2

    def decorate(function):
        sig = function.__signature__
        original = sig.annotations

        for i, dec in enumerate(decorators):
            fake = dict((p, original[p][i]) for p in original)

            function.__signature__.annotations = fake
            function = dec(function)

        function.__signature__.annotations = original
        return function
    return decorate

A similar function can be worked out for using dictionaries to specify
multiple annotations.

I'll update the PEP draft to include a section on guidelines for
writing such decorators.

Collin Winter
### For faking functions with signatures
########################################

class Sig(object):
    def __init__(self, **kwargs):
        for k, v in kwargs.items():
            setattr(self, k, v)

class Func(object):
    def __init__(self, call, **kwargs):
        self.__signature__ = Sig(annotations=kwargs)
        self._callable = call
        
    def __call__(self, *args, **kwargs):
        return self._callable(*args, **kwargs)
        
### For chaining annotation-intrepreting decorators
### Annotations should be in the form of n-tuples, where n is the number
### of decorators given to chain()
########################################################################

def chain(*decorators):
    assert len(decorators) >= 2

    def decorate(function):
        sig = function.__signature__
        original = sig.annotations
        
        for i, dec in enumerate(decorators):
            fake = dict((p, original[p][i]) for p in original)
            
            function.__signature__.annotations = fake
            function = dec(function)            
        
        function.__signature__.annotations = original 
        return function
    return decorate


### Demonstrate
###############    
    
def dec_1(func):
    print "dec_1:", func.__signature__.annotations
    return func
    
def dec_2(func):
    print "dec_2:", func.__signature__.annotations
    return func


f = Func(min, a=(4, "four"), b=(5, "five"), c=(6, "six"))

print chain(dec_1, dec_2)(f)(5, 8)
_______________________________________________
Python-3000 mailing list
[email protected]
http://mail.python.org/mailman/listinfo/python-3000
Unsubscribe: 
http://mail.python.org/mailman/options/python-3000/archive%40mail-archive.com

Reply via email to