[Python-ideas] Re: dict.sort()?

2021-05-29 Thread Inada Naoki
FWI, this is a previous thread.

https://discuss.python.org/t/add-a-dict-sort-method/5747

2021年5月30日(日) 1:57 Marco Sulla :

> Since `dict` now is ordered, how about a `sort()` method?
> It could have the same signature of list.sort(), with an optional
> parameter "by" that can be "keys" or "values" ("keys" could be the
> default).
> ___
> 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/XXA2E5ILMAEMFLPWZIZN3T67FERJPBFF/
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
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/NLRSYBPC7PZKCRZSROXQTERHDXYEDZMF/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: dict.sort()?

2021-05-29 Thread Steven D'Aprano
On Sat, May 29, 2021 at 06:54:15PM +0200, Marco Sulla wrote:

> Since `dict` now is ordered, how about a `sort()` method?
> It could have the same signature of list.sort(), with an optional
> parameter "by" that can be "keys" or "values" ("keys" could be the
> default).

Dicts keep their insertion order stable, that doesn't mean that they are 
sortable. They aren't lists where you can just reorder items, the 
implementation is more complex than a simple list of (key,value) pairs 
that can be sorted.

My understanding of the implementation is that the only practical way to 
sort a dict is to sort the items ahead of time and then build it.

I don't know the current implementation, but I think it *might* be 
something like Raymond Hettinger's proposal for a compact, 
order-preserving, key-sharing dict:

https://mail.python.org/pipermail/python-dev/2012-December/123028.html

If you can think of a way to sort something like that, without changing 
the way hash lookups work, and more efficiently than just sorting the 
items and building a new dict, remember that the implementation can 
change at any time.

The bottom line here is that *dicts aren't lists* and it doesn't make 
sense to sort them. If you want a sortable data structure, stick to a 
list or a tree, or a specialised data structure designed for the task.


-- 
Steve
___
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/FEKMJ4RBJ2BFHJDTAUJOFJPUVV5KXMDD/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Cleaner tracebacks from Python code

2021-05-29 Thread Paul Sokolovsky
Hello,

On Sat, 29 May 2021 17:29:26 -0300
André Roberge  wrote:

> On Sat, May 29, 2021 at 4:54 PM Irit Katriel 
> wrote:
> 
> >
> > You can control what the traceback of exceptions you are emitting:
> >
> > "raise e.with_traceback(None)" should clear everything before the
> > current frame.
> >  
> 
> I'm sorry, but I still don't see how. This particular line would
> still show up.
> 
> 
> Traceback (most recent call last):
>   File "test.py", line 2, in 
> d = date(2021, 13, 1)
>   File "C:\Users\andre\local_datetime.py", line 852, in __new__
> raise e.with_traceback(None)
> ValueError: ('month must be in 1..12', 13)
> 
> 
> Sorry if I am missing something obvious.  In the example I gave, as a
> user calling date() [from a library], I would only want to see that
> line show up.



It would be *very* confusing to see something like:

>   File "some/where/deep.py", line 2123, in 
> foo = bar(x, *y)
> ValueError: ('month must be in 1..12', 13)

You can start your stopwatch and see how much time it will take you to
figure out that "bar" is a variable referencing "date" and sequence "y"
has "month" somewhere in it.

That already happens in CPython in some places, and it's quite
confusing when you hit it:
https://mail.python.org/archives/list/python-ideas@python.org/thread/MINLM7BBAAI44WJDHDZ2ZBHNQ4P4XCQG/


On the topic of "functions implemented in C provide clean tracebacks",
on a couple of occasions, I found them to be terse up to being
obfuscated. I really consider one sweet day to be able to implement
feature to bring them closer to Python level of user-friendliness,
e.g.

> Traceback (most recent call last):
>   File "foo.py", line 2, in test
> builtin_func(a)
>   File "~/projects/foo_module/src1.c", line 34, in builtin_func_impl
> ValueError("wrong phase of moon")

So it was possible to debug code across C extensions boundary more
easily (instead of grepping loads of C code for confusing/generic error
messages guessing which one was actually hit).


Oh, and btw CPython importlib also implements some traceback
obfuscation:

https://github.com/python/cpython/blob/bb3e0c240bc60fe08d332ff5955d54197f79751c/Lib/importlib/_bootstrap.py#L233

Besides user satisfaction ("clean tracebacks"), I guess it contributes
largely to the fact that only a few people know how Python import
machinery works and are able to customize it. (At least, I found it
pretty hard to work with - you literally need to go thru the entire
importlib source code and remove those pesky
_call_with_frames_removed() calls, and only then you start to get a
picture what breaks where and how it all works together).


