Re: Lambda returning tuple question, multi-expression

2023-03-09 Thread Alan Gauld
On 08/03/2023 21:56, aapost wrote:
> When making a UI there are a lot of binding/trace operations that need 
> to occur that lead to a lot of annoying 1 use function definitions. I 
> don't really see lambda use like below.

Lambdas are very common in GUI callbacks but I admit I've never seen
tuples used to create multiple expressions. That's a neat trick I
hadn't thought of and will probably use.

> Giving 2 working lambda examples using a returned tuple to accomplish 
> multiple expressions - what sort of gotchas, if any, might make the 
> following bad practice if I am missing something?

Not bad practice per-se but you are still limited to expressions, no
loops for example (although you could fake it with a list comp,
but that gets ugly fast!)

Also layout is all important here. It could get very messy to read if
indentation isn't clear. You only have to look at some Javascript code
with function definitions as arguments to functions to see how clunky
that can be.

Similarly debugging so much code passed as arguments might be an
issue - no easy way to step into the lambda.

But as an alternative to writing many typical event handlers it's
definitely a valid approach that I'll be trying.

> b = tk.Button(master=main, text="Enable")
> b.config(
>  command=lambda: (
>  e1.config(state="normal"),
>  e2.config(state="normal"),
>  e3.config(state="normal")
>  )
> )

You could of course single line that with:

b = tk.Button(master=main,
  text="Enable",
  command=lambda: (
  e1.config(state="normal"),
  e2.config(state="normal"),
  e3.config(state="normal")
  )
  )

It's not a radical change from using a lamba as a
callback but it does extend the use case to cover
a common GUI scenario.

I like it. I wish I'd thought of it years ago.
Thanks for sharing.

-- 
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
Follow my photo-blog on Flickr at:
http://www.flickr.com/photos/alangauldphotos


-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Lambda returning tuple question, multi-expression

2023-03-09 Thread Weatherby,Gerard
Other than the admittedly subjective viewpoint that using the lambda is 
confusing, there’s probably nothing wrong with the lambda approach. A couple of 
alternatives:


def e():
 for e in (e1,e2,e3):
 e.config(state="normal")
b = tk.Button(master=main, text="Enable",command=e)

or

b = tk.Button(master=main, text="Enable",command=lambda: 
[e.config(state="normal") for e in (e1, e2, e3)])

From: Python-list  on 
behalf of aapost 
Date: Wednesday, March 8, 2023 at 5:15 PM
To: python-list@python.org 
Subject: Lambda returning tuple question, multi-expression
*** Attention: This is an external email. Use caution responding, opening 
attachments or clicking on links. ***

When making a UI there are a lot of binding/trace operations that need
to occur that lead to a lot of annoying 1 use function definitions. I
don't really see lambda use like below.

Giving 2 working lambda examples using a returned tuple to accomplish
multiple expressions - what sort of gotchas, if any, might make the
following bad practice if I am missing something?


Example 1:

import tkinter as tk

main = tk.Tk()
e1 = tk.Entry(master=main)
e1["state"] = "disabled"
e1.pack()
e2 = tk.Entry(master=main)
e2["state"] = "disabled"
e2.pack()
e3 = tk.Entry(master=main)
e3["state"] = "disabled"
e3.pack()

b = tk.Button(master=main, text="Enable")
b.config(
 command=lambda: (
 e1.config(state="normal"),
 e2.config(state="normal"),
 e3.config(state="normal")
 )
)
b.pack()


Example 2:

import tkinter as tk

main = tk.Tk()
l = tk.Label(master=main)
l.a = {"seconds":0}
l._updater = lambda: (
 l.a.update({"seconds": 1 + l.a["seconds"]}),
 l.config(text=l.a["seconds"]),
 l.after(ms=1000, func=l._updater)
)
l._updater()
l.pack()

--
https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!i8mp9fRKlBLziXCn6-OIC8fNx0LBohis8m6VARp17Igg5036wrTflGiwwptY18Rgkriw5MquUKxe9Fglqpu8FHEy$
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Python 3.12.0 alpha 6 released

2023-03-09 Thread Robin Becker

On 08/03/2023 04:37, Thomas Wouters wrote:

I'm pleased to announce the release of Python 3.12 alpha 6.

https://www.python.org/downloads/release/python-3120a6/


*This is an early developer preview of Python 3.12.*
Major new features of the 3.12 series, compared to 3.11



I was able to test reportlab with the 3.12.0a5 release (I build following the Archlinux pkgbuild), but am unable to do 
so with 3.12.0a6 because of problems with cython/lxml/freetype-py (I think).


With an optimized build of a6 I was getting segfaults which I think were caused by incompatible C extensions from the 
pip cache so decided to rebuild the requirements.


With latest cython git (allegedly 3.0.0b1) I see errors related to tstate eg



Cython/Compiler/Parsing.c:86861:34: error: ‘PyThreadState’ {aka ‘struct _ts’} 
has no member named ‘curexc_traceback’
86861 | PyObject* tmp_tb = tstate->curexc_traceback;


I guess that this is caused by changes in what we are allowed to see of Python 
internal structure.

If anyone knows of a way to advance further I can try to experiment.


Python 3.12 is still in development. This release, 3.12.0a6 is the sixth of
seven planned alpha releases.

Alpha releases are intended to make it easier to test the current state of
new features and bug fixes and to test the release process.

During the alpha phase, features may be added up until the start of the
beta phase (2023-05-08) and, if necessary, may be modified or deleted up
until the release candidate phase (2023-07-31). Please keep in mind that
this is a preview release and its use is not recommended for production
environments.

Many new features for Python 3.12 are still being planned and written.
Among the new major new features and changes so far:


Your release team,
Thomas Wouters
Ned Deily
Steve Dower


--
Robin Becker
--
https://mail.python.org/mailman/listinfo/python-list


Re: Lambda returning tuple question, multi-expression

2023-03-09 Thread aapost

On 3/9/23 00:13, Thomas Passin wrote:




