<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
  <meta content="text/html;charset=ISO-8859-1" http-equiv="Content-Type">
  <title></title>
</head>
<body bgcolor="#ffffff" text="#000000">
I realize now that it would probably be best to define the problem I'm
having according to the constraints imposed by other requirements, and
not by describing the basic functionality. That way, since there are so
many possible ways to get something like what I want, there will
probably be only one (or none) solutions to the problem that matches
the criteria completely.<br>
<br>
So, to restate the original problem: I want to be able to tag the
methods of a class so that they only can be called if some external
global says it's okay. Think of it as a security device for what can or
cannot be called from a particular class instance. So if "restrict" is
True, attempts to call methods on class A: foo() and bar(), will be
disallowed, and raise an exception.<br>
<br>
Now, here are the constraints:<br>
<br>
Whatever implements this security should be something that class A is a
subclass of, or is in some other way external to the class definition
itself, since multiple classes will want to use this ability.<br>
<br>
It can't be a metaclass, because for other reasons, class A already has
a special metaclass, and you can't have two metaclasses on one class
without having one metaclass inherit from the other.<br>
<br>
You should not be able to "foil" the security by overriding the secured
methods in a subclass of A. So if A.foo() is "secured" and you make
class B a subclass of A and define b.foo(), b.foo() should also be
secured.<br>
<br>
The exception that gets raised when calling a restricted method when it
isn't allowed should be able to indicate what method was called on what
class.<br>
<br>
I'd prefer not to override __getattribute__ to look at every attempt to
access any attribute of the class instance to see if it's restricted.<br>
It'd also be nice if the ability to restrict some method was done via a
decorator-like syntax:<br>
<br>
class X:<br>
    def foo():<br>
        ...<br>
    restrict(foo)<br>
<br>
So there's the problem and constraints. I've painted myself into a
corner, and I realize that, but I have faith that someone out there who
is far better at python than me, will know some way to do this, or
something close to it.<br>
<br>
Thanks again,<br>
-David<br>
<br>
<br>
Bengt Richter wrote:
<blockquote cite="mid43cd2e6a.1346140738@news.oz.net" type="cite">
  <pre wrap="">On Mon, 16 Jan 2006 18:55:43 -0800, David Hirschfield <a class="moz-txt-link-rfc2396E" href="mailto:davidh@ilm.com"><davidh@ilm.com></a> wrote:

  </pre>
  <blockquote type="cite">
    <pre wrap="">Thanks for this, it's a great list of the ways it can be done. Here's a 
    </pre>
  </blockquote>
  <pre wrap=""><!---->Actually, your way is yet another ;-)

  </pre>
  <blockquote type="cite">
    <pre wrap="">bit more insight into the arrangement I'm trying to get:

restrict = True
    </pre>
  </blockquote>
  <pre wrap=""><!---->Why a global value? If it is to affect class instantiation, why not pass it
or a value to the constructor, e.g., C(True) or C(some_bool)?

  </pre>
  <blockquote type="cite">
    <pre wrap="">class A(object):
    </pre>
  </blockquote>
  <pre wrap=""><!---->       ^--should that be R?
  </pre>
  <blockquote type="cite">
    <pre wrap="">   _restrict = ["test"]
  
   def _null(self, *args, **kws):
       raise Exception,"not allowed to access"
      
   def test(self):
       print "test restricted"
  
   def __init__(self):
       if restrict:
           for f in self._restrict:
               setattr(self,f,self._null)
    </pre>
  </blockquote>
  <pre wrap=""><!---->I assume you know that you are using a bound method attribute
on the instance to shadow the method of the class, for a per-instance
effect as opposed to an all-instances shared effect.

  </pre>
  <blockquote type="cite">
    <pre wrap="">      
class C(R):
   def __init__(self):
       super(C,self).__init__()
      
   def test(self):
       print "test from c"


In this design, calling c.test() where c is an instance of C will raise 
an exception. Now, the only thing I'd like is to not have to fill out 
that _restrict list like that, but to have some function or something 
that let's me say which methods are restricted in the same way you 
define class methods or properties, i.e.:

class A(object):
   _restrict = []
  
   def _null(self, *args, **kws):
       raise Exception,"not allowed to access"
      
   def test(self):
       print "test restricted"
   restrict(test)
   #### this does some magic to insert "test" into the _restrict list


I can't really find a way to make that work with descriptors, and it 
can't just be a function call, because I won't know what object to get 
the _restrict list from. Is there a way to refer to the class that "is 
being defined" when calling a function or classmethod?
So, ideas on how to accomplish that...again, greatly appreciated.
    </pre>
  </blockquote>
  <pre wrap=""><!---->
You can do it with a decorator, though it doesn't really do decoration,
just adding the decoratee to the associated _restrict list. You don't
have to factor out mkrdeco if you'r'e only defining the restrict decorator
in one class.

I changed A to R, and made the global restriction flag a constructor argument,
but you can easily change that back, either by using the global restricted
in R.__init__ as a global, or by passing it explicitly like c = C(restricted).

 >>> def mkrdeco(rlist):
 ...     def restrict(f):
 ...         rlist.append(f.func_name)
 ...         return f
 ...     return restrict
 ...
 >>> class R(object):
 ...     _restrict = []
 ...     restrict = mkrdeco(_restrict)
 ...     def _null(self, *args, **kws):
 ...         raise Exception,"not allowed to access"
 ...     def __init__(self, restricted):
 ...         if restricted:
 ...             for f in self._restrict:
 ...                 setattr(self,f,self._null)
 ...     @restrict
 ...     def test(self):
 ...         print "test restricted"
 ...
 >>> class C(R):
 ...    def __init__(self, restricted=False):
 ...        super(C,self).__init__(restricted)
 ...
 ...    def test(self):
 ...        print "test from c"
 ...
 >>> c = C(True)
 >>> c.test()
 Traceback (most recent call last):
   File "<stdin>", line 1, in ?
   File "<stdin>", line 5, in _null
 Exception: not allowed to access
 >>> c2 = C(False)
 >>> c2.test()
 test from c
 >>> vars(c)
 {'test': <bound method C._null of <__main__.C object at 0x02EF3C4C>>}
 >>> vars(c2)
 {}
 >>> R._restrict
 ['test']
 
Still don't know what real application problem this is solving, but that's ok ;-)

Regards,
Bengt Richter
  </pre>
</blockquote>
<br>
<pre class="moz-signature" cols="72">-- 
Presenting:
mediocre nebula.
</pre>
</body>
</html>