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 @@ + +
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. +
+ +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.
+ +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.
gensuitemodule
.Python:Mac:Lib:lib-scriptpackages:StdSuites
+ to import the standard suites (or _builtinSuites
if you are
+ generating StdSuites
itself). cancel
to skip a suite).gensuitemodule
does not handle all Python reserved words, so
+ if
+ one of the AppleScript verbs is a Python reserved word, a SyntaxError
+ may be raised when the package is imported.
+ Simply rename the class into something acceptable, if this happens;
+ take a look at how the
+ print
verb is handled (automatically by gensuitemodule
)
+ in the standard suites. But: f you need to edit your package this should be considered a
+ bug in gensuitemodule, so please report it so it can be fixed in future releases.
+ System Folder:Extensions:Scripting
+Additions:Dialects:English Dialect
. For newer versions, you will
+find them in System Folder:Extensions:Applescript
.
+Gensuitemodule.py
may ask you questions
+like “Where is enum 'xyz ' declared?”.
+This is either due to a misunderstanding on my part or (rather too commonly)
+bugs in the AETE resources. Pressing cancel
is usually the
+right choice: it will cause the specific enum not to be treated as an enum
+but as a “normal” type. As things like fsspecs and TEXT strings clearly are
+not enumerators, this is correct. If someone understands what is really going on
+here, please let me know.+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.
+
aetools
module contains some other nifty
+AppleEvent tools as well. Have a look at it sometime, there is (of
+course) no documentation yet.
+aetools.Word(10,
+aetools.Document(1))
, where the corresponding AppleScript
+terminology would be word 10 of the first
+document
. Examine
+aetools
and aetools.TalkTo
+along with
+the comments at the end of your suite module if you need to create
+more than the standard object specifiers.
+
+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
.
+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).
+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.
+
+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.
+