Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-03-13 Thread Steven D'Aprano
On Thu, Mar 13, 2014 at 07:54:18AM +1100, Chris Angelico wrote:
 On Thu, Mar 13, 2014 at 7:26 AM, Martin v. Löwis mar...@v.loewis.de wrote:
  I think you (or someone) first needs to find a BDFL delegate.
  Traditionally, with syntax changes, there is a good chance that Guido
  doesn't want to delegate at all, so ask him whether he wants to delegate
  or not.
 
 He beat you to it; the PEP has now been rejected. :)

Guido said he *wanted* to reject it, and that there would be no more 
pronouncement until after the language summit. I think you should wait 
until after the summit before declaring it categorically rejected, 
perhaps somebody will persuade Guido to change his mind :-)

But either way, thanks for tackling this, the threads about syntax were 
monsterous and I ran out of steam trying to keep up with it all long 
ago.

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-03-12 Thread Brett Cannon
On Tue Mar 11 2014 at 11:59:23 PM, Chris Angelico ros...@gmail.com wrote:

 On Wed, Mar 12, 2014 at 2:20 PM, Ethan Furman et...@stoneleaf.us wrote:
  I sure hope this is accepted.  I could have used it at least a half-dozen
  times in the last week -- which is more often than I would have used the
  ternary-if!  :)

 Where do we go from here? I've not made any edits for some time - no
 material edits for a good while - how do I request pronouncement?


You start a new email thread asking for pronouncement. Don't be surprised,
though, if it is postponed until PyCon since the language summit is 4 weeks
away.
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-03-12 Thread Martin v. Löwis
Am 12.03.14 04:58, schrieb Chris Angelico:
 On Wed, Mar 12, 2014 at 2:20 PM, Ethan Furman et...@stoneleaf.us wrote:
 I sure hope this is accepted.  I could have used it at least a half-dozen
 times in the last week -- which is more often than I would have used the
 ternary-if!  :)
 
 Where do we go from here? I've not made any edits for some time - no
 material edits for a good while - how do I request pronouncement?

I think you (or someone) first needs to find a BDFL delegate.
Traditionally, with syntax changes, there is a good chance that Guido
doesn't want to delegate at all, so ask him whether he wants to delegate
or not.

You should also add a section on the implementation status; it's unclear
(to me) whether the proposed implementation actually matches the
specification.

Regards,
Martin

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-03-12 Thread Chris Angelico
On Thu, Mar 13, 2014 at 7:26 AM, Martin v. Löwis mar...@v.loewis.de wrote:
 I think you (or someone) first needs to find a BDFL delegate.
 Traditionally, with syntax changes, there is a good chance that Guido
 doesn't want to delegate at all, so ask him whether he wants to delegate
 or not.

He beat you to it; the PEP has now been rejected. :)

 You should also add a section on the implementation status; it's unclear
 (to me) whether the proposed implementation actually matches the
 specification.

Hmm. I left that sort of comment out, partly because both the proposal
and the implementation were fluid. I also had a bit of trouble making
everything work, and had to submit some more patches. So I'm not sure
what would be counted as the reference implementation.

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-03-11 Thread Ethan Furman
I sure hope this is accepted.  I could have used it at least a half-dozen times in the last week -- which is more often 
than I would have used the ternary-if!  :)


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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-03-11 Thread Chris Angelico
On Wed, Mar 12, 2014 at 2:20 PM, Ethan Furman et...@stoneleaf.us wrote:
 I sure hope this is accepted.  I could have used it at least a half-dozen
 times in the last week -- which is more often than I would have used the
 ternary-if!  :)

Where do we go from here? I've not made any edits for some time - no
material edits for a good while - how do I request pronouncement?

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-03-05 Thread Thomas Wouters
On Thu, Feb 27, 2014 at 1:29 PM, Chris Angelico ros...@gmail.com wrote:

 +Had this facility existed early in Python's history, there would have been
 +no need to create dict.get() and related methods;


FWIW, after experimenting and some consideration I've come to the
conclusion that this is incorrect. 'd[k] except KeyError: default' is still
much broader than dict.get(k):

Python 3.4.0rc1+ (default:aa2ae744e701+, Feb 24 2014, 01:22:15)
[GCC 4.6.3] on linux
Type help, copyright, credits or license for more information.
 expensive_calculation = hash
 class C:
... _hash_cache = {}
... def __init__(self, value):
... self.value = value
... if value not in self._hash_cache:
... self._hash_cache[value] = expensive_calculation(value)
... def __hash__(self):
... return self._hash_cache[self.value]
... def __eq__(self, other):
... return self.value == other
...
 a, b, c, d = C(1), C(2), C(3), C(4)
 D = {a: 1, b: 2, c: 3, d: 4}

 a.value = 5
 print(except expr:, (D[a] except KeyError: 'default'))
except expr: default
 print(dict.get:, D.get(a, 'default'))
Traceback (most recent call last):
  File stdin, line 1, in module
  File stdin, line 8, in __hash__
KeyError: 5

All in all I believe I will continue to prefer specific methods for
specific use-cases; I'm -0 on the idea of an except-expression, -0 on the
syntax with the mandatory parentheses around the whole thing (and so far -1
on any of the other suggested forms.) I can see the attractiveness, but
frankly, all the suggested changes to the stdlib fall in two categories:
easier to express (and narrower in its exception handling) with e.g.
dict.get for the trivial ones, or much better written out using temporary
variables for the complex ones. As soon as an except-expression has trouble
fitting on two lines it becomes an unsightly mess; it no longer becomes
obvious what it does from a glance. Not having except-expr may mean we keep
adding methods (with different names, and slightly different semantics) to
cover specific use-cases of specific types, but I can live with that.

-- 
Thomas Wouters tho...@python.org

Hi! I'm an email virus! Think twice before sending your email to help me
spread!
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-03-05 Thread Chris Angelico
On Thu, Mar 6, 2014 at 7:57 AM, Thomas Wouters tho...@python.org wrote:
 On Thu, Feb 27, 2014 at 1:29 PM, Chris Angelico ros...@gmail.com wrote:

 +Had this facility existed early in Python's history, there would have
 been
 +no need to create dict.get() and related methods;


 FWIW, after experimenting and some consideration I've come to the conclusion
 that this is incorrect. 'd[k] except KeyError: default' is still much
 broader than dict.get(k):

*Much* broader? You prove that it's broader, yes, but most types
aren't defining __hash__ methods that can fail with KeyError. Can you
show any real-world code that trips this?

I'd say the broadened exception scope (or, putting it the other way,
the narrowed exception scope of adding dict.get() after
except-expressions had already existed) is insufficiently significant
to justify adding an extra method to the dict. Since the method does
exist, it will continue to be useful, but if except expressions did
and dict.get() didn't, there'd have been very little justification for
them. And certainly hasattr() wouldn't need to exist, since it exactly
_does_ try to get the attribute and see if AttributeError is raised.

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-03-05 Thread Chris Angelico
On Thu, Mar 6, 2014 at 7:57 AM, Thomas Wouters tho...@python.org wrote:
 All in all I believe I will continue to prefer specific methods for specific
 use-cases; I'm -0 on the idea of an except-expression, -0 on the syntax with
 the mandatory parentheses around the whole thing (and so far -1 on any of
 the other suggested forms.) I can see the attractiveness, but frankly, all
 the suggested changes to the stdlib fall in two categories: easier to
 express (and narrower in its exception handling) with e.g. dict.get for the
 trivial ones, or much better written out using temporary variables for the
 complex ones. As soon as an except-expression has trouble fitting on two
 lines it becomes an unsightly mess; it no longer becomes obvious what it
 does from a glance. Not having except-expr may mean we keep adding methods
 (with different names, and slightly different semantics) to cover specific
 use-cases of specific types, but I can live with that.

Most of those concerns could also be aimed at the if/else expression.
There are definitely places that do not merit its use, but that
doesn't mean the feature is a bad one. The PEP has a number of
examples that fit quite happily on a single line, and it's those that
I'm advocating. We have comprehensions, genexps, etc, etc, all (or at
least most) of which can be written out in some form of long-hand, and
it's usually better to use the short-hand - it's not just laziness,
it's expressiveness.

Speaking of the PEP, if someone could apply the latest changes, I
think it's pretty much ready for pronouncement. Thanks!

Content:
https://raw.github.com/Rosuav/ExceptExpr/master/pep-0463.txt

Diff from current peps repo:

diff -r 2cf89e9e50a3 pep-0463.txt
--- a/pep-0463.txt Tue Mar 04 18:47:44 2014 -0800
+++ b/pep-0463.txt Thu Mar 06 11:12:44 2014 +1100
@@ -250,7 +250,8 @@
 alternatives listed above must (by the nature of functions) evaluate their
 default values eagerly.  The preferred form, using the colon, parallels
 try/except by using except exception_list:, and parallels lambda by having
-keyword name_list: subexpression.  Using the arrow introduces a token many
+keyword name_list: subexpression; it also can be read as mapping Exception
+to the default value, dict-style.  Using the arrow introduces a token many
 programmers will not be familiar with, and which currently has no similar
 meaning, but is otherwise quite readable.  The English word pass has a
 vaguely similar meaning (consider the common usage pass by value/reference
@@ -271,6 +272,18 @@
 Using the preferred order, subexpressions will always be evaluated from
 left to right, no matter how the syntax is nested.

+Keeping the existing notation, but shifting the mandatory parentheses, we
+have the following suggestion::
+
+value = expr except (Exception: default)
+value = expr except(Exception: default)
+
+This is reminiscent of a function call, or a dict initializer.  The colon
+cannot be confused with introducing a suite, but on the other hand, the new
+syntax guarantees lazy evaluation, which a dict does not.  The potential
+to reduce confusion is considered unjustified by the corresponding potential
+to increase it.
+

 Example usage
 =
@@ -854,6 +867,32 @@
 expression to achieve this.


+Common objections
+=
+
+Colons always introduce suites
+--
+
+While it is true that many of Python's syntactic elements use the colon to
+introduce a statement suite (if, while, with, for, etcetera), this is not
+by any means the sole use of the colon. Currently, Python syntax includes
+four cases where a colon introduces a subexpression:
+
+* dict display - { ... key:value ... }
+* slice notation - [start:stop:step]
+* function definition - parameter : annotation
+* lambda - arg list: return value
+
+This proposal simply adds a fifth:
+
+* except-expression - exception list: result
+
+Style guides and PEP 8 should recommend not having the colon at the end of
+a wrapped line, which could potentially look like the introduction of a
+suite, but instead advocate wrapping before the exception list, keeping the
+colon clearly between two expressions.
+
+
 Copyright
 =

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-03-05 Thread Thomas Wouters
On Wed, Mar 5, 2014 at 4:28 PM, Chris Angelico ros...@gmail.com wrote:

 On Thu, Mar 6, 2014 at 7:57 AM, Thomas Wouters tho...@python.org wrote:
  All in all I believe I will continue to prefer specific methods for
 specific
  use-cases; I'm -0 on the idea of an except-expression, -0 on the syntax
 with
  the mandatory parentheses around the whole thing (and so far -1 on any of
  the other suggested forms.) I can see the attractiveness, but frankly,
 all
  the suggested changes to the stdlib fall in two categories: easier to
  express (and narrower in its exception handling) with e.g. dict.get for
 the
  trivial ones, or much better written out using temporary variables for
 the
  complex ones. As soon as an except-expression has trouble fitting on two
  lines it becomes an unsightly mess; it no longer becomes obvious what it
  does from a glance. Not having except-expr may mean we keep adding
 methods
  (with different names, and slightly different semantics) to cover
 specific
  use-cases of specific types, but I can live with that.

 Most of those concerns could also be aimed at the if/else expression.


And I did :) But the if-else expression had a single thing going for it,
the thing that landed the actual feature: it prevents people from using
buggy alternatives in the quest for short code, the and-or trick. You may
remember that Guido initially rejected the if-else expression, until he
realized people were going to use something like it whether he liked it or
not. The except-expression has a different issue: people catching
exceptions too broadly. I don't believe that's as big a problem, nor is it
as subtly wrong. And the except-expression doesn't solve _all_ such issues,
just a very small subset. It's just another thing to learn when you're new,
and just another thing to consider when reviewing code.


 There are definitely places that do not merit its use, but that
 doesn't mean the feature is a bad one. The PEP has a number of
 examples that fit quite happily on a single line, and it's those that
 I'm advocating. We have comprehensions, genexps, etc, etc, all (or at
 least most) of which can be written out in some form of long-hand, and
 it's usually better to use the short-hand - it's not just laziness,
 it's expressiveness.


It's not a question of it being expressive, it's a question of it being
worth separate syntax. I don't think it's worth syntax.



 Speaking of the PEP, if someone could apply the latest changes, I
 think it's pretty much ready for pronouncement. Thanks!


PEP update pushed (changeset 59653081cdf6.)



 Content:
 https://raw.github.com/Rosuav/ExceptExpr/master/pep-0463.txt

 Diff from current peps repo:

 diff -r 2cf89e9e50a3 pep-0463.txt
 --- a/pep-0463.txt Tue Mar 04 18:47:44 2014 -0800
 +++ b/pep-0463.txt Thu Mar 06 11:12:44 2014 +1100
 @@ -250,7 +250,8 @@
  alternatives listed above must (by the nature of functions) evaluate their
  default values eagerly.  The preferred form, using the colon, parallels
  try/except by using except exception_list:, and parallels lambda by
 having
 -keyword name_list: subexpression.  Using the arrow introduces a token
 many
 +keyword name_list: subexpression; it also can be read as mapping
 Exception
 +to the default value, dict-style.  Using the arrow introduces a token many
  programmers will not be familiar with, and which currently has no similar
  meaning, but is otherwise quite readable.  The English word pass has a
  vaguely similar meaning (consider the common usage pass by
 value/reference
 @@ -271,6 +272,18 @@
  Using the preferred order, subexpressions will always be evaluated from
  left to right, no matter how the syntax is nested.

 +Keeping the existing notation, but shifting the mandatory parentheses, we
 +have the following suggestion::
 +
 +value = expr except (Exception: default)
 +value = expr except(Exception: default)
 +
 +This is reminiscent of a function call, or a dict initializer.  The colon
 +cannot be confused with introducing a suite, but on the other hand, the
 new
 +syntax guarantees lazy evaluation, which a dict does not.  The potential
 +to reduce confusion is considered unjustified by the corresponding
 potential
 +to increase it.
 +

  Example usage
  =
 @@ -854,6 +867,32 @@
  expression to achieve this.


 +Common objections
 +=
 +
 +Colons always introduce suites
 +--
 +
 +While it is true that many of Python's syntactic elements use the colon to
 +introduce a statement suite (if, while, with, for, etcetera), this is not
 +by any means the sole use of the colon. Currently, Python syntax includes
 +four cases where a colon introduces a subexpression:
 +
 +* dict display - { ... key:value ... }
 +* slice notation - [start:stop:step]
 +* function definition - parameter : annotation
 +* lambda - arg list: return value
 +
 +This proposal simply adds a fifth:
 +
 +* except-expression - exception list: result
 +
 +Style guides and PEP 8 should 

Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-03-05 Thread Chris Angelico
On Thu, Mar 6, 2014 at 12:03 PM, Thomas Wouters tho...@python.org wrote:
 PEP update pushed (changeset 59653081cdf6.)


Thanks for that!

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-03-05 Thread Steven D'Aprano
On Wed, Mar 05, 2014 at 12:57:03PM -0800, Thomas Wouters wrote:
 On Thu, Feb 27, 2014 at 1:29 PM, Chris Angelico ros...@gmail.com wrote:
 
  +Had this facility existed early in Python's history, there would have been
  +no need to create dict.get() and related methods;
 
 
 FWIW, after experimenting and some consideration I've come to the
 conclusion that this is incorrect. 'd[k] except KeyError: default' is still
 much broader than dict.get(k):

I don't think your example proves what you think it does. I think it 
demonstrates a bug in the dict.get method. The documentation for get 
states clearly that get will never raise KeyError:

Return the value for key if key is in the dictionary, else default.
If default is not given, it defaults to None, so that this method 
never raises a KeyError.

http://docs.python.org/3/library/stdtypes.html#dict.get


but your example demonstrates that in fact it can raise KeyError 
(albeit under some rather unusual circumstances):


 Python 3.4.0rc1+ (default:aa2ae744e701+, Feb 24 2014, 01:22:15)
 [GCC 4.6.3] on linux
 Type help, copyright, credits or license for more information.
  expensive_calculation = hash
  class C:
 ... _hash_cache = {}
 ... def __init__(self, value):
 ... self.value = value
 ... if value not in self._hash_cache:
 ... self._hash_cache[value] = expensive_calculation(value)
 ... def __hash__(self):
 ... return self._hash_cache[self.value]
 ... def __eq__(self, other):
 ... return self.value == other
 ...
  a, b, c, d = C(1), C(2), C(3), C(4)
  D = {a: 1, b: 2, c: 3, d: 4}
  a.value = 5

  print(except expr:, (D[a] except KeyError: 'default'))
 except expr: default

  print(dict.get:, D.get(a, 'default'))
 Traceback (most recent call last):
   File stdin, line 1, in module
   File stdin, line 8, in __hash__
 KeyError: 5

According to the documentation, this behaviour is wrong.

Now, you might argue that the documentation is wrong. I'm sympathetic to 
that argument, but *as documented now*, dict.get is documented as being 
logically equivalent to:

try:
return d[key]
except KeyError:
return default


The fact that it actually isn't is an artifact of the specific 
implementation used. If it were a deliberate design choice, that design 
is not reflected in the documentation.

Whether the current behaviour is wrong, or the documentation is wrong, 
is irrelevant to the question of whether or not the developers back in 
nineteen-ninety-whatever would have choosen to add dict.get had there 
been syntax for catching the KeyError in an expression. Perhaps they 
would have argued:

Sure, you can catch the KeyError yourself, but 'get' is a fundamental 
operation for mappings, and I think that dict should implement a 'get' 
method just to be complete.

Or perhaps not. Some developers prefer minimalist APIs, some developers 
prefer more exhaustive APIs.

Regardless of what might have happened back in 199x when dict.get was 
first discussed, I think we can agree that an except expression will 
lower the pressure on Python to add *more* get-like methods, or add 
default arguments, in the future.



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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-03-05 Thread Terry Reedy

On 3/5/2014 8:15 PM, Steven D'Aprano wrote:

On Wed, Mar 05, 2014 at 12:57:03PM -0800, Thomas Wouters wrote:

On Thu, Feb 27, 2014 at 1:29 PM, Chris Angelico ros...@gmail.com wrote:


+Had this facility existed early in Python's history, there would have been
+no need to create dict.get() and related methods;



FWIW, after experimenting and some consideration I've come to the
conclusion that this is incorrect. 'd[k] except KeyError: default' is still
much broader than dict.get(k):


I don't think your example proves what you think it does. I think it
demonstrates a bug in the dict.get method. The documentation for get
states clearly that get will never raise KeyError:

 Return the value for key if key is in the dictionary, else default.
 If default is not given, it defaults to None, so that this method
 never raises a KeyError.

http://docs.python.org/3/library/stdtypes.html#dict.get


but your example demonstrates that in fact it can raise KeyError
(albeit under some rather unusual circumstances):



Python 3.4.0rc1+ (default:aa2ae744e701+, Feb 24 2014, 01:22:15)
[GCC 4.6.3] on linux
Type help, copyright, credits or license for more information.

expensive_calculation = hash
class C:

... _hash_cache = {}
... def __init__(self, value):
... self.value = value
... if value not in self._hash_cache:
... self._hash_cache[value] = expensive_calculation(value)
... def __hash__(self):
... return self._hash_cache[self.value]


This is a buggy special method. According to the docs for hash and 
__hash__ and the general convention on exceptions, a __hash__ method 
should return an int or raise TypeError.



... def __eq__(self, other):
... return self.value == other
...

a, b, c, d = C(1), C(2), C(3), C(4)
D = {a: 1, b: 2, c: 3, d: 4}
a.value = 5


This breaks the implied C invariant and makes the object 'a' incoherent 
and buggy



print(dict.get:, D.get(a, 'default'))

Traceback (most recent call last):
   File stdin, line 1, in module
   File stdin, line 8, in __hash__
KeyError: 5



According to the documentation, this behaviour is wrong.


One could argue that an error raised in a special method is not raised 
*by* a function that uses the special method. The docs constantly assume 
that special methods are coded correctly.


'''bool([x])
Convert a value to a Boolean, using the standard truth testing 
procedure. If x is false or omitted, this returns False; otherwise it 
returns True.'''


... unless x.__bool__ raises or returns something other than True/False 
-- in which case bool itself raises.

TypeError: __bool__ should return bool, returned int


Now, you might argue that the documentation is wrong. I'm sympathetic to
that argument, but *as documented now*, dict.get is documented as being
logically equivalent to:

try:
 return d[key]
except KeyError:
 return default


It appears to be actually equivalent to

key_hash = hash(key)
try:
return d._hashlookup(key_has)
except KeyError:
return default


The fact that it actually isn't is an artifact of the specific
implementation used. If it were a deliberate design choice,


Given that the choice is that bugs in special methods should not pass 
silently, I would presume that it is intentional.


  that design is not reflected in the documentation.

The docs generally describe behavior in the absence of coding errors.

--
Terry Jan Reedy

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-03-05 Thread Greg Ewing

Steven D'Aprano wrote:

Return the value for key if key is in the dictionary, else default.
If default is not given, it defaults to None, so that this method 
never raises a KeyError.


I think that's supposed to mean that it won't raise
KeyError as a result of the key not being in the
dictionary. The actual behaviour is correct, IMO,
because it avoids masking bugs, so this could probably
be worded better.

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-28 Thread Chris Angelico
On Fri, Feb 28, 2014 at 6:38 PM, Glenn Linderman v+pyt...@g.nevcal.com wrote:
 Whereas the current PEP syntax has ambiguity regarding how to interpret
 a-expr except except-list-b: b-expr except except-list-c: c-expr (does the
 2nd except apply to a-expr or b-expr?), without parentheses, and, as far as
 I am concerned, even with the parentheses, this syntax makes it very clear
 that each of the Exception-lists apply to a-expr.

Fair enough. It's a bit hard to talk about multiple except
expressions, though, as they're a problem unless formally supported -
and they're almost never needed. Really, all you need to do is say
never abut except-expressions without parentheses (which the current
proposal and the parens around the exception bit only proposal both
enforce), and then there's no problem. I expect that normal use of
this won't include any form of chaining. Yes, it can - like any
feature - be used abnormally, but at some point it's better to just
drop it out as a statement.

 Key advantage to others may be that because the : is within the () [and the
 leading ( is quite nearby, making it obvious], it is less likely to be
 considered a statement boundary, and more easily explained as a special type
 of list syntax... not _really_ a list, because it is really code to be
 executed somewhat sequentially rather than data, and lists don't have : ...
 and not _really_ a dict constant, which does have :, because the Exception
 is not _really_ a key, but the syntax can draw on analogies with the dict
 constant syntax which will help people remember it, and even sort of
 understand that there is a pair-wise relationship between the Exception-list
 and the expression after the :, without repeating the except over and over.

See the confusing terminology we have here? It might be called a
list of except-expressions, but the brackets are round, and a list's
are square. It's kinda like dict syntax, only again, the other sort of
bracket, and it's wrong to try to construct a dict; it'd be too
tempting to conflate this with some of the other current proposals for
lazily-evaluated expressions (aka simpler syntax for lambda or other
terms). This is, fundamentally, a multi-part expression on par with
and and or: first, evaluate the primary expression; then, if an
exception is raised, evaluate the exception list and see if it
matches; then, if it matches, squash the exception and evaluate the
default expression. You can't turn that into a dict, partly because
you'd need to sort out lazy evaluation, and partly because a dict is
unordered - if this is expanded to support multiple except clauses,
they have to be processed in order. (You might, for instance, catch
ZeroDivisionError, and then Exception, with different handling. It'd
be VERY confusing for them to be processed in the wrong order,
particularly if it happens unpredictably.)

Are there any other expressions that allow parens around a part of the
expression, without the stuff inside them becoming a completely
separate sub-expression?

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-28 Thread Glenn Linderman

On 2/28/2014 12:41 AM, Chris Angelico wrote:

On Fri, Feb 28, 2014 at 6:38 PM, Glenn Linderman v+pyt...@g.nevcal.com wrote:

Whereas the current PEP syntax has ambiguity regarding how to interpret
a-expr except except-list-b: b-expr except except-list-c: c-expr (does the
2nd except apply to a-expr or b-expr?), without parentheses, and, as far as
I am concerned, even with the parentheses, this syntax makes it very clear
that each of the Exception-lists apply to a-expr.

Fair enough. It's a bit hard to talk about multiple except
expressions, though, as they're a problem unless formally supported -
and they're almost never needed. Really, all you need to do is say
never abut except-expressions without parentheses (which the current
proposal and the parens around the exception bit only proposal both
enforce), and then there's no problem. I expect that normal use of
this won't include any form of chaining. Yes, it can - like any
feature - be used abnormally, but at some point it's better to just
drop it out as a statement.


Key advantage to others may be that because the : is within the () [and the
leading ( is quite nearby, making it obvious], it is less likely to be
considered a statement boundary, and more easily explained as a special type
of list syntax... not _really_ a list, because it is really code to be
executed somewhat sequentially rather than data, and lists don't have : ...
and not _really_ a dict constant, which does have :, because the Exception
is not _really_ a key, but the syntax can draw on analogies with the dict
constant syntax which will help people remember it, and even sort of
understand that there is a pair-wise relationship between the Exception-list
and the expression after the :, without repeating the except over and over.

See the confusing terminology we have here? It might be called a
list of except-expressions, but the brackets are round, and a list's
are square. It's kinda like dict syntax, only again, the other sort of
bracket, and it's wrong to try to construct a dict; it'd be too
tempting to conflate this with some of the other current proposals for
lazily-evaluated expressions (aka simpler syntax for lambda or other
terms). This is, fundamentally, a multi-part expression on par with
and and or: first, evaluate the primary expression; then, if an
exception is raised, evaluate the exception list and see if it
matches; then, if it matches, squash the exception and evaluate the
default expression. You can't turn that into a dict, partly because
you'd need to sort out lazy evaluation, and partly because a dict is
unordered - if this is expanded to support multiple except clauses,
they have to be processed in order. (You might, for instance, catch
ZeroDivisionError, and then Exception, with different handling. It'd
be VERY confusing for them to be processed in the wrong order,
particularly if it happens unpredictably.)


That's why I kept saying not _really_ :)  It isn't a list, but it has 
an order requirement; it isn't a dict, but it has pairs; and finally, it 
isn't data, but code.  But nonetheless the analogies are somewhat useful.



Are there any other expressions that allow parens around a part of the
expression, without the stuff inside them becoming a completely
separate sub-expression?


Sure. Function invocation.  You can claim (and it is accurate) that the 
stuff inside is somewhat independent of the actual function called, but 
the syntax is  function-name open-paren parameter-list close-paren, and 
the stuff in the parens would be a tuple if it were purely data, except 
not quite a tuple because some items are pairs (name and value), but it 
winds up being neither a tuple, nor a list, nor a dict, but instead a 
complex structure related to code execution :)  Actually, this sounds 
quite similar to


value = expr except (
Exception1: default1,
Exception2: default2,
Exception3: default3,
   )

except that to get the pairing aspect of some parameters for a function call, 
you use = instead of :, and instead of a named function it has an expression 
and a keyword.

Not being an expert parser generator, I don't know if the () could be 
made optional if there is only one exception-list, but that would also 
remove one of the benefits some folks might perceive with using this 
syntax, and would also make the analogy with function call syntax a 
little less comparable.


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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-28 Thread Thomas Wouters
On Fri, Feb 28, 2014 at 1:30 AM, Glenn Linderman v+pyt...@g.nevcal.comwrote:


 value = expr except (
 Exception1: default1,
 Exception2: default2,
 Exception3: default3,
)

 except that to get the pairing aspect of some parameters for a function call, 
 you use = instead of :, and instead of a named function it has an expression 
 and a keyword.

 [ Cue people suggesting the use of '=' or '=' or '-' instead of ':' ]


 Not being an expert parser generator, I don't know if the () could
 be made optional if there is only one exception-list, but that would
 also remove one of the benefits some folks might perceive with using
 this syntax, and would also make the analogy with function call
 syntax a little less comparable.

 I believe it's possible, but it's probably tricky: the parser has to
consider two or three cases:

1.  expr1 except expr2: expr4
2.  expr1 except (expr2: expr4)
3.  expr1 except (expr2, expr3): expr4
4.  expr1 except ((expr2, expr3): expr4)

(for simplicity I use 'expr' here, which is entirely the wrong thing to do
in terms of CPython's grammar: there's different types of expressions for
different situations. #2 and #4 are actually automatically derived from #1
and #3 by 'expr' including tuples and parenthesized expressions.) CPython's
parser is a LL(1) parser, which means it can look ahead 1 character to
choose between alternatives (and that's not going to change, Guido likes it
this way -- and so I do, personally :). Looking at #2 and #3 you can't tell
which alternative to use until you see the ':' or ',' after 'expr2', which
is too late. The only way to handle that, I think, is to include all
possible alternatives in the grammar for the 'except' statement,
duplicating logic and definitions from a lot of places. We already do this
kind of thing to deal with other potentially-ambiguous situations (to
handle dicts and sets and dict comprehensions and set comprehensions, for
example) but this would be even more duplication.

It would be easier if we weren't talking about '(' or any other token that
can be part of a normal expression ;-P

[ Cue people suggesting the use of 'expr1 except  expr2: expr4 '... ]

-- 
Thomas Wouters tho...@python.org

Hi! I'm an email virus! Think twice before sending your email to help me
spread!
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-28 Thread Chris Angelico
On Fri, Feb 28, 2014 at 8:30 PM, Glenn Linderman v+pyt...@g.nevcal.com wrote:
  Are there any other expressions that allow parens around a part of the
  expression, without the stuff inside them becoming a completely
  separate sub-expression?


 Sure. Function invocation.  You can claim (and it is accurate) that the
 stuff inside is somewhat independent of the actual function called, but the
 syntax is  function-name open-paren parameter-list close-paren, and the
 stuff in the parens would be a tuple if it were purely data, except not
 quite a tuple because some items are pairs (name and value), but it winds up
 being neither a tuple, nor a list, nor a dict, but instead a complex
 structure related to code execution :)

Thanks, that's exactly the sort of example I was looking for :) For
some reason I mentally blanked and didn't think of that. My point is,
if you're going to look for parens around the bit after except, we
should look at styling and layout that follows how that's done.

As TW says:
 [ Cue people suggesting the use of '=' or '=' or '-' instead of ':' ]

If this is to be laid out like a function call, '=' would indeed make
sense. But let's stick to the colon for now, so this is a mix of
dict-style and function-call-style.

expr except(Exception: default)

In a more function-call-style layout, that would be:

expr except(Exception=default)

Both of those look reasonable, and they're tying the parens to the
word except so it can't *actually* be a function call. Then it looks
like it should be laid out like this:

except(expr, Exception=default)

and it really *is* looking like a function call - and now it's hit the
uncanny valley [1], where it's close enough to be a problem (eg
because of lazy evaluation, or because Exception could be
(AttributeError, KeyError), which can't be a keyword argument). I
don't like this last form; does anyone else support it?

Removing the space after the word except makes me a lot less averse
to this form. Funny how stylistic choices can influence a structural
one! Here are a few more examples. How do other people feel about
them?

cond = args[1] except(IndexError: None)

pwd = os.getcwd() except(OSError: None)

e.widget = self._nametowidget(W) except(KeyError=W)

line = readline() except(StopIteration='')

_CONFIG_VARS['abiflags'] = sys.abiflags except(AttributeError: '')

def getNamedItem(self, name):
return self._attrs[name] except(KeyError: None)

g = grp.getgrnam(tarinfo.gname)[2] except(KeyError=tarinfo.gid)
u = pwd.getpwnam(tarinfo.uname)[2] except(KeyError=tarinfo.uid)

mode = f.mode except(AttributeError: 'rb')

return sys._getframe(1) except(AttributeError=None)

ips.append(ip.ip except(AttributeError: ip.network_address))

dirlist.append(_os.getcwd() except((AttributeError, OSError)=_os.curdir))

The last one is really critical here, I think. It's the only stdlib
example I could find that catches two different errors (IIRC). Here it
is with the colon:

dirlist.append(_os.getcwd() except((AttributeError, OSError): _os.curdir))

Thoughts?

ChrisA

[1] http://tvtropes.org/pmwiki/pmwiki.php/Main/UncannyValley
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-28 Thread Nick Coghlan
On 28 February 2014 21:46, Chris Angelico ros...@gmail.com wrote:
 On Fri, Feb 28, 2014 at 8:30 PM, Glenn Linderman v+pyt...@g.nevcal.com 
 wrote:
  Are there any other expressions that allow parens around a part of the
  expression, without the stuff inside them becoming a completely
  separate sub-expression?

 Sure. Function invocation.  You can claim (and it is accurate) that the
 stuff inside is somewhat independent of the actual function called, but the
 syntax is  function-name open-paren parameter-list close-paren, and the
 stuff in the parens would be a tuple if it were purely data, except not
 quite a tuple because some items are pairs (name and value), but it winds up
 being neither a tuple, nor a list, nor a dict, but instead a complex
 structure related to code execution :)

 Thanks, that's exactly the sort of example I was looking for :) For
 some reason I mentally blanked and didn't think of that. My point is,
 if you're going to look for parens around the bit after except, we
 should look at styling and layout that follows how that's done.

Also generator expressions and most uses of yield or yield from as
embedded expressions. Parentheses are our general this next bit may
not be following the normal syntax rules utility, in addition to
being used to override the normal precedence rules (square brackets
and curly braces similarly denote regions where the parsing rules may
differ from the top level ones).

As far as the specific problem I'm attacking with this variant of the
proposal goes, one of the recurring reactions from different people
has been but colons are used to introduce suites, not expressions.
This impression is not, in fact, correct, as the colon is already used
as a subexpression separator in four cases:

* dict display key:value pairs
* slice notation start:stop:step triples
* function parameter : annotation separation
* lambda expression arg list : return value separation

PEP 463 just adds a fifth such case, as an exception spec:result separator.

The preferred notation in the PEP most resembles the existing lambda
use case, with except instead of lambda, an exception handling
spec instead of an argument list and an additional leading expression:

(expr except Exception: default)

Lots of people don't like the lambda notation though, so it isn't
necessarily a particularly compelling parallel to use. By contrast,
it's rare to hear any objections to the {key:value} dict display
syntax. Hence the proposed tweak to the syntax to define an exception
handler expression syntax that is analogous to a dict display rather
than a lambda expression:

expr except (Exception: default)

However, I have realised that there *is* a major downside to that
notation, which is that it lacks the connotations of lazy evaluation
associated with lambda expressions, whereas the default result of an
except expression won't be evaluated at all if the exception isn't
thrown.

So I think that on balance, I actually do prefer your current
proposal. That said, I do think this is a variant worth discussing
explicitly in the PEP, if only to remind people that there's
definitely precedent for using a colon to separate two subexpressions
inside a larger expression element - it's not *just* used to introduce
suites, even though that is by far the most *common* use case.

Cheers,
Nick.


-- 
Nick Coghlan   |   ncogh...@gmail.com   |   Brisbane, Australia
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-28 Thread Chris Angelico
On Fri, Feb 28, 2014 at 11:51 PM, Nick Coghlan ncogh...@gmail.com wrote:
 So I think that on balance, I actually do prefer your current
 proposal. That said, I do think this is a variant worth discussing
 explicitly in the PEP, if only to remind people that there's
 definitely precedent for using a colon to separate two subexpressions
 inside a larger expression element - it's not *just* used to introduce
 suites, even though that is by far the most *common* use case.

I've added a bit more to the PEP about that.

https://github.com/Rosuav/ExceptExpr/commit/f32387

Does that explain it, do you think?

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-28 Thread Nick Coghlan
On 28 February 2014 23:07, Chris Angelico ros...@gmail.com wrote:
 On Fri, Feb 28, 2014 at 11:51 PM, Nick Coghlan ncogh...@gmail.com wrote:
 So I think that on balance, I actually do prefer your current
 proposal. That said, I do think this is a variant worth discussing
 explicitly in the PEP, if only to remind people that there's
 definitely precedent for using a colon to separate two subexpressions
 inside a larger expression element - it's not *just* used to introduce
 suites, even though that is by far the most *common* use case.

 I've added a bit more to the PEP about that.

 https://github.com/Rosuav/ExceptExpr/commit/f32387

 Does that explain it, do you think?

Yeah, that works. You may also want to add a common objections
section to explicitly cover the but colons introduce suites
objection. That would provide a space to explicitly list all of the
current not introducing a suite use cases for the colon in Python's
syntax, since increasing that tally from four to five is less radical
than introducing the first non-suite related use case for the symbol.

Cheers,
Nick.

-- 
Nick Coghlan   |   ncogh...@gmail.com   |   Brisbane, Australia
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-28 Thread Chris Angelico
On Fri, Feb 28, 2014 at 11:51 PM, Nick Coghlan ncogh...@gmail.com wrote:
  Are there any other expressions that allow parens around a part of the
  expression, without the stuff inside them becoming a completely
  separate sub-expression?

 Also generator expressions and most uses of yield or yield from as
 embedded expressions. Parentheses are our general this next bit may
 not be following the normal syntax rules utility, in addition to
 being used to override the normal precedence rules (square brackets
 and curly braces similarly denote regions where the parsing rules may
 differ from the top level ones).

In those cases, the stuff inside the parens is the entire syntactic
structure of that sub-element, right? I was looking for something
where there's syntax inside and syntax outside the parens, where
what's in the parens isn't just an expression or tuple, so I could try
laying out an except expression to imitate that style. The function
call is excellent; removing one space from the layout did make the
expression look better, but as explained above, I still prefer the
current form. Would like to make the parens optional; maybe make them
mandatory if there are two except-expressions abutting, or something,
but I'd like to simplify the syntax for the common case. Otherwise,
current syntax is still my personal preferred.

Of course, we still have to convince Guido that this is a good idea at
all, syntax or no :)

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-28 Thread Chris Angelico
On Sat, Mar 1, 2014 at 12:24 AM, Nick Coghlan ncogh...@gmail.com wrote:
 Yeah, that works. You may also want to add a common objections
 section to explicitly cover the but colons introduce suites
 objection. That would provide a space to explicitly list all of the
 current not introducing a suite use cases for the colon in Python's
 syntax, since increasing that tally from four to five is less radical
 than introducing the first non-suite related use case for the symbol.

https://github.com/Rosuav/ExceptExpr/commit/b770f9

Any other objections that should be listed?

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-28 Thread Glenn Linderman

On 2/28/2014 4:51 AM, Nick Coghlan wrote:

The preferred notation in the PEP most resembles the existing lambda
use case, with except instead of lambda, an exception handling
spec instead of an argument list and an additional leading expression:

 (expr except Exception: default)

Lots of people don't like the lambda notation though, so it isn't
necessarily a particularly compelling parallel to use.


Thank you for explaining why I find the above notation awkward.  : as 
introducing a suite never bothered me, because, as you've now 
enumerated, there are other uses of :.


But the lambda syntax parallel is what I don't like about it... I find 
the lambda syntax hard to read.



By contrast,
it's rare to hear any objections to the {key:value} dict display
syntax. Hence the proposed tweak to the syntax to define an exception
handler expression syntax that is analogous to a dict display rather
than a lambda expression:

 expr except (Exception: default)

However, I have realised that there*is*  a major downside to that
notation, which is that it lacks the connotations of lazy evaluation
associated with lambda expressions, whereas the default result of an
except expression won't be evaluated at all if the exception isn't
thrown.
You are overlooking that the keyword except provides exactly the 
connotation of lazy evaluation, so if this is your only reason for 
preferring the lambda syntax, you just erased it :)
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-28 Thread Chris Angelico
On Sat, Mar 1, 2014 at 12:24 PM, Glenn Linderman v+pyt...@g.nevcal.com wrote:
 You are overlooking that the keyword except provides exactly the connotation
 of lazy evaluation, so if this is your only reason for preferring the lambda
 syntax, you just erased it :)

