Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #41826 > unrolled thread

Help me pick an API design (OO vs functional)

Started byMichael Herrmann <michael.herrmann@getautoma.com>
First post2013-03-25 12:29 -0700
Last post2013-04-04 00:05 -0700
Articles 20 on this page of 44 — 8 participants

Back to article view | Back to comp.lang.python


Contents

  Help me pick an API design (OO vs functional) Michael Herrmann <michael.herrmann@getautoma.com> - 2013-03-25 12:29 -0700
    Re: Help me pick an API design (OO vs functional) Kwpolska <kwpolska@gmail.com> - 2013-03-25 20:42 +0100
      Re: Help me pick an API design (OO vs functional) Michael Herrmann <michael.herrmann@getautoma.com> - 2013-03-25 13:48 -0700
        Re: Help me pick an API design (OO vs functional) Chris Angelico <rosuav@gmail.com> - 2013-03-26 08:08 +1100
          Re: Help me pick an API design (OO vs functional) Michael Herrmann <michael.herrmann@getautoma.com> - 2013-03-26 01:53 -0700
            Re: Help me pick an API design (OO vs functional) Chris Angelico <rosuav@gmail.com> - 2013-03-26 22:38 +1100
              Re: Help me pick an API design (OO vs functional) Michael Herrmann <michael.herrmann@getautoma.com> - 2013-03-26 05:13 -0700
              Re: Help me pick an API design (OO vs functional) Michael Herrmann <michael.herrmann@getautoma.com> - 2013-03-26 05:13 -0700
      Re: Help me pick an API design (OO vs functional) Michael Herrmann <michael.herrmann@getautoma.com> - 2013-03-25 13:48 -0700
    Re: Help me pick an API design (OO vs functional) Ethan Furman <ethan@stoneleaf.us> - 2013-03-25 16:11 -0700
      Re: Help me pick an API design (OO vs functional) Michael Herrmann <michael.herrmann@getautoma.com> - 2013-03-26 02:06 -0700
        Re: Help me pick an API design (OO vs functional) Dave Angel <davea@davea.name> - 2013-03-26 06:26 -0400
          Re: Help me pick an API design (OO vs functional) Michael Herrmann <michael.herrmann@getautoma.com> - 2013-03-26 05:04 -0700
            Re: Help me pick an API design (OO vs functional) Dave Angel <davea@davea.name> - 2013-03-26 08:42 -0400
              Re: Help me pick an API design (OO vs functional) Michael Herrmann <michael.herrmann@getautoma.com> - 2013-03-26 07:33 -0700
                Re: Help me pick an API design (OO vs functional) Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-03-26 22:37 +0000
                  Re: Help me pick an API design (OO vs functional) Michael Herrmann <michael.herrmann@getautoma.com> - 2013-03-27 02:34 -0700
                    Re: Help me pick an API design (OO vs functional) Ethan Furman <ethan@stoneleaf.us> - 2013-03-27 09:45 -0700
                      Re: Help me pick an API design (OO vs functional) Michael Herrmann <michael.herrmann@getautoma.com> - 2013-03-28 03:54 -0700
                    Re: Help me pick an API design (OO vs functional) Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-03-28 00:42 +0000
                      Re: Help me pick an API design (OO vs functional) Michael Herrmann <michael.herrmann@getautoma.com> - 2013-03-28 04:41 -0700
            Re: Help me pick an API design (OO vs functional) Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-03-26 12:59 +0000
              Re: Help me pick an API design (OO vs functional) Michael Herrmann <michael.herrmann@getautoma.com> - 2013-03-26 07:26 -0700
    Re: Help me pick an API design (OO vs functional) Mitya Sirenef <msirenef@lightbird.net> - 2013-03-25 19:40 -0400
      Re: Help me pick an API design (OO vs functional) Michael Herrmann <michael.herrmann@getautoma.com> - 2013-03-26 02:38 -0700
        Re: Help me pick an API design (OO vs functional) Chris Angelico <rosuav@gmail.com> - 2013-03-26 22:43 +1100
          Re: Help me pick an API design (OO vs functional) Michael Herrmann <michael.herrmann@getautoma.com> - 2013-03-26 05:18 -0700
        Re: Help me pick an API design (OO vs functional) Mitya Sirenef <msirenef@lightbird.net> - 2013-03-26 09:41 -0400
          Re: Help me pick an API design (OO vs functional) Michael Herrmann <michael.herrmann@getautoma.com> - 2013-03-26 07:59 -0700
            Re: Help me pick an API design (OO vs functional) Chris Angelico <rosuav@gmail.com> - 2013-03-27 02:16 +1100
              Re: Help me pick an API design (OO vs functional) Michael Herrmann <michael.herrmann@getautoma.com> - 2013-03-27 01:45 -0700
            Re: Help me pick an API design (OO vs functional) Mitya Sirenef <msirenef@lightbird.net> - 2013-03-26 18:01 -0400
              Re: Help me pick an API design (OO vs functional) Michael Herrmann <michael.herrmann@getautoma.com> - 2013-03-27 02:10 -0700
                Re: Help me pick an API design (OO vs functional) Mitya Sirenef <msirenef@lightbird.net> - 2013-03-27 09:56 -0400
                  Re: Help me pick an API design (OO vs functional) Michael Herrmann <michael.herrmann@getautoma.com> - 2013-03-28 03:52 -0700
      Re: Help me pick an API design (OO vs functional) Neil Cerutti <neilc@norwich.edu> - 2013-03-26 14:13 +0000
        Re: Help me pick an API design (OO vs functional) Michael Herrmann <michael.herrmann@getautoma.com> - 2013-03-26 07:40 -0700
          Re: Help me pick an API design (OO vs functional) Dave Angel <davea@davea.name> - 2013-03-26 12:41 -0400
            Re: Help me pick an API design (OO vs functional) Neil Cerutti <neilc@norwich.edu> - 2013-03-26 17:25 +0000
            Re: Help me pick an API design (OO vs functional) Michael Herrmann <michael.herrmann@getautoma.com> - 2013-03-27 01:55 -0700
              Re: Help me pick an API design (OO vs functional) Chris Angelico <rosuav@gmail.com> - 2013-03-27 22:44 +1100
                Re: Help me pick an API design (OO vs functional) Michael Herrmann <michael.herrmann@getautoma.com> - 2013-03-27 05:23 -0700
                Re: Help me pick an API design (OO vs functional) Michael Herrmann <michael.herrmann@getautoma.com> - 2013-03-27 05:23 -0700
    Re: Help me pick an API design (OO vs functional) Michael Herrmann <michael.herrmann@getautoma.com> - 2013-04-04 00:05 -0700

Page 2 of 3 — ← Prev page 1 [2] 3  Next page →


