Releases: geo-martino/musify
Releases · geo-martino/musify
v1.1.6
v1.1.5
Fixed
- Bug in escaping of '&' characters when export :py:class:
.XAutoPF
playlists with the :py:class:.XMLPlaylistParser
.
Was previously escaping multiple times when already escaped e.g. '&' > '&'.
Now correctly skips already occurrences of '&'.
v1.1.4
Added
- :py:class:
.LocalPlaylist
now allows setting of thepath
property - :py:class:
.LocalLibrary
now allows setting of thename
property. Addedname
as an init parameter too.
Changed
- :py:meth:
.LocalLibrary.merge_playlists
now updates the path of new playlists added to the library to be relative
to the library'splaylist_folder
v1.1.3
Fixed
- When given an empty :py:class:
.M3U
playlist file, produces expected result i.e. an empty playlist.
Previously always added all given tracks to playlist when calling :py:meth:.M3U.load
v1.1.2
Changed
- :py:meth:
.File.get_filepaths
now ignores hidden files. - Replace os.makedirs with Pathlib implementation of
mkdir
q everywhere.
v1.1.1
Changed
- Update aiorequestful version to 1.0
v1.1.0
Changed
- :py:class:
.ItemDownloadHelper
only ever takes the first field when the singular name of a field is given
and many values are available for that field. e.g. only ever takes the first artist when multiple artists are present
and the requested field is 'artist' and not 'artists' - :py:class:
.RemoteCollectionLoader
now inherits from :py:class:.MusifyItem
interface.
The class already implemented all necessary methods for this interface and was always designed
to be an implementation of the :py:class:.MusifyItem
interface. - Rename
print
method on :py:class:.MusifyLogger
to :py:meth:.MusifyLogger.print_line
Removed
- Implementation of REST API handling including all cache + authorisation implementations.
Separated this off to anew package <https://github.com/geo-martino/aiorequestful>
_. - Moved all enum definitions to
types
modules and removed allenum
modules.
Documentation
- Fix references to non-existent packages + add missing packages in API reference index
v1.0.2
Added
- Expanded error message on :py:class:
.DynamicProcessor
processor lookup exception. - Improved logging of bad responses on :py:class:
.RequestHandler
wait_max
time to cap wait time between requests for :py:class:.RequestHandler
- Add log on :py:class:
.CachedSession
for when either acache hit
or aHTTP request
happens.
Removed
limiter_deduplication
attribute from print output on :py:class:.XAutoPF
Fixed
- Bug in :py:class:
.XMLLibraryParser
which would not read 'Playlists' keys. - Moved 'check api' logic later when deleting playlists in :py:class:
.RemoteItemChecker
to ensure API is not checked on close when checker has not actually run. - :py:class:
.RequestHandler
now handles wait and backoff logic asynchronously. - Tracks on playlists from the JSON output of :py:class:
.LocalLibrary
now display correctly.
Previously showed 'null' for every track.
v1.0.1
Documentation
- Update PyPI classifiers for release
- Update readme
v1.0.0
Added
- Custom API caching backend to replace dependency on
requests-cache
package.
Currently only supports SQLite backend. More backends can be implemented in future if desired. - Cache settings for specific
GET
request endpoints on :py:class:.SpotifyAPI
replacing need
for per methoduse_cache
parameter. - The following classes should now be run as AsyncContextManagers to function correctly:
- :py:class:
.SQLiteCache
- :py:class:
.RequestHandler
- :py:class:
.CachedSession
- :py:class:
.RemoteAPI
& :py:class:.SpotifyAPI
- :py:class:
- Introduce print wrapper for logger and remove most bare
print
statements across package. - :py:meth:
.SpotifyAPI.extend_items
now enriches collection item responses with the parent collection response. - ARTISTS field added to LocalTrackField
- Add compatibility with
yarl
package for any logic which uses URL logic. - Add compatibility for pathlib.Path for any logic which uses path logic.
- Extended logging on :py:func:
.report_playlist_differences
source
property on :py:class:.Library
- :py:meth:
.RemoteAPI.get_or_create_playlist
method for only creating a playlist when it doesn't
already exist by name. Gets the existing playlist otherwise - Added :py:meth:
.MusifyCollection.outer_difference
method to cover the logic previously handled
by the mislabelled :py:meth:.MusifyCollection.outer_difference
method - :py:class:
.RemoteDataWrangler
and its implementations now handle URL objects from theyarl
package - :py:meth:
.RemoteAPI.follow_playlist
method - Wait time logic for :py:class:
.RequestHandler
. This waits by a certain time after each request,
incrementing this wait time every time a 429 code is returned.
This allows better handling of rate limits, with the aim of preventing a lock out from a service.
Changed
- :py:class:
.RequestHandler
now handles requests asynchronously. These changes to async calls have
been implemented all the way on :py:class:.RemoteAPI
and all other objects that depend on it. - All I/O operations on local libraries and their dependent objects now run asynchronously.
- Dependency injection pattern for :py:class:
.RequestHandler
.
Now takes :py:class:.APIAuthoriser
and generator for :py:class:.ClientSession
objects for instantiation
instead of kwargs for :py:class:.APIAuthoriser
. - Dependency injection pattern for :py:class:
.RemoteAPI
.
Now takes :py:class:.APIAuthoriser
and generator for :py:class:.ResponseCache
objects for instantiation
instead of kwargs for :py:class:.APIAuthoriser
. - :py:class:
.APIAuthoriser
kwargs given to :py:class:.SpotifyAPI
now merge with default kwargs. - Moved
remote_wrangler
attribute from :py:class:.MusifyCollection
to :py:class:.LocalCollection
.
This attribute was only needed by :py:class:.LocalCollection
branch of child classes. - Moved
logger
attribute from :py:class:.Library
to :py:class:.RemoteLibrary
. - Switch some dependencies to be optional for groups of operation: progress bars, musicbee, sqlite
- Replace urllib usages with
yarl
package. - Replace all path logic to use pathlib.Path instead. All
- :py:class:
.SpotifyAPI
now logs to the new central :py:meth:.RequestHandler.log
method
to help unify log formatting. user_id
anduser_name
now raise an error when called before settinguser_data
attribute.
This is due to avoiding asynchronous calls in a property.
It is therefore best to now enter the async context of the api to set these automatically.- Renamed :py:meth:
.LocalGenres.genres
to :py:meth:.LocalGenres.related_genres
- Reduced scope of :py:meth:
.TagWriter._delete_tag
method to private - :py:class:
.LocalTrack
now removes any loaded embedded image from the mutagen file object.
This is to reduce memory usage when loading many of these objects. - Extend logging on :py:meth:
.LocalCollection.log_save_tracks_result
to show when no tags
have been or would be updated. - :py:class:
.RemoteItemChecker
now uses the new :py:meth:.RemoteAPI.get_or_create_playlist
method
when creating playlists to avoid creating many duplicate playlists which could have lead to playlist
creation explosion in repeated uses. The processor also accounts for any items that may have existed
in the playlist before it was run and discounts them from any matches. - :py:class:
.RemoteItemChecker
also uses the new :py:meth:.RemoteAPI.follow_playlist
method
when creating playlists to ensure that a user is following the playlists it creates to avoid 'ghost playlist' issue. - :py:meth:
.SpotifyAPI.create_playlist
now returns the full response rather than just the URL of the playlist. - Moved :py:class:
.RemoteItemChecker
and :py:class:.RemoteItemSearcher
tomusify.processors
package. - Moved :py:class:
.RemoteDataWrangler
up a level tomusify.libraries.remote.core
. - Renamed
musify.libraries.remote.spotify.processors
module tomusify.libraries.remote.spotify.wrangle
. - Moved
musify.logger
module tomusify
base package. - Restructured contents of
musify.core
package to modules inmusify
base package.
Fixed
- Added missing variables to slots definitions
- Correctly applied slots pattern to child classes. Now works as expected.
- :py:class:
.LocalTrack
now copies tags as expected when callingcopy.copy()
- Bug where loading an M3U playlist with new track objects would force all created track objects
to have lower case paths - :py:meth:
.RemoteLibrary.restore_playlists
now correctly handles the backup
output from :py:meth:.RemoteLibrary.backup_playlists
- Issue detecting stdout_handlers affecting :py:meth:
.MusifyLogger.print
and :py:meth:.MusifyLogger.get_iterator
.
Now works as expected. - :py:meth:
.LocalLibrary.artists
now generates a :py:class:.LocalArtist
object per individual artist
rather than on combined artists - Issue where :py:meth:
.SpotifyAPI.extend_items
did not show progress when extending some types of responses - Fixed logic in :py:meth:
.MusifyCollection.intersection
and :py:meth:.MusifyCollection.difference
Removed
- Dependency on
requests
package in favour ofaiohttp
for async requests. - Dependency on
requests-cache
package in favour of custom cache implementation. use_cache
parameter from all :py:class:.RemoteAPI
related methods.
Cache settings now handled by :py:class:.ResponseCache
- ThreadPoolExecutor use on :py:class:
.RemoteItemSearcher
. Now uses asynchronous logic instead. last_modified
field as attribute to ignore when getting attributes
to print onLocalCollection
to improve performance- Removed logger filters and handlers. Moved to CLI repo.
- Deleted
musify.libraries.remote.core.processors
package.
Documentation
- Updated how-to section to reflect implementation of async logic to underlying code
- Created a how-to page for installation