> >
> >
> > Or you can get clever and construct a traceback with only the
> > frames you want.
> >
> >
> > On Saturday, May 29, 2021, 08:27:18 PM GMT+1, André Roberge <  
> > andre.robe...@gmail.com> wrote:  
> >
> > What I am interested in is having a project-agnostic standardised
> > Python way to specify what to show to an end-user when an exception
> > is raised.
> >
> >  



-- 
Best regards,
 Paul  mailto:pmis...@gmail.com
___
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/J7M3SM52W4ZXC7LM3GCIVXLYTZBCUFZH/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Cleaner tracebacks from Python code

2021-05-29 Thread André Roberge
On Sat, May 29, 2021 at 4:54 PM Irit Katriel  wrote:

>
> You can control what the traceback of exceptions you are emitting:
>
> "raise e.with_traceback(None)" should clear everything before the current
> frame.
>

I'm sorry, but I still don't see how. This particular line would still show
up.


Traceback (most recent call last):
  File "test.py", line 2, in 
d = date(2021, 13, 1)
  File "C:\Users\andre\local_datetime.py", line 852, in __new__
raise e.with_traceback(None)
ValueError: ('month must be in 1..12', 13)


Sorry if I am missing something obvious.  In the example I gave, as a user
calling date() [from a library], I would only want to see that line show up.



>
>
> Or you can get clever and construct a traceback with only the frames you
> want.
>
>
> On Saturday, May 29, 2021, 08:27:18 PM GMT+1, André Roberge <
> andre.robe...@gmail.com> wrote:
>
> What I am interested in is having a project-agnostic standardised Python
> way to specify what to show to an end-user when an exception is raised.
>
>
___
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/EUDM54E3PDCYW4COZANAL7CQ77WMT2MS/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Cleaner tracebacks from Python code

2021-05-29 Thread Irit Katriel via Python-ideas
 
You can control what the traceback of exceptions you are emitting: 

"raise e.with_traceback(None)" should clear everything before the current 
frame. 

Or you can get clever and construct a traceback with only the frames you want.


On Saturday, May 29, 2021, 08:27:18 PM GMT+1, André Roberge 
 wrote:

What I am interested in is having a project-agnostic standardised Python way to 
specify what to show to an end-user when an exception is raised.

  ___
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/RMA5Y567KY7LYP3BFWGBR57NGD6JBBOJ/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Cleaner tracebacks from Python code

2021-05-29 Thread Thomas Grainger
https://github.com/agronholm/anyio/blob/9eb4671547b01f5e3ba0e0ca602b6aceec15af86/src/anyio/_backends/_asyncio.py#L598

On Sat, 29 May 2021, 20:24 André Roberge,  wrote:

>
>
> On Sat, May 29, 2021 at 3:25 PM Thomas Grainger  wrote:
>
>> pytest  uses __tracebackhide__
>>
>> https://doc.pytest.org/en/latest/example/simple.html#writing-well-integrated-assertion-helpers
>>
>
> Thanks for the reminder.  Pytest takes care of traceback formatting for
> users.  Individual projects can of course do that. But I want to do the
> reverse: I want to limit what users of my projects will see in a traceback,
> without having them specify something in their code.
>
> What I am interested in is having a project-agnostic standardised Python
> way to specify what to show to an end-user when an exception is raised.
>
>>
>> Eg anyio sets __tracebackhide__ = __traceback_hide__ = True to remove
>> internal frames from user Tracebacks
>>
>
> Do you have a specific link to this?  I have looked in the documentation
> as well as in a few modules (_core/_exceptions.py in particular) without
> seeing any reference to this. I am not interested in custom formatting for
> testing, which is something comparatively easy to do.
>
___
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/4UK5HO5X3RLWGCSZYPDASZBVVQT5RRHE/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Cleaner tracebacks from Python code

2021-05-29 Thread André Roberge
On Sat, May 29, 2021 at 3:25 PM Thomas Grainger  wrote:

> pytest  uses __tracebackhide__
>
> https://doc.pytest.org/en/latest/example/simple.html#writing-well-integrated-assertion-helpers
>

Thanks for the reminder.  Pytest takes care of traceback formatting for
users.  Individual projects can of course do that. But I want to do the
reverse: I want to limit what users of my projects will see in a traceback,
without having them specify something in their code.

What I am interested in is having a project-agnostic standardised Python
way to specify what to show to an end-user when an exception is raised.

>
> Eg anyio sets __tracebackhide__ = __traceback_hide__ = True to remove
> internal frames from user Tracebacks
>

Do you have a specific link to this?  I have looked in the documentation as
well as in a few modules (_core/_exceptions.py in particular) without
seeing any reference to this. I am not interested in custom formatting for
testing, which is something comparatively easy to do.
___
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/AX3WADP4ZTKMO4VXV2JLDGZW2P76QIHU/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: A __decoration_call__ method for Callable objects (WAS: Decorators on variables)

