Re: [Python-Dev] PEP 343 - Abstract Block Redux

2005-05-14 Thread Nick Coghlan
Robert Brewer wrote:
 There's a typo in the code snippets at the moment.
 
 The translation of the above statement is:
 
 abc = EXPR
 exc = ()  # Or (None, None, None) ?
 try:
 try:
 VAR = abc.__enter__()
 BLOCK
 except:
 exc = sys.exc_info()
 raise
 finally:
 abc.__exit__(exc)
 
 I think you meant abc.__exit__(*exc). Assuming that, then exc =
 (None, None, None) makes the most sense. If exc_info() is going to be
 passed as a single arg, then I'd rather have the default exc = (), so
 I can simply check if exc: in the __exit__ method.

Also, the call to __enter__() needs to be before the try/finally block (as it 
is 
in PEP 310). Otherwise we get the releasing a lock you failed to acquire 
problem.

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 - Abstract Block Redux

2005-05-14 Thread Nick Coghlan
Guido van Rossum wrote:
 I've written up the specs for my PEP 340 redux proposal as a
 separate PEP, PEP 343.
 
 http://python.org/peps/pep-0343.html
 
 Those who have been following the thread Merging PEP 310 and PEP
 340-redux? will recognize my proposal in that thread, which received
 mostly positive responses there.
 
 Please review and ask for clarifications of anything that's unclear.

On the keyword front, the two keyword choices affect the naming conventions of 
templates differently, and I think need to be considered in that light.

The naming convention for 'do' is shown in the current PEP 343. The issue I've 
noticed with it is that *functions* read well, but methods don't because things 
get out of sequence. That is, do locking(the_lock) reads well, but do 
the_lock.locking() does not.

Whereas, using 'with', it can be written either way, and still read reasonably 
well (with locked(the_lock), with the_lock.locked()).

The 'with' keyword also reads better if objects natively support use in 'with' 
blocks (with the_lock, with the_file).

Guido's concern regarding file objects being reused inappropriately can be 
dealt 
with in the file __enter__ method:

   def __enter__(self):
   if self.closed:
   raise RuntimeError, Cannot reopen closed file handle

Template generators have the exact same problem with reusability - the solution 
used there is raising a RuntimeError when __enter__() is called 
inappropriately. 
This would make sense as a standard idiom - if a statement template can't be 
reused, attempting to do so should trigger a RuntimeError the second time 
__enter__() is invoked.

For files, it may then become the common practice to keep pathnames around, 
rather than open file handles. When you actually needed access to the file, the 
existing open builtin would suffice:

   with open(filename, rb) as f:
   for line in f:
   print line

I've written out the PEP 343 examples below, assuming types acquire native with 
statement support (including Decimal contexts - I also give PEP 343 style code 
for Decimal contexts).

PEP343 examples: 'with' keyword, native support in objects

1. A template for ensuring that a lock, acquired at the start of a
block, is released when the block is left:

 # New methods on lock objects
 def __enter__(self):
 self.acquire()

 def __exit__(self, *args):
 self.release()

Used as follows:

 with myLock:
 # Code here executes with myLock held.  The lock is
 # guaranteed to be released when the block is left (even
 # if via return or by an uncaught exception).

 2. A template for opening a file that ensures the file is closed
when the block is left:

 # New methods on file objects
 def __enter__(self):
 if self.closed:
 raise RuntimeError, Cannot reopen closed file handle

 def __exit__(self, *args):
 self.close()

Used as follows:

 with open(/etc/passwd) as f:
 for line in f:
 print line.rstrip()

 3. A template for committing or rolling back a database
transaction; this is written as a class rather than as a
decorator since it requires access to the exception information:

 class transaction:
 def __init__(self, db):
 self.db = db
 def __enter__(self):
 self.db.begin()
 def __exit__(self, *args):
 if args and args[0] is not None:
 self.db.rollback()
 else:
 self.db.commit()

   Used as follows:

 with transaction(db):
 # Exceptions in this code cause a rollback

 5. Redirect stdout temporarily:

 @with_template
 def redirected_stdout(new_stdout):
 save_stdout = sys.stdout
 sys.stdout = new_stdout
 yield None
 sys.stdout = save_stdout