Statements are always executed sequentially. That's not lazy
evaluation, that's just the way statements are :)

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-27 Thread Ronald Oussoren

On 21 Feb 2014, at 16:52, Chris Angelico ros...@gmail.com wrote:

 On Sat, Feb 22, 2014 at 1:34 AM, Brett Cannon br...@python.org wrote:
 While I like the general concept, I agree that it looks too much like a
 crunched statement; the use of the colon is a non-starter for me. I'm sure
 I'm not the only one whose brain has been trained to view a colon in Python
 to mean statement, period. This goes against that syntactic practice and
 just doesn't work for me.
 
 I'm -1 with the current syntax, but it can go into the + range if a better
 syntax can be chosen.
 
 We bikeshedded that extensively on -ideas. The four best options are:
 
 value = (expr except Exception: default)
 value = (expr except Exception - default)
 value = (expr except Exception pass default)
 value = (expr except Exception then default)
 
 Note that the last option involves the creation of a new keyword.
 
 Would any of the others feel better to you?

What about (also mentioned in the PEP)?

  value = (expr except Exception try default)

This seems to read nicely, although “try” is at a completely different position 
than it is in the equivalent try statement. 

I like the general idea, but like Brett I don’t like using a colon here at all.

Ronald

P.S. Sorry if this way already brought up, I’ve browsed through most of the 
threads on this on -ideas and -dev, but haven’t read all messages.
 
 ChrisA
 ___
 Python-Dev mailing list
 Python-Dev@python.org
 https://mail.python.org/mailman/listinfo/python-dev
 Unsubscribe: 
 https://mail.python.org/mailman/options/python-dev/ronaldoussoren%40mac.com

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-27 Thread Chris Angelico
On Thu, Feb 27, 2014 at 7:44 PM, Ronald Oussoren ronaldousso...@mac.com wrote:
 What about (also mentioned in the PEP)?

   value = (expr except Exception try default)

 This seems to read nicely, although “try” is at a completely different 
 position than it is in the equivalent try statement.

 I like the general idea, but like Brett I don’t like using a colon here at 
 all.

I see your although clause to be quite a strong objection. In the
statement form of an if, you have:

if cond: true_suite
else: false_suite

In the expression form, you have:

true_expr if cond else false_expr

Personally, I think it's a weakness of the if-expression that they're
not in the same order (cond, true_expr, false_expr), but they're still
introduced with the same keywords. The 'if' keyword is followed by the
condition, and the 'else' keyword by the false stuff.

Putting try followed by the default is confusing, because any
exception raised in the default-expr will bubble up. Stealing any
other keyword from the try/except block would make just as little
sense:

expr except Exception finally default # finally implies something
that always happens
expr except Exception else default # else implies *no* exception
expr except Exception try default # try indicates the initial expr,
not the default
default except Exception try expr # breaks L-R evaluation order

Left to right evaluation order is extremely important to me. I don't
know about anyone else, but since I'm the one championing the PEP,
you're going to have to show me a *really* strong incentive to reword
it to advocate something like the last one :) This is stated in the
PEP:

http://www.python.org/dev/peps/pep-0463/#alternative-proposals

Using try and except leaves the notation mentally ambiguous as to
which of the two outer expressions is which. It doesn't make perfect
sense either way, and I expect a lot of people would be flicking back
to the docs constantly to make sure they had it right. It's hard when
there's confusion across languages (try writing some code in REXX and
Python that uses division and modulo operators - 1234/10 - 123.4 in
Py3 and REXX, but 1234//10 and 1234%10 have opposite meaning); it's
unnecessarily hard to have the same confusion in different places in
the same language.

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-27 Thread Ronald Oussoren

On 27 Feb 2014, at 11:09, Chris Angelico ros...@gmail.com wrote:

 On Thu, Feb 27, 2014 at 7:44 PM, Ronald Oussoren ronaldousso...@mac.com 
 wrote:
 What about (also mentioned in the PEP)?
 
  value = (expr except Exception try default)
 
 This seems to read nicely, although “try” is at a completely different 
 position than it is in the equivalent try statement.
 
 I like the general idea, but like Brett I don’t like using a colon here at 
 all.
 
 I see your although clause to be quite a strong objection. In the
 statement form of an if, you have:

I’m not convinced that this is a strong objection. The order of keywords is 
different, but that doesn’t have to be problem.

 
 if cond: true_suite
 else: false_suite
 
 In the expression form, you have:
 
 true_expr if cond else false_expr

[…]

 
 
 Putting try followed by the default is confusing, because any
 exception raised in the default-expr will bubble up. Stealing any
 other keyword from the try/except block would make just as little
 sense:
 
 expr except Exception finally default # finally implies something
 that always happens
 expr except Exception else default # else implies *no* exception
 expr except Exception try default # try indicates the initial expr,
 not the default

I didn’t parse the expression this way at all, but quite naturally parsed is as 
“use expr, and try using default if expr raises Exception” and not as a RTL 
expression.  

 default except Exception try expr # breaks L-R evaluation order
 
 Left to right evaluation order is extremely important to me.

I agree with that, RTL evaluation would be pretty odd in Python.


 I don't
 know about anyone else, but since I'm the one championing the PEP,
 you're going to have to show me a *really* strong incentive to reword
 it to advocate something like the last one :) This is stated in the
 PEP:
 
 http://www.python.org/dev/peps/pep-0463/#alternative-proposals
 
 Using try and except leaves the notation mentally ambiguous as to
 which of the two outer expressions is which. It doesn't make perfect
 sense either way, and I expect a lot of people would be flicking back
 to the docs constantly to make sure they had it right.

Really? The evaluation order you mention in above didn’t make sense to me until 
I tried to make sense of it.

Ronald

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-27 Thread Chris Angelico
On Thu, Feb 27, 2014 at 9:44 PM, Ronald Oussoren ronaldousso...@mac.com wrote:
 expr except Exception try default # try indicates the initial expr,
 not the default

 I didn’t parse the expression this way at all, but quite naturally parsed is 
 as “use expr, and try using default if expr raises Exception” and not as a 
 RTL expression.

Thing is, in the statement form, try doing this means do this, and
you might get an exception, so deal with it. In the 'try default'
form, try this means oops, you got an exception, so try this
instead. It's using try in the opposite way.

 default except Exception try expr # breaks L-R evaluation order

 Left to right evaluation order is extremely important to me.

 I agree with that, RTL evaluation would be pretty odd in Python.

 Really? The evaluation order you mention in above didn’t make sense to me 
 until I tried to make sense of it.

The default except Exception try expr notation has try followed by
the thing that might raise an exception, which mimics the statement.
The expr except Exception try default notation evaluates from left
to right. Both make some sense, and I'd say it's on balance which is
the more likely to be expected. Imagine an overall expression where
it's ambiguous:

value = (d[foo] except KeyError try d[spam])

Which one do you expect to be tried first? I'd say you could poll a
bunch of moderately-experienced Python programmers and get both
answers in reasonable numbers.

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-27 Thread Nick Coghlan
On 27 February 2014 20:44, Ronald Oussoren ronaldousso...@mac.com wrote:

 On 27 Feb 2014, at 11:09, Chris Angelico ros...@gmail.com wrote:

 On Thu, Feb 27, 2014 at 7:44 PM, Ronald Oussoren ronaldousso...@mac.com 
 wrote:
 What about (also mentioned in the PEP)?

  value = (expr except Exception try default)

 This seems to read nicely, although try is at a completely different 
 position than it is in the equivalent try statement.

 I like the general idea, but like Brett I don't like using a colon here at 
 all.

 I see your although clause to be quite a strong objection. In the
 statement form of an if, you have:

 I'm not convinced that this is a strong objection. The order of keywords is 
 different, but that doesn't have to be problem.

As Chris notes, the problem is that if you use try, the two
plausible interpretations are:

1. Evaluates left-to-right, try introduces a different part of the
syntax (different from every past statement-expression conversion
where the clauses are reordered, but almost always introduced by the
same keywords as they are in the statement form)
2. Evaluates right-to-left, try introduces the expressions covered by
the exception handler (this is just backwards, and significantly
harder to follow than even the middle first conditional expression)

Neither interpretation is particularly acceptable, and the fact that
the other interpretation would remain plausible regardless is a
further strike against both of them.

Personally, I think the PEP makes a good case for particular semantics
with a spelling that isn't great, but isn't completely abhorrent
either. I definitely think it represents an improvement over the
status quo, which is an ongoing proliferation of function-based
special cases for doing particular kinds of exception handling as an
expression, and the spelling advocated for in the PEP seems like the
best of the (many) alternatives that have been proposed.

The way I get the colon in the proposed syntax to make sense to my
brain is to view it as being more like the colon in a dictionary
key:value pair than it is like the one that introduces a suite or the
body of a lambda expression:

(lst[2] except {IndexError: No value})

The analogy isn't exact (since exception handling is isinstance()
based rather than equality based), but I think it gives the right
general flavour in terms of the intended meaning of the colon in this
construct. The analogy could likely be encouraged and strengthened by
changing the parentheses requirements to make this read more like a
binary except expression with a parenthesised RHS rather than a
ternary expression:

lst[2] except (IndexError: No value)

Catching multiple errors would involve a parenthesised tuple as the key:

f() except ((TypeError, AttributeError): No value)

The deferred multiple except clauses part of the PEP could also
change to be more dict display like:

value = expr except (
Exception1: default1,
Exception2: default2,
Exception3: default3,
   )

Writing out those examples, I actually like that version (where the
parentheses are still mandatory, but the left paren is after the
except keyword rather than before the first expression) better than
the one currently in the PEP. It also avoids the weirdly unbalanced
look of the variant that had the left paren *before* the except
keyword. The main downside I see is that the exception handling
definition syntax would only be permitted in that specific location,
but still look a lot like an ordinary parenthesised expression.

Cheers,
Nick.

-- 
Nick Coghlan   |   ncogh...@gmail.com   |   Brisbane, Australia
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-27 Thread Glenn Linderman

On 2/27/2014 4:57 AM, Nick Coghlan wrote:

The way I get the colon in the proposed syntax to make sense to my
brain is to view it as being more like the colon in a dictionary
key:value pair than it is like the one that introduces a suite or the
body of a lambda expression:

 (lst[2] except {IndexError: No value})

The analogy isn't exact (since exception handling is isinstance()
based rather than equality based), but I think it gives the right
general flavour in terms of the intended meaning of the colon in this
construct. The analogy could likely be encouraged and strengthened by
changing the parentheses requirements to make this read more like a
binary except expression with a parenthesised RHS rather than a
ternary expression:

 lst[2] except (IndexError: No value)

Catching multiple errors would involve a parenthesised tuple as the key:

 f() except ((TypeError, AttributeError): No value)

The deferred multiple except clauses part of the PEP could also
change to be more dict display like:

 value = expr except (
 Exception1: default1,
 Exception2: default2,
 Exception3: default3,
)

Writing out those examples, I actually like that version (where the
parentheses are still mandatory, but the left paren is after the
except keyword rather than before the first expression) better than
the one currently in the PEP. It also avoids the weirdly unbalanced
look of the variant that had the left paren*before*  the except
keyword. The main downside I see is that the exception handling
definition syntax would only be permitted in that specific location,
but still look a lot like an ordinary parenthesised expression.

Cheers,
Nick.

+1

f() except ((TypeError, AttributeError): No value)

is a nice extension to the idea of

value = expr except (
Exception1: default1,
Exception2: default2,
Exception3: default3,
   )

Which I've liked since I first saw it, as it neatly solves handling multiple 
except clauses.

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-27 Thread Chris Angelico
On Fri, Feb 28, 2014 at 6:36 AM, Glenn Linderman v+pyt...@g.nevcal.com wrote:
 +1

 f() except ((TypeError, AttributeError): No value)

 is a nice extension to the idea of

 value = expr except (
 Exception1: default1,
 Exception2: default2,
 Exception3: default3,
)

 Which I've liked since I first saw it, as it neatly solves handling multiple
 except clauses.

You can already list multiple exception types. The definition of the
exception_list is exactly as per the try/except statement (bar the
'as' keyword, which I would love to see implemented some day).

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-27 Thread Chris Angelico
I've added another utility script to my PEP draft repo:

https://github.com/Rosuav/ExceptExpr/blob/master/replace_except_expr.py

It's built out of some pretty horrendous hacks, it makes some
assumptions about code layout (eg spaces for indentation, and a
try/except block never has anything else on the same line(s)), and the
code's a bit messy, but it does work. I ran it on the Python stdlib
and it produced a whole lot of edits (I had it keep the old version in
comments, bracketed with markers with the text PEP 463 in them,
which makes it easy to find and analyze); one file (with two try
blocks) causes a test failure, but all the rest still pass.

If people can try the script on their own codebases and see how it
looks, that'd be great. I recommend first running the script with
ast.Expr handling removed (as per the file you see above), and then
maybe running it with that one line commented out. You'll get a lot of
unhelpful change suggestions from the double-expression handler.


Could a core committer please apply the last few changes to the PEP?

https://raw.github.com/Rosuav/ExceptExpr/master/pep-0463.txt