#42118

FromMichael Herrmann <michael.herrmann@getautoma.com>
Date2013-03-28 04:41 -0700
Message-ID<367d05b1-bb24-418f-a40e-3fb2287af12a@googlegroups.com>
In reply to#42051
On Thursday, March 28, 2013 1:42:35 AM UTC+1, Steven D'Aprano wrote:
> On Wed, 27 Mar 2013 02:34:09 -0700, Michael Herrmann wrote:
> 
> > On Tuesday, March 26, 2013 11:37:23 PM UTC+1, Steven D'Aprano wrote:
> >> 
> >> Global *variables* are bad, not global functions. You have one global
> >> variable, "the current window". So long as your API makes it obvious
> >> when the current window changes, implicitly operating on the current
> >> window is no more dangerous than Python's implicit operations on the
> >> current namespace (e.g. "x = 2" binds 2 to x in the current namespace).
> 
> > I'm generally wary of everything global, but you're right as long as no
> > (global) state is involved.
> 
> That comment surprises me. Your preferred API:
> 
> switch_to(notepad)
> write("Hello World!")
> press(CTRL + 'a', CTRL + 'c')
> 
> uses implied global state (the current window). Even if you avoid the use 
> of an actual global for (say) an instance attribute, it's still 
> semantically a global. Surely you realise that?

I do :-) You made the statement that global variables are bad, not global functions. I didn't want to agree completely with this comment, because if a global function refers to a global variable, I would consider it "bad" too. You correctly point out that our global functions would be exactly of that "bad" kind. Of course, it doesn't make sense to be too dogmatic about "bad", which is why I am considering the global functions as an option, for advantages they have despite being "bad".

> Not trying to be argumentative, I'm just surprised at your comment.

No offense taken :) I guess I just wasn't expressing myself clearly.

> > ...
> > After everybody's input, I think Design #2 or Design #4 would be the
> > best fit for us:
> > 
> > Design #2:
> >         notepad_1 = start("Notepad")
> >         notepad_2 = start("Notepad")
> >         switch_to(notepad_1)
> >         write("Hello World!")
> >         press(CTRL + 'a', CTRL + 'c')
> >         switch_to(notepad_2)
> >         press(CTRL + 'v')
> 
> This is nice syntax for trivial cases and beginners whose needs are not 
> demanding, but annoying for experts who have more complicated 
> requirements. If this is the only API, experts who need to simultaneously 
> operate in two windows will be forced to write unproductive boilerplate 
> code that does nothing but jump from window to window.
> 
> 
> Well what do you know, even in the simple case above, you have 
> unproductive code that does nothing but jump from window to window :-)
> 
> I'm not against this API, I'm just against it as the *only* API.
> 
> > Design #4:
> >         notepad_1 = start("Notepad")
> >         notepad_2 = start("Notepad")
> >         notepad_1.activate()
> >         write("Hello World!")
> >         press(CTRL + 'a', CTRL + 'c')
> >         notepad_2.activate()
> >         press(CTRL + 'v')
> 
> This is actually no different from #2 above, except that it uses method 
> call syntax while #2 uses function call syntax. So it has the same 
> limitations as above: it's simple for simple uses, but annoying for 
> complex use.
> 
> Neither API supports advanced users with complicated needs. A hybrid 
> approach, where you have function call syntax that operates on the 
> implicit current window, plus method call syntax that operates on any 
> window, strikes me as the best of both worlds. With a little forethought 
> in your implementation, you don't have to duplicate code. E.g. something 
> like this:
> 
> class WindowOps:
>     def __init__(self, theWindow=None):
>         self.theWindow = None
> 
>     def press(self, c):
>         win = self.getWindow()
>         send_keypress_to(win)
> 
>     def getWindow(self):
>         if self.theWindow is None:
>             return gTheTopWindow
>         return self.theWindow
> 
> _implicit = WindowOps(None)
> press = _implicit.press
> # etc.
> del _implicit
> 
> This gives you the best of both worlds, for free: a simple API using an 
> implicit top window for simple cases, and a slightly more complex API 
> with an explicit window for advanced users.

I understand completely where you are coming from, however if we offer two ways of doing the same thing, people will start mixing the styles and things will get messy. A user commented above that this approach - offering global as well as object oriented functions to do the same thing - is offered by matplotlib and makes examples on the net very confusing and difficult to read. For this reason, I would rather only offer one way of doing things now, and add additional ways later in case they are really needed. You are right that this may not cater for experts' needs very well, but I think I prefer a smaller API that can be extended to one that may result in being difficult to read.

> > Normally, I'd go for Design #4, as it results in one less global,
> 
> I don't see how this is possible. Both APIs use an implicit "top window". 
> What's the one less global you are referring to?

By "global" I meant function name.

> > is
> > better for autocompletion etc. The thing with our library is that it
> > tries to make its scripts as similar as possible to giving instructions
> > to someone looking over their shoulder at a screen. And in this
> > situation you would just say
> >        activate(notepad)
> > rather than
> >        notepad.activate().
> 
> Depends like Yoda they talk whether or not.
> 
> Unless you go all the way to writing your own parser that accepts English-
> like syntax, like Hypertalk:
> 
> select notepad
> type hello world
> 
> I don't think it makes that much difference. Function call syntax is not 
> exactly English-like either. We don't generally speak like this:
> 
> write bracket quote hello world quote close bracket
> 
> My personal feeling is that people aren't going to be *too* confused by 
> method call syntax, especially not if they've seen or been introduced to 
> any programming at all. You say tom-a-to, I say tom-ar-to.
> 
> But I think it is useful to distinguish between the "basic API" using 
> function call syntax and an implied current window, and an "advanced API" 
> using method call syntax with an explicit window:
> 
> 
> # Basic API is pure function calls, using an implicit window
> 
> switch_to(notepad)
> write("Hello World!")
> press(CTRL + 'a', CTRL + 'c')
> switch_to(calculator)
> write('2+3=')
> press(CTRL + 'a')
> switch_to(notepad)
> press(CTRL + 'v')
> 
> # Advanced API uses an explicit window and method calls:
> 
> notepad.write("Hello World!")
> notepad.press(CTRL + 'a', CTRL + 'c')
> calculator.write('2+3=')
> calculator.press(CTRL + 'a')
> notepad.press(CTRL + 'v')
> 
> # Of course you can mix usage:
> 
> switch_to(notepad)
> write("Hello World!")
> press(CTRL + 'a', CTRL + 'c')
> calculator.write('2+3=')
> calculator.press(CTRL + 'a')
> press(CTRL + 'v')

As I said, I think I prefer not giving the possibility to mix usage and potentially adding it later over offering it to begin with. 

