Mangle function name with decorator?

Adam adam.crossland at gmail.com
Wed Mar 18 09:47:56 EDT 2009


On Mar 17, 1:49 pm, Aaron Brady <castiro... at gmail.com> wrote:

> You would need a unique attribute to look for on values in the
> dictionary, which means you'd need to detect what functions you are
> renaming; possibly by using a decorator to mark them.  (Untested:)
>
> class X( metaclass= M ):
>   @mark( 'A' )
>   def foo( ... ).
>
> class M( type ):
>   def __new__( cls, name, bases, namespace ):
>     for k, v in namespace.items():
>       if v.tag== 'mark-A':
>         namespace[ k ]= modification( v )
> or in your case:
>         del namespace[ k ]
>         namespace[ k_mod ]= v.original
>
> possibly also setting func_name as well.
>     return type( name, bases, namespace )

I tried this, but unfortunately, it still doesn't allow me to have two
methods that initially have the same name, because the namespace
dictionary that the metaclass gets only has one one entry, the last
one in.  So, if I try code like this:

def get_only(action):
    setattr(action, "get_only", True)

    return action

class ControllerMetaclass(type):
    def __new__(cls, name, bases, namespace):
        print str(namespace)
        for k, v in namespace.items():
            if hasattr(v, "get_only"):
                new_name = "_get_" + k
                print "new_name is " + new_name
                del namespace[k]
                namespace[new_name] = v
                v.__name__ = new_name
        return type(name, bases, namespace)

class Controller(object):
    def __call__(self):
        if (self.method != None):
            get_mangled_name = "_" + self.method + "_" + self.action
            if hasattr(self, get_mangled_name):
                method = getattr(self, get_mangled_name)
                return method()
            else:
                if hasattr(self, self.action):
                    return getattr(self, self.action)()
                else:
                    raise NotImplementedError
        else:
            if hasattr(self, self.action):
                return getattr(self, self.action)()
            else:
                raise NotImplementedError

class foo_controller(Controller):
    __metaclass__= ControllerMetaclass
    def __init__(self, action, method = None):
        self.action = action
        self.method = method


    def foo(self):
        print "in foo()"

    @get_only
    def foo(self):
        print "in get_only foo()"

    def bar(self):
        print "in bar()"


a = foo_controller("foo", "get")
a()

b = foo_controller("foo")
print dir(b)
b()

c = foo_controller("bar","get")
c()

The first definition of foo (the one that is not decorated) is over-
written by the second one, and the metaclass never sees it.  So, I
think that I understand what you said about storing the functions in a
hashtable.  That makes sense, as I can keep a reference to the
function even if ti gets over-written in the class main namespace
dictionary.  However, I'm not entirely sure about how to do that with
decorators.  Wouldn't the decorator function have to be bound to a
context to keep a hastable between calls?  I can't us a bound method
as a decorator, can I?



More information about the Python-list mailing list