or the diff is below. I think this is the last important change left;
things have gone fairly quiet here, and I think the PEP's about ready
to request pronouncement, unless someone knows of something I've
forgotten. (Have I said I'll write up a paragraph about that about
anything and not done it yet? Now's the perfect time to remind me.)

Thanks!

ChrisA

diff -r 5f63c8a92d1c pep-0463.txt
--- a/pep-0463.txt Mon Feb 24 14:22:46 2014 -0800
+++ b/pep-0463.txt Fri Feb 28 08:25:33 2014 +1100
@@ -43,6 +43,34 @@

 * statistics.mean(data) - no way to handle an empty iterator

+Had this facility existed early in Python's history, there would have been
+no need to create dict.get() and related methods; the one obvious way to
+handle an absent key would be to respond to the exception.  One method is
+written which signal the absence in one way, and one consistent technique
+is used to respond to the absence.  Instead, we have dict.get(), and as of
+Python 3.4, we also have min(... default=default), and myriad others.  We
+have a LBYL syntax for testing inside an expression, but there is currently
+no EAFP notation; compare the following::
+
+# LBYL:
+if key in dic:
+process(dic[key])
+else:
+process(None)
+# As an expression:
+process(dic[key] if key in dic else None)
+
+# EAFP:
+try:
+process(dic[key])
+except KeyError:
+process(None)
+# As an expression:
+process(dic[key] except KeyError: None)
+
+Python generally recommends the EAFP policy, but must then proliferate
+utility functions like dic.get(key,None) to enable this.
+

 Rationale
 =
@@ -338,6 +366,19 @@
 except KeyError:
 u = tarinfo.uid

+Look up an attribute, falling back on a default::
+mode = (f.mode except AttributeError: 'rb')
+
+# Lib/aifc.py:882:
+if hasattr(f, 'mode'):
+mode = f.mode
+else:
+mode = 'rb'
+
+return (sys._getframe(1) except AttributeError: None)
+# Lib/inspect.py:1350:
+return sys._getframe(1) if hasattr(sys, _getframe) else None
+
 Perform some lengthy calculations in EAFP mode, handling division by
 zero as a sort of sticky NaN::

@@ -616,7 +657,7 @@
 it would be with the statement form, and as its syntax is a point on
 which consensus has not been reached, the entire feature is deferred.

-Multiple 'except' keywords can be used, and they will all catch
+Multiple 'except' keywords could be used, and they will all catch
 exceptions raised in the original expression (only)::

 # Will catch any of the listed exceptions thrown by expr;

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-27 Thread Chris Angelico
On Fri, Feb 28, 2014 at 8:29 AM, Chris Angelico ros...@gmail.com wrote:
 @@ -43,6 +43,34 @@

  * statistics.mean(data) - no way to handle an empty iterator

 +Had this facility existed early in Python's history, there would have been
 +no need to create dict.get() and related methods; the one obvious way to
 +handle an absent key would be to respond to the exception.  One method is
 +written which signal the absence in one way, and one consistent technique

Doh! Typical... I notice the typo only after hitting send. This should
be which signals. The linked-to draft file has been updated.

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-27 Thread Nick Coghlan
On 28 Feb 2014 05:56, Chris Angelico ros...@gmail.com wrote:

 On Fri, Feb 28, 2014 at 6:36 AM, Glenn Linderman v+pyt...@g.nevcal.com
wrote:
  +1
 
  f() except ((TypeError, AttributeError): No value)
 
  is a nice extension to the idea of
 
  value = expr except (
  Exception1: default1,
  Exception2: default2,
  Exception3: default3,
 )
 
  Which I've liked since I first saw it, as it neatly solves handling
multiple
  except clauses.

 You can already list multiple exception types. The definition of the
 exception_list is exactly as per the try/except statement (bar the
 'as' keyword, which I would love to see implemented some day).

Note that this example is covering the deferred case of multiple except
clauses that resolve to different values, not the already handled case of
multiple exception types that resolve to the same value.

Anyway, even if you choose not to switch the parenthesis requirement in
PEP, it should at least make the colon as in dict display, not as in suite
introduction comparison, and note this as an alternative proposal for the
required parentheses.

Cheers,
Nick.


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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-27 Thread Chris Angelico
On Fri, Feb 28, 2014 at 1:12 PM, Glenn Linderman v+pyt...@g.nevcal.com wrote:
 Yes.  But the point is really the location of the (), sorry if my nice
 extension comment is throwing you off that track.

Ah! I see.

We touched on this syntax on -ideas, but at the time, the proposed
syntax didn't have parens around the outside. Either location will
solve most of the same problems (like precedence/associativity versus
multiple except clauses), but shrinking down to just the exception
list and default value makes it look very different. It looks like
what's inside should be an expression, which it isn't. What's the
advantage of this form? What's its key advantage over the
parens-around-the-whole-thing form?

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-27 Thread Glenn Linderman

On 2/27/2014 7:46 PM, Chris Angelico wrote:

On Fri, Feb 28, 2014 at 1:12 PM, Glenn Linderman v+pyt...@g.nevcal.com wrote:

Yes.  But the point is really the location of the (), sorry if my nice
extension comment is throwing you off that track.

Ah! I see.

We touched on this syntax on -ideas, but at the time, the proposed
syntax didn't have parens around the outside. Either location will
solve most of the same problems (like precedence/associativity versus
multiple except clauses), but shrinking down to just the exception
list and default value makes it look very different. It looks like
what's inside should be an expression, which it isn't. What's the
advantage of this form? What's its key advantage over the
parens-around-the-whole-thing form?


Key advantage to me is that if a function call or other expression may 
produce multiple exceptions, the syntax doesn't require repeating the 
except over and over.  By not repeating the except over and over, 
there is less ambiguity about what expression the Exception-lists apply 
to, when there is more than one Exception list in the expression.  
Whereas the current PEP syntax has ambiguity regarding how to interpret  
a-expr except except-list-b: b-expr except except-list-c: c-expr (does 
the 2nd except apply to a-expr or b-expr?), without parentheses, and, as 
far as I am concerned, even with the parentheses, this syntax makes it 
very clear that each of the Exception-lists apply to a-expr.


Key advantage to others may be that because the : is within the () [and 
the leading ( is quite nearby, making it obvious], it is less likely to 
be considered a statement boundary, and more easily explained as a 
special type of list syntax... not _really_ a list, because it is really 
code to be executed somewhat sequentially rather than data, and lists 
don't have : ... and not _really_ a dict constant, which does have :, 
because the Exception is not _really_ a key, but the syntax can draw on 
analogies with the dict constant syntax which will help people remember 
it, and even sort of understand that there is a pair-wise relationship 
between the Exception-list and the expression after the :, without 
repeating the except over and over.
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-24 Thread Rob Cliffe


On 22/02/2014 21:26, Tim Delaney wrote:


On 23 February 2014 02:29, Nick Coghlan ncogh...@gmail.com 
mailto:ncogh...@gmail.com wrote:


On 22 Feb 2014 22:15, Stephen J. Turnbull step...@xemacs.org
mailto:step...@xemacs.org wrote:
 Antoine Pitrou writes:
   Chris Angelico ros...@gmail.com mailto:ros...@gmail.com
wrote:
hasattr(x,y) - (x.y or True except AttributeError: False)
   But it's not the same. hasattr() returns a boolean, not an
arbitrary
   value.
 I think he meant
 hasattr(x,y) - (x.y and True except AttributeError: False)

With PEP 463, the explicit equivalent of hasattr() would be
something like :

hasattr(x,y) - (bool(x.y) or True except AttributeError: False)

That would work, but I think I'd prefer:

hasattr(x,y) - bool(x.y or True except AttributeError: False)

Makes it clearer IMO that the entire expression will always return a 
boolean.



This also works:

hasattr(x,y)  -  (lambda v: True)(x.y) except AttributeError: False

Which is less obscure is a matter of judgement.
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-24 Thread Rob Cliffe
Some of your points have been answered by others, I'll try to avoid 
repetition.


On 21/02/2014 19:04, Yury Selivanov wrote:

[snip]

Inconvenience of dict[] raising KeyError was solved by
introducing the dict.get() method. And I think that

dct.get('a', 'b')

is 1000 times better than

dct['a'] except KeyError: 'b'
Do you?  I don't.  Explicit is better than implicit.  I think this may 
be partly a matter of familiarity.



Translate numbers to names, falling back on the numbers::
 g = grp.getgrnam(tarinfo.gname)[2] except KeyError: 
tarinfo.gid
 u = pwd.getpwnam(tarinfo.uname)[2] except KeyError: 
tarinfo.uid


 # Lib/tarfile.py:2198:
 try:
 g = grp.getgrnam(tarinfo.gname)[2]
 except KeyError:
 g = tarinfo.gid
 try:
 u = pwd.getpwnam(tarinfo.uname)[2]
 except KeyError:
 u = tarinfo.uid

This one is a valid example, but totally unparseable by
humans.
Again, I find the more concise version easier to read than the 
original.  It is dense, yes.  It takes time to read and absorb, sure -  
but so does the original 8-line version.

And it makes the repetition of the same code structure much more obvious.




I think all of the above more readable with try statement.


Retrieving a message from either a cache or the internet, with auth
check::

 logging.info(Message shown to user: %s,((cache[k]
 except LookupError:
 (backend.read(k) except OSError: 'Resource not available')
 )
 if check_permission(k) else 'Access denied'
 ) except BaseException: This is like a bare except clause)

 try:
 if check_permission(k):
 try:
 _ = cache[k]
 except LookupError:
 try:
 _ = backend.read(k)
 except OSError:
 _ = 'Resource not available'
 else:
 _ = 'Access denied'
 except BaseException:
 _ = This is like a bare except clause
 logging.info(Message shown to user: %s, _)


I think there is a consensus that this was a poor example, unless 
intended to show how the new construction (like any other) could be 
abused to produce hard-to-understand code.



If you replace '_' with a 'msg' (why did you use '_'??)
then try statements are *much* more readable.


[snip]

Lib/ipaddress.py:343::
 try:
 ips.append(ip.ip)
 except AttributeError:
 ips.append(ip.network_address)
Becomes::
 ips.append(ip.ip except AttributeError: ip.network_address)

or it may become:

ips.append(getattr(ip, 'ip', ip.network_address))

or

address = getattr(ip, 'ip', ip.network_address)
ips.append(address)
Please note that any of these is an improvement on the original, in that 
they don't trap an AttributeError evaluating ips.append.  (The old try 
... except syntax can be used incorrectly, just as any new syntax can.)


---

All in all, your proposal scares me. I doesn't make python
code readable,

Again, a personal judgement.

it doesn't solve the problem of overbroad
exceptions handling (you have couple examples of overbroad
handling in your PEP examples section).

Yes, some examples look neat. But your syntax is much easier
to abuse, than 'if..else' expression,

Why?  Any syntax can be abused.  I can easily abuse if..else if I want to:
ErrorMessage = (None if eggs else No eggs) if ham else No ham if 
eggs else No ham or eggs # Tested


Suppose you were learning Python.
Which is easier, to learn lots of special methods (dict.get, getattr 
etc.), or to learn ONE self-explanatory form of syntax that covers them all:

Dict[Key] except KeyError: default
List[Index] except IndexError: default
x.y except AttributeError: default
(Of course, I'm not saying Don't use getattr.  Just that you could get 
by if you've never heard of it.)


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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-24 Thread Rob Cliffe


On 21/02/2014 23:36, Ethan Furman wrote:

On 02/21/2014 02:26 PM, Eric V. Smith wrote:

On 2/21/2014 5:06 PM, Greg Ewing wrote:

On 21 February 2014 13:15, Chris Angelico wrote:


Generator expressions require parentheses, unless they would be
strictly redundant.  Ambiguities with except expressions could be
resolved in the same way, forcing nested except-in-except trees to be
correctly parenthesized


There would be no ambiguity if only nested excepts are allowed. If one 
wants to catch multiple exceptions from one expression, /and do 
something different for each one/, use the statement form as it's 
going to be clearer.  For example:


   try:
   value = 1/x
   except ZeroDivisionError:
   try:
   value = 1/default['denominator']
   except KeyError:
   value = NaN

is much cleaner as:

   value = 1/x except ZeroDivisionError: 1/default['denominator'] 
except KeyError: NaN


However, this:

   try:
  result = Parse(some_stuff)
   except MissingOperator:
  result = ...
   except InvalidOperand:
  result = ...
   except SomethingElse:
  result = ...

would not benefit from being condensed into a single expression

--
~Ethan~

Funny, my feeling was exactly the reverse. :-)
Probably because the latter seems to me to be a more natural thing to 
want to do (I find it easier to imagine use cases for it).
And also because there is no way of getting exactly the same effect with 
a parenthesized except-expression:
(expr except ValueError: ValueErrrorMessage) except 
NameError:NameErrorMessage # doesn't quite do what I want
(here if expr raises a ValueError, evaluating ValueErrrorMessage which 
is mis-spelt will raise a NameError which will be misleadingly caught).
But I guess the truth is that any except-expression which gets too long 
and complicated should be written some other way.

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-24 Thread Rob Cliffe


On 22/02/2014 02:08, Glenn Linderman wrote:

On 2/21/2014 5:06 PM, Jan Kaliszewski wrote:

Or even (still being my favorite):

msg = seq[i] except (IndexError: nothing) 


This syntax actually has a benefit: the parenthesized syntax after 
except could become a list, to allow handling different exceptions 
from the tried expression with different results:


msg = seq[dictionary[i]] except (IndexError: nothing, KeyError: 
serious problems)
It shouldn't be a true list.  We need lazy evaluation of the default 
values.  And if an unlisted exception is raised, we don't want any of 
the defaults evaluated.

Rob Cliffe


And still allows nesting:

msg = seq[i] except (IndexError: dictionary[i] except (KeyError: no 
fallback data for %s % i))



___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/rob.cliffe%40btinternet.com


No virus found in this message.
Checked by AVG - www.avg.com http://www.avg.com
Version: 2012.0.2247 / Virus Database: 3705/6616 - Release Date: 02/22/14



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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-24 Thread Jim J. Jewett



Yury Selivanov wrote:

 I think the Motivation section is pretty weak.

I have normally wished for this when I was (semi-
interactively) exploring a weakly structured dataset.

Often, I start with a string, split it into something
hopefully like records, and then start applying filters
and transforms.  I would prefer to write a comprehension
instead of a for loop.  Alas, without pre-editing, I
can be fairly confident that the data is dirty.


Sometimes I can solve it with a filter (assuming
that I remember and don't mind the out-of-order
evaluation):

# The if value happens first,
# so the 1/value turns out to be safe.
[1/value for value in working_list if value]

Note that this means dropping the bad data, so that
items in this list will have different indices than
those in the parent working_list.

I would rather have written:

[1/value except (TypeError, ZeroDivisionError): None] 

which would keep the matching indices, and clearly
indicate where I now had missing/invalid data.



Sometimes I solve it with a clumsy workaround:

sum((e.weight if hasattr(e, 'weight') else 1.0)
for e in working_list)

But the hasattr implies that I am doing some sort of
classification based on whether or not the element has
a weight.

The true intent was to recognize that while every element
does have a weight, the representation that I'm starting
from didn't always bother to store it -- so I am repairing
that before processing.

sum(e.weight except AttributeError: 1)


Often I give up, and create a junky helper function, or several.
But to avoid polluting the namespace, I may leave it outside
the class, or give it a truly bad name:

def __only_n2(worklist):
results = []
for line in worklist:
line=line.strip()
if not line:  # or maybe just edit the input file...
continue
split1=line.split(, )
if 7 != len(split1):
continue
if n2 == split1[3]:
results.append(split1)
return results

worklist_n2 = __only_n2(worklist7)


In real life code, even after hand-editing the input data
to fix a few cases, I recently ended up with:

class VoteMark:
...
@classmethod
def from_property(cls, voteline):
# print (voteline)
count, _junk, prefs = voteline.partition(: )
return cls(count, prefs)

... # module level scope

def make_votes(vs=votestring):
return [VoteMark.from_property(e) for e in vs.splitlines()]

vs=make_votes()

You can correctly point out that I was being sloppy, and that I
*should* have gone back to clean it up.  But I wouldn't have had
to clean up either the code or the data (well, not as much), if
I had been able to just keep the step-at-a-time transformations
I was building up during development:

vs=[(VoteMark(*e.strip().split(: ))
   except (TypeError, ValueError): None)
for e in votestring.splitlines()]


Yes, the first line is still doing too much, and might be
worth a helper function during cleanup.

But it is already better than an alternate constructor that
exists only to simplify a single (outside the class) function
that is only called once.

Which in turn is better than the first draft that was so
ugly that I actually did fix it during that same work session.



 Inconvenience of dict[] raising KeyError was solved by
 introducing the dict.get() method. And I think that

 dct.get('a', 'b')

 is 1000 times better than

 dct['a'] except KeyError: 'b'

I don't.

dct.get('a', default='b')

would be considerably better, but it would still imply
that missing values are normal.  So even after argclinic
is fully integrated, there will still be times when I
prefer to make it explicit that I consider this an
abnormal case.  (And, as others have pointed out, .get
isn't a good solution when the default is expensive to
compute.)


 Consider this example of a two-level cache::
  for key in sequence:
  x = (lvl1[key] except KeyError: (lvl2[key] except KeyError: f(key)))

 I'm sorry, it took me a minute to understand what your
 example is doing.  I would rather see two try..except blocks
 than this.

Agreed -- like my semi-interactive code above, it does too much
on one line.  I don't object as much to:

for key in sequence:
x = (lvl1[key]
   except KeyError: (lvl2[key]
 except KeyError: f(key)))


 Retrieve an argument, defaulting to None::
  cond = args[1] except IndexError: None

  # Lib/pdb.py:803:
  try:
  cond = args[1]
  except IndexError:
  cond = None

 cond = None if (len(args)  2) else args[1]

This is an area where tastes will differ.

I view the first as saying that not having a cond
would be unusual, or at least a different kind of
call.

I view your version as a warning that argument
parsing will be complex, and that 

Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-24 Thread Jim J. Jewett



Greg Ewing suggested:

 This version might be more readable:

 value = lst[2] except No value if IndexError


Ethan Furman asked:

 It does read nicely, and is fine for the single, non-nested, case
 (which is probably the vast majority), but how would
 it handle nested exceptions?

With parentheses.

Sometimes, the parentheses will make a complex expression ugly.
Sometimes, a complex expression should really be factored into pieces anyway.

Hopefully, these times are highly correlated.



The above syntax does lend itself somewhat naturally
to multiple *short* except clauses:

value = (lst[2]
   except No value if IndexError
   except Bad Input if TypeError)

and nested exception expressions are at least possible, but deservedly ugly:

value = (lvl1[name]
  except (lvl2[name]
   except (compute_new_answer(name)
 except None if AppValueError)
   if KeyError)
  if KeyError)
  

This also makes me wonder whether the cost of a subscope 
(for exception capture) could be limited to when an
exception actually occurs, and whether that might lower
the cost enough to make the it a good tradeoff.

def myfunc1(a, b, e):
assert main scope e value == e

e = main scope e value
value = (myfunc1(val1, val2, e)
  except e.reason if AppError as e)
assert main scope e value == e


-jJ

-- 

If there are still threading problems with my replies, please 
email me with details, so that I can try to resolve them.  -jJ

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-24 Thread Chris Angelico
On Tue, Feb 25, 2014 at 11:27 AM, Jim J. Jewett jimjjew...@gmail.com wrote:
 This also makes me wonder whether the cost of a subscope
 (for exception capture) could be limited to when an
 exception actually occurs, and whether that might lower
 the cost enough to make the it a good tradeoff.

 def myfunc1(a, b, e):
 assert main scope e value == e

 e = main scope e value
 value = (myfunc1(val1, val2, e)
   except e.reason if AppError as e)
 assert main scope e value == e

I'm sure it could. But there aren't many use-cases. Look at the one
example I was able to find in the stdlib:

http://legacy.python.org/dev/peps/pep-0463/#capturing-the-exception-object

It's hardly a shining example of the value of the proposal. Got any
really awesome demo that requires 'as'? Most of the supporting
examples use something like KeyError where it's simply was an
exception thrown or not.

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-23 Thread Isaac Morland

On Sun, 23 Feb 2014, Nick Coghlan wrote:


Note that mandatory parentheses means we can duck the precedence
question entirely, which I count as another point in favour of
requiring them :)


