pyrekordbox 0.3.2__py3-none-any.whl → 0.4.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. pyrekordbox/__init__.py +8 -8
  2. pyrekordbox/__main__.py +3 -2
  3. pyrekordbox/_version.py +2 -2
  4. pyrekordbox/anlz/__init__.py +3 -2
  5. pyrekordbox/anlz/file.py +4 -2
  6. pyrekordbox/anlz/tags.py +3 -1
  7. pyrekordbox/config.py +79 -23
  8. pyrekordbox/db6/__init__.py +2 -2
  9. pyrekordbox/db6/aux_files.py +3 -2
  10. pyrekordbox/db6/database.py +101 -111
  11. pyrekordbox/db6/registry.py +1 -0
  12. pyrekordbox/db6/smartlist.py +7 -6
  13. pyrekordbox/db6/tables.py +44 -16
  14. pyrekordbox/logger.py +0 -1
  15. pyrekordbox/mysettings/__init__.py +5 -4
  16. pyrekordbox/mysettings/file.py +3 -1
  17. pyrekordbox/rbxml.py +5 -3
  18. pyrekordbox/utils.py +4 -3
  19. {pyrekordbox-0.3.2.dist-info → pyrekordbox-0.4.0.dist-info}/METADATA +21 -41
  20. pyrekordbox-0.4.0.dist-info/RECORD +25 -0
  21. {pyrekordbox-0.3.2.dist-info → pyrekordbox-0.4.0.dist-info}/WHEEL +1 -1
  22. {pyrekordbox-0.3.2.dist-info → pyrekordbox-0.4.0.dist-info}/top_level.txt +0 -2
  23. docs/Makefile +0 -20
  24. docs/make.bat +0 -35
  25. docs/source/_static/images/anlz_beat.svg +0 -53
  26. docs/source/_static/images/anlz_file.svg +0 -204
  27. docs/source/_static/images/anlz_pco2.svg +0 -138
  28. docs/source/_static/images/anlz_pcob.svg +0 -148
  29. docs/source/_static/images/anlz_pcp2.svg +0 -398
  30. docs/source/_static/images/anlz_pcpt.svg +0 -263
  31. docs/source/_static/images/anlz_ppth.svg +0 -123
  32. docs/source/_static/images/anlz_pqt2.svg +0 -324
  33. docs/source/_static/images/anlz_pqt2_2.svg +0 -253
  34. docs/source/_static/images/anlz_pqtz.svg +0 -140
  35. docs/source/_static/images/anlz_pssi.svg +0 -192
  36. docs/source/_static/images/anlz_pssi_entry.svg +0 -191
  37. docs/source/_static/images/anlz_pvbr.svg +0 -125
  38. docs/source/_static/images/anlz_pwav.svg +0 -130
  39. docs/source/_static/images/anlz_pwv3.svg +0 -139
  40. docs/source/_static/images/anlz_pwv4.svg +0 -139
  41. docs/source/_static/images/anlz_pwv5.svg +0 -139
  42. docs/source/_static/images/anlz_pwv5_entry.svg +0 -100
  43. docs/source/_static/images/anlz_pwv6.svg +0 -130
  44. docs/source/_static/images/anlz_pwv7.svg +0 -139
  45. docs/source/_static/images/anlz_pwvc.svg +0 -125
  46. docs/source/_static/images/anlz_tag.svg +0 -110
  47. docs/source/_static/images/x64dbg_rb_key.png +0 -0
  48. docs/source/_static/logos/dark/logo_primary.svg +0 -75
  49. docs/source/_static/logos/light/logo_primary.svg +0 -75
  50. docs/source/_static/logos/mid/logo_primary.svg +0 -75
  51. docs/source/_templates/apidoc/module.rst_t +0 -8
  52. docs/source/_templates/apidoc/package.rst_t +0 -57
  53. docs/source/_templates/apidoc/toc.rst_t +0 -7
  54. docs/source/_templates/autosummary/class.rst +0 -32
  55. docs/source/_templates/autosummary/module.rst +0 -55
  56. docs/source/api.md +0 -18
  57. docs/source/conf.py +0 -178
  58. docs/source/development/changes.md +0 -3
  59. docs/source/development/contributing.md +0 -3
  60. docs/source/formats/anlz.md +0 -634
  61. docs/source/formats/db6.md +0 -1233
  62. docs/source/formats/mysetting.md +0 -392
  63. docs/source/formats/xml.md +0 -376
  64. docs/source/index.md +0 -103
  65. docs/source/installation.md +0 -271
  66. docs/source/key.md +0 -103
  67. docs/source/quickstart.md +0 -189
  68. docs/source/requirements.txt +0 -7
  69. docs/source/tutorial/anlz.md +0 -7
  70. docs/source/tutorial/configuration.md +0 -66
  71. docs/source/tutorial/db6.md +0 -178
  72. docs/source/tutorial/index.md +0 -20
  73. docs/source/tutorial/mysetting.md +0 -124
  74. docs/source/tutorial/xml.md +0 -140
  75. pyrekordbox/xml.py +0 -8
  76. pyrekordbox-0.3.2.dist-info/RECORD +0 -84
  77. tests/__init__.py +0 -3
  78. tests/test_anlz.py +0 -206
  79. tests/test_config.py +0 -175
  80. tests/test_db6.py +0 -1193
  81. tests/test_mysetting.py +0 -203
  82. tests/test_xml.py +0 -629
  83. {pyrekordbox-0.3.2.dist-info → pyrekordbox-0.4.0.dist-info}/LICENSE +0 -0
