Closed geigerzaehler closed 7 months ago
Could you comment a bit on your motivation to refactor this now?
Of course. I’ve been bugged by finding the cause for #74 and my suspicion is that it comes from beets’s path handling. In addition to that, I feel that beets’s path handling is hard to understand, difficult to use and a lot less readable than
pathlib
.
It definitely is, and I don't think there's any documentation on how it's supposed to work. However, I'm not sure whether pathlib
would really resolve all issues on its own, or whether it would just shift input validation/normalization to different places in the code.
My impression is that this might introduce extra friction at the interface between beets and the plugin, given that beets still (tries to) consistently represents everything as bytes internally.
I understand your concern. But in my experience the main friction comes from how beets handles paths and how hard that is to understand and predict. For example, you said that beets “tries to“ use bytes for paths but that is not actually the case on Windows where
syspath
returns astr
. On all other platforms it just passes through the argument, so it is up to the user to ensure the correct type.
It should be the case on Windows as well: From my understanding, the intended usage is
bytestringpath
-> internal representation as bytes
(no-op on *nix, conversion on Windows)syspath
-> OS APIs and third-party libraries (no-op on *nix, conversion on Windows. There's a bit of defensive programming here when passing in str
, but that should really be considered a programming error.)py3_path
-> APIs that only accept str
, even on Linux where the native path type is bytes
displayable_path
takes the internal bytes
representation and returns a string that can safely be printed (but this might be lossy)BLOB
s, i.e. bytes
Thus, overall, except for input and at API boundaries, any path handled by beets should always be represented as bytes. I'm pretty sure that there are still some bugs lurking in beets, definitely in some of the vendored plugins and possibly even in the core.
This is also why improved type hints don’t solve the underlying problem. (The would help improve understanding in a lot of other areas, though.)
One idea that I mentioned at some point is using newtypes for InternalPath
, SysPath
(which would have a platform-dependent inner type) and thereby help verification by the type checker. But that on its own would already by a rather big project in beets.
I didn't review this PR in full; and I don't think I have the time to do so: That would require going back to the beets code quite a lot and checking my expectations about it.
That’s ok, thanks for your effort anyway. Since this only touches test code (for now) I think it’s ok to play a bit loose with things like the type passed to
Mediafile
since it just works™.
I'm still not fully convinced, since this means that the testing code might end up using different types/code paths than the real usage in beets.
That said and given that I'm not going to review this in more depth, please ignore my comments and go with your judgement if you're convinced that this should be done!
Thanks for the reply. I appreciate your input on this.
I’ve reflected on the change again but I think the main argument is still very strong: There’s a standard, pythonic way to deal with paths robustly and not care about the OS. That way is different from beets’s but I trust the former more and I believe it is the way forward. I’m willing to deal with the friction that comes from using both.
With that in mind, I’ll go ahead and merge this change. I’ll have another PR ready soon that also switches to pathlib
in the actual plugin implementation.
Of course. I’ve been bugged by finding the cause for #74 and my suspicion is that it comes from beets’s path handling. In addition to that, I feel that beets’s path handling is hard to understand, difficult to use and a lot less readable than
pathlib
.I understand your concern. But in my experience the main friction comes from how beets handles paths and how hard that is to understand and predict. For example, you said that beets “tries to“ use bytes for paths but that is not actually the case on Windows where
syspath
returns astr
. On all other platforms it just passes through the argument, so it is up to the user to ensure the correct type.This is also why improved type hints don’t solve the underlying problem. (The would help improve understanding in a lot of other areas, though.)
That’s ok, thanks for your effort anyway. Since this only touches test code (for now) I think it’s ok to play a bit loose with things like the type passed to
Mediafile
since it just works™.