Careful, if you take that too far then Python 4 will have to be Scheme. ;-)

Isaac Morland   CSCF Web Guru
DC 2619, x36650 WWW Software Specialist
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-23 Thread Stefan Behnel
Chris Angelico, 21.02.2014 04:15:
 Just as PEP 308 introduced a means of value-based conditions in an
 expression, this system allows exception-based conditions to be used
 as part of an expression.
 [...]
 This currently works::
 
 lst = [1, 2, None, 3]
 value = lst[2] or No value
 
 The proposal adds this::
 
 lst = [1, 2]
 value = lst[2] except IndexError: No value

I see a risk of interfering with in-place assignment operators, e.g.

x /= y except ZeroDivisionError: 1

might not do what one could expect, because (as I assume) it would behave
differently from

x = x / y except ZeroDivisionError: 1

I think that falls under the overly broad exception handling issue. If
you want to include the assignment, you'll have to spell out the try-except
block yourself. I find the difference in the two behaviours very
unfortunate, though.

This also reduces the scope of applicability somewhat. Cython has typed
assignments, so a straight forward idea would be to handle TypeErrors in
assignments like this:

cdef str s
s = x except TypeError: str(x)

However, I guess that would similarly counter the idea of exception
handling in an *expression*, and the correct and non-ambiguous way to do
this would be to spell out the try-except block.

Summing it up, my impression is that it helps some use cases but leaves
others more ambiguous/unclear/unfortunate, which makes me lean towards
rejecting it.

Stefan


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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-23 Thread Stefan Behnel
Stefan Behnel, 23.02.2014 19:51:
 Cython has typed
 assignments, so a straight forward idea would be to handle TypeErrors in
 assignments like this:
 
 cdef str s
 s = x except TypeError: str(x)

Similar code in Python would be this:

from array import array
x = array('i', [1,2,3])
value = 123

x[0] = value except TypeError: int(value)


 However, I guess that would similarly counter the idea of exception
 handling in an *expression*, and the correct and non-ambiguous way to do
 this would be to spell out the try-except block.

Stefan


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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-23 Thread Thomas Wouters
On Feb 23, 2014 7:52 PM, Stefan Behnel stefan...@behnel.de wrote:

 Chris Angelico, 21.02.2014 04:15:
  Just as PEP 308 introduced a means of value-based conditions in an
  expression, this system allows exception-based conditions to be used
  as part of an expression.
  [...]
  This currently works::
 
  lst = [1, 2, None, 3]
  value = lst[2] or No value
 
  The proposal adds this::
 
  lst = [1, 2]
  value = lst[2] except IndexError: No value

 I see a risk of interfering with in-place assignment operators, e.g.

 x /= y except ZeroDivisionError: 1

 might not do what one could expect, because (as I assume) it would behave
 differently from

 x = x / y except ZeroDivisionError: 1

Yes. Augmented assignment is still assignment, so a statement. The only way
to parse that is as

x /= (y except ZeroDivisionError: 1)

and it'd be equivalent to

x = x / (y except ZeroDivisionError: 1)

(If the parentheses are mandatory that makes it easier to spot the
difference.)


 I think that falls under the overly broad exception handling issue. If
 you want to include the assignment, you'll have to spell out the
try-except
 block yourself. I find the difference in the two behaviours very
 unfortunate, though.

 This also reduces the scope of applicability somewhat. Cython has typed
 assignments, so a straight forward idea would be to handle TypeErrors in
 assignments like this:

 cdef str s
 s = x except TypeError: str(x)

 However, I guess that would similarly counter the idea of exception
 handling in an *expression*, and the correct and non-ambiguous way to do
 this would be to spell out the try-except block.

 Summing it up, my impression is that it helps some use cases but leaves
 others more ambiguous/unclear/unfortunate, which makes me lean towards
 rejecting it.

 Stefan


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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-23 Thread Ethan Furman

On 02/23/2014 11:26 AM, Thomas Wouters wrote:


On Feb 23, 2014 7:52 PM, Stefan Behnel stefan...@behnel.de 
mailto:stefan...@behnel.de wrote:


Chris Angelico, 21.02.2014 04:15:
 Just as PEP 308 introduced a means of value-based conditions in an
 expression, this system allows exception-based conditions to be used
 as part of an expression.
 [...]
 This currently works::

 lst = [1, 2, None, 3]
 value = lst[2] or No value

 The proposal adds this::

 lst = [1, 2]
 value = lst[2] except IndexError: No value

I see a risk of interfering with in-place assignment operators, e.g.

x /= y except ZeroDivisionError: 1

might not do what one could expect, because (as I assume) it would behave
differently from

x = x / y except ZeroDivisionError: 1


Yes. Augmented assignment is still assignment, so a statement. The only way to 
parse that is as

x /= (y except ZeroDivisionError: 1)


Well, that is certainly not what I would have expected.

I can also see how parentheses can help, but I still would like them optional.

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-23 Thread Chris Angelico
On Mon, Feb 24, 2014 at 6:26 AM, Thomas Wouters tho...@python.org wrote:
 I see a risk of interfering with in-place assignment operators, e.g.

 x /= y except ZeroDivisionError: 1

 might not do what one could expect, because (as I assume) it would behave
 differently from

 x = x / y except ZeroDivisionError: 1

 Yes. Augmented assignment is still assignment, so a statement. The only way
 to parse that is as

 x /= (y except ZeroDivisionError: 1)

 and it'd be equivalent to

 x = x / (y except ZeroDivisionError: 1)

 (If the parentheses are mandatory that makes it easier to spot the
 difference.)


 I think that falls under the overly broad exception handling issue. If
 you want to include the assignment, you'll have to spell out the
 try-except
 block yourself. I find the difference in the two behaviours very
 unfortunate, though.

Thomas's analysis is correct. It's not overly broad; in fact, what you
have is an overly _narrow_ exception handler, catching a
ZeroDivisionError from the evaluation of y only.

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-23 Thread Jan Kaliszewski

23.02.2014 19:51, Stefan Behnel wrote:


I see a risk of interfering with in-place assignment operators, e.g.

x /= y except ZeroDivisionError: 1

might not do what one could expect, because (as I assume) it would 
behave

differently from

x = x / y except ZeroDivisionError: 1

[snip]

Please note that:

x /= y if y else 0

also behaves differently from

x = x / y if y else 0

Anyway, enclosing in parens would make that expicit and clear.

Cheers.
*j

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-23 Thread Chris Angelico
On Mon, Feb 24, 2014 at 7:51 AM, Ethan Furman et...@stoneleaf.us wrote:
 Yes. Augmented assignment is still assignment, so a statement. The only
 way to parse that is as

 x /= (y except ZeroDivisionError: 1)


 Well, that is certainly not what I would have expected.

I can see that you'd want to have that go back and redo the division
with a second argument of 1, which'd look like this in statement form:

try: x /= y
except ZeroDivisionError: x /= 1

But, just like the decried error suppression technique, the second
half of this is something that should instead be written pass. At
very least, I'd say that an except-expression where one or other of
its forms is better spelled pass is code smell, and at worst, I'd
say it's a hint that the expression form might not even be what you
think it is - as in this case.

Remember, this is a scope-narrowing. Where previously you had to
try/except entire statements, now you can try/except just one part of
something. That means you won't catch errors in the actual assignment
- which is usually a good thing - but it does affect augmented
assignment. My recommendation: Just use try... except pass. I'm not
trying to supplant the statement form :)

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-22 Thread Ethan Furman

On 02/21/2014 10:57 PM, Stephen J. Turnbull wrote:

Ethan Furman writes:

On 02/21/2014 07:46 PM, Chris Angelico wrote:


but not this:

value = expr except Exception: default except Exception: default


This should be the way it works.  Nothing is gained in readability
by turning a try with multiple except statements into an
expression.


Examples have been given several times.  In general, if 'expr' is a
function call, it may well have a couple of different ways to fail
which imply different default values.

 interpolable = func(key) except TypeError: not a string: %s % key \
  except KeyError: no such key: %s % key
 print(Some message that refers to '%s' % interpolable)

versus

 try:
 interpolable = func(key)
 except TypeError:
 interpolable = not a string: %s % key
 except KeyError:
 interpolable = no such key: %s % key
 print(Some message that refers to '%s' % interpolable)

I think the latter begs to be written as the former.


Okay, that's the best example of that style I've seen so far (sorry, Chris, if something similar was in the PEP and I 
missed it).  I will yield the point that something is gained -- still, I think it is a small something compared to 
converting a nested except statement into an expression, and if only allowing one or the other makes the whole thing 
simpler I vote for the nested excepts to be converted, not the already easily read multiple excepts.


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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-22 Thread Antoine Pitrou
On Sat, 22 Feb 2014 15:57:02 +0900
Stephen J. Turnbull step...@xemacs.org wrote:
 
 try:
 interpolable = func(key)
 except TypeError:
 interpolable = not a string: %s % key
 except KeyError:
 interpolable = no such key: %s % key
 print(Some message that refers to '%s' % interpolable)

I think that's a rare enough case, though (compared to the other idioms
showcased in the PEP), that we needn't care about it.

Regards

Antoine.


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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-22 Thread Antoine Pitrou
On Fri, 21 Feb 2014 09:37:29 -0800
Guido van Rossum gu...@python.org wrote:
 I'm put off by the ':' syntax myself (it looks to me as if someone forgot a
 newline somewhere) but 'then' feels even weirder (it's been hard-coded in
 my brain as meaning the first branch of an 'if').

Would 'else' work rather than 'then'?

Regards

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-22 Thread Antoine Pitrou
On Sat, 22 Feb 2014 16:12:27 +0900
Stephen J. Turnbull step...@xemacs.org wrote:
 
 Note in support: I originally thought that get methods would be more
 efficient, but since Nick pointed out that haveattr is implemented
 by catching the exception (Yikes! LBYL implemented by using EAFP!), I
 assume that get methods also are (explicitly or implicitly)
 implemented that way.

Well, the only way to know that a key (or attribute) exists is to do
the lookup. What else would you suggest?

And, yes, EAFP can avoid race conditions and the like (besides being
more efficient with non-trivial keys).

Regards

Antoine.


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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-22 Thread Antoine Pitrou
On Fri, 21 Feb 2014 19:49:20 -0700
Eric Snow ericsnowcurren...@gmail.com wrote:
 On Fri, Feb 21, 2014 at 7:07 PM, Victor Stinner
 victor.stin...@gmail.com wrote:
  Consider this example of a two-level cache::
  for key in sequence:
  x = (lvl1[key] except KeyError: (lvl2[key] except KeyError: 
  f(key)))
  # do something with x
 
  ... but I don't like when it is used to build complex expressions.
 
 This is true of any expression syntax, not just this proposal--though
 some expression syntax is more apt to be abused than others: you won't
 see many multiline int literals! ;)

But this is precisely why Python has refrained from making everything
an expression. For example, why assignements are not expressions.

Regards

Antoine.


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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-22 Thread Chris Angelico
On Sat, Feb 22, 2014 at 8:20 PM, Antoine Pitrou solip...@pitrou.net wrote:
 On Sat, 22 Feb 2014 16:12:27 +0900
 Stephen J. Turnbull step...@xemacs.org wrote:

 Note in support: I originally thought that get methods would be more
 efficient, but since Nick pointed out that haveattr is implemented
 by catching the exception (Yikes! LBYL implemented by using EAFP!), I
 assume that get methods also are (explicitly or implicitly)
 implemented that way.

 Well, the only way to know that a key (or attribute) exists is to do
 the lookup. What else would you suggest?

 And, yes, EAFP can avoid race conditions and the like (besides being
 more efficient with non-trivial keys).

Which means that, fundamentally, EAFP is the way to do it. So if PEP
463 expressions had existed from the beginning, hasattr() probably
wouldn't have been written - people would just use an
except-expression instead.

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-22 Thread Antoine Pitrou
On Sat, 22 Feb 2014 20:29:27 +1100
Chris Angelico ros...@gmail.com wrote:
 
 Which means that, fundamentally, EAFP is the way to do it. So if PEP
 463 expressions had existed from the beginning, hasattr() probably
 wouldn't have been written - people would just use an
 except-expression instead.

Really? hasattr() is much easier to write than the corresponding
except-expression.

Regards

Antoine.


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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-22 Thread Chris Angelico
On Sat, Feb 22, 2014 at 8:58 PM, Antoine Pitrou solip...@pitrou.net wrote:
 On Sat, 22 Feb 2014 20:29:27 +1100
 Chris Angelico ros...@gmail.com wrote:

 Which means that, fundamentally, EAFP is the way to do it. So if PEP
 463 expressions had existed from the beginning, hasattr() probably
 wouldn't have been written - people would just use an
 except-expression instead.

 Really? hasattr() is much easier to write than the corresponding
 except-expression.

But would it be sufficiently easier to justify the creation of a
built-in? Imagine this were the other way around: we have
except-expressions, but we don't have hasattr. Now someone comes onto
python-ideas and says, Wouldn't it be nice if we had a hasattr()
function to tell us whether something has an attribute or not.
Considering that hasattr can be easily implemented using an
except-expression, it would be unlikely to be considered worthy of a
built-in.

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-22 Thread Thomas Wouters
On Fri, Feb 21, 2014 at 7:46 PM, Chris Angelico ros...@gmail.com wrote:

 On Sat, Feb 22, 2014 at 9:06 AM, Greg Ewing greg.ew...@canterbury.ac.nz
 wrote:
  Nick Coghlan wrote:
 
  On 21 February 2014 13:15, Chris Angelico ros...@gmail.com wrote:
 
  Generator expressions require parentheses, unless they would be
  strictly redundant.  Ambiguities with except expressions could be
  resolved in the same way, forcing nested except-in-except trees to be
  correctly parenthesized
 
 
  I'd like to make the case that the PEP should adopt this as its
  default position.
 
 
  I generally agree, but I'd like to point out that this
  doesn't necessarily mean making the parenthesizing rules as
  strict as they are for generator expressions.
 
  The starting point for genexps is that the parens are part of
  the syntax, the same way that square brackets are part of
  the syntax of a list comprehension; we only allow them to
  be omitted in very special circumstances.
 
  On the other hand, I don't think there's any harm in allowing
  an except expression to stand on its own when there is no
  risk of ambiguity, e.g.
 
 foo = things[i] except IndexError: None
 
  should be allowed, just as we allow
 
 x = a if b else c
 
  and don't require
 
 x = (a if b else c)

 I'm inclined to agree with you. I fought against the mandated parens
 for a long time. Would be happy to un-mandate them, as long as there's
 no way for there to be ambiguity. Is CPython able to make an operator
 non-associative? That is, to allow these:

 value = expr except Exception: default
 value = (expr except Exception: default) except Exception: default
 value = expr except Exception: (default except Exception: default)

 but not this:

 value = expr except Exception: default except Exception: default

 ?


Yes, although how to do it depends on what else 'default' and 'expr' can
be. The simple answer is to make 'expr' and 'default' be subsets of
expressions that don't include the 'except' expression themselves. Just
like how in 'A if C else B', 'A' and 'C' do not include the 'if' syntax,
but 'B' does: you need parentheses in '(a if c1 else b) if c2 else d' and
'a if (c1 if c3 else c2) else b' but not in 'a if c1 else b if c2 else d'.

However, the question becomes what to do with 'lambda' and 'if-else'. Which
of these should be valid (and mean what it means with the parentheses,
which is how the PEP currently suggests it should be; ones without
parenthesized alternatives are unambiguous, as far as I can tell.)

1. make_adder(x) except TypeError: lambda y: y + 0

2. lambda x: x + 0 except TypeError: 1
- lambda x: (x + 0 except TypeError: 1)

3. A if f(A) except TypeError: C else B

4. f(A1) except TypeError: A2 if C else B
- f(A1) except TypeError: (A2 if C else B)

5. f(A1) except TypeError if C else ValueError: f(A2)

6. A if C else f(B) except TypeError: B
- (A if C else f(B)) except TypeError: B

7. f(A) except E1(A) except E2(A): E2: E1
- f(A) except (E1(A) except E2(A): E2): E1

8. f(A) or f(B) except TypeError: f(C)
- (f(A) or f(B)) except TypeError: f(C)

9. f(A) except TypeError: f(B) or f(C)
- f(A) except TypeError: (f(B) or f(C))

10. A == f(A) except TypeError: B
- (A == f(A)) except TypeError: B

11. f(A) except TypeError: A == B
- f(A) except TypeError: (A == B)

12. A + B except TypeError: C
- (A + B) except TypeError: C

13. f(A) except TypeError: A + B
- f(A) except TypeError: (A + B)

#6 in particular and to some extent #4, #8 and #10 look wrong to me, so if
they'd be allowed without parentheses perhaps the precedence of if-expr and
except should be more nuanced. ('between lambda and ifexpr' is not really a
sensible way to describe precedence anyway, since despite the insistence of
the reference manual, the precedence of 'lambda' and 'ifexpr' is at best
'mixed': the grammar actually tries to match ifexpr first, but it works the
way we all expect because 'lambda' is not an infix operator.)

It's easy to disallow most of these (allowing only their parenthesized
versions), the question is where to draw the line :) Some of these require
a bit more work in the grammar, duplicating some of the grammar nodes, but
it shouldn't be too bad. However, disallowing any infix operators in the
'default' expression means it'll still be valid, just mean something
different; #9, for example, would be parsed as '(f(A) except TypeError:
f(B)) or f(C)' if the 'default' expression couldn't be an or-expression.
Disallowing it in the 'expr' expression wouldn't have that effect without
parentheses.