2021-05-29 Thread Rob Cliffe via Python-ideas



On 29/05/2021 01:26, micro codery wrote:



On Fri, May 28, 2021 at 5:07 PM Rob Cliffe 
Comailto:rob.cli...@btinternet.com>> wrote:




On 29/05/2021 00:51, micro codery wrote:


I also don't know what should happen for complicated assignments,
and I think this
has been the death of such variable decorator discussions in the
past, so I would
still push for only bare identifiers, with or without a type hint
(but maybe it will be
better received by more if the type hint is required?).

Please, please, please, don't ever make type hints *required*! 
Some of us are perfectly happy not using them (and not having to
learn them)!

Rob Cliffe

Fair enough! If this became accepted syntax I would
use it without type hints. Even for those of us that do
use type hints in places, it shouldn’t generally be
necessary because the decorator will have a return
type annotation.
I think the original argument was that currently bare
identifiers are not allowed unless they have
annotation.
I think I'm missing something (no, NOT just my marbles, something else 
).  Do you mean bare unbound identifiers?


spam = 'eggs'
spam # No problem

Rob Cliffe

But this is introducing a new multiline
syntax, and it makes no more sense to take away the
second line and expect a naked decorator to be valid
than it does remove the decorator and expect the
naked identifier to be valid.


___
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/DKU5YRG42H222RK2EC7USUHB6O72HOXB/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Cleaner tracebacks from Python code

2021-05-29 Thread André Roberge
On Sat, May 29, 2021 at 3:38 PM Irit Katriel  wrote:

> See this issue:  https://bugs.python.org/issue31299
>
> This issue refers to https://bugs.python.org/issue16217 which talks about
lines "above" the one of interest (compared with those that I describe as
being "below").  It also talks about filtering some specific modules --
something I already do in one of my projects.

Still, interesting to see; thanks for the link.



>
>
> On Saturday, May 29, 2021, 07:19:32 PM GMT+1, André Roberge <
> andre.robe...@gmail.com> wrote:
>
>
> With CPython, tracebacks obtained from code written in C can be extremely
> clean compared with functionally equivalent code written in Python.
> Consider the following test file where I am using a local copy of Python's
> datetime.py module.
>
> ```py
> from local_datetime import date
> d = date(2021, 13, 1)
> ```
>
> Executing this code results in the following, very "clean" traceback:
> ```pytb
> Traceback (most recent call last):
>   File "test.py", line 2, in 
> d = date(2021, 13, 1)
> ValueError: month must be in 1..12
> ```
>
> A single line of code is shown, which is the one written by the end-user
> of this library; all code details from inside the library module are hidden.
>
> As it turns out, the datetime module imports (if it is available) the
> _datetime module written in C. If we comment out this import, so that the
> pure Python code is used instead,
> here is the new traceback:
>
> ```pytb
> Traceback (most recent call last):
>   File "test.py", line 2, in 
> d = date(2021, 13, 1)
>   File "C:\Users\andre\local_datetime.py", line 847, in __new__
> year, month, day = _check_date_fields(year, month, day)
>   File "C:\Users\andre\local_datetime.py", line 422, in _check_date_fields
> raise ValueError('month must be in 1..12', month)
> ValueError: ('month must be in 1..12', 13)
> ```
>
> In addition to the call by the end-user of that library, we see some inner
> code of that library that has no practical value to the end-user.
>
> We can suppress some lines of the traceback by replacing the line
>
> ```py
> year, month, day = _check_date_fields(year, month, day)
> ```
> by
> ```py
> try:
> year, month, day = _check_date_fields(year, month, day)
> except Exception:
> _, _, tb = sys.exc_info()
> tb.tb_next = None
> raise
> ```
>
> which simplifies the traceback somewhat:
> ```pytb
> Traceback (most recent call last):
>   File "test.py", line 2, in 
> d = date(2021, 13, 1)
>   File "C:\Users\andre\local_datetime.py", line 848, in __new__
> year, month, day = _check_date_fields(year, month, day)
> ValueError: ('month must be in 1..12', 13)
> ```
> but there is still one line of code from inside the library.
> ===
> Idea: it would be nice if one could somehow define **callables** with a
> custom attribute that
> would indicate that tracebacks should not include frames "below" it.
> More explicitly, using the notation of the above example, imagine that we
> could write
>
> ```py
> date.__hide_tb__ = True
> ```
> and that any call to `date()` that generate a traceback would not show
> frames below the
> calling frame, thus reproducing what we see when using the C code in this
> example.
> For library writers, this would be easily reverted when attempting to
> debug.
> For end users, this would result in much more readable tracebacks,
> unencumbered by extra lines of code that are outside of their control.
>
> 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/WQN7QJUVV62IO3J7ALOJYHS6URYVRDFD/
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
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/3XCRIWFK6NB6WCY3KJZZXNI2TSDMH7WF/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Cleaner tracebacks from Python code