lol.. 'us'..

So.. to give an example from your own code:

but_play = Tk.Button(_frame, text='Play', width = BUTTONWIDTH + 1, pady 
= PADY, command=lambda x=plotmgr:play_macro(x), bg = BUTTON_BG, font = 
NEWFONT)


Can be written as:

b = Tk.Button(master=_frame)
b.config(text='Play', width = BUTTONWIDTH + 1, pady = PADY, 
command=lambda x=plotmgr:play_macro(x), bg = BUTTON_BG, font = NEWFONT)


.config() is just a way of adding/modifying most of the same 
initialization arguments after the instantiation of the object.


tkinter objects are flexible by design, You can also do
b["text"] = "adsfa"
b["command"] = lambda: (a,b,c,d)

I could also rewrite the original example with the exact same result:
b = tk.Button(
master=main,
text="Enable",
command=lambda: (
e1.config(state="normal"),
e2.config(state="normal"),
e3.config(state="normal")
)
)
b.pack()

b is not changing states at any point. Nothing "happens" to state when 
.config() is called. b does nothing without a command= configured. 
.config() is binding the button press event via command= to a call so 
than an action can occur on button press. There is no 'instead' of 
b.config() (unless of course using one of the equivalent examples above 
to do the exact same thing)


The disconnect is not in the not understanding of my code, it's in the 
not understanding of .config(). (which is no big deal, I forgot what a 
file buffer was just this week, lol)


So, as far as the examples, they are simplified abstract 
psuedo-like-code illustrations to accompany the ask of and open ended 
question regarding a programming practice.


(I did forgot to include main.mainloop() at the end of each one, as I 
was using python -i when I quickly wrote them)


example 1 described:
A button press does sequence of actions against widgets, i.e. I have 3 
disabled widgets, I press a button, now in sequence all 3 are enabled so 
I can type in them. Without a lambda tuple sequence this requires a def 
and an another lambda.


example 2 described:
dict with an attribute assigned to a label (you can't assign directly to 
external variables within a lambda, but you can call something with a 
method like .update(), which why would that be considered any different 
than any other state changing call?)
Then lambda assigned to a label and called to start it up, recursively 
performs an update to said widget every 1 second. There are several ways 
to do this without a lambda tuple sequence, none as concise.


The 'what I am trying to do' is ask a question regarding opinions and 
practices on issuing a sequence of actions within a lambda via a tuple 
(since the common practice approaches against it - mainly with tkinter - 
feel more convoluted), and in doing so leaving it open ended to get a 
feel on what opinions are, and to see if any opinions influence mine.

--
https://mail.python.org/mailman/listinfo/python-list


Baffled by readline module

2023-03-09 Thread Grant Edwards
In an interactive command-line Python program on Linux, I want to be
able to read a line at a time from stdin, providing command line
history and editing to the user. In C, I would use GNU readline to do
that.

Python has the readline module, which appears to be a wrapper for GNU
readline. However, I've read and re-read the documenation for that
module, but I'm completely baffled. There's all sorts of stuff about
history files, but I neither need nor want a history file. Likewise
tab-completion: don't want it.  All the examples not only involve
history files and tab-completion but they're somehow connected to the
interactive Python REPL, which is also completely off-base for my use
case.

Is the readline module not the right tool for an interactive Linux
command-line application that needs to provide command line recall and
editing to the user who's entering stuff on stdin from a tty?

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Baffled by readline module

2023-03-09 Thread Grant Edwards
On 2023-03-09, Grant Edwards  wrote:

> In an interactive command-line Python program on Linux, I want to be
> able to read a line at a time from stdin, providing command line
> history and editing to the user. In C, I would use GNU readline to do
> that.
>
> Python has the readline module, which appears to be a wrapper for GNU
> readline. However, I've read and re-read the documenation for that
> module, but I'm completely baffled.

After googling for a while, I finally stumbled across an old Python 2
example that pointed me in the right direction. Here's the sort of
example I had hoped to find in the module's docs:

#!/usr/bin/python
import readline

readline.parse_and_bind('set editing-mode emacs')

while True:
try:
line = input('enter something (EOF to quit): ')
except EOFError:
print()
break
print('You entered: "%s"' % line)




-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Baffled by readline module

2023-03-09 Thread Chris Angelico
On Fri, 10 Mar 2023 at 06:28, Grant Edwards  wrote:
>
> In an interactive command-line Python program on Linux, I want to be
> able to read a line at a time from stdin, providing command line
> history and editing to the user. In C, I would use GNU readline to do
> that.
>
> Python has the readline module, which appears to be a wrapper for GNU
> readline. However, I've read and re-read the documenation for that
> module, but I'm completely baffled. There's all sorts of stuff about
> history files, but I neither need nor want a history file. Likewise
> tab-completion: don't want it.  All the examples not only involve
> history files and tab-completion but they're somehow connected to the
> interactive Python REPL, which is also completely off-base for my use
> case.
>
> Is the readline module not the right tool for an interactive Linux
> command-line application that needs to provide command line recall and
> editing to the user who's entering stuff on stdin from a tty?
>

Not sure about the history file, and I would assume that if you don't
configure one, history is simply lost when you restart. But with tab
completion, unless you need to be able to input a tab character, it
should be safe to ignore the feature and leave it at the defaults.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Lambda returning tuple question, multi-expression

2023-03-09 Thread Thomas Passin

On 3/9/2023 3:29 AM, aapost wrote:
The 'what I am trying to do' is ask a question regarding opinions and 
practices on issuing a sequence of actions within a lambda via a tuple 
(since the common practice approaches against it - mainly with tkinter - 
feel more convoluted), and in doing so leaving it open ended to get a 
feel on what opinions are, and to see if any opinions influence mine.


I finally realized why I am uncomfortable with doing this kind of thing. 
 It's because, IMHO, lambda expressions should not have side effects 
and should not require much mental effort to grasp what they do.  Yes, 
you can do so.  You can even print from a lambda (and it might be useful 
for debugging):


