Releases: metasauce/plistsync
Release 0.6.0
Breaking Changes
Playlist Class Hierarchy Refactor
The playlist class hierarchy has been redesigned for clearer separation of concerns:
Renamed Classes:
PlaylistCollection→Playlist(base protocol)SpotifyPlaylistCollection→SpotifyPlaylistTidalPlaylistCollection→TidalPlaylistPlexPlaylistCollection→PlexPlaylistNMLPlaylistCollection→NMLPlaylist
Library Classes Renamed:
SpotifyLibraryCollection→SpotifyLibraryTidalLibraryCollection→TidalLibraryPlexLibrarySectionCollection→PlexLibraryNMLLibraryCollection→NMLLibrary
New Abstractions:
OfflinePlaylist— In-memory playlist with no service synchronizationServicePlaylist— Base for playlists synchronized with music servicesMultiRequestServicePlaylist— For APIs requiring multi-request modificationsPlaylistIDs— Unified TypedDict for cross-service playlist identification
Method Changes:
| Old | New | Notes |
|---|---|---|
remote_edit() |
edit() |
Context manager for transactional edits |
remote_delete() |
delete() |
Returns OfflinePlaylist with last state |
remote_create() |
library.create_playlist() |
Factory method on library |
remote_upsert() |
update() |
Bulk sync to remote |
remote_associated |
Removed | Service playlists always correspond to remote |
Migration:
# Old
pl = SpotifyPlaylistCollection(library, "Name", "desc")
pl.remote_create()
with pl.remote_edit():
pl.tracks.append(track)
# New
pl = library.create_playlist("Name", "desc")
with pl.edit():
pl.tracks.append(track)- Auth commands are now available via
plistsync auth [service]instead ofplistsync [service] auth
Added
- Split Playlist ABC into two classes: one for simple services, like filesystems, where states can be pushed via a single API call (
PlaylistCollection) and one where multiple API calls are required (MultiRequestPlaylistCollection), e.g. when a playlists description cannot be pushed in the same call as track changes. - Added
allservicesdependency group to allow a loaded pip install with batteries included. - Added
plistsync --versioncommand to show the currently installed version of the library
Fixed
- Fixed lazy track loading when playlist has 0 tracks (
force=Truelogic in_load_tracks) - In rare cases, spotify playlists can contain invalid items, which do not appear in the web interface (but through the api). We now filter and remove them.
- Fixed an issue with the spotify api returning duplicate playlists on pagination borders.
- In rare cases, spotify playlists can contain invalid items, which do not appear in the web interface (but through the api). We now filter and remove them.
📦 PyPI: https://pypi.org/project/plistsync/0.6.0/
📁 Artifacts:
- sdist:
plistsync-0.6.0.tar.gz - wheel:
plistsync-0.6.0-py3-none-any.whl
v0.5.1
v0.5.0
This marks the first public release of plistsync, a major milestone for the project! 🎉
While the library is now in a very usable state and suitable for real-world music library synchronization, we’re still actively refining the public API. As such, breaking changes to function signatures, module structure, or core abstractions may occur without deprecation warnings until we reach version 1.0.0.
We encourage early adopters to:
- Experiment freely and share feedback (via GitHub Issues or Discussions)
- Pin to this version if stability is critical
- Expect occasional breaking changes as we iterate toward a stable
1.0.0API
Added
- Traktor config option
backup_before_write(enabled by default), which creates a backup of the NML file before each write operation. pyproject.tomlmetadata enhancements: updatedreadme,license,authors,project_urls, andclassifiersfor better discoverability and packaging.- Support for batched remote operations, enabling efficient minification of expensive network requests (e.g., bulk playlist updates across services).
- Improved examples: now hosted in
docs/examples(full-fledged Jupyter notebooks by the core team) anddocs/examples/community(community-contributed scripts, including simple CLI workflows).
Changed
- Unified
__repr__format across all core classes toClassName(key=value)for consistent, debug-friendly output. - Standardized
get_playlist()behavior across all services: now consistently returnsNonewhen no playlist is found, regardless of the lookup identifier used. Introducedget_playlist_or_raise()for predictable, exception-raising behavior when a playlist must exist.
v0.4.0
What's Changed
- Traktor playlist collection by @semohr in #34
- Added nbstripout as precommit hook by @semohr in #43
- Plex notebook by @pSpitzner in #41
- Collection refactor by @pSpitzner in #42
- Global config directory by @semohr in #29
- Added generic to matches and the lookup protocols by @semohr in #45
- Enhanced logging by @semohr in #44
- Test nbmake by @semohr in #49
- Avoid stack traces that could expose api tokens by @pSpitzner in #51
- icon v2 by @pSpitzner in #52
Full Changelog: v0.3.0...v0.4.0
v0.3.0
What's Changed
- Revises plex authentication flow by @semohr in #7
- UV as dependency managment by @semohr in #12
- Fixed coverage report upload by @semohr in #20
- Spotify api refactor by @semohr in #18
- Tidal api refactor by @semohr in #19
- Enhacments to docs by @semohr in #21
- Replace difflib.SequenceMatcher with custom diff algorithm by @semohr in #25
- Auth unification & refactor by @semohr in #28
- Track stream by @semohr in #30
Full Changelog: v0.2.0...v0.3.0
v0.2.0
v0.1.0
Initial release
Full Changelog: https://github.com/metasauce/plistsync/commits/v0.1.0