Re: tkinter newbie question

2016-01-25 Thread Peter Otten
KP wrote:

> See my code below (which works). 

>From the import of lowercase "tkinter" I conclude you are using Python 3.

> I'd like to have the 2nd window as a
> class in a separate unit. How do I code that unit and how do I call it
> from my first unit?
> 
> As always, thanks for all help!

Move the code from open_window2() into a class in settings.py, e. g.


import tkinter as tk # avoid star-import

class SettingsWindow(tk.Toplevel): # Class names start with uppercase letter
   # Prefer self-explaining names
def __init__(self, root):
super().__init__(root)
self.title('New window')
self.geometry('262x65+200+250')
self.transient(root)

Then use it in your main script:


> #!/usr/bin/env python
> """
> """
> from tkinter import *
import settings

> class window1():
> 
> def open_window2(self):
  settings.SettingsWindow(self.root)

> def setup_menu(self):
> self.menubar = Menu(self.root)
> self.menu1 = Menu(self.menubar, tearoff=0 )
> self.menu1.add_command(label="Settings",   accelerator='Ctrl+S',
> command=self.open_window2) self.menubar.add_cascade(label="Menu
> 1", menu=self.menu1) self.root.config(menu=self.menubar)
> 
> def __init__(self):
> self.root = Tk()
> self.root.title('Window #1')
> self.setup_menu()
> self.root.geometry('800x600+200+200')
> #
> self.root.mainloop()
> 
> if __name__ == '__main__':
> 
> w1 = window1()


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


Re: Question about asyncio and blocking operations

2016-01-25 Thread Frank Millman
"Ian Kelly"  wrote in message 
news:calwzidngogpx+cpmvba8vpefuq4-bwmvs0gz3shb0owzi0b...@mail.gmail.com...


On Sat, Jan 23, 2016 at 7:38 AM, Frank Millman  wrote:
> Here is the difficulty. The recommended way to handle a blocking 
> operation
> is to run it as task in a different thread, using run_in_executor(). 
> This
> method is a coroutine. An implication of this is that any method that 
> calls

> it must also be a coroutine, so I end up with a chain of coroutines
> stretching all the way back to the initial event that triggered it.

This seems to be a common misapprehension about asyncio programming.
While coroutines are the focus of the library, they're based on
futures, and so by working at a slightly lower level you can also
handle them as such. So  while this would be the typical way to use
run_in_executor:

async def my_coroutine(stuff):
value = await get_event_loop().run_in_executor(None,
blocking_function, stuff)
result = await do_something_else_with(value)
return result

This is also a perfectly valid way to use it:

def normal_function(stuff):
loop = get_event_loop()
coro = loop.run_in_executor(None, blocking_function, stuff)
task = loop.create_task(coro)
task.add_done_callback(do_something_else)
return task


I am struggling to get my head around this.

1. In the second function, AFAICT coro is already a future. Why is it 
necessary to turn it into a task? In fact when I tried that in my testing, I 
got an assertion error -


File: "C:\Python35\lib\asyncio\base_events.py", line 211, in create_task
   task = tasks.Task(coro, loop=self)
File: "C:\Python35\lib\asyncio\tasks.py", line 70, in __init__
   assert coroutines.iscoroutine(coro), repr(coro)
AssertionError: 

2. In the first function, calling 'run_in_executor' unblocks the main loop 
so that it can continue with other tasks, but the function itself is 
suspended until the blocking function returns. In the second function, I 
cannot see how the function gets suspended. It looks as if the blocking 
function will run in the background, and the main function will continue.


I would like to experiment with this further, but I would need to see the 
broader context - IOW see the 'caller' of normal_function(), and see what it 
does with the return value.


I feel I am getting closer to an 'aha' moment, but I am not there yet, so 
all info is appreciated.


Frank


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


Re: Question about asyncio and blocking operations

2016-01-25 Thread Frank Millman

"Ian Kelly"  wrote in message
news:calwzidngogpx+cpmvba8vpefuq4-bwmvs0gz3shb0owzi0b...@mail.gmail.com...


On Sat, Jan 23, 2016 at 7:38 AM, Frank Millman  wrote:
> Here is the difficulty. The recommended way to handle a blocking
> operation
> is to run it as task in a different thread, using run_in_executor().
> This
> method is a coroutine. An implication of this is that any method that
> calls
> it must also be a coroutine, so I end up with a chain of coroutines
> stretching all the way back to the initial event that triggered it.

This seems to be a common misapprehension about asyncio programming.
While coroutines are the focus of the library, they're based on
futures, and so by working at a slightly lower level you can also
handle them as such. So  while this would be the typical way to use
run_in_executor:

async def my_coroutine(stuff):
value = await get_event_loop().run_in_executor(None,
blocking_function, stuff)
result = await do_something_else_with(value)
return result

This is also a perfectly valid way to use it:

def normal_function(stuff):
loop = get_event_loop()
coro = loop.run_in_executor(None, blocking_function, stuff)
task = loop.create_task(coro)
task.add_done_callback(do_something_else)
return task


I am struggling to get my head around this.

1. In the second function, AFAICT coro is already a future. Why is it
necessary to turn it into a task? In fact when I tried that in my testing, I
got an assertion error -

File: "C:\Python35\lib\asyncio\base_events.py", line 211, in create_task
   task = tasks.Task(coro, loop=self)
File: "C:\Python35\lib\asyncio\tasks.py", line 70, in __init__
   assert coroutines.iscoroutine(coro), repr(coro)
AssertionError: 

2. In the first function, calling 'run_in_executor' unblocks the main loop
so that it can continue with other tasks, but the function itself is
suspended until the blocking function returns. In the second function, I
cannot see how the function gets suspended. It looks as if the blocking
function will run in the background, and the main function will continue.

I would like to experiment with this further, but I would need to see the
broader context - IOW see the 'caller' of normal_function(), and see what it
does with the return value.

I feel I am getting closer to an 'aha' moment, but I am not there yet, so
all info is appreciated.

Frank 



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


Re: tkinter newbie question

2016-01-25 Thread KP
On Sunday, 24 January 2016 20:20:07 UTC-8, KP  wrote:
> See my code below (which works). I'd like to have the 2nd window as a class 
> in a separate unit. How do I code that unit and how do I call it from my 
> first unit?
> 
> As always, thanks for all help!
> 
> 
> 
> 
> #!/usr/bin/env python
> """
> """ 
> from tkinter import *
> from settings import *
> 
> class window1():
> 
> def open_window2(self):
> t = Toplevel(self.root)
> t.title('New window')
> t.geometry('262x65+200+250')
> t.transient(self.root)
> 
> def setup_menu(self):
> self.menubar = Menu(self.root)
> self.menu1 = Menu(self.menubar, tearoff=0 ) 
> self.menu1.add_command(label="Settings",   accelerator='Ctrl+S', 
> command=self.open_window2)
> self.menubar.add_cascade(label="Menu 1", menu=self.menu1)  
> self.root.config(menu=self.menubar)
> 
> def __init__(self):
> self.root = Tk()
> self.root.title('Window #1')
> self.setup_menu()
> self.root.geometry('800x600+200+200')
> #
> self.root.mainloop()
> 
> if __name__ == '__main__':
> 
> w1 = window1()

Thank you - much appreciated!
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Question about asyncio and blocking operations

2016-01-25 Thread Ian Kelly
On Jan 25, 2016 2:04 AM, "Frank Millman"  wrote:
>
> "Ian Kelly"  wrote in message
news:calwzidngogpx+cpmvba8vpefuq4-bwmvs0gz3shb0owzi0b...@mail.gmail.com...
>>
>> This seems to be a common misapprehension about asyncio programming.
>> While coroutines are the focus of the library, they're based on
>> futures, and so by working at a slightly lower level you can also
>> handle them as such. So  while this would be the typical way to use
>> run_in_executor:
>>
>> async def my_coroutine(stuff):
>> value = await get_event_loop().run_in_executor(None,
>> blocking_function, stuff)
>> result = await do_something_else_with(value)
>> return result
>>
>> This is also a perfectly valid way to use it:
>>
>> def normal_function(stuff):
>> loop = get_event_loop()
>> coro = loop.run_in_executor(None, blocking_function, stuff)
>> task = loop.create_task(coro)
>> task.add_done_callback(do_something_else)
>> return task
>
>
> I am struggling to get my head around this.
>
> 1. In the second function, AFAICT coro is already a future. Why is it
necessary to turn it into a task? In fact when I tried that in my testing,
I got an assertion error -
>
> File: "C:\Python35\lib\asyncio\base_events.py", line 211, in create_task
>task = tasks.Task(coro, loop=self)
> File: "C:\Python35\lib\asyncio\tasks.py", line 70, in __init__
>assert coroutines.iscoroutine(coro), repr(coro)
> AssertionError: 

I didn't test this; it was based on the documentation, which says that
run_in_executor is a coroutine. Looking at the source, it's actually a
function that returns a future, so this may be a documentation bug.

There's no need to get a task specifically. We just need a future so that
callbacks can be added, so if the result of run_in_executor is already a
future then the create_task call is unnecessary. To be safe, you could
replace that call with asyncio.ensure_future, which accepts any awaitable
and returns a future.

> 2. In the first function, calling 'run_in_executor' unblocks the main
loop so that it can continue with other tasks, but the function itself is
suspended until the blocking function returns. In the second function, I
cannot see how the function gets suspended. It looks as if the blocking
function will run in the background, and the main function will continue.

Correct. It's not a coroutine, so it has no facility for being suspended
and resumed; it can only block or return. That's why the callback is
necessary to schedule additional code to run after blocking_function
finishes. normal_function itself can continue to make other non-blocking
calls such as scheduling additional tasks, but it shouldn't do anything
that depends on the result of blocking_function since it can't be assumed
to be available yet.

> I would like to experiment with this further, but I would need to see the
broader context - IOW see the 'caller' of normal_function(), and see what
it does with the return value.

The caller of normal_function can do anything it wants with the return
value, including adding additional callbacks or just discarding it. The
caller could be a coroutine or another normal non-blocking function. If
it's a coroutine, then it can await the future, but it doesn't need to
unless it wants to do something with the result. Depending on what the
future represents, it might also be considered internal to normal_function,
in which case it shouldn't be returned at all.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Question about asyncio and blocking operations

2016-01-25 Thread Ian Kelly
On Mon, Jan 25, 2016 at 8:32 AM, Ian Kelly  wrote:
>
> On Jan 25, 2016 2:04 AM, "Frank Millman"  wrote:
>>
>> "Ian Kelly"  wrote in message
>> news:calwzidngogpx+cpmvba8vpefuq4-bwmvs0gz3shb0owzi0b...@mail.gmail.com...
>>>
>>> This seems to be a common misapprehension about asyncio programming.
>>> While coroutines are the focus of the library, they're based on
>>> futures, and so by working at a slightly lower level you can also
>>> handle them as such. So  while this would be the typical way to use
>>> run_in_executor:
>>>
>>> async def my_coroutine(stuff):
>>> value = await get_event_loop().run_in_executor(None,
>>> blocking_function, stuff)
>>> result = await do_something_else_with(value)
>>> return result
>>>
>>> This is also a perfectly valid way to use it:
>>>
>>> def normal_function(stuff):
>>> loop = get_event_loop()
>>> coro = loop.run_in_executor(None, blocking_function, stuff)
>>> task = loop.create_task(coro)
>>> task.add_done_callback(do_something_else)
>>> return task
>>
>>
>> I am struggling to get my head around this.
>>
>> 1. In the second function, AFAICT coro is already a future. Why is it
>> necessary to turn it into a task? In fact when I tried that in my testing, I
>> got an assertion error -
>>
>> File: "C:\Python35\lib\asyncio\base_events.py", line 211, in create_task
>>task = tasks.Task(coro, loop=self)
>> File: "C:\Python35\lib\asyncio\tasks.py", line 70, in __init__
>>assert coroutines.iscoroutine(coro), repr(coro)
>> AssertionError: 
>
> I didn't test this; it was based on the documentation, which says that
> run_in_executor is a coroutine. Looking at the source, it's actually a
> function that returns a future, so this may be a documentation bug.

And now I'm reminded of this note in the asyncio docs:

"""
Note: In this documentation, some methods are documented as
coroutines, even if they are plain Python functions returning a
Future. This is intentional to have a freedom of tweaking the
implementation of these functions in the future. If such a function is
needed to be used in a callback-style code, wrap its result with
ensure_future().
"""

IMO such methods should simply be documented as awaitables, not
coroutines. I wonder if that's already settled, or if it's worth
starting a discussion around.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: tkinter newbie question

2016-01-25 Thread KP
On Monday, 25 January 2016 08:22:12 UTC-8, KP  wrote:
> On Monday, 25 January 2016 00:51:34 UTC-8, Peter Otten  wrote:
> > KP wrote:
> > 
> > > See my code below (which works). 
> > 
> > >From the import of lowercase "tkinter" I conclude you are using Python 3.
> > 
> > > I'd like to have the 2nd window as a
> > > class in a separate unit. How do I code that unit and how do I call it
> > > from my first unit?
> > > 
> > > As always, thanks for all help!
> > 
> > Move the code from open_window2() into a class in settings.py, e. g.
> > 
> > 
> > import tkinter as tk # avoid star-import
> > 
> > class SettingsWindow(tk.Toplevel): # Class names start with uppercase letter
> ># Prefer self-explaining names
> > def __init__(self, root):
> > super().__init__(root)
> > self.title('New window')
> > self.geometry('262x65+200+250')
> > self.transient(root)
> > 
> > Then use it in your main script:
> > 
> > 
> > > #!/usr/bin/env python
> > > """
> > > """
> > > from tkinter import *
> > import settings
> > 
> > > class window1():
> > > 
> > > def open_window2(self):
> >   settings.SettingsWindow(self.root)
> > 
> > > def setup_menu(self):
> > > self.menubar = Menu(self.root)
> > > self.menu1 = Menu(self.menubar, tearoff=0 )
> > > self.menu1.add_command(label="Settings",   accelerator='Ctrl+S',
> > > command=self.open_window2) self.menubar.add_cascade(label="Menu
> > > 1", menu=self.menu1) self.root.config(menu=self.menubar)
> > > 
> > > def __init__(self):
> > > self.root = Tk()
> > > self.root.title('Window #1')
> > > self.setup_menu()
> > > self.root.geometry('800x600+200+200')
> > > #
> > > self.root.mainloop()
> > > 
> > > if __name__ == '__main__':
> > > 
> > > w1 = window1()
> 
> Dang - almost there. Using your code, I get the new window with the specified 
> geometry and its type is transient, as expected.
> 
> Its caption, however, is NOT the caption specified, but the caption of the 
> first window, leaving me with 2 windows with identical caption.
> 
> Any idea why?

Forget that post - mea culpa - figured it out - sorry!
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: tkinter newbie question

2016-01-25 Thread KP
On Monday, 25 January 2016 00:51:34 UTC-8, Peter Otten  wrote:
> KP wrote:
> 
> > See my code below (which works). 
> 
> >From the import of lowercase "tkinter" I conclude you are using Python 3.
> 
> > I'd like to have the 2nd window as a
> > class in a separate unit. How do I code that unit and how do I call it
> > from my first unit?
> > 
> > As always, thanks for all help!
> 
> Move the code from open_window2() into a class in settings.py, e. g.
> 
> 
> import tkinter as tk # avoid star-import
> 
> class SettingsWindow(tk.Toplevel): # Class names start with uppercase letter
># Prefer self-explaining names
> def __init__(self, root):
> super().__init__(root)
> self.title('New window')
> self.geometry('262x65+200+250')
> self.transient(root)
> 
> Then use it in your main script:
> 
> 
> > #!/usr/bin/env python
> > """
> > """
> > from tkinter import *
> import settings
> 
> > class window1():
> > 
> > def open_window2(self):
>   settings.SettingsWindow(self.root)
> 
> > def setup_menu(self):
> > self.menubar = Menu(self.root)
> > self.menu1 = Menu(self.menubar, tearoff=0 )
> > self.menu1.add_command(label="Settings",   accelerator='Ctrl+S',
> > command=self.open_window2) self.menubar.add_cascade(label="Menu
> > 1", menu=self.menu1) self.root.config(menu=self.menubar)
> > 
> > def __init__(self):
> > self.root = Tk()
> > self.root.title('Window #1')
> > self.setup_menu()
> > self.root.geometry('800x600+200+200')
> > #
> > self.root.mainloop()
> > 
> > if __name__ == '__main__':
> > 
> > w1 = window1()

Dang - almost there. Using your code, I get the new window with the specified 
geometry and its type is transient, as expected.

Its caption, however, is NOT the caption specified, but the caption of the 
first window, leaving me with 2 windows with identical caption.

Any idea why?
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: .format won't display my value with 2 decimal places: Why?

2016-01-25 Thread Ian Kelly
On Sun, Jan 24, 2016 at 2:20 PM, MRAB  wrote:
> The format method, on the other hand, belongs to the format string it's
> attached to. In this example:
>
> 'The new price is {}' .format(newPrice, '.2f')
>
> the format string is 'The new price is {}' and you're calling its 'format'
> method with 2 values for that string, the first being 4.0 (used) and the
> second on being '.2f' (unused).
>
> What you want is:
>
> print('The new price is {:.2f}'.format(newPrice))

Why doesn't str.format raise an exception when passed extra positional
arguments?
-- 
https://mail.python.org/mailman/listinfo/python-list


Re[2]: .format won't display my value with 2 decimal places: Why?

2016-01-25 Thread MRAB



On 2016-01-25 16:51:36, "Ian Kelly"  wrote:

On Sun, Jan 24, 2016 at 2:20 PM, MRAB  
wrote:
 The format method, on the other hand, belongs to the format string 
it's

 attached to. In this example:

 'The new price is {}' .format(newPrice, '.2f')

 the format string is 'The new price is {}' and you're calling its 
'format'
 method with 2 values for that string, the first being 4.0 (used) and 
the

 second on being '.2f' (unused).

 What you want is:

 print('The new price is {:.2f}'.format(newPrice))


Why doesn't str.format raise an exception when passed extra positional
arguments?

That format string uses auto-numbering, and it's equivalent to 'The new 
price is {0:.2f}'.


In general, the positional arguments can be used in any order, and there 
can also be keyword arguments, so it would need to remember which 
arguments had been used. Would it be worth it?


Do you really want to insist that the format string always used _all_ of 
the arguments?


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


Re: .format won't display my value with 2 decimal places: Why?

2016-01-25 Thread Chris Angelico
On Tue, Jan 26, 2016 at 3:51 AM, Ian Kelly  wrote:
> On Sun, Jan 24, 2016 at 2:20 PM, MRAB  wrote:
>> The format method, on the other hand, belongs to the format string it's
>> attached to. In this example:
>>
>> 'The new price is {}' .format(newPrice, '.2f')
>>
>> the format string is 'The new price is {}' and you're calling its 'format'
>> method with 2 values for that string, the first being 4.0 (used) and the
>> second on being '.2f' (unused).
>>
>> What you want is:
>>
>> print('The new price is {:.2f}'.format(newPrice))
>
> Why doesn't str.format raise an exception when passed extra positional
> arguments?

That's a very good question. I suspect the answer will have to do with
i18n and the way you can reorder arguments; if some translations don't
use a token at all, it shouldn't be a fatal error that you have to
hack around by formatting something into zero characters.

It may be worth adding a special case: if no positional selectors are
used, the number of arguments must match the number of placeholders.
For comparison, here's how Pike does things (%O is roughly equivalent
to Python's {!r}):

> sprintf("%O", 1);
(1) Result: "1"
> sprintf("%O %O", 1, 2);
(2) Result: "1 2"
> sprintf("%O", 1, 2);
Compiler Error: 1: Too many arguments to sprintf (expected 2 arguments).
Compiler Error: 1: Got : int(2..2).
> sprintf("%[0]O", 1, 2);
(3) Result: "1"
> sprintf("%[1]O", 1, 2);
(4) Result: "2"

If you're doing i18n, you probably want to use {0} {1} anyway; and if
you're deliberately ignoring some of the parameters, it's not too much
hassle to be explicit about which parameters you're not ignoring.

IMO this would be a useful protection. You get it with percent
formatting, but currently not with .format().

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


Re: .format won't display my value with 2 decimal places: Why?

2016-01-25 Thread Random832
On Mon, Jan 25, 2016, at 12:19, MRAB wrote:
> Do you really want to insist that the format string always used _all_ of 
> the arguments?

Um, yes? Why on earth _wouldn't_ you want to insist that?
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: .format won't display my value with 2 decimal places: Why?

2016-01-25 Thread Random832
On Mon, Jan 25, 2016, at 12:23, Chris Angelico wrote:
> if some translations don't use a token at all,

I'm not sure what situation that would be reasonable in.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Re[2]: .format won't display my value with 2 decimal places: Why?

2016-01-25 Thread Ian Kelly
On Mon, Jan 25, 2016 at 10:19 AM, MRAB  wrote:
>
>
> On 2016-01-25 16:51:36, "Ian Kelly"  wrote:
>
>>
>> Why doesn't str.format raise an exception when passed extra positional
>> arguments?
>>
> That format string uses auto-numbering, and it's equivalent to 'The new
> price is {0:.2f}'.
>
> In general, the positional arguments can be used in any order, and there can
> also be keyword arguments, so it would need to remember which arguments had
> been used. Would it be worth it?
>
> Do you really want to insist that the format string always used _all_ of the
> arguments?

Good point, that makes sense. For example, I would expect this to work:

'{0} {2}'.format(*some_list)

as long as some_list has three elements. I wouldn't expect it to fail
just because the middle element is unused, so why should it fail if
there are trailing elements that are unused?
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Re[2]: .format won't display my value with 2 decimal places: Why?

2016-01-25 Thread Chris Angelico
On Tue, Jan 26, 2016 at 4:31 AM, Ian Kelly  wrote:
>> Do you really want to insist that the format string always used _all_ of the
>> arguments?
>
> Good point, that makes sense. For example, I would expect this to work:
>
> '{0} {2}'.format(*some_list)
>
> as long as some_list has three elements. I wouldn't expect it to fail
> just because the middle element is unused, so why should it fail if
> there are trailing elements that are unused?

That's using selectors, so under my suggested semantics, that would
still work - as long as it has *at least* three elements, the middle
one and any extras after the third are all ignored.

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


Re: .format won't display my value with 2 decimal places: Why?

2016-01-25 Thread Chris Angelico
On Tue, Jan 26, 2016 at 4:32 AM, Random832  wrote:
> On Mon, Jan 25, 2016, at 12:23, Chris Angelico wrote:
>> if some translations don't use a token at all,
>
> I'm not sure what situation that would be reasonable in.

I don't do much with different human languages, but it's possible that
you might build up a message in a variety of different ways, and
include tokens differently. Maybe you'd include a product name in two
different places, and each translation would get to choose which of
the lines includes it. Maybe there's a fixed string that carries the
sense of what you're saying better than the parameterized one does, so
you ignore the parameter. It's the same flexibility as reordering
tokens, but some tokens get reordered to nowhere. (Is it still a
teleportation spell when the destination is oblivion? -- Venser)

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


Re: .format won't display my value with 2 decimal places: Why?

2016-01-25 Thread Chris Kaynor
On Mon, Jan 25, 2016 at 9:48 AM, Chris Angelico  wrote:

> On Tue, Jan 26, 2016 at 4:32 AM, Random832  wrote:
> > On Mon, Jan 25, 2016, at 12:23, Chris Angelico wrote:
> >> if some translations don't use a token at all,
> >
> > I'm not sure what situation that would be reasonable in.
>
> I don't do much with different human languages, but it's possible that
> you might build up a message in a variety of different ways, and
> include tokens differently. Maybe you'd include a product name in two
> different places, and each translation would get to choose which of
> the lines includes it. Maybe there's a fixed string that carries the
> sense of what you're saying better than the parameterized one does, so
> you ignore the parameter. It's the same flexibility as reordering
> tokens, but some tokens get reordered to nowhere. (Is it still a
> teleportation spell when the destination is oblivion? -- Venser)


One of the most useful reasons to not require all arguments be used is when
using the string as part of a templating system, though in those cases,
using named (over positional) arguments makes it easiest.

While I have not seen any cases where some arguments go unused in other
languages, it is often useful to generate a bunch of data, and let a
designer or translator decide on the exact arguments to use in a specific
string. Often times, this will mean using different template strings, which
only use a subset (and sometimes even none) of the arguments.

While not using Python, a project I am working on uses this for some of the
data being displayed. In this case, some of the template strings do not use
any template values, while others use multiple, but rather than have to
special case each variation, it can just run the template strings though
formatting code. This is particularly useful in the cases where a quantity
is included, and variations are used for singular vs plural cases.
-- 
https://mail.python.org/mailman/listinfo/python-list


Tkinter spacing

2016-01-25 Thread KP
If I want to have some space between, say, btn_last & btn_new, will I have to 
use a dummy label in between these two or is there a better way?

Thanks for any help, as always!




from tkinter import *
from tkinter import ttk

root = Tk()
root.geometry("822x600+100+100")
nav_bar = ttk.Frame(root, borderwidth=2, relief='ridge', padding=(10, 3, 10, 3))

btn_first  = ttk.Button(nav_bar, text='|<', width=4)  # for buttons showing 
text only, this will be text units (= average characters?)
btn_prev   = ttk.Button(nav_bar, text='<',  width=4)  # for image buttons, it 
will be in pixels 
btn_next   = ttk.Button(nav_bar, text='>',  width=4)
btn_last   = ttk.Button(nav_bar, text='>|', width=4)
btn_new= ttk.Button(nav_bar, text='New')
btn_edit   = ttk.Button(nav_bar, text='Edit')
btn_delete = ttk.Button(nav_bar, text='Delete')
btn_cancel = ttk.Button(nav_bar, text='Cancel')
btn_print  = ttk.Button(nav_bar, text='Print')
btn_help   = ttk.Button(nav_bar, text='Help')
btn_save   = ttk.Button(nav_bar, text='Save')
lbl_Recs   = ttk.Label(nav_bar,  text='Records')
lbl_RCount = ttk.Label(nav_bar,  text='0 ', width=10, borderwidth=2, 
relief='sunken', anchor='e')  # fake entry look

nav_bar.grid(column=0, row=0, columnspan=13)

btn_first.grid(column=0, row=0)
btn_prev.grid(column=1,  row=0)
btn_next.grid(column=2,  row=0)
btn_last.grid(column=3,  row=0)

btn_new.grid(column=4,row=0)
btn_edit.grid(column=5,   row=0)
btn_delete.grid(column=6, row=0)
btn_cancel.grid(column=7, row=0)

lbl_Recs.grid(column=8,   row=0, padx=5)
lbl_RCount.grid(column=9, row=0, padx=5)
btn_print.grid(column=10, row=0)
btn_help.grid(column=11,  row=0)
btn_save.grid(column=12,  row=0)

root.mainloop()
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Question about asyncio and blocking operations

2016-01-25 Thread Rustom Mody
On Monday, January 25, 2016 at 9:16:13 PM UTC+5:30, Ian wrote:
> On Mon, Jan 25, 2016 at 8:32 AM, Ian Kelly wrote:
> >
> > On Jan 25, 2016 2:04 AM, "Frank Millman"  wrote:
> >>
> >> "Ian Kelly"  wrote in message
> >>>
> >>> This seems to be a common misapprehension about asyncio programming.
> >>> While coroutines are the focus of the library, they're based on
> >>> futures, and so by working at a slightly lower level you can also
> >>> handle them as such. So  while this would be the typical way to use
> >>> run_in_executor:
> >>>
> >>> async def my_coroutine(stuff):
> >>> value = await get_event_loop().run_in_executor(None,
> >>> blocking_function, stuff)
> >>> result = await do_something_else_with(value)
> >>> return result
> >>>
> >>> This is also a perfectly valid way to use it:
> >>>
> >>> def normal_function(stuff):
> >>> loop = get_event_loop()
> >>> coro = loop.run_in_executor(None, blocking_function, stuff)
> >>> task = loop.create_task(coro)
> >>> task.add_done_callback(do_something_else)
> >>> return task
> >>
> >>
> >> I am struggling to get my head around this.
> >>
> >> 1. In the second function, AFAICT coro is already a future. Why is it
> >> necessary to turn it into a task? In fact when I tried that in my testing, 
> >> I
> >> got an assertion error -
> >>
> >> File: "C:\Python35\lib\asyncio\base_events.py", line 211, in create_task
> >>task = tasks.Task(coro, loop=self)
> >> File: "C:\Python35\lib\asyncio\tasks.py", line 70, in __init__
> >>assert coroutines.iscoroutine(coro), repr(coro)
> >> AssertionError: 
> >
> > I didn't test this; it was based on the documentation, which says that
> > run_in_executor is a coroutine. Looking at the source, it's actually a
> > function that returns a future, so this may be a documentation bug.
> 
> And now I'm reminded of this note in the asyncio docs:
> 
> """
> Note: In this documentation, some methods are documented as
> coroutines, even if they are plain Python functions returning a
> Future. This is intentional to have a freedom of tweaking the
> implementation of these functions in the future. If such a function is
> needed to be used in a callback-style code, wrap its result with
> ensure_future().
> """
> 
> IMO such methods should simply be documented as awaitables, not
> coroutines. I wonder if that's already settled, or if it's worth
> starting a discussion around.

Bah -- What a bloody mess!
And thanks for pointing this out, Ian.
Keep wondering whether my brain is atrophying, or its rocket science or...
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Question about asyncio and blocking operations

2016-01-25 Thread Marko Rauhamaa
Rustom Mody :

> Bah -- What a bloody mess!
> And thanks for pointing this out, Ian.
> Keep wondering whether my brain is atrophying, or its rocket science or...

I'm afraid the asyncio idea will not fly.

Adding the keywords "async" and "await" did make things much better, but
the programming model seems very cumbersome.

Say you have an async that calls a nonblocking function as follows:


 async def t():
 ...
 f()
 ...

 def f():
 ...
 g()
 ...

 def g():
 ...
 h()
 ...

 def h():
 ...

Then, you need to add a blocking call to h(). You then have a cascading
effect of having to sprinkle asyncs and awaits everywhere:

 async def t():
 ...
 await f()
 ...

 async def f():
 ...
 await g()
 ...

 async def g():
 ...
 await h()
 ...

 async def h():
 ...
 await ...
 ...

A nasty case of nonlocality. Makes you wonder if you ought to declare
*all* functions *always* as asyncs just in case they turn out that way.

Note that neither the multithreading model (which I dislike) nor the
callback hell (which I like) suffer from this problem.


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


Re: Question about asyncio and blocking operations

2016-01-25 Thread Paul Rubin
Marko Rauhamaa  writes:
> Note that neither the multithreading model (which I dislike) nor the
> callback hell (which I like) suffer from this problem.

There are some runtimes (GHC and Erlang) where everything is nonblocking
under the covers, which lets even the asyncs be swept under the rug.
Similarly with some low-tech cooperative multitaskers, say in Forth.
When you've got a mixture of blocking and nonblocking, it becomes a
mess.
-- 
https://mail.python.org/mailman/listinfo/python-list