lambda x: print(f'The lambda received {x}') or x*x

The Python Reference on readthedocs.io also has a tk example that 
specifically wants the side effect (see 
https://python-reference.readthedocs.io/en/latest/docs/operators/lambda.html):


>>> # this is a code snippet from a Tkinter gui app
>>> # in this case lambda is quite convenient
>>> self.btn_cancel = Button(self.progress_container, text='Cancel',
>>> command=lambda: subprocess.call('taskkill /f /im uberzip.exe',
>>> shell=True))

Maybe so, but I think it's better not to have side effects hidden away 
in expressions that are hard to read and understand.  And being 
anonymous, there is no function name to remind you what the action is 
suppose to do. Much better (still IMHO, of course):


def kill_uberzip():
"""Kill an external running program named uberzip.exe."""
subprocess.call('taskkill /f /im uberzip.exe', shell=True))

self.btn_cancel = Button(self.progress_container, text='Cancel',
 command = kill_uberzip())

This way, it's easy to understand what btn_cancel() will do each time 
you scan that line of code.  Using the lambda makes you reparse the line 
and spend mental effort each time you scan it.  And this way, you know 
directly that the button is going to cause a side effect outside your 
program, which you have to infer (an indirect mental operation) when you 
scan the lambda.


For this particular example, it might turn out that there could be more 
than one instance of uberzip.exe running at the same time.  Which one 
should be killed, and how do you kill the right one?  With the function, 
you can get those details under control, but I hate to think what might 
happen to the lambda expression.


Yes, of course, there can be times when the lambda expression is 
somewhat easy to understand and the side effects are harmless.  In that 
case, it may be easy enough to grasp quickly that the anonymous function 
would not benefit from having a name.  So OK, it's not a hard-and-fast 
rule.

--
https://mail.python.org/mailman/listinfo/python-list


Re: Baffled by readline module

2023-03-09 Thread Grant Edwards
On 2023-03-09, Chris Angelico  wrote:

> Not sure about the history file, and I would assume that if you don't
> configure one, history is simply lost when you restart. But with tab
> completion, unless you need to be able to input a tab character, it
> should be safe to ignore the feature and leave it at the defaults.

Indeed, that seems to be how it works (though I never found that
stated anywhere in the docs).

What's really weird about the docs is that when it is described it
doesn't even _mention_ that it provides command-line recall and
editing:

The readline module defines a number of functions to facilitate
completion and reading/writing of history files from the Python
interpreter. This module can be used directly, or via the
rlcompleter module, which supports completion of Python
identifiers at the interactive prompt. Settings made using this
module affect the behaviour of both the interpreter’s interactive
prompt and the prompts offered by the built-in input() function.

It just talks about manipulating history files and about
tab-completion of Python identfiers.  The last sentence mentions that
settings affect both the REPL prompt and the prompts offered by the
built-in input() function.

However, I also don't really care about the "prompts offered"
either. What I care about is the interactive handling of user
keystrokes vis-a-vis command line recall and editing.

Or is that what's meant by the phrase "behavior of the prompt"?

To me "the prompt" is the string that's printed _before_ the program
starts reading user keystrokes and doing the stuff I care about.

It finally dawned on me after seeing an example I found elsewhere that
you don't call some module method to fetch the next user-entered line.

You call the input() built-in.

Having a module modify the behavior of a built-in makes me cringe.

I suppose this way you can easily slap-on "readline" command-line
recall/editing to an existing application as long as it uses the
input() built-in instead of reading from stdin.

--
Grant


-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Lambda returning tuple question, multi-expression

2023-03-09 Thread Cameron Simpson

On 09Mar2023 09:06, Alan Gauld  wrote:

On 08/03/2023 21:56, aapost wrote:

When making a UI there are a lot of binding/trace operations that need
to occur that lead to a lot of annoying 1 use function definitions. I
don't really see lambda use like below.


Lambdas are very common in GUI callbacks but I admit I've never seen
tuples used to create multiple expressions. That's a neat trick I
hadn't thought of and will probably use.


I often uses as a debugging hack. Given:

foo=lambda: expr

I'll often write:

foo=lambda: (X("foo happening here!"), ...maybe more..., expr)[-1]

to embed some debug tracing in a lambda defined expression.

Cheers,
Cameron Simpson 
--
https://mail.python.org/mailman/listinfo/python-list


Re: Lambda returning tuple question, multi-expression

2023-03-09 Thread Cameron Simpson

On 09Mar2023 09:06, Alan Gauld  wrote:

Also layout is all important here. It could get very messy to read if
indentation isn't clear. You only have to look at some Javascript code
with function definitions as arguments to functions to see how clunky
that can be.


Just a note that some code formatters use a trailing comma on the last 
element to make the commas fold points. Both yapf (my preference) and 
black let you write a line like (and, indeed, flatten if short enough):


( a, b, c )

but if you write:

( a, b, c, )

they'll fold the lines like:

( a,
  b,
  c,
)

in varying flavours of indentation depending on tuning. The point being 
that if, like me, you often have a code formatter active-on-save it can 
be hinted to nicely present complex tuples (or parameter lists and 
imports).


It isn't magic, but can be quite effective.

Cheers,
Cameron Simpson 
--
https://mail.python.org/mailman/listinfo/python-list


Re: Baffled by readline module

2023-03-09 Thread Chris Angelico
On Fri, 10 Mar 2023 at 08:10, Grant Edwards  wrote:
> What's really weird about the docs is that when it is described it
> doesn't even _mention_ that it provides command-line recall and
> editing:
>
> It just talks about manipulating history files and about
> tab-completion of Python identfiers.  The last sentence mentions that
> settings affect both the REPL prompt and the prompts offered by the
> built-in input() function.
>

Ah. Yes, that's because the **module** doesn't provide command-line
recall and editing. It does affect the input() builtin, as is
mentioned, but mainly, the module is to configure readline, not to ask
for a line of text.

It's a bit confusing, but very useful.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Baffled by readline module

