When we store paths in the database, we always use bytestrings for consistency.
But on Windows, these paths are converted back to Unicode before they reach the
FS API. This means that the codec used internally is immaterial.
However, we were naively using sys.getfilesystemencoding() for this internal
representation. On Windows, this is MBCS, a broken encoding that can't represent
all of Unicode. This change replaces that with UTF-8, a "real" codec.
The decoding bit now tries UTF-8 and falls back to MBCS for compatibility with
existing databases. The reality, however, is that existing databases may not
work with this change -- a byte string may represent something different in
UTF-8 from what it represents in MBCS. So users should recreated their DBs if
anything goes wrong.
This necessitated a slight refactoring in the plugin event handling mechanism.
Rather than loading all handlers up front and storing them in a module-scope
structure, we now scan for event handlers at every send(). This is probably
very slightly less efficient but allows for more flexible logic.
The shutil.move() function attempts to copy metadata (e.g., permissions and
mtime) when copying a file across filesystems. This always fails on Samba shares
because the utime() call is never permitted by normal users. We don't care about
preserving mtimes across moves, though, so this commit eschews shutil and
reimplements the move algorithm.
Previously, exceptions while communicating with the MusicBrainz API would bring
down the entire autotagging process. These errors are depressingly common, so we
now handle them and log errors to the console (much as we already do with any
exception raised by the Mutagen module). Fault isolation!
This has the added side-effect of giving better context for MB errors when they
do happen -- the logged errors now show the query that was running when MB
failed.