(FWIW, I have a working patch without tests that allows all of these, I'll
upload it tonight so people can play with it. Oh, and FWIW, currently I'm
+0 on the idea, -0 on the specific syntax.)
-- 
Thomas Wouters tho...@python.org

Hi! I'm an email virus! Think twice before sending your email to help me
spread!
___
Python-Dev mailing list
Python-Dev@python.org

Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-22 Thread Antoine Pitrou
On Sat, 22 Feb 2014 21:09:07 +1100
Chris Angelico ros...@gmail.com wrote:
 On Sat, Feb 22, 2014 at 8:58 PM, Antoine Pitrou solip...@pitrou.net wrote:
  On Sat, 22 Feb 2014 20:29:27 +1100
  Chris Angelico ros...@gmail.com wrote:
 
  Which means that, fundamentally, EAFP is the way to do it. So if PEP
  463 expressions had existed from the beginning, hasattr() probably
  wouldn't have been written - people would just use an
  except-expression instead.
 
  Really? hasattr() is much easier to write than the corresponding
  except-expression.
 
 But would it be sufficiently easier to justify the creation of a
 built-in?

Well, can you propose the corresponding except-expression?

Regards

Antoine.


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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-22 Thread Stephen J. Turnbull
Antoine Pitrou writes:

  Well, the only way to know that a key (or attribute) exists is to do
  the lookup. What else would you suggest?

Do the lookup at the C level (or whatever the implementation language
is) and generate no exception, of course.  That's what would make it
possibly more efficient.
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-22 Thread Antoine Pitrou
On sam., 2014-02-22 at 19:29 +0900, Stephen J. Turnbull wrote:
 Antoine Pitrou writes:
 
   Well, the only way to know that a key (or attribute) exists is to do
   the lookup. What else would you suggest?
 
 Do the lookup at the C level (or whatever the implementation language
 is) and generate no exception, of course.  That's what would make it
 possibly more efficient.

Let's see:
- hasattr() does the lookup at the C level, and silences the
AttributeError
- dict.get() does the lookup at the C level, and doesn't generate an
exception

So apart from the minor inefficiency of generating and silencing the
AttributeError, those functions already do what you suggest.

Regards

Antoine.


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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-22 Thread Chris Angelico
On Sat, Feb 22, 2014 at 9:17 PM, Antoine Pitrou solip...@pitrou.net wrote:
 On Sat, 22 Feb 2014 21:09:07 +1100
 Chris Angelico ros...@gmail.com wrote:
 On Sat, Feb 22, 2014 at 8:58 PM, Antoine Pitrou solip...@pitrou.net wrote:
  On Sat, 22 Feb 2014 20:29:27 +1100
  Chris Angelico ros...@gmail.com wrote:
 
  Which means that, fundamentally, EAFP is the way to do it. So if PEP
  463 expressions had existed from the beginning, hasattr() probably
  wouldn't have been written - people would just use an
  except-expression instead.
 
  Really? hasattr() is much easier to write than the corresponding
  except-expression.

 But would it be sufficiently easier to justify the creation of a
 built-in?

 Well, can you propose the corresponding except-expression?

It's hard to do hasattr itself without something messy - the best I
can come up with is this:

hasattr(x,y) - (x.y or True except AttributeError: False)

but the bulk of uses of it are immediately before attempting to use
the attribute. Many require multiple statements, so they'd be better
done as a full try/except:

cpython/python-gdb.py:1392:
if not hasattr(self._gdbframe, 'select'):
print ('Unable to select frame: '
   'this build of gdb does not expose a
gdb.Frame.select method')
return False
self._gdbframe.select()
return True
becomes
try:
self._gdbframe.select()
return True
except AttributeError:
print ('Unable to select frame: '
   'this build of gdb does not expose a
gdb.Frame.select method')
return False

but others are clearly expressions in disguise:

Lib/aifc.py:882:
if hasattr(f, 'mode'):
mode = f.mode
else:
mode = 'rb'
becomes
mode = (f.mode except AttributeError: 'rb')

(In fact, I'm adding that one to the PEP's examples section.)

Lib/cgi.py:145:
if hasattr(fp,'encoding'):
encoding = fp.encoding
else:
encoding = 'latin-1'
becomes
encoding = (fp.encoding except AttributeError: 'latin-1')

Some could be done either way. If hasattr didn't exist, then this:

Lib/argparse.py:597:
if hasattr(params[name], '__name__'):
params[name] = params[name].__name__

could be written instead as:
params[name] = (params[name].__name__
except AttributeError: params[name])

which is similar length and doesn't require a built-in.

Some are fairly clearly asking to be done as try/except, irrespective
of this PEP:

Lib/decimal.py:449:
if hasattr(threading.current_thread(), '__decimal_context__'):
del threading.current_thread().__decimal_context__
becomes
try: del threading.current_thread().__decimal_context__
except AttributeError: pass

(also ibid:476)

Some are a bit of a mixture.

Lib/dis.py:40:
if hasattr(x, '__func__'):  # Method
x = x.__func__
if hasattr(x, '__code__'):  # Function
x = x.__code__
if hasattr(x, '__dict__'):  # Class or module
... lots more code ...

Could be done as try/except; first part could be done cleanly as an expression.

This one's not quite as clean, but if hasattr didn't exist, this could
be done either of two ways:

Lib/fileinput.py:342:
if hasattr(os, 'O_BINARY'):
mode |= os.O_BINARY
As an expression:
mode |= (os.O_BINARY except AttributeError: 0)
Or as a statement:
try: mode |= os.O_BINARY
except AttributeError: pass

This one definitely would want to be changed, and is also going in the PEP:

Lib/inspect.py:1350:
return sys._getframe(1) if hasattr(sys, _getframe) else None
becomes
return (sys._getframe(1) except AttributeError: None)

Lib/ntpath.py:558:
# Win9x family and earlier have no Unicode filename support.
supports_unicode_filenames = (hasattr(sys, getwindowsversion) and
  sys.getwindowsversion()[3] = 2)
becomes
supports_unicode_filenames = (sys.getwindowsversion()[3] = 2
  except AttributeError: False)

Another ternary-if LBYL that could become an expression-except EAFP:
Lib/pdb.py:745:
globs = self.curframe.f_globals if hasattr(self, 'curframe') else None
becomes
globs = (self.curframe.f_globals except AttributeError: None)
although that will return None if self.curframe has no f_globals.

Another nice easy one:
Lib/pickletools.py:2227:
if hasattr(data, tell):
getpos = data.tell
else:
getpos = lambda: None
becomes
getpos = (data.tell except AttributeError: lambda: None)

I could continue this theme, but behold, as Rose Maybud said, I have
said enough.

There are definitely cases where a local hasattr function could be
useful, but if the code were already written to use try/except or an
except-expression, there aren't many that would justify the creation
of a builtin.


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-22 Thread Antoine Pitrou
On Sat, 22 Feb 2014 22:13:58 +1100
Chris Angelico ros...@gmail.com wrote:
 
  Well, can you propose the corresponding except-expression?
 
 It's hard to do hasattr itself without something messy - the best I
 can come up with is this:
 
 hasattr(x,y) - (x.y or True except AttributeError: False)

But it's not the same. hasattr() returns a boolean, not an arbitrary
value.

 try:
 self._gdbframe.select()
 return True
 except AttributeError:
 print ('Unable to select frame: '
'this build of gdb does not expose a
 gdb.Frame.select method')
 return False

But then you can't distinguish between a missing select method
and an AttributeError raised by self._gdbframe.select() itself.

 but others are clearly expressions in disguise:
 
 Lib/aifc.py:882:
 if hasattr(f, 'mode'):
 mode = f.mode
 else:
 mode = 'rb'
 becomes
 mode = (f.mode except AttributeError: 'rb')

Not significantly less wordy. Note you can already write:

   mode = getattr(f, 'mode', 'rb')

which is more concise.

 (In fact, I'm adding that one to the PEP's examples section.)
 
 Lib/cgi.py:145:
 if hasattr(fp,'encoding'):
 encoding = fp.encoding
 else:
 encoding = 'latin-1'
 becomes
 encoding = (fp.encoding except AttributeError: 'latin-1')

Same here:

encoding = getattr(fp, 'encoding', 'latin-1')

 Some could be done either way. If hasattr didn't exist, then this:
 
 Lib/argparse.py:597:
 if hasattr(params[name], '__name__'):
 params[name] = params[name].__name__
 
 could be written instead as:
 params[name] = (params[name].__name__
 except AttributeError: params[name])

This makes a useless assignment if the attribute doesn't exist; it also
spans a single expression over two lines instead of having two simple
statements. It's definitely worse IMO.

 Some are fairly clearly asking to be done as try/except, irrespective
 of this PEP:
 
 Lib/decimal.py:449:
 if hasattr(threading.current_thread(), '__decimal_context__'):
 del threading.current_thread().__decimal_context__
 becomes
 try: del threading.current_thread().__decimal_context__
 except AttributeError: pass

May hide a bug if threading.current_thread doesn't exist.

 Lib/inspect.py:1350:
 return sys._getframe(1) if hasattr(sys, _getframe) else None
 becomes
 return (sys._getframe(1) except AttributeError: None)

May hide a bug if sys._getframe(1) itself raises AttributeError.

(etc.)

 I could continue this theme, but behold, as Rose Maybud said, I have
 said enough.

Yeah, none of these examples makes a convincing case that hasattr() is
useless, IMO.

Regards

Antoine.


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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-22 Thread Chris Angelico
On Sat, Feb 22, 2014 at 10:27 PM, Antoine Pitrou solip...@pitrou.net wrote:
 Yeah, none of these examples makes a convincing case that hasattr() is
 useless, IMO.

I'm not trying to make the case that it's useless. I'm trying to show
that, if it didn't exist, all of these would be written some other
way, and the case for its creation would not be terribly strong. It's
definitely of value (and as you've shown in some of those cases, its
proper use can narrow the exception-catching scope - a good thing),
but not enough to be worth blessing with a built-in function.

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-22 Thread Stephen J. Turnbull
Antoine Pitrou writes:
  On sam., 2014-02-22 at 19:29 +0900, Stephen J. Turnbull wrote:
   Antoine Pitrou writes:
   
 Well, the only way to know that a key (or attribute) exists is to do
 the lookup. What else would you suggest?
   
   Do the lookup at the C level (or whatever the implementation language
   is) and generate no exception, of course.  That's what would make it
   possibly more efficient.
  
  Let's see:
  - hasattr() does the lookup at the C level, and silences the
  AttributeError
  - dict.get() does the lookup at the C level, and doesn't generate an
  exception
  
  So apart from the minor inefficiency of generating and silencing the
  AttributeError, those functions already do what you suggest.

But that's precisely the inefficiency I'm referring to.

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-22 Thread Antoine Pitrou
On sam., 2014-02-22 at 20:54 +0900, Stephen J. Turnbull wrote:
 Antoine Pitrou writes:
   On sam., 2014-02-22 at 19:29 +0900, Stephen J. Turnbull wrote:
Antoine Pitrou writes:

  Well, the only way to know that a key (or attribute) exists is to do
  the lookup. What else would you suggest?

Do the lookup at the C level (or whatever the implementation language
is) and generate no exception, of course.  That's what would make it
possibly more efficient.
   
   Let's see:
   - hasattr() does the lookup at the C level, and silences the
   AttributeError
   - dict.get() does the lookup at the C level, and doesn't generate an
   exception
   
   So apart from the minor inefficiency of generating and silencing the
   AttributeError, those functions already do what you suggest.
 
 But that's precisely the inefficiency I'm referring to.

Sure, but complaining about inefficiencies without asserting their
significance is not very useful.

Regards

Antoine.


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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-22 Thread Stephen J. Turnbull
Antoine Pitrou writes:
  On Sat, 22 Feb 2014 22:13:58 +1100
  Chris Angelico ros...@gmail.com wrote:

   hasattr(x,y) - (x.y or True except AttributeError: False)

  But it's not the same. hasattr() returns a boolean, not an arbitrary
  value.

I think he meant 

hasattr(x,y) - (x.y and True except AttributeError: False)

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-22 Thread Eric V. Smith
On 2/22/2014 6:27 AM, Antoine Pitrou wrote:
 On Sat, 22 Feb 2014 22:13:58 +1100
 Chris Angelico ros...@gmail.com wrote:

 Lib/inspect.py:1350:
 return sys._getframe(1) if hasattr(sys, _getframe) else None
 becomes
 return (sys._getframe(1) except AttributeError: None)
 
 May hide a bug if sys._getframe(1) itself raises AttributeError.

return (sys._getframe except AttributeError: lambda i: None)(1)

Assuming I have the syntax correct, and the bindings work this way, of
course.
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-22 Thread Chris Angelico
On Sat, Feb 22, 2014 at 11:14 PM, Stephen J. Turnbull
step...@xemacs.org wrote:
 Antoine Pitrou writes:
   On Sat, 22 Feb 2014 22:13:58 +1100
   Chris Angelico ros...@gmail.com wrote:

hasattr(x,y) - (x.y or True except AttributeError: False)

   But it's not the same. hasattr() returns a boolean, not an arbitrary
   value.

 I think he meant

 hasattr(x,y) - (x.y and True except AttributeError: False)

No, I meant 'or' to ensure that an attribute holding a false value
doesn't come up false. But if you really want a boolean, just wrap it
up in bool().

My main point, though, was that most usage of hasattr is probing just
before something gets used - something like this:

if hasattr(obj, attr):
blah blah obj.attr
else:
maybe use a default or maybe do nothing

Some cases could become except-expressions; others could become
try/except statements. In each case, the loss would be small. I'm not
saying hasattr should be removed, just that it wouldn't have a strong
case if it didn't already exist.

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-22 Thread Nick Coghlan
On 22 Feb 2014 22:15, Stephen J. Turnbull step...@xemacs.org wrote:

 Antoine Pitrou writes:
   On Sat, 22 Feb 2014 22:13:58 +1100
   Chris Angelico ros...@gmail.com wrote:

hasattr(x,y) - (x.y or True except AttributeError: False)

   But it's not the same. hasattr() returns a boolean, not an arbitrary
   value.

 I think he meant

 hasattr(x,y) - (x.y and True except AttributeError: False)

With PEP 463, the explicit equivalent of hasattr() would be something like :

hasattr(x,y) - (bool(x.y) or True except AttributeError: False)

The version Chris came up with was close, but as Antoine noted, didn't
ensure the result was always exactly True or False.

The translation isn't simple because we don't allow an else clause on the
except expression (and I agree with this limitation), so the first
expression needs to be one that will *evaluate* x.y, but ensure the result
of the expression is True if no exception is thrown.

However, as Chris noted in his reply, there are still cases where using
hasattr makes more sense, so the fact it *can* be written as an except
expression instead is a curiosity rather than anything with deep practical
implications.

Cheers,
Nick.

P.S. The fully general variant of else emulation under PEP 463:

((bool(EXPR) and False) or NO_EXC_RESULT except EXC: EXC_RESULT)

Note: never actually use this, it's effectively unreadable ;)


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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-22 Thread Brett Cannon
On Fri, Feb 21, 2014 at 8:41 PM, Greg Ewing greg.ew...@canterbury.ac.nzwrote:

 Ethan Furman wrote:

 On 02/21/2014 03:29 PM, Greg Ewing wrote:

  value = lst[2] except No value if IndexError


 It does read nicely, and is fine for the single, non-nested, case (which
 is probably the vast majority), but how would it handle nested exceptions?


 Hmmm, probably not very well, unless we define

a except b if E1 except c if E2

 to mean

a except (b except c if E2) if E1

 If E1 == E2, that could perhaps be abbreviated to

a except b except c if E

 Or we could just decide that the nested case is going
 to be so rare it's not worth worrying about.


+1 on not caring. Keep the expression for simple, obvious cases of a single
exception type and fall back to the statement for fancier use (just like
listcomps). The focus should be ease of expressiveness for a common
pattern, not trying to convert tons of try/except statements into an
expression just because we can.
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-22 Thread Brett Cannon
On Sat, Feb 22, 2014 at 4:13 AM, Antoine Pitrou solip...@pitrou.net wrote:

 On Fri, 21 Feb 2014 09:37:29 -0800
 Guido van Rossum gu...@python.org wrote:
  I'm put off by the ':' syntax myself (it looks to me as if someone
 forgot a
  newline somewhere) but 'then' feels even weirder (it's been hard-coded in
  my brain as meaning the first branch of an 'if').

 Would 'else' work rather than 'then'?


thing = stuff['key'] except KeyError else None

That reads to me like the exception was silenced and only if there is no
exception the None is returned, just like an 'else' clause on a 'try'
statement.

I personally don't mind the 'then' as my brain has been hard-coded to mean
the first branch of a statement so it's looser than being explicitly
associated with 'if' but with any multi-clause statement.
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-22 Thread Jeff Allen


On 22/02/2014 16:36, Brett Cannon wrote:


On Sat, Feb 22, 2014 at 4:13 AM, Antoine Pitrou solip...@pitrou.net 
mailto:solip...@pitrou.net wrote:


On Fri, 21 Feb 2014 09:37:29 -0800
Guido van Rossum gu...@python.org mailto:gu...@python.org wrote:
 I'm put off by the ':' syntax myself (it looks to me as if
someone forgot a
 newline somewhere) but 'then' feels even weirder (it's been
hard-coded in
 my brain as meaning the first branch of an 'if').

Would 'else' work rather than 'then'?


thing = stuff['key'] except KeyError else None

That reads to me like the exception was silenced and only if there is 
no exception the None is returned, just like an 'else' clause on a 
'try' statement.


I personally don't mind the 'then' as my brain has been hard-coded to 
mean the first branch of a statement so it's looser than being 
explicitly associated with 'if' but with any multi-clause statement.


I read *except* as 'except if', and *:* as 'then' (often), so the main 
proposal reads naturally to me.  I'm surprised to find others don't 
also, as that's the (only?) pronunciation that makes the familiar 
if-else and try-except constructs approximate English.


Isn't adding a new keyword (*then*) likely to be a big deal? There is 
the odd example of its use as an identifier, just in our test code:

http://hg.python.org/cpython/file/0695e465affe/Lib/test/test_epoll.py#l168
http://hg.python.org/cpython/file/0695e465affe/Lib/test/test_xmlrpc.py#l310

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-22 Thread Tim Delaney
On 23 February 2014 02:29, Nick Coghlan ncogh...@gmail.com wrote:

 On 22 Feb 2014 22:15, Stephen J. Turnbull step...@xemacs.org wrote:
  Antoine Pitrou writes:
Chris Angelico ros...@gmail.com wrote:
 hasattr(x,y) - (x.y or True except AttributeError: False)
But it's not the same. hasattr() returns a boolean, not an arbitrary
value.
  I think he meant
  hasattr(x,y) - (x.y and True except AttributeError: False)

 With PEP 463, the explicit equivalent of hasattr() would be something like
 :

 hasattr(x,y) - (bool(x.y) or True except AttributeError: False)

That would work, but I think I'd prefer:

hasattr(x,y) - bool(x.y or True except AttributeError: False)

Makes it clearer IMO that the entire expression will always return a
boolean.

If exception expressions already existed in the language, I would think
there would be a strong argument for a library function hasattr(), but
probably not a builtin.

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-22 Thread Nikolaus Rath
Stephen J. Turnbull step...@xemacs.org writes:
 Ethan Furman writes:
   On 02/21/2014 07:46 PM, Chris Angelico wrote:
   
but not this:
   
value = expr except Exception: default except Exception: default
   
   This should be the way it works.  Nothing is gained in readability
   by turning a try with multiple except statements into an
   expression.

 Examples have been given several times.  In general, if 'expr' is a
 function call, it may well have a couple of different ways to fail
 which imply different default values.

 interpolable = func(key) except TypeError: not a string: %s % key \
  except KeyError: no such key: %s % key
 print(Some message that refers to '%s' % interpolable)

 versus

 try:
 interpolable = func(key)
 except TypeError:
 interpolable = not a string: %s % key
 except KeyError:
 interpolable = no such key: %s % key
 print(Some message that refers to '%s' % interpolable)

I think the following suggestion from elsewhere in the thread would look
even better in this case:

 interpolable = func(key) except (TypeError: not a string: %s % key,
  KeyError: no such key: %s % key)
 print(Some message that refers to '%s' % interpolable)

 
It does not require the backslash, it is shorter, and it can still be
chained:

 interpolable = func(key) except (TypeError: not a string: %s % key,
  KeyError: defaults[key]
  except (KeyError: no such key: %s % 
key))
 print(Some message that refers to '%s' % interpolable)

Best,
-Nikolaus

-- 
Encrypted emails preferred.
PGP fingerprint: 5B93 61F8 4EA2 E279 ABF6  02CF A9AD B7F8 AE4E 425C

 »Time flies like an arrow, fruit flies like a Banana.«
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-22 Thread Stephen J. Turnbull
Antoine Pitrou writes:

  Sure, but complaining about inefficiencies without asserting their
  significance is not very useful.

Since you completely missed the point of my post, I'll explain.  I was
in no way complaining about inefficiencies.

My point was precisely the opposite: to the extent that most 'get'
methods would be implemented in Python, even the minor inefficiency of
creating and suppressing a useless exception can't be avoided with the
LBYL of a get method, because haveattr itself is implemented by
generating and suppressing an exception.

I know that it's not a big deal[1], but it did help swing me to
positive on this PEP.


Footnotes: 
[1]  If it were, somebody would have reimplemented haveattr to avoid
generating an exception.

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-22 Thread Thomas Wouters
On Sat, Feb 22, 2014 at 2:08 AM, Thomas Wouters tho...@python.org wrote:



 (FWIW, I have a working patch without tests that allows all of these, I'll
 upload it tonight so people can play with it. Oh, and FWIW, currently I'm
 +0 on the idea, -0 on the specific syntax.)


http://bugs.python.org/issue20739 is the patch.

-- 
Thomas Wouters tho...@python.org

Hi! I'm an email virus! Think twice before sending your email to help me
spread!
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-22 Thread Chris Angelico
On Sun, Feb 23, 2014 at 11:00 AM, Thomas Wouters tho...@python.org wrote:
 On Sat, Feb 22, 2014 at 2:08 AM, Thomas Wouters tho...@python.org wrote:

 (FWIW, I have a working patch without tests that allows all of these, I'll
 upload it tonight so people can play with it. Oh, and FWIW, currently I'm +0
 on the idea, -0 on the specific syntax.)


 http://bugs.python.org/issue20739 is the patch.

Thanks!

You make a comment about precedence. When I wrote that up, it was
basically just that seems about right; whether it's equal to lambda,
equal to if/else, above both, below both, or in between, is free to be
tweaked according to what makes sense. Nobody has to date discussed
the exact precedence order, so feel free to tweak it for the benefit
of implementation.

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-22 Thread MRAB

On 2014-02-23 00:09, Chris Angelico wrote:
 On Sun, Feb 23, 2014 at 11:00 AM, Thomas Wouters tho...@python.org
 wrote:
 On Sat, Feb 22, 2014 at 2:08 AM, Thomas Wouters tho...@python.org
 wrote:

 (FWIW, I have a working patch without tests that allows all of
 these, I'll upload it tonight so people can play with it. Oh, and
 FWIW, currently I'm +0 on the idea, -0 on the specific syntax.)


 http://bugs.python.org/issue20739 is the patch.

 Thanks!

 You make a comment about precedence. When I wrote that up, it was
 basically just that seems about right; whether it's equal to
 lambda, equal to if/else, above both, below both, or in between, is
 free to be tweaked according to what makes sense. Nobody has to date
 discussed the exact precedence order, so feel free to tweak it for
 the benefit of implementation.

My feeling is that catching exceptions should have a lower precedence
than the other parts of an expression, but higher than comma, so:

A if C else B except E: D

would be parsed as:

(A if C else B) except E: D

I think that's because it's kind of replacing:

try:
_ = expr
except E:
_ = D

with the try..except enclosing the expression.

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-22 Thread Nick Coghlan
On 23 February 2014 11:11, MRAB pyt...@mrabarnett.plus.com wrote:
 On 2014-02-23 00:09, Chris Angelico wrote:
 On Sun, Feb 23, 2014 at 11:00 AM, Thomas Wouters tho...@python.org
 wrote:
 On Sat, Feb 22, 2014 at 2:08 AM, Thomas Wouters tho...@python.org
 wrote:

 (FWIW, I have a working patch without tests that allows all of
 these, I'll upload it tonight so people can play with it. Oh, and
 FWIW, currently I'm +0 on the idea, -0 on the specific syntax.)


 http://bugs.python.org/issue20739 is the patch.

 Thanks!

 You make a comment about precedence. When I wrote that up, it was
 basically just that seems about right; whether it's equal to
 lambda, equal to if/else, above both, below both, or in between, is
 free to be tweaked according to what makes sense. Nobody has to date
 discussed the exact precedence order, so feel free to tweak it for
 the benefit of implementation.

 My feeling is that catching exceptions should have a lower precedence
 than the other parts of an expression, but higher than comma, so:

 A if C else B except E: D

 would be parsed as:

 (A if C else B) except E: D

 I think that's because it's kind of replacing:

 try:
 _ = expr
 except E:
 _ = D

 with the try..except enclosing the expression.

Note that mandatory parentheses means we can duck the precedence
question entirely, which I count as another point in favour of
requiring them :)

Cheers,
Nick.

-- 
Nick Coghlan   |   ncogh...@gmail.com   |   Brisbane, Australia
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-21 Thread Nick Coghlan
On 21 February 2014 13:15, Chris Angelico ros...@gmail.com wrote:
 PEP: 463
 Title: Exception-catching expressions
 Version: $Revision$
 Last-Modified: $Date$
 Author: Chris Angelico ros...@gmail.com
 Status: Draft
 Type: Standards Track
 Content-Type: text/x-rst
 Created: 15-Feb-2014
 Python-Version: 3.5
 Post-History: 16-Feb-2014, 21-Feb-2014


 Abstract
 

 Just as PEP 308 introduced a means of value-based conditions in an
 expression, this system allows exception-based conditions to be used
 as part of an expression.

Great work on this Chris - this is one of the best researched and
justified Python syntax proposals I've seen :)

 Open Issues
 ===

 Parentheses around the entire expression
 

 Generator expressions require parentheses, unless they would be
 strictly redundant.  Ambiguities with except expressions could be
 resolved in the same way, forcing nested except-in-except trees to be
 correctly parenthesized and requiring that the outer expression be
 clearly delineated.  `Steven D'Aprano elaborates on the issue.`__

 __ https://mail.python.org/pipermail/python-ideas/2014-February/025647.html

I'd like to make the case that the PEP should adopt this as its
default position. My rationale is mainly that if we start by requiring
the parentheses, it's pretty straightforward to take that requirement
away in specific cases later, as well as making it easier to introduce
multiple except clauses if that ever seems necessary.

However, if we start without the required parentheses, that's it - we
can't introduce a requirement for parentheses later if we decide the
bare form is too confusing in too many contexts, and there's plenty of
potential for such confusion.

In addition to the odd interactions with other uses of the colon as a
marker in the syntax, including suite headers, lambdas and function
annotations, omitting the parentheses makes it harder to decide which
behaviour was intended in ambiguous cases, while the explicit
parentheses would force the writer to be clear which one they meant.
Consider:

x = get_value() except NotFound: foo is not None

There are two plausible interpretations of that:

x = (get_value() except NotFound: foo) is not None
x = get_value() except NotFound: (foo is not None)

With the proposed precedence in the PEP (which I agree with), the
latter is the correct interpretation, but that's not at all obvious to
the reader - they would have to just know that's the way it works.
By contrast, if the parentheses are required, then the spelling would
have to be one of the following to be legal:

x = (get_value() except NotFound: foo is not None)
x = (get_value() except NotFound: foo) is not None

Which means the : and the closing ) nicely bracket the fallback
value in both cases and make the author's intent relatively clear.

The required parentheses also help in the cases where there is a
nearby colon with a different meaning:

   if check() except Exception: False:
...
   if (check() except Exception: False):
...

   lambda x: calculate(x) except Exception: None
   lambda x: (calculate(x) except Exception: None)

   def f(a: OS dependent = os_defaults[os.name] except KeyError: None): pass
   def f(a: OS dependent = (os_defaults[os.name] except KeyError: None)): pass

Rather than making people consider do I need the parentheses in this
case or not?, adopting the genexp rule makes it simple: yes, you need
them, because the compiler will complain if you leave them out.

 Retrieving a message from either a cache or the internet, with auth
 check::

 logging.info(Message shown to user: %s,((cache[k]
 except LookupError:
 (backend.read(k) except OSError: 'Resource not available')
 )
 if check_permission(k) else 'Access denied'
 ) except BaseException: This is like a bare except clause)

I don't think taking it all the way to one expression shows the new
construct in the best light. Keeping this as multiple statements
assigning to a temporary variable improves the readability quite a
bit:

if not check_permission(k):
msg = 'Access denied'
else:
msg = (cache[k] except LookupError: None)
if msg is None:
msg = (backend.read(k) except OSError: 'Resource not available')

logging.info(Message shown to user: %s, msg)

I would also move the bare except clause equivalent out to a
separate example. Remember, you're trying to convince people to *like*
the PEP, not scare them away with the consequences of what happens
when people try to jam too much application logic into a single
statement. While we're admittedly giving people another tool to help
them win obfuscated Python contests, we don't have to *encourage* them
:)

 try:
 if check_permission(k):
 try:
 _ = cache[k]
 except LookupError:
 try:
 _ = backend.read(k)
  

Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-21 Thread Paul Moore
On 21 February 2014 11:35, Nick Coghlan ncogh...@gmail.com wrote:
 Just as PEP 308 introduced a means of value-based conditions in an
 expression, this system allows exception-based conditions to be used
 as part of an expression.

 Great work on this Chris - this is one of the best researched and
 justified Python syntax proposals I've seen :)