> You could avoid method call syntax altogether by giving your functions an 
> optional argument that points to the window to operate on:
> 
> write("Hello World!")
> write("Hello World!", notepad)
> 
> but the difference is mere syntax.

That's been pointed out above. I guess it's mostly a question of taste, but I'd like to avoid mixing the concept of "window switching" with the not-very related concepts of typing and clicking. I'm a big fan of orthogonality, mainly because of the book "The Pragmatic Programmer" but also because of the article http://www.artima.com/intv/dry3.html.

> There's little or no additional complexity of implementation to allow the 
> user to optionally specify an explicit window. 

That's of course true. What I'm worried about is API complexity: I think the matplotlib example shows that offering too many ways of doing one thing leads to scripts that are difficult to read/maintain. I want to keep the API as simple as possible at first, and then add to it when it turns out it's needed.

> ...
> See, for example, the decimal module. Most operations take an optional 
> "context" argument that specifies the number of decimal places, rounding 
> mode, etc. If not supplied, the global "current context" is used.
> This gives the simplicity and convenience of a global, without the 
> disadvantages.

That's a very interesting example! I think the decimal module's "setcontext" would be similar to our "switch_to". The fact that this module offers the optional "context" parameter makes it likely that you'll prove me wrong in not including offering such an optional parameter, but I want to see first if we can get by without it, too.

Thanks for all your input.

Michael
www.getautoma.com

[toc] | [prev] | [next] | [standalone]


#41898

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2013-03-26 12:59 +0000
Message-ID<51519bcd$0$29998$c3e8da3$5496439d@news.astraweb.com>
In reply to#41886
On Tue, 26 Mar 2013 05:04:43 -0700, Michael Herrmann wrote:

> On Tuesday, March 26, 2013 11:26:30 AM UTC+1, Dave Angel wrote:
>> ...
>> Seems to me that the official interface should all be methods. 
>> However, you could have a new object which always represents the
>> "focus" window.
>>   Then the USER could define trivial functions:
>> 
>> def write(*args):
>>      focused.write(*args)
> 
> It's an interesting idea. But why not give this write(...) to them in
> the first place? Am I the only one who appreciates the simplicity of
> 
>         start("Notepad")
>         write("Hello World!")
>         press(CTRL + 's')
>         write("test.txt", into="File name")
>         click("Save")
>         press(ALT + F4)
> 
> over
> 
>         notepad = start("Notepad")
>         notepad.write("Hello World!")
>         notepad.press(CTRL + 's')
>         notepad.write("test.txt", into="File name")
>         notepad.click("Save")
>         notepad.press(ALT + F4)?

You are not the only one.

I suggest that you have a set of functions that work on "the current 
window", whatever that is. Preferably there should always be a current 
window, but if not, ensure that you give a clear error message.

Then you have syntax for operating on any named(?) window. So a user can 
implicitly operate on the current window:

select(notepad)
write("goodbye cruel world")
save()

or explicitly on any window they like:

excel.quit()


I suggest you dig up an old book on "Hypercard", for Apple Macs in the 
1980s and 90s. Back in the day, Macs could only run a single application 
at a time, and Hypercard was limited to a single window at a time (called 
a "stack"). But that stack (think: window) could have multiple 
"cards" (think: window tabs), one of which was always current. 
Hypercard's built-in programming language Hypertalk let you do things 
like this:


go to stack "Notepad"
type "goodbye cruel world" in field "main" of card 7
click button "Save"

click button "Quit" of card "Main" of stack "Excel"


(more or less... it's been a few years since I've had a classic Mac 
capable of running Hypercard.)




-- 
Steven

[toc] | [prev] | [next] | [standalone]


#41905

FromMichael Herrmann <michael.herrmann@getautoma.com>
Date2013-03-26 07:26 -0700
Message-ID<2deabbbd-7f39-4434-872b-a903f5c2d305@googlegroups.com>
In reply to#41898
On Tuesday, March 26, 2013 1:59:58 PM UTC+1, Steven D'Aprano wrote:
> On Tue, 26 Mar 2013 05:04:43 -0700, Michael Herrmann wrote:
> ...
> Am I the only one who appreciates the simplicity of
> 
> >         start("Notepad")
> >         write("Hello World!")
> >         press(CTRL + 's')
> >         write("test.txt", into="File name")
> >         click("Save")
> >         press(ALT + F4)
> 
> > over
> 
> >         notepad = start("Notepad")
> >         notepad.write("Hello World!")
> >         notepad.press(CTRL + 's')
> >         notepad.write("test.txt", into="File name")
> >         notepad.click("Save")
> >         notepad.press(ALT + F4)?
> 
> You are not the only one.
> 
> I suggest that you have a set of functions that work on "the current 
> window", whatever that is. Preferably there should always be a current 
> window, but if not, ensure that you give a clear error message.

This is exactly the way it is currently. I am glad you also see it that way.

> Then you have syntax for operating on any named(?) window. So a user can 
> implicitly operate on the current window:
> 
> select(notepad)
> write("goodbye cruel world")
> save()

One idea would be to use the Window(...) constructor to select windows:

    notepad = Window('Untitled - Notepad')
    select(notepad)
    save()

One advantage of using a global method to switch to a window is that this would allow you to directly switch to a Window without having to call Window(...):

    switch_to('Untitled - Notepad')

I'm still not fully convinced of a global method though, for the reasons several people here have already mentioned.

> or explicitly on any window they like:
> 
> excel.quit()

This example makes it look likely that there will have to be other operations that can be performed on windows (/running applications as Dave pointed out). So, a 'quit()' method that closes a window in addition to the already mentioned focus/select/activate method. This in turn makes the global function less attractive as once we start going down that route, global functions will proliferate.

> I suggest you dig up an old book on "Hypercard", for Apple Macs in the 
> 1980s and 90s. Back in the day, Macs could only run a single application 
> at a time, and Hypercard was limited to a single window at a time (called 
> a "stack"). But that stack (think: window) could have multiple 
> "cards" (think: window tabs), one of which was always current. 
> Hypercard's built-in programming language Hypertalk let you do things 
> like this:
> 
> go to stack "Notepad"
> type "goodbye cruel world" in field "main" of card 7
> click button "Save"
> click button "Quit" of card "Main" of stack "Excel"
> 
> (more or less... it's been a few years since I've had a classic Mac 
> capable of running Hypercard.)

Very interesting. I had never heard of HyperCard. I read up on it a little and it sounds very similar to the model we are internally building of open applications (stacks) and their windows (cards). Also funny that HyperCard was one of Ward Cunningham's inspirations for coming up with the Wiki idea: http://c2.com/cgi/wiki?WikiWikiHyperCard

Thanks for this!

Michael
www.getautoma.com

[toc] | [prev] | [next] | [standalone]


#41838

