Re: Context manager with class methods

2011-09-23 Thread Gregory Ewing

Terry Reedy wrote:


it is normal to look for special methods on the class (and superclasses)

 of an object rather than starting with the object itself.

I suspect there was a deliberate change to correct an anomaly, though 
this might have been done as part of some other change.


It's a necessary consequence of the fact that new-style classes
are also instances. Without it, there would be an ambiguity as
to whether a special method defined the behaviour of instances
of a class or of the class object itself.

It also increases efficiency, because for those special methods
that correspond to C-level type slots, you only have to look
in the type slot to find an implementation of the method,
rather than having to look in the instance dict first.

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


Context manager with class methods

2011-09-22 Thread Gavin Panella
Hi,

On Python 2.6 and 3.1 the following code works fine:

class Foo(object):

@classmethod
def __enter__(cls):
print(__enter__)

@classmethod
def __exit__(cls, exc_type, exc_value, traceback):
print(__exit__)

with Foo: pass

However, in 2.7 and 3.2 I get:

Traceback (most recent call last):
  File stdin, line 1, in module
AttributeError: __exit__

Is this a regression or a deliberate change? Off the top of my head I
can't think that this pattern is particularly useful, but it seems
like something that ought to work.

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


Re: Context manager with class methods

2011-09-22 Thread Thomas Rachel

Am 22.09.2011 12:21 schrieb Gavin Panella:

Hi,

On Python 2.6 and 3.1 the following code works fine:

 class Foo(object):

 @classmethod
 def __enter__(cls):
 print(__enter__)

 @classmethod
 def __exit__(cls, exc_type, exc_value, traceback):
 print(__exit__)

 with Foo: pass

However, in 2.7 and 3.2 I get:

 Traceback (most recent call last):
   File stdin, line 1, inmodule
 AttributeError: __exit__


Same here.

But

with Foo(): pass

works, and that is more important and more logical.


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


Re: Context manager with class methods

2011-09-22 Thread Mel
Gavin Panella wrote:

 Hi,
 
 On Python 2.6 and 3.1 the following code works fine:
 
 class Foo(object):
 
 @classmethod
 def __enter__(cls):
 print(__enter__)
 
 @classmethod
 def __exit__(cls, exc_type, exc_value, traceback):
 print(__exit__)
 
 with Foo: pass
 
 However, in 2.7 and 3.2 I get:
 
 Traceback (most recent call last):
   File stdin, line 1, in module
 AttributeError: __exit__
 
 Is this a regression or a deliberate change? Off the top of my head I
 can't think that this pattern is particularly useful, but it seems
 like something that ought to work.

This seems to work:



class MetaWith (type):
@classmethod
def __enter__(cls):
print(__enter__)

@classmethod
def __exit__(cls, exc_type, exc_value, traceback):
print(__exit__)

class With (object):
__metaclass__ = MetaWith

with With:
pass



Mel.

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


Re: Context manager with class methods

2011-09-22 Thread Mel
Mel wrote:
 This seems to work:
 
 
 
 class MetaWith (type):
 @classmethod
 def __enter__(cls):
 print(__enter__)
 
 @classmethod
 def __exit__(cls, exc_type, exc_value, traceback):
 print(__exit__)
 
 class With (object):
 __metaclass__ = MetaWith
 
 with With:
 pass

It seems to work equally well without the `@classmethod`s

Mel.

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


Re: Context manager with class methods

2011-09-22 Thread Terry Reedy

On 9/22/2011 6:21 AM, Gavin Panella wrote:


On Python 2.6 and 3.1 the following code works fine:
 class Foo(object):
 @classmethod
 def __enter__(cls):
 print(__enter__)
 @classmethod
 def __exit__(cls, exc_type, exc_value, traceback):
 print(__exit__)

 with Foo: pass


This could be regarded as a bug, see below.


However, in 2.7 and 3.2 I get:

 Traceback (most recent call last):
   File stdin, line 1, inmodule
 AttributeError: __exit__


type(Foo) == type and type has no such attribute.

Unless otherwise specified, 'method' typically means 'instance method'. 
In particular, the '__xxx__' special methods are (all?) (intended to be) 
instance methods, which is to say, functions that are attributes of an 
object's class. So it is normal to look for special methods on the class 
(and superclasses) of an object rather than starting with the object 
itself. For instance, when executing 'a+b', the interpreter never looks 
for __add__ as an attribute of a itself (in a.__dict__)

but starts the search looking for with type(a).__add__


Is this a regression or a deliberate change? Off the top of my head I
can't think that this pattern is particularly useful, but it seems
like something that ought to work.


I suspect there was a deliberate change to correct an anomaly, though 
this might have been done as part of some other change. As Thomas noted, 
*instances* of Foo work and as Mei noted, making Foo an instance of a 
(meta)class with the needed methods also works.


--
Terry Jan Reedy

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