Pattern for foo tool <-> API <-> shell|GUI

Anastasios Hatzis ah at hatzis.de
Mon Mar 26 10:55:15 CEST 2007


On Sunday 25 March 2007 16:44, Steven Bethard wrote:
> Anastasios Hatzis wrote:
> > I'm working on a tool which is totally command-line based and consisting
> > of multiple scripts. The user can execute a Python script in the shell,
> > this script does some basic verification before delegating a call into my
> > tool's package and depending on some arguments and options provided in
> > the command-line, e.g.
> >     $python generate.py myproject --force --verbose
> > the tool processes whatever necessary. There are multiple command
> > handlers available in this package which are responsible for different
> > tasks and depending of the script that has been executed one or more of
> > these command handlers are fired to do their work ;)
>
> Side note: you might find argparse (http://argparse.python-hosting.com/)
>
> makes this a bit easier if you have positional arguments or sub-commands::

Steve, thank you, for the note. I didn't know argparse before. I have multiple 
scripts since optparse puts all arguments and options into one single help 
text, and the arguments and options are too specific for most commands (and 
thus the help would be absolutely overloaded and useless for new users). It 
seems that argparse has multiple help pages separated for each sub-command, 
as far as I understand the page.

>
> > And I don't think that this is very trivial (at least not for my
> > programming skill level). In the given example "generate.py" (above) the
> > following scenario is pretty likely:
> >
> > (1) User works with UML tool and clicks in some dialog a "generate"
> > button (2) UML tool triggers this event an calls a magic generate()
> > method of my tool (via the API I provide for this purpose), like my
> > generate.py script would do same way
> > (3) Somewhen with-in this generate process my tool may need to get some
> > information from the user in order to continue (it is in the nature of
> > the features that I can't avoid this need of interaction in any case).
>
> So you're imagining an API something like::
>
>      def generate(name,
>                   force=False,
>                   verbose=False,
>                   handler=command_line_handler):
>          ...
>          choice = handler.prompt_user(question_text, user_choices)
>          ...
>
> where the command-line handler might look something like::
>
>      class CommandLineHandler(object):
>          ...
>          def prompt_user(self, question_text, user_choices):
>              while True:
>                  choice = raw_input(question_text)
>                  if choice in user_choices:
>                      return choice
>                  print 'invalid choice, choose from %s' % choices
>
> and the GUI client would implement the equivalent thing with dialogs?

Exactly.

- Now, as I see your example, I wonder if this would work with a GUI which is 
event-driven... I have to look into my wx GUI prototype.

> That seems basically reasonable to me, though you should be clear in the
> documentation of generate() -- and any other methods that accept handler
> objects -- exactly what methods the handler must provide.
>
> You also may find that "prompt_user" is a bit too generic -- e.g. a file
> chooser dialog looks a lot different from a color chooser dialog -- so
> you may need to split this up into "prompt_user_file",
> "prompt_user_color", etc. so that handler's don't have to introspect the
> question text to know what to do...
>
> STeVe

Hey, right, good idea. I didn't think about the different task-specific 
dialogs in most GUIs. But I see that usability will gain benefit from 
differentiated "prompt" methods.

Anastasios



More information about the Python-list mailing list