Re: [Python-Dev] Cherry-pick between Python 3.4 RC2 and final?

2014-03-05 Thread Nick Coghlan
On 5 Mar 2014 12:48, "Larry Hastings"  wrote:
>
> On 03/04/2014 03:59 PM, Barry Warsaw wrote:
>>
>> I too would like an rc3, especially to see if issue 19021 can be fixed,
which
>> I suspect will hit a lot of people.
>
>
> I talked to the other guys on the 3.4 team, and we're all willing to do
an rc3 this weekend.  I'll add that to PEP 429.

Thanks Larry, I just saw that commit. It's genuinely appreciated! :)

> In other news, I'm thrilled to confirm something Antoine mentioned a week
or two ago: it is literally impossible for garden-variety core devs to push
new branches back into trunk.  I tried to, early this morning (PST), with
someone logged in to hg.python.org ready to clean up in case it actually
worked.  But happily hg hooks on the server reject new branches every time.

Ah, *now* I understand your concern - yes, that hook was put in place
during the initial migration to Mercurial, but if you weren't aware of it,
then your desire to keep the release clone offline to prevent erroneous
pushes makes a lot more sense to me :)

> Since this banishes my chief objection to publishing the repo where I do
my cherry picking, I'll be publishing that repo this week.  I think I still
have a rebase ahead of me, so I'm going wait until after the latest (and
hopefully last!) round of cherry-picking.  I'll post to python-dev once the
tree is public.

Sweet, thanks!

Cheers,
Nick.

>
>
> /arry
>
> ___
> Python-Dev mailing list
> [email protected]
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe:
https://mail.python.org/mailman/options/python-dev/ncoghlan%40gmail.com
>
___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Cherry-pick between Python 3.4 RC2 and final?

2014-03-05 Thread Antoine Pitrou

Le 05/03/2014 03:46, Larry Hastings a écrit :

On 03/04/2014 03:59 PM, Barry Warsaw wrote:

I too would like an rc3, especially to see if issue 19021 can be fixed, which
I suspect will hit a lot of people.


I talked to the other guys on the 3.4 team, and we're all willing to do
an rc3 this weekend.  I'll add that to PEP 429.


In other news, I'm thrilled to confirm something Antoine mentioned a
week or two ago: it is literally impossible for garden-variety core devs
to push new branches back into trunk.  I tried to, early this morning
(PST), with someone logged in to hg.python.org ready to clean up in case
it actually worked.  But happily hg hooks on the server reject new
branches every time.


And I thought the hook would be overkill!

Regards

Antoine.


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


[Python-Dev] Reference cycles in Exception.__traceback__

2014-03-05 Thread Victor Stinner
Hi,

Python 3 now stores the traceback object in Exception.__traceback__
and exceptions can be chained through Exception.__context__. It's
convinient but it introduced tricky reference cycles if the exception
object is used out of the except block.

Refrences: Exception.__traceback__ -> traceback -> frames -> local variables

Exception.__traceback__ keeps strong references to local variables
which will only be deleted after the exception is destroyed.

It becomes worse if the exception is stored in an object which is also
a local variables somewhere in the traceback:

DebugObject -> Exception -> ... frame -> DebugObject

For a concrete example of object storing an exception, see
Future.set_exception() of the ayncio module.

Python 3.4 introduced frame.clear(), but frame.clear() raises an
RuntimeError if the frame is still running. And it doesn't break all
reference cycles.

An obvious workaround is to store the traceback as text, but this
operation is "expensive" especially if the traceback is only needed in
rare cases.

I tried to write "views" of the traceback (and frames), but
Exception.__traceback__ rejects types other than traceback and
traceback instances cannot be created. It's possible to store the
traceback somewhere else and set Exception.__traceback__ to None, but
there is still the problem with chained exceptions.

Any idea for a generic fix to such problem?

Another workaround is to set Exception.__traceback__ to None in
release mode, and leaves it unchanged in debug mode. But it's not a
good solution because bugs also occur in production, and most tricky
bugs *only* occur in production :-)

For more info, see:

http://bugs.python.org/issue20032
http://code.google.com/p/tulip/issues/detail?id=42
http://code.google.com/p/tulip/issues/detail?id=155

Victor
___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Reference cycles in Exception.__traceback__

2014-03-05 Thread Antoine Pitrou

Le 05/03/2014 17:37, Victor Stinner a écrit :


Python 3.4 introduced frame.clear(), but frame.clear() raises an
RuntimeError if the frame is still running. And it doesn't break all
reference cycles.

An obvious workaround is to store the traceback as text, but this
operation is "expensive" especially if the traceback is only needed in
rare cases.


Another "obvious" workaround is to call frame.clear() from the parent 
function (i.e. have a dedicated wrapping layer).