2021-05-29 Thread Irit Katriel via Python-ideas
 See this issue:  https://bugs.python.org/issue31299


On Saturday, May 29, 2021, 07:19:32 PM GMT+1, André Roberge 
 wrote:  
 
 With CPython, tracebacks obtained from code written in C can be extremely 
clean compared with functionally equivalent code written in Python.  Consider 
the following test file where I am using a local copy of Python's datetime.py 
module.
```pyfrom local_datetime import date
d = date(2021, 13, 1)
```
Executing this code results in the following, very "clean" 
traceback:```pytbTraceback (most recent call last):
  File "test.py", line 2, in 
    d = date(2021, 13, 1)
ValueError: month must be in 1..12
```
A single line of code is shown, which is the one written by the end-user of 
this library; all code details from inside the library module are hidden.
As it turns out, the datetime module imports (if it is available) the _datetime 
module written in C. If we comment out this import, so that the pure Python 
code is used instead,here is the new traceback:
```pytbTraceback (most recent call last):
  File "test.py", line 2, in 
    d = date(2021, 13, 1)
  File "C:\Users\andre\local_datetime.py", line 847, in __new__
    year, month, day = _check_date_fields(year, month, day)
  File "C:\Users\andre\local_datetime.py", line 422, in _check_date_fields
    raise ValueError('month must be in 1..12', month)
ValueError: ('month must be in 1..12', 13)
```
In addition to the call by the end-user of that library, we see some inner code 
of that library that has no practical value to the end-user.
We can suppress some lines of the traceback by replacing the line
```pyyear, month, day = _check_date_fields(year, month, day)
```by```pytry:
    year, month, day = _check_date_fields(year, month, day)
except Exception:
    _, _, tb = sys.exc_info()
    tb.tb_next = None
    raise
```
which simplifies the traceback somewhat:```pytbTraceback (most recent call 
last):
  File "test.py", line 2, in 
    d = date(2021, 13, 1)
  File "C:\Users\andre\local_datetime.py", line 848, in __new__
    year, month, day = _check_date_fields(year, month, day)
ValueError: ('month must be in 1..12', 13)
```but there is still one line of code from inside the library.===Idea: it 
would be nice if one could somehow define **callables** with a custom attribute 
thatwould indicate that tracebacks should not include frames "below" it.More 
explicitly, using the notation of the above example, imagine that we could write
```pydate.__hide_tb__ = True```and that any call to `date()` that generate a 
traceback would not show frames below thecalling frame, thus reproducing what 
we see when using the C code in this example.For library writers, this would be 
easily reverted when attempting to debug.For end users, this would result in 
much more readable tracebacks, unencumbered by extra lines of code that are 
outside of their control.
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/WQN7QJUVV62IO3J7ALOJYHS6URYVRDFD/
Code of Conduct: http://python.org/psf/codeofconduct/
  ___
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/3HJEEPE7JPDE7N23HQVDP6YNR25E4TRI/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Cleaner tracebacks from Python code

2021-05-29 Thread Thomas Grainger
pytest  uses __tracebackhide__

https://doc.pytest.org/en/latest/example/simple.html#writing-well-integrated-assertion-helpers

Eg anyio sets __tracebackhide__ = __traceback_hide__ = True to remove
internal frames from user Tracebacks

On Sat, 29 May 2021, 19:21 André Roberge,  wrote:

