I'm looking for a pattern where different client implementations can use the same commands of some fictive tool ("foo") by accessing some kind of API. Actually I have the need for such pattern for my own tool (http://openswarm.sourceforge.net). I already started restructuring my code to separate the actual command implementations from the command-line scripts (which is optparser-based now) and have some ideas how to proceed. But probably there is already a good pattern used for Python-based tools.
In the case that some of you are interested into this topic and my recent thoughts, you may want to have a look at the description below. Any comments are very much appreciated. Hopefully this list is a good place for discussing a pattern, otherwise I would be okay to move this to another place. Thank you. Here we go: The tool package itself provides several commands, although not important for the pattern itself, here some examples: modifying user-specific preferences, creating and changing project settings files, project-related code-generation, or combinations of such commands ... later also commands for transformation between several XML formats etc. The classes which implement these commands are currently in multiple modules, each having a class named CmdHandler. I have some Python scripts (each having a ScriptHandler classes), for use via command-line. Each ScriptHandler class is responsible to add all related command-line options and process those provided by the user (based on optparse library from Python standard lib). The script then calls the corresponding command and provide the verified options as parameters. Due to the nature of the tool under specific conditions the following results may come during command execution: * successful execution, no interaction * critical error, execution cancelled * user interaction needed (e.g. prompt user to approve replace existing directory (yes/no), prompt user to provide an alternative option) Command-line interactions work simply with raw_input(). So far this works. Nevertheless, there are some other aspects that could be improved, but this is another topic: The tool uses custom exceptions (e.g. for critical errors) and logging features (based on logging from Python standard lib). Currently no automated tests, but I have to add. For the next step I plan to support not only my own command-line scripts, but also a GUI to access the commands, as well as 3rd-party products (themselves command-line scripts or GUIs, such as foo plugins for any 3rd-party-tools). As far as I see, these clients need to implement a handler that: (1) Collecting all required parameters and optional parameters from a user (2) Provide these parameters for a particular call to command API (3) Provides some kind of hooks that are called back from the API on specific events, e.g. Question with user-choice; Information with user-input (4) Provide a logging handler object from the tool logging class or a sub-class of that in the case that a client-specific logging object should be triggered on each debug, message, warning etc. (1) is very client-specific, e.g. in a GUI via dialogs. (2) Each command provides a signature for all required/optional parameters. They are all verified from the command itself, although a client could do some verification at the first place. (3) Example use-case: a command needs to know if the user wants the command to proceed with a particular action, e.g. "Do you want to delete bar.txt?" with "Yes", "No" and "Cancel" choice. So the client's handler object (which is provided as first parameter to each command) implements client-specific features to show the user this question (e.g. pop-up dialog with question and three buttons), receive the user input (clicking one of the buttons) and pass this choice back to the foo API. Alternatively some kind of text information could be required, as in raw_input(), so actually this probably would be two different interaction features to be implemented. (4) The foo API also provides a logging class. The client needs to initialize such an object and provide it as member of the handler object provided to the API. I wonder if some clients may have own logging features and want to include all log messages from foo tool to the own logs. In this case a client could its own sub-class of the foo logging class and extending it with callbacks to its (client-)native logging object. What do you think about this? Best regards, Anastasios -- http://mail.python.org/mailman/listinfo/python-list