Added
-----
* :py:class:`.RemoteAPI` methods now accept :py:class:`.RemoteResponse` objects as input, refreshing them automatically
* Property 'kind' to all objects which have an associated :py:class:`.RemoteObjectType`
* Introduced :py:class:`.MusifyItemSettable` class to allow distinction
between items that can have their properties set and those that can't
* Extend :py:class:`.FilterMatcher` with group_by tag functionality
* Now fully supports parsing of processors relating to :py:class:`.XAutoPF` objects with full I/O of settings
to/from their related XML files on disk
* Now supports creating new :py:class:`.XAutoPF` files from scratch without the file needing to already exist
For XML values not directly controlled by Musify, users can use the 'default_xml' class attribute
to control the initial default values applied in this scenario
* 'length' property on :py:class:`.MusifyCollection` and implementation on all subclasses
Changed
-------
* Major refactoring and restructuring to all modules to improve modularity and add composition
* The following classes and methods have been modified to implement concurrency to improve performance:
* :py:meth:`.LocalLibrary.load_tracks`
* :py:meth:`.LocalLibrary.save_tracks`
* :py:meth:`.LocalLibrary.load_playlists`
* :py:meth:`.LocalLibrary.save_playlists`
* :py:meth:`.LocalLibrary.json` + optimisation for extracting JSON data from tracks
* :py:class:`.ItemMatcher`
* :py:class:`.RemoteItemChecker`
* :py:class:`.RemoteItemSearcher`
* Made :py:func:`.load_tracks` and :py:func:`.load_playlists` utility functions more DRY
* Move :py:meth:`.TagReader.load` from :py:class:`.LocalTrack` to super class :py:class:`.TagReader`
* :py:meth:`.SpotifyAPI.extend_items` now skips on responses that are already fully extended
* :py:meth:`.SpotifyArtist.load` now uses the base `load` method from :py:class:`.SpotifyCollectionLoader`
meaning it now takes full advantage of the item filtering this method offers.
As part of this, the base method was made more generic to accommodate all :py:class:`.SpotifyObject` types
* Renamed 'kind' property on :py:class:`.LocalTrack` to 'type' to avoid clashing property names
* :py:class:`.ItemMatcher`, :py:class:`.RemoteItemChecker`, and :py:class:`.RemoteItemSearcher` now accept
all MusifyItem types that may have their URI property set manually
* :py:class:`.RemoteItemChecker` and :py:class:`.RemoteItemSearcher` no longer inherit from :py:class:`.ItemMatcher`.
Composite pattern used instead.
* :py:class:`.ItemSorter` now shuffles randomly on unsupported types
+ prioritises fields settings over shuffle settings
* :py:meth:`.Comparer._in_range` now uses inclusive range i.e. ``a <= x <= b`` where ``x`` is the value to compare
and ``a`` and ``b`` are the limits. Previously used exclusive range i.e. ``a < x < b``
* Removed ``from_xml`` and ``to_xml`` methods from all :py:class:`.MusicBeeProcessor` subclasses.
Moved this logic to :py:class:`.XMLPlaylistParser` as distinct 'get' methods for each processor type
* Moved loading of XML file logic from :py:class:`.XAutoPF` to :py:class:`.XMLPlaylistParser`.
:py:class:`.XMLPlaylistParser` is now solely responsible for all XML parsing and handling
for :py:class:`.XAutoPF` files
Fixed
-----
* :py:class:`.Comparer` dynamic processor methods which process string values now cast expected types before processing
Removed
-------
* Redundant ShuffleBy enum and related arguments from :py:class:`.ItemSorter`
* ``ItemProcessor`` and ``MusicBeeProcessor`` abstraction layers. No longer needed after some refactoring
* ``get_filtered_playlists`` method from :py:class:`.Library`.
This contained author specific logic and was not appropriate for general use
Documentation
-------------
* Added info on lint checking for the contributing page