Used as follows:

 with open(filename, w) as f:
 with redirected_stdout(f):
 print Hello world

This isn't thread-safe, of course, but neither is doing this
same dance manually.  In a single-threaded program (e.g., a
script) it is a totally fine way of doing things.

 6. A variant on opening() that also returns an error condition:

 @with_template
 def open_w_error(filename, mode=r):
 try:
 f = open(filename, mode)
 except IOError, err:
 yield None, err
 else:
 yield f, None
 f.close()

Used as follows:

 with open_w_error(/etc/passwd, a) as f, err:
 if err:
 print IOError:, err
 else:
 f.write(guido::0:0::/:/bin/sh\n)

 7. 

Re: [Python-Dev] PEP 343 - Abstract Block Redux

2005-05-14 Thread Fredrik Lundh
Guido van Rossum wrote:

 I've written up the specs for my PEP 340 redux proposal as a
 separate PEP, PEP 343.

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

 Those who have been following the thread Merging PEP 310 and PEP
 340-redux? will recognize my proposal in that thread, which received
 mostly positive responses there.

 Please review and ask for clarifications of anything that's unclear.

intuitively, I'm -1 on this proposal.

unlike the original design, all you get from this is
the ability to add try/finally blocks to your code
without ever writing a try/finally-clause (neither
in your code or in the block controller).  that
doesn't strike me as especially pythonic.

(neither does the argument that just because you
can use a mechanism to write inscrutable code,
such a mechanism must not be made available
feel right; Python's design has always been about
careful tradeoffs between policy and mechanism,
but this is too much policy for my taste.  the
original PEP 340 might have been too clever, but
this reduced version feels pretty pointless).

/F



___
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 - Abstract Block Redux

2005-05-14 Thread Nick Coghlan
Fredrik Lundh wrote:
 unlike the original design, all you get from this is
 the ability to add try/finally blocks to your code
 without ever writing a try/finally-clause (neither
 in your code or in the block controller).  that
 doesn't strike me as especially pythonic.

I think the key benefit relates to the fact that correctly written resource 
management code currently has to be split it into two pieces - the first piece 
before the try block (e.g. 'lock.acquire()', 'f = open()'), and the latter in 
the finally clause (e.g. 'lock.release()', 'f.close()').

PEP 343 (like PEP 310 before it) makes it possible to define the correct 
resource management *once*, and then invoke it via a 'with' (or 'do') statement.

Instead of having to check for is this file closed properly?, as soon as you 
write or see with open(filename) as f:, you *know* that that file is going to 
be closed correctly.

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] Merging PEP 310 and PEP 340-redux?

2005-05-14 Thread Michael Hudson
Guido van Rossum [EMAIL PROTECTED] writes:

 [Michael Hudson, after much thinking aloud]

Yeah, sorry about that :)

 Oh, I guess the point is that with a decorated generator you can yield
 a value to be used as VAR, rather than just discarding the value as
 here.  Hmm.

 Right. (I thought it was worth quoting this for the benefit of other
 who went down the same trail but didn't quite make it to this
 destination.)

 If things were fiddled such that sys.exc_info() return non-Nones when
 a finally clause is being executed because of an exception, we don't
 really need this wart, do we?

 The problem is that sys.exc_info() almost always returns *something*
 -- it's usually the last exception that was *ever* caught, except in
 certain circumstances.

