[Python-ideas] Adding `pathlib.Path` method that would send file to recycle bin

Andrew Barnert abarnert at yahoo.com
Wed Dec 31 11:50:04 CET 2014

On Dec 31, 2014, at 0:47, Steven D'Aprano <steve at pearwood.info> wrote:

> On Wed, Dec 31, 2014 at 12:12:01AM +0100, Andrew Barnert wrote:
>> By "suitable" I mean "suitable for widespread-enough use that it 
>> should be in the stdlib". As I said earlier in the thread, I think 
>> it's perfectly reasonable to have a third-party library that uses a 
>> deprecated API, requires 10.8, requires a runloop, directly or 
>> indirectly asks the Finder to do the work for you, or doesn't quite 
>> meet Apple's HIG rules, because all of those could be acceptable in 
>> _many_ applications; I just don't think any of those should be in the 
>> stdlib, because none of those are acceptable in _most_ applications.
> What's wrong with asking the Finder to move the file? Under what 
> circumstances would that be unacceptable? Are there scenarios on OS X 
> where the Finder isn't available but the trash is?

I already answered this briefly earlier in the thread, but in more detail:

1. If you don't have a GUI login session (e.g., because you've ssh'd into the box, or are running as a LaunchDaemon or a traditional detached script), you have no Finder in your session to script.

2. If you're running in a sandbox that doesn't have scripting rights for Finder added in--as will be the case in most Mac App Store apps--you can't script Finder. Of course you can include a sandbox exception to allow for this, but the only way to do this that's allowed in the App Store requires 10.8.0 to run and, IIRC, 10.8.2 to run without serious bugs. And the Python docs would have to explain that any app that may call shutil.trash must use a custom sandbox. 

3. If you're running in a sandbox, you can't execute osascript; if you need pre-10.8 compat, you can't use the modern APIs; this means the only thing you can do is include a compiled AppleScript as a resource and use the 10.7 APIs to execute it--which still requires 10.7, and it seems to have problems with the new 10.9.5/10.10.1 code signing rules (although it may be easy to work around that; I haven't tried).

4. If you're using a third-party Finder replacement like PathFinder, it won't respond to messages sent to Finder.

5. If you've killed the Finder to save resources (pretty rare nowadays, but still legal) you'll relaunch it.

6. The Finder may pop up a progress bar--or, worse, an auth dialog, or a "delete immediately?" dialog, on behalf of your app. This could be surprising from a console program.

7. Depending on how you do the scripting, your request may time out after 5 or 30 seconds, leaving you no way to know whether the trashing succeeded.

8. If Finder is hidden, it may unhide. If another app is fullscreen in front of Finder, it may slide offscreen, or Finder's dialogs may just be invisible. (You can guarantee a fix for the latter by forcing the former.)

9. If your session or system is screwed up and you're trying to shut down cleanly or repair things, Finder could be unresponsive or even hung. For example, on 10.6, if you have for separate moves blocked on an NFS mount, a trash will block forever, but (assuming you aren't trying to trash something on the same mount) there's nothing stopping you from trashing on your own.

In some cases, this may all be fine. For example, if you're writing a trash script that you intend to use on your specific computer in local Terminal sessions only, you may _want_ the Finder to take care of auth, no-trash mounts, and other issues for you, and show you progress on long tasks. Fortunately, you can already write that script with about 5 lines of ScriptingBridge code that will run on the Python 2.7 with PyObjC and other extras that Apple has pre-installed as /usr/bin/python on all 10.6-10.10 versions, so you're already covered.

> http://www.anthonysmith.me.uk/2008/01/08/moving-files-to-trash-from-the-mac-command-line/

Even if you want to use osascript, you don't want to do it that way. Build a single AppleScript command that trashes all of your files in a single call. One of the other blog posts someone linked earlier in this thread shows how to do that. Also, for the usual reasons, os.system is not the best way to call osascript (you'll end up with a success retcode even on failure, quoting for both the shell and AppleScript is double the fun, etc.).

> Having to call out to an external program via Applescript feels rather 
> icky, but given the difficulty of simultaneously supporting 
> multiple OS X versions, satisfying the rules of Apple Store, and using 
> Apple's APIs, I don't see any alternative.

Since this doesn't satisfy the rules of the App Store, it doesn't solve the problem it's intended to.

But see my previous email. For almost any app, there is a much better alternative. The problem is that there's no _single_ alternative that's good for most apps; there are different ones for different use cases.

In particular, for just writing a little trash script for use on the command line on your own 10.8+ computer, the NSFileManager version is even simpler than the scripting version (again using Apple's pre-installed 2.7 with PyObjC), and without any of its problems. For older computers, it's a _bit_ more work with the FS function, but still very simple, and it's a known problem that multiple people have solved years ago (and linked to earlier in this thread), so Python 3.5 doesn't need to retroactively solve it.

More information about the Python-ideas mailing list