Regards

Antoine.


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


Re: [Python-Dev] Reference cycles in Exception.__traceback__

2014-03-05 Thread Yury Selivanov


On 2014-03-05, 11:37 AM, Victor Stinner wrote:

[snip]

I tried to write "views" of the traceback (and frames), but
Exception.__traceback__ rejects types other than traceback and
traceback instances cannot be created. It's possible to store the
traceback somewhere else and set Exception.__traceback__ to None, but
there is still the problem with chained exceptions.



Can we allow instantiation of types.FrameType and
types.TracebackType?  If it's allowed, we can write
a simple code, that will recreate tracebacks with
cleaned-up frames without references to locals etc.

Yury
___
Python-Dev mailing list
[email protected]
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  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 "", line 1, in 
  File "", 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 

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


Re: [Python-Dev] Cherry-pick between Python 3.4 RC2 and final?

2014-03-05 Thread Nick Coghlan
On 6 Mar 2014 01:32, "Antoine Pitrou"  wrote:
>
> Le 05/03/2014 03:46, Larry Hastings a écrit :
>
>> On 03/04/2014 03:59 PM, Barry Warsaw wrote:
>>>
>>> I too would like an rc3, especially to see if issue 19021 can be fixed,
which
>>> I suspect will hit a lot of people.
>>
>>
>> I talked to the other guys on the 3.4 team, and we're all willing to do
>> an rc3 this weekend.  I'll add that to PEP 429.
>>
>>
>> In other news, I'm thrilled to confirm something Antoine mentioned a
>> week or two ago: it is literally impossible for garden-variety core devs
>> to push new branches back into trunk.  I tried to, early this morning
>> (PST), with someone logged in to hg.python.org ready to clean up in case
>> it actually worked.  But happily hg hooks on the server reject new
>> branches every time.
>
>
> And I thought the hook would be overkill!

I found it to be quite a handy failsafe in the early days of using
Mercurial. Haven't triggered it since I set up my separate sandbox repo,
though :)

Cheers,
Nick.

>
> Regards
>
> Antoine.
>
>
>
> ___
> Python-Dev mailing list
> [email protected]
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe:
https://mail.python.org/mailman/options/python-dev/ncoghlan%40gmail.com
___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Reference cycles in Exception.__traceback__

2014-03-05 Thread Nick Coghlan
On 6 Mar 2014 02:43, "Antoine Pitrou"  wrote:
>
> Le 05/03/2014 17:37, Victor Stinner a écrit :
>
>>
>> Python 3.4 introduced frame.clear(), but frame.clear() raises an
>> RuntimeError if the frame is still running. And it doesn't break all
>> reference cycles.
>>
>> An obvious workaround is to store the traceback as text, but this
>> operation is "expensive" especially if the traceback is only needed in
>> rare cases.
>
>
> Another "obvious" workaround is to call frame.clear() from the parent
function (i.e. have a dedicated wrapping layer).

Guido had a fix in mind - splitting traceback formatting into two pieces.
The first would convert a traceback to a sequence of named tuples, the
second would do the actual string formatting.

There's an RFE for it on the tracker, but I don't have a link handy.

Cheers,
Nick.

>
> Regards
>
> Antoine.
>
>
>
> ___
> Python-Dev mailing list
> [email protected]
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe:
https://mail.python.org/mailman/options/python-dev/ncoghlan%40gmail.com
___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Reference cycles in Exception.__traceback__

2014-03-05 Thread Guido van Rossum
I think it was http://bugs.python.org/issue17911


On Wed, Mar 5, 2014 at 1:54 PM, Nick Coghlan  wrote:

>
> On 6 Mar 2014 02:43, "Antoine Pitrou"  wrote:
> >
> > Le 05/03/2014 17:37, Victor Stinner a écrit :
> >
> >>
> >> Python 3.4 introduced frame.clear(), but frame.clear() raises an
> >> RuntimeError if the frame is still running. And it doesn't break all
> >> reference cycles.
> >>
> >> An obvious workaround is to store the traceback as text, but this
> >> operation is "expensive" especially if the traceback is only needed in
> >> rare cases.
> >
> >
> > Another "obvious" workaround is to call frame.clear() from the parent
> function (i.e. have a dedicated wrapping layer).
>
> Guido had a fix in mind - splitting traceback formatting into two pieces.
> The first would convert a traceback to a sequence of named tuples, the
> second would do the actual string formatting.
>
> There's an RFE for it on the tracker, but I don't have a link handy.
>
> Cheers,
> Nick.
>
> >
> > Regards
> >
> > Antoine.
> >
> >
> >
> > ___
> > Python-Dev mailing list
> > [email protected]
> > https://mail.python.org/mailman/listinfo/python-dev
> > Unsubscribe:
> https://mail.python.org/mailman/options/python-dev/ncoghlan%40gmail.com
>
>
> ___
> Python-Dev mailing list
> [email protected]
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe:
> https://mail.python.org/mailman/options/python-dev/guido%40python.org
>
>


