Bypassing __getattribute__ for attribute access

2007-10-25 Thread Adam Donahue
As an exercise I'm attempting to write a metaclass that causes an
exception to be thrown whenever a user tries to access
'attributes' (in the traditional sense) via a direct reference.

Consider:

class X( object ):
y = 'private value'
def get_y( self ): return self.y

Normally one can access y here via:

X().y

or

X().get_y()

I want the former case, however, to throw an exception.

I figured the way to do this would be to introduce a metaclass that
overrides the default __getattrribute__ call and throws an exception.
So my first attempt was something like:

class XType( type ):
def __my_getattribute__( self, name ):
 raise AttributeError()
def __init__( klass, name, bases, dict ):
super( XType, klass ).__init__( name, bases, dict )
setattr( klass, '__getattribute__',
klass.__my_getattribute__ )

But whereas the X().y attribute behaves as I intend, the X().get_y()
returns raises that exception as well:

>>> X().y
Traceback (most recent call last):
  File "", line 1, in ?
  File "", line 3, in __my_getattribute__
AttributeError
>>> X().get_y()
Traceback (most recent call last):
  File "", line 1, in ?
  File "", line 3, in __my_getattribute__
AttributeError

So it looks as if 'attribute' here means any key in self.__dict__,
whether referenced via self.var, self.__dict__['var'] (because this
references __dict__), or getattr( self, 'var' ) (which is the same as
a direct self.var access, I believe).

So I tried:

class XType( type ):
def __my_getattribute__( self, name ):
if name != '__dict__':
raise AttributeError()
return super( self.__class__,
self ).__getattribute__( name )
def __init__( klass, name, bases, dict ):
super( XType, klass ).__init__( name, bases, dict )
setattr( klass, '__getattribute__',
klass.__my_getattribute__ )

This allows me to access X().__dict__ directly (and then
X().__dict__['y']), but it still limits caller access to the get_y()
method.

It sounds then like the "solution" will be to check whether the name
referenced is called __dict__ or is a method or function type,
otherwise throw the exception, and to ensure all internal calls are
handled via self.__dict__[name] not self.name.

Something like:

import types
class XType( type ):
def __my_getattribute__( self, name ):
if name != '__dict__' and not
isinstance( self.__dict__[name], types.FunctionType ):
raise AttributeError()
return super( self.__class__,
self ).__getattribute__( name )
def __init__( klass, name, bases, dict ):
super( XType, klass ).__init__( name, bases, dict )
setattr( klass, '__getattribute__',
klass.__my_getattribute__ )

Of course this is imperfect as a user can simply bypass the
__getattribute__ call too and access __dict__ directly, but it's
closer to what I was thinking.  The problem is the return value for
functions is not bound - how do I bind these to the associated
instance?

(Caveat - I am not sure whether using __get__ itself in lieu of
__getattribute__ would be a better solution; but I would like to see
how binding would be done here for general knowledge.)

Thanks.

Adam

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Delete all not allowed characters..

2007-10-25 Thread Adam Donahue
On Oct 25, 10:52 am, Abandoned <[EMAIL PROTECTED]> wrote:
> Hi..
> I want to delete all now allowed characters in my text.
> I use this function:
>
> def clear(s1=""):
> if s1:
> allowed =
> [u'+',u'0',u'1',u'2',u'3',u'4',u'5',u'6',u'7',u'8',u'9',u' ', u'Þ',
> u'þ', u'Ö', u'ö', u'Ü', u'ü', u'Ç', u'ç', u'Ý', u'ý', u'Ð', u'ð', 'A',
> 'C', 'B', 'E', 'D', 'G', 'F', 'I', 'H', 'K', 'J', 'M', 'L', 'O', 'N',
> 'Q', 'P', 'S', 'R', 'U', 'T', 'W', 'V', 'Y', 'X', 'Z', 'a', 'c', 'b',
> 'e', 'd', 'g', 'f', 'i', 'h', 'k', 'j', 'm', 'l', 'o', 'n', 'q', 'p',
> 's', 'r', 'u', 't', 'w', 'v', 'y', 'x', 'z']
> s1 = "".join(ch for ch in s1 if ch in allowed)
> return s1
>
> And my problem this function replace the character to "" but i
> want to " "
> for example:
> input: Exam%^^ple
> output: Exam   ple
> I want to this output but in my code output "Example"
> How can i do quickly because the text is very long..

