SKaplanOfficial/PyXA

2 issues

Closed this issue · 2 comments

hhas commented
  1. Scripting Bridge is straight garbage. Defective by design: crippled, weak, incompetent, unsupported, dead. Should have opened Mac Automation to millions of enthusiastic new Python, Ruby, and ObjC coders; was first nail in its coffin instead. Worst. Foundation. Ever.

  2. Appscript already exists, and has done so for the last 18 years. The Python3 version still works too. Just use that.

Python appscript and its descendents speak Apple events right. Furthermore, appscript’s the only AE bridge in the last 30 years that gets Apple events right. Every other AE bridge: gensuitemodule, Mac::Glue, JavaScriptOSA, aeve, appscript (pre-0.6.0), RubyOSA, Scriptarian, JXA, ScriptingBridge, and now, by extension, PyXA has done it fatally wrong. Apple event IPC is not Object-Oriented Programming, it is RPC plus simple, first-class relational queries. You can’t force that into an OO mold, it doesn’t fit. And when users try to use those broken bridges with real-world “AppleScriptable” apps, some trivial things work alright but everything beyond that just breaks. Which is why all of these bridges are long-since defunct: they were all even worse than using AppleScript. Except for appscript, which eventually got better after a total rethink+redesign+rewrite, plus another 3 years of shaking out a myriad compatibility bugs with the aforementioned real-world apps until it was the world’s best Apple event bridge bar none and was poised for inclusion in 10.5… until my own laziness and naivety about how the world works saw it clobbered by Apple’s in-house nonsense instead. But that’s a separate story.

Do a little due diligence, studying all the prior art before you jump in yourself and figuring out why they all failed, and you’ll save hours of your life from reinventing the same broken useless wheel that a dozen others already made and abandoned before you.

If you want to automate macOS apps using Python: pip3 install appscript. Read the documentation (which is crusty and not great, though still leagues above all of Apple’s), download the ASDictionary and ASTranslate support apps which can answer 99% of “How do I…?” questions for you (then curse me if you’re on an ARM Mac as I’ve still not bothered to codesign them), and you’re golden [1]. I no longer offer (free) support—I don’t even build its new .whl wheels now (another user has taken on that)—although it is possible to get on my good side if there is anything you really want to know (i.e. just punt a tenner to charity).

Else, Python3 appscript is quite straightforward, incredibly competent (99.9% compatibility with real-world apps), and easily the best Mac Automation technology that Apple’s Mac Automation team ever tossed down the toilet cos they couldn’t give a crap. BTW, there isn’t even a Mac Automation team at Apple any more: they got themselves disbanded in 2016 at the end of a series of failures. The entire AE/OSA/AppleScript stack has been shoved into legacy maintenance ever since, left quietly to die out by itself. Apple has now begun discarding AS features, starting with dropping the AppleScript-ObjC project template in Xcode 14. I think it fair to expect more to go over the coming years as Apple moves from Mac-only AppleScript to cross-platform Shortcuts. To paraphrase Sancho Panza: there’s not much point still tilting at windmills when the windmill itself awaits demolition.

HTH

--

[1] Or, just use py-applescript which is a capable wrapper around AppleScript itself which allows you to call AppleScript handlers directly and takes care of converting standard Python types to AS types and back.

@hhas Thank you for taking the time to give feedback on this. I've used Appscript previously, and I agree that your approach is better in the technical sense in regard to how Apple events are handled, but I think an OO approach addresses some issues that currently prevent general (Python) users from getting started in the Mac automation space. In my personal experience with both JXA and Appscript, the largest challenges arose when scripting dictionaries are ambiguous about what types of information can be used in which situations, as well as what methods are available at any given time. While the OO approach in PyXA may not work for fringe cases in addition to being limited to only the currently supported applications, there is no ambiguity about whether generic methods are available and functional for any given object type.

PyXA is also not designed to be a 1-to-1 bridge to Apple events; the goal is more focused on creating a well-documented and easy to use automation interface that supports scripting commands and adds additional automation capabilities via other Apple APIs, URI schemes, etc. I'll admit that the choice to use ScriptingBridge was originally an exercise for me, and it might make more sense to use Appscript or py-applescript to support PyXA's features -- a moot point at this stage, I suppose.

In essence, my thought is that there are practical benefits to an OO approach in this form that outweigh the shortcomings, especially when those particular shortcomings are already addressed by Appscript.

hhas commented

“the largest challenges arose when scripting dictionaries are ambiguous about what types of information can be used in which situations, as well as what methods are available at any given time”

That’s the unfortunate, unavoidable nature of app dictionaries: they are not IDLs. The SDEF format isn’t expressive enough, and individual dictionaries often contain omissions and errors on top of that.

Furthermore, in an untyped dynamic language such as Python, having the bridge perform runtime “OO” checking of the user’s code before sending a command to the app as an Apple event provides the user zero benefit. The app already performs full runtime checks of every command and will tell the user if it’s not valid. All you do is duplicate that, just not as thoroughly. The first version of appscript (<0.6) already tried this approach. I threw that appscript out once I realized it was a waste of time and broke stuff that worked in AS.

ORMs are always a great idea on paper and a right pain in reality. The abstraction breaks down as soon as you start doing non-trivial stuff; the impedance mismatch between relational queries and the much less expressive OO is too large. Even AppleScript’s own light abstractions cause users as much trouble as they solve. APIs that try to be “clever” just create pain for their users, all the way down.

Unfortunately, the SB and JXA developers never dogfooded their own work, or even studied prior art, or they’d have known this and done something else. Instead, they just made excuses when new SB/JXA users pointed out their APIs didn’t work, and so those users gave up and just went back to AppleScript. (And as crippled and limited as SB and JXA are, they are still more useful and capable than PyXA.)

Anyway, that’s the technical problem. Which is actually the easy one to solve. The real problem you have is this: Your entire bridge is built on quicksand.

Scripting Bridge and JXA had a ready audience of 10 million Python, Ruby, ObjC, and JS programmers, and they couldn’t even attract—never mind retain—0.01% percent of that, even with Apple’s backing. And once they failed, Apple eliminated the entire Mac Automation department, effectively retiring the whole technology stack. It is clear Apple intends the future of Automation to be cross-platform Shortcuts, with app extensions and intents providing the IPC part. Which is to say, Apple event automation is already dead; it just hasn’t stopped twitching next.

PyXA has 0% chance of affecting this. Were AppleScript’s future secure I would call PyXA a vanity project. But AppleScript’s prospects are bleak and most likely terminal, making PyXA (and appscript, etc) a Bad Investment: high risk, little-to-no reward.

This is why I advise folk against using appscript: as good as it is, Apple can kill it tomorrow without even a thought. If PyXA ever comes up in discussion I would recommend the same.

My advice to Python users who really need to control Mac apps: stick to AppleScript. 1. Call osascript via subprocess (for simple scripts that only pass string arguments/results), or 2. Use py-applescript (which requires installing PyObjC but provides flexibility and power). It isn’t worth users investing greater time in learning and writing code appscript or PyXA. Do the quickest, easiest, cheapest thing that works, so that if/when Apple kills AppleScript, you can quickly and easily throw it out and haven’t wasted too much time on it.

Anyway I’m done now. Whatever you do, good luck.