controlling method execution

Discussion in 'Python' started by mic, Nov 20, 2003.

  1. mic

    mic Guest

    Is it possible to control method exectution using similiar mechanism as with
    get/setatrribute special methods for attributes? I'd like to have every (or
    some of ) method of class instance run common code defined outside the class
    without making any explicit references to it.
    To give an example, I'd like to prepare secure environment, in which users
    could execute only methods that can be accessed by them. IMO the most
    universal way to do it would be to run automatically authorisation routine
    before every method execution.

    Regards,

    Michal
    mic, Nov 20, 2003
    #1
    1. Advertising

  2. mic

    anton muhin Guest

    mic wrote:
    > Is it possible to control method exectution using similiar mechanism as with
    > get/setatrribute special methods for attributes? I'd like to have every (or
    > some of ) method of class instance run common code defined outside the class
    > without making any explicit references to it.
    > To give an example, I'd like to prepare secure environment, in which users
    > could execute only methods that can be accessed by them. IMO the most
    > universal way to do it would be to run automatically authorisation routine
    > before every method execution.
    >
    > Regards,
    >
    > Michal
    >
    >

    Here comes my humble attempt:

    import inspect
    import new

    def before():
    print "before"

    class WrapperMeta(type):
    def __new__(cls, name, bases, attrs):
    wrapped = {}
    for n, v in attrs.iteritems():
    if inspect.isfunction(v):
    class Controled(object):
    def __get__(self, obj, cls):
    before()
    return new.instancemethod(v, obj, cls)

    wrapped[n] = Controled()
    attrs.update(wrapped)
    return super(WrapperMeta, cls).__new__(cls, name, bases, attrs)

    class Controled(object):
    __metaclass__ = WrapperMeta

    class Test(Controled):
    def method(self, x, y):
    print 'Test.method(%s, %s)' % (x, y)

    test = Test()
    test.method(10, 11)

    I hope gurus will suggest better approaches. However, I'm afraid that
    metaclass approach cannot guarantee enough security: one can simple get
    rid of metaclass to bypass the mechanism.

    regards,
    anton.
    anton muhin, Nov 20, 2003
    #2
    1. Advertising

  3. mic

    anton muhin Guest

    anton muhin wrote:

    > mic wrote:
    >
    >> Is it possible to control method exectution using similiar mechanism
    >> as with
    >> get/setatrribute special methods for attributes? I'd like to have
    >> every (or
    >> some of ) method of class instance run common code defined outside the
    >> class
    >> without making any explicit references to it.
    >> To give an example, I'd like to prepare secure environment, in which
    >> users
    >> could execute only methods that can be accessed by them. IMO the most
    >> universal way to do it would be to run automatically authorisation
    >> routine
    >> before every method execution.
    >>
    >> Regards,
    >>
    >> Michal
    >>
    >>

    > Here comes my humble attempt:
    >
    > import inspect
    > import new
    >
    > def before():
    > print "before"
    >
    > class WrapperMeta(type):
    > def __new__(cls, name, bases, attrs):
    > wrapped = {}
    > for n, v in attrs.iteritems():
    > if inspect.isfunction(v):
    > class Controled(object):
    > def __get__(self, obj, cls):
    > before()
    > return new.instancemethod(v, obj, cls)
    >
    > wrapped[n] = Controled()
    > attrs.update(wrapped)
    > return super(WrapperMeta, cls).__new__(cls, name, bases, attrs)
    >
    > class Controled(object):
    > __metaclass__ = WrapperMeta
    >
    > class Test(Controled):
    > def method(self, x, y):
    > print 'Test.method(%s, %s)' % (x, y)
    >
    > test = Test()
    > test.method(10, 11)
    >
    > I hope gurus will suggest better approaches. However, I'm afraid that
    > metaclass approach cannot guarantee enough security: one can simple get
    > rid of metaclass to bypass the mechanism.
    >
    > regards,
    > anton.
    >


    A bug: before gets called on simple Test.method. Better solution:

    import inspect
    import new

    def before():
    print 'before'

    def after():
    print 'after'

    class WrapperMeta(type):
    def __new__(cls, name, bases, attrs):
    wrapped = {}
    for n, v in attrs.iteritems():
    if inspect.isfunction(v):
    def wrapper(self, *args, **kwargs):
    before()
    new.instancemethod(v, self, cls)(*args, **kwargs)
    after()

    wrapped[n] = wrapper
    attrs.update(wrapped)
    return super(WrapperMeta, cls).__new__(cls, name, bases, attrs)

    class Controled(object):
    __metaclass__ = WrapperMeta

    class Test(Controled):
    def method(self, x, y):
    print 'Test.method(%s, %s)' % (x, y)

    test = Test()
    test.method(10, 11)
    test.method

    sorry,
    anton.
    anton muhin, Nov 20, 2003
    #3
  4. "mic" <> wrote in message news:<bphufr$1iaf$>...
    > Is it possible to control method exectution using similiar mechanism as with
    > get/setatrribute special methods for attributes? I'd like to have every (or
    > some of ) method of class instance run common code defined outside the class
    > without making any explicit references to it.
    > To give an example, I'd like to prepare secure environment, in which users
    > could execute only methods that can be accessed by them. IMO the most
    > universal way to do it would be to run automatically authorisation routine
    > before every method execution.
    >
    > Regards,
    >
    > Michal


    setattr/getattr work with methods just as with attributes, provided you
    define your setattr/getattr in the right place, i.e. in the metaclass.
    Google for "simionato frozen" in c.l.py (first hit) and you will see
    an example of how to make methods "safe" under accidental overriding
    with this trick. Also, you may want to look at properties.
    For what concern your problem (securing method execution) here I show
    you another metaclass based solution, which is the less intrusive solution
    (i.e. you don't change the original class).
    Of course, the password mechanism I show in this example is ridicolous from
    the point of view of security, but you can replace the password
    step with any kind of "secure" identification mechanism you want.
    Needless to say, security goes to zero if people have access to Python
    and they know how to use its dynamical capabilities. Still, the method may
    prevent accidental method calls:

    ### protecting methods from execution ####

    PASSWD="xxx"
    class ProtectionError(Exception): pass

    def securecall(func,*args):
    know_the_passwd=raw_input("Password required to use this method:")==PASSWD
    if know_the_passwd: return func(*args)
    else: raise ProtectionError("Wrong password given")

    class Secure(type):
    def __init__(cls,n,b,d):
    for k,v in d.iteritems():
    if hasattr(v,"__doc__") and v.__doc__=='protected':
    setattr(cls,k,lambda self,*args: securecall(v,self,*args))

    class C(object):
    __metaclass__=Secure
    def f(self,*args):
    "protected"
    print "Doing something if the user know the password"

    C().f()

    # END

    Here you protect your methods by using a docstring containing the word
    "protected". It is easy to try variations of this idea.

    HTH,

    Michele
    Michele Simionato, Nov 21, 2003
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Itai
    Replies:
    0
    Views:
    433
  2. TomislaW
    Replies:
    2
    Views:
    4,153
    James Moore
    Nov 10, 2004
  3. Angus Parvis
    Replies:
    1
    Views:
    19,435
    Angus Parvis
    Aug 4, 2004
  4. Andy Fish
    Replies:
    2
    Views:
    499
    Andy Fish
    Jun 15, 2004
  5. Kyung won Cheon
    Replies:
    0
    Views:
    182
    Kyung won Cheon
    Nov 21, 2008
Loading...

Share This Page