2023-03-09 Thread Cameron Simpson

On 09Mar2023 13:08, Grant Edwards  wrote:

On 2023-03-09, Chris Angelico  wrote:

Not sure about the history file, and I would assume that if you don't
configure one, history is simply lost when you restart. But with tab
completion, unless you need to be able to input a tab character, it
should be safe to ignore the feature and leave it at the defaults.


Indeed, that seems to be how it works (though I never found that
stated anywhere in the docs).

What's really weird about the docs is that when it is described it
doesn't even _mention_ that it provides command-line recall and
editing:

[...]

I think this might be the common case of a module which wraps another 
library: there's a tension between describing everything in pointless 
detail and the trite "we're just shimming this library, go read its 
docs".


The module documentation needs to:
- not insult the reader by saying nearly nothing ("this is just GNU 
  readline, hooked to Python!") I'm looking at you, many "man" pages on 
  a GNU based system which say "oh just go and read GNI info, it's all 
  over there"
- be detailed enough to enumerate the API calls and at least summarise 
  their semantics
- be general enough to not overprescribe so that small shifts in the 
  library as it evolves don't cause falsehoods in the module docs (and a 
  nightmarish maintenance burden)


Similar example: the "os" modules, which largely shims the OS POSIX 
calls. It lists them and has a paragraph on their purpose and the 
meaning of the flags (for example). But the platform specifics and fine 
grained stuff is off in "man 2 foo" for the Python "os.foo" function.


[...]

It finally dawned on me after seeing an example I found elsewhere that
you don't call some module method to fetch the next user-entered line.

You call the input() built-in.


Ah. That's not overtly stated? [...reads...] Ah, there it is in the last 
sentence of the opening paragraph. Not quite as in-your-face as I'd have 
liked it. That paragraph could do with being a bullet list of use cases.


Cheers,
Cameron Simpson 
--
https://mail.python.org/mailman/listinfo/python-list


Re: Lambda returning tuple question, multi-expression

2023-03-09 Thread Chris Angelico
On Fri, 10 Mar 2023 at 07:43, Thomas Passin  wrote:
>
> On 3/9/2023 3:29 AM, aapost wrote:
> > The 'what I am trying to do' is ask a question regarding opinions and
> > practices on issuing a sequence of actions within a lambda via a tuple
> > (since the common practice approaches against it - mainly with tkinter -
> > feel more convoluted), and in doing so leaving it open ended to get a
> > feel on what opinions are, and to see if any opinions influence mine.
>
> I finally realized why I am uncomfortable with doing this kind of thing.
>   It's because, IMHO, lambda expressions should not have side effects
> and should not require much mental effort to grasp what they do.  Yes,
> you can do so.  You can even print from a lambda (and it might be useful
> for debugging):
>
> lambda x: print(f'The lambda received {x}') or x*x

I'm not sure why lambda functions shouldn't have side effects. They
can be used for anything, as long as it's a single expression (which
can, of course, be composed of other expressions).

> The Python Reference on readthedocs.io also has a tk example that
> specifically wants the side effect (see
> https://python-reference.readthedocs.io/en/latest/docs/operators/lambda.html):
>
>  >>> # this is a code snippet from a Tkinter gui app
>  >>> # in this case lambda is quite convenient
>  >>> self.btn_cancel = Button(self.progress_container, text='Cancel',
>  >>> command=lambda: subprocess.call('taskkill /f /im uberzip.exe',
>  >>> shell=True))
>
> Maybe so, but I think it's better not to have side effects hidden away
> in expressions that are hard to read and understand.  And being
> anonymous, there is no function name to remind you what the action is
> suppose to do. Much better (still IMHO, of course):

The purpose of the lambda function is to tie the effect to the
function. Otherwise, you have to go elsewhere to figure out what each
one does. It's not inherently better to give names to everything,
especially when those functions are only ever used once. In fact, I'd
say that that is usually *worse*.

> def kill_uberzip():
>  """Kill an external running program named uberzip.exe."""
>  subprocess.call('taskkill /f /im uberzip.exe', shell=True))
>
> self.btn_cancel = Button(self.progress_container, text='Cancel',
>   command = kill_uberzip())

And this is one of the reasons it's worse: with the lambda function,
you won't fall into this trap. It's a classic bug, and a rather nasty
one; can you see it? If not, this is a VERY strong argument in favour
of the lambda function. Even if you can, the mere fact that you made
this error indicates how easy it is to slip into the faulty way of
writing it.

> This way, it's easy to understand what btn_cancel() will do each time
> you scan that line of code.

Only if the name is enough information, and it seldom is. Whereas with
the lambda function, you have the entire code there, so you can
understand what btn_cancel does without having to bookmark your spot
there, go elsewhere, and find out what kill_uberzip() does.

> For this particular example, it might turn out that there could be more
> than one instance of uberzip.exe running at the same time.  Which one
> should be killed, and how do you kill the right one?  With the function,
> you can get those details under control, but I hate to think what might
> happen to the lambda expression.

Maybe, but this is just the example getting in the way. Obviously the
larger a function needs to be, the less reasonable to make it a lambda
function.

That's why I'm of the opinion that it's better to use a different
system, such as function decorators or a class namespace. For example:

self.btn_cancel = Button(...)

@on(self.btn_cancel, "command")
def kill_uberzip(): ...

Or alternatively:

class btn_cancel(Button):
def command(self):
...

These kinds of systems allow much more flexibility than lambda
functions, without the issues of name repetition and disconnection.

> Yes, of course, there can be times when the lambda expression is
> somewhat easy to understand and the side effects are harmless.  In that
> case, it may be easy enough to grasp quickly that the anonymous function
> would not benefit from having a name.  So OK, it's not a hard-and-fast
> rule.

Definitely not a hard-and-fast rule, but in defense of the Python's
lambda, at least we don't have resonance cascades happening.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Baffled by readline module

