Re: [Python-ideas] A GUI for beginners and experts alike

2018-08-24 Thread Clément Pit-Claudel
Hi Mike,

Thanks, this code is nice and short.  Is adding 'if button is None: break' to 
the 'Read' version of your code the right way to make it exit when the main 
window is closed? (On my machine it enters an infinite loop after I close the 
main window).

For comparison, I tried doing this with PyGObject.
I created the UI with glade, which auto-generated the attached XML file.  Then 
I had to write the following code (I had never used Glade or PyGObject before, 
so apologies if there are mistakes in the following):

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk

def main():
builder = Gtk.Builder()
builder.add_from_file("sum.glade")

get = builder.get_object
a, b, answer, window = get("a"), get("b"), get("answer"), get("window")

def update_sum(_entry):
try:
tanswer = int(a.get_text()) + int(b.get_text())
answer.set_text(str(tanswer))
except ValueError:
pass

a.connect("changed", update_sum)
b.connect("changed", update_sum)
window.connect("destroy", Gtk.main_quit)

window.show_all()
Gtk.main()

if __name__ == '__main__':
main()

Having a visual editor for the UI feels like a plus, and I find the resulting 
XML verbose but acceptably readable.
On the other hand, I like the conciseness of your UI specs.

Cheers,
Clément.

On 2018-08-24 16:38, Mike Barnett wrote:
> I should have mentioned that you need the GitHub version of the code in order 
> to get the keyboard events. Rather than do a pip install you can download 
> this file and put it in your project folder:
> 
> https://github.com/MikeTheWatchGuy/PySimpleGUI/blob/master/PySimpleGUI.py
> 
> Sorry for any confusion.
> 
> I also got a question if this code blocks or is in a spin-loop.   The answer 
> is that the posted version blocks until some kind of form input.  Should you 
> want to turn the program into one that polls instead of blocks,  the loop 
> changes slightly to enable form close detection.  It's basically the same 
> with the Read call being replaced by ReadNonBlocking.
> 
> while True:
> button, values = form.ReadNonBlocking()
> if button is None and values is None:
> break
> a, b = values
> try:
> output.Update(int(a) + int(b))
> except:
> pass
> 
> 
> 
> @mike
> 
> -Original Message-
> From: Mike Barnett  
> Sent: Friday, August 24, 2018 3:36 PM
> To: Chris Angelico ; Python-Ideas 
> Subject: RE: [Python-ideas] A GUI for beginners and experts alike
> 
> 
> So here's my alternative challenge:
> 
> Take two numbers as inputs. Add them together and display them in a third 
> field. Whenever either input is changed, recalculate the output.
> 
> This requires proper event handling, so it's less likely to create a useless 
> one-liner that has no bearing on real-world code.
> 
> 
> 
> 
> 
> Sure thing... post yours. I'll go ahead and post mine first.
> 
> Here's the window this code produces.
> 
> https://user-images.githubusercontent.com/13696193/44604157-02a2ac00-a7b3-11e8-928b-f67c5f2b3961.jpg
> 
> And here's the code in a more readable form since the email formatting sucks.
> https://user-images.githubusercontent.com/13696193/44604220-2cf46980-a7b3-11e8-86c5-ad3051222eaf.jpg
> 
> It's rather, uhm, simple to do
> 
> 
> import PySimpleGUI as gui
> 
> output = gui.Text('')
> 
> layout = [ [gui.Text('Enter 2 numbers')],
>[gui.Text('A'), gui.InputText()],
>[gui.Text('B'), gui.InputText()],
>[gui.Text('Answer = '), output],
>]
> 
> form = gui.FlexForm('Realtime Updates', return_keyboard_events=True)
> form.LayoutAndRead(layout)
> while True:
> button, (a,b) = form.Read()
> try:
> answer = int(a) + int(b)
> output.Update(answer)
> except:
> pass
> 
> 
> @mike
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
> 



sum.glade
Description: application/glade
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 505: None-aware operators