> With CPython, tracebacks obtained from code written in C can be extremely
> clean compared with functionally equivalent code written in Python.
> Consider the following test file where I am using a local copy of Python's
> datetime.py module.
>
> ```py
> from local_datetime import date
> d = date(2021, 13, 1)
> ```
>
> Executing this code results in the following, very "clean" traceback:
> ```pytb
> Traceback (most recent call last):
>   File "test.py", line 2, in 
> d = date(2021, 13, 1)
> ValueError: month must be in 1..12
> ```
>
> A single line of code is shown, which is the one written by the end-user
> of this library; all code details from inside the library module are hidden.
>
> As it turns out, the datetime module imports (if it is available) the
> _datetime module written in C. If we comment out this import, so that the
> pure Python code is used instead,
> here is the new traceback:
>
> ```pytb
> Traceback (most recent call last):
>   File "test.py", line 2, in 
> d = date(2021, 13, 1)
>   File "C:\Users\andre\local_datetime.py", line 847, in __new__
> year, month, day = _check_date_fields(year, month, day)
>   File "C:\Users\andre\local_datetime.py", line 422, in _check_date_fields
> raise ValueError('month must be in 1..12', month)
> ValueError: ('month must be in 1..12', 13)
> ```
>
> In addition to the call by the end-user of that library, we see some inner
> code of that library that has no practical value to the end-user.
>
> We can suppress some lines of the traceback by replacing the line
>
> ```py
> year, month, day = _check_date_fields(year, month, day)
> ```
> by
> ```py
> try:
> year, month, day = _check_date_fields(year, month, day)
> except Exception:
> _, _, tb = sys.exc_info()
> tb.tb_next = None
> raise
> ```
>
> which simplifies the traceback somewhat:
> ```pytb
> Traceback (most recent call last):
>   File "test.py", line 2, in 
> d = date(2021, 13, 1)
>   File "C:\Users\andre\local_datetime.py", line 848, in __new__
> year, month, day = _check_date_fields(year, month, day)
> ValueError: ('month must be in 1..12', 13)
> ```
> but there is still one line of code from inside the library.
> ===
> Idea: it would be nice if one could somehow define **callables** with a
> custom attribute that
> would indicate that tracebacks should not include frames "below" it.
> More explicitly, using the notation of the above example, imagine that we
> could write
>
> ```py
> date.__hide_tb__ = True
> ```
> and that any call to `date()` that generate a traceback would not show
> frames below the
> calling frame, thus reproducing what we see when using the C code in this
> example.
> For library writers, this would be easily reverted when attempting to
> debug.
> For end users, this would result in much more readable tracebacks,
> unencumbered by extra lines of code that are outside of their control.
>
> 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/WQN7QJUVV62IO3J7ALOJYHS6URYVRDFD/
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
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/MQIGFKW762O2BKXCA5HW7WVSQOI5DPHV/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Cleaner tracebacks from Python code

2021-05-29 Thread André Roberge
With CPython, tracebacks obtained from code written in C can be extremely
clean compared with functionally equivalent code written in Python.
Consider the following test file where I am using a local copy of Python's
datetime.py module.

```py
from local_datetime import date
d = date(2021, 13, 1)
```

Executing this code results in the following, very "clean" traceback:
```pytb
Traceback (most recent call last):
  File "test.py", line 2, in 
d = date(2021, 13, 1)
ValueError: month must be in 1..12
```

A single line of code is shown, which is the one written by the end-user of
this library; all code details from inside the library module are hidden.

As it turns out, the datetime module imports (if it is available) the
_datetime module written in C. If we comment out this import, so that the
pure Python code is used instead,
here is the new traceback:

```pytb
Traceback (most recent call last):
  File "test.py", line 2, in 
d = date(2021, 13, 1)
  File "C:\Users\andre\local_datetime.py", line 847, in __new__
year, month, day = _check_date_fields(year, month, day)
  File "C:\Users\andre\local_datetime.py", line 422, in _check_date_fields
raise ValueError('month must be in 1..12', month)
ValueError: ('month must be in 1..12', 13)
```

In addition to the call by the end-user of that library, we see some inner
code of that library that has no practical value to the end-user.

We can suppress some lines of the traceback by replacing the line

```py
year, month, day = _check_date_fields(year, month, day)
```
by
```py
try:
year, month, day = _check_date_fields(year, month, day)
except Exception:
_, _, tb = sys.exc_info()
tb.tb_next = None
raise
```

which simplifies the traceback somewhat:
```pytb
Traceback (most recent call last):
  File "test.py", line 2, in 
d = date(2021, 13, 1)
  File "C:\Users\andre\local_datetime.py", line 848, in __new__
year, month, day = _check_date_fields(year, month, day)
ValueError: ('month must be in 1..12', 13)
```
but there is still one line of code from inside the library.
===
Idea: it would be nice if one could somehow define **callables** with a
custom attribute that
would indicate that tracebacks should not include frames "below" it.
More explicitly, using the notation of the above example, imagine that we
could write

```py
date.__hide_tb__ = True
```
and that any call to `date()` that generate a traceback would not show
frames below the
calling frame, thus reproducing what we see when using the C code in this
example.
For library writers, this would be easily reverted when attempting to debug.
For end users, this would result in much more readable tracebacks,
unencumbered by extra lines of code that are outside of their control.

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/WQN7QJUVV62IO3J7ALOJYHS6URYVRDFD/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: dict.sort()?

2021-05-29 Thread Jonathan Fine
On Sat, May 29, 2021 at 6:01 PM Chris Angelico

> But if you're okay with constructing a new dict, you can do this:
>
> d = dict(sorted(d.items(), key=lambda kv: ...))
>

Or to keep the same dict (not tested)

tmp = list(sorted(d.items()))
d.clear()
d.update(tmp)

-- 
Jonathan
___
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/SN75Q4U5PPSMAKTMHBTPRXL4K24NHUN6/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: dict.sort()?

2021-05-29 Thread Chris Angelico
On Sun, May 30, 2021 at 2:57 AM Marco Sulla
 wrote:
>
> Since `dict` now is ordered, how about a `sort()` method?
> It could have the same signature of list.sort(), with an optional
> parameter "by" that can be "keys" or "values" ("keys" could be the
> default).

Not really a thing - if you want that level of flexibility, try
OrderedDict, which lets you move elements around.

But if you're okay with constructing a new dict, you can do this:

d = dict(sorted(d.items(), key=lambda kv: ...))

Your key function will receive a tuple of the key and the value. If
you don't provide one, default tuple sorting will effectively sort the
elements by their keys - probably a good default.

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/XA5JDSWRDWQKZ722EHJJHABOIAWFZV4Q/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] dict.sort()?

2021-05-29 Thread Marco Sulla
Since `dict` now is ordered, how about a `sort()` method?
It could have the same signature of list.sort(), with an optional
parameter "by" that can be "keys" or "values" ("keys" could be the
default).
___
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/XXA2E5ILMAEMFLPWZIZN3T67FERJPBFF/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] SEMANTICS for 'variables' produced by a decorator

2021-05-29 Thread Jonathan Fine
There's been a discussion in this list on extending Python to provide
SYNTAX such as
@decorator
name = EXPRESSION
and also suitable semantics. (Here 'name' is an identifier, in the
discussion called a 'variable'.)

This post is about providing SEMANTICS for such decorator syntax. We can do
this within the existing Python syntax for decorators.

Recall that
@decorator
def fn():
# body
is usually equivalent to
def fn():
# body
fn =  decorator(fn)
and that decorator is just a callable that returns something. It need not
return another function. It could return a 'variable', such as the result
of calling fn.

Here's a proof of concept. Consider the following
BEGIN
$ cat work.py
from collections import namedtuple
Locn = namedtuple('Locn', 'doc module name')

def locn_from_fn(fn):
name = fn.__name__
module = fn.__module__
doc = fn.__doc__
return Locn(name=name, module=module, doc=doc)

def decovar(fn):
locn = locn_from_fn(fn)
return fn(locn)

@decovar
def variable(locn):
return ('value', locn)

def deconamedtuple(fn):
locn = locn_from_fn(fn)
nt = namedtuple(locn.name, fn())

nt.__doc__ = locn.doc
nt.__module__ = locn.module
nt.__name__ = locn.name

return nt

@deconamedtuple
def Point():
'''Return a point (x, y) in the plane.'''
return 'x y'

print(variable)
print(Point)
print(Point.__doc__)
END

Here's what we get when we run the script.
BEGIN
$ python3 work.py
('value', Locn(doc=None, module='__main__', name='variable'))

Return a point (x, y) in the plane.
END

It should now be clear that this approach allows us to pass much useful
information to the decorator.

I claim that this approach gives most or all of the semantic benefits of
'decorators on variables', and within the current Python syntax. If so, and
the semantic benefits are strong, then here's part of a good case for
extending the syntax in a future version of Python.
-- 
Jonathan
___
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/QJACDY45QEAIY5XTXGBQBGXGOLWRJK3U/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: A __decoration_call__ method for Callable objects (WAS: Decorators on variables)

2021-05-29 Thread Matt del Valle
>
> I just thought it looked better, but would you and others here like it
> better if the
> NEWLINE requirement was kept for all decorators? There is nothing in the
> original
> proposal that requires a single line.
> I also don't know what should happen for complicated assignments, and I
> think this
> has been the death of such variable decorator discussions in the past, so
> I would
> still push for only bare identifiers, with or without a type hint (but
> maybe it will be
> better received by more if the type hint is required?). I still think such
> a proposal is
> strong enough on its own to be of value to the language.
>
> So now the syntax would be:
>
> @decorator
> variable: Type
>
> @decorator("spam", eggs)
> variable: Type
>
> become
>
> variable = decorator("variable")
>
> variable = decorator("spam", eggs)("variable")
>
> I'm not sure that the type hint shouldn't be passed as an additional
> parameter,
> especially if one is always required. Yes it is still different from a
> function
> decorator in that you are not getting the variable object (which may or
> may not
> exist) but instead its name as a string. However, decorators that expect
> to be
> applied to variables should already be drastically different. Even if they
> did get
> the variable object, there would be not necessarily be a __code__ or
> __name__ or __dict__ attribute. They won't be callable (generally) where
> most
> current decorators attempt to call func, wrapped in an internal closure.
>

I think there's a fundamental difference between your original proposal and
the OPs proposal in this thread, which is that you seem to envision
variable decorators as granting access to just a name (and potentially a
type-hint?), whereas the OP wants the decorators extended to assignment in
general.

Basically, your proposal is a subset of the OPs proposal. Any
implementation of the OPs decorators would also allow us to do all the
things you want to be able to do with variable decorators (as a happy
side-effect), but would also offer a LOT more functionality.

