controlling method execution

M

mic

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
 
A

anton muhin

mic said:
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

anton muhin

anton said:
mic said:
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.
 
M

Michele Simionato

mic said:
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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top