Yeah, OK.  I'll stop claiming to understand sys.exc_info() apart from
the simple cases.

 [Michael again]
 Compare and contrast:
 
 @template
 def redirected_stdout(out):
 save_stdout = sys.stdout
 sys.stdout = out
 
 yield None
 
 sys.stdout = save_stdout
 
 class redirected_stdout(object):
 
 def __init__(self, output):
 self.output = output
 
 def __enter__(self):
 self.save_stdout = sys.stdout
 sys.stdout = self.output
 
 def __exit__(self):
 sys.stdout = self.save_stdout
 
 The former is shorter and contains less (well, no) 'self.'s, but I
 think I find the latter somewhat clearer.

 Tastes differ. I think the generator wins; more so when there's more
 state to remember.

Certainly when there's more state to manage, yes.  But both will be
possible, so, *shrug*.  It's not a big deal.

 [Michael quoting Guido]
  The added complexity is caused by the need to separate VAR from EXPR
  so that a generator can be used. I personally like this separation; I
  actually like that the anonymous block controller is logically
  separate from the variable bound by the construct.
 
 Nevertheless, I think I actually like this argument!

 (Repeated for the benefit of others.)

I guess this means PEP 310 can be retracted.

Finally, from PEP 343 rev 1.7:

exc = ()  # Or (None, None, None) ?

The latter, please.

Cheers,
mwh

-- 
. - the pointyour article - .
|- a long way |
   -- Christophe Rhodes, ucam.chat
___
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 - Abstract Block Redux

2005-05-14 Thread Paul Moore
On 5/14/05, Fredrik Lundh [EMAIL PROTECTED] wrote:
 Nick Coghlan wrote:
 
  PEP 343 (like PEP 310 before it) makes it possible to define the correct
  resource management *once*, and then invoke it via a 'with' (or 'do')
  statement.

This is probably the main point for me - encapsulate the try...finally
dance in such a way that the two parts are not separated by an
(arbitrarily long) chunk of code. I hated the equivalent dances in C
(usually malloc/free stuff in that case) and it feels awkward that
this is the one real ugliness of C that Python hasn't fixed for me :-)

 sure, but even if you look at both the application code *and*
 the resource management, there are no clues that the with
 statement is really just a masked try/finally statement.  just
 look at the generator example:
 
 acquire
 yield
 release
 
 what in this snippet tells you that the release part will run even if
 the external block raises an exception?

I agree with this point, though. What I liked about the original PEP
340 was the fact that the generator was a template, with yield
acting as a put the block here placeholder.

 but I still think that something closer to the original PEP 340 is a lot
 more useful.

Overall, I'd agree. I'm still fond of the original PEP 340 in all its
glory - the looping issue was a wart, but PEP 343 seems so stripped
down as to be something entirely different, not just a fix to the
looping issue.

My view - PEP 343 get a +1 in preference to PEP 310.
I'd like to see PEP 342 - that gets a +1 from me.

Covering both these areas at once, PEP 340 would still probably be my
preference, though. (I'm not convinced there's much chance of
resurrecting it, though).

Even it its limited form, I prefer PEP 343 to the status quo, though.

Oh, and I'm leaning towards with as a keyword again, as a result of
the works better with member functions argument.

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 - Abstract Block Redux

2005-05-14 Thread Nick Coghlan
Paul Moore wrote:
 On 5/14/05, Fredrik Lundh [EMAIL PROTECTED] wrote:
 
Nick Coghlan wrote:


PEP 343 (like PEP 310 before it) makes it possible to define the correct
resource management *once*, and then invoke it via a 'with' (or 'do')
statement.
 
 
 This is probably the main point for me - encapsulate the try...finally
 dance in such a way that the two parts are not separated by an
 (arbitrarily long) chunk of code. I hated the equivalent dances in C
 (usually malloc/free stuff in that case) and it feels awkward that
 this is the one real ugliness of C that Python hasn't fixed for me :-)
 
 
sure, but even if you look at both the application code *and*
the resource management, there are no clues that the with
statement is really just a masked try/finally statement.  just
look at the generator example:

acquire
yield
release

