[Python-ideas] More descriptive error message than "too many values to unpack"

2020-03-01 Thread Alex Hall
Currently this code:

d = {"key": "value"}
for key, value in d:
pass

produces this error:

ValueError: too many values to unpack (expected 2)

I suggest that the error message should also have:

1. The name of the type of the unpacked value
2. The length of the unpacked value, if it exists and (to not execute arbitrary 
__len__ implementations) if the type belongs to a safe subset, e.g. only 
builtin types.

Then the error message could be:

ValueError: too many values to unpack (expected 2, found 3) from object of type 
str
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/C6QEAEEAELUHMLB23OBRSQK2UYU3AF5O/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: More descriptive error message than "too many values to unpack"

2020-03-01 Thread Chris Angelico
On Sun, Mar 1, 2020 at 11:35 PM Alex Hall  wrote:
>
> Currently this code:
>
> d = {"key": "value"}
> for key, value in d:
> pass
>
> produces this error:
>
> ValueError: too many values to unpack (expected 2)
>
> I suggest that the error message should also have:
>
> 1. The name of the type of the unpacked value
> 2. The length of the unpacked value, if it exists and (to not execute 
> arbitrary __len__ implementations) if the type belongs to a safe subset, e.g. 
> only builtin types.
>
> Then the error message could be:
>
> ValueError: too many values to unpack (expected 2, found 3) from object of 
> type str
>

Adding the type name would be pretty safe to do. Adding the length,
though, is a bit harder. Consider:

>>> def gen():
... for n in range(50):
... print("Yielding", n)
... yield n
...
>>> a, b = gen()
Yielding 0
Yielding 1
Yielding 2
Traceback (most recent call last):
  File "", line 1, in 
ValueError: too many values to unpack (expected 2)

So the only way would be to call len(), and if it fails, fall back on
the "expected 2" form. And I'm not sure if that would be worthwhile,
given that it's going to have to run arbitrary code just for the sake
of the error message.

+0.5 for showing the type name, -0.5 for trying to show the length.

ChrisA
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/J7S35JHCXJVN5PDBIL4GPW2TITHXMR7Y/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: More descriptive error message than "too many values to unpack"

2020-03-01 Thread Alex Hall
Chris Angelico wrote:
> So the only way would be to call len(), and if it fails, fall back
> on
> the "expected 2" form. And I'm not sure if that would be worthwhile,
> given that it's going to have to run arbitrary code just for the sake
> of the error message.

I did address these:

> The length of the unpacked value, if it exists and (to not execute arbitrary 
> __len__ implementations) if the type belongs to a safe subset, e.g. only 
> builtin types.

Is there anyone who thinks it's acceptable to run `len()` on arbitrary objects 
for an error message? Assuming 'no', then the length is only shown if the type 
is exactly one of list, tuple, str, etc. where we know __len__ exists and is 
safe. Alternatively, instead of checking the type, we could check if `__len__` 
itself belongs to a safe set, if we want to include e.g. subclasses of `list`.
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/3MSHVDWV2YPCYLNPTWXAADUBTFNUCXTB/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: More descriptive error message than "too many values to unpack"

2020-03-01 Thread Chris Angelico
On Mon, Mar 2, 2020 at 12:01 AM Alex Hall  wrote:
>
> Chris Angelico wrote:
> > So the only way would be to call len(), and if it fails, fall back
> > on
> > the "expected 2" form. And I'm not sure if that would be worthwhile,
> > given that it's going to have to run arbitrary code just for the sake
> > of the error message.
>
> I did address these:
>
> > The length of the unpacked value, if it exists and (to not execute 
> > arbitrary __len__ implementations) if the type belongs to a safe subset, 
> > e.g. only builtin types.
>
> Is there anyone who thinks it's acceptable to run `len()` on arbitrary 
> objects for an error message? Assuming 'no', then the length is only shown if 
> the type is exactly one of list, tuple, str, etc. where we know __len__ 
> exists and is safe. Alternatively, instead of checking the type, we could 
> check if `__len__` itself belongs to a safe set, if we want to include e.g. 
> subclasses of `list`.
>

It seems very odd to say "built-in types only", IMO (or any other
arbitrary whitelist). It'd be cleaner to either call it regardless of
the type, or just not do that. The inconsistency seems like more
trouble than it's worth.

