I’ve been looking for a way to interface with some Cocoa classes in the Mac OS X API from FileMaker for a while. My initial target was PDFDocument, part of the PDF Kit suite of classes. For more information on Cocoa’s PDF Kit see here: Introduction to PDF Kit Programming Guide
I’ve had a couple versions of this working for some time, but I could never get anything that worked consistently across the various OS and Python combinations (Python is my default tool of choice for these kinds of things). Changes to both the Cocoa interfaces in Python and the OS architecture kept getting in the way. But I may of finally hit it.
Below is a Python script I’m using to test this out. It uses the PyObjC module, which is the more recent method of interfacing Python with Cocoa classes. To make interfacing between Python and FileMaker easier, I’m also using bBox, a free FileMaker plug-in I wrote that allows integration between FileMaker and Python.
import sys, os
import getopt
from pprint import pprint
#
For some OS versions we must explicitly add the PyObjC path.
sys.path.append (‘/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/PyObjC/’)
#
from Foundation import *
from Quartz import *
#
Set by the calling FMP script. Path of PDF that we will examine.
sourcePath
#
Set by the calling FMP script. Path to store the modified version of PDF.
destPath
#
Subroutine that does all the work.
#
def addAttributes(filepath,destPath):
url = NSURL.fileURLWithPath_(filepath)
pdfdoc = PDFDocument.alloc().initWithURL_(url)
attrs = NSMutableDictionary.alloc().initWithDictionary_(pdfdoc.documentAttributes())
print attrs
attrs[PDFDocumentTitleAttribute] = ‘PDF TITLE’
attrs[PDFDocumentAuthorAttribute] = ‘A. Author and B. Author’
pdfdoc.setDocumentAttributes_(attrs)
pdfdoc.writeToFile_(destPath)
#
Execute the subroutine with the given paths.
addAttributes (sourcePath, destPath)
The above script is stored in a FileMaker field. Here’s the script used in FileMaker to call the Python script:
Set Variable [ $py_sourcePath; Value:"/Applications/Safari.app/Contents/Resources/SearchMagGlassTemplate~snowleopard.pdf" ] Set Variable [ $py_destPath; Value:"/Users/Shared/bbox_version.pdf" ] Set Variable [ $py_script; Value:bbox pyobjc::pdf_attributes_script ] # # Compile the script & setup context. Set Variable [ $compile_result; Value:bBox_PythonCompile(0; $py_script) ] If [ $compile_result ≠"" ] Exit Script [ ] End If # Set Variable [ $ignore; Value:bBox_PythonSetVar("sourcePath"; "/Applications/Mail.app/Contents/Resources/ActionTemplate.pdf";"s") ] Set Variable [ $ignore; Value:bBox_PythonSetVar("destPath"; "/Users/Shared/bbox_version of_pdf_file.pdf"; "s") ] # Set Variable [ $execute_result; Value:bBox_PythonExecute(0) ] # # For unknown reasons, should NOT call finalize here in bBox 0.52 and possibly earlier versions, so currently disabled. // Set Variable [ $ignore; Value:bBox_PythonFinalize ] # Show Custom Dialog [ Title: "Python Result"; Message: $execute_result; Buttons: “OK†]
The key change was adding in the path for PyObjC. This may only be necessary because bBox interfaces with Python using its C based API, so it probably wouldn’t be necessary in a “normal” Python script. Having systems that have Python.org’s version of Python could also account for the differences I’ve seen, but bBox is only linked to Apple’s version of the Python framework so that would be surprising cause for the difference.
Since I am working on getting a new version of bBox out I’ll hopefully get a bit more clarity on this issue and maybe a few more examples as I test out the new version.