what in this snippet tells you that the release part will run even if
the external block raises an exception?
 
 
 I agree with this point, though. What I liked about the original PEP
 340 was the fact that the generator was a template, with yield
 acting as a put the block here placeholder.

I also think the generator as statement template works much better if the 
__exit__ method is able to inject the exception into the generator frame, 
rather 
than always calling next().

Maybe PEP 343 should drop any suggestion of using generators to define these 
things, and focus on the PEP 310 style templates.

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 - Abstract Block Redux

2005-05-14 Thread Phillip J. Eby
At 01:55 PM 5/14/2005 +0200, Fredrik Lundh wrote:
also, come to think of it, adding a new statement just to hide
try/finally statements is a waste of statement space.  why not
just enhance the existing try statement?  let

 try with opening(file) as f:
 body
 except IOError:
 deal with the error (you have to do this anyway)

behave like

 try:
 f = opening(file)
 try:
 try:
 body
 except:
 exc = sys.exc_info()
 else:
 exc = None
 finally:
 f.__cleanup__(exc)
 except IOError:
 deal with the error

and you're done.  (or you could use __enter__ and __exit__ instead,
which would give you a variation of PEP-343-as-I-understand-it)

I like this, if you take out the with part, change the method names to 
__try__ and __finally__, and allow try to work as a block on its own if 
you've specified an expression.  i.e.:

 try opening(filename) as f:
 # do stuff

 try locking(self.__lock):
 # do stuff

 try redirecting_stdout(f):
 # something

 try decimal.Context(precision=23):
 # okay, this one's a little weird

 try self.__lock:
 # and so's this; nouns read better with a gerund wrapper

and I'd make the translation be:

 try:
 __exc = ()
 VAR = EXPR.__try__()
 try:
 try:
 BODY
 except:
 __exc = sys.exc_info()
 raise
 finally:
 EXPR.__finally__()

 # except/else/finally clauses here, if there were any in the original try


but I still think that something closer to the original PEP 340 is a lot
more useful.

I agree, but mainly because I'd like to be able to allow try/finally around 
yield in generators, be able to pass exceptions into generators, and tell 
generators to release their resources.  :)

I do think that the PEP 340 template concept is much more elegant than the 
various PEP 310-derived approaches, though.

___
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 - Abstract Block Redux

2005-05-14 Thread Guido van Rossum
[Fredrik Lundh]
 intuitively, I'm -1 on this proposal.

So we need to do better. Do you just prefer all of PEP 340? What about
the objections against it? The mostly unnecessary loopiness in
particular?

 unlike the original design, all you get from this is
 the ability to add try/finally blocks to your code
 without ever writing a try/finally-clause (neither
 in your code or in the block controller).  that
 doesn't strike me as especially pythonic.

Would it be better if we pulled back in the generator exit handling
from PEP 340? That's a pretty self-contained thing, and would let you
write try/finally around the yield.

 (neither does the argument that just because you
 can use a mechanism to write inscrutable code,
 such a mechanism must not be made available
 feel right; Python's design has always been about
 careful tradeoffs between policy and mechanism,
 but this is too much policy for my taste.  the
 original PEP 340 might have been too clever, but
 this reduced version feels pretty pointless).

Maybe. It still solves the majority of use cases for PEP 340, most of
which are try/finally abstractions.

Maybe I'm overreacting to Raymond Chen's rant about flow-control
macros -- but having had to maintain code once that was riddled with
these, it rang very true.

PEP 340 is still my favorite, but it seems there's too much opposition
to it, so I'm trying to explore alternatives; at the same time I
*really* dislike the complexities of some of the non-looping
counterproposals (e.g. Nick Coghlan's PEP 3XX or the proposals that
make every keyword associated with 'try' a method).

-- 
--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] Tidier Exceptions