For your provided use-case, the length is almost irrelevant; the best
way to spot the bug is to see "oh, it was trying to unpack a string,
not a tuple". And that part can be done much more easily and safely.

ChrisA
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/MOM2ZELD6BMVML7AEJ6QMNGYPUFG72I5/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: More descriptive error message than "too many values to unpack"

2020-03-01 Thread Andrew Barnert via Python-ideas
On Mar 1, 2020, at 05:03, Alex Hall  wrote:
> 
> Is there anyone who thinks it's acceptable to run `len()` on arbitrary 
> objects for an error message? Assuming 'no', then the length is only shown if 
> the type is exactly one of list, tuple, str, etc. where we know __len__ 
> exists and is safe. Alternatively, instead of checking the type, we could 
> check if `__len__` itself belongs to a safe set, if we want to include e.g. 
> subclasses of `list`.

IIRC, the new unpacking code still works like the old in that it special-cases 
list and tuple (where it can use the fast indexing API that just accesses the C 
array underneath), but for everything else it calls a function with iter(obj). 
If so, adding the length for list and tuple would be trivial, but adding it for 
other builtin types would not.

Is list and tuple good enough? It won’t help your example use, where it’s str, 
but I think for that case you don’t generally care that the string had 6 chars 
instead of 2; you already know the problem from it being a string in the first 
place. I suspect that almost every time the type is right but the length isn’t, 
the type is list, tuple, or a non-builtin type. How often do you accidentally 
unpack a length-6 dict where you wanted to unpack a length-2 dict?
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/2A2DSFIZDLSMJJ7F5X37BT44YN5RQLDX/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: More descriptive error message than "too many values to unpack"

2020-03-01 Thread Alex Hall
>
> IIRC, the new unpacking code still works like the old in that it
> special-cases list and tuple (where it can use the fast indexing API that
> just accesses the C array underneath), but for everything else it calls a
> function with iter(obj). If so, adding the length for list and tuple would
> be trivial, but adding it for other builtin types would not.
>

Seems you're right:
https://github.com/python/cpython/blob/baf29b221682be0f4fde53a05ea3f57c3c79f431/Python/ceval.c#L2243-L2252


> Is list and tuple good enough? It won’t help your example use, where it’s
> str, but I think for that case you don’t generally care that the string had
> 6 chars instead of 2; you already know the problem from it being a string
> in the first place. I suspect that almost every time the type is right but
> the length isn’t, the type is list, tuple, or a non-builtin type. How often
> do you accidentally unpack a length-6 dict where you wanted to unpack a
> length-2 dict?
>

I agree with all of this, and I think this is a great balance of
implementation complexity and value, especially when the code already
accounts for it.

I've made an issue here: https://bugs.python.org/issue39816?
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/BQEBVV6YBGIRP3YM4U2SPG6W5YOM4FFL/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: More descriptive error message than "too many values to unpack"

2020-03-01 Thread Christopher Barker
the problem here is that "iterable unpacking" (is that what we call it
now?) is pretty general, and used all over python. In the example given, it
seemed that that would be a helpful message, but it wouldn't really solve
the general problem: that is, that dicts iterate over keys, and people
sometimes forget and expect that they are iteration go over the items. but
if your keys happen to be length-2 iterables, then you won't get an error
-- but you will also not get what is likely expected:

In [3]: d = {"ab": 123,
   ...:  "cd": 345}


In [4]: for string, number in d:
   ...: print(string, number)
   ...:

a b
c d

oops!

So, in the general case how helpful is it to provide the type of what is
being unpacked??