FromMitya Sirenef <msirenef@lightbird.net>
Date2013-03-25 19:40 -0400
Message-ID<mailman.3706.1364254851.2939.python-list@python.org>
In reply to#41826
On 03/25/2013 03:29 PM, Michael Herrmann wrote:
> Hello everyone,
>
> my name is Michael, I'm the lead developer of a Python GUI automation library for Windows called Automa: http://www.getautoma.com. We want to add some features to our library but are unsure how to best expose them via our API. It would be extremely helpful for us if you could let us know which API design feels "right" to you.
>
> Our API already offers very simple commands for automating the GUI of a Windows computer. For example:
>
> 	from automa.api import *
> 	start("Notepad")
> 	write("Hello World!")
> 	press(CTRL + 's')
> 	write("test.txt", into="File name")
> 	click("Save")
> 	click("Close")
>
> When you execute this script, Automa starts Notepad and simulates key strokes, mouse movements and clicks to perform the required commands. At the moment, each action is performed in the currently active window.
>
> We do not (yet) have a functionality that allows you to explicitly switch to a specific window. Such a functionality would for instance make it possible to open two Notepad windows using the start(...) command, and copy text between them.
>
> One API design would be to have our start(...) function return a "Window" (say) object, whose methods allow you to do the same operations as the global functions write(...), press(...), click(...) etc., but in the respective window. In this design, the example of operating two Notepad windows could be written as
>
> 	notepad_1 = start("Notepad")
> 	notepad_2 = start("Notepad")
> 	notepad_1.write("Hello World!")
> 	notepad_1.press(CTRL + 'a', CTRL + 'c')
> 	notepad_2.press(CTRL + 'v')
>
> The problem with this design is that it effectively duplicates our API: We want to keep our "global" functions because they are so easy to read. If we add methods to a new "Window" class that do more or less the same, we feel that we are violating Python's principle that "There should be one - and preferably only one - obvious way to do it."
>
> An alternative design would be to make the window switching an explicit action. One way of doing this would be to add a new global function, say "switch_to" or "activate", that takes a single parameter that identifies the window to be switched to. We could still have start(...) return a Window object, that could then be passed to our function:
>
> 	notepad_1 = start("Notepad")
> 	notepad_2 = start("Notepad")
> 	switch_to(notepad_1)
> 	write("Hello World!")
> 	press(CTRL + 'a', CTRL + 'c')
> 	switch_to(notepad_2)
> 	press(CTRL + 'v')
>
> Maybe our Window objects could also be used as context managers:
>
> 	notepad_1 = start("Notepad")
> 	notepad_2 = start("Notepad")
> 	with notepad_1:
> 		write("Hello World!")
> 		press(CTRL + 'a', CTRL + 'c')
> 	with notepad_2:
> 		press(CTRL + 'v')
>
> As a final idea, switching could also be done as a method of the Window class:
>
> 	notepad_1 = start("Notepad")
> 	notepad_2 = start("Notepad")
> 	notepad_1.activate()
> 	write("Hello World!")
> 	press(CTRL + 'a', CTRL + 'c')
> 	notepad_2.activate()
> 	press(CTRL + 'v')
>
> It would be extremely helpful for us if you could let me know which way of using the API you would prefer. If you opt for an explicit version, how would you call the respective method? "activate" / "switch_to" / "focus" or something else?
>
> Thank you so much!
>
> Best wishes,
> Michael


I think I would prefer context managers. I don't think it's a big 
problem for
win users because this behaviour would be one of the first things documented
in the start guide and would be all over example scripts, so a new user 
missing
or forgetting it is not a realistic scenario.

The advantages are that it's explicit, blocks are indented and it's 
impossible to
miss which window is the action applied to, and at the same time actions are
short and easy to type and read.

  -m


-- 
Lark's Tongue Guide to Python: http://lightbird.net/larks/

[toc] | [prev] | [next] | [standalone]


#41868

FromMichael Herrmann <michael.herrmann@getautoma.com>
Date2013-03-26 02:38 -0700
Message-ID<01a290d9-6a59-45ad-bc30-e09d13aa7799@googlegroups.com>
In reply to#41838
On Tuesday, March 26, 2013 12:40:45 AM UTC+1, Mitya Sirenef wrote:
> ...
> 
> I think I would prefer context managers. I don't think it's a big 
> problem for
> win users because this behaviour would be one of the first things documented
> in the start guide and would be all over example scripts, so a new user 
> missing
> or forgetting it is not a realistic scenario.
> 
> The advantages are that it's explicit, blocks are indented and it's 
> impossible to
> miss which window is the action applied to, and at the same time actions are
> short and easy to type and read.

Thank you for your reply. What do you think of Chris Angelico's points?
He wrote:
> What happens at the __exit__ of the context manager? What happens if 
> context managers are nested? I'd be inclined to the simpler option of 
> an explicit switch (since focus doesn't really "stack" and it'd feel 
> weird for focus to *sometimes* switch away when you're done working 
> with one window), though the context manager syntax does have its 
> advantages too. 

What I am most afraid of: that the window that's currently the context "disappears":
	notepad = start("Notepad")
	with notepad:
		press(ALT + TAB)
		write("Am I in Notepad now?")

What do you think of designs #3 and #4?

        notepad_1 = start("Notepad") 
        notepad_2 = start("Notepad") 
        switch_to(notepad_1) 
        write("Hello World!") 
        press(CTRL + 'a', CTRL + 'c') 
        switch_to(notepad_2) 
        press(CTRL + 'v') 

        notepad_1 = start("Notepad") 
        notepad_2 = start("Notepad") 
        notepad_1.activate() 
        write("Hello World!") 
        press(CTRL + 'a', CTRL + 'c') 
        notepad_2.activate() 
        press(CTRL + 'v')

I somehow prefer "activate" over "focus" as in my feeling, you'd normally say that you focus *on* something, so it should be called "focus_on" or "give_focus[_to]". Can you say, in everyday English, that you "focus a window"? I'm not a native speaker so maybe my feeling is misguided.

Thanks,
Michael

[toc] | [prev] | [next] | [standalone]


#41882

FromChris Angelico <rosuav@gmail.com>
Date2013-03-26 22:43 +1100
Message-ID<mailman.3736.1364298201.2939.python-list@python.org>
In reply to#41868
On Tue, Mar 26, 2013 at 8:38 PM, Michael Herrmann
<michael.herrmann@getautoma.com> wrote:
> What do you think of designs #3 and #4?
>
>         notepad_1 = start("Notepad")
>         notepad_2 = start("Notepad")
>         switch_to(notepad_1)
>         write("Hello World!")
>         press(CTRL + 'a', CTRL + 'c')
>         switch_to(notepad_2)
>         press(CTRL + 'v')
>
>         notepad_1 = start("Notepad")
>         notepad_2 = start("Notepad")
>         notepad_1.activate()
>         write("Hello World!")
>         press(CTRL + 'a', CTRL + 'c')
>         notepad_2.activate()
>         press(CTRL + 'v')