2023-03-09 Thread Chris Angelico
On Fri, 10 Mar 2023 at 09:01, Cameron Simpson  wrote:
> I think this might be the common case of a module which wraps another
> library: there's a tension between describing everything in pointless
> detail and the trite "we're just shimming this library, go read its
> docs".

Yeah, it's a combination of this...

> >You call the input() built-in.
>
> Ah. That's not overtly stated? [...reads...] Ah, there it is in the last
> sentence of the opening paragraph. Not quite as in-your-face as I'd have
> liked it. That paragraph could do with being a bullet list of use cases.

... and this. With a lot of "just wrap that library" functions, it can
be exactly as you say: a bit of documentation about each function, and
you can skim those to see what's available. But with readline, there
isn't a "give me a command from the user" function, because that's
input().

Maybe there should be an example added at the end?

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Baffled by readline module

2023-03-09 Thread Grant Edwards
On 2023-03-09, Cameron Simpson  wrote:

> [...]
>>It finally dawned on me after seeing an example I found elsewhere that
>>you don't call some module method to fetch the next user-entered line.
>>
>>You call the input() built-in.
>
> Ah. That's not overtly stated? [...reads...] Ah, there it is in the last 
> sentence of the opening paragraph. Not quite as in-your-face as I'd have 
> liked it.

What threw me off the track for a while was that the sentence to which
you refer says it affects the "prompts offered by input()". In my head,
that means it changes the string that's printed on stdout before stuff
is read from stdin. That's different that affecting the handling of
user input read by input().

It doesn't actually change anything about the prompts provided by
input(). It changes the handling of the user input by input().

I guess I read it too literally. I must spend too much time with
computers.

> That paragraph could do with being a bullet list of use cases.



-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Lambda returning tuple question, multi-expression

2023-03-09 Thread aapost

On 3/9/23 04:06, Alan Gauld wrote:




Thank you for the feedback, I appreciate the comments.