(and note that in this case, I (key, value) tuple is expected, and a tuple
is a perfectly valid dict key, too, so again, type isn't
necessarily helpful. Length would be a bit more helpful, but still not
always.

That being said, more information is better than less, so maybe an
unpacking error should show the *value* of what was being unpacked:

>>> a, b = 1, 2, 3
Traceback (most recent call last):
  File "", line 1, in 
ValueError: too many values to unpack (expected 2)

Which, in fact, is what iPython already does:

In [5]: a,b = 1,2,3

---
ValueErrorTraceback (most recent call last)
 in 
> 1 a,b = 1,2,3

ValueError: too many values to unpack (expected 2)

But not in the dict iterating case:

In [2]: for key, val in d:
   ...: print(key, val)
   ...:

---
ValueErrorTraceback (most recent call last)
 in 
> 1 for key, val in d:
  2 print(key, val)
  3

ValueError: too many values to unpack (expected 2)

(cause it's showing the line of code, not the run time values)

So if possible, it would be great if error messages did generally show the
value(s) of the objects involved, if possible.

Then that would be:

ValueError: too many values to unpack (expected 2, got : 'this')

Given that it's a ValueError, it seem the *value* should be known, and
generally relevant.

And this is already done for some ValueErrors:

In [3]: i = int('45f')

---
ValueErrorTraceback (most recent call last)
 in 
> 1 i = int('45f')

ValueError: invalid literal for int() with base 10: '45f'

Maybe it should be for ALL Value Errors?

-CHB

On Sun, Mar 1, 2020 at 11:38 AM Alex Hall  wrote:

> IIRC, the new unpacking code still works like the old in that it
>> special-cases list and tuple (where it can use the fast indexing API that
>> just accesses the C array underneath), but for everything else it calls a
>> function with iter(obj). If so, adding the length for list and tuple would
>> be trivial, but adding it for other builtin types would not.
>>
>
> Seems you're right:
> https://github.com/python/cpython/blob/baf29b221682be0f4fde53a05ea3f57c3c79f431/Python/ceval.c#L2243-L2252
>
>
>> Is list and tuple good enough? It won’t help your example use, where it’s
>> str, but I think for that case you don’t generally care that the string had
>> 6 chars instead of 2; you already know the problem from it being a string
>> in the first place. I suspect that almost every time the type is right but
>> the length isn’t, the type is list, tuple, or a non-builtin type. How often
>> do you accidentally unpack a length-6 dict where you wanted to unpack a
>> length-2 dict?
>>
>
> I agree with all of this, and I think this is a great balance of
> implementation complexity and value, especially when the code already
> accounts for it.
>
> I've made an issue here: https://bugs.python.org/issue39816?
> ___
> Python-ideas mailing list -- python-ideas@python.org
> To unsubscribe send an email to python-ideas-le...@python.org
> https://mail.python.org/mailman3/lists/python-ideas.python.org/
> Message archived at
> https://mail.python.org/archives/list/python-ideas@python.org/message/BQEBVV6YBGIRP3YM4U2SPG6W5YOM4FFL/
> Code of Conduct: http://python.org/psf/codeofconduct/
>


-- 
Christopher Barker, PhD

Python Language Consulting
  - Teaching
  - Scientific Software Development
  - Desktop GUI and Web Development
  - wxPython, numpy, scipy, Cython
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/KMCR2334DJSGBGBLQKTMZMV67ERESPXA/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: More descriptive error message than "too many values to unpack"

2020-03-01 Thread André Roberge
On Sun, Mar 1, 2020 at 6:51 PM Christopher Barker 
wrote:
SNIP

the problem here is that "iterable unpacking" (is that what we call it
> now?) is pretty general, and used all over python.
> ValueError: too many values to unpack (expected 2)
>
> Which, in fact, is what iPython already does:
>
> In [5]: a,b = 1,2,3
>
> ---
> ValueErrorTraceback (most recent call last)
>  in 
> > 1 a,b = 1,2,3
>
> ValueError: too many values to unpack (expected 2)
>
> But not in the dict iterating case:
>
> In [2]: for key, val in d:
>...: print(key, val)
>...:
>
> ---
> ValueErrorTraceback (most recent call last)
>  in 
> > 1 for key, val in d:
>   2 print(key, val)
>   3
>
> ValueError: too many values to unpack (expected 2)
>
> (cause it's showing the line of code, not the run time values)
>
> So if possible, it would be great if error messages did generally show the
> value(s) of the objects involved, if possible.
>
This information is certainly retrievable - but not by standard consoles.

$ python -m friendly_traceback
Friendly Console version 0.0.28a. [Python version: 3.7.3]

>>> d = {"a": 1, "b": 2}
>>> for key, value in d:
...print(key, value)
...

Python exception:
ValueError: not enough values to unpack (expected 2, got 1)

A ValueError indicates that a function or an operation
received an argument of the right type, but an inappropriate value.

Execution stopped on line 1 of file ''.

-->1: for key, value in d:

d: {'a': 1, 'b': 2}


==
André Roberge
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/UIDNB2EZQYVUBHNMDIHJ7CZYKMRM6UJV/
Code of Conduct: http://python.org/psf/codeofconduct/