Ehh, I referred to these as options 2 and 4. Got lost in the indexing
somewhere. These are the same two I meant, though - these are the
options I think are the most plausible.

(Hindsight being 20/20, it'd have been awesome if the original
snippets had had identifiers next to them. Oh well, no matter.)

ChrisA

[toc] | [prev] | [next] | [standalone]


#41889

FromMichael Herrmann <michael.herrmann@getautoma.com>
Date2013-03-26 05:18 -0700
Message-ID<99417dba-d543-4a61-9cea-54638e9cbf4a@googlegroups.com>
In reply to#41882
On Tuesday, March 26, 2013 12:43:18 PM UTC+1, Chris Angelico wrote:
> On Tue, Mar 26, 2013 at 8:38 PM, Michael Herrmann
> 
> > What do you think of designs #3 and #4?
> 
> >         notepad_1 = start("Notepad")
> >         notepad_2 = start("Notepad")
> >         switch_to(notepad_1)
> >         write("Hello World!")
> >         press(CTRL + 'a', CTRL + 'c')
> >         switch_to(notepad_2)
> >         press(CTRL + 'v')
> >
> 
> >         notepad_1 = start("Notepad")
> >         notepad_2 = start("Notepad")
> >         notepad_1.activate()
> >         write("Hello World!")
> >         press(CTRL + 'a', CTRL + 'c')
> >         notepad_2.activate()
> >         press(CTRL + 'v')
> 
> Ehh, I referred to these as options 2 and 4. Got lost in the indexing
> somewhere. These are the same two I meant, though - these are the
> options I think are the most plausible.
> 
> (Hindsight being 20/20, it'd have been awesome if the original
> snippets had had identifiers next to them. Oh well, no matter.)

True, and the indexing mistake was my fault... Here goes:

Design #1:
        notepad_1 = start("Notepad") 
        notepad_2 = start("Notepad") 
        notepad_1.write("Hello World!") 
        notepad_1.press(CTRL + 'a', CTRL + 'c') 
        notepad_2.press(CTRL + 'v')

Design #2:
        notepad_1 = start("Notepad") 
        notepad_2 = start("Notepad") 
        switch_to(notepad_1) 
        write("Hello World!") 
        press(CTRL + 'a', CTRL + 'c') 
        switch_to(notepad_2) 
        press(CTRL + 'v')

Design #3:
        notepad_1 = start("Notepad") 
        notepad_2 = start("Notepad") 
        with notepad_1: 
                write("Hello World!") 
                press(CTRL + 'a', CTRL + 'c') 
        with notepad_2: 
                press(CTRL + 'v')

Design #4:
        notepad_1 = start("Notepad") 
        notepad_2 = start("Notepad") 
        notepad_1.activate() 
        write("Hello World!") 
        press(CTRL + 'a', CTRL + 'c') 
        notepad_2.activate() 
        press(CTRL + 'v')

Michael
www.getautoma.com

[toc] | [prev] | [next] | [standalone]


#41901

FromMitya Sirenef <msirenef@lightbird.net>
Date2013-03-26 09:41 -0400
Message-ID<mailman.3746.1364305302.2939.python-list@python.org>
In reply to#41868
On 03/26/2013 05:38 AM, Michael Herrmann wrote:
> On Tuesday, March 26, 2013  12:40:45 AM UTC+1, Mitya Sirenef wrote:
 >> ...
 >>
 >> I think I would prefer context managers. I don't think it's a big
 >> problem for
 >> win users because this behaviour would be one of the first things 
documented
 >> in the start guide and would be all over example scripts, so a new user
 >> missing
 >> or forgetting it is not a realistic scenario.
 >>
 >> The advantages are that it's explicit, blocks are indented and it's
 >> impossible to
 >> miss which window is the action applied to, and at the same time 
actions are
 >> short and easy to type and read.
 >
 > Thank you for your reply. What do you think of Chris Angelico's points?


At the __exit__, further commands are no longer routed to that window;
if it was a nested context, window is switched to the outer context,
WHEN there are commands in it (i.e. on the first command). This seems
pretty intuitive to me:

with notepad1:
     ^S
     with notepad2:
         ^S
     write('something')

>
 > He wrote:
 >> What happens at the __exit__ of the context manager? What happens if
 >> context managers are nested? I'd be inclined to the simpler option of
 >> an explicit switch (since focus doesn't really "stack" and it'd feel
 >> weird for focus to *sometimes* switch away when you're done working
 >> with one window), though the context manager syntax does have its
 >> advantages too.
 >
 > What I am most afraid of: that the window that's currently the 
context "disappears":
 >     notepad = start("Notepad")
 >     with notepad:
 >         press(ALT + TAB)
 >         write("Am I in Notepad now?")


Alt-tab needs to be handled by a wrapper function that gives you the
object of the window you've switched to:

otherwin = alt_tab()
with otherwin:
     ...

If window is changed within 'with' block, the rest of block should be
ignored. Perhaps there could also be a way to switch this behaviour off,
for the entire script or for current block only.

>
 > What do you think of designs #3 and #4?
 >
 >         notepad_1 = start("Notepad")
 >         notepad_2 = start("Notepad")
 >         switch_to(notepad_1)
 >         write("Hello World!")
 >         press(CTRL + 'a', CTRL + 'c')
 >         switch_to(notepad_2)
 >         press(CTRL + 'v')
 >
 >         notepad_1 = start("Notepad")
 >         notepad_2 = start("Notepad")
 >         notepad_1.activate()
 >         write("Hello World!")
 >         press(CTRL + 'a', CTRL + 'c')
 >         notepad_2.activate()
 >         press(CTRL + 'v')
 >
 > I somehow prefer "activate" over "focus" as in my feeling, you'd 
normally say that you focus *on* something, so it should be called 
"focus_on" or "give_focus[_to]". Can you say, in everyday English, that 
you "focus a window"? I'm not a native speaker so maybe my feeling is 
misguided.


These are ok, too, but I feel it's much easier to send commands to a
wrong window vs. context managers. The same command in a different
window can have vastly different and dangerous effect. In other python
code that's generally not common at all, and would be bad style:

lst = lst1
lst.append('x')
del lst[3]
lst.insert(0, 'a')
lst = lst2
del lst[2]
lst.append('y')
lst = lst3
lst.insert(0, 'x')
lst += [1,2]


I think current window should also be acquired explicitly:

with get_current_window():
     type("some kind of snippet")

