Re: [Python-Dev] PEP 343 rewrite complete

2005-06-06 Thread Nick Coghlan
Paul Moore wrote:
 Unfortunately, I don't have a better naming suggestion (other than
 simply template, which is probably too general to work), so I just
 raise this as something you should expect to need to clarify a few
 times...

PEP 346 used statement_template for the generator decorator. That 
could be shortened to stmt_template without losing much in 
readability (stmt being a fairly common abbreviation of statement).

Avoiding the problem with the English meaning of the phrases do 
template and with template was part of the reason for PEP 346's 
choice of name (the other part being that the name tied in nicely with 
that PEP's user defined statement terminology).

Cheers,
Nick.

-- 
Nick Coghlan   |   [EMAIL PROTECTED]   |   Brisbane, Australia
---
 http://boredomandlaziness.blogspot.com
___
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 343 rewrite complete

2005-06-05 Thread Paul Moore
On 6/1/05, Guido van Rossum [EMAIL PROTECTED] wrote:
 I hope that I've got the rewrite of PEP 343 to include generator
 extensions right now. I've chosen the 'with' keyword. Please review
 here; I think this is ready for review by the unwashed masses. :-)
 
   http://www.python.org/peps/pep-0343.html

A fairly minor point - with_template read wrongly to me for quite a
while: I read it as something along the lines of with a template
(which then doesn't make much sense...) rather than template for the
with statement.

Unfortunately, I don't have a better naming suggestion (other than
simply template, which is probably too general to work), so I just
raise this as something you should expect to need to clarify a few
times...

Paul.
___
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 343 rewrite complete

2005-06-05 Thread Martin v. Löwis
Guido van Rossum wrote:
   @with_template
   def closing(obj):
   try:
   yield obj
   finally:
   obj.close()

 I just realized this has a race condition. The bytecode for the
 expression closing(open(...)) must necessarily contain a bytecode
 that calls open() followed by another bytecode that calls closing().

This is not a convincing point. That race condition always existed,
e.g. in the traditional

  f = open(filename)
  try:
process(f)
  finally:
f.close()

as you could always get an async exception between open returns and
f is assigned. This isn't much of an issue, since CPython would always
release the file immediately as the stack frame is cleared due to
the exception.

I think would should explicitly weaken our guarantees for
asynchronous exceptions (of which we currently only have
KeyboardInterrupt). The PEP should point out that an async
exception between the beginning of the with statement and
the assignment to the variable may or may not cause __exit__
to be called (depending on how far you are into __enter__)

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 343 rewrite complete

2005-06-05 Thread Guido van Rossum
On 6/5/05, Martin v. Löwis [EMAIL PROTECTED] wrote:
 Guido van Rossum wrote:
@with_template
def closing(obj):
try:
yield obj
finally:
obj.close()
 
  I just realized this has a race condition. The bytecode for the
  expression closing(open(...)) must necessarily contain a bytecode
  that calls open() followed by another bytecode that calls closing().
 
 This is not a convincing point. That race condition always existed,
 e.g. in the traditional
 
   f = open(filename)
   try:
 process(f)
   finally:
 f.close()
 
 as you could always get an async exception between open returns and
 f is assigned. This isn't much of an issue, since CPython would always
 release the file immediately as the stack frame is cleared due to
 the exception.
 
 I think would should explicitly weaken our guarantees for
 asynchronous exceptions (of which we currently only have
 KeyboardInterrupt). The PEP should point out that an async
 exception between the beginning of the with statement and
 the assignment to the variable may or may not cause __exit__
 to be called (depending on how far you are into __enter__)

That is pretty clear from the translation given in the PEP.

What is not so clear is that the cace can be completely avoided *if*
the call to __enter__ and the try-finally setup are combined in one
opcode, *and* __enter__ is implemented in C, *and* the reversible
actions are all done by __enter__.

This is also why I don't like giving file objects __enter__ and
__exit__ methods.

I know all this doesn't matter in most situations, but sometimes it
does, and it would be good if there was a solution -- today, there
really isn't one except to rely on CPython's reference counting.

