Python and AppleEvents on Mac OS X Donovan Preston dp@ulaluma.com - - PowerPoint PPT Presentation

python and appleevents on mac os x
SMART_READER_LITE
LIVE PREVIEW

Python and AppleEvents on Mac OS X Donovan Preston dp@ulaluma.com - - PowerPoint PPT Presentation

Python and AppleEvents on Mac OS X Donovan Preston dp@ulaluma.com Survey How many people have heard of Python? How many people have used Python? How many people have heard of AppleScript? How many people have used AppleScript?


slide-1
SLIDE 1

Python and AppleEvents on Mac OS X

Donovan Preston dp@ulaluma.com

slide-2
SLIDE 2

Survey

  • How many people have heard of Python?
  • How many people have used Python?
  • How many people have heard of AppleScript?
  • How many people have used AppleScript?
  • How many people have heard of AppleEvents?
  • How many people have used AppleEvents?
  • Did you think this talk was cancelled?
slide-3
SLIDE 3

What is Python?

  • High level scripting language
  • Object oriented
  • Written in C
  • Very easy to extend in C or C++
  • Python makes a very good glue language
  • Dynamically Typed
  • The type of a variable doesn't matter, but
  • bjects have a type
slide-4
SLIDE 4

What are AppleEvents?

  • Language-independent binary IPC protocol
  • Applications expose:
  • Verbs
  • Objects (Components)
  • Properties
  • AppleEvent data structures are created and

manipulated using a C API

  • Events are posted to an app's event queue
  • Application handles event, constructs reply
slide-5
SLIDE 5

Language-Independent?!?

  • OSA: The Open Scripting Architecture
  • AppleEvents are the low-level description
  • f what should occur and what is occurring
  • High-level languages use the Dictionary (also

called Terminology) to map between low-level data structures and high-level syntax

  • Applications provide a “Dictionary” mapping

between low-level binary codes and english

  • 'odoc': open
  • 'clos': close
  • 'crel': make
slide-6
SLIDE 6

Python-C Glue

  • At the C API Level, AppleEvent data structures

are populated mostly with 32-bit integers

  • The MacPython distribution comes with the

extension module “Carbon.AppleEvents”

  • This module wraps all C functions required

to create and send AppleEvents

  • Using it is tedious
  • We want to write Python, not C!
  • 4 characters fit in a 32-bit integer, thus all the

Four Character Codes used throughout AE

slide-7
SLIDE 7

from Carbon import AppleEvents from Carbon import AE ## Create an AEDesc describing the Application we ## want to target, the Finder target = AE.AECreateDesc(AppleEvents.typeApplSignature, 'MACS') ## Create an AEDesc describing the event we want to send, noop noop = AE.AECreateAppleEvent( 'ascr', 'noop', target, AppleEvents.kAutoGenerateReturnID, AppleEvents.kAnyTransactionID) ## Send the event! noop.AESend(AppleEvents.kAEWaitReply, AppleEvents.kAENormalPriority, AppleEvents.kAEDefaultTimeout)

Carbon.AppleEvents Example

slide-8
SLIDE 8

aepack, aetools, aetypes

  • Carbon.AppleEvents is too low level
  • The MacPython distribution comes with three

Pure-Python modules which make creating and sending events easier

aepack Conversion to/from Python Types (str, int, list, etc) aetools Creation, packing, sending, unpacking events aetypes Python classes representing AE Types.

slide-9
SLIDE 9

import aetools, aetypes, aepack ## Send the "activate" to the Finder finder = aetools.TalkTo('MACS') finder.send('misc', 'actv') ## Request the name property from document 1 of OmniGraffle

  • mnigraffle = aetools.TalkTo('OGfl')

aedesc, reply, params = omnigraffle.send( 'core', 'getd', {'----': aetypes.Property( 'pnam', fr=aetypes.SelectableItem( 'docu', 1) )} ) ## Print the result print reply['----']

ae* Example

slide-10
SLIDE 10

Still Too Low-Level!

  • Using the ae* modules shortens the code

significantly

  • NOT Four Character Codes!

Applications provide the Dictionary (also called Terminology) for translation between Four Character Codes and English (and other languages) — We need to harness this

  • But we want to use nice-looking Python objects

and methods

slide-11
SLIDE 11

gensuitemodule.py

  • gensuitemodule is a Python script which

creates “Suite Modules”

  • Core Suite
  • Verbs: run, open, etc
  • Components: document, page, etc
  • Properties: document.name, window.name, etc.
  • Application Specific Suites
  • Application specific verbs, components, and properties
  • 'aete' (AppleEvent Terminology) resources are
  • rganized into “Suites”
  • gensuitemodule parses the aete and generates

Python code—one module per suite

slide-12
SLIDE 12

Running gensuitemodule

  • gensuitemodule is in lib/python2.3/plat-mac

% setenv LIB \ /Library/Frameworks/Python.framework\ /Versions/Current/lib/python2.3/plat-mac % pythonw $LIB/gensuitemodule.py --output iCal \ /Applications/iCal.app

  • You will need 2.3b2 Framework Build or later
  • The Python package iCal is created, with
  • ne Module per suite and an __init__
slide-13
SLIDE 13

Or...

slide-14
SLIDE 14

import iCal i = iCal.iCal() ## Creates a custom TalkTo ## Create an ObjectSpecifier specifying the first calendar holidays = iCal.calendar(1) numEvents = i.count(holidays, each=iCal.event) for eventNum in range(numEvents): ## Create a Specifier for the summary property of an event summarySpecifier = holidays.event(eventNum + 1).summary ## Execute the 'get' verb, passing this specifier print i.get(summarySpecifier)

Suite Module Example (use pythonw)

slide-15
SLIDE 15

gensuitemodule weirdness

  • You must iterate items by calling count yourself

and creating ObjectSpecifiers for each

The following code works: i.make( new=iCal.calendar, with_properties={iCal.calendar(1).title: 'hello'}) But is strange because we can't just say 'calendar.title'; we must say 'calendar(1).title'

  • You must use get and set, passing a Property

specifier, to retrieve and affect data

  • You cannot access a Property instance without

first having an ObjectSpecifier instance

slide-16
SLIDE 16

A Look Into the Future

  • Bob Ippolito and I are planning on doing a

ground-up rewrite of gensuitemodule

  • We will take advantage of Python 2.2's

properties and generators

  • Python Modules created by this will be

significantly easier to use

  • The rewrite will probably not be called

gensuitemodule because it may not be backwards-compatible (API compatible)

slide-17
SLIDE 17

library = iTunes.source['Library'] for song in library.songs: print song.location library.song[1].name = "SomeName"

Possible Future Syntax

  • This nice, natural looking syntax will be

accomplished by:

  • Passing a reference to the TalkTo to each ComponentItem
  • Using Python 2.2 properties instead of __getattr__ as

ComponentItem and Property factories

  • Defining an __iter__ which uses the TalkTo to call count

automatically, and returns n ComponentItems

slide-18
SLIDE 18

Q & A Interactive Demos