Skip to content
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

Feature/v0.7.7 prep3 #288

Merged
merged 24 commits into from
Oct 14, 2024
Merged
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
0be52bd
Added clarifications to video_url. Check video URLs for all available…
tehkillerbee Sep 11, 2024
24152e4
Populate the track/items.album attributes from the parent Album objec…
tehkillerbee Sep 11, 2024
0c0f332
Remove deprecated username/pass login method (Fixes #279)
tehkillerbee Sep 11, 2024
1d94898
Remove multiple items from UserPlaylist. Set UserPlaylist public/priv…
tehkillerbee Sep 30, 2024
e9fcd6c
Add method for getting public user playlists
tehkillerbee Sep 30, 2024
89cc63b
Formatting
tehkillerbee Sep 30, 2024
90daa30
Updated changelog
tehkillerbee Sep 30, 2024
15191b4
Add support for adding tracks to playlists at an offset. Allow duplic…
tehkillerbee Oct 1, 2024
7c2b777
Add support for moving playlist items (Fixes #116)
tehkillerbee Oct 1, 2024
2c5e42b
Add method return value on success.
tehkillerbee Oct 1, 2024
0a867a6
Updated changelog
tehkillerbee Oct 1, 2024
8c73676
Formatting
tehkillerbee Oct 1, 2024
076fc81
Add track to user playlist, user tracks from ISRC (#96). Updated chan…
tehkillerbee Oct 1, 2024
00fecb6
Add support for playlist folders (#181)
tehkillerbee Oct 8, 2024
4375a0c
Use v2 endpoint for playlist creation. Fix playlist delete naming. Ad…
tehkillerbee Oct 9, 2024
0280c0f
Validate method input
tehkillerbee Oct 10, 2024
21c432e
Added trn to playlist object
tehkillerbee Oct 10, 2024
f8013ae
Add support for playlist merge. Return list of added tracks.
tehkillerbee Oct 10, 2024
9d8aa6b
Add additional playlist tests. Fix broken tests
tehkillerbee Oct 10, 2024
64386f3
Cleanup parser methods. Fix misc. comments.
tehkillerbee Oct 10, 2024
523dec1
Update changelog
tehkillerbee Oct 10, 2024
952abc4
Fix formatting. Removed redundant method
tehkillerbee Oct 10, 2024
6338a2b
Added misc. page tests. Fixed misc. comments.
tehkillerbee Oct 11, 2024
9ad1be5
Fix doxygen. Added playlist folders test
tehkillerbee Oct 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
@@ -4,6 +4,22 @@ History
=======
v0.7.7
------
* Tests: Added additional playlist, folder tests. - tehkillerbee_
* Feature: Add support for playlist merging. - tehkillerbee_
* Added trn to playlist object for convenience. - tehkillerbee_
* Set limits from argument in all relevant methods. - tehkillerbee_
* Feature: Use v2 endpoint for playlist creation. - tehkillerbee_
* Feature: Add support for playlist folders (#181) - tehkillerbee_
* Feature: Add track to user playlist, user tracks from ISRC (#96) - tehkillerbee_
* Feature: Add optional fn_print to Session::login_session_file - GioF71_
* Feature: Add support for moving playlist items (#116) - tehkillerbee_
* Feature: Allow adding items multiple times to the same playlist - tehkillerbee_
* Feature: Add support for adding items to a playlists at a specific position (#116) - tehkillerbee_
* Feature: Set UserPlaylist public/private. Add method for getting public user playlists. - tehkillerbee_
* Feature: Remove multiple items from UserPlaylist. (Fixes #259) - tehkillerbee_
* Remove deprecated username/pass login method (Fixes #279) - tehkillerbee_
* Populate the track/items.album attributes from the parent Album object. Updated tests (Fixes #281) - tehkillerbee_
* Added clarifications to video_url method. Check video URLs for all available video qualities (Fixes #257) - tehkillerbee_
* Tests: Fix all tests that previously failed. - tehkillerbee_
* Use enum to specify default audio / video quality - tehkillerbee_
* Bugfix: Recent TIDAL changes resulted in missing Mix not causing a ObjectNotFound exception. - tehkillerbee_
@@ -198,6 +214,7 @@ v0.6.2
.. _Jimmyscene: https://github.com/Jimmyscene
.. _quodrum-glas: https://github.com/quodrum-glas
.. _M4TH1EU: https://github.com/M4TH1EU
.. _GioF71: https://github.com/GioF71



21 changes: 19 additions & 2 deletions tests/test_album.py
Original file line number Diff line number Diff line change
@@ -23,8 +23,7 @@
from dateutil import tz

import tidalapi
from tidalapi.album import Album
from tidalapi.exceptions import MetadataNotAvailable, ObjectNotFound
from tidalapi.exceptions import ObjectNotFound
from tidalapi.media import AudioMode, Quality

from .cover import verify_image_cover, verify_video_cover
@@ -72,11 +71,20 @@ def test_get_tracks(session):
assert tracks[0].id == 17927864
assert tracks[0].volume_num == 1
assert tracks[0].track_num == 1
assert tracks[0].album == album

assert tracks[-1].name == "Pray"
assert tracks[-1].id == 17927885
assert tracks[-1].volume_num == 2
assert tracks[-1].track_num == 8
assert tracks[-1].album == album

# Getting album.tracks with sparse_album=True will result in a track.album containing only essential fields
tracks_sparse = album.tracks(sparse_album=True)
assert tracks_sparse[0].album.audio_quality is None
assert tracks_sparse[0].album.id == 17927863
assert tracks_sparse[-1].album.audio_quality is None
assert tracks_sparse[-1].album.id == 17927863


def test_get_items(session):
@@ -87,11 +95,20 @@ def test_get_items(session):
assert items[0].id == 108043415
assert items[0].volume_num == 1
assert items[0].track_num == 1
assert items[0].album == album

assert items[-1].name == "Lemonade Film"
assert items[-1].id == 108043437
assert items[-1].volume_num == 1
assert items[-1].track_num == 15
assert items[-1].album == album

# Getting album.items with sparse_album=True will result in a track.album containing only essential fields
items_sparse = album.items(sparse_album=True)
assert items_sparse[0].album.id == 108043414
assert items_sparse[0].album.audio_quality is None
assert items_sparse[-1].album.id == 108043414
assert items_sparse[-1].album.audio_quality is None


def test_image_cover(session):
16 changes: 16 additions & 0 deletions tests/test_media.py
Original file line number Diff line number Diff line change
@@ -23,6 +23,7 @@
from dateutil import tz

import tidalapi
from tidalapi import VideoQuality
from tidalapi.exceptions import MetadataNotAvailable, ObjectNotFound
from tidalapi.media import (
AudioExtensions,
@@ -341,8 +342,23 @@ def test_video_no_release_date(session):
]


def test_video_not_found(session):
with pytest.raises(ObjectNotFound):
session.video(12345678)


def test_video_url(session):
# Test video URLs at all available qualities
video = session.video(125506698)
session.video_quality = VideoQuality.low
url = video.get_url()
assert "m3u8" in url
verify_video_resolution(url, 640, 360)
session.video_quality = VideoQuality.medium
url = video.get_url()
assert "m3u8" in url
verify_video_resolution(url, 1280, 720)
session.video_quality = VideoQuality.high
url = video.get_url()
assert "m3u8" in url
verify_video_resolution(url, 1920, 1080)
21 changes: 19 additions & 2 deletions tests/test_page.py
Original file line number Diff line number Diff line change
@@ -15,7 +15,6 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import pytest

import tidalapi

@@ -48,13 +47,15 @@ def test_get_explore_items(session):
assert first_item.categories[1].title == "Milestone Year Albums"
assert first_item.categories[2].title == "Albums Of The Decade"
playlist = first_item.categories[0].items[0]
assert isinstance(playlist, tidalapi.Playlist)
assert playlist.name # == 'Remember...the 1950s'
assert playlist.num_tracks > 1
assert playlist.num_videos == 0

genre_genres = explore.categories[0].items[1]
genre_genres_page_items = iter(genre_genres.get())
playlist = next(genre_genres_page_items) # Usually a playlist
assert isinstance(playlist, tidalapi.Playlist)
assert playlist.name # == 'Remember...the 1950s'
assert playlist.num_tracks > 1
assert playlist.num_videos == 0
@@ -66,9 +67,25 @@ def test_get_explore_items(session):
assert next(iterator).title == "Country"


def test_hires_page(session):
hires = session.hires_page()
first = next(iter(hires))
assert first.name == "Electronic: Headphone Classics"
assert isinstance(first, tidalapi.Playlist)


def test_for_you(session):
for_you = session.for_you()
assert for_you
first = next(iter(for_you))
assert first.title == "My Daily Discovery"
assert isinstance(first, tidalapi.Mix)


def test_videos(session):
videos = session.videos()
first = next(iter(videos))
assert first.type == "VIDEO"
assert isinstance(first.get(), tidalapi.Video)


def test_show_more(session):
187 changes: 187 additions & 0 deletions tests/test_playlist.py
Original file line number Diff line number Diff line change
@@ -93,6 +93,193 @@ def test_playlist_not_found(session):
session.playlist("12345678")


def test_playlist_categories(session):
playlist = session.user.create_playlist("TestingA", "Testing1234")
playlist_id = playlist.id
assert playlist.add("125169484", allow_duplicates=True)
# Playlist should be found in (user) playlists
user_playlists = session.user.playlists()
playlist_ids = [playlist.id for playlist in user_playlists]
assert playlist_id in playlist_ids

# Playlist not found in user favourite playlists
# playlists_favs = session.user.favorites.playlists()
# playlist_ids = [playlist.id for playlist in playlists_favs]
# assert playlist_id in playlist_ids

# Playlist is found in user (created) playlists and favourite playlists
playlists_and_favs = session.user.playlist_and_favorite_playlists()
playlist_ids = [playlist.id for playlist in playlists_and_favs]
assert playlist_id in playlist_ids

# Check if playlist is found in list of public playlists
public_playlists = session.user.public_playlists()
playlist_ids = [playlist.id for playlist in public_playlists]
assert not playlist_id in playlist_ids
playlist.set_playlist_public()

# Check if playlist is found in list of public playlists
public_playlists = session.user.public_playlists()
playlist_ids = [playlist.id for playlist in public_playlists]
assert playlist_id in playlist_ids
playlist.delete()


def test_playlist_add_duplicate(session):
playlist = session.user.create_playlist("TestingA", "Testing1234")
# track id 125169484
assert 125169484 in playlist.add("125169484", allow_duplicates=True)
assert 125169484 in playlist.add("125169484", allow_duplicates=True)
assert 125169484 not in playlist.add("125169484", allow_duplicates=False)
playlist.add(["125169484", "125169484", "125169484"], allow_duplicates=False)
# Check if track has been added more than 2 times
item_ids = [item.id for item in playlist.items()]
assert item_ids.count(125169484) == 2
# Add again, this time allowing duplicates
assert playlist.add(["125169484", "125169484", "125169484"], allow_duplicates=True)
item_ids = [item.id for item in playlist.items()]
assert item_ids.count(125169484) == 5
playlist.delete()


def test_playlist_add_at_position(session):
playlist = session.user.create_playlist("TestingA", "Testing1234")
playlist_a = session.playlist("7eafb342-141a-4092-91eb-da0012da3a19")
# Add 10 tracks to the new playlist
track_ids = [track.id for track in playlist_a.tracks()]
playlist.add(track_ids[0:10])
# Add a track to the end of the playlist (default)
assert playlist.add("125169484")
item_ids = [item.id for item in playlist.items()]
assert str(item_ids[-1]) == "125169484"
# Add a new track to a specific position
assert playlist.add("77692131", position=2)
# Verify that track matches the expected position
item_ids = [item.id for item in playlist.items()]
assert str(item_ids[2]) == "77692131"
# Add last four tracks to position 2 in the playlist and verify they are stored at the expected location
playlist.add(track_ids[-4:], position=2)
tracks = [item.id for item in playlist.items()][2:6]
for idx, track_id in enumerate(track_ids[-4:]):
assert tracks[idx] == track_id
playlist.delete()


def test_playlist_remove_by_indices(session):
playlist = session.user.create_playlist("TestingA", "Testing1234")
playlist_a = session.playlist("7eafb342-141a-4092-91eb-da0012da3a19")
track_ids = [track.id for track in playlist_a.tracks()][0:9]
playlist.add(track_ids)
# Remove odd tracks
playlist.remove_by_indices([1, 3, 5, 7])
# Verify remaining tracks
tracks = [item.id for item in playlist.items()]
for idx, track_id in enumerate(tracks):
assert track_id == track_ids[idx * 2]
# Remove last track in playlist and check that track has been removed
last_track = tracks[-1]
playlist.remove_by_index(playlist.num_tracks - 1)
tracks = [item.id for item in playlist.items()]
assert last_track not in tracks
playlist.delete()


def test_playlist_remove_by_id(session):
playlist = session.user.create_playlist("TestingA", "Testing1234")
playlist_a = session.playlist("7eafb342-141a-4092-91eb-da0012da3a19")
track_ids = [track.id for track in playlist_a.tracks()][0:9]
playlist.add(track_ids)
# Remove track with specific ID
playlist.remove_by_id(str(track_ids[2]))
tracks = [item.id for item in playlist.items()]
assert track_ids[2] not in tracks
playlist.delete()


def test_playlist_add_isrc(session):
playlist = session.user.create_playlist("TestingA", "Testing1234")
# track id 125169484
assert playlist.add_by_isrc("NOG841907010", allow_duplicates=True)
assert playlist.add_by_isrc("NOG841907010", allow_duplicates=True)
assert not playlist.add_by_isrc("NOG841907010", allow_duplicates=False)
assert not playlist.add_by_isrc(
"NOG841907123", allow_duplicates=True, position=0
) # Does not exist, returns false
# Check if track has been added more than 2 times
item_ids = [item.id for item in playlist.items()]
assert item_ids.count(125169484) == 2
playlist.delete()


def test_playlist_move_by_id(session):
playlist = session.user.create_playlist("TestingA", "Testing1234")
# Add tracks from existing playlist
playlist_a = session.playlist("7eafb342-141a-4092-91eb-da0012da3a19")
track_ids = [track.id for track in playlist_a.tracks()]
playlist.add(track_ids[0:9])
# Move first track to the end
first_track_id = track_ids[0]
playlist.move_by_id(media_id=str(first_track_id), position=playlist.num_tracks - 2)
# Last track(-2) should now match the previous first track
tracks = playlist.tracks()
assert first_track_id == tracks[playlist.num_tracks - 2].id
playlist.delete()


def test_playlist_move_by_index(session):
playlist = session.user.create_playlist("TestingA", "Testing1234")
# Add tracks from existing playlist
playlist_a = session.playlist("7eafb342-141a-4092-91eb-da0012da3a19")
track_ids = [track.id for track in playlist_a.tracks()]
playlist.add(track_ids[0:9])
# Move first track to the end
first_track_id = track_ids[0]
playlist.move_by_index(index=0, position=playlist.num_tracks - 2)
# Last track(-2) should now match the previous first track
tracks = playlist.tracks()
track_ids = [track.id for track in playlist.tracks()]
assert track_ids.index(first_track_id) == playlist.num_tracks - 2
playlist.delete()


def test_playlist_move_by_indices(session):
playlist = session.user.create_playlist("TestingA", "Testing1234")
# Add tracks from existing playlist
playlist_a = session.playlist("7eafb342-141a-4092-91eb-da0012da3a19")
track_ids = [track.id for track in playlist_a.tracks()]
playlist.add(track_ids[0:9])
# Move first 4 tracks to the end
playlist.move_by_indices(indices=[0, 1, 2, 3], position=playlist.num_tracks)
# First four tracks should now be moved to the end
last_tracks = [track.id for track in playlist.tracks()][-4:]
for idx, track_id in enumerate(last_tracks):
assert track_ids[idx] == track_id
playlist.delete()


def test_playlist_merge(session):
playlist = session.user.create_playlist("TestingA", "Testing1234")
# Add tracks from existing playlist
added_items = playlist.merge("7eafb342-141a-4092-91eb-da0012da3a19")
# Check if tracks were added
# Note: Certain tracks might be skipped for unknown reasons. (Why?)
# Therefore, we will compare the list of added items with the actual playlist content.
tracks = [track.id for track in playlist.tracks()]
for track in tracks:
assert track in added_items


def test_playlist_public_private(session):
playlist = session.user.create_playlist("TestingA", "Testing1234")
# Default: UserPlaylist is not public
assert not playlist.public
playlist.set_playlist_public()
assert playlist.public
playlist.set_playlist_private()
assert not playlist.public
playlist.delete()


def test_video_playlist(session):
playlist = session.playlist("aa3611ff-5b25-4bbe-8ce4-36c678c3438f")
assert playlist.id == "aa3611ff-5b25-4bbe-8ce4-36c678c3438f"
7 changes: 0 additions & 7 deletions tests/test_session.py
Original file line number Diff line number Diff line change
@@ -37,13 +37,6 @@ def test_load_oauth_session(session):
assert isinstance(session.user, tidalapi.LoggedInUser)


def test_failed_login():
session = tidalapi.Session()
with pytest.raises(requests.HTTPError):
session.login("", "")
assert session.check_login() is False


@pytest.mark.interactive
def test_oauth_login(capsys):
config = tidalapi.Config(item_limit=20000)
Loading