For usage when a command should apply to all types of windows.

HTH, -m



-- 
Lark's Tongue Guide to Python: http://lightbird.net/larks/

Food is an important part of a balanced diet.
Fran Lebowitz

[toc] | [prev] | [next] | [standalone]


#41909

FromMichael Herrmann <michael.herrmann@getautoma.com>
Date2013-03-26 07:59 -0700
Message-ID<c2b7ea32-f73c-4613-bbaf-b40492c469f2@googlegroups.com>
In reply to#41901
On Tuesday, March 26, 2013 2:41:38 PM UTC+1, Mitya Sirenef wrote:
> ... 
> At the __exit__, further commands are no longer routed to that window;
> if it was a nested context, window is switched to the outer context,
> WHEN there are commands in it (i.e. on the first command). This seems
> pretty intuitive to me:
> 
> with notepad1:
>      ^S
>      with notepad2:
>          ^S
>      write('something')
> 

> ...
>  > What I am most afraid of: that the window that's currently the 
>  > context "disappears":
> 
>  >     notepad = start("Notepad")
>  >     with notepad:
>  >         press(ALT + TAB)
>  >         write("Am I in Notepad now?")
> 
> 
> Alt-tab needs to be handled by a wrapper function that gives you the
> object of the window you've switched to:
> 
> otherwin = alt_tab()
> with otherwin:
>      ...
> 
> If window is changed within 'with' block, the rest of block should be
> ignored. Perhaps there could also be a way to switch this behaviour off,
> for the entire script or for current block only.
> 
> 
>  > What do you think of designs #3 and #4?
>  > ...
> 
> These are ok, too, but I feel it's much easier to send commands to a
> wrong window vs. context managers. The same command in a different
> window can have vastly different and dangerous effect. In other python
> code that's generally not common at all, and would be bad style:
> 
> lst = lst1
> lst.append('x')
> del lst[3]
> lst.insert(0, 'a')
> lst = lst2
> del lst[2]
> lst.append('y')
> lst = lst3
> lst.insert(0, 'x')
> lst += [1,2]
> 
> I think current window should also be acquired explicitly:
> 
> with get_current_window():
>      type("some kind of snippet")
> 
> For usage when a command should apply to all types of windows.

I was skeptical of your suggestion at first but trying it out on an example script made me see its appeal:

	notepad_main = start("Notepad")
	with notepad_main:
		write("Hello World!")
		save_dialogue = press(CTRL + 's')
		with save_dialogue:
			write("test.txt", into="File name")
			click("Save")
		click("Close")

Forcing the library user to always use the "with ..." seems like overkill though. I think the gained precision does not justify this burden on the library user. Hm....

[toc] | [prev] | [next] | [standalone]


#41911

FromChris Angelico <rosuav@gmail.com>
Date2013-03-27 02:16 +1100
Message-ID<mailman.3750.1364311020.2939.python-list@python.org>
In reply to#41909
On Wed, Mar 27, 2013 at 1:59 AM, Michael Herrmann
<michael.herrmann@getautoma.com> wrote:
> save_dialogue = press(CTRL + 's')

Does every single API need to then consider the possibility of focus
changing? How does the press() function know that this will (or might
- if the file's already been named, Ctrl-S won't open a dlg) change
focus? How does the caller know?

ChrisA

[toc] | [prev] | [next] | [standalone]


#41989

FromMichael Herrmann <michael.herrmann@getautoma.com>
Date2013-03-27 01:45 -0700
Message-ID<41f33ffa-1c26-4e25-bee3-52647c30a141@googlegroups.com>
In reply to#41911
On Tuesday, March 26, 2013 4:16:57 PM UTC+1, Chris Angelico wrote:
> On Wed, Mar 27, 2013 at 1:59 AM, Michael Herrmann
> 
> <michael.herrmann@...> wrote:
> > save_dialogue = press(CTRL + 's')
> 
> Does every single API need to then consider the possibility of focus
> changing? How does the press() function know that this will (or might
> - if the file's already been named, Ctrl-S won't open a dlg) change
> focus? How does the caller know?

While I can see where it is coming from, I am also not a big fan of this idea. 

Michael

[toc] | [prev] | [next] | [standalone]


#41957

FromMitya Sirenef <msirenef@lightbird.net>
Date2013-03-26 18:01 -0400
Message-ID<mailman.3780.1364335271.2939.python-list@python.org>
In reply to#41909
On 03/26/2013 10:59 AM, Michael Herrmann wrote:
> On Tuesday, March 26, 2013  2:41:38 PM UTC+1, Mitya Sirenef wrote:
 >> ...
 >> At the __exit__, further commands are no longer routed to that window;
 >> if it was a nested context, window is switched to the outer context,
 >> WHEN there are commands in it (i.e. on the first command). This seems
 >> pretty intuitive to me:
 >>
 >> with notepad1:
 >>      ^S
 >>      with notepad2:
 >>          ^S
 >>      write('something')
 >>
 >
 >> ...
 >>  > What I am most afraid of: that the window that's currently the
 >>  > context "disappears":
 >>
 >>  >     notepad = start("Notepad")
 >>  >     with notepad:
 >>  >         press(ALT + TAB)
 >>  >         write("Am I in Notepad now?")
 >>
 >>
 >> Alt-tab needs to be handled by a wrapper function that gives you the
 >> object of the window you've switched to:
 >>
 >> otherwin = alt_tab()
 >> with otherwin:
 >>      ...
 >>
 >> If window is changed within 'with' block, the rest of block should be
 >> ignored. Perhaps there could also be a way to switch this behaviour off,
 >> for the entire script or for current block only.
 >>
 >>
 >>  > What do you think of designs #3 and #4?
 >>  > ...
 >>
 >> These are ok, too, but I feel it's much easier to send commands to a
 >> wrong window vs. context managers. The same command in a different
 >> window can have vastly different and dangerous effect. In other python
 >> code that's generally not common at all, and would be bad style:
 >>
 >> lst = lst1
 >> lst.append('x')
 >> del lst[3]
 >> lst.insert(0, 'a')
 >> lst = lst2
 >> del lst[2]
 >> lst.append('y')
 >> lst = lst3
 >> lst.insert(0, 'x')
 >> lst += [1,2]
 >>
 >> I think current window should also be acquired explicitly:
 >>
 >> with get_current_window():
 >>      type("some kind of snippet")
 >>
 >> For usage when a command should apply to all types of windows.
 >
 > I was skeptical of your suggestion at first but trying it out on an 
example script made me see its appeal:
 >
 >     notepad_main = start("Notepad")
 >     with notepad_main:
 >         write("Hello World!")
 >         save_dialogue = press(CTRL + 's')
 >         with save_dialogue:
 >             write("test.txt", into="File name")
 >             click("Save")
 >         click("Close")
 >
 > Forcing the library user to always use the "with ..." seems like 