2005-05-14 Thread Aahz
On Fri, May 13, 2005, Greg Ewing wrote:
 Brett C. wrote:
 
 Seems like, especially if we require inheritance from a base
 exception class in Python 3000, exceptions should have standard 'arg'
 and 'traceback' attributes with a possible 'context' attribute (or
 always a 'context' attribute set to None if not a chained exception).

 Instead of an 'args' attribute, I'd suggest that the constructor take
 keyword arguments and store them in corresponding attributes. Then
 interested parties could retrieve them by name instead of having to
 remember their positions in the args tuple of the exception class
 concerned.

Sounds reasonable, but it should be equally easy to handle::

raise MyError, message
-- 
Aahz ([EMAIL PROTECTED])   * http://www.pythoncraft.com/

And if that makes me an elitist...I couldn't be happier.  --JMS
___
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] Python's Unicode width default (New Py_UNICODE doc)

2005-05-14 Thread Shane Hathaway
M.-A. Lemburg wrote:
 It is important to be able to rely on a default that
 is used when no special options are given. The decision
 to use UCS2 or UCS4 is much too important to be
 left to a configure script.

Should the choice be a runtime decision?  I think it should be.  That
could mean two unicode types, a call similar to
sys.setdefaultencoding(), a new unicode extension module, or something else.

BTW, thanks for discussing these issues.  I tried to write a patch to
the unicode API documentation, but it's hard to know just what to write.
 I think I can say this: sometimes your strings are UTF-16, so you're
working with code units that are not necessarily complete code points;
sometimes your strings are UCS4, so you're working with code units that
are also complete code points.  The choice between UTF-16 and UCS4 is
made at the time the Python interpreter is compiled and the default
choice varies by operating system and configuration.

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


Re: [Python-Dev] Tidier Exceptions

2005-05-14 Thread James Y Knight
On May 14, 2005, at 2:34 PM, Aahz wrote:
 On Fri, May 13, 2005, Greg Ewing wrote:

 Sounds reasonable, but it should be equally easy to handle::

 raise MyError, message

Make that:
raise MyError(message)

There's really no reason for a multi-argument raise when exceptions  
are objects anyhow.

James
___
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 - Abstract Block Redux

2005-05-14 Thread Brett C.
Guido van Rossum wrote:
 [Fredrik Lundh]
 
intuitively, I'm -1 on this proposal.
 

Just to toss in my opinion, I prefer PEP 340 over 343 as well, but not so much
to give 343 a -1 from me.

[SNIP - question of how to handle argument against 340 being a loop which I
never totally got since you know it ahead of time so you just deal with it]

[SNIP]
 Maybe I'm overreacting to Raymond Chen's rant about flow-control
 macros -- but having had to maintain code once that was riddled with
 these, it rang very true.
 

You might be overreacting.  I read the essay and I understand his arguments
having been taught how to program in Scheme.  But I don't think this is as
serious.  People will have the semantics of the block statement explained to
them so how that works will be clear.  And at that point they just have to
track down the generator or iterator that the block statement is using.

If you think about it, how is it different than the implicit iter() call on a
'for' loop along with the implicit next() call each time through the loop?
Just because there is an implicit closing call back into the block generator at
the end of a block statement?  Doesn't seem so bad to me or that much of a
stretch from the magic of a 'for' loop to be that huge of a thing.

I think Raymond was reeling against arbitrary macro creation that hides flow
control.  We don't have that here.  What we have is a clearly defined statement
that does some very handy syntactic sugar for us.  It doesn't feel as arbitrary
as what Lisp and Scheme allow you to do.

 PEP 340 is still my favorite, but it seems there's too much opposition
 to it, so I'm trying to explore alternatives; at the same time I
 *really* dislike the complexities of some of the non-looping
 counterproposals (e.g. Nick Coghlan's PEP 3XX or the proposals that
 make every keyword associated with 'try' a method).
 

Nick's was obviously directly against looping, but, with no offense to Nick,
how many other people were against it looping?  It never felt like it was a
screaming mass with pitchforks but more of a I don't love it, but I can deal
crowd.

