Moved all the scripting stuff to a separate section, added all the

missing bits (well, all the bits I could think of) and updated the
rest.
This commit is contained in:
Jack Jansen 2003-04-11 15:35:28 +00:00
parent 126f2b76b9
commit bae5c965e8
8 changed files with 392 additions and 35 deletions

View File

@ -345,10 +345,13 @@ LIBFILES= $(MANSTYLES) $(INDEXSTYLES) $(COMMONTEX) \
MACFILES= $(HOWTOSTYLES) $(INDEXSTYLES) $(COMMONTEX) \
mac/mac.tex \
mac/using.tex \
mac/scripting.tex \
mac/toolbox.tex \
mac/undoc.tex \
mac/libcolorpicker.tex \
mac/libmac.tex \
mac/libgensuitemodule.tex \
mac/libaetools.tex \
mac/libaepack.tex \
mac/libaetypes.tex \
mac/libmacfs.tex \

View File

@ -45,7 +45,7 @@ the Python string representation of a value (the repr() function)
encoded as a text descriptor.
\end{funcdesc}
\begin{funcdesc}{unpack}{x}
\begin{funcdesc}{unpack}{x\optional{, formodulename}}
\var{x} must be an object of type \class{AEDesc}. This function
returns a Python object representation of the data in the Apple
Event descriptor \var{x}. Simple AppleEvent data types (integer,
@ -53,16 +53,26 @@ encoded as a text descriptor.
Apple Event lists are returned as Python lists, and the list
elements are recursively unpacked. Object references
(ex. \code{line 3 of document 1}) are returned as instances of
\class{aetypes.ObjectSpecifier}. AppleEvent descriptors with
\class{aetypes.ObjectSpecifier}, unless \code{formodulename}
is specified. AppleEvent descriptors with
descriptor type typeFSS are returned as \class{FSSpec}
objects. AppleEvent record descriptors are returned as Python
dictionaries, with keys of type \class{?} and elements recursively
dictionaries, with 4-character string keys and elements recursively
unpacked.
The optional \code{formodulename} argument is used by the stub packages
generated by \module{gensuitemodule}, and ensures that the OSA classes
for object specifiers are looked up in the correct module. This ensures
that if, say, the Finder returns an object specifier for a window
you get an instance of \code{Finder.Window} and not a generic
\code{aetypes.Window}. The former knows about all the properties
and elements a window has in the Finder, while the latter knows
no such things.
\end{funcdesc}
\begin{seealso}
\seemodule{AE}{Built-in access to Apple Event Manager routines.}
\seemodule{Carbon.AE}{Built-in access to Apple Event Manager routines.}
\seemodule{aetypes}{Python definitions of codes for Apple Event
descriptor types.}
\seetitle[http://developer.apple.com/techpubs/mac/IAC/IAC-2.html]{

83
Doc/mac/libaetools.tex Normal file
View File

@ -0,0 +1,83 @@
\section{\module{aetools} ---
OSA client support}
\declaremodule{standard}{aetools}
\platform{Mac}
%\moduleauthor{Jack Jansen?}{email}
\modulesynopsis{Basic support for sending Apple Events}
\sectionauthor{Jack Jansen}{Jack.Jansen@cwi.nl}
The \module{aetools} module contains the basic functionality
on which Python AppleScript client support is built. It also
imports and re-exports the core functionality of the
\module{aetypes} and \module{aepack} modules. The stub packages
generated by \module{gensuitemodule} import the relevant
portions of \module{aetools}, so usually you do not need to
import it yourself. The exception to this is when you
cannot use a generated suite package and need lower-level
access to scripting.
The \module{aetools} module itself uses the AppleEvent support
provided by the \module{Carbon.AE} module. This has one drawback:
you need access to the window manager, see section \ref{osx-gui-scripts}
for details. This restriction may be lifted in future releases.
The \module{aetools} module defines the following functions:
\begin{funcdesc}{packevent}{ae, parameters, attributes}
Stores parameters and attributes in a pre-created \code{Carbon.AE.AEDesc}
object. \code{parameters} and \code{attributes} are
dictionaries mapping 4-character OSA parameter keys to Python objects. The
objects are packed using \code{aepack.pack()}.
\end{funcdesc}
\begin{funcdesc}{unpackevent}{ae\optional{, formodulename}}
Recursively unpacks a \code{Carbon.AE.AEDesc} event to Python objects.
The function returns the parameter dictionary and the attribute dictionary.
The \code{formodulename} argument is used by generated stub packages to
control where AppleScript classes are looked up.
\end{funcdesc}
\begin{funcdesc}{keysubst}{arguments, keydict}
Converts a Python keyword argument dictionary \code{arguments} to
the format required by \code{packevent} by replacing the keys,
which are Python identifiers, by the four-character OSA keys according
to the mapping specified in \code{keydict}. Used by the generated suite
packages.
\end{funcdesc}
\begin{funcdesc}{enumsubst}{arguments, key, edict}
If the \code{arguments} dictionary contains an entry for \code{key}
convert the value for that entry according to dictionary \code{edict}.
This converts human-readable Python enumeration names to the OSA 4-character
codes.
Used by the generated suite
packages.
\end{funcdesc}
The \module{aetools} module defines the following class:
\begin{classdesc}{TalkTo}{\optional{signature=None, start=0, timeout=0}}
Base class for the proxy used to talk to an application. \code{signature}
overrides the class attribute \code{_signature} (which is usually set by subclasses)
and is the 4-char creator code defining the application to talk to.
\code{start} can be set to true to enable running the application on
class instantiation. \code{timeout} can be specified to change the
default timeout used while waiting for an AppleEvent reply.
\end{classdesc}
\begin{methoddesc}{_start}{}
Test whether the application is running, and attempt to start it if not.
\end{methoddesc}
\begin{methoddesc}{send}{code, subcode\optional{, parameters, attributes}}
Create the AppleEvent \code{Carbon.AE.AEDesc} for the verb with
the OSA designation \code{code, subcode} (which are the usual 4-character
strings), pack the \code{parameters} and \code{attributes} into it, send it
to the target application, wait for the reply, unpack the reply with
\code{unpackevent} and return the reply appleevent, the unpacked return values
as a dictionary and the return attributes.
\end{methoddesc}

View File

@ -8,32 +8,128 @@
\sectionauthor{Vincent Marchetti}{vincem@en.com}
The \module{aetypes} defines classes used to represent Apple Event
object specifiers. An object specifier is essentially an address of an
object implemented in a Apple Event server. An Apple Event specifier
is used as the direct object for an Apple Event or as the argument of
an optional parameter. In AppleScript an object specifier is
represented by a phrase such as:
\code{character 23 of document "Semprini"}. The classes defined in
this module allow this specifier to be represented by a Python object
which is initialized as follows:
\code{res = Document(1).Character(23)}
The \module{aetypes} defines classes used to represent Apple Event data
descriptors and Apple Event object specifiers.
Apple Event data is is contained in descriptors, and these descriptors
are typed. For many descriptors the Python representation is simply the
corresponding Python type: \code{typeText} in OSA is a Python string,
\code{typeFloat} is a float, etc. For OSA types that have no direct
Python counterpart this module declares classes. Packing and unpacking
instances of these classes is handled automatically by \module{aepack}.
An object specifier is essentially an address of an object implemented
in a Apple Event server. An Apple Event specifier is used as the direct
object for an Apple Event or as the argument of an optional parameter.
The \module{aetypes} module contains the base classes for OSA classes
and properties, which are used by the packages generated by
\module{gensuitemodule} to populate the classes and properties in a
given suite.
For reasons of backward compatibility, and for cases where you need to
script an application for which you have not generated the stub package
this module also contains object specifiers for a number of common OSA
classes such as \code{Document}, \code{Window}, \code{Character}, etc.
The \module{AEObjects} module defines the following class:
\begin{classdesc}{ObjectSpecifier}{want, form, seld, from}
This is the base class for representing object specifiers and is
generally not constructed directly by the user. Its important
functionality is to define an \function{__aepack__()} function,
which returns the Apple Event descriptor containing the object
specifier. Its data members, set directly from the constructor
arguments, are:
The \module{AEObjects} module defines the following classes to represent
Apple Event descriptor data:
\begin{classdesc}{Unknown}{type, data}
The representation of OSA descriptor data for which the \module{aepack}
and \module{aetypes} modules have no support, i.e. anything that is not
represented by the other classes here and that is not equivalent to a
simple Python value.
\end{classdesc}
\begin{classdesc}{Enum}{enum}
An enumeration value with the given 4-character string value.
\end{classdesc}
\begin{classdesc}{InsertionLoc}{of, pos}
Position \code{pos} in object \code{of}.
\end{classdesc}
\begin{classdesc}{Boolean}{bool}
A boolean.
\end{classdesc}
\begin{classdesc}{StyledText}{style, text}
Text with style information (font, face, etc) included.
\end{classdesc}
\begin{classdesc}{AEText}{script, style, text}
Text with script system and style information included.
\end{classdesc}
\begin{classdesc}{IntlText}{script, language, text}
Text with script system and language information included.
\end{classdesc}
\begin{classdesc}{IntlWritingCode}{script, language}
Script system and language information.
\end{classdesc}
\begin{classdesc}{QDPoint}{v, h}
A quickdraw point.
\end{classdesc}
\begin{classdesc}{QDRectangle}{v0, h0, v1, h1}
A quickdraw rectangle.
\end{classdesc}
\begin{classdesc}{RGBColor}{r, g, b}
A color.
\end{classdesc}
\begin{classdesc}{Type}{type}
An OSA type value with the given 4-character name.
\end{classdesc}
\begin{classdesc}{Keyword}{name}
An OSA keyword with the given 4-character name.
\end{classdesc}
\begin{classdesc}{Range}{start, stop}
A range.
\end{classdesc}
\begin{classdesc}{Ordinal}{abso}
Non-numeric absolute positions, such as \code{"firs"}, first, or \code{"midd"},
middle.
\end{classdesc}
\begin{classdesc}{Logical}{logc, term}
The logical expression of applying operator \code{logc} to
\code{term}.
\end{classdesc}
\begin{classdesc}{Comparison}{obj1, relo, obj2}
The comparison \code{relo} of \code{obj1} to \code{obj2}.
\end{classdesc}
The following classes are used as base classes by the generated stub
packages to represent AppleScript classes and properties in Python:
\begin{classdesc}{ComponentItem}{which\optional{, fr}}
Abstract baseclass for an OSA class. The subclass should set the class
attribute \code{want} to the 4-character OSA class code. Instances of
subclasses of this class are equivalent to AppleScript Object
Specifiers. Upon instantiation you should pass a selector in
\code{which}, and optionally a parent object in \code{fr}.
\end{classdesc}
\begin{classdesc}{NProperty}{fr}
Abstract basclass for an OSA property. The subclass should set the class
attributes \code{want} and \code{which} to designate which property we
are talking about. Instances of subclasses of this class are Object
Specifiers.
\end{classdesc}
\begin{classdesc}{ObjectSpecifier}{want, form, seld\optional{, fr}}
Base class of \code{ComponentItem} and \code{NProperty}, a general
OSA Object Specifier. See the Apple Open Scripting Architecture
documentation for the parameters. Note that this class is not abstract.
\end{classdesc}
\begin{memberdesc}{want}
A four character string representing the class code of the
object. These class codes are specified in Apple Event Suites; for
example the standard code for a character object is the 4 bytes
\samp{char}.
\end{memberdesc}

View File

@ -0,0 +1,64 @@
\section{\module{gensuitemodule} ---
Generate OSA stub packages}
\declaremodule{standard}{gensuitemodule}
\platform{Mac}
%\moduleauthor{Jack Jansen?}{email}
\modulesynopsis{Create a stub package from an OSA dictionary}
\sectionauthor{Jack Jansen}{Jack.Jansen@cwi.nl}
The \module{gensuitemodule} module creates a Python package implementing
stub code for the AppleScript suites that are implemented by a specific
application, according to its AppleScript dictionary.
It is usually invoked by the user through the \program{PythonIDE}, but
it can also be run as a script from the command line (pass \code{--help}
for help on the options) or imported from Python code. For an example of
its use see \file{Mac/scripts/genallsuites.py} in a source distribution,
which generates the stub packages that are included in the standard
library.
It defines the following public functions:
\begin{funcdesc}{is_scriptable}{application}
Returns true if \code{application}, which should be passed as a pathname,
appears to be scriptable. Take the return value with a grain of salt:
\program{Internet Explorer} appears not to be scriptable but definitely is.
\end{funcdesc}
\begin{funcdesc}{processfile}{application\optional{, output, basepkgname,
edit_modnames, creatorsignature, dump, verbose}}
Create a stub package for \code{application}, which should be passed as
a full pathname. For a \file{.app} bundle this is the pathname to the
bundle, not to the executable inside the bundle; for an unbundled CFM
application you pass the filename of the application binary.
This function asks the application for its OSA terminology resources,
decodes these resources and uses the resultant data to create the Python
code for the package implementing the client stubs.
\code{output} is the pathname where the resulting package is stored, if
not specified a standard "save file as" dialog is presented to
the user. \code{basepkgname} is the base package on which this package
will build, and defaults to \module{StdSuites}. Only when generating
\module{StdSuites} itself do you need to specify this.
\code{edit_modnames} is a dictionary that can be used to change
modulenames that are too ugly after name mangling.
\code{creator_signature} can be used to override the 4-char creator
code, which is normally obtained from the \file{PkgInfo} file in the
package or from the CFM file creator signature. When \code{dump} is
given it should refer to a file object, and \code{processfile} will stop
after decoding the resources and dump the Python representation of the
terminology resources to this file. \code{verbose} should also be a file
object, and specifying it will cause \code{processfile} to tell you what
it is doing.
\end{funcdesc}
\begin{funcdesc}{processfile_fromresource}{application\optional{, output,
basepkgname, edit_modnames, creatorsignature, dump, verbose}}
This function does the same as \code{processfile}, except that it uses a
different method to get the terminology resources. It opens \code{application}
as a resource file and reads all \code{"aete"} and \code{"aeut"} resources
from this file.
\end{funcdesc}

View File

@ -57,9 +57,8 @@ documented here:
\input{libmacostools}
\input{libmacui}
\input{libframework}
\input{libminiae}
\input{libaepack}
\input{libaetypes}
\input{scripting}
\input{toolbox} % MacOS Toolbox Modules
\input{libcolorpicker}

98
Doc/mac/scripting.tex Normal file
View File

@ -0,0 +1,98 @@
\chapter{MacPython OSA Modules \label{scripting}}
Python has a fairly complete implementation of the Open Scripting
Architecure (OSA, also commonly referred to as AppleScript), allowing
you to control scriptable applications from your Python program,
and with a fairly pythonic interface.
For a description of the various components of AppleScript and OSA, and
to get an understanding of the architecture and terminology, you should
read Apple's documentation. The "Applescript Language Guide" explains
the conceptual model and the terminology, and documents the standard
suite. The "Open Scripting Architecture" document explains how to use
OSA from an application programmers point of view. In the Apple Help
Viewer these book sare located in the Developer Documentation, Core
Technologies section.
As an example of scripting an application, the following piece of
AppleScript will get the name of the frontmost \program{Finder} window
and print it:
\begin{verbatim}
tell application "Finder"
get name of window 1
end tell
\end{verbatim}
In Python, the following code fragment will do the same:
\begin{verbatim}
import Finder
f = Finder.Finder()
print f.get(Finder.window(1).name)
\end{verbatim}
As distributed the Python library includes packages that implement the
standard suites, plus packages that interface to a small number of
common applications.
To send AppleEvents to an application you must first create the Python
package interfacing to the terminology of the application (what
\program{Script Editor} calls the "Dictionary"). This can be done from
within the \program{PythonIDE} or by running the
\file{gensuitemodule.py} module as a standalone program from the command
line.
The generated output is a package with a number of modules, one for
every suite used in the program plus an \module{__init__} module to glue
it all together. The Python inheritance graph follows the AppleScript
inheritance graph, so if a programs dictionary specifies that it
includes support for the Standard Suite, but extends one or two verbs
with extra arguments then the output suite will contain a module
\module{Standard_Suite} that imports and re-exports everything from
\module{StdSuites.Standard_Suite} but overrides the methods that have
extra functionality. The output of \module{gensuitemodule} is pretty
readable, and contains the documentation that was in the original
AppleScript dictionary in Python docstrings, so reading it is a good
source of documentation.
The output package implements a main class with the same name as the
package which contains all the AppleScript verbs as methods, with the
direct object as the first argument and all optional parameters as
keyword arguments. AppleScript classes are also implemented as Python
classes, as are comparisons and all the other thingies.
Note that in the current release there is no coupling between the main
Python class implementing the verbs and the Python classes implementing
the AppleScript classes. Hence, in the example above we need to use
\code{f.get(Finder.window(1).name)} in stead of the more Pythonic
\code{f.window(1).name.get()}.
If an AppleScript identifier is not a Python identifier the name is
mangled according to a small number of rules:
\begin{itemize}
\item spaces are replaced with underscores
\item other non-alphanumeric characters are replaced with
\code{_xx_} where \code{xx} is the hexadecimal character value
\item any Python reserved word gets an underscore appended
\end{itemize}
Python also has support for creating scriptable applications
in Python, but
The following modules are relevant to MacPython AppleScript support:
\localmoduletable
In addition, support modules have been pre-generated for
\module{Finder}, \module{Terminal}, \module{Explorer},
\module{Netscape}, \module{CodeWarrior}, \module{SystemEvents} and
\module{StdSuites}.
\input{libgensuitemodule}
\input{libaetools}
\input{libaepack}
\input{libaetypes}
\input{libminiae}

View File

@ -67,10 +67,7 @@ format only.
To run your script from the Terminal window you must make sure that
\file{/usr/local/bin} is in your shell search path before \file{/usr/bin},
where the Apple-supplied Python lives (which is version 2.2, as of Mac OS X
10.2.4). There is one Mac OS X quirk that you need to be aware of: programs
that talk to the window manager (in other words, anything that has a GUI)
need to be run in a special way. Use \program{pythonw} in stead of \program{python}
to start such scripts.
10.2.4).
To run your script from the Finder you have two options:
\begin{itemize}
@ -84,6 +81,13 @@ PythonLauncher has various preferences to control how your script is launched.
Option-dragging allows you to change these for one invocation, or use its
Preferences menu to change things globally.
\subsection{Running scripts with a GUI \label{osx-gui-scripts}}
There is one Mac OS X quirk that you need to be aware of: programs
that talk to the Aqua window manager (in other words, anything that has a GUI)
need to be run in a special way. Use \program{pythonw} in stead of \program{python}
to start such scripts.
\subsection{configuration}
MacPython honours all standard unix environment variables such as \envvar{PYTHONPATH},