diff -r ffa851df0825 -r 2fb8b9db1c86 symbian-qemu-0.9.1-12/python-2.6.1/Mac/Demo/applescript.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/symbian-qemu-0.9.1-12/python-2.6.1/Mac/Demo/applescript.html Fri Jul 31 15:01:17 2009 +0100 @@ -0,0 +1,362 @@ + +Using the Open Scripting Architecture from Python + +

Using the Open Scripting Architecture from Python

+
+ +

NOTE: this document describes the OSA support that is shipped with +the core python distribution. Most users are better of with the more +userfriendly appscript library. + +

OSA support in Python is still not 100% complete, but +there is already enough in place to allow you to do some nifty things +with other programs from your python program.

+ + +

+In this example, we will look at a scriptable application, extract its +“AppleScript Dictionary,” generate a Python interface package from +the dictionary, and use that package to control the application. +The application we are going to script is Disk Copy, Apple's standard +utility for making copies of floppies, creating files that are mountable +as disk images, etc. +Because we want +to concentrate on the OSA details, we won’t bother with a real +user-interface for our application.

+ + +

+When we say “AppleScript” in this document we actually mean +“the Open Scripting Architecture.” There is nothing +AppleScript-specific in the Python implementation. Most of this document +focuses on the classic Mac OS; Mac OS X users have some +additional tools. +

+ +

Python OSA architecture

+ +

Open Scripting suites and inheritance can be modelled rather nicely +with Python packages, so we generate +a package for each application we want to script. Each suite defined in +the application becomes a module in the +package, and the package main module imports everything from all the +submodules and glues together all the classes (in Python terminology— +events in OSA terminology or verbs in AppleScript terminology).

+ +

+A suite in an OSA application can extend the functionality of a standard +suite. This is implemented in Python by importing everything from the +module that implements the standard suites and overriding anything that has +been extended. The standard suites live in the StdSuite package.

+ +

+This all sounds complicated, but the good news is that basic +scripting is actually pretty simple. You can do strange and wondrous things +with OSA scripting once you fully understand it.

+ +

Creating the Python interface package

+ + +

There is a tool in the standard distribution that can automatically +generate the interface packages. This tool is called +gensuitemodule.py, and lives in Mac:scripts. +It looks through a file +for an ‘AETE’ or ‘AEUT’ resource, +the internal representation of the +AppleScript dictionary, and parses the resource to generate the suite +modules. +When we start gensuitemodule, it asks us for an input file; +for our example, +we point it to the Disk Copy executable.

+ +

+Next, gensuitemodule wants a folder where it will store the +package it is going to generate. +Note that this is the package folder, not the parent folder, so we +navigate to Python:Mac:Demo:applescript, create a folder +Disk_Copy, and select that.

+ +

+We next specify the folder from which gensuitemodule +should import the standard suites. Here, +we always select Python:Mac:Lib:lib-scriptpackages:StdSuites. (There is +one exception to this rule: when you are generating StdSuites itself +you select _builtinSuites.) +

+ +

+It starts parsing the AETE resource, and for +each AppleEvent suite it finds, gensuitemodule.py +prompts us for the filename of the +resulting python module. Remember to change folders for the first +module—you don't want to clutter up, say, the +Disk Copy folder +with your python +interfaces. If you want to skip a suite, press cancel and the process +continues with the next suite.

+ +

Summary

+ +
    + +
  1. Run gensuitemodule.
  2. + +
  3. Select the application (or OSAX) for which you would like a Python interface.
  4. + +
  5. Select the package folder where the interface modules should be + stored.
  6. + +
  7. Specify the folder Python:Mac:Lib:lib-scriptpackages:StdSuites + to import the standard suites (or _builtinSuites if you are + generating StdSuites itself).
  8. + +
  9. Save the generated suites (use cancel to skip a suite).
  10. + + +
+ + +

Notes

+ + + + + + +

The Python interface package contents

+ +

+Let’s glance at the +Disk_Copy package just created. You +may want to open Script Editor alongside to see how it +interprets the dictionary. +

+ + +

+The main package module is in __init__.py. +The only interesting bit is the Disk_Copy class, which +includes the event handling classes from the individual suites. It also +inherits aetools.TalkTo, which is a base class that handles all +details on how to start the program and talk to it, and a class variable +_signature which is the default application this class will talk +to (you can override this in various ways when you instantiate your class, see +aetools.py for details). +

+ +

+The Special_Events +module is a nice example of a suite module. +The Special_Events_Events class is the bulk of the code +generated. For each verb, it contains a method. Each method knows what +arguments the verb expects, and it makes use of keyword +arguments to present a palatable +interface to the python programmer. + +Notice that each method +calls some routines from aetools, an auxiliary module +living in Mac:Lib. +The other thing to notice is that each method calls +self.send. This comes from the aetools.TalkTo +baseclass.

+ + +

+After the big class, there are a number of little class declarations. These +declarations are for the (AppleEvent) classes and properties in the suite. +They allow you to create object IDs, which can then be passed to the verbs. +For instance, +when scripting the popular email program Eudora, +you would use mailbox("inbox").message(1).sender +to get the name of the sender of the first message in mailbox +inbox. It is +also possible to specify this as sender(message(1, mailbox("inbox"))), +which is sometimes needed because these classes don’t always inherit correctly +from baseclasses, so you may have to use a class or property from another +suite.

+ +

+Next we get the enumeration dictionaries, which allow you to pass +english names as arguments to verbs, so you don't have to bother with the 4-letter +type code. So, you can say + + diskcopy.create(..., filesystem="Mac OS Standard") + +as it is called in Script Editor, instead of the cryptic lowlevel + + diskcopy.create(..., filesystem="Fhfs") +

+ +

+Finally, we get the “table of contents” of the module, listing all +classes and such +by code, which is used by gensuitemodule itself: if you use this +suite as a base package in a later run this is how it knows what is defined in this +suite, and what the Python names are. +

+ +

Notes

+ + + + + + +

Using a Python suite module

+ +

+Now that we have created the suite module, we can use it in a Python script. +In older MacPython distributions this used to be a rather +complicated affair, but with the package scheme and with the application signature +known by the package it is very simple: you import the package and instantiate +the class, e.g. + + talker = Disk_Copy.Disk_Copy(start=1) + +You will usually specify the start=1: it will run the application if it is +not already running. +You may want to omit it if you want to talk to the application +only if it is already running, or if the application is something like the Finder. +Another way to ensure that the application is running is to call talker._start(). +

+ +

+Looking at the sourcefile makedisk.py, we see that it starts +with some imports. Naturally, one of these is the Python interface to Disk +Copy.

+ +

+The main program itself is a wonder of simplicity: we create the +object (talker) that talks to Disk Copy, +create a disk, and mount it. The bulk of +the work is done by talker and the Python interface package we +just created.

+ +

+The exception handling does warrant a few comments, though. Since +AppleScript is basically a connectionless RPC protocol, +nothing happens +when we create the talker object. Hence, if the destination application +is not running, we will not notice until we send our first +command (avoid this as described above). There is another thing to note about errors returned by +AppleScript calls: MacOS.Error is raised for +all of the errors that are known to be OSErr-type errors, +while +server generated errors raise aetools.Error.

+ +

Scripting Additions

+ +

+If you want to use any of the scripting additions (or OSAXen, in +everyday speech) from a Python program, you can use the same method +as for applications, i.e. run gensuitemodule on the +OSAX (commonly found in System Folder:Scripting Additions +or something similar). There is one minor gotcha: the application +signature to use is MACS. You will need to edit the main class +in the __init__.py file of the created package and change the value +of _signature to MACS, or use a subclass to the +same effect. +

+ +

+There are two minor points to watch out for when using gensuitemodule +on OSAXen: they appear all to define the class System_Object_Suite, +and a lot of them have the command set in multiple dialects. You have to +watch out for name conflicts and make sure you select a reasonable dialect +(some of the non-English dialects cause gensuitemodule to generate incorrect +Python code).

+ +Despite these difficulties, OSAXen offer a lot of possibilities. Take a +look at some of the OSAXen in the Scripting Additions folder, or +download some from the net. + +

Further Reading

+ +

+If you want to look at more involved examples of applescripting, look at the standard +modules findertools and nsremote, or (possibly better, as it +is more involved) fullbuild from the Mac:scripts folder. +

+ +

Alternatives

+ +

Mac OS X

+ +

+Under Mac OS X, the above still works, but with some new difficulties. +The application package structure can hide the ‘AETE’ or +‘AEUT’ resource from gensuitemodule, so that, +for example, it cannot generate an OSA interface to iTunes. Script +Editor gets at the dictionary of such programs using a ‘Get +AETE’ AppleEvent, if someone wants to donate code to use the same +method for gensuitemodule: by all means! +

+ +

+One alternative is available through the Unix command line version of python. +Apple has provided the osacompile and osascript tools, +which can be used to compile and execute scripts written in OSA languages. See the +man pages for more details. +

+ + + +