My view is that variable decorators should be legal for:

1) assignment statements (so that the decorator can modify or replace the
object that is getting assigned)
2) bare type-hints, since these are arguably *a sort of* assignment
operation that still carries useful info a decorator might want to capture
(you're not assigning the name and its value to globals(), but rather the
name and its type to globals()['__annotations__'])

If there was huge pushback against point 2 I'd be happy to see it deferred
and revisit it at a later point, but as far as I'm concerned point 1 is
what actually interests me about this proposal.

Your point about complicated assignment being a problem seems solvable
using the following rules:

1) Variable decorators only capture the name (or names) on the LHS of a
true assignment statement (or bare type-hint). Expressions that happen to
bind names (such as the walrus operator, for loop, etc.) don't have their
names available for use in the decorator.
2) The proposed __decoration_call__ is given the value, name, and type-hint
from the decorated statement (and potentially the code object from the RHS,
as OP suggested). We could provide the names as a series of useful
pre-parsed parsed AST-like objects, like:

@decorate
some_obj.foo = first, _, third, *some_obj.rest = some_dict[(lost_name
:= ('ba' + 'r'))] = baz = (another_lost_name := [0, 1, 2, 3, 4])

such that __decoration_call__ receives:

def __decoration_call__(self, obj, names, annotation):
print(obj)
# [0, 1, 2, 3, 4]

print(names)
# ParsedNames(names=[
# ObjectAssignment(obj={reference_to_some_obj}, name='foo'),
# DestructuringAssignment(names=[
# BasicAssignment(name='first'),
# BasicAssignment(name='_'),
# BasicAssignment(name='third'),
# ObjectAssignment(obj={reference_to_some_obj}, name='*rest')
# ]),
# ItemAssignment(obj={ref_to_some_dict}, name='bar'),
# BasicAssignment(name='baz')
# ])

print(annotation)
# NOTSET


Notice that as per point 1 above, `lost_name` and `another_lost_name` do
not get captured, because they are not part of the assignment statement.
They're only sub-expressions.
Also, notice that expressions like 'ba' + 'r' are evaluated before being
passed to the decorator, so that it actually receives 'bar' for the
__setitem__ assignment name.

3) Augmented assignment gets expanded out to its true meaning before being
passed to the decorator, so for example:

foo = 3

@decorate
foo += 2


behaves exactly the same as:

foo = 3

@decorate
foo = foo + 2



If there are still any issues given these rules that I can't think of I'd
be happy for people to raise them. There are so many edge-cases in python
assignment that I could very easily be forgetting about something. But I
think this covers 99% of cases.


class Colors(Enum):
> @str
> RED: str
> @str
> 

[Python-ideas] Re: Introduce constants in Python (constant name binding)

2021-05-29 Thread Shreyan Avigyan
Now it seems Python doesn’t need constant. There are many ways we can achieve 
constants. Though constants may increase performance. Yet again it can also be 
the opposite.


From: Paul Sokolovsky 
Sent: Saturday, May 29, 2021 12:44:09 AM
To: Shreyan Avigyan 
Cc: python-ideas@python.org 
Subject: [Python-ideas] Re: Introduce constants in Python (constant name 
binding)

Hello,

On Tue, 25 May 2021 11:53:20 -
"Shreyan Avigyan"  wrote:

> I posted my previous idea regarding this on the mailing list. This
> idea is a little different. This idea suggests introducing constant
> name bindings. This is similar to const pointer in C/C++. Once a name
> has been assigned to a data we can change the data (if mutable) but
> we cannot change the name to point to a different data. The only way
> the data the constant points can get deallocated is if it goes out of
> scope, the program exits or the constant is manually `del` by the
> user. The proposed syntax is as follows,
>
> constant x = 10
> constant y = ["List"]
> constant z: str = "Hi"

The idea of introducing constants on the core language level in Python
is well-known topic and was brought up on multiple occasions both on
the python-ideas and python-dev mailing lists. A random example:

https://www.mail-archive.com/python-dev@python.org/msg110424.html
"constants in Python: Starting simple and gradually adding more
features, was: Re: Pattern Matching controversy"

The matter is actually implementing it in different Python
implementations. And some implementations had support for *some kind*
of constants for many years (e.g. MicroPython with it's pre-annotation
syntax of "FOO = const(1)"), while CPython still has it only on the
level of external first-generation annotation module, "typing".