And as for the overly complex examples, that I believed stemmed from people
realizing what might be possible if the statement was extended and tweaked this
way or that so as to be able to do just one more thing.  But that happens with
every proposal; seemed like standard feature creep.  The reason we have a BDFL
is to tell us that yes, we could get the jumbo sized candy bar for $2 more but
there is no way you will be able to finish that much chocolate before it melts
all over your hands and get it all over your nice PyCon t-shirt.

But then again I don't know if you got private emails asking to see if PEP 340
weighed as much as wood so it could be burned at the stake for being a witch.

-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] Python's Unicode width default (New Py_UNICODE doc)

2005-05-14 Thread Bob Ippolito

On May 14, 2005, at 3:05 PM, Shane Hathaway wrote:

 M.-A. Lemburg wrote:

 It is important to be able to rely on a default that
 is used when no special options are given. The decision
 to use UCS2 or UCS4 is much too important to be
 left to a configure script.


 Should the choice be a runtime decision?  I think it should be.  That
 could mean two unicode types, a call similar to
 sys.setdefaultencoding(), a new unicode extension module, or  
 something else.

 BTW, thanks for discussing these issues.  I tried to write a patch to
 the unicode API documentation, but it's hard to know just what to  
 write.
  I think I can say this: sometimes your strings are UTF-16, so you're
 working with code units that are not necessarily complete code points;
 sometimes your strings are UCS4, so you're working with code units  
 that
 are also complete code points.  The choice between UTF-16 and UCS4 is
 made at the time the Python interpreter is compiled and the default
 choice varies by operating system and configuration.

Well, if you're going to make it runtime, you might as well do it  
right.  Take away the restriction that the unicode type backing store  
is forced to be a particular encoding (i.e. get rid of  
PyUnicode_AS_UNICODE) and give it more flexibility.

The implementation of NSString in OpenDarwin's libFoundation http:// 
libfoundation.opendarwin.org/ (BSD license), or the CFString  
implementation in Apple's CoreFoundation http://developer.apple.com/ 
darwin/cflite.html (APSL) would be an excellent place to look for  
how this can be done.

Of course, for backwards compatibility reasons, this would have to be  
a new type that descends from basestring.  text would probably be a  
good name for it.  This would be an abstract implementation, where  
you can make concrete subclasses that actually implement the various  
operations as necessary.  For example, you could have text_ucs2,  
text_ucs4, text_ascii, text_codec, etc.

The bonus here is you can get people to shut up about space efficient  
representations, because you can use whatever makes sense.

-bob

___
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 - Abstract Block Redux

2005-05-14 Thread Shane Hathaway
Guido van Rossum wrote:
 [Nick Coghlan]
 
Also, the call to __enter__() needs to be before the try/finally block (as it 
is
in PEP 310). Otherwise we get the releasing a lock you failed to acquire 
problem.
 
 
 I did that on purpose. There's a separate object ('abc' in the
 pseudo-code of the translation) whose __enter__ and __exit__ methods
 are called, and in __enter__ it can keep track of the reversible
 actions it has taken.
 
 Consider an application where you have to acquire *two* locks regularly:
 
 def lockBoth():
 got1 = got2 = False
 lock1.acquire(); got1 = True
 lock2.acquire(); got2 = True
 yield None
 if got2: lock2.release()
 if got1: lock1.release()
 
 If this gets interrupted after locking lock1 but before locking lock2,
 it still has some cleanup to do.

That code is incorrect, though.  Say lockBoth() acquires lock1 but then
lock2.acquire() throws an exception.  (Maybe the lock requires some I/O
operation, and the operation fails.)  The interpreter will never reach
the yield statement and lock1 will never be released.

You really have to write it like this:

def lockBoth():
lock1.acquire()
try:
lock2.acquire()
except:
lock1.release()
raise
yield None
try:
lock2.release()
finally:
lock1.release()

 I know that this complicates simpler use cases, and I'm not 100% sure
 this is the right solution; but I don't know how else to handle this
 use case.

If __enter__ raises an exception, it has to clean up after itself before
propagating the exception.  __exit__ shouldn't be called if __enter__ fails.

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


Re: [Python-Dev] PEP 343 - Abstract Block Redux

2005-05-14 Thread Shane Hathaway
Brett C. wrote:
 Guido van Rossum wrote:
PEP 340 is still my favorite, but it seems there's too much opposition
to it, so I'm trying to explore alternatives; at the same time I
*really* dislike the complexities of some of the non-looping
counterproposals (e.g. Nick Coghlan's PEP 3XX or the proposals that
make every keyword associated with 'try' a method).

 
 
 Nick's was obviously directly against looping, but, with no offense to Nick,
 how many other people were against it looping?  It never felt like it was a
 screaming mass with pitchforks but more of a I don't love it, but I can deal
 crowd.

PEP 340 is very nice, but it became less appealing to me when I saw what
it would do to break and continue statements.

text = 'diamond'
for fn in filenames:
opening(fn) as f:
if text in f.read():
print 'I found the text in %s' % fn
break

I think it would be pretty surprising if the break didn't stop the loop.

Here's a new suggestion for PEP 340: use one keyword to start a block
you don't want to loop, and a different keyword to start a block that
can loop.  If you specify the non-looping keyword but the block template
produces more than one result, a RuntimeError results.  Here is example
A, a non-looping block statement using try:

text = 'diamond'
for fn in filenames:
try opening(fn) as f:
if text in f.read():
print 'I found the text in %s' % fn
break

In example A, the break statement breaks the for loop.  If the
opening() iterator returns more than one result, a RuntimeError will be
generated by the Python interpreter.

Here is example B, a looping block statement using in, adapted from
PEP 340:

in auto_retry(3, IOError) as attempt:
f = urllib.urlopen(http://python.org/peps/pep-0340.html;)
print f.read()

Note that I introduced no new keywords except as, and the syntax in
both cases is currently illegal.

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


Re: [Python-Dev] PEP 343 - Abstract Block Redux

2005-05-14 Thread Nick Coghlan
Guido van Rossum wrote:
 [Nick Coghlan]
 
Also, the call to __enter__() needs to be before the try/finally block (as it 
is
in PEP 310). Otherwise we get the releasing a lock you failed to acquire 
problem.
 
 
 I did that on purpose. There's a separate object ('abc' in the
 pseudo-code of the translation) whose __enter__ and __exit__ methods
 are called, and in __enter__ it can keep track of the reversible
 actions it has taken.
 
 Consider an application where you have to acquire *two* locks regularly:
 
 def lockBoth():
 got1 = got2 = False
 lock1.acquire(); got1 = True
 lock2.acquire(); got2 = True
 yield None
 if got2: lock2.release()
 if got1: lock1.release()
 
 If this gets interrupted after locking lock1 but before locking lock2,
 it still has some cleanup to do.
 
 I know that this complicates simpler use cases, and I'm not 100% sure
 this is the right solution; but I don't know how else to handle this
 use case.
 

If we retained the ability to inject exceptions into generators, this would be 
written with the extremely natural:

   @with template:
   def lockboth():
 lock1.acquire()
 try:
 lock2.acquire()
 try:
 yield
 finally:
 lock2.release()
 finally:
 lock1.release()

Or, even more simply:

@with_template:
def lockboth():
with lock1:
with lock2:
yield

I think Fredrik's intuition is on to something - PEP 343 has scaled the idea 
back *too* far by throwing away the injection of exceptions into generator 
templates, when the only major objection was to the looping nature of the 
proposal.

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] [Python-checkins] python/nondist/peps pep-0343.txt, 1.8, 1.9

2005-05-14 Thread Raymond Hettinger
 -was, under the covers, a (optential) looping construct.  This
 +was, under the covers, a (potential) looping construct.  This

I'm glad I didn't fix this one.
I thought he meant to use optional.


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