-- 
--Guido van Rossum (python.org/~guido)
___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Reference cycles in Exception.__traceback__

2014-03-05 Thread Eric Snow
On Wed, Mar 5, 2014 at 2:54 PM, Nick Coghlan  wrote:
> Guido had a fix in mind - splitting traceback formatting into two pieces.
> The first would convert a traceback to a sequence of named tuples, the
> second would do the actual string formatting.

+1

This is basically how I've handled pickling tracebacks in a project at
work (using 2.7).  You can already using extract_tb() and
format_list() from the traceback module to get the effect.

As to how to use this to avoid holding those references (without
taking a performance hit), that will take some more thought.  :)

-eric
___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Reference cycles in Exception.__traceback__

2014-03-05 Thread Yury Selivanov


On 2014-03-05, 4:54 PM, Nick Coghlan wrote:

On 6 Mar 2014 02:43, "Antoine Pitrou"  wrote:

Le 05/03/2014 17:37, Victor Stinner a écrit :


Python 3.4 introduced frame.clear(), but frame.clear() raises an
RuntimeError if the frame is still running. And it doesn't break all
reference cycles.

An obvious workaround is to store the traceback as text, but this
operation is "expensive" especially if the traceback is only needed in
rare cases.


Another "obvious" workaround is to call frame.clear() from the parent

function (i.e. have a dedicated wrapping layer).

Guido had a fix in mind - splitting traceback formatting into two pieces.
The first would convert a traceback to a sequence of named tuples, the
second would do the actual string formatting.


I don't like the idea of using tuples instead of tracebacks
in 'exception.__traceback__'.  Lots of introspection and logging
tools except to find tracebacks in exceptions, and do custom
formatting or submitting data to remote servers for further
analysis (sometimes with values of local variables in frames).
If asyncio starts stripping exception.__traceback__ and using
namedtuples, it will make it harder to write/integrate such
tools.

Yury
___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Reference cycles in Exception.__traceback__

2014-03-05 Thread Nick Coghlan
On 6 Mar 2014 08:32, "Yury Selivanov"  wrote:
>
>
> On 2014-03-05, 4:54 PM, Nick Coghlan wrote:
>>
>> On 6 Mar 2014 02:43, "Antoine Pitrou"  wrote:
>>>
>>> Le 05/03/2014 17:37, Victor Stinner a écrit :
>>>
 Python 3.4 introduced frame.clear(), but frame.clear() raises an
 RuntimeError if the frame is still running. And it doesn't break all
 reference cycles.

 An obvious workaround is to store the traceback as text, but this
 operation is "expensive" especially if the traceback is only needed in
 rare cases.
>>>
>>>
>>> Another "obvious" workaround is to call frame.clear() from the parent
>>
>> function (i.e. have a dedicated wrapping layer).
>>
>> Guido had a fix in mind - splitting traceback formatting into two pieces.
>> The first would convert a traceback to a sequence of named tuples, the
>> second would do the actual string formatting.
>
>
> I don't like the idea of using tuples instead of tracebacks
> in 'exception.__traceback__'.  Lots of introspection and logging
> tools except to find tracebacks in exceptions, and do custom
> formatting or submitting data to remote servers for further
> analysis (sometimes with values of local variables in frames).
> If asyncio starts stripping exception.__traceback__ and using
> namedtuples, it will make it harder to write/integrate such
> tools.

__traceback__ wouldn't change - this is a variant on Victor's point that it
is currently easy to store the already formatted traceback as a string, but
that wastes time formatting a string you may never display, and is hard to
manipulate programmatically.

Extracting a traceback summary from __traceback__ instead can address both
limitations.

Cheers,
Nick.

>
> Yury
>
> ___
> Python-Dev mailing list
> [email protected]
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe:
https://mail.python.org/mailman/options/python-dev/ncoghlan%40gmail.com
___
Python-Dev mailing list
[email protected]
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  wrote:
> On Thu, Feb 27, 2014 at 1:29 PM, Chris Angelico  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
[email protected]
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  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
[email protected]
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  wrote:

> On Thu, Mar 6, 2014 at 7:57 AM, Thomas Wouters  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 fif

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  wrote:
> PEP update pushed (changeset 59653081cdf6.)
>

Thanks for that!

ChrisA
___
Python-Dev mailing list
[email protected]
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  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 "", line 1, in 
>   File "", 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
[email protected]
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  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 "", line 1, in 
   File "", 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
[email protected]
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
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com