diff options
-rw-r--r-- | Doc/Makefile.deps | 3 | ||||
-rw-r--r-- | Doc/mac/libaepack.tex | 18 | ||||
-rw-r--r-- | Doc/mac/libaetools.tex | 83 | ||||
-rw-r--r-- | Doc/mac/libaetypes.tex | 154 | ||||
-rw-r--r-- | Doc/mac/libgensuitemodule.tex | 64 | ||||
-rw-r--r-- | Doc/mac/mac.tex | 5 | ||||
-rw-r--r-- | Doc/mac/scripting.tex | 98 | ||||
-rw-r--r-- | Doc/mac/using.tex | 12 |
8 files changed, 397 insertions, 40 deletions
diff --git a/Doc/Makefile.deps b/Doc/Makefile.deps index 502e9ea..7d8043e 100644 --- a/Doc/Makefile.deps +++ b/Doc/Makefile.deps @@ -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 \ diff --git a/Doc/mac/libaepack.tex b/Doc/mac/libaepack.tex index b8276be..6c275bd 100644 --- a/Doc/mac/libaepack.tex +++ b/Doc/mac/libaepack.tex @@ -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]{ diff --git a/Doc/mac/libaetools.tex b/Doc/mac/libaetools.tex new file mode 100644 index 0000000..463755b --- /dev/null +++ b/Doc/mac/libaetools.tex @@ -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} diff --git a/Doc/mac/libaetypes.tex b/Doc/mac/libaetypes.tex index 0c2795a..1b6046d 100644 --- a/Doc/mac/libaetypes.tex +++ b/Doc/mac/libaetypes.tex @@ -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{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: -\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} +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 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} + diff --git a/Doc/mac/libgensuitemodule.tex b/Doc/mac/libgensuitemodule.tex new file mode 100644 index 0000000..5ab0cfd --- /dev/null +++ b/Doc/mac/libgensuitemodule.tex @@ -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} + diff --git a/Doc/mac/mac.tex b/Doc/mac/mac.tex index bbbd3aa..41ff2d3 100644 --- a/Doc/mac/mac.tex +++ b/Doc/mac/mac.tex @@ -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} diff --git a/Doc/mac/scripting.tex b/Doc/mac/scripting.tex new file mode 100644 index 0000000..f126e3c --- /dev/null +++ b/Doc/mac/scripting.tex @@ -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} diff --git a/Doc/mac/using.tex b/Doc/mac/using.tex index e44cbfb..c515e03 100644 --- a/Doc/mac/using.tex +++ b/Doc/mac/using.tex @@ -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}, |