-- 
--Guido van Rossum (home page: http://www.python.org/~guido/)
___
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 343 rewrite complete

2005-06-02 Thread Arnold deVos
Guido van Rossum wrote:
 [Phillip J. Eby]
* The transaction handler could also be written as:

 @with_template
 def transactional(db):
 db.begin()
 try:
 yield db
 except:
 db.rollback()
 else:
 db.commit()

at least, if I understand it correctly.
 
 
 Ah, of course. I've updated the PEP.
 

This template eats eats the exception, which will cause a RuntimeError
in the proposed Wrapper, I think.  A raise after rollback is needed.

- Arnold
___
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 343 rewrite complete

2005-06-02 Thread Arnold deVos
Arnold deVos wrote:
 
 This template eats eats the exception, which will cause a RuntimeError
 in the proposed Wrapper, I think.  A raise after rollback is needed.

Actually, the Wrapper as written in the PEP does not raise RuntimeError
if the generator catches a block's exception.

Shouldn't the relevant clause in the Wrapper go like this:

try:
self.gen.throw(type, value, traceback)
except type:
return
except StopIteration:
raise RuntimeError(generator caught exception)
else:
raise RuntimeError(generator didn't stop)

And the transaction template would go like this (re-raising the exception):

@with_template
def transactional(db):
db.begin()
try:
yield None
except:
db.rollback()
raise
else:
db.commit()

At least this is what I gleaned from the earlier threads.  It means that
the template does not appear to supress an exception that it cannot
actually supress.

- Arnold

___
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 343 rewrite complete

2005-06-02 Thread Guido van Rossum
[Arnold deVos, responding to himself]
  This template eats eats the exception, which will cause a RuntimeError
  in the proposed Wrapper, I think.  A raise after rollback is needed.

No, the generator returns after rolling back, which causes throw() to
raise StopIteration, which is good enough for the wrapper as written.

 Actually, the Wrapper as written in the PEP does not raise RuntimeError
 if the generator catches a block's exception.
 
 Shouldn't the relevant clause in the Wrapper go like this:
 
 try:
 self.gen.throw(type, value, traceback)
 except type:
 return
 except StopIteration:
 raise RuntimeError(generator caught exception)
 else:
 raise RuntimeError(generator didn't stop)

I considered that, but decided that it should be okay for the
generator to respond to a throw() by returning (thus replacing the
exception thrown by StopIteration) since the call to __exit__() is
contained inside a finally-clause, so that when __exit__() returns
normally, the finally-clause will re-raise the original exception
anyway.

Note that there are currently no other use cases for throw() except
the with_template decorator and the close() method. Both allow the
generator to respond either by letting the exception pass through it
unchanged (after executing finally-clauses if present) or by simply
returning (which will raise StopIteration in the caller of throw()).
Erroneous behaviors are, in both cases, raising some other exception
or *yielding* another value. There may be *other* use cases for
yielding a value, for example, a future (looping) block-statement a la
PEP 343. Raising another exception is always an indication of a bug in
the generator.

 And the transaction template would go like this (re-raising the exception):
 
 @with_template
 def transactional(db):
 db.begin()
 try:
 yield None
 except:
 db.rollback()
 raise
 else:
 db.commit()
 
 At least this is what I gleaned from the earlier threads.  It means that
 the template does not appear to supress an exception that it cannot
 actually supress.

I disagree (at the -0 to -0.5 level); given that the with_template
decorator allows StopIteration, I think that appearing to suppress an
exception it doesn't actually suppress is a minor sin -- the key
point is that the cleanup gets executed and doesn't raise a new
exception or reaches a yield-statement.

I'll summarize this discussion in the PEP.

-- 
--Guido van Rossum (home page: http://www.python.org/~guido/)
___
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 343 rewrite complete

2005-06-02 Thread Guido van Rossum
[me]
 I'll summarize this discussion in the PEP.

I've added this section to the PEP. Is anyone dead set against the
tentative resolutions here?

Open Issues

Discussion on python-dev has revealed some open issues.  I list
them here, with my preferred resolution and its motivation.  The
PEP as currently written reflects this preferred resolution.

1. What exception should be raised by close() when the generator
   yields another value as a response to the GeneratorExit
   exception?

   I originally chose TypeError because it represents gross
   misbehavior of the generator function, which should be fixed by
   changing the code.  But the with_template decorator class uses
   RuntimeError for similar offenses.  Arguably they should all
   use the same exception.  I'd rather not introduce a new
   exception class just for this purpose, since it's not an
   exception that I want people to catch: I want it to turn into a
   traceback which is seen by the programmer who then fixes the
   code.  So now I believe they should both raise RuntimeError.
   There are some precedents for that: it's raised by the core
   Python code in situations where endless recursion is detected,
   and for uninitialized objects (and for a variety of
   miscellaneous conditions).

2. Both the generator close() method and the __exit__() method of
   the with_template decorator class catch StopIteration and
   consider it equivalent to re-raising the exception passed to
   throw().  Is allowing StopIteration right here?

   This is so that a generator doing cleanup depending on the
   exception thrown (like the transactional() example below) can
   *catch* the exception thrown if it wants to and doesn't have to
   worry about re-raising it.  I find this more convenient for the
   generator writer.  Against this was brought in that the
   generator *appears* to suppress an exception that it cannot
   suppress: the transactional() example would be more clear
   according to this view if it re-raised the original exception
   after the call to db.rollback().  I personally would find the
   requirement to re-raise the exception an annoyance in a
   generator used as a with-template, since all the code after
   yield is used for is cleanup, and it is invoked from a
   finally-clause (the one implicit in the with-statement) which
   re-raises the original exception anyway.


-- 
--Guido van Rossum (home page: http://www.python.org/~guido/)
___
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 343 rewrite complete

2005-06-02 Thread Nick Coghlan
Guido van Rossum wrote:
 I hope that I've got the rewrite of PEP 343 to include generator
 extensions right now. I've chosen the 'with' keyword. Please review
 here; I think this is ready for review by the unwashed masses. :-)
 
   http://www.python.org/peps/pep-0343.html
 

Looks pretty good to me (looking at version 1.19).

One comment is that, in the 'optional extensions' section, where you 
say 'such mistakes are easily diagnosed', you could point to your 
generator wrapper as an example where attempting to reuse the block 
handler raises a RuntimeError on the second attempt.

Also, I'm wondering if it would be useful to have a 'closing' template 
that looked like:

   @with_template
   def closing(obj):
   try:
   yield obj
   finally:
   obj.close()

That can be used to deterministically close anything with a close 
method, be it file, generator, or something else:

   with closing(open(argument.txt)) as contradiction:
  for line in contradiction:
  print line

   with closing(some_gen()) as data:
  for datum in data:
  process(datum)


Cheers,
Nick.

-- 
Nick Coghlan   |   [EMAIL PROTECTED]   |   Brisbane, Australia
---
 http://boredomandlaziness.blogspot.com
___
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 343 rewrite complete

2005-06-02 Thread Phillip J. Eby
At 01:08 AM 6/3/2005 +1000, Nick Coghlan wrote:
Also, I'm wondering if it would be useful to have a 'closing' template
that looked like:

@with_template
def closing(obj):
try:
yield obj
finally:
obj.close()

+1 if you make it 'if hasattr(obj,close): obj.close()' in the finally 
clause, so that it will still work if the type of the object changes.

___
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 343 rewrite complete

2005-06-02 Thread Guido van Rossum
On 6/2/05, Phillip J. Eby [EMAIL PROTECTED] wrote:
 At 01:08 AM 6/3/2005 +1000, Nick Coghlan wrote:
 Also, I'm wondering if it would be useful to have a 'closing' template
 that looked like:
 
 @with_template
 def closing(obj):
 try:
 yield obj
 finally:
 obj.close()
 
 +1 if you make it 'if hasattr(obj,close): obj.close()' in the finally
 clause, so that it will still work if the type of the object changes.

But then you'd get back the bug where it would silently do nothing
when you pass it the wrong thing; wasn't that argument used against an
earlier proposal to skip calling __exit__() when it doesn't exist?

-- 
--Guido van Rossum (home page: http://www.python.org/~guido/)
___
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 343 rewrite complete

2005-06-02 Thread Phillip J. Eby
At 09:20 AM 6/2/2005 -0700, Guido van Rossum wrote:
On 6/2/05, Phillip J. Eby [EMAIL PROTECTED] wrote:
  At 01:08 AM 6/3/2005 +1000, Nick Coghlan wrote:
  Also, I'm wondering if it would be useful to have a 'closing' template
  that looked like:
  
  @with_template
  def closing(obj):
  try:
  yield obj
  finally:
  obj.close()
 
  +1 if you make it 'if hasattr(obj,close): obj.close()' in the finally
  clause, so that it will still work if the type of the object changes.

But then you'd get back the bug where it would silently do nothing
when you pass it the wrong thing;

That's not a bug, it's a feature.  If the object doesn't have a 'close()' 
method, clearly it doesn't need to be closed.  If it's the wrong object 
for what you're using it for in the body of the 'with' block, it'll show up 
there, so this doesn't hide any errors.

The idea is that with closing(foo): is just an assertion that you only 
intend to use 'foo' in the body of that block, and not afterwards, so if 
'foo' is something that needs closing, go ahead and close it.

The specific use case I have in mind is situations where a piece of code 
expects an iterable, but there are callers (or callees) that need to do 
cleanup.  On the other hand some callers (or callees) would like to just 
pass in or return a list, or are passing or returning an object from 
somewhere else that may or may not have a close() method.

Thus, a whole bunch of code would suddenly be strewed with assumptions 
about whether things can be closed or not, which seems like pure 
administrivia.  The important functionality is what the object does 
*before* you close it; that's what the programmer should be able to remain 
focused on.


wasn't that argument used against an
earlier proposal to skip calling __exit__() when it doesn't exist?

I thought the resolution of that discussion was that you should use an 
explicit wrapper if you want this behavior -- which is what 'closing()' 
is.  Anyway, if you don't like it, don't put it in.  I just thought it 
would be a good example to include for a wrapper whose behavior is more 
optional in nature.

___
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 343 rewrite complete

2005-06-02 Thread Eric Nieuwland
Phillip J. Eby wrote:
 At 10:00 PM 6/1/2005 +0200, Eric Nieuwland wrote:
 Phillip J. Eby wrote:
  -1, too confusing.

 A matter of taste, I guess. IMHO 'with' secretly handling exceptions 
 is
 confusing.

 It doesn't secretly handle them; it simply gets access to them, which 
 is an entirely different thing.

 By confusing, I mean that it is not clear from your construct what 
 exceptions are caught by the 'except' clause, due to its structural 
 layout.  It's also not clear whether the __enter__/__exit__ of EXPR 
 wrap BLOCK1 only, or both BLOCK1 and BLOCK2.  These aspects are 
 confusing because whatever decision you make about the semantics, 
 someone will have to *remember* them, as opposed to being 
 unambiguously represented by the block structure.

 By contrast, if you remove the except: clause from your construct, it 
 is clear that BLOCK1 is what is wrapped, and there is no possible 
 confusion about who sees what exceptions.  Exceptions inside the block 
 are communicated to __exit__, exceptions outside (including those in 
 the 'with' statement itself) are not.

OK. This forwarding (is that the proper expression here?) of an 
exception to __exit__ is what I meant by 'secretly handling'.

If everybody agrees I'll write
with EXPR as VAR:
try:
BLOCK1
except EXCEPTION:
BLOCK2
instead. Seems a waiste to me, though.
I was thinking about 'try EXPR [as VAR]:' as a 'try' that handles 
uncaught exceptions by forwarding it to EXPR's __exit__ method. No 
confusion with me.

--eric

___
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 343 rewrite complete

2005-06-02 Thread Phillip J. Eby
At 10:04 PM 6/2/2005 +0200, Eric Nieuwland wrote:
I was thinking about 'try EXPR [as VAR]:' as a 'try' that handles uncaught 
exceptions by forwarding it to EXPR's __exit__ method. No confusion with me.

No doubt.  However, it's not obvious what happens to an exception in EXPR; 
surely it can't be passed to EXPR's __exit__ method.  So, is it handled by 
the try, or does it pass out of the block?  Whichever answer you give, 
there is somebody who will think the opposite.  And this is precisely the 
ambiguity I've been talking about.

In contrast, a 'with' unmixed with 'try' is absolutely unambiguous as to 
which except: clauses handle what exceptions where.

___
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 343 rewrite complete

2005-06-02 Thread Eric Nieuwland

On 2 jun 2005, at 22:12, Phillip J. Eby wrote:

 At 10:04 PM 6/2/2005 +0200, Eric Nieuwland wrote:
 I was thinking about 'try EXPR [as VAR]:' as a 'try' that handles 
 uncaught exceptions by forwarding it to EXPR's __exit__ method. No 
 confusion with me.

 No doubt.  However, it's not obvious what happens to an exception in 
 EXPR; surely it can't be passed to EXPR's __exit__ method.  So, is it 
 handled by the try, or does it pass out of the block?  Whichever 
 answer you give, there is somebody who will think the opposite.  And 
 this is precisely the ambiguity I've been talking about.

 In contrast, a 'with' unmixed with 'try' is absolutely unambiguous as 
 to which except: clauses handle what exceptions where.

slap forehead I never thought of that! Now I see what you mean.
I could only save my idea by stating the scope of 'try' only starts 
after the ':', but that seems too artificial.

--eric

___
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 343 rewrite complete

2005-06-02 Thread Phillip J. Eby
At 10:16 PM 6/2/2005 +0200, Eric Nieuwland wrote:

On 2 jun 2005, at 22:12, Phillip J. Eby wrote:

  At 10:04 PM 6/2/2005 +0200, Eric Nieuwland wrote:
  I was thinking about 'try EXPR [as VAR]:' as a 'try' that handles
  uncaught exceptions by forwarding it to EXPR's __exit__ method. No
  confusion with me.
 
  No doubt.  However, it's not obvious what happens to an exception in
  EXPR; surely it can't be passed to EXPR's __exit__ method.  So, is it
  handled by the try, or does it pass out of the block?  Whichever
  answer you give, there is somebody who will think the opposite.  And
  this is precisely the ambiguity I've been talking about.
 
  In contrast, a 'with' unmixed with 'try' is absolutely unambiguous as
  to which except: clauses handle what exceptions where.

slap forehead I never thought of that! Now I see what you mean.
I could only save my idea by stating the scope of 'try' only starts
after the ':', but that seems too artificial.

That's what I mean: if you have to solve it by decree, it becomes a rule 
that people have to *remember* (or at least read carefully and think about 
it), which goes against the executable pseudocode nature.

___
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 343 rewrite complete

2005-06-02 Thread Delaney, Timothy C (Timothy)
Phillip J. Eby wrote:

 That's not a bug, it's a feature.  If the object doesn't have a
 'close()' 
 method, clearly it doesn't need to be closed.  If it's the wrong
 object 
 for what you're using it for in the body of the 'with' block, it'll
 show up 
 there, so this doesn't hide any errors.

For those semantics, I think one of the following would be better:

with local(obj):

with scoped(obj):

but those semantics apply better to __enter__ and __exit__ anyway.

I think a closing adaptor should only work with objects that have a
close() method.

Perhaps:

with scoped_closable(obj):

Tim Delaney
___
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 343 rewrite complete

2005-06-02 Thread Guido van Rossum
[Nick Coghlan]
 Also, I'm wondering if it would be useful to have a 'closing' template
 that looked like:
 
@with_template
def closing(obj):
try:
yield obj
finally:
obj.close()
 
 That can be used to deterministically close anything with a close
 method, be it file, generator, or something else:
 
with closing(open(argument.txt)) as contradiction:
   for line in contradiction:
   print line
 
with closing(some_gen()) as data:
   for datum in data:
   process(datum)

I just realized this has a race condition. The bytecode for the
expression closing(open(...)) must necessarily contain a bytecode
that calls open() followed by another bytecode that calls closing().
If a ^C happens between these two byte codes, the stack contains an
open file object that won't be closed explicitly.

With the original opening() template, this race can be avoided (and I
intend to do so) by implementing opening() in C (as a class with
__enter__ and __exit__ methods), and by making sure that the
interpreter does *not* check for interrupts between the call to
__enter__ and the start of the try-finally-statement in the
translation of the with-statement.

The only way to avoid the race that I can see with the closing()
template would be to disable signals for the duration of the
evaluation of the expression in the with-statement, but I really don't
like that solution at all -- system calls like that can be
excruciatingly expensive compared to bytecode execution. Most
applications don't catch ^C so they don't need this extra protection
-- but the compiler doesn't know that so everybody pays for it. The
solution for avoiding interrupts between the __enter__() call and the
try start doesn't require disabling signals; there can be a single
opcode that calls __enter__ and sets up the try-finally context.

-- 
--Guido van Rossum (home page: http://www.python.org/~guido/)
___
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 343 rewrite complete

2005-06-02 Thread Arnold deVos
Guido van Rossum wrote:
 
[...] a generator doing cleanup depending on the
exception thrown (like the transactional() example below) can
*catch* the exception thrown if it wants to and doesn't have to
worry about re-raising it.  I find this more convenient for the
generator writer.  Against this was brought in that the
generator *appears* to suppress an exception that it cannot
suppress: the transactional() example would be more clear
according to this view if it re-raised the original exception
after the call to db.rollback().  [...]

Of course, the explicit re-raise is only needed in a minority of use 
cases where the exception is caught. Two additional points in favour of 
this:

- refactoring a naked try as a with + template is more direct and 
uniform across all use cases.

- it is upwards compatible if the prohibition on templates suppressing 
exceptions is ever reconsidered. (Flow control macro discussion not 
withstanding.)

- Arnold

___
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 343 rewrite complete

2005-06-01 Thread Guido van Rossum
   http://www.python.org/peps/pep-0343.html

I should add that IMO this obsoletes PEP 288 and PEP 325; I plan to
reject those when PEP 343 is accepted. I've already withdrawn PEP 340.
PEP 342 is separate (but I'll probably present it together with PEP
343).

-- 
--Guido van Rossum (home page: http://www.python.org/~guido/)
___
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 343 rewrite complete

2005-06-01 Thread Phillip J. Eby
At 08:16 AM 6/1/2005 -0700, Guido van Rossum wrote:
I hope that I've got the rewrite of PEP 343 to include generator
extensions right now. I've chosen the 'with' keyword. Please review
here; I think this is ready for review by the unwashed masses. :-)

   http://www.python.org/peps/pep-0343.html


Looks great.  A few questions/comments:

* What's the rationale for raising TypeError from close()?  Wasn't 
RuntimeError discussed previously for that role?  (and it's also used by 
the with_template example)  OTOH, maybe that means we want a 
ControlFlowError or some such that can be used for both.

* The opening example under Generator Decorator seems to be missing a 
try/finally block.

* The transaction handler could also be written as:

 @with_template
 def transactional(db):
 db.begin()
 try:
 yield db
 except:
 db.rollback()
 else:
 db.commit()

at least, if I understand it correctly.
  

___
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 343 rewrite complete

2005-06-01 Thread Guido van Rossum
[Guido van Rossum]
http://www.python.org/peps/pep-0343.html

[Phillip J. Eby]
 Looks great.  A few questions/comments:
 
 * What's the rationale for raising TypeError from close()?  Wasn't
 RuntimeError discussed previously for that role?  (and it's also used by
 the with_template example)  OTOH, maybe that means we want a
 ControlFlowError or some such that can be used for both.

I really don't want a new exception for this, since it's just a bug in
the generator's code. I could go with RuntimeError here too, but I
figured TypeError's meaning in a wider sense applies: the generator
doesn't respond appropriately to the throw() call, which is similar to
not handling a particular argument (list) correctly.

 * The opening example under Generator Decorator seems to be missing a
 try/finally block.

Good catch. I've fixed this in the PEP.

 * The transaction handler could also be written as:
 
  @with_template
  def transactional(db):
  db.begin()
  try:
  yield db
  except:
  db.rollback()
  else:
  db.commit()
 
 at least, if I understand it correctly.

Ah, of course. I've updated the PEP.

-- 
--Guido van Rossum (home page: http://www.python.org/~guido/)
___
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 343 rewrite complete

2005-06-01 Thread Eric Nieuwland
Nice going! But ...

Could we extend the 'try' syntax for this instead of introducing 
'with'? If I look at the translation it an augmented 'try'.
with EXPR as VAR:
BLOCK1
except EXCEPTION:
BLOCK2
could then be translated to
abc = EXPR
exc = (None, None, None)
VAR = abc.__enter__()
try:
try:
BLOCK1
except EXCEPTION:
BLOCK2
except:
exc = sys.exc_info()
raise
finally:
abc.__exit__(*exc)


Can the 'throw()' method be renamed 'raise()'? IMHO that makes much 
clearer what happens.

Same thing with 'GeneratorExit', 'StopGeneration' more closely matches 
'StopIteration'.

--eric

___
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 343 rewrite complete

2005-06-01 Thread Eric Nieuwland
Eric Nieuwland wrote:

 If I look at the translation it an augmented 'try'.
   with EXPR as VAR:
   BLOCK1
   except EXCEPTION:
   BLOCK2

Oops, that should read:

try EXPR as VAR:
BLOCK1
except EXCEPTION:
BLOCK2

--eric

___
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 343 rewrite complete

2005-06-01 Thread Phillip J. Eby
At 08:46 PM 6/1/2005 +0200, Eric Nieuwland wrote:
Nice going! But ...

Could we extend the 'try' syntax for this instead of introducing
'with'? If I look at the translation it an augmented 'try'.
 with EXPR as VAR:
 BLOCK1
 except EXCEPTION:
 BLOCK2
could then be translated to

-1, too confusing.


Can the 'throw()' method be renamed 'raise()'? IMHO that makes much
clearer what happens.

No, 'raise' is a reserved word.  It would have to be 'raise_()'.  -0.


Same thing with 'GeneratorExit', 'StopGeneration' more closely matches
'StopIteration'.

StopIteration is raised the *other* way, so closely matching isn't really a 
benefit.  -1.

___
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 343 rewrite complete

2005-06-01 Thread Eric Nieuwland
Phillip J. Eby wrote:
 At 08:46 PM 6/1/2005 +0200, Eric Nieuwland wrote:
 If I look at the translation it an augmented 'try'.
 with EXPR as VAR:
 BLOCK1
 except EXCEPTION:
 BLOCK2
 could then be translated to

 -1, too confusing.

A matter of taste, I guess. IMHO 'with' secretly handling exceptions is 
confusing.

 Can the 'throw()' method be renamed 'raise()'? IMHO that makes much
 clearer what happens.

 No, 'raise' is a reserved word.  It would have to be 'raise_()'.  -0.

My bad. Should have thought about that.

 Same thing with 'GeneratorExit', 'StopGeneration' more closely matches
 'StopIteration'.

 StopIteration is raised the *other* way, so closely matching isn't 
 really a benefit.  -1.

Yep! Misread that one.

--eric

___
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 343 rewrite complete

2005-06-01 Thread Phillip J. Eby
At 10:00 PM 6/1/2005 +0200, Eric Nieuwland wrote:
Phillip J. Eby wrote:
  At 08:46 PM 6/1/2005 +0200, Eric Nieuwland wrote:
  If I look at the translation it an augmented 'try'.
  with EXPR as VAR:
  BLOCK1
  except EXCEPTION:
  BLOCK2
  could then be translated to
 
  -1, too confusing.

A matter of taste, I guess. IMHO 'with' secretly handling exceptions is
confusing.

It doesn't secretly handle them; it simply gets access to them, which is an 
entirely different thing.

By confusing, I mean that it is not clear from your construct what 
exceptions are caught by the 'except' clause, due to its structural 
layout.  It's also not clear whether the __enter__/__exit__ of EXPR wrap 
BLOCK1 only, or both BLOCK1 and BLOCK2.  These aspects are confusing 
because whatever decision you make about the semantics, someone will have 
to *remember* them, as opposed to being unambiguously represented by the 
block structure.

By contrast, if you remove the except: clause from your construct, it is 
clear that BLOCK1 is what is wrapped, and there is no possible confusion 
about who sees what exceptions.  Exceptions inside the block are 
communicated to __exit__, exceptions outside (including those in the 'with' 
statement itself) are not.

___
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