overkill though. I think the gained precision does not justify this 
burden on the library user. Hm....


I don't see why that's a big deal, I've used AHK extensively and in my
experience you don't switch windows all that often. I think it's best to
optimize to have easy to type and read commands while you're working in
the same window.

I think you could argue that dialogs that belong to the main window
should be handled implicitly, though. I think for other windows it'd
definitely be good to use context managers, but for quick/simple dialogs
it's too much hassle, although for large, complex dialogs that have
inner tabs and require a lot of work, it again starts to make sense.

At the very least, for small dialogs it's sipmpler to do:

with press(CTRL + 's'):
     write("test.txt", into="File name")
     click("Save")


  -m


-- 
Lark's Tongue Guide to Python: http://lightbird.net/larks/

Calamities are of two kinds: misfortunes to ourselves, and good fortune 
to others.
Ambrose Bierce, The Devil's Dictionary

[toc] | [prev] | [next] | [standalone]


#41994

FromMichael Herrmann <michael.herrmann@getautoma.com>
Date2013-03-27 02:10 -0700
Message-ID<fa5c483e-4ee8-4ae6-8793-867de4c298c3@googlegroups.com>
In reply to#41957
On Tuesday, March 26, 2013 11:01:08 PM UTC+1, Mitya Sirenef wrote:
> On 03/26/2013 10:59 AM, Michael Herrmann wrote:
>  > ...
>  > Forcing the library user to always use the "with ..." seems like 
> overkill though. I think the gained precision does not justify this 
> burden on the library user. Hm....
> 
> I don't see why that's a big deal, I've used AHK extensively and in my
> experience you don't switch windows all that often. I think it's best to
> optimize to have easy to type and read commands while you're working in
> the same window.
> 
> I think you could argue that dialogs that belong to the main window
> should be handled implicitly, though. I think for other windows it'd
> definitely be good to use context managers, but for quick/simple dialogs
> it's too much hassle, although for large, complex dialogs that have
> inner tabs and require a lot of work, it again starts to make sense.
> 
> At the very least, for small dialogs it's sipmpler to do:
> 
> with press(CTRL + 's'):
>      write("test.txt", into="File name")
>      click("Save")

I think what the context manager approach really has going for itself is the syntactic structure it gives to scripts, that makes it easy to see what is going on in which window. Semantically, however, I think the fit of this approach has some rough edges: The fact that there needs to be some special treatment for ALT + TAB, that actions such as `press` "sometimes" return values that are needed to continue the script and so on. It really has its appeal, but I think it's a bit too special and intricate to be used by a broad audience.

> Calamities are of two kinds: misfortunes to ourselves, and good fortune 
> to others.

;-)

Michael
www.getautoma.com

[toc] | [prev] | [next] | [standalone]


#42014

FromMitya Sirenef <msirenef@lightbird.net>
Date2013-03-27 09:56 -0400
Message-ID<mailman.3810.1364392660.2939.python-list@python.org>
In reply to#41994
On 03/27/2013 05:10 AM, Michael Herrmann wrote:
>> At the very least, for  small dialogs it's sipmpler to do:
 >> >
 >> > with press(CTRL + 's'):
 >> >      write("test.txt", into="File name")
 >> >      click("Save")
 > I think what the context manager approach really has going for itself
 > is the syntactic structure it gives to scripts, that makes it easy to
 > see what is going on in which window. Semantically, however, I think
 > the fit of this approach has some rough edges: The fact that there
 > needs to be some special treatment for ALT + TAB, that actions such as
 > `press` "sometimes" return values that are needed to continue the
 > script and so on. It really has its appeal, but I think it's a bit too
 > special and intricate to be used by a broad audience.
 >


I think alt-tab has to be special in any case. Regular alt-tab would act
like the GOTO statement. As a programmer looking at a script you have no
idea where you just alt-tabbed to without possibly looking through
dozens of lines of previous code.

Keypresses that start a new window also seem pretty special to me.
They're inherently special. After all, the essential function of a
windowing system is when a new window is created, which means subsequent
operations have an entirely different meaning, in a text editor <del>
key will delete a character, in a file manager <del> key will delete a
file!

But, as I mentioned, if you can get away with treating simple dialogs
implicitly (and I don't see why you can't, at this point), that'd be the
preferred way for me.

  -m


-- 
Lark's Tongue Guide to Python: http://lightbird.net/larks/

"The condition of man is already close to satiety and arrogance, and
there is danger of destruction of everything in existence."
- a Brahmin to Onesicritus, 327 BC, reported in Strabo's Geography

[toc] | [prev] | [next] | [standalone]


#42113

FromMichael Herrmann <michael.herrmann@getautoma.com>
Date2013-03-28 03:52 -0700
Message-ID<b586e9cd-3e42-49ab-bf9c-6cc1b1f96019@googlegroups.com>
In reply to#42014
On Wednesday, March 27, 2013 2:56:55 PM UTC+1, Mitya Sirenef wrote:
> ...
> 
> I think alt-tab has to be special in any case. Regular alt-tab would act
> like the GOTO statement. As a programmer looking at a script you have no
> idea where you just alt-tabbed to without possibly looking through
> dozens of lines of previous code.
> 
> Keypresses that start a new window also seem pretty special to me.
> They're inherently special. After all, the essential function of a
> windowing system is when a new window is created, which means subsequent
> operations have an entirely different meaning, in a text editor <del>
> key will delete a character, in a file manager <del> key will delete a
> file!
> 
> But, as I mentioned, if you can get away with treating simple dialogs
> implicitly (and I don't see why you can't, at this point), that'd be the
> preferred way for me.

Ok. Thank you for your inputs!

[toc] | [prev] | [next] | [standalone]


#41903

FromNeil Cerutti <neilc@norwich.edu>
Date2013-03-26 14:13 +0000
Message-ID<ardooaF3o0oU1@mid.individual.net>
In reply to#41838
On 2013-03-25, Mitya Sirenef <msirenef@lightbird.net> wrote:
> I think I would prefer context managers. I don't think it's a
> big problem for win users because this behaviour would be one
> of the first things documented in the start guide and would be
> all over example scripts, so a new user missing or forgetting
> it is not a realistic scenario.

If window focus switching is really a rarity, and only done
briefly then I agree that a context manager makes a nice and neat
solution.

But it's too powerful a generalisation for such a small corner
case.

Have you considered adding a keyword argument to each of your
global functions, which is normally None, but allows a user to
provide a prefered focus window?

enter_text("test.txt", focus=save_dialog)
press_button(Savebutton, focus=save_dialog)

(Those are just guesses at your API functions; sorry.)

