Re: [Python-Dev] PEP 310 and exceptions

2005-04-23 Thread Josiah Carlson

[EMAIL PROTECTED] (holger krekel) wrote:
 basically translates to: 
 
 if hasattr(x, '__enter__'): 
 x.__enter__() 
 try: 
 ... 
 except: 
 if hasattr(x, '__except__'): x.__except__(...) 
 else: x.__exit__()
 else: 
 x.__exit__()

Nope...

 def foo():
... try:
... print 1
... return
... except:
... print 2
... else:
... print 3
...
 foo()
1
 

 - Josiah

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 310 and exceptions

2005-04-23 Thread Alex Martelli
On Apr 22, 2005, at 16:51, holger krekel wrote:
Moreover, i think that there are more than the transactional
use cases mentioned in the PEP.  For example, a handler
may want to log exceptions to some tracing utility
or it may want to swallow certain exceptions when
its block does IO operations that are ok to fail.
I entirely agree!  In fact, I was discussing this very issue recently 
with colleagues at Google, most of them well acquainted with Python but 
not all of them Python enthusiasts, and I was surprised to see 
unanimity on how PEP 310 *with* __except__ would be a huge step up in 
usefulness wrt the simple __enter__/__exit__ model, which is roughly 
equivalent in power to the C++ approach (destructors of auto variables) 
whose absence from Python and Java some people were bemoaning (which is 
how the whole discussion got started...).

The use cases appear to be aleph-0 or more...;-).  Essentially, think 
of it of encapsulating into reusable forms many common patterns of 
try/except use, much like iterators/generators can encapsulate looping 
and recursive constructs, and a new vista of uses open up...

Imagine that in two or three places in your code you see something 
like...

try:
   ...different blocks here...
except FooError, foo:
   # some FooError cases need whizbang resetting before they propagate
   if foo.wobble  FOOBAR_RESET_THRESHOLD:
  whizbang.reset_all()
   raise
With PEP 310 and __except__, this would become:
with foohandler:
   ...whatever block..
in each and every otherwise-duplicated-logic case... now THAT is 
progress!!!

IOW, +1 ... !
Alex
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] a few SF bugs which can (probably) be closed

2005-04-23 Thread Ilya Sandler
Good morning/evening/:

Here a few sourceforge bugs which can probably be closed:

[ 1168983 ] : ftplib.py string index out of range
Original poster reports that the problem disappeared after a patch
committed by Raymond

[ 1178863 ] Variable.__init__ uses self.set(), blocking specialization
seems like a dup of 1178872

[ 415492 ] Compiler generates relative filenames
seems to have been fixed at some point. I could not reproduce it with
python2.4

[ 751612 ] smtplib crashes Windows Kernal.
Seems like an obvious Windows bug (not python's bug) and seems to be
unreproducible

Ilya
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Proper place to put extra args for building

2005-04-23 Thread Brett C.
Martin v. Lwis wrote:
 Brett C. wrote:
 
Yep, you're right.  I initially thought that the parentheses meant it was a
Makefile-only variable, but it actually goes to the environment for those
unknown values.

Before I check it in, though, should setup.py be tweaked to use it as well?  I
say yes.
 
 
 You means sysconfig.py, right?

No, I mean Python's setup.py; line 174.

 Probably yes.
 

You mean Distutils' sysconfig, right?  I can change that as well if you want.

-Brett
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Proper place to put extra args for building

2005-04-23 Thread Martin v. Löwis
Brett C. wrote:
 Yep, you're right.  I initially thought that the parentheses meant it was a
 Makefile-only variable, but it actually goes to the environment for those
 unknown values.
 
 Before I check it in, though, should setup.py be tweaked to use it as well?  I
 say yes.

You means sysconfig.py, right? Probably yes.

This is a mess. distutils should just do what Makefile does for builtin
modules, i.e. use CFLAGS from the Makefile. Instead, it supports CFLAGS
as being additive to the Makefile value CFLAGS, which in turn it just
*knows* $(BASECFLAGS) $(OPT).

Regards,
Martin
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] anonymous blocks

2005-04-23 Thread Nick Coghlan
Skip Montanaro wrote:
Guido or perhaps even (making for VAR optional in the for-loop syntax)
Guido with
Guido in synchronized(the_lock):
Guido BODY
This could be a new statement, so the problematic issue of implicit
try/finally in every for statement wouldn't be necessary.  That complication
would only be needed for the above form.
s/in/with/ to get PEP 310.
A parallel which has been bugging me is the existence of the iterator protocol 
(__iter__, next()) which you can implement manually if you want, and the 
existence of generators, which provide a nice clean way of writing iterators as 
functions.