tests/test_db6.py DELETED
@@ -1,1193 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- # Author: Dylan Jones
3
- # Date: 2023-02-01
4
-
5
- import os
6
- import pytest
7
- from pytest import mark
8
- from pathlib import Path
9
- import shutil
10
- import tempfile
11
- from sqlalchemy.orm.query import Query
12
- from pyrekordbox import Rekordbox6Database, open_rekordbox_database
13
- from pyrekordbox.db6 import tables
14
- from pyrekordbox.db6.smartlist import SmartList, LogicalOperator, Operator, Property
15
-
16
- TEST_ROOT = Path(__file__).parent.parent / ".testdata"
17
- LOCKED = TEST_ROOT / "rekordbox 6" / "master_locked.db"
18
- UNLOCKED = TEST_ROOT / "rekordbox 6" / "master_unlocked.db"
19
- UNLOCKED_COPY = TEST_ROOT / "rekordbox 6" / "master_unlocked_copy.db"
20
- UNLOCKED_OUT = TEST_ROOT / "rekordbox 6" / "master_unlocked_out.db"
21
- MASTER_PLAYLIST_SRC = TEST_ROOT / "rekordbox 6" / "masterPlaylists6_template.xml"
22
- MASTER_PLAYLIST_DST = TEST_ROOT / "rekordbox 6" / "masterPlaylists6.xml"
23
- # Create a copy of the masterPlaylists6.xml file
24
- shutil.copy(MASTER_PLAYLIST_SRC, MASTER_PLAYLIST_DST)
25
-
26
- DB = Rekordbox6Database(UNLOCKED, unlock=False)
27
-
28
- # Content IDs
29
- CID1 = 178162577 # Demo Track 1
30
- CID2 = 66382436 # Demo Track 2
31
- CID3 = 181094952 # HORN
32
- CID4 = 24401986 # NOISE
33
-
34
- # Playlist ID
35
- PID1 = 2602250856 # Trial playlist - Cloud Library Sync
36
-
37
-
38
- @pytest.fixture
39
- def db():
40
- """Return a clean Rekordbox v6 database instance and close it after tests."""
41
- shutil.copy(UNLOCKED, UNLOCKED_COPY)
42
- shutil.copy(MASTER_PLAYLIST_SRC, MASTER_PLAYLIST_DST)
43
- db = Rekordbox6Database(UNLOCKED_COPY, unlock=False)
44
- yield db
45
- db.close()
46
-
47
-
48
- def test_open_rekordbox_database():
49
- con = open_rekordbox_database(UNLOCKED, unlock=False)
50
- con.execute("SELECT name FROM sqlite_master WHERE type='table';")
51
- con.close()
52
-
53
-
54
- def test_close_open():
55
- db = Rekordbox6Database(UNLOCKED, unlock=False)
56
- db.close()
57
- db.open()
58
- _ = db.get_content()[0] # Try to query the database
59
- db.close()
60
-
61
-
62
- @mark.parametrize(
63
- "name,cls",
64
- [
65
- ("get_active_censor", tables.DjmdActiveCensor),
66
- ("get_album", tables.DjmdAlbum),
67
- ("get_artist", tables.DjmdArtist),
68
- ("get_category", tables.DjmdCategory),
69
- ("get_color", tables.DjmdColor),
70
- ("get_content", tables.DjmdContent),
71
- ("get_cue", tables.DjmdCue),
72
- ("get_device", tables.DjmdDevice),
73
- ("get_genre", tables.DjmdGenre),
74
- ("get_history", tables.DjmdHistory),
75
- ("get_hot_cue_banklist", tables.DjmdHotCueBanklist),
76
- ("get_key", tables.DjmdKey),
77
- ("get_label", tables.DjmdLabel),
78
- ("get_menu_items", tables.DjmdMenuItems),
79
- ("get_mixer_param", tables.DjmdMixerParam),
80
- ("get_my_tag", tables.DjmdMyTag),
81
- ("get_playlist", tables.DjmdPlaylist),
82
- ("get_property", tables.DjmdProperty),
83
- ("get_related_tracks", tables.DjmdRelatedTracks),
84
- ("get_sampler", tables.DjmdSampler),
85
- ("get_sort", tables.DjmdSort),
86
- ("get_agent_registry", tables.AgentRegistry),
87
- ("get_cloud_agent_registry", tables.CloudAgentRegistry),
88
- ("get_content_active_censor", tables.ContentActiveCensor),
89
- ("get_content_cue", tables.ContentCue),
90
- ("get_content_file", tables.ContentFile),
91
- ("get_hot_cue_banklist_cue", tables.HotCueBanklistCue),
92
- ("get_image_file", tables.ImageFile),
93
- ("get_setting_file", tables.SettingFile),
94
- ("get_uuid_map", tables.UuidIDMap),
95
- ],
96
- )
97
- def test_getter(name, cls):
98
- getter = getattr(DB, name)
99
- # Test return is query
100
- query = getter()
101
- assert isinstance(query, Query)
102
- assert query.column_descriptions[0]["type"] == cls
103
-
104
- # Test type of query result is the right table class
105
- res = query.first()
106
- assert res is None or isinstance(res, cls)
107
-
108
-
109
- @mark.parametrize(
110
- "name,cls",
111
- [
112
- ("get_active_censor", tables.DjmdActiveCensor),
113
- ("get_album", tables.DjmdAlbum),
114
- ("get_artist", tables.DjmdArtist),
115
- ("get_category", tables.DjmdCategory),
116
- ("get_color", tables.DjmdColor),
117
- ("get_content", tables.DjmdContent),
118
- ("get_cue", tables.DjmdCue),
119
- ("get_device", tables.DjmdDevice),
120
- ("get_genre", tables.DjmdGenre),
121
- ("get_history", tables.DjmdHistory),
122
- ("get_hot_cue_banklist", tables.DjmdHotCueBanklist),
123
- ("get_key", tables.DjmdKey),
124
- ("get_label", tables.DjmdLabel),
125
- ("get_menu_items", tables.DjmdMenuItems),
126
- ("get_mixer_param", tables.DjmdMixerParam),
127
- ("get_my_tag", tables.DjmdMyTag),
128
- ("get_playlist", tables.DjmdPlaylist),
129
- # ("get_property", tables.DjmdProperty),
130
- ("get_related_tracks", tables.DjmdRelatedTracks),
131
- ("get_sampler", tables.DjmdSampler),
132
- ("get_sort", tables.DjmdSort),
133
- # ("get_agent_registry", tables.AgentRegistry),
134
- ("get_cloud_agent_registry", tables.CloudAgentRegistry),
135
- ("get_content_active_censor", tables.ContentActiveCensor),
136
- ("get_content_cue", tables.ContentCue),
137
- ("get_content_file", tables.ContentFile),
138
- ("get_hot_cue_banklist_cue", tables.HotCueBanklistCue),
139
- ("get_image_file", tables.ImageFile),
140
- ("get_setting_file", tables.SettingFile),
141
- ("get_uuid_map", tables.UuidIDMap),
142
- ],
143
- )
144
- def test_getter_by_id(name, cls):
145
- # Get method from class
146
- getter = getattr(DB, name)
147
-
148
- # Try to get a valid ID
149
- item = getter().first()
150
- if item is None:
151
- return
152
- id_ = item.ID
153
-
154
- # Test type of result is a table class, not the query
155
- res = getter(ID=id_)
156
- assert res is None or isinstance(res, cls)
157
-
158
-
159
- @mark.parametrize(
160
- "parent_name,key,cls",
161
- [
162
- ("get_history", "HistoryID", tables.DjmdSongHistory),
163
- ("get_hot_cue_banklist", "HotCueBanklistID", tables.DjmdSongHotCueBanklist),
164
- ("get_my_tag", "MyTagID", tables.DjmdSongMyTag),
165
- ("get_playlist", "PlaylistID", tables.DjmdSongPlaylist),
166
- ("get_related_tracks", "RelatedTracksID", tables.DjmdSongPlaylist),
167
- ("get_sampler", "SamplerID", tables.DjmdSongPlaylist),
168
- ],
169
- )
170
- def test_songs_getters(parent_name, key, cls):
171
- # Get list (containing songs) getter
172
- getter = getattr(DB, parent_name)
173
- # Try to get a valid list ID
174
- query = getter()
175
- if not query.count():
176
- return # No data to check...
177
-
178
- item = query.first()
179
- id_ = item.ID
180
-
181
- # Get list songs getter
182
- getter = getattr(DB, f"{parent_name}_songs")
183
- # Get song items
184
- query = getter(**{key: id_})
185
- if not query.count():
186
- return # No data to check...
187
-
188
- assert isinstance(query.first(), cls)
189
-
190
-
191
- def test_mixer_gain_setters(db):
192
- for item in db.get_mixer_param():
193
- # Check Gain setter
194
- low, high, value = int(item.GainLow), int(item.GainHigh), item.Gain
195
- item.Gain = value
196
- db.flush()
197
- assert item.GainLow == low
198
- assert item.GainHigh == high
199
-
200
- # Check Peak setter
201
- low, high, value = int(item.PeakLow), int(item.PeakHigh), item.Peak
202
- item.Peak = value
203
- db.flush()
204
- assert item.PeakLow == low
205
- assert item.PeakHigh == high
206
-
207
-
208
- @mark.parametrize(
209
- "search,ids",
210
- [
211
- ("Demo Track 1", [CID1]), # Title
212
- ("Demo Track 2", [CID2]), # Title
213
- ("Loopmasters", [CID1, CID2]), # Label/Artist Name
214
- ("Noise", [CID4]), # lowercase
215
- ("NOIS", [CID4]), # incomplete
216
- ],
217
- )
218
- def test_search_content(search, ids):
219
- results = DB.search_content(search)
220
- for id_, res in zip(ids, results):
221
- assert int(res.ID) == id_
222
-
223
-
224
- def test_increment_local_usn(db):
225
- old = db.get_local_usn()
226
- db.increment_local_usn()
227
- assert db.get_local_usn() == old + 1
228
-
229
- db.increment_local_usn(1)
230
- assert db.get_local_usn() == old + 2
231
-
232
- db.increment_local_usn(2)
233
- assert db.get_local_usn() == old + 4
234
-
235
- with pytest.raises(ValueError):
236
- db.increment_local_usn(0)
237
-
238
- with pytest.raises(ValueError):
239
- db.increment_local_usn(-1)
240
-
241
-
242
- def test_autoincrement_local_usn(db):
243
- old_usn = db.get_local_usn() # store USN before changes
244
- track1 = db.get_content(ID=CID1)
245
- track2 = db.get_content(ID=CID2)
246
- track3 = db.get_content(ID=CID3)
247
- playlist = db.get_playlist(ID=PID1)
248
- with db.session.no_autoflush:
249
- # Change one field in first track (+1)
250
- track1.Title = "New title 1"
251
- # Change two fields in second track (+2)
252
- track2.Title = "New title 2"
253
- track2.BPM = 12900
254
- # Delete row from table )+1)
255
- db.delete(track3)
256
- # Change name of playlist (+1)
257
- playlist.Name = "New name"
258
-
259
- # Auto-increment USN
260
- new_usn = db.autoincrement_usn()
261
-
262
- # Check local Rekordbox USN and instance USN's
263
- assert new_usn == old_usn + 5
264
- assert track1.rb_local_usn == old_usn + 1
265
- assert track2.rb_local_usn == old_usn + 3
266
- # USN of deleted rows obviously don't get updated
267
- assert playlist.rb_local_usn == new_usn
268
-
269
-
270
- def _check_playlist_xml(db):
271
- # Check that playlist is in XML and update time is correct
272
- for pl in db.get_playlist():
273
- plxml = db.playlist_xml.get(pl.ID)
274
- ts = plxml["Timestamp"]
275
- diff = pl.updated_at - ts
276
- if abs(diff.total_seconds()) > 1:
277
- return False
278
- return True
279
-
280
-
281
- def _check_playlist_xml_delete(db):
282
- # Check that there are no items in the XML that are not in the db
283
- for plxml in db.playlist_xml.get_playlists():
284
- if plxml["Lib_Type"] != 0:
285
- continue
286
- pid = int(plxml["Id"], 16)
287
- if db.query(tables.DjmdPlaylist).filter_by(ID=pid).count() != 1:
288
- return False
289
- return True
290
-
291
-
292
- def test_add_song_to_playlist(db):
293
- usn_old = db.get_local_usn()
294
- mtime_old = db.get_playlist(ID=PID1).updated_at
295
-
296
- # test adding song to playlist
297
- song = db.add_to_playlist(PID1, CID1)
298
- db.commit()
299
-
300
- pl = db.get_playlist(ID=PID1)
301
- assert len(pl.Songs) == 1
302
- assert pl.Songs[0].ContentID == str(CID1)
303
- assert song.TrackNo == 1
304
-
305
- # Test USN and update time are correct
306
- assert pl.updated_at == mtime_old
307
- assert song.rb_local_usn == usn_old + 1
308
- assert db.get_local_usn() == usn_old + 1
309
-
310
- # test raising error when adding song to playlist with wrong TrackNo
311
- with pytest.raises(ValueError):
312
- db.add_to_playlist(PID1, CID2, track_no=0)
313
- with pytest.raises(ValueError):
314
- db.add_to_playlist(PID1, CID2, track_no=3)
315
-
316
- assert _check_playlist_xml(db)
317
-
318
-
319
- def test_add_song_to_playlist_trackno_end(db):
320
- old_usn = db.get_local_usn()
321
- song1 = db.add_to_playlist(PID1, CID1)
322
- song2 = db.add_to_playlist(PID1, CID2)
323
- song3 = db.add_to_playlist(PID1, CID3)
324
- db.commit()
325
- assert song1.TrackNo == 1
326
- assert song2.TrackNo == 2
327
- assert song3.TrackNo == 3
328
- assert db.get_local_usn() == old_usn + 3
329
-
330
- assert _check_playlist_xml(db)
331
-
332
-
333
- def test_add_song_to_playlist_trackno_middle(db):
334
- song1 = db.add_to_playlist(PID1, CID1)
335
- song2 = db.add_to_playlist(PID1, CID2)
336
- assert song1.TrackNo == 1
337
- assert song2.TrackNo == 2
338
- db.commit()
339
-
340
- usn_old = db.get_local_usn()
341
- mtime_old = db.get_playlist(ID=PID1).updated_at
342
-
343
- # Insert song in the middle
344
- song3 = db.add_to_playlist(PID1, CID3, track_no=2)
345
- db.commit()
346
- assert song3.TrackNo == 2
347
-
348
- pl = db.get_playlist(ID=PID1)
349
- songs = sorted(pl.Songs, key=lambda x: int(x.TrackNo))
350
- assert len(songs) == 3
351
- assert songs[0].ContentID == str(CID1)
352
- assert songs[0].TrackNo == 1
353
- assert songs[1].ContentID == str(CID3)
354
- assert songs[1].TrackNo == 2
355
- assert songs[2].ContentID == str(CID2)
356
- assert songs[2].TrackNo == 3
357
-
358
- # Test USN and update time are correct
359
- # First USN increment is for adding song, second for updating track no
360
- # of other songs in playlist
361
- assert pl.updated_at == mtime_old
362
- assert songs[1].rb_local_usn == usn_old + 2
363
- assert songs[2].rb_local_usn == usn_old + 2
364
- assert db.get_local_usn() == usn_old + 2
365
-
366
- assert _check_playlist_xml(db)
367
-
368
-
369
- def test_remove_song_from_playlist_end(db):
370
- # Add songs to playlist
371
- db.add_to_playlist(PID1, CID1, track_no=1)
372
- db.add_to_playlist(PID1, CID2, track_no=2)
373
- song3 = db.add_to_playlist(PID1, CID3, track_no=3)
374
- sid3 = song3.ID
375
- db.commit()
376
-
377
- usn_old = db.get_local_usn()
378
- mtime_old = db.get_playlist(ID=PID1).updated_at
379
-
380
- # test removing song from playlist
381
- db.remove_from_playlist(PID1, sid3)
382
- db.commit()
383
-
384
- pl = db.get_playlist(ID=PID1)
385
- songs = sorted(pl.Songs, key=lambda x: x.TrackNo)
386
- assert len(songs) == 2
387
- assert songs[0].ContentID == str(CID1)
388
- assert songs[0].TrackNo == 1
389
- assert songs[1].ContentID == str(CID2)
390
- assert songs[1].TrackNo == 2
391
- pl = db.get_playlist(ID=PID1)
392
- # Test USN and update time are correct
393
- assert pl.updated_at == mtime_old
394
- assert db.get_local_usn() == usn_old + 1
395
-
396
- assert _check_playlist_xml(db)
397
-
398
-
399
- def test_remove_song_from_playlist_middle(db):
400
- # Add songs to playlist
401
- db.add_to_playlist(PID1, CID1, track_no=1)
402
- song2 = db.add_to_playlist(PID1, CID2, track_no=2)
403
- db.add_to_playlist(PID1, CID3, track_no=3)
404
- sid2 = song2.ID
405
- db.commit()
406
- usn_old = db.get_local_usn()
407
-
408
- # test removing song from playlist
409
- db.remove_from_playlist(PID1, sid2)
410
- db.commit()
411
-
412
- pl = db.get_playlist(ID=PID1)
413
- songs = sorted(pl.Songs, key=lambda x: x.TrackNo)
414
- assert len(songs) == 2
415
- assert songs[0].ContentID == str(CID1)
416
- assert songs[0].TrackNo == 1
417
- assert songs[1].ContentID == str(CID3)
418
- assert songs[1].TrackNo == 2
419
-
420
- # Check USN is correct
421
- assert db.get_local_usn() == usn_old + 2
422
- assert songs[1].rb_local_usn == usn_old + 2
423
-
424
- assert _check_playlist_xml(db)
425
-
426
-
427
- def test_move_in_playlist_forward(db):
428
- # Add songs to playlist
429
- s1 = db.add_to_playlist(PID1, CID1)
430
- s2 = db.add_to_playlist(PID1, CID2)
431
- s3 = db.add_to_playlist(PID1, CID3)
432
- s4 = db.add_to_playlist(PID1, CID4)
433
- db.commit()
434
- pl = db.get_playlist(ID=PID1)
435
- songs = sorted(pl.Songs, key=lambda x: x.TrackNo)
436
- assert [int(s.ContentID) for s in songs] == [CID1, CID2, CID3, CID4]
437
- usn_old = db.get_local_usn()
438
-
439
- # Move song forward
440
- db.move_song_in_playlist(PID1, s3, 1)
441
- db.commit()
442
- pl = db.get_playlist(ID=PID1)
443
- songs = sorted(pl.Songs, key=lambda x: x.TrackNo)
444
- assert [int(s.ContentID) for s in songs] == [CID3, CID1, CID2, CID4]
445
-
446
- # Check USN
447
- expected_usn = usn_old + 1
448
- assert db.get_local_usn() == expected_usn
449
- assert s1.rb_local_usn == expected_usn
450
- assert s2.rb_local_usn == expected_usn
451
- assert s3.rb_local_usn == expected_usn
452
- assert s4.rb_local_usn == usn_old
453
-
454
- assert _check_playlist_xml(db)
455
-
456
-
457
- def test_move_in_playlist_backward(db):
458
- # Add songs to playlist
459
- s1 = db.add_to_playlist(PID1, CID1)
460
- s2 = db.add_to_playlist(PID1, CID2)
461
- s3 = db.add_to_playlist(PID1, CID3)
462
- s4 = db.add_to_playlist(PID1, CID4)
463
- db.commit()
464
- pl = db.get_playlist(ID=PID1)
465
- songs = sorted(pl.Songs, key=lambda x: x.TrackNo)
466
- assert [int(s.ContentID) for s in songs] == [CID1, CID2, CID3, CID4]
467
- usn_old = db.get_local_usn()
468
-
469
- # Move song backward
470
- db.move_song_in_playlist(PID1, s1, 3)
471
- db.commit()
472
- pl = db.get_playlist(ID=PID1)
473
- songs = sorted(pl.Songs, key=lambda x: x.TrackNo)
474
- assert [int(s.ContentID) for s in songs] == [CID2, CID3, CID1, CID4]
475
-
476
- # Check USN
477
- expected_usn = usn_old + 1
478
- assert db.get_local_usn() == expected_usn
479
- assert s1.rb_local_usn == expected_usn
480
- assert s2.rb_local_usn == expected_usn
481
- assert s3.rb_local_usn == expected_usn
482
- assert s4.rb_local_usn == usn_old
483
-
484
- assert _check_playlist_xml(db)
485
-
486
-
487
- def test_create_playlist(db):
488
- seqs = [pl.Seq for pl in db.get_playlist()]
489
- assert max(seqs) == 2
490
- old_usn = db.get_local_usn()
491
-
492
- # Create playlist
493
- pl = db.create_playlist("Test playlist")
494
- pid = pl.ID
495
- db.commit()
496
-
497
- # Check if playlist was created correctly
498
- pl = db.get_playlist(ID=pid)
499
- assert pl.Name == "Test playlist"
500
- assert pl.Seq == 3
501
- assert pl.Attribute == 0
502
- assert pl.Songs == []
503
- assert pl.ParentID == "root"
504
- assert pl.Children == []
505
-
506
- # Check USN is correct (+1 for creating, +1 for renaming)
507
- assert pl.rb_local_usn == old_usn + 2
508
- assert db.get_local_usn() == old_usn + 2
509
-
510
- # Try to add song to playlist
511
- db.add_to_playlist(pl, CID1)
512
- db.commit()
513
-
514
- pl = db.get_playlist(ID=pid)
515
- assert len(pl.Songs) == 1
516
-
517
- # Check if playlist was added to xml
518
- plxml = db.playlist_xml.get(pl.ID)
519
- assert plxml is not None
520
- assert _check_playlist_xml(db)
521
-
522
-
523
- def test_create_playlist_seq_middle(db):
524
- seqs = [pl.Seq for pl in db.get_playlist()]
525
- assert max(seqs) == 2
526
- old_usn = db.get_local_usn()
527
-
528
- # Create playlist
529
- pl = db.create_playlist("playlist1")
530
- pid1 = pl.ID
531
- assert pl.Seq == 3
532
- db.commit()
533
- # Check USN is correct (+1 for creating, +1 for renaming)
534
- assert pl.rb_local_usn == old_usn + 2
535
- assert db.get_local_usn() == old_usn + 2
536
-
537
- old_usn = db.get_local_usn()
538
- pl = db.create_playlist("playlist2", seq=3)
539
- pid2 = pl.ID
540
- db.commit()
541
-
542
- pl1 = db.get_playlist(ID=pid1)
543
- pl2 = db.get_playlist(ID=pid2)
544
- assert pl1.Seq == 4
545
- assert pl2.Seq == 3
546
- # Check USN is correct
547
- assert db.get_local_usn() == old_usn + 3 # +2 for creating, +1 for moving others
548
- assert pl1.rb_local_usn == old_usn + 1
549
- assert pl2.rb_local_usn == old_usn + 3
550
-
551
- assert _check_playlist_xml(db)
552
-
553
-
554
- def test_create_playlist_folder(db):
555
- seqs = [pl.Seq for pl in db.get_playlist()]
556
- assert max(seqs) == 2
557
- usn_old = db.get_local_usn()
558
-
559
- # Create playlist
560
- pl = db.create_playlist_folder("Test playlist folder")
561
- pid = pl.ID
562
- db.commit()
563
-
564
- # Check if playlist folder was created correctly
565
- pl = db.get_playlist(ID=pid)
566
- assert pl.Name == "Test playlist folder"
567
- assert pl.Seq == 3
568
- assert pl.Attribute == 1
569
- assert pl.Songs == []
570
- assert pl.ParentID == "root"
571
- assert pl.Children == []
572
- # Check USN is correct (+1 for creating, +1 for renaming)
573
- assert db.get_local_usn() == usn_old + 2
574
- assert pl.rb_local_usn == usn_old + 2
575
-
576
- # Try to add sub-playlist to playlist folder
577
- db.create_playlist("Test playlist", parent=pl)
578
- db.commit()
579
-
580
- pl = db.get_playlist(ID=pid)
581
- assert len(pl.Children) == 1
582
-
583
- assert _check_playlist_xml(db)
584
-
585
-
586
- def test_create_smart_playlist(db):
587
- seqs = [pl.Seq for pl in db.get_playlist()]
588
- assert max(seqs) == 2
589
- old_usn = db.get_local_usn()
590
-
591
- # Create smart list
592
- smart = SmartList(LogicalOperator.ALL)
593
- smart.add_condition(Property.ARTIST, Operator.EQUAL, "Loopmasters")
594
-
595
- # create smart playlist from smart list
596
- pl = db.create_smart_playlist("Smart playlist", smart)
597
- pid = pl.ID
598
- db.commit()
599
-
600
- # Check if playlist was created correctly
601
- pl = db.get_playlist(ID=pid)
602
- assert pl.Name == "Smart playlist"
603
- assert pl.Seq == 3
604
- assert pl.Attribute == 4
605
- assert pl.Songs == []
606
- assert pl.ParentID == "root"
607
- assert pl.Children == []
608
-
609
- # Check USN is correct (+1 for creating, +1 for renaming)
610
- assert pl.rb_local_usn == old_usn + 2
611
- assert db.get_local_usn() == old_usn + 2
612
-
613
- # Check if playlist was added to xml
614
- plxml = db.playlist_xml.get(pl.ID)
615
- assert plxml is not None
616
- assert _check_playlist_xml(db)
617
-
618
-
619
- def test_delete_playlist_empty_end(db):
620
- # Create playlist structure
621
- folder = db.create_playlist_folder("folder")
622
- pl1 = db.create_playlist("sub playlist 1", parent=folder.ID)
623
- pl2 = db.create_playlist("sub playlist 2", parent=folder.ID)
624
- pl3 = db.create_playlist("sub playlist 3", parent=folder.ID)
625
- assert pl1.Seq == 1 and pl2.Seq == 2 and pl3.Seq == 3
626
- db.commit()
627
- usn_old = db.get_local_usn()
628
-
629
- # Delete playlist
630
- pl = db.get_playlist(Name="sub playlist 3").one()
631
- pid = pl.ID
632
- db.delete_playlist(pl)
633
- db.commit()
634
-
635
- # Check if playlist was deleted
636
- pl = db.get_playlist(ID=pid)
637
- assert pl is None
638
- # Check if playlist was deleted from xml
639
- plxml = db.playlist_xml.get(pid)
640
- assert plxml is None
641
- # Check USN is correct (+1 for deleting)
642
- assert db.get_local_usn() == usn_old + 1
643
-
644
- assert _check_playlist_xml(db)
645
- assert _check_playlist_xml_delete(db)
646
-
647
-
648
- def test_delete_playlist_empty(db):
649
- # Create playlist structure
650
- folder = db.create_playlist_folder("folder")
651
- pl1 = db.create_playlist("sub playlist 1", parent=folder.ID)
652
- pl2 = db.create_playlist("sub playlist 2", parent=folder.ID)
653
- pl3 = db.create_playlist("sub playlist 3", parent=folder.ID)
654
- assert pl1.Seq == 1 and pl2.Seq == 2 and pl3.Seq == 3
655
- db.commit()
656
- usn_old = db.get_local_usn()
657
-
658
- # Delete playlist
659
- pl = db.get_playlist(Name="sub playlist 2").one()
660
- pid = pl.ID
661
- db.delete_playlist(pl)
662
- db.commit()
663
-
664
- # Check if playlist was deleted
665
- pl = db.get_playlist(ID=pid)
666
- assert pl is None
667
- # Check if playlist was deleted from xml
668
- plxml = db.playlist_xml.get(pid)
669
- assert plxml is None
670
- # Check USN is correct (+1 for deleting, all moved playlists get same USN)
671
- assert db.get_local_usn() == usn_old + 1
672
- # Check if seq numbers in parent were updated
673
- pl = db.get_playlist(Name="sub playlist 3").one()
674
- assert pl.Seq == 2
675
- assert pl.rb_local_usn == usn_old + 1
676
-
677
- assert _check_playlist_xml(db)
678
- assert _check_playlist_xml_delete(db)
679
-
680
-
681
- def test_delete_playlist_folder_empty(db):
682
- # Create playlist structure
683
- folder = db.create_playlist_folder("folder")
684
- pl1 = db.create_playlist("sub playlist 1", parent=folder.ID)
685
- pl2 = db.create_playlist_folder("sub playlist folder", parent=folder.ID)
686
- pl3 = db.create_playlist("sub playlist 3", parent=folder.ID)
687
- assert pl1.Seq == 1 and pl2.Seq == 2 and pl3.Seq == 3
688
- db.commit()
689
- usn_old = db.get_local_usn()
690
-
691
- # Delete playlist
692
- pl = db.get_playlist(Name="sub playlist folder").one()
693
- pid = pl.ID
694
- db.delete_playlist(pl)
695
- db.commit()
696
-
697
- # Check if playlist was deleted
698
- pl = db.get_playlist(ID=pid)
699
- assert pl is None
700
- # Check if playlist was deleted from xml
701
- plxml = db.playlist_xml.get(pid)
702
- assert plxml is None
703
- # Check if seq numbers in parent were updated
704
- pl = db.get_playlist(Name="sub playlist 3").one()
705
- assert pl.Seq == 2
706
- # Check USN is correct (+1 for deleting)
707
- assert db.get_local_usn() == usn_old + 1
708
- assert pl.rb_local_usn == usn_old + 1
709
-
710
- assert _check_playlist_xml(db)
711
- assert _check_playlist_xml_delete(db)
712
-
713
-
714
- def test_delete_playlist_non_empty(db):
715
- # Create playlist structure
716
- folder = db.create_playlist_folder("folder")
717
- pl1 = db.create_playlist("sub playlist 1", parent=folder.ID)
718
- pl2 = db.create_playlist("sub playlist 2", parent=folder.ID)
719
- pl3 = db.create_playlist("sub playlist 3", parent=folder.ID)
720
- # Add songs to playlists
721
- sid1 = db.add_to_playlist(pl1, CID1).ID
722
- sid2 = db.add_to_playlist(pl2, CID2).ID
723
- sid3 = db.add_to_playlist(pl2, CID3).ID
724
- sid4 = db.add_to_playlist(pl3, CID4).ID
725
- db.commit()
726
- usn_old = db.get_local_usn()
727
-
728
- assert db.query(tables.DjmdSongPlaylist).count() == 4
729
-
730
- # Delete playlist
731
- pl = db.get_playlist(Name="sub playlist 2").one()
732
- pid = pl.ID
733
- db.delete_playlist(pl)
734
- db.commit()
735
-
736
- # Check if playlist was deleted
737
- pl = db.get_playlist(ID=pid)
738
- assert pl is None
739
- # Check if songs in playlist were deleted
740
- assert db.query(tables.DjmdSongPlaylist).count() == 2
741
- assert db.query(tables.DjmdSongPlaylist).filter_by(ID=sid1).count() == 1
742
- assert db.query(tables.DjmdSongPlaylist).filter_by(ID=sid2).count() == 0
743
- assert db.query(tables.DjmdSongPlaylist).filter_by(ID=sid3).count() == 0
744
- assert db.query(tables.DjmdSongPlaylist).filter_by(ID=sid4).count() == 1
745
- # Check if USN is correct (+1 for deleting with contents)
746
- assert db.get_local_usn() == usn_old + 1
747
-
748
- assert _check_playlist_xml(db)
749
- assert _check_playlist_xml_delete(db)
750
-
751
-
752
- def test_delete_playlist_folder_non_empty(db):
753
- # Create playlist structure
754
- folder = db.create_playlist_folder("folder")
755
- pl1 = db.create_playlist("sub playlist 1", parent=folder.ID)
756
- folder2 = db.create_playlist_folder("sub playlist folder", parent=folder.ID)
757
- pl2 = db.create_playlist("sub sub playlist", parent=folder2.ID)
758
- pl3 = db.create_playlist("sub playlist 3", parent=folder.ID)
759
- # Add songs to playlists
760
- sid1 = db.add_to_playlist(pl1, CID1).ID
761
- sid2 = db.add_to_playlist(pl2, CID2).ID
762
- sid3 = db.add_to_playlist(pl2, CID3).ID
763
- sid4 = db.add_to_playlist(pl3, CID4).ID
764
- db.commit()
765
- usn_old = db.get_local_usn()
766
-
767
- assert db.query(tables.DjmdSongPlaylist).count() == 4
768
-
769
- # Delete playlist
770
- pl = db.get_playlist(Name="sub playlist folder").one()
771
- pid = pl.ID
772
-
773
- pid2 = db.get_playlist(Name="sub sub playlist").one().ID
774
-
775
- db.delete_playlist(pl)
776
- db.commit()
777
-
778
- # Check if playlists were deleted
779
- pl = db.get_playlist(ID=pid)
780
- assert pl is None
781
- pl = db.get_playlist(ID=pid2)
782
- assert pl is None
783
- # Check if songs in playlist were deleted
784
- assert db.query(tables.DjmdSongPlaylist).count() == 2
785
- assert db.query(tables.DjmdSongPlaylist).filter_by(ID=sid1).count() == 1
786
- assert db.query(tables.DjmdSongPlaylist).filter_by(ID=sid2).count() == 0
787
- assert db.query(tables.DjmdSongPlaylist).filter_by(ID=sid3).count() == 0
788
- assert db.query(tables.DjmdSongPlaylist).filter_by(ID=sid4).count() == 1
789
-
790
- # Check if USN is correct (+1 for deleting with Seq update, +1 for children)
791
- assert db.get_local_usn() == usn_old + 2
792
-
793
- assert _check_playlist_xml(db)
794
- assert _check_playlist_xml_delete(db)
795
-
796
-
797
- def test_delete_playlist_folder_chained(db):
798
- # Create playlist structure
799
- folder = db.create_playlist_folder("folder")
800
- subfolder1 = db.create_playlist_folder("subfolder", parent=folder.ID)
801
- subfolder2 = db.create_playlist_folder("subsubfolder", parent=subfolder1.ID)
802
- subfolder3 = db.create_playlist_folder("subsubsubfolder", parent=subfolder2.ID)
803
- pl1 = db.create_playlist("sub playlist 1", parent=subfolder2.ID)
804
- pl2 = db.create_playlist("sub playlist 2", parent=subfolder3.ID)
805
-
806
- pid1 = folder.ID
807
- pid2 = subfolder1.ID
808
- pid3 = subfolder2.ID
809
- pid4 = subfolder3.ID
810
- pid5 = pl1.ID
811
- pid6 = pl2.ID
812
-
813
- # Add songs to playlists
814
- sid1 = db.add_to_playlist(pl1, CID1).ID
815
- sid2 = db.add_to_playlist(pl1, CID2).ID
816
- sid3 = db.add_to_playlist(pl2, CID3).ID
817
- sid4 = db.add_to_playlist(pl2, CID4).ID
818
-
819
- db.commit()
820
- usn_old = db.get_local_usn()
821
-
822
- db.delete_playlist(folder)
823
- db.commit()
824
-
825
- # Check if all playlists and songs were deleted
826
- assert db.get_playlist(ID=pid1) is None
827
- assert db.get_playlist(ID=pid2) is None
828
- assert db.get_playlist(ID=pid3) is None
829
- assert db.get_playlist(ID=pid5) is None
830
- assert db.get_playlist(ID=pid4) is None
831
- assert db.get_playlist(ID=pid6) is None
832
- assert db.query(tables.DjmdSongPlaylist).filter_by(ID=sid1).count() == 0
833
- assert db.query(tables.DjmdSongPlaylist).filter_by(ID=sid2).count() == 0
834
- assert db.query(tables.DjmdSongPlaylist).filter_by(ID=sid3).count() == 0
835
- assert db.query(tables.DjmdSongPlaylist).filter_by(ID=sid4).count() == 0
836
-
837
- # Check all the corresponding xml entries were deleted
838
- assert db.playlist_xml.get(pid1) is None
839
- assert db.playlist_xml.get(pid2) is None
840
- assert db.playlist_xml.get(pid3) is None
841
- assert db.playlist_xml.get(pid4) is None
842
- assert db.playlist_xml.get(pid5) is None
843
- assert db.playlist_xml.get(pid6) is None
844
-
845
- # Check if USN is correct (+1 for deleting with Seq update, +1 for children)
846
- assert db.get_local_usn() == usn_old + 2
847
-
848
- assert _check_playlist_xml(db)
849
- assert _check_playlist_xml_delete(db)
850
-
851
-
852
- def test_move_playlist_seq(db):
853
- # Create playlist structure
854
- folder = db.create_playlist_folder("folder")
855
- f1 = db.create_playlist_folder("f 1", parent=folder)
856
- _ = db.create_playlist_folder("f 2", parent=folder)
857
- db.create_playlist("pl 1", parent=folder)
858
- db.create_playlist("pl 2", parent=folder)
859
- db.create_playlist("pl 3", parent=folder)
860
- db.create_playlist("pl 4", parent=folder)
861
- db.create_playlist("sub pl 1", parent=f1)
862
- db.create_playlist("sub pl 2", parent=f1)
863
- db.create_playlist("sub pl 3", parent=f1)
864
- db.create_playlist("sub pl 4", parent=f1)
865
- db.commit()
866
-
867
- playlists = db.get_playlist(ParentID=folder.ID).order_by(tables.DjmdPlaylist.Seq)
868
- expected = ["f 1", "f 2", "pl 1", "pl 2", "pl 3", "pl 4"]
869
- assert [p.Name for p in playlists] == expected
870
- assert [pl.Seq for pl in playlists] == [1, 2, 3, 4, 5, 6]
871
-
872
- playlists = db.get_playlist(ParentID=f1.ID).order_by(tables.DjmdPlaylist.Seq)
873
- expected = ["sub pl 1", "sub pl 2", "sub pl 3", "sub pl 4"]
874
- assert [p.Name for p in playlists] == expected
875
- assert [pl.Seq for pl in playlists] == [1, 2, 3, 4]
876
-
877
- usn_old = db.get_local_usn()
878
- # Move playlist 1 to position 5
879
- pl = db.get_playlist(Name="pl 1").one()
880
- mtime_old = pl.updated_at
881
- db.move_playlist(pl, seq=5)
882
- db.commit()
883
-
884
- playlists = db.get_playlist(ParentID=folder.ID).order_by(tables.DjmdPlaylist.Seq)
885
- expected = ["f 1", "f 2", "pl 2", "pl 3", "pl 1", "pl 4"]
886
- assert [p.Name for p in playlists] == expected
887
- assert [pl.Seq for pl in playlists] == [1, 2, 3, 4, 5, 6]
888
- # Check that the usn and update time was updated correctly
889
- # First the moved playlist USN is set, then the other updated playlists
890
- # in the seq order
891
- pl1 = db.get_playlist(Name="pl 1").one()
892
- pl2 = db.get_playlist(Name="pl 2").one()
893
- pl3 = db.get_playlist(Name="pl 3").one()
894
- assert db.get_local_usn() == usn_old + 3
895
- assert pl1.rb_local_usn == usn_old + 1
896
- assert pl2.rb_local_usn == usn_old + 2
897
- assert pl3.rb_local_usn == usn_old + 3
898
- assert pl1.updated_at > mtime_old
899
- assert pl2.updated_at > mtime_old
900
- assert pl3.updated_at > mtime_old
901
-
902
- usn_old = db.get_local_usn()
903
- # Move playlist 3 to position 2
904
- pl = db.get_playlist(Name="pl 3").one()
905
- mtime_old = pl.updated_at
906
- db.move_playlist(pl, seq=2)
907
- db.commit()
908
-
909
- playlists = db.get_playlist(ParentID=folder.ID).order_by(tables.DjmdPlaylist.Seq)
910
- expected = ["f 1", "pl 3", "f 2", "pl 2", "pl 1", "pl 4"]
911
- assert [p.Name for p in playlists] == expected
912
- assert [pl.Seq for pl in playlists] == [1, 2, 3, 4, 5, 6]
913
- # Check that the usn and update time was updated correctly
914
- # First the moved playlist USN is set, then the other updated playlists
915
- # in the seq order
916
- pl2 = db.get_playlist(Name="pl 2").one()
917
- pl3 = db.get_playlist(Name="pl 3").one()
918
- f2 = db.get_playlist(Name="f 2").one()
919
- assert db.get_local_usn() == usn_old + 3
920
- assert pl3.rb_local_usn == usn_old + 1
921
- assert f2.rb_local_usn == usn_old + 2
922
- assert pl2.rb_local_usn == usn_old + 3
923
- assert pl2.updated_at > mtime_old
924
- assert pl3.updated_at > mtime_old
925
- assert f2.updated_at > mtime_old
926
-
927
- assert _check_playlist_xml(db)
928
-
929
-
930
- def test_move_playlist_parent(db):
931
- # Create playlist structure
932
- folder = db.create_playlist_folder("folder")
933
- f1 = db.create_playlist_folder("f 1", parent=folder)
934
- _ = db.create_playlist_folder("f 2", parent=folder)
935
- db.create_playlist("pl 1", parent=folder)
936
- db.create_playlist("pl 2", parent=folder)
937
- db.create_playlist("pl 3", parent=folder)
938
- db.create_playlist("pl 4", parent=folder)
939
- db.create_playlist("sub pl 1", parent=f1)
940
- db.create_playlist("sub pl 2", parent=f1)
941
- db.create_playlist("sub pl 3", parent=f1)
942
- db.create_playlist("sub pl 4", parent=f1)
943
- db.commit()
944
-
945
- playlists = db.get_playlist(ParentID=folder.ID).order_by(tables.DjmdPlaylist.Seq)
946
- expected = ["f 1", "f 2", "pl 1", "pl 2", "pl 3", "pl 4"]
947
- assert [p.Name for p in playlists] == expected
948
- assert [pl.Seq for pl in playlists] == [1, 2, 3, 4, 5, 6]
949
-
950
- playlists = db.get_playlist(ParentID=f1.ID).order_by(tables.DjmdPlaylist.Seq)
951
- expected = ["sub pl 1", "sub pl 2", "sub pl 3", "sub pl 4"]
952
- assert [p.Name for p in playlists] == expected
953
- assert [pl.Seq for pl in playlists] == [1, 2, 3, 4]
954
-
955
- # Move playlist 1 to sub playlist (at the end)
956
- old_usn = db.get_local_usn()
957
- pl = db.get_playlist(Name="pl 1").one()
958
- old_mtime = pl.updated_at
959
- db.move_playlist(pl, parent=f1)
960
- db.commit()
961
-
962
- playlists = db.get_playlist(ParentID=folder.ID).order_by(tables.DjmdPlaylist.Seq)
963
- expected = ["f 1", "f 2", "pl 2", "pl 3", "pl 4"]
964
- assert [p.Name for p in playlists] == expected
965
- assert [pl.Seq for pl in playlists] == [1, 2, 3, 4, 5]
966
- playlists = db.get_playlist(ParentID=f1.ID).order_by(tables.DjmdPlaylist.Seq)
967
- expected = ["sub pl 1", "sub pl 2", "sub pl 3", "sub pl 4", "pl 1"]
968
- assert [p.Name for p in playlists] == expected
969
- assert [pl.Seq for pl in playlists] == [1, 2, 3, 4, 5]
970
-
971
- # Check that the usn and update time was updated correctly
972
- pl = db.get_playlist(Name="pl 1").one()
973
- assert db.get_local_usn() == old_usn + 1
974
- assert pl.rb_local_usn == old_usn + 1
975
- assert pl.updated_at > old_mtime
976
-
977
- # Move playlist 2 to sub playlist
978
- old_usn = db.get_local_usn()
979
- pl = db.get_playlist(Name="pl 2").one()
980
- old_mtime = pl.updated_at
981
- db.move_playlist(pl, seq=2, parent=f1)
982
- db.commit()
983
-
984
- playlists = db.get_playlist(ParentID=folder.ID).order_by(tables.DjmdPlaylist.Seq)
985
- expected = ["f 1", "f 2", "pl 3", "pl 4"]
986
- assert [p.Name for p in playlists] == expected
987
- assert [pl.Seq for pl in playlists] == [1, 2, 3, 4]
988
- playlists = db.get_playlist(ParentID=f1.ID).order_by(tables.DjmdPlaylist.Seq)
989
- expected = ["sub pl 1", "pl 2", "sub pl 2", "sub pl 3", "sub pl 4", "pl 1"]
990
- assert [p.Name for p in playlists] == expected
991
- assert [pl.Seq for pl in playlists] == [1, 2, 3, 4, 5, 6]
992
- # Check that the usn and update time was updated correctly
993
- _ = db.get_playlist(Name="sub pl 1").one()
994
- subpl2 = db.get_playlist(Name="sub pl 2").one()
995
- subpl3 = db.get_playlist(Name="sub pl 3").one()
996
- subpl4 = db.get_playlist(Name="sub pl 4").one()
997
- pl1 = db.get_playlist(Name="pl 1").one()
998
- pl = db.get_playlist(Name="pl 2").one()
999
- assert db.get_local_usn() == old_usn + 5
1000
- assert pl.rb_local_usn == old_usn + 1
1001
- assert pl.updated_at > old_mtime
1002
- assert subpl2.rb_local_usn == old_usn + 2
1003
- assert subpl3.rb_local_usn == old_usn + 3
1004
- assert subpl4.rb_local_usn == old_usn + 4
1005
- assert pl1.rb_local_usn == old_usn + 5
1006
-
1007
- assert _check_playlist_xml(db)
1008
-
1009
-
1010
- def test_rename_playlist(db):
1011
- # Create playlist structure
1012
- folder = db.create_playlist_folder("folder")
1013
- db.create_playlist("pl 1", parent=folder)
1014
- db.create_playlist("pl 2", parent=folder)
1015
- db.commit()
1016
-
1017
- pl = db.get_playlist(Name="pl 1").one()
1018
- pid = pl.ID
1019
- mtime_old = pl.updated_at
1020
- usn_old = db.get_local_usn()
1021
-
1022
- # Rename playlist
1023
- db.rename_playlist(pl, "pl 1 new")
1024
- db.commit()
1025
-
1026
- pl = db.get_playlist(ID=pid)
1027
- assert pl.Name == "pl 1 new"
1028
- assert pl.updated_at > mtime_old
1029
- assert db.get_local_usn() == usn_old + 1
1030
- assert pl.rb_local_usn == usn_old + 1
1031
-
1032
- assert _check_playlist_xml(db)
1033
-
1034
-
1035
- def test_get_playlist_contents(db):
1036
- # Create playlist and add content
1037
- pl = db.create_playlist("Test playlist")
1038
- db.add_to_playlist(pl, CID1)
1039
- db.add_to_playlist(pl, CID2)
1040
- db.commit()
1041
-
1042
- # Get playlist contents
1043
- contents = db.get_playlist_contents(pl).all()
1044
- assert len(contents) == 2
1045
- assert {c.ID for c in contents} == {str(CID1), str(CID2)}
1046
-
1047
-
1048
- def test_get_playlist_contents_smart(db):
1049
- # Singe condition
1050
- smart = SmartList(LogicalOperator.ALL)
1051
- smart.add_condition(Property.ARTIST, Operator.EQUAL, "Loopmasters")
1052
- pl = db.create_smart_playlist("Smart playlist", smart)
1053
- db.commit()
1054
- contents = db.get_playlist_contents(pl).all()
1055
- assert len(contents) == 2
1056
- assert {c.ID for c in contents} == {str(CID1), str(CID2)}
1057
-
1058
- # All conditions
1059
- smart = SmartList(LogicalOperator.ALL)
1060
- smart.add_condition(Property.ARTIST, Operator.EQUAL, "Loopmasters")
1061
- smart.add_condition(Property.NAME, Operator.EQUAL, "Demo Track 1")
1062
- pl = db.create_smart_playlist("Smart playlist", smart)
1063
- db.commit()
1064
- contents = db.get_playlist_contents(pl).all()
1065
- assert len(contents) == 1
1066
- assert {c.ID for c in contents} == {str(CID1)}
1067
-
1068
- # Any conditions
1069
- smart = SmartList(LogicalOperator.ANY)
1070
- smart.add_condition(Property.ARTIST, Operator.EQUAL, "Loopmasters")
1071
- smart.add_condition(Property.NAME, Operator.EQUAL, "HORN")
1072
- pl = db.create_smart_playlist("Smart playlist", smart)
1073
- db.commit()
1074
- contents = db.get_playlist_contents(pl).all()
1075
- assert len(contents) == 3
1076
- assert {c.ID for c in contents} == {str(CID1), str(CID2), str(CID3)}
1077
-
1078
-
1079
- def test_add_album(db):
1080
- old_usn = db.get_local_usn()
1081
- name = "test"
1082
- db.add_album(name)
1083
- db.commit()
1084
-
1085
- # Check that album was created and USN is incremented
1086
- instance = db.get_album(Name=name).one()
1087
- assert instance.Name == name
1088
- assert instance.rb_local_usn == old_usn + 1
1089
- assert db.get_local_usn() == old_usn + 1
1090
-
1091
- # Fail if album with same name is added
1092
- with pytest.raises(ValueError):
1093
- db.add_album(name)
1094
-
1095
- # Add album with album artist by artist
1096
- artist = db.get_artist().first()
1097
- album = db.add_album("album 2", artist=artist)
1098
- assert album.AlbumArtistID == artist.ID
1099
-
1100
- # Add album with album artist by ID
1101
- artist = db.get_artist().first()
1102
- album = db.add_album("album 3", artist=artist.ID)
1103
- assert album.AlbumArtistID == artist.ID
1104
-
1105
-
1106
- def test_add_artist(db):
1107
- old_usn = db.get_local_usn()
1108
- name = "test"
1109
- db.add_artist(name)
1110
- db.commit()
1111
-
1112
- # Check that album was created and USN is incremented
1113
- instance = db.get_artist(Name=name).one()
1114
- assert instance.Name == name
1115
- assert instance.rb_local_usn == old_usn + 1
1116
- assert db.get_local_usn() == old_usn + 1
1117
-
1118
- # Fail if album with same name is added
1119
- with pytest.raises(ValueError):
1120
- db.add_artist(name)
1121
-
1122
-
1123
- def test_add_genre(db):
1124
- old_usn = db.get_local_usn()
1125
- name = "test"
1126
- db.add_genre(name)
1127
- db.commit()
1128
-
1129
- # Check that album was created and USN is incremented
1130
- instance = db.get_genre(Name=name).one()
1131
- assert instance.Name == name
1132
- assert instance.rb_local_usn == old_usn + 1
1133
- assert db.get_local_usn() == old_usn + 1
1134
-
1135
- # Fail if album with same name is added
1136
- with pytest.raises(ValueError):
1137
- db.add_genre(name)
1138
-
1139
-
1140
- def test_add_label(db):
1141
- old_usn = db.get_local_usn()
1142
- name = "test"
1143
- db.add_label(name)
1144
- db.commit()
1145
-
1146
- # Check that album was created and USN is incremented
1147
- instance = db.get_label(Name=name).one()
1148
- assert instance.Name == name
1149
- assert instance.rb_local_usn == old_usn + 1
1150
- assert db.get_local_usn() == old_usn + 1
1151
-
1152
- # Fail if album with same name is added
1153
- with pytest.raises(ValueError):
1154
- db.add_label(name)
1155
-
1156
-
1157
- def test_get_anlz_paths():
1158
- content = DB.get_content().first()
1159
-
1160
- anlz_dir = str(DB.get_anlz_dir(content)).replace("\\", "/")
1161
- expected = r"share/PIONEER/USBANLZ/735/e8b81-e69b-41ad-80f8-9c0d7613b96d"
1162
- assert anlz_dir.endswith(expected)
1163
-
1164
-
1165
- def test_to_json():
1166
- # Check if saving to json works
1167
-
1168
- tmp = tempfile.NamedTemporaryFile(delete=False)
1169
- try:
1170
- DB.to_json(tmp.name)
1171
- finally:
1172
- tmp.close()
1173
- os.remove(tmp.name)
1174
-
1175
-
1176
- def test_copy_unlocked():
1177
- db = Rekordbox6Database(UNLOCKED, unlock=False)
1178
- db.copy_unlocked(UNLOCKED_OUT)
1179
-
1180
- db2 = Rekordbox6Database(UNLOCKED_OUT, unlock=False)
1181
- # Check everything got copied
1182
- for name in tables.TABLES:
1183
- table = getattr(tables, name)
1184
- for row in db.query(table):
1185
- data = row.to_dict()
1186
- if name == "AgentRegistry":
1187
- query = db2.query(table).filter_by(registry_id=row.registry_id)
1188
- elif name == "DjmdProperty":
1189
- query = db2.query(table).filter_by(DBID=row.DBID)
1190
- else:
1191
- query = db2.query(table).filter_by(ID=row.ID)
1192
- data2 = query.one().to_dict()
1193
- assert data == data2