To add a little extra, there is actually a reason I lean toward overuse 
of .config() for a lot of things even though they could be sent to the 
constructor (other than that w["attribute"]= doesn't work in a lambda).


It comes from a use case I needed to solve in the shortcoming of tk with 
frames not being scrollable, requiring a canvas.


When dynamically generating a series of widgets (i.e. loading a custom 
json/xml layout config file), getting the scrollable area right is a bit 
of a chore with a catch-22 situation.


With an inner frame in a canvas, pack_propogate(tk.True) is the default 
on the frame, so that the children dictate the size, but in doing so it 
prevents the frame from expanding to the full width of the area it's 
given within the UI layout.


If you turn pack_propogate to tk.False, it breaks the ability for the 
canvas to return bbox(tk.ALL) (which is kind of rough anyway as the tcl 
docs state "The return value may overestimate the actual bounding box by 
a few pixels."). So you end up with 1,1 and no way of knowing what size 
scrollable area to set. Trying to obtain this value from a source 
outside of the canvas requires knowing what you are placing the canvas 
in each time, and was creating a similar catch-22 as the outer widget 
doesn't know what it wants it's size to be without knowing what the 
inner widget wants.. Switching to False, grabbing bbox, then back to 
True of course causes an unsightly flicker and disrupts the smoothness 
of the user experience.


So my solution is to create a widget instantiator which does a few 
things, mainly adding something I call a "ghost".


it's something like this:

instantiator(qlass, master, config_args=None, pack_args=None, 
init_args=None, ghost=False):

  if not init_args:
init_args = {}
  object = qlass(master=master, **init_args)
  if hasattr(master, "ghost"):
object.ghost = qlass(master=master.ghost, **init_args)
  elif ghost:
object.ghost = qlass(master=tk.Frame(), **init_args)

When i pass it a canvas and say ghost=True, the canvas gets a .ghost 
duplicate, which is attached to an arbitrary frame that I never pack and 
stays invisible.


Subsequent widgets created to the canvas then see that their parent, 
starting with the canvas, have a ghost, and in return get a ghost of 
themselves attached to their parents ghost.


This allows you to get an accurate bbox size from the unseen ghost 
canvas that mirrors the visible version.


Keeping the init_args down to only what is necessary helps in 
consistency, and the subsequent config_args and pack_args I have in 
their respective dicts.


This also allows me to create a quality of life pack function I call ppack()

def ppack(self):
  self.pack(**self.pack_args)
  if hasattr(self, "ghost"):
self.ghost.pack(**self.ghost.pack_args)
  return self

That allows each primary widget to manage and track their own set of 
configurations.


Of course I could strip a lot of that crap out if I find a better and 
smooth way of obtaining those bbox numbers, but I didn't see any quick 
solutions in glancing through the tcl/tk source so I went with what 
works for now.








--
https://mail.python.org/mailman/listinfo/python-list


Re: Baffled by readline module

2023-03-09 Thread Chris Angelico
On Fri, 10 Mar 2023 at 09:20, Grant Edwards  wrote:
>
> On 2023-03-09, Cameron Simpson  wrote:
>
> > [...]
> >>It finally dawned on me after seeing an example I found elsewhere that
> >>you don't call some module method to fetch the next user-entered line.
> >>
> >>You call the input() built-in.
> >
> > Ah. That's not overtly stated? [...reads...] Ah, there it is in the last
> > sentence of the opening paragraph. Not quite as in-your-face as I'd have
> > liked it.
>
> What threw me off the track for a while was that the sentence to which
> you refer says it affects the "prompts offered by input()". In my head,
> that means it changes the string that's printed on stdout before stuff
> is read from stdin. That's different that affecting the handling of
> user input read by input().
>
> It doesn't actually change anything about the prompts provided by
> input(). It changes the handling of the user input by input().
>
> I guess I read it too literally. I must spend too much time with
> computers.

It does actually affect the prompts, although only in subtle ways.

import readline
print("Pseudo-prompt: ", end="")
msg1 = input()
msg2 = input("Actual prompt: ")
print(repr(msg1))
print(repr(msg2))

At each of the prompts, type a bit of text, then backspace it all the
way. The actual prompt will remain, but the pseudo-prompt will get
cleared off. There'll be other small differences too.

Maybe that could be mentioned somewhere too; but this is definitely
something to be more careful with locking in, since the behaviour may
not be quite the same if it's using libedit instead of GNU readline.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Baffled by readline module

2023-03-09 Thread Grant Edwards
On 2023-03-09, Grant Edwards  wrote:
> On 2023-03-09, Cameron Simpson  wrote:
>
>> [...]
>>>It finally dawned on me after seeing an example I found elsewhere that
>>>you don't call some module method to fetch the next user-entered line.
>>>
>>>You call the input() built-in.
>>
>> Ah. That's not overtly stated? [...reads...] Ah, there it is in the last 
>> sentence of the opening paragraph. Not quite as in-your-face as I'd have 
>> liked it.
>
> What threw me off the track for a while was that the sentence to which
> you refer says it affects the "prompts offered by input()". In my head,
> that means it changes the string that's printed on stdout before stuff
> is read from stdin. That's different that affecting the handling of
> user input read by input().
>
> It doesn't actually change anything about the prompts provided by
> input(). It changes the handling of the user input by input().
>
> I guess I read it too literally. I must spend too much time with
> computers.

Yeesh. What's _really_ embarassing is that I just stumbled across a
small test program with which I had apparently figured this out 10-12
years ago.  Must be about time to retire...

--
Grant
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Baffled by readline module

2023-03-09 Thread Chris Angelico
On Fri, 10 Mar 2023 at 10:04, Grant Edwards  wrote:
>
> Yeesh. What's _really_ embarassing is that I just stumbled across a
> small test program with which I had apparently figured this out 10-12
> years ago.  Must be about time to retire...
>

You expect yourself to remember test programs you wrote a decade ago??
I've forgotten full-on projects from that far back!

Though, congrats on being able to stumble across it. That's quite something.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Baffled by readline module

2023-03-09 Thread Grant Edwards
On 2023-03-09, Chris Angelico  wrote:
> On Fri, 10 Mar 2023 at 10:04, Grant Edwards  wrote:
>
>> Yeesh. What's _really_ embarassing is that I just stumbled across a
>> small test program with which I had apparently figured this out
>> 10-12 years ago.  Must be about time to retire...
>
> You expect yourself to remember test programs you wrote a decade
> ago??  I've forgotten full-on projects from that far back!

Another thing that has happened a few times is that I'm trying to
figure out how to do something I'm pretty sure should be possible, but
I can't figure out how. After the usual resources fail, then I start
Googling with varous sets of keywords. After a while, Google eventually
finds the answer in an old mailing-list archive where there's a nice
explanation in a post...

 by me.


> Though, congrats on being able to stumble across it. That's quite
> something.

After I figured out the answer, I realized it did seem a little
familar, so I tried a grep -r in my home directory which has stuff
lying around from as far back as 2001. When a computer dies, I
generally just cp -a (or rsync -a) $HOME to a new one.

--
Grant
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Baffled by readline module

2023-03-09 Thread 2QdxY4RzWzUUiLuE
On 2023-03-09 at 15:02:53 -0800,
Grant Edwards  wrote:

> Yeesh. What's _really_ embarassing is that I just stumbled across a
> small test program with which I had apparently figured this out 10-12
> years ago.  Must be about time to retire...

Retiring doesn't help.  :-)

I retired almost five years ago, and I just (within the past few days)
(re)discovered a command line parsing library I'd written about a year
and a half ago (i.e., after I retired).

Dan
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Baffled by readline module

2023-03-09 Thread Cameron Simpson

On 09Mar2023 13:08, Grant Edwards  wrote:

Having a module modify the behavior of a built-in makes me cringe.


Maybe. But input(), like print(), is one of those funky conveniences for 
human interaction. I'm somewhat ok with that. If for no other reason 
than to make keyboard arrow keys act as normal humans expect them to (as 
opposed to old nerds who predate such fancies). General improvement of 
the user experience.


Another thing affected by readline is the cmd module, which will use it 
during the input step for completion _if the module is present_.  And 
use it for the input itself if it is loaded. (These might not mean 
different things and instead be an accident of phrasing.) Again, a human 
interaction convenience and I'm good with it.


Good enough to have written this code recently:

try:
  import readline
except ImportError:
  pass

just to turn it on if available.

Cheers,
Cameron Simpson 
--
https://mail.python.org/mailman/listinfo/python-list


Re: Baffled by readline module

2023-03-09 Thread Chris Angelico
On Fri, 10 Mar 2023 at 10:51, <2qdxy4rzwzuui...@potatochowder.com> wrote:
>
> On 2023-03-09 at 15:02:53 -0800,
> Grant Edwards  wrote:
>
> > Yeesh. What's _really_ embarassing is that I just stumbled across a
> > small test program with which I had apparently figured this out 10-12
> > years ago.  Must be about time to retire...
>
> Retiring doesn't help.  :-)
>
> I retired almost five years ago, and I just (within the past few days)
> (re)discovered a command line parsing library I'd written about a year
> and a half ago (i.e., after I retired).
>

Traditional retirement: Work till you're 60 or 65 or whatever, then
society pats you on the head, calls you a "senior citizen", and lets
you go and be idle till you die (which might be prematurely soon).

Direction-change retirement: Work till you can afford to zero out your
income, then finally do what you've always wanted to do, but never had
time because you spent so much of it earning money.

Tell-the-next-generation: Work till you know so much that you're
infinitely valuable, then spend the rest of your life empowering the
next group of amazing people. See for instance: NASA.

Programmer retirement: At an early age, learn how to wield PHENOMENAL
COSMIC POWER, and spend the next X years in an itty bitty working
space, earning money. Eventually, upgrade to better living/working
space. Eventually, downgrade to a small wooden box six feet below the
ground. Never once relinquish the power. Never once abandon that
feeling of mastery.

We're not really an industry that has a concept of retirement.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Lambda returning tuple question, multi-expression

2023-03-09 Thread aapost

On 3/9/23 16:37, Cameron Simpson wrote:

On 09Mar2023 09:06, Alan Gauld  wrote:


Just a note that some code formatters use a trailing comma on the last 
element to make the commas fold points. Both yapf (my preference) and 
black let you write a line like (and, indeed, flatten if short enough):


     ( a, b, c )

but if you write:

     ( a, b, c, )

they'll fold the lines like:

     ( a,
   b,
   c,
     )
Cameron Simpson 



Thanks for the info, good to know, I actually do like the idea of 
trailing commas for tuples (helps prevent things like the difference 
between ("abc") and ("abc",) and makes swapping things around nicer.


I've just been using a lot of json lately and it has been subconsciously 
training me different, lol.

--
https://mail.python.org/mailman/listinfo/python-list


Re: Baffled by readline module

2023-03-09 Thread Greg Ewing via Python-list

On 10/03/23 10:08 am, Grant Edwards wrote:

It finally dawned on me after seeing an example I found elsewhere that
you don't call some module method to fetch the next user-entered line.

You call the input() built-in.

Having a module modify the behavior of a built-in makes me cringe.


Importing the module is not modifying the built-in.

If your Python has been compiled with gnu readline support,
input() *already* provides recall and editing facilities.

You only need to import the readline module if you want to
change the configuration.

Yes, it would be helpful if the docs for the readline module
explained this. At present they seem to assume that you already
know what the readline module is for and just want a summary
of the API.

It *is* mentioned briefly in the docs for input(), but again
somebody wanting line editing functionality wouldn't necessarily
think of looking there.

--
Greg
--
https://mail.python.org/mailman/listinfo/python-list


Re: Baffled by readline module

2023-03-09 Thread Greg Ewing via Python-list

On 10/03/23 10:59 am, Cameron Simpson wrote:
I think this might be the common case of a module which wraps another 
library


It's not quite the same thing, though -- the library it wraps
is already hooked into things behind the scenes in ways that
may not be obvious. (Unless you're Dutch?)

--
Greg

--
https://mail.python.org/mailman/listinfo/python-list


Re: Baffled by readline module

2023-03-09 Thread Greg Ewing via Python-list

On 10/03/23 11:43 am, Chris Angelico wrote:

import readline
print("Pseudo-prompt: ", end="")
msg1 = input()
msg2 = input("Actual prompt: ")
print(repr(msg1))
print(repr(msg2))

At each of the prompts, type a bit of text, then backspace it all the
way. The actual prompt will remain, but the pseudo-prompt will get
cleared off. There'll be other small differences too.


Hmmm, so it seems that merely importing readline does change
things a little bit.

This is rather nasty. I'd go so far as to call it a bug in
gnu readline -- it shouldn't be erasing something that the
user didn't type in.

--
Greg
--
https://mail.python.org/mailman/listinfo/python-list


Re: Baffled by readline module

2023-03-09 Thread Greg Ewing via Python-list

On 10/03/23 12:43 pm, Grant Edwards wrote:

When a computer dies, I
generally just cp -a (or rsync -a) $HOME to a new one.


Same here, more or less. My current machine has multiple
archaeological layers going back about 5 generations of
technology...

--
Greg
--
https://mail.python.org/mailman/listinfo/python-list


Re: Baffled by readline module

2023-03-09 Thread Grant Edwards
On 2023-03-10, Greg Ewing via Python-list  wrote:
> On 10/03/23 10:08 am, Grant Edwards wrote:
>> It finally dawned on me after seeing an example I found elsewhere that
>> you don't call some module method to fetch the next user-entered line.
>> 
>> You call the input() built-in.
>> 
>> Having a module modify the behavior of a built-in makes me cringe.
>
> Importing the module is not modifying the built-in.
>
> If your Python has been compiled with gnu readline support,
> input() *already* provides recall and editing facilities.

That's not how Python 3.10.10 works for me. When I run the code below,
I do not get command recall and editing. If I hit arrow keys, I just
see the escape sequence echoed and returned by input(). Likewise for
things like ctrl-P, ctrl-N, etc. I have to uncomment the import
statement to get command line recall and editing to work. Without the
import, the escape sequences from arrow keys just end up in the input
data.

#!/usr/bin/python

# import readline
# readline.parse_and_bind('set editing-mode emacs')

while True:
try:
line = input('enter something (EOF to quit): ')
except EOFError:
print()
break
print('ENTERED: "%s"' % line)


> You only need to import the readline module if you want to
> change the configuration.

That's not how it acts for me. I have to "import readline" to get
command line recall and editing.  The parse_and_bind, doesn't seem to
do anything -- emacs mode seems to be the default.

> Yes, it would be helpful if the docs for the readline module
> explained this. At present they seem to assume that you already
> know what the readline module is for and just want a summary
> of the API.
>
> It *is* mentioned briefly in the docs for input(), but again
> somebody wanting line editing functionality wouldn't necessarily
> think of looking there.



-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Baffled by readline module

2023-03-09 Thread 2QdxY4RzWzUUiLuE
On 2023-03-10 at 11:02:52 +1100,
Chris Angelico  wrote:

> Traditional retirement: Work till you're 60 or 65 or whatever, then
> society pats you on the head, calls you a "senior citizen", and lets
> you go and be idle till you die (which might be prematurely soon).

Sounds like Free Four¹:

  The memories of a man in his old age
  Are the deeds of a man in his prime.

  You shuffle in the gloom of the sickroom
  And talk to yourself as you die.

Great tune.  Bad life.

> Direction-change retirement: Work till you can afford to zero out your
> income, then finally do what you've always wanted to do, but never had
> time because you spent so much of it earning money.

A little bit of that.  We live in the RV, and we have crisscrossed the
country more than once, coronavirus notwithstanding.

> Tell-the-next-generation: Work till you know so much that you're
> infinitely valuable, then spend the rest of your life empowering the
> next group of amazing people. See for instance: NASA.

And a little bit of that, too.  NASA would have been nice; I did my most
of my time in the commercial space, with a short break in the government
contracting business.

> Programmer retirement: At an early age, learn how to wield PHENOMENAL
> COSMIC POWER, and spend the next X years in an itty bitty working
> space, earning money. Eventually, upgrade to better living/working
> space. Eventually, downgrade to a small wooden box six feet below the
> ground. Never once relinquish the power. Never once abandon that
> feeling of mastery.

I was with you until that part of the small wooden box.  :-)

> We're not really an industry that has a concept of retirement.

Which is why I'm still here (on this mailing list, and a handful of
others like it).

Thanks for asking.

¹ https://www.azlyrics.com/lyrics/pinkfloyd/freefour.html
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Baffled by readline module

2023-03-09 Thread Greg Ewing via Python-list

On 10/03/23 1:46 pm, Grant Edwards wrote:

That's not how it acts for me. I have to "import readline" to get
command line recall and editing.


Maybe this has changed? Or is platform dependent?

With Python 3.8 on MacOSX I can use up arrow with input()
to recall stuff I've typed before, without having to
import anything.

--
Greg
--
https://mail.python.org/mailman/listinfo/python-list


Re: Baffled by readline module

2023-03-09 Thread Chris Angelico
On Fri, 10 Mar 2023 at 12:56, Greg Ewing via Python-list
 wrote:
>
> On 10/03/23 1:46 pm, Grant Edwards wrote:
> > That's not how it acts for me. I have to "import readline" to get
> > command line recall and editing.
>
> Maybe this has changed? Or is platform dependent?
>
> With Python 3.8 on MacOSX I can use up arrow with input()
> to recall stuff I've typed before, without having to
> import anything.
>

import sys; "readline" in sys.modules

Is it? Might be that something's pre-importing it.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Baffled by readline module

2023-03-09 Thread 2QdxY4RzWzUUiLuE
On 2023-03-10 at 12:57:48 +1100,
Chris Angelico  wrote:

> On Fri, 10 Mar 2023 at 12:56, Greg Ewing via Python-list
>  wrote:
> >
> > On 10/03/23 1:46 pm, Grant Edwards wrote:
> > > That's not how it acts for me. I have to "import readline" to get
> > > command line recall and editing.
> >
> > Maybe this has changed? Or is platform dependent?
> >
> > With Python 3.8 on MacOSX I can use up arrow with input()
> > to recall stuff I've typed before, without having to
> > import anything.
> >
> 
> import sys; "readline" in sys.modules
> 
> Is it? Might be that something's pre-importing it.

My ~/.pythonrc contains the following:

import readline
import rlcompleter
readline.parse_and_bind( 'tab: complete' )

IIRC, that's been there "forever," certainly back into Python2, and
probably back into Python1.  On my Arch Linux system Python 3.10.9, I
get readline behavior with or without those lines.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Baffled by readline module

2023-03-09 Thread Grant Edwards
On 2023-03-10, 2qdxy4rzwzuui...@potatochowder.com 
<2qdxy4rzwzuui...@potatochowder.com> wrote:
> On 2023-03-10 at 12:57:48 +1100,
> Chris Angelico  wrote:
>
>> On Fri, 10 Mar 2023 at 12:56, Greg Ewing via Python-list
>>  wrote:
>> >
>> > On 10/03/23 1:46 pm, Grant Edwards wrote:
>> > > That's not how it acts for me. I have to "import readline" to get
>> > > command line recall and editing.
>> >
>> > Maybe this has changed? Or is platform dependent?
>> >
>> > With Python 3.8 on MacOSX I can use up arrow with input()
>> > to recall stuff I've typed before, without having to
>> > import anything.

If you run this application from the command line, you get command
recall and editing when entering strings at the "cmd:" prompt?

#!/usr/bin/python
while True:
try:
line = input('cmd: ')
except EOFError:
print()
break
print('You entered "%s"' % line)

>> import sys; "readline" in sys.modules
>> 
>> Is it? Might be that something's pre-importing it.
>
> My ~/.pythonrc contains the following:
>
> import readline
> import rlcompleter
> readline.parse_and_bind( 'tab: complete' )
>
> IIRC, that's been there "forever," certainly back into Python2, and
> probably back into Python1.  On my Arch Linux system Python 3.10.9, I
> get readline behavior with or without those lines.

I "get readline behavior" in the REPL without an "import readline",
but that's irrelevent.  We're talking about a command-line
application that's calling input().

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Baffled by readline module

2023-03-09 Thread 2QdxY4RzWzUUiLuE
On 2023-03-09 at 19:11:56 -0800,
Grant Edwards  wrote:

> On 2023-03-10, 2qdxy4rzwzuui...@potatochowder.com 
> <2qdxy4rzwzuui...@potatochowder.com> wrote:

> If you run this application from the command line, you get command
> recall and editing when entering strings at the "cmd:" prompt?
> 
> #!/usr/bin/python
> while True:
> try:
> line = input('cmd: ')
> except EOFError:
> print()
> break
> print('You entered "%s"' % line)

In my case, no.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Baffled by readline module

2023-03-09 Thread Greg Ewing via Python-list

On 10/03/23 2:57 pm, Chris Angelico wrote:

import sys; "readline" in sys.modules

Is it?


Yes, it is -- but only when using the repl!
If I put that in a script, I get False.

My current theory is that it gets pre-imported when using
Python interactively because the repl itself uses it.

--
Greg
--
https://mail.python.org/mailman/listinfo/python-list


Re: Baffled by readline module

2023-03-09 Thread Greg Ewing via Python-list

On 10/03/23 4:00 pm, 2qdxy4rzwzuui...@potatochowder.com wrote:

My ~/.pythonrc contains the following:

 import readline
 import rlcompleter
 readline.parse_and_bind( 'tab: complete' )


I don't have a ~/.pythonrc, so that's not what's doing it
for me.

--
Greg
--
https://mail.python.org/mailman/listinfo/python-list