2018-07-22 Thread Clément Pit-Claudel
On 2018-07-22 08:10, Steven D'Aprano wrote:
> Indeed. And I think we ought to think carefully about the benefits and 
> costs of all of those variants separately.
> 
> To me, the ?? operator seems like a clear and obvious win. The other 
> variants are more complex and the benefit is not as obvious to me, so I 
> haven't decided where I stand on them.

I like the ?? operator too; I like the short circuiting behavior a lot, and the 
semantics are simple.

I guess I'd use the other operators fairly often, too, mostly in quick-n-dirty 
scripts.  The one place where I miss them is when browsing through dictionaries 
that I get by querying a remote server and deserializing the resulting JSON.  I 
foten have situation where the value I'm interested in is e.g. either in 
response[0]["addresses"]["workplace"]["email"], or in 
response["records"][0]["contactInfo"]["emails"][0], and any of these subrecords 
may be missing.

Rewriting these using the ?[…] and ?. operators, I guess I would write 
something like this:

tmp = response?.get("records")
try:
tmp = tmp?[0]
except IndexError:
tmp = None
tmp = tmp?.get("contactInfo")?.get("emails")
try:
tmp = tmp?[0]
except IndexError:
tmp = None

Is there a shorter way to write these with the "?[…]" and "?." operators?  I 
guess the difficulty is that I need to swallow index and key errors, not just 
the type errors that come from indexing into None.

For cases like the one above, I usually use something like nget(response, 
["records"], [0], ["contactInfo"], ["emails"], [0]), where nget is defined as 
shown below (in this use case, the lack of short-circuiting isn't an issue):

def nget(obj, *fields, default=None):
for field in fields:
if obj is None:
return default
if isinstance(field, str):
obj = getattr(obj, field, None)
elif isinstance(field, list):
try:
obj = obj.__getitem__(field[0])
except (TypeError, KeyError, IndexError):
obj = None
return obj

class Test():
def __init__(self):
self.x = [{"y": 42, "z": ["aBc", "def"]}, [1]]

a = Test()
print(nget(a, "x", [0], ["z"], [0], [1]))  # B
print(nget(a, "x", [0], ["y"]))# 42
print(nget(a, "z", [0], ["y"], default="not found"))   # not found
print(nget(a, "z", [57], ["y"], default="not found"))  # not found

It would probably not be hard to wrap this into a special object, to be able to 
write something like 
wrap(response)["records"][0]["contactInfo"]["emails"][0].unwrap(). "wrap" would 
change its argument into a proxy returning a special indexable variant of None 
on key errors, and that dictionary would also call "wrap" on the results of 
__getitem__.  Something like this:

class wrap():
SENTINEL = object()

def __init__(self, obj):
self.obj = obj

def unwrap(self):
return self.obj

def __getitem__(self, key):
try:
return wrap(self.obj.__getitem__(key))
except (TypeError, AttributeError, KeyError):
return wrap(None)

a = [{"y": 42, "z": ["aBc", "def"]}, [1]]
print(wrap(a)[0]["z"][0][1].unwrap())

I think that's more or less what pymaybe does, in fact.

Cheers,
Clément.
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Fwd: Trigonometry in degrees

2018-06-11 Thread Clément Pit-Claudel
On 2018-06-11 14:04, Stephan Houben wrote:
> 2018-06-11 19:33 GMT+02:00 Michael Selik  >:
> 
> Whoops, it turns out Euler's formula does work! I expected imprecision, 
> but at least one test matched.
> 
> x = 42
> cos(x) + 1j * sin(x) == e ** (1j * x)
> 
> 
> I think you will find it holds for any x (except inf, -inf and nan).
> The boat is less leaky than you think; IEEE floating-point arithmetic goes
> out of its way to produce exact answers whenever possible.
> (To great consternation of hardware designers who felt that
> requiring 1.0*x == x was too expensive.)

In fact, 1.0*x == x is almost all that this test exercises.  If I'm looking in 
the right place, this is C the implementation of a ** b, omitting in a few 
special cases:

vabs = hypot(a.real,a.imag);
len = pow(vabs,b.real);
at = atan2(a.imag, a.real);
phase = at*b.real;
if (b.imag != 0.0) {
len /= exp(at*b.imag);
phase += b.imag*log(vabs);
}
r.real = len*cos(phase);
r.imag = len*sin(phase);

This means that (e ** ...) is essentially implemented in terms of the formula 
above.  Indeed, in the special case of e ** (1j * x), we have a.real = e, 
a.imag = 0.0, b.real = 0.0, and b.imag = 1.0, so concretely the code simplifies 
to this:

vabs = e
len = 1.0
at = 0.0
phase = 0.0
if (b.imag != 0.0) {
len = 1.0;
phase = x; // requires log(e) == 1.0 and x * 1.0 == x
}
r.real = cos(phase); // requires 1.0 * x == x
r.imag = sin(phase);

Thus, it shouldn't be too surprising that the formula holds :)

Clément.
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] "any" and "all" support multiple arguments