Agreed - given the number of differing opinions on python-ideas, it's
particularly impressive how well the debate was conducted too.

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-21 Thread Chris Angelico
On Fri, Feb 21, 2014 at 10:35 PM, Nick Coghlan ncogh...@gmail.com wrote:
 On 21 February 2014 13:15, Chris Angelico ros...@gmail.com wrote:
 PEP: 463
 Title: Exception-catching expressions
 Great work on this Chris - this is one of the best researched and
 justified Python syntax proposals I've seen :)

It is? Wow... I'm not sure what that says about other syntax
proposals. This is one week's python-ideas discussion plus one little
script doing analysis on the standard library. Hardly PhD level
research :)

 Parentheses around the entire expression
 

 Generator expressions require parentheses, unless they would be
 strictly redundant.  Ambiguities with except expressions could be
 resolved in the same way, forcing nested except-in-except trees to be
 correctly parenthesized and requiring that the outer expression be
 clearly delineated.  `Steven D'Aprano elaborates on the issue.`__

 __ https://mail.python.org/pipermail/python-ideas/2014-February/025647.html

 I'd like to make the case that the PEP should adopt this as its
 default position. My rationale is mainly that if we start by requiring
 the parentheses, it's pretty straightforward to take that requirement
 away in specific cases later, as well as making it easier to introduce
 multiple except clauses if that ever seems necessary.

 However, if we start without the required parentheses, that's it - we
 can't introduce a requirement for parentheses later if we decide the
 bare form is too confusing in too many contexts, and there's plenty of
 potential for such confusion.

If once the parens are made mandatory, they'll most likely stay
mandatory forever - I can't imagine there being any strong impetus to
change the language to make them optional.

 The required parentheses also help in the cases where there is a
 nearby colon with a different meaning:

if check() except Exception: False:
 ...
if (check() except Exception: False):

People can already write:

if (x if y else z):

without the parens, and it works. Readability suffers when the same
keyword is used twice (here if rather than the colon, but same
difference), yet the parens are considered optional. Python is a
language that, by and large, lacks syntactic salt; style guides are
free to stipulate more, but the language doesn't make demands. I would
strongly *recommend* using parens in all the cases you've shown,
especially lambda:

lambda x: calculate(x) except Exception: None
lambda x: (calculate(x) except Exception: None)

as it would otherwise depend on operator precedence; but mandating
them feels to me like demanding readability.

def f(a: OS dependent = os_defaults[os.name] except KeyError: None): pass
def f(a: OS dependent = (os_defaults[os.name] except KeyError: None)): 
 pass

Ehh, that one's a mess. I'd be looking at breaking out the default:

default = os_defaults[os.name] except KeyError: None
def f(a: OS dependent = default): pass

with possibly some better name than 'default'. The one-liner is almost
80 characters long without indentation and with very short names. But
if it's okay to wrap it, that would work without the parens:

def f(
a: OS dependent = os_defaults[os.name] except KeyError: None,
another_arg .,
more, args ..,
):
pass

Clarity is maintained by judicious placement of newlines just as much
as by parentheses.

 Rather than making people consider do I need the parentheses in this
 case or not?, adopting the genexp rule makes it simple: yes, you need
 them, because the compiler will complain if you leave them out.

Yes, that is a reasonable line of argument. On the other hand, there's
no demand for parens when you mix and and or:

x or y and z

I'd wager more than half of Python programmers would be unable to say
for sure which would be evaluated first. The compiler could have been
written to reject this (by placing and and or at the same precedence
and having no associativity - I'm not sure if the current lexer in
CPython can do that, but it's certainly not conceptually
inconceivable), but a decision was made to make this legal.

 Retrieving a message from either a cache or the internet, with auth
 check::

 logging.info(Message shown to user: %s,((cache[k]
 except LookupError:
 (backend.read(k) except OSError: 'Resource not available')
 )
 if check_permission(k) else 'Access denied'
 ) except BaseException: This is like a bare except clause)

 I don't think taking it all the way to one expression shows the new
 construct in the best light. Keeping this as multiple statements
 assigning to a temporary variable improves the readability quite a
 bit:

Yeah, good point. I tried to strike a balance between simple and
complex examples, but it's hard to judge.

 I would also move the bare except clause equivalent out to a
 separate example. Remember, you're trying to convince people to *like*
 the PEP, not scare them away with 

Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-21 Thread Chris Angelico
On Fri, Feb 21, 2014 at 11:37 PM, Paul Moore p.f.mo...@gmail.com wrote:
 On 21 February 2014 11:35, Nick Coghlan ncogh...@gmail.com wrote:
 Just as PEP 308 introduced a means of value-based conditions in an
 expression, this system allows exception-based conditions to be used
 as part of an expression.

 Great work on this Chris - this is one of the best researched and
 justified Python syntax proposals I've seen :)

 Agreed - given the number of differing opinions on python-ideas, it's
 particularly impressive how well the debate was conducted too.

On that subject, I'd like to thank everyone involved in the
python-ideas discussion, and particularly Steven D'Aprano, Rob Cliffe,
and Andrew Barnert; it was an amazingly productive thread, getting to
nearly four hundred emails before seriously meandering. And even then,
it mostly just started looping back on itself, which isn't surprising
given that it was so long - anyone not majorly invested in the topic
won't have read every single post.

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-21 Thread Nick Coghlan
On 21 February 2014 22:42, Chris Angelico ros...@gmail.com wrote:
 It'd be a backward-incompatible change, but it's more likely to be
 what people expect. The general assumption of with ... as ... is
 that the thing should be used inside the block, and should be finished
 with when you exit the block, so having the name valid only inside the
 block does make sense.

 That's a completely separate proposal. But suppose that were to
 happen, and to not require a closure. It would then make good sense to
 be able to capture an exception inside an expression - and it could be
 done without breaking anything.

 So, if it is to be rejected, I'd say it's on the technical grounds
 that it would require a closure in CPython, and that a closure is
 incompatible with the current proposal. Does that sound right?

 (It's also not a huge loss, since it's almost unused. But it's an
 incompatibility between statement and expression form.)

It's probably OK to leave it in the deferred section and just note the
difficulty of implementing it in a backwards compatible way, since
we're *not* going to be introducing a closure. Python 3 except clauses
are already a bit weird anyway, since they do an implicit delete at
the end, but only if the except clause is actually triggered:


 e = Hello
 try:
... 1/0
... except ZeroDivisionError as e:
... pass
...
 e