I'm wondering if something similar can't be found for the __enter__/__exit__ 
resource protocol.

Guido's recent screed crystallised the idea of writing resources as two-part 
generators:

def my_resource():
  print Hi!   # Do entrance code
  yield None# Go on with the contents of the 'with' block
  print Bye!  # Do exit code
Giving the internal generator object an enter method that calls self.next() 
(expecting None to be returned), and an exit method that does the same (but 
expects StopIteration to be raised) should suffice to make this possible with a 
PEP 310 style syntax.

Interestingly, with this approach, for dummy in my_resource() would still wrap 
the block of code in the entrance/exit code (because my_resource *is* a 
generator), but it wouldn't get the try/finally semantics.

An alternative would be to replace the 'yield None' with a 'break' or 
'continue', and create an object which supports the resource protocol and NOT 
the iterator protocol. Something like:

def my_resource():
  print Hi!   # Do entrance code
  continue  # Go on with the contents of the 'with' block
  print Bye!  # Do exit code
(This is currently a SyntaxError, so it isn't ambiguous in any way)
Cheers,
Nick.
--
Nick Coghlan   |   [EMAIL PROTECTED]   |   Brisbane, Australia
---
http://boredomandlaziness.skystorm.net
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] Re: switch statement

2005-04-23 Thread Jim Jewett
Michael Chermside wrote:

 Now the pattern matching is more interesting, but again, I'd need to
 see a proposed syntax for Python before I could begin to consider it.
 If I understand it properly, pattern matching in Haskell relies
 primarily on Haskell's excellent typing system, which is absent in
 Python.

Why not just use classes?  With either mixins or new-style classes,
it is quite reasonable to use many small classes for fine distinctions.

Change 
if predicate1(obj):
action1(obj)
elif predicate2(obj):
action2(obj)
...
else:
default(obj)

into either

try:
obj.action(locals())
except AttributeError:
default(obj, locals())

or

if hasattr(obj, action):
obj.action(locals())
else:
default

And then define an action method (perhaps through inheritance
from a mixin) for any object that should not take the default path.  
The object's own methods will have access to any variables used 
in the match and locals will have access to the current scope.  If
you have at least one class per switch, you have a switch statement.

The down sides are that 

(1)  Your domain objects will have to conform to a least a weak OO 
model (or take the default path)

(2)  Logic that should be together will be split up.  Either classes will 
be modified externally, or the switch statement logic will be broken 
up between different classes.  If single-method mixins are used to 
keep the logic close, then real objects will have to pick an ancestor 
for what may seem like arbitrary reasons.

These objections apply to any matching system based on types; the 
difference is that other languages have often already paid the price.
For Python it is an incremental cost incurred by the match system.

-jJ
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] defmacro (was: Anonymous blocks)

2005-04-23 Thread Jim Jewett
As best I can tell, the anonymous blocks are used to take 
care of boilerplate code without changing the scope -- exactly 
what macros are used for.  The only difference I see is that in 
this case, the macros are limited to entire (possibly compound) 
statements.  

To make this more concrete,

Guido:
 in synchronized(the_lock):
 BODY

Nick Coghlan:
 s/in/with/ to get PEP 310.
...

Guido's recent screed crystallised the idea of writing resources
 as two-part generators:
...

[Adding Reinhold Birkenfeld's suggestion of a blank yield]

 def my_resource():
print Hi! # Do entrance code
yield   # Go on with the contents of the 'with' block
print Bye!# Do exit code

The macro itself looks reasonable -- so long as there is only 
ever one changing block inside the macro.  I'm not sure that 
is a reasonable restriction, but the alternative is ugly enough 
that maybe passing around locals() starts to be just as good.

What about a block that indicates the enclosed namespaces
will collapse a level?

defmacro myresource(filename):
make explicit calls to named callback functions, but 
  within the same locals() scope.

with myresource(thefile):
def reader(): 
...
def writer():
...
def fn():


Then myresource, reader, writer, and fn would share a
namespace without having to manually pass it around.

-jJ
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] Re: anonymous blocks