2017-08-01 Thread Clément Pit-Claudel
On 2017-08-01 17:28, Nick Coghlan wrote:
> Right, the main correspondence here is with "sum()": folks can't write
> "sum(a, b, c)", but they can write "a + b + c".
> 
> The various container constructors are also consistent in only taking
> an iterable, with multiple explicit items being expected to use the
> syntactic forms (e.g. [a, b, c], {a, b, c}, (a, b, c))
> 
> The same rationale holds for any() and all(): supporting multiple
> positional arguments would be redundant with the existing binary
> operator syntax, with no clear reason to ever prefer one option over
> the other.

Isn't there a difference, though, insofar as we don't have a '+/sum' or 
'and/all' equivalent of [a, b, *c]?
You need to write 1 + 3 + sum(xs), or a and b and all(ys).  Or, of course, 
any(chain([a], [b], c)), but that is not pretty.

Clément.
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] namedtuple literals [Was: RE a new namedtuple]

2017-07-20 Thread Clément Pit-Claudel
On 2017-07-20 11:30, Paul Moore wrote:
> On 20 July 2017 at 10:15, Clément Pit-Claudel <cpitclau...@gmail.com> wrote:
>> On 2017-07-20 11:02, Paul Moore wrote:
>>>> Also, what's the advantage of (x=1, y=2) over ntuple(x=1, y=2)? I.e.,
>>>> why does this need to be syntax instead of a library?
>>>
>>> Agreed. Now that keyword argument dictionaries retain their order,
>>> there's no need for new syntax here. In fact, that's one of the key
>>> motivating reasons for the feature.
>>
>> Isn't there a speed aspect?  That is, doesn't the library approach require 
>> creating (and likely discarding) a dictionary every time a new ntuple is 
>> created?  The syntax approach wouldn't need to do that.
> 
> I don't think anyone has suggested that the instance creation time
> penalty for namedtuple is the issue (it's the initial creation of the
> class that affects interpreter startup time), so it's not clear that
> we need to optimise that (at this stage)

Indeed, it's not clear we do.  I was just offering a response to the original 
question, "what's the advantage of (x=1, y=2) over ntuple(x=1, y=2)?".
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] namedtuple literals [Was: RE a new namedtuple]

2017-07-20 Thread Clément Pit-Claudel
On 2017-07-20 11:02, Paul Moore wrote:
>> Also, what's the advantage of (x=1, y=2) over ntuple(x=1, y=2)? I.e.,
>> why does this need to be syntax instead of a library?
>
> Agreed. Now that keyword argument dictionaries retain their order,
> there's no need for new syntax here. In fact, that's one of the key
> motivating reasons for the feature.

Isn't there a speed aspect?  That is, doesn't the library approach require 
creating (and likely discarding) a dictionary every time a new ntuple is 
created?  The syntax approach wouldn't need to do that.

Clément.
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/