… where the file needs to be preprocessed in some way before uploading to remote storage. The storage.upload() method must be called manually after this preprocessing has taken place. TODO: The upload task should be called with delay() instead of apply(), but I can only make this work syncronously on my machine for reasons I don't yet understand (task reports success, but file does not upload).
It's difficult to differentiate between code errors and network errors reliably at this point. So rather than swallowing all exceptions and trying again, we'll log all exceptions and try again, allowing the system administrator to sort out which ones are false positives.
Previously, open() wasn't accepting *args (only **kwargs), which caused crashes when called as foo.open(filename, "r"), for example. Also, it was only attempting to open the locally saved copy, which may not even exist for something that has already been sent to remote storage. So now we try remote first and then local, the same as for all the other methods.
This drastically speeds up startup times for anything that imports all models (which is pretty much anything in Django). It saves having to connect to the remote storage, in particular, until it's required.