Traceback (most recent call last):
  File stdin, line 1, in module
NameError: name 'e' is not defined
 e = Hello
 try:
... pass
... except Exception as e:
... pass
...
 e
'Hello'

Cheers,
Nick.

-- 
Nick Coghlan   |   ncogh...@gmail.com   |   Brisbane, Australia
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-21 Thread Antoine Pitrou
On Fri, 21 Feb 2014 14:15:59 +1100
Chris Angelico ros...@gmail.com wrote:
 
 A number of functions and methods have parameters which will cause
 them to return a specified value instead of raising an exception.  The
 current system is ad-hoc and inconsistent, and requires that each
 function be individually written to have this functionality; not all
 support this.

While I sympathize with the motivation, I really don't like the end
result:

 lst = [1, 2]
 value = lst[2] except IndexError: No value

is too much of a break from the usual stylistic conventions, and looks
like several statements were stuffed on a single line.

In other words, the gain in concision is counterbalanced by a loss in
readability, a compromise which doesn't fit in Python's overall design
principles.

(compare with with, which solves actual readability issues due to the
distance between the try and the finally clause, and also promotes
better resource management)

So -0.5 from me.

Regards

Antoine.


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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-21 Thread Nick Coghlan
On 21 February 2014 22:42, Chris Angelico ros...@gmail.com wrote:
 People can already write:

 if (x if y else z):

 without the parens, and it works. Readability suffers when the same
 keyword is used twice (here if rather than the colon, but same
 difference), yet the parens are considered optional. Python is a
 language that, by and large, lacks syntactic salt; style guides are
 free to stipulate more, but the language doesn't make demands. I would
 strongly *recommend* using parens in all the cases you've shown,
 especially lambda:

lambda x: calculate(x) except Exception: None
lambda x: (calculate(x) except Exception: None)

 as it would otherwise depend on operator precedence; but mandating
 them feels to me like demanding readability.

Right, that's why my main motivation for this suggestion is the one
relating to keeping future options open. If the parentheses are
optional, than adding multiple except clauses latter isn't possible,
since this would already be valid, but mean something different:

expr except Exception1: default1 except Exception2: default2

The deferral currently has this snippet:

In order to ensure compatibility with future versions, ensure that
any consecutive except operators are parenthesized to guarantee the
interpretation you expect.

That's not a reasonable expectation - either the parentheses have to
be mandatory as part of the deferral, or else multiple except clause
support needs to be listed as rejected rather than deferred.

Cheers,
Nick.

-- 
Nick Coghlan   |   ncogh...@gmail.com   |   Brisbane, Australia
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-21 Thread Rob Cliffe

My 2 cents worth:


On 21/02/2014 12:42, Chris Angelico wrote:

On Fri, Feb 21, 2014 at 10:35 PM, Nick Coghlan ncogh...@gmail.com wrote:

Great work on this Chris - this is one of the best researched and
justified Python syntax proposals I've seen :)

Hear, hear!  (Praise from the praiseworthy is praise indeed - Tolkien.)

Small point: in one of your examples you give a plug for the PEP note 
the DRY improvement.

I would suggest that similarly
perhaps in your Lib/tarfile.py:2198 example you point out the 
increase in readability due to the 2 lines lining up
in your Lib/ipaddress.py:343 example you point out that the new 
form is probably an improvement (i.e. probably closer to the author's 
intention) as it will NOT catch an AttributeError evaluating 
ips.append (this would matter e.g. if append were mis-spelt).  YOU 
are clearly aware of this but it would often escape the casual reader.

Retrieving a message from either a cache or the internet, with auth
check::

 logging.info(Message shown to user: %s,((cache[k]
 except LookupError:
 (backend.read(k) except OSError: 'Resource not available')
 )
 if check_permission(k) else 'Access denied'
 ) except BaseException: This is like a bare except clause)

I don't think taking it all the way to one expression shows the new
construct in the best light. Keeping this as multiple statements
assigning to a temporary variable improves the readability quite a
bit:
I agree, it looks scary (too many branches in one statement).  The 
shorter the example, the more convincing.

Yeah, good point. I tried to strike a balance between simple and
complex examples, but it's hard to judge.



Capturing the exception object
--

An examination of the Python standard library shows that, while the use
of 'as' is fairly common (occurring in roughly one except clause in five),
it is extremely *uncommon* in the cases which could logically be converted
into the expression form.  Its few uses can simply be left unchanged.
Consequently, in the interests of simplicity, the 'as' clause is not
included in this proposal.  A subsequent Python version can add this without
breaking any existing code, as 'as' is already a keyword.

We can't defer this one - if we don't implement it now, we should
reject it as a future addition. The reason we can't defer it is
[ chomped for brevity ]

So I think it makes more sense to reject this subproposal outright -
it makes the change more complex and make the handling of the common
case worse, for the sake of something that will almost never be an
appropriate thing to do.

Thanks for looking into this Nick.
I confess I don't entirely understand the technical argument (my 
understanding breaks down at the subexpressions can't see the class 
level variables, but I don't want to waste anybody's time expecting an 
explanation, I can always look into it myself) but I accept that there 
is a good reason for disallowing 'as' and its usage would be rare, so I 
will (slightly regretfully) wave it goodbye.





So, if it is to be rejected, I'd say it's on the technical grounds
that it would require a closure in CPython, and that a closure is
incompatible with the current proposal. Does that sound right?

It does to me FWIW.


(It's also not a huge loss, since it's almost unused. But it's an
incompatibility between statement and expression form.)

ChrisA
Assuming the PEP is accepted (not a trivial assumption!)  I hope that at 
some stage allowing multiple except clauses (to trap different 
exceptions raised by the original expression) will be reinstated.  But I 
have to accept that it would be rarely used.


To my mind the real unsung hero of this story is the existing try ... 
except ... finally syntax and its flexibility.  In my code base there 
were a few hundred of these, but just over a dozen where the new syntax 
would be appropriate.  (Hope I'm not starting to argue against the PEP!)

Rob Cliffe

___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/rob.cliffe%40btinternet.com


-
No virus found in this message.
Checked by AVG - www.avg.com
Version: 2012.0.2247 / Virus Database: 3705/6611 - Release Date: 02/20/14




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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-21 Thread Nick Coghlan
On 22 February 2014 00:03, Eli Bendersky eli...@gmail.com wrote:
 On Thu, Feb 20, 2014 at 7:15 PM, Chris Angelico ros...@gmail.com wrote:

 PEP: 463
 Title: Exception-catching expressions
 Version: $Revision$
 Last-Modified: $Date$
 Author: Chris Angelico ros...@gmail.com
 Status: Draft
 Type: Standards Track
 Content-Type: text/x-rst
 Created: 15-Feb-2014
 Python-Version: 3.5
 Post-History: 16-Feb-2014, 21-Feb-2014


 Abstract
 

 Just as PEP 308 introduced a means of value-based conditions in an
 expression, this system allows exception-based conditions to be used
 as part of an expression.



 Chris, while I also commend you for the comprehensive PEP, I'm -1 on the
 proposal, for two main reasons:

 1. Many proposals suggest new syntax to gain some succinctness. Each has to
 be judged for its own merits, and in this case IMHO the cons eclipse the
 pros. I don't think this will save a lot of code in a typical
 well-structured program - maybe a few lines out of hundreds. On the other
 hand, it adds yet another syntax to remember and understand, which is not
 the Pythonic way.

 2. Worse, this idea subverts exceptions to control flow, which is not only
 un-Pythonic but also against the accepted practices of programming in
 general. Here, the comparison to PEP 308 is misguided. PEP 308, whatever
 syntax it adds, still remains within the domain of normal control flow. PEP
 463, OTOH, makes it deliberately easy to make exceptions part of
 non-exceptional code, encouraging very bad programming practices.

Neither of these objections addresses the problems with the status quo, though:

- the status quo encourages overbroad exception handling (as
illustrated by examples in the PEP)
- the status quo encourages an ad hoc approach to hiding exception
handling inside functions

PEP 308 was accepted primarily because the and/or hack was a bug
magnet. The status quo for exception handling is both a bug magnet
(due to overbroad exception handlers), and a cause of creeping
complexity in API design (as more and more APIs, both in the standard
library and elsewhere, acquire ways to request implicit exception
handling).

That's why the comparison to PEP 308 is appropriate: it's less about
making the language better directly, and more about deciding the
consequences of not having it are no longer acceptable.

Cheers,
Nick.

-- 
Nick Coghlan   |   ncogh...@gmail.com   |   Brisbane, Australia
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-21 Thread Brett Cannon
On Fri, Feb 21, 2014 at 8:52 AM, Antoine Pitrou solip...@pitrou.net wrote:

 On Fri, 21 Feb 2014 14:15:59 +1100
 Chris Angelico ros...@gmail.com wrote:
 
  A number of functions and methods have parameters which will cause
  them to return a specified value instead of raising an exception.  The
  current system is ad-hoc and inconsistent, and requires that each
  function be individually written to have this functionality; not all
  support this.

 While I sympathize with the motivation, I really don't like the end
 result:

  lst = [1, 2]
  value = lst[2] except IndexError: No value

 is too much of a break from the usual stylistic conventions, and looks
 like several statements were stuffed on a single line.

 In other words, the gain in concision is counterbalanced by a loss in
 readability, a compromise which doesn't fit in Python's overall design
 principles.

 (compare with with, which solves actual readability issues due to the
 distance between the try and the finally clause, and also promotes
 better resource management)


While I like the general concept, I agree that it looks too much like a
crunched statement; the use of the colon is a non-starter for me. I'm sure
I'm not the only one whose brain has been trained to view a colon in Python
to mean statement, period. This goes against that syntactic practice and
just doesn't work for me.

I'm -1 with the current syntax, but it can go into the + range if a better
syntax can be chosen.
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-21 Thread Eli Bendersky
On Fri, Feb 21, 2014 at 6:28 AM, Nick Coghlan ncogh...@gmail.com wrote:

 On 22 February 2014 00:03, Eli Bendersky eli...@gmail.com wrote:
  On Thu, Feb 20, 2014 at 7:15 PM, Chris Angelico ros...@gmail.com
 wrote:
 
  PEP: 463
  Title: Exception-catching expressions
  Version: $Revision$
  Last-Modified: $Date$
  Author: Chris Angelico ros...@gmail.com
  Status: Draft
  Type: Standards Track
  Content-Type: text/x-rst
  Created: 15-Feb-2014
  Python-Version: 3.5
  Post-History: 16-Feb-2014, 21-Feb-2014
 
 
  Abstract
  
 
  Just as PEP 308 introduced a means of value-based conditions in an
  expression, this system allows exception-based conditions to be used
  as part of an expression.
 
 
 
  Chris, while I also commend you for the comprehensive PEP, I'm -1 on the
  proposal, for two main reasons:
 
  1. Many proposals suggest new syntax to gain some succinctness. Each has
 to
  be judged for its own merits, and in this case IMHO the cons eclipse the
  pros. I don't think this will save a lot of code in a typical
  well-structured program - maybe a few lines out of hundreds. On the other
  hand, it adds yet another syntax to remember and understand, which is not
  the Pythonic way.
 
  2. Worse, this idea subverts exceptions to control flow, which is not
 only
  un-Pythonic but also against the accepted practices of programming in
  general. Here, the comparison to PEP 308 is misguided. PEP 308, whatever
  syntax it adds, still remains within the domain of normal control flow.
 PEP
  463, OTOH, makes it deliberately easy to make exceptions part of
  non-exceptional code, encouraging very bad programming practices.

 Neither of these objections addresses the problems with the status quo,
 though:

 - the status quo encourages overbroad exception handling (as
 illustrated by examples in the PEP)
 - the status quo encourages an ad hoc approach to hiding exception
 handling inside functions


I think the PEP, and your reply, focuses too much on one single status
quo situation, which is the dict.get-like usage. However, the PEP does not
propose a narrow solution - it proposes a significant change in the way
expressions may be written and exceptions may be caught, and thus opens a
can of worms. Even if the status quo will be made better by it, and even
this I'm not sure about (*), many many other possibilities of bad code open
up.

(*) IMHO it's better to hide these exceptions inside well defined functions
-- because dict.get tells me it's the normal code flow, not the exceptional
code flow. On the other hand, the syntax proposed herein tells me - yeah
it's the exceptional code flow, but let me merge it into the normal code
flow for you.

This goes against anything I understand about how exceptions should and
should not be used.

Eli





 PEP 308 was accepted primarily because the and/or hack was a bug
 magnet. The status quo for exception handling is both a bug magnet
 (due to overbroad exception handlers), and a cause of creeping
 complexity in API design (as more and more APIs, both in the standard
 library and elsewhere, acquire ways to request implicit exception
 handling).

 That's why the comparison to PEP 308 is appropriate: it's less about
 making the language better directly, and more about deciding the
 consequences of not having it are no longer acceptable.


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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-21 Thread Nick Coghlan
On 22 February 2014 00:37, Eli Bendersky eli...@gmail.com wrote:
 This goes against anything I understand about how exceptions should and
 should not be used.

I think you're thinking of a language that isn't Python - we use
exceptions for control flow all over the place (it's how hasattr() is
*defined*, for example).

Cheers,
Nick.

-- 
Nick Coghlan   |   ncogh...@gmail.com   |   Brisbane, Australia
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-21 Thread Eli Bendersky
On Fri, Feb 21, 2014 at 6:46 AM, Nick Coghlan ncogh...@gmail.com wrote:

 On 22 February 2014 00:37, Eli Bendersky eli...@gmail.com wrote:
  This goes against anything I understand about how exceptions should and
  should not be used.

 I think you're thinking of a language that isn't Python - we use
 exceptions for control flow all over the place (it's how hasattr() is
 *defined*, for example).


No, it is Python I'm thinking about. As I mentioned in the reply to Brett's
message, I see a difference between allowing exceptions on expression level
and statement level. The latter is less likely to be abused. Once you add
exceptions into expressions, all bets are off.

For instance, it is sometime non-trivial to know which exceptions some
function may throw. When you write a try...raise statement, you think hard
about covering all the bases. In an expression you're unlikely to, which
opens up a lot of possibilities for bugs. Again, please stop focusing just
on the list[index] case -- the proposal adds a new significant feature to
the language that can (and thus will) be used in a variety of scenarios.

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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-21 Thread Antoine Pitrou
On Sat, 22 Feb 2014 00:28:01 +1000
Nick Coghlan ncogh...@gmail.com wrote:
 
 Neither of these objections addresses the problems with the status quo, 
 though:
 
 - the status quo encourages overbroad exception handling (as
 illustrated by examples in the PEP)

I don't get this. Using the proper exception class in a try...except
suite is no more bothersome than using the proper exception class in
this newly-proposed construct.

Regards

Antoine.


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


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-21 Thread Nick Coghlan
On 22 February 2014 00:44, Eli Bendersky eli...@gmail.com wrote:
 True, but at least you still have to explicitly try...except... which takes
 a toll on the code so isn't taken lightly. Adding except into expressions, I
 fear, will proliferate this usage much more.

The same fears were raised regarding conditional expressions, and
they'll be dealt with the same way: style guides and code review.

That's also why the examples part of the PEP is so important, though:
this is about providing a tool to *improve* readability in the cases
where it applies, without significantly increasing the cognitive
burden of the language.

One example not mentioned in the PEP is that text.find(substr) would
become just a shorthand for text.index(substr) except ValueError:
-1, but the latter has the benefit that you can substitute None
instead, which avoids the trap where -1 is a valid subscript for the
string (but doesn't give you the answer you want).

Cheers,
Nick.

-- 
Nick Coghlan   |   ncogh...@gmail.com   |   Brisbane, Australia
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-21 Thread Chris Angelico
On Sat, Feb 22, 2014 at 12:53 AM, Nick Coghlan ncogh...@gmail.com wrote:
 On 21 February 2014 22:42, Chris Angelico ros...@gmail.com wrote:
 People can already write:

 if (x if y else z):

 without the parens, and it works. Readability suffers when the same
 keyword is used twice (here if rather than the colon, but same
 difference), yet the parens are considered optional. Python is a
 language that, by and large, lacks syntactic salt; style guides are
 free to stipulate more, but the language doesn't make demands. I would
 strongly *recommend* using parens in all the cases you've shown,
 especially lambda:

lambda x: calculate(x) except Exception: None
lambda x: (calculate(x) except Exception: None)

 as it would otherwise depend on operator precedence; but mandating
 them feels to me like demanding readability.

 Right, that's why my main motivation for this suggestion is the one
 relating to keeping future options open. If the parentheses are
 optional, than adding multiple except clauses latter isn't possible,
 since this would already be valid, but mean something different:

 expr except Exception1: default1 except Exception2: default2

 The deferral currently has this snippet:

 In order to ensure compatibility with future versions, ensure that
 any consecutive except operators are parenthesized to guarantee the
 interpretation you expect.

 That's not a reasonable expectation - either the parentheses have to
 be mandatory as part of the deferral, or else multiple except clause
 support needs to be listed as rejected rather than deferred.

I've spent the better part of the last hour debating this in my head.
It's basically a question of simplicity versus future flexibility:
either keep the syntax clean and deny the multiple-except-clause
option, or mandate the parens and permit it. The first option has, in
my own head, the stronger case - this is designed for simplicity, and
it wouldn't be that big a deal to completely reject multiple except
clauses and simply require that the
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 463: Exception-catching expressions

2014-02-21 Thread Chris Angelico
On Sat, Feb 22, 2014 at 1:59 AM, Chris Angelico ros...@gmail.com wrote:
 I've spent the better part of the last hour debating this in my head.
 It's basically a question of simplicity versus future flexibility:
 either keep the syntax clean and deny the multiple-except-clause
 option, or mandate the parens and permit it. The first option has, in
 my own head, the stronger case - this is designed for simplicity, and
 it wouldn't be that big a deal to completely reject multiple except
 clauses and simply require that the

Oops, hit the wrong key and sent that half-written.

... and simply require that the statement form be used. But the
whelming opinion of python-dev seems to be in favour of the parens
anyway, and since they give us the possibility of future expansion
effectively for free, I've gone that way. Parens are now required; the
syntax is:

value = (expr except Exception: default)

and, as per genexp rules, redundant parens can be omitted:

print(lst[i] except IndexError: Out of bounds)

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


  1   2   >