Something like:

import re
def clear( s, allowed=[], case_sensitive=True):
flags = ''
if not case_sensitive:
flags = '(?i)'
return re.sub( flags + '[^%s]' % ''.join( allowed ), ' ', s )

And call:

clear( '123abcdefgABCdefg321', [ 'a', 'b', 'c' ] )
clear( '123abcdefgABCdefg321', [ 'a', 'b', 'c' ], False )

And so forth.  Or just use re directly!

(This implementation is imperfect in that it's possible to hack the
regular expression, and it may break with mismatched '[]' characters,
but the idea is there.)

Adam

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Bypassing __getattribute__ for attribute access

2007-10-25 Thread Adam Donahue
Bruno,

I appreciate your attempt to answer my questions below, although I
think my main point was lost amongst all your commentary and
assumptions.  :^)  I'm not inexperienced, but I take the blame for
the rambling initial post, though, which probably lead to the
confusion.

So let me be more direct:

>From reading it seems that, indeed, __getattribute__ handles calling
attribute.__get__( obj, type(obj ), which does the binding of the
attribute to the object.

That is:

.

in turn is a call to

.__getattribute__( '' )<1>

The default body of __getattribute__ in turn fetches the associated
value (by traversing the class hierarchy if necessary) and examines
its type in order to determine what to return.

Let's assume the ultimate value associated with the attribute (key) is
v.

If type(v) is a function, __getattribute__ returns
v.__get__( , type(  )
If type(v) is, say, an integer, __getattribute__ returns v unmolested.

And so forth.

So:
>>> class X( object ):
... a = 1
... class b( object ): pass
... def c( self ): pass
...
>>> X.a
1
>>> X.b

>>> X.c

>>> x = X()
>>> x.a
1
>>> x.b

>>> x.c
>

If my interpretation is correct, the X.c's __getattribute__ call knows
the attribute reference is via a class, and thus returns an unbound
method (though it does convert the value to a method).  Likewise,
x.c's __getattribute__ returns the value as a method bound to the x
instance.

How does __getattribute__ knows the calling context.  Its first
argument is the attribute name from what I can tell, not the object
calling it.

Is this correct so far?

Moving on to __get__.  Assume:

class X( object ):
def foo(self):
print `self`
x = X()

Then:

x.foo()

Is similar (perhaps the same as) to:

X.foo.__get__( x, X )()

(__getattribute__ performs the transformation automatically when one
references via the . operator.)

And so one can do:

>>> class X( object ):
... x = 1
...
>>> def set_x( self, x ): self.x = x
...
>>> x = X()
>>> set_x.__get__( x, X )( 5 )
>>> x.x
5

The logical next question then is how does one best add a new method
to this class so that future references to x.set_x() and X.set_x will
properly resolve?  It seems the answer would be to somehow add to
X.__dict__ a new value, with key 'set_x', value the function set_x.
>From there on the . operator I assume would perform the binding to X
or x as needed on-the-fly.

Adam

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Bypassing __getattribute__ for attribute access

2007-10-26 Thread Adam Donahue
Thank you all for the detailed replies, I appreciate it.  I only read
up on this yesterday morning, but I feel I've gotten a lot of insight
in a short time thanks to your contributions to this thread.  Useful
all around!

Adam

On Oct 26, 2:50 am, Bruno Desthuilliers  wrote:
> Chris Mellon a écrit :
>
> > On Thu, 2007-10-25 at 23:13 +0200, Bruno Desthuilliers wrote:
> > 
>
> 
>
> >> Dynamically adding methods to classes is pretty
> >> straightforward, the tricky point is to dynamically add methods to
> >> instances, since the descriptor protocol is only triggered for class
> >> attributes. But you obviously found how to do it using func.__get__(obj,
> >> type(obj)) !-)
>
> > This is the greasy, getting your hands dirty way. I vastly prefer (and
> > reccomend) using the new module:
>
> Indeed.


-- 
http://mail.python.org/mailman/listinfo/python-list