As another example, I can give "strict mode"
(https://www.mail-archive.com/python-ideas@python.org/msg25403.html)
feature of my Python dialect, Pycopy
(https://github.com/pfalcon/pycopy), which implements some (but again,
not all) aspects of const'ness. E.g.:

===
print("In import-time")
a: const = 1
a: const = 2


def __main__():
print("In run-time")
global a
a = 3
===


Gives:


In import-time
Warning: strict mode: overriding (monkey-patching) const name 'a'
In run-time
Traceback (most recent call last):
  File "strict.py", line 9, in __main__
RuntimeError: strict mode: cannot override const name




--
Best regards,
 Paul  mailto:pmis...@gmail.com
___
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/PHU3YE47SI55JODFG3W53GZIJK6IH4FL/
Code of Conduct: http://python.org/psf/codeofconduct/
___
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/5UU3IYKZZ5Z5WZQH2DKJILKYVVYRRDJQ/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Add static variable storage in functions

2021-05-29 Thread Steven D'Aprano
On Fri, May 28, 2021 at 07:37:57PM -0700, Brendan Barnwell wrote:

>   I see your point, but I don't agree that static function variables 
>   are parallel to either closures or generators.

Okay, this is an important point, I think. I argue that some sort of 
sugar for static storage in functions is exactly analogous to closures 
and generators.

The history of Python demonstrates a pattern of using classes for 
complex data structures with state and *multiple* behaviours (methods), 
while using functions for the simple cases where you have only a single 
behaviour and a small amount of state, without the anti-pattern of 
global variables.

Closures, generators and coroutines are all ways of doing this.


>   Closures are, to my mind, just an outgrowth of Python's ability to 
> define functions inside other functions.  If you're going to allow such 
> nested functions, you have to have some well-defined behavior for 
> variables that are defined in the other function and used in the inner 
> one, and closures are just a reasonable way to do that.

When closures and lexical scoping were first introduced, they were 
intentionally and explicitly limited because classes could do everything 
that closures can. Here is the history of the feature.

Python didn't gain closures until version 2.1 (with a future import):

https://www.python.org/dev/peps/pep-0227/

Before then, nested functions behaved quite differently. This is 
Python1.5:


>>> x = "outside"
>>> def function(): 
... x = "inside"
... def inner():
... print x
... inner()
... 
>>> function()
outside


That's a simple, reasonable behaviour. Inner functions were allowed by 
the language but they didn't add much functionality and consequently 
were hardly ever used.

Lexical scoping changed that, and made inner functions much more useful. 
At the time people wanted a way to rebind nonlocal variables, but that 
was explicitly rejected because:

"this would encourage the use of local variables to hold state that is 
better stored in a class instance"

https://www.python.org/dev/peps/pep-0227/#id15

That comment has aged like milk. By the time Python 2.3 and 2.4 came 
along and people were talking about some future "Python 3000", it had 
already become clear that it would be useful to rebind nonlocal names 
and hold state encapsulated in a function without going to all the 
trouble of creating a class.

And so in Python 3 we gained the nonlocal keyword and the ability to 
store and modify state in a closure.

The proposed static statement would be sugar for functionality already 
possible: storing per function data in the function without needing to 
write a class.

Classes are great, but not everything is a nail that needs to be 
hammered with a class.


>   As for generators, they are tied to iteration, which is a 
> pre-existing concept in Python.  Generators provide a way to make your 
> own functions/objects that work in a `for` loop in a manner that 
> naturally extends the existing iteration behavior of lists, tuples, 
> etc.

We already had a way to create our own iterable values: classes using 
the sequence or iterator protocols.

Iteration using `__getitem__` and IndexError was possible all the way 
back to Python 1.x. The iterator protocol with `__iter__` and `__next__` 
wasn't introduced until 2.2 (and originally the second dunder was 
spelled `next`).

https://www.python.org/dev/peps/pep-0234/

Generators were also introduced in 2.2, explicitly as a way for 
functions to *hold state from one call to the next*:

https://www.python.org/dev/peps/pep-0255/

The motivation section of the PEP starts with this:

"When a producer function has a hard enough job that it requires 
maintaining state between values produced, most programming languages 
offer no pleasant and efficient solution ..."

and goes on to discuss alternatives such as functions with global state. 
(Global variables.) One alternative left out is to write a class, 
possibly because everyone acknowledged that writing a single function 
with its own state is so obviously superior to a class for solving this 
sort of problem that nobody bothered to list it as an alternative.

(You *can* spread butter on bread using a surf board, but why would you 
even try when you have a butterknife?)

The next step in the evolution of function-local state was to make 
generators two-way coroutines.

(Alas, the name "corountine" has been hijacked by async for a related 
but different concept, so there is some unavoidable terminology 
confusion here.)

https://www.python.org/dev/peps/pep-0342/

Generators now have send and throw methods, even when you can't use 
them for anything useful!

>>> g = (x+1 for x in range(10))
>>> g.send

>>> g.throw


So that's yet another unobvious way to get static storage in a function: 
use a PEP 343 enhanced generator coroutine.