When focus remains None, your usual assumptions about focus would
apply, otherwise the user preference overrides it.

-- 
Neil Cerutti

[toc] | [prev] | [next] | [standalone]


#41907

FromMichael Herrmann <michael.herrmann@getautoma.com>
Date2013-03-26 07:40 -0700
Message-ID<5b2ddb12-ad76-46f9-9f01-f67595b7ff54@googlegroups.com>
In reply to#41903
On Tuesday, March 26, 2013 3:13:30 PM UTC+1, Neil Cerutti wrote:
> On 2013-03-25, Mitya Sirenef wrote:
> 
> > I think I would prefer context managers. I don't think it's a
> > big problem for win users because this behaviour would be one
> > of the first things documented in the start guide and would be
> > all over example scripts, so a new user missing or forgetting
> > it is not a realistic scenario.
> 
> 
> If window focus switching is really a rarity, and only done
> briefly then I agree that a context manager makes a nice and neat
> solution.
> 
> 
> But it's too powerful a generalisation for such a small corner
> case.
> 
> Have you considered adding a keyword argument to each of your
> global functions, which is normally None, but allows a user to
> provide a prefered focus window?
> 
> enter_text("test.txt", focus=save_dialog)
> 
> press_button(Savebutton, focus=save_dialog)

It's an interesting new idea but I somehow feel it makes the existing functions too complicated. Also, having to add it to all existing, and future functions sounds a bit too cumbersome to me. 

> (Those are just guesses at your API functions; sorry.)

No worries! Thank you for your suggestion!

Michael
www.getautoma.com

[toc] | [prev] | [next] | [standalone]


#41921

FromDave Angel <davea@davea.name>
Date2013-03-26 12:41 -0400
Message-ID<mailman.3755.1364316131.2939.python-list@python.org>
In reply to#41907
On 03/26/2013 10:40 AM, Michael Herrmann wrote:
> On Tuesday, March 26, 2013 3:13:30 PM UTC+1, Neil Cerutti wrote:
>>
>>    <SNIP>
>> Have you considered adding a keyword argument to each of your
>> global functions, which is normally None, but allows a user to
>> provide a prefered focus window?
>>
>> enter_text("test.txt", focus=save_dialog)
>>
>> press_button(Savebutton, focus=save_dialog)
>
> It's an interesting new idea but I somehow feel it makes the existing functions too complicated. Also, having to add it to all existing, and future functions sounds a bit too cumbersome to me.
>

Perhaps Neil didn't make it clear enough.  I figure he meant a keyword 
argument with an explicit default value of None.  (or if you followed my 
earlier discussion, default value of focused)

That way your user can keep using the functions for when there's no 
ambiguity, but add a focus= parameter only when needed.

To go back to my sample wrapper functions, they'd look something like 
(untested):


def write(*args, focus=focused):
     focus.write(*args)

Of course, the user should only use the wrappers when things are sure to 
remain "simple."


-- 
DaveA

[toc] | [prev] | [next] | [standalone]


#41929

FromNeil Cerutti <neilc@norwich.edu>
Date2013-03-26 17:25 +0000
Message-ID<are40lF6nclU1@mid.individual.net>
In reply to#41921
On 2013-03-26, Dave Angel <davea@davea.name> wrote:
> On 03/26/2013 10:40 AM, Michael Herrmann wrote:
>> On Tuesday, March 26, 2013 3:13:30 PM UTC+1, Neil Cerutti wrote:
>>>
>>>    <SNIP>
>>> Have you considered adding a keyword argument to each of your
>>> global functions, which is normally None, but allows a user to
>>> provide a prefered focus window?
>>>
>>> enter_text("test.txt", focus=save_dialog)
>>>
>>> press_button(Savebutton, focus=save_dialog)
>>
>> It's an interesting new idea but I somehow feel it makes the existing functions too complicated. Also, having to add it to all existing, and future functions sounds a bit too cumbersome to me.
>>
>
> Perhaps Neil didn't make it clear enough.  I figure he meant a keyword 
> argument with an explicit default value of None.  (or if you followed my 
> earlier discussion, default value of focused)
>
> That way your user can keep using the functions for when there's no 
> ambiguity, but add a focus= parameter only when needed.
>
> To go back to my sample wrapper functions, they'd look something like 
> (untested):
>
>
> def write(*args, focus=focused):
>      focus.write(*args)
>
> Of course, the user should only use the wrappers when things
> are sure to remain "simple."

Yes, along those lines. Most code would never need to provide the
focus= keyword. Only when setting focus in a weird way would it
be needed.

-- 
Neil Cerutti

[toc] | [prev] | [next] | [standalone]


#41992

FromMichael Herrmann <michael.herrmann@getautoma.com>
Date2013-03-27 01:55 -0700
Message-ID<5483aad6-221e-46f8-8909-bf743e9fcb5c@googlegroups.com>
In reply to#41921
On Tuesday, March 26, 2013 5:41:42 PM UTC+1, Dave Angel wrote:
> On 03/26/2013 10:40 AM, Michael Herrmann wrote:
> 
> > On Tuesday, March 26, 2013 3:13:30 PM UTC+1, Neil Cerutti wrote:
> >>    <SNIP>
> >> Have you considered adding a keyword argument to each of your
> >> global functions, which is normally None, but allows a user to
> >> provide a prefered focus window?
> 
> >> enter_text("test.txt", focus=save_dialog)
> >> press_button(Savebutton, focus=save_dialog)
> 
> > It's an interesting new idea but I somehow feel it makes the existing functions too complicated. Also, having to add it to all existing, and future functions sounds a bit too cumbersome to me.
> 
> Perhaps Neil didn't make it clear enough.  I figure he meant a keyword 
> argument with an explicit default value of None.  (or if you followed my 
> earlier discussion, default value of focused)
> 
> That way your user can keep using the functions for when there's no 
> ambiguity, but add a focus= parameter only when needed.
> 
> To go back to my sample wrapper functions, they'd look something like 
> (untested):
> 
> def write(*args, focus=focused):
>      focus.write(*args)

I understood what you meant - I'm not so worried about the invocations, as of course the parameter can be omitted if there's a default value/behaviour. What I am worried about is the complexity this approach adds to several functions. Yes, you could argue that one keyword argument really isn't that much, but then you have to maintain and document it for all functions that have the new keyword parameter. In other words, a single functionality that is not needed 90% of the time increases the complexity of several, not really related functions. I am very grateful for your suggestions! But I don't think adding this keyword parameter is the way to go for us.

Thanks,
Michael
www.getautoma.com

[toc] | [prev] | [next] | [standalone]


Page 2 of 3 — ← Prev page 1 [2] 3  Next page →

Back to top | Article view | comp.lang.python


csiph-web