-
Notifications
You must be signed in to change notification settings - Fork 36
Export previous public defs #96
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Thank you for the PR! The changelog has not been updated, so here is a friendly reminder to check if you need to add an entry. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #96 +/- ##
=======================================
Coverage 93.26% 93.26%
=======================================
Files 16 16
Lines 817 817
Branches 118 118
=======================================
Hits 762 762
Misses 35 35
Partials 20 20 |
|
As I mentioned indirectly in #86 (comment), I’m strongly against re-adding all exports from the original monolithic module. We bumped the major version specifically to define and narrow the public API. Re-exposing legacy imports would effectively commit us to supporting all of those classes and functions indefinitely, which would severely limit our ability to refactor or redesign the internals. So this is a firm NO from my side. |
|
I am fundamentally against breaking functionality for people who depend on mediafile for the sole reason of internal restructuring - when all we have to do is to simply include the previously available API in the Please search GitHub and you will find that multiple projects import these classes/functions that I have re-added. I don't understand what is the drawback for us simply including them in |
|
The main point is that the whole reason we bumped to 1.0.0 was to define and enforce a stable public API. By re-adding internal or legacy exports to Yes, some projects currently import these legacy items, but they were never guaranteed to be stable. Changing an import path or deprecating these internal functions is exactly what a 1.0.0 release is for: it’s the first version where we define what is public and what isn’t. In other words, breaking internal imports is reasonable and expected at this stage. Re-exposing everything in Take for instance #97: if we exported |
|
Can you point me to the discussion where the specifics of what constitutes a stable public API, and what counts as legacy, have been debated, before you decided to remove these imports? I am specifically interested to see the consensus regarding downstream developers that rely on them.
Can you explain how # mediafile/__init__.py
from .fields import MediaField
__all__ = [
...
MediaField,
...
]has any impact on the refactoring that you linked? |
We regard everything defined in Generally downstream users who depend on such private or internal objects (intentionally not defined in
In short, the refactor changes the inheritance hierarchy of the Under semantic versioning, modifying class relationships in a way that breaks inheritance expectations would require a major version bump, provided that |
Philosophically speaking, I agree with you. However, in practice, we know that these accidentally public imports are being used by many downstream projects. The only definitions that we could safely treat as private were prefixed an underscore, as I mentioned in my comment under your PR. It is my responsibility as a maintainer to consider this and not break their functionality, unless we have a very, very convincing reason to do so.
I am not convinced - this class will break If you're still not convinced that the pre-existing definition of __all__ = ["UnreadableFileError", "FileTypeError", "MediaFile"]Simply have a glance at internal tests that rely on other definitions # test/test_mediafile.py
from mediafile import CoverArtField, Image, ImageType, MediaFile, UnreadableFileErrorAnd finally, if __all__ = [
"UnreadableFileError",
"FileTypeError",
"MutagenError",
"MediaFile",
"Image",
"TYPES",
"ImageType",
] |
|
There are two ways to define the public API: either
Internal tests also aren’t a good indicator of public API. They are free to import private or internal symbols, and using them as evidence would make refactoring effectively impossible.
The breaking change comes from the altered class hierarchy itself, not from whether a class is imported via mediafile or mediafile.fields. Changing the inheritance will affect isinstance checks regardless of import path. What I'm saying is
The fact that If the concern is widespread downstream reliance on specific internal helpers (e.g. Tagging @JOJ0 and @henry-oberholtzer for some external perspective and in case they want to give their 2 cents. |
|
And @Serene-Arc! |
|
My inexperience with Python packaging & this project in general means that my opinion is maybe more along the lines of that of a user. I do feel like since we're working towards the first major release, we have a lot more freedom to change things up. If we were to remove this after a 1.0.0 update, I think there would be more to worry about. We also have the advantage of having not published a package on PyPi for over a year, which gives more impetus to users to investigate the breaking changes with the update. I think it's also necessary to assume that users will look into major changes between versions, so the deprecation of that export could be mentioned in our release notes. It looks like importing filetype and using There's also the third option of maintaining the export with a deprecation warning, but I think that goes counter to the 1.0.0 ideals. |
|
After thinking about the feedback here, I've decided to merge this PR but release it as v0.14.0 instead of v1.0.0. @semohr @henry-oberholtzer you both make good points about what v1.0.0 should represent, and I get the argument about not freezing internal stuff forever. But I think we're viewing it differently. v1.0.0 doesn't mean "let's break everything and start fresh" - it means "OK, we've been shipping this for 10+ releases, we know what works, and this is the API we're committing to not change." It's about acknowledging reality and making a promise based on what's already proven stable in the field. These imports aren't hypothetical - they're in actual projects right now. Multiple beets plugins are importing The way I see it:
That's more honest about what stability means. We're not breaking things "because it's v1.0" - we're being intentional about what we support and giving people time to adapt. Appreciate the discussion on this – it's exactly the kind of thing that matters. |
5807412 to
0cace9f
Compare
|
You are again arguing for usage defines the api (which is fine btw). Could you please provide a list and show where each exported class is used externally also when the package/app was updated last. Compatibility with beets might also be interesting. I would not count beets here tbh as we can make it compatible easily and it is not really that big of an issue to change an import when we increment the mediafile version. Also we should keep the |
Export all previously publicly available definitions.
Once this is merged we should be good to go ahead with v1, I think.
Context
I found that
fetchartplugin crashed inbeetsdue to