2005-04-23 Thread Reinhold Birkenfeld
Nick Coghlan wrote:

 Interestingly, with this approach, for dummy in my_resource() would still 
 wrap 
 the block of code in the entrance/exit code (because my_resource *is* a 
 generator), but it wouldn't get the try/finally semantics.
 
 An alternative would be to replace the 'yield None' with a 'break' or 
 'continue', and create an object which supports the resource protocol and NOT 
 the iterator protocol. Something like:
 
 def my_resource():
print Hi!   # Do entrance code
continue  # Go on with the contents of the 'with' block
print Bye!  # Do exit code
 
 (This is currently a SyntaxError, so it isn't ambiguous in any way)

Oh, it is ambiguous, as soon as you insert a for/while statement in your 
resource
function and want to call continue in there. Other than that, it's very neat.

Maybe yield alone (which is always a SyntaxError) could be used.

Reinhold

-- 
Mail address is perfectly valid!

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] anonymous blocks

2005-04-23 Thread Shane Hathaway
Nick Coghlan wrote:
 An alternative would be to replace the 'yield None' with a 'break' or
 'continue', and create an object which supports the resource protocol
 and NOT the iterator protocol. Something like:
 
 def my_resource():
   print Hi!   # Do entrance code
   continue  # Go on with the contents of the 'with' block
   print Bye!  # Do exit code
 
 (This is currently a SyntaxError, so it isn't ambiguous in any way)

That's a very interesting suggestion.  I've been lurking, thinking about
a way to use something like PEP 310 to help manage database
transactions.  Here is some typical code that changes something under
transaction control:

begin_transaction()
try:
changestuff()
changemorestuff()
except:
abort_transaction()
raise
else:
commit_transaction()

There's a lot of boilerplate code there.  Using your suggestion, I could
write that something like this:

def transaction():
begin_transaction()
try:
continue
except:
abort_transaction()
raise
else:
commit_transaction()

with transaction():
changestuff()
changemorestuff()

Shane
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] Error checking in initmodule functions

2005-04-23 Thread Thomas Heller
I always wondered why there usually is very sloppy error checking in
initmodule functions.  Usually it goes like this (I removed
declarations and some other lines for clarity):

PyMODINIT_FUNC
PyInit_zlib(void)
{
m = Py_InitModule4(zlib, zlib_methods,
   zlib_module_documentation,
   (PyObject*)NULL,PYTHON_API_VERSION);

ZlibError = PyErr_NewException(zlib.error, NULL, NULL);
if (ZlibError != NULL) {
Py_INCREF(ZlibError);
PyModule_AddObject(m, error, ZlibError);
}
PyModule_AddIntConstant(m, MAX_WBITS, MAX_WBITS);
PyModule_AddIntConstant(m, DEFLATED, DEFLATED);

ver = PyString_FromString(ZLIB_VERSION);
if (ver != NULL)
PyModule_AddObject(m, ZLIB_VERSION, ver);

PyModule_AddStringConstant(m, __version__, 1.0);
}

Why isn't the result checked in the PyModule_... functions?
Why is the failure of PyErr_NewException silently ignored?
The problem is that when one of these things fail (although they are
probably supposed to NOT fail) you end up with a module missing
something, without any error message.

What would be the correct thing to do - I assume something like

 if (PyModule_AddIntConstant(m, MAX_WBITS, MAX_WBITS)) {
 PyErr_Print();
 return;
 }

Thomas

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] anonymous blocks

2005-04-23 Thread Timothy Fitz
On 4/21/05, Guido van Rossum [EMAIL PROTECTED] wrote: 
for dummy in synchronized(the_lock):
BODY
 
 or perhaps even (making for VAR optional in the for-loop syntax)
 with
 
in synchronized(the_lock):
BODY
 
 Then synchronized() could be written cleanly as follows:
 
def synchronized(lock):
lock.acquire()
try:
yield None
finally:
lock.release()

How is this different from:

def synchronized(lock):
  def synch_fn(block):
lock.acquire()
try:
  block()
finally:
  lock.release()
  return synch_fn

@synchronized
def foo():
  BLOCK

True, it's non-obvious that foo is being immediately executed, but
regardless I like the way synchronized is defined, and doesn't use
yield (which in my opinion is a non-obvious solution)
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


RE: [Python-Dev] Caching objects in memory

2005-04-23 Thread Raymond Hettinger
[Facundo Batista]
 Is there a document that details which objects are cached in memory
 (to not create the same object multiple times, for performance)?

The caches get cleaned-up before Python exit's, so you can find them all
listed together in the code in Python/pythonrun.c:

/* Sundry finalizers */
PyMethod_Fini();
PyFrame_Fini();
PyCFunction_Fini();
PyTuple_Fini();
PyList_Fini();
PyString_Fini();
PyInt_Fini();
PyFloat_Fini();

#ifdef Py_USING_UNICODE
/* Cleanup Unicode implementation */
_PyUnicode_Fini();
#endif


Raymond Hettinger
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Proper place to put extra args for building

2005-04-23 Thread Martin v. Löwis
Brett C. wrote:
You means sysconfig.py, right?

Right.

 No, I mean Python's setup.py; line 174.

Ah, ok.

 You mean Distutils' sysconfig, right?  I can change that as well if you want.

Please do; otherwise, people might see strange effects.

Regards,
Martin
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 310 and exceptions

2005-04-23 Thread holger krekel
On Fri, Apr 22, 2005 at 19:03 -0700, Josiah Carlson wrote:
 [EMAIL PROTECTED] (holger krekel) wrote:
  basically translates to: 
  
  if hasattr(x, '__enter__'): 
  x.__enter__() 
  try: 
  ... 
  except: 
  if hasattr(x, '__except__'): x.__except__(...) 
  else: x.__exit__()
  else: 
  x.__exit__()
 
 Nope...
 
  def foo():
 ... try:
 ... print 1
 ... return
 ... except:
 ... print 2
 ... else:
 ... print 3
 ...
  foo()
 1
  

doh! of course, you are right.  So it indeeds better translates 
to a nested try-finally/try-except when transformed to python code. 
Nick Coghlan points at the correct ideas below in this thread. 

At the time i was implementing things by modifying ceval.c 
rather than by just a compiling addition, i have to admit. 

cheers, 

holger
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 310 and exceptions

2005-04-23 Thread Aahz
On Sat, Apr 23, 2005, Nick Coghlan wrote:

 In light of Alex's comments, I'd actually like to suggest the below as a 
 potential new definition for PEP 310 (making __exit__ optional, and adding 
 an __else__ handler):
 
 if hasattr(x, '__enter__'):
 x.__enter__()
 try:
 try:
 # Contents of 'with' block
 except:
 if hasattr(x, '__except__'):
 if not x.__except__(*sys.exc_info()): # [1]
 raise
 else:
 raise
 else:
 if hasattr(x, '__else__'):
 x.__else__()
 finally:
 if hasattr(x, '__exit__'):
 x.__exit__()

+1, but prior to reading this post I was thinking along similar lines
with your __exit__ named __finally__ and your __else__ named __exit__.
My reasoning for that is that most of the time, people want their exit
condition aborted if an exception is raised; having the normal exit
routine called __else__ would be confusing except to people who do lots
of exception handling.

(I'm a bit sensitive to that right now; this week I wasted an hour
because I didn't understand exceptions as well as I thought I did,
although it was related more to the precise mechanics of raising and
catching exceptions.  Perhaps I'll submit a doc bug; I didn't find this
explained in _Learning Python_ or Nutshell...)
-- 
Aahz ([EMAIL PROTECTED])   * http://www.pythoncraft.com/

It's 106 miles to Chicago.  We have a full tank of gas, a half-pack of
cigarettes, it's dark, and we're wearing sunglasses.  Hit it.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 310 and exceptions

2005-04-23 Thread Nick Coghlan
Nick Coghlan wrote:
Alternately, PEP 310 could be defined as equivalent to:
if hasattr(x, '__enter__'):
x.__enter__()
try:
try:
...
except:
if hasattr(x, '__except__'):
x.__except__(*sys.exc_info())
else:
raise
finally:
x.__exit__()
In light of Alex's comments, I'd actually like to suggest the below as a 
potential new definition for PEP 310 (making __exit__ optional, and adding an 
__else__ handler):

if hasattr(x, '__enter__'):
x.__enter__()
try:
try:
# Contents of 'with' block
except:
if hasattr(x, '__except__'):
if not x.__except__(*sys.exc_info()): # [1]
raise
else:
raise
else:
if hasattr(x, '__else__'):
x.__else__()
finally:
if hasattr(x, '__exit__'):
x.__exit__()
[1] A possible tweak to this line would be to have it swallow the exception by 
default (by removing the conditional reraise). I'd prefer to make the silencing 
of the exception explicit, by returning 'True' from the exception handling, and 
have 'falling off the end' of the exception handler cause the exception to 
propagate.

Whichever way that point goes, this definition would allow PEP 310 to handle 
Alex's example of factoring out standardised exception handling, as well as the 
original use case of resource cleanup, and the transaction handling:

class transaction(object):
def __enter__(self):
begin_transaction()
def __except__(self, *exc_info):
abort_transaction()
def __else__(self):
commit_transaction()
Cheers,
Nick.
--
Nick Coghlan   |   [EMAIL PROTECTED]   |   Brisbane, Australia
---
http://boredomandlaziness.skystorm.net
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 310 and exceptions

2005-04-23 Thread Phillip J. Eby
At 01:41 PM 4/23/05 +1000, Nick Coghlan wrote:
Whichever way that point goes, this definition would allow PEP 310 to 
handle Alex's example of factoring out standardised exception handling, as 
well as the original use case of resource cleanup, and the transaction 
handling:

class transaction(object):
def __enter__(self):
begin_transaction()
def __except__(self, *exc_info):
abort_transaction()
def __else__(self):
commit_transaction()
I'd like to suggest '__success__' in place of '__else__' and 
'__before__'/'__after__' instead of '__enter__'/'__exit__', if you do take 
this approach, so that what they do is a bit more obvious. 

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 310 and exceptions

2005-04-23 Thread Bernhard Herzog
Nick Coghlan [EMAIL PROTECTED] writes:

 holger krekel wrote:
 Moreover, i think that there are more than the transactional
 use cases mentioned in the PEP.  For example, a handler may want to
 log exceptions to some tracing utility or it may want to swallow
 certain exceptions when
 its block does IO operations that are ok to fail. 

 With the current PEP 310 definition, these can be manually handled using
 sys.exc_info() in the __exit__ method.

With the proposed implementation of PEP 310 rev. 1.5 it wouldn't work.
sys.exc_info returns a tuple of Nones unless an except: clause has been
entered.  Either sys.exc_info() would have to be changed to always
return exception information after an exception has been raised or the
implementation would have to be changed to do the equivalent of e.g.

if hasattr(var, __enter__):
var.__enter__()

try:
try:
suite
except:
pass
finally:
var.__exit__()


An empty except: suite suffices.  In C that's equivalent to a call to
PyErr_NormalizeException AFAICT.



   Bernhard

-- 
Intevation GmbH http://intevation.de/
Skencil   http://skencil.org/
Thuban  http://thuban.intevation.org/
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 310 and exceptions

2005-04-23 Thread Nick Coghlan
Bernhard Herzog wrote:
With the proposed implementation of PEP 310 rev. 1.5 it wouldn't work.
sys.exc_info returns a tuple of Nones unless an except: clause has been
entered.  Either sys.exc_info() would have to be changed to always
return exception information after an exception has been raised or the
implementation would have to be changed to do the equivalent of e.g.
Interesting. Although the 'null' except block should probably be a bare 'raise', 
rather than a 'pass':

Py try:
...   try:
... raise TypeError(I'm an error!)
...   except:
... raise
... finally:
...   print sys.exc_info()
...
(class exceptions.TypeError at 0x009745A0, exceptions.TypeError instance at 0
x009E7238, traceback object at 0x009E72B0)
Traceback (most recent call last):
  File stdin, line 3, in ?
TypeError: I'm an error!
All the more reason to consider switching to a nested try/finally + 
try/except/else definition for 'with' blocks, I guess.

Cheers,
Nick.
--
Nick Coghlan   |   [EMAIL PROTECTED]   |   Brisbane, Australia
---
http://boredomandlaziness.skystorm.net
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 310 and exceptions

2005-04-23 Thread Nick Coghlan
Aahz wrote:
On Sat, Apr 23, 2005, Nick Coghlan wrote:
In light of Alex's comments, I'd actually like to suggest the below as a 
potential new definition for PEP 310 (making __exit__ optional, and adding 
an __else__ handler):

   if hasattr(x, '__enter__'):
   x.__enter__()
   try:
   try:
   # Contents of 'with' block
   except:
   if hasattr(x, '__except__'):
   if not x.__except__(*sys.exc_info()): # [1]
   raise
   else:
   raise
   else:
   if hasattr(x, '__else__'):
   x.__else__()
   finally:
   if hasattr(x, '__exit__'):
   x.__exit__()

+1, but prior to reading this post I was thinking along similar lines
with your __exit__ named __finally__ and your __else__ named __exit__.
My reasoning for that is that most of the time, people want their exit
condition aborted if an exception is raised; having the normal exit
routine called __else__ would be confusing except to people who do lots
of exception handling.
In the original motivating use cases (file handles, synchronisation objects), 
the resource release is desired unconditionally. The aim is to achieve something 
similar to C++ scope-delimited objects (which release their resources 
unconditionally as the scope is exited). This parallel is also probably the 
source of the names of the two basic functions ('enter'ing the contained block, 
'exit'ing the contained block).

So, I think try/finally is the right semantics for the basic __enter__/__exit__ 
use case (consider that PEP 310 is seen as possibly worthwhile with *only* these 
semantics!).

For error logging type use cases, only the exception handling is required. The 
issue of a 'no exception raised' handler only comes up for cases like 
transactions, where the commit operation is conditional on no exception being 
triggered. I understand you agree that, for those cases, the best spot to call 
the handler is an else clause on the inner try/except block. That way, it is 
skipped by default if an exception goes off, but the exception handling method 
can still invoke the method directly if desired (e.g. an exception is determined 
to be 'harmless'.

However, I do agree with you that the use of '__else__' as a name is exposing 
too much of the underlying implementation (i.e. you need to understand the 
implementation for the name to make sense). I think renaming '__exit_' to 
'__finally__' would be a similar error, though.

Which means finding a different name for '__else__'. Two possibilities that 
occur to me are '__ok__' or '__no_except__'. The latter makes a fair amount of 
sense, since I can't think of a way to refer to the thing other than as a 'no 
exception' handler.

Cheers,
Nick.
P.S. I'm ignoring my housemate's suggestion of '__accept__' for the no-exception 
handler :)

--
Nick Coghlan   |   [EMAIL PROTECTED]   |   Brisbane, Australia
---
http://boredomandlaziness.skystorm.net
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] Re: __except__ use cases

2005-04-23 Thread Nick Coghlan
holger krekel wrote:
On a side note, I don't see too much point in having __except__ 
return something when it is otherwise easy to say: 

def __except__(self, typ, val, tb): 
self.abort_transaction() 
raise typ, val, tb 
It has to do with Errors should never pass silently, unless explicitly 
silenced. Consider:

 def __except__(self, typ, val, tb):
 self.abort_transaction()
With __except__ returning a value, the implicit 'return None' means that the 
exception is propagated by default. Without the 'suppress exception' boolean 
return value, this naive handler would not only abort the transaction, but 
swallow each and every exception that occured inside the 'with' block.

Another common error with a manual reraise would involve not including the 
traceback properly, leading to difficulties with debugging.

IOW, returning a value from __except__ should make the exception handlers 
cleaner, and easier to 'do right' (since reraising simply means returning a 
value that evaluates to False, or falling off the end of the function). 
Suppressing the exception would require actively adding 'return True' to the end 
of the handler.

But actually i'd like to to mention some other than
transaction-use cases for __except__, for example with
class MyObject: 
def __except__(self, typ, val, tb): 
if isinstance(val, KeyboardInterrupt): 
raise 
# process exception and swallow it
s/raise/return True/ for the return value version.
def __getattr__(self, name): 
Key2AttributeError: 
return self._cache[key]
... 

with an obvious __except__() implementation for
Key2AttributeError.
Seeing this example has convinced me of something. PEP 310 should use the 'with' 
keyword, and 'expression block' syntax should be used to denote the 'default 
object' semantics proposed for Python 3K. For example:

class Key2AttributeError(object):
def __init__(self, obj, attr):
self:
.obj_type = type(obj)
.attr = attr
def __except__(self, ex_type, ex_val, ex_tb):
if isinstance(ex_type, KeyError):
 self:
 raise AttributeError(%s instance has no attribute %s
   % (.obj_type, .attr))
# Somewhere else. . .
def __getattr__(self, name):
with Key2AttributeError(self, key):
self:
return ._cache[key]
Cheers,
Nick.
--
Nick Coghlan   |   [EMAIL PROTECTED]   |   Brisbane, Australia
---
http://boredomandlaziness.skystorm.net
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com