python and appleevents on mac os x
play

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?


  1. Python and AppleEvents on Mac OS X Donovan Preston dp@ulaluma.com

  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?

  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 objects have a type

  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

  5. Language-Independent?!? • OSA: The Open Scripting Architecture • AppleEvents are the low-level description of what should occur and what is occurring • Applications provide a “Dictionary” mapping between low-level binary codes and english • 'odoc': open • 'clos': close • 'crel': make • High-level languages use the Dictionary (also called Terminology) to map between low-level data structures and high-level syntax

  6. Python-C Glue • At the C API Level, AppleEvent data structures are populated mostly with 32-bit integers • 4 characters fit in a 32-bit integer, thus all the Four Character Codes used throughout AE • 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!

  7. Carbon.AppleEvents Example 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)

  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 aetools aetypes Conversion Creation, to/from packing, Python classes Python Types sending, representing AE (str, int, list, etc) unpacking Types. events

  9. ae* Example 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 omnigraffle = aetools.TalkTo('OGfl') aedesc, reply, params = omnigraffle.send( 'core', 'getd', {'----': aetypes.Property( 'pnam', fr=aetypes.SelectableItem( 'docu', 1) )} ) ## Print the result print reply['----']

  10. Still Too Low-Level! • Using the ae* modules shortens the code significantly • But we want to use nice-looking Python objects and methods • 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

  11. gensuitemodule.py • gensuitemodule is a Python script which creates “Suite Modules” • 'aete' (AppleEvent Terminology) resources are organized into “Suites” • 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 • gensuitemodule parses the aete and generates Python code—one module per suite

  12. Running gensuitemodule • gensuitemodule is in lib/python2.3/plat-mac • You will need 2.3b2 Framework Build or later % setenv LIB \ /Library/Frameworks/Python.framework\ /Versions/Current/lib/python2.3/plat-mac % pythonw $LIB/gensuitemodule.py --output iCal \ /Applications/iCal.app • The Python package iCal is created, with one Module per suite and an __init__

  13. Or...

  14. Suite Module Example (use pythonw) 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)

  15. gensuitemodule weirdness • You must iterate items by calling count yourself and creating ObjectSpecifiers for each • 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 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'

  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)

  17. Possible Future Syntax library = iTunes.source['Library'] for song in library.songs: print song.location library.song[1].name = "SomeName" • 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

  18. Q & A Interactive Demos

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend