mirror of
https://github.com/spl0k/supysonic.git
synced 2024-12-22 08:56:17 +00:00
Fix Folder ID bugs, add initial DB migration work
This commit is contained in:
parent
c3fd94343f
commit
99ce42c9ff
@ -91,6 +91,16 @@ def get_entity(cls, param="id"):
|
||||
return entity
|
||||
|
||||
|
||||
def get_entity_id(cls, eid):
|
||||
"""Return the entity ID as its proper type."""
|
||||
if cls == Folder:
|
||||
try:
|
||||
return int(eid)
|
||||
except ValueError:
|
||||
raise ValueError("Invalid Folder ID: %s", eid)
|
||||
return uuid.UUID(eid)
|
||||
|
||||
|
||||
from .errors import *
|
||||
|
||||
from .system import *
|
||||
|
@ -7,8 +7,6 @@
|
||||
#
|
||||
# Distributed under terms of the GNU AGPLv3 license.
|
||||
|
||||
import uuid
|
||||
|
||||
from datetime import timedelta
|
||||
from flask import request
|
||||
from pony.orm import select, desc, avg, max, min, count
|
||||
@ -42,7 +40,12 @@ def rand_songs():
|
||||
size = int(size) if size else 10
|
||||
fromYear = int(fromYear) if fromYear else None
|
||||
toYear = int(toYear) if toYear else None
|
||||
fid = uuid.UUID(musicFolderId) if musicFolderId else None
|
||||
fid = None
|
||||
if musicFolderId:
|
||||
try:
|
||||
fid = int(musicFolderId)
|
||||
except ValueError:
|
||||
raise ValueError("Invalid folder ID")
|
||||
|
||||
query = Track.select()
|
||||
if fromYear:
|
||||
|
@ -21,7 +21,7 @@ from ..db import RatingTrack, RatingFolder
|
||||
from ..lastfm import LastFm
|
||||
from ..py23 import dict
|
||||
|
||||
from . import api, get_entity
|
||||
from . import api, get_entity, get_entity_id
|
||||
from .exceptions import AggregateException, GenericError, MissingParameter, NotFound
|
||||
|
||||
|
||||
@ -32,7 +32,7 @@ def star_single(cls, eid):
|
||||
:param eid: id of the entity to star
|
||||
"""
|
||||
|
||||
uid = uuid.UUID(eid)
|
||||
uid = get_entity_id(cls, eid)
|
||||
e = cls[uid]
|
||||
|
||||
starred_cls = getattr(sys.modules[__name__], "Starred" + cls.__name__)
|
||||
@ -52,7 +52,7 @@ def unstar_single(cls, eid):
|
||||
:param eid: id of the entity to unstar
|
||||
"""
|
||||
|
||||
uid = uuid.UUID(eid)
|
||||
uid = get_entity_id(cls, eid)
|
||||
starred_cls = getattr(sys.modules[__name__], "Starred" + cls.__name__)
|
||||
delete(
|
||||
s for s in starred_cls if s.user.id == request.user.id and s.starred.id == uid
|
||||
@ -115,7 +115,9 @@ def rate():
|
||||
id = request.values["id"]
|
||||
rating = request.values["rating"]
|
||||
|
||||
uid = uuid.UUID(id)
|
||||
tid = get_entity_id(Track, id)
|
||||
fid = get_entity_id(Folder, id)
|
||||
uid = None
|
||||
rating = int(rating)
|
||||
|
||||
if not 0 <= rating <= 5:
|
||||
@ -123,21 +125,23 @@ def rate():
|
||||
|
||||
if rating == 0:
|
||||
delete(
|
||||
r for r in RatingTrack if r.user.id == request.user.id and r.rated.id == uid
|
||||
r for r in RatingTrack if r.user.id == request.user.id and r.rated.id == tid
|
||||
)
|
||||
delete(
|
||||
r
|
||||
for r in RatingFolder
|
||||
if r.user.id == request.user.id and r.rated.id == uid
|
||||
if r.user.id == request.user.id and r.rated.id == fid
|
||||
)
|
||||
else:
|
||||
try:
|
||||
rated = Track[uid]
|
||||
rated = Track[tid]
|
||||
rating_cls = RatingTrack
|
||||
uid = tid
|
||||
except ObjectNotFound:
|
||||
try:
|
||||
rated = Folder[uid]
|
||||
rated = Folder[fid]
|
||||
rating_cls = RatingFolder
|
||||
uid = fid
|
||||
except ObjectNotFound:
|
||||
raise NotFound("Track or Folder")
|
||||
|
||||
|
@ -16,7 +16,7 @@ from pony.orm import ObjectNotFound, select
|
||||
from ..db import Folder, Artist, Album, Track
|
||||
from ..py23 import dict
|
||||
|
||||
from . import api, get_entity
|
||||
from . import api, get_entity, get_entity_id
|
||||
|
||||
|
||||
@api.route("/getMusicFolders.view", methods=["GET", "POST"])
|
||||
@ -42,10 +42,7 @@ def list_indexes():
|
||||
if musicFolderId is None:
|
||||
folders = Folder.select(lambda f: f.root)[:]
|
||||
else:
|
||||
try:
|
||||
mfid = int(musicFolderId)
|
||||
except ValueError:
|
||||
raise ValueError("Invalid folder ID")
|
||||
mfid = get_entity_id(Folder, musicFolderId)
|
||||
folder = Folder[mfid]
|
||||
if not folder.root:
|
||||
raise ObjectNotFound(Folder, mfid)
|
||||
|
@ -187,7 +187,8 @@ def stream_media():
|
||||
@api.route("/download.view", methods=["GET", "POST"])
|
||||
def download_media():
|
||||
id = request.values["id"]
|
||||
uid = uuid.UUID(id)
|
||||
uid = get_entity_id(Track, id)
|
||||
fid = get_entity_id(Folder, id)
|
||||
|
||||
try: # Track -> direct download
|
||||
rv = Track[uid]
|
||||
@ -196,7 +197,7 @@ def download_media():
|
||||
pass
|
||||
|
||||
try: # Folder -> stream zipped tracks, non recursive
|
||||
rv = Folder[uid]
|
||||
rv = Folder[fid]
|
||||
except ObjectNotFound:
|
||||
try: # Album -> stream zipped tracks
|
||||
rv = Album[uid]
|
||||
|
70
supysonic/schema/migration/mysql/20190915.sql
Normal file
70
supysonic/schema/migration/mysql/20190915.sql
Normal file
@ -0,0 +1,70 @@
|
||||
START TRANSACTION;
|
||||
|
||||
CREATE TEMPORARY TABLE IF NOT EXISTS folder_id_to_int (
|
||||
id INTEGER PRIMARY KEY AUTO_INCREMENT,
|
||||
uuid BINARY(16) NOT NULL
|
||||
);
|
||||
|
||||
INSERT INTO folder_id_to_int(uuid) SELECT id FROM folder;
|
||||
|
||||
DROP INDEX index_folder_parent_id_fk ON folder;
|
||||
DROP INDEX index_track_folder_id_fk ON track;
|
||||
DROP INDEX index_track_root_folder_id_fk ON track;
|
||||
DROP INDEX index_starred_folder_starred_id_fk ON starred_folder;
|
||||
DROP INDEX index_rating_folder_rated_id_fk ON rating_folder;
|
||||
|
||||
|
||||
ALTER TABLE folder
|
||||
ADD int_id INTEGER AFTER id,
|
||||
ADD int_parent_id INTEGER REFERENCES folder AFTER parent_id;
|
||||
UPDATE folder SET int_id = (SELECT id FROM folder_id_to_int WHERE uuid == folder.id);
|
||||
UPDATE folder SET int_parent_id = (SELECT id FROM folder_id_to_int WHERE uuid == folder.parent_id);
|
||||
ALTER TABLE folder
|
||||
DROP PRIMARY KEY,
|
||||
DROP COLUMN id,
|
||||
DROP COLUMN parent_id,
|
||||
RENAME COLUMN int_id TO id,
|
||||
RENAME COLUMN int_parent_id TO parent_id,
|
||||
MODIFY id INTEGER AUTO_INCREMENT,
|
||||
ADD PRIMARY KEY (id);
|
||||
|
||||
|
||||
ALTER TABLE track
|
||||
ADD int_root_folder_id INTEGER NOT NULL REFERENCES folder AFTER root_folder_id,
|
||||
ADD int_folder_id INTEGER NOT NULL REFERENCES folder AFTER folder_id;
|
||||
UPDATE track SET int_root_folder_id = (SELECT id FROM folder_id_to_int WHERE uuid == track.root_folder_id);
|
||||
UPDATE track SET int_folder_id = (SELECT id FROM folder_id_to_int WHERE uuid == track.folder_id);
|
||||
ALTER TABLE track
|
||||
DROP COLUMN root_folder_id,
|
||||
DROP COLUMN folder_id,
|
||||
RENAME COLUMN int_root_folder_id TO root_folder_id,
|
||||
RENAME COLUMN int_folder_id TO folder_id,
|
||||
|
||||
|
||||
ALTER TABLE starred_folder ADD int_starred_id INTEGER NOT NULL REFERENCES folder AFTER starred_id;
|
||||
UPDATE starred_folder SET int_starred_id = (SELECT id FROM folder_id_to_int WHERE uuid == starred_folder.starred_id);
|
||||
ALTER TABLE starred_folder
|
||||
DROP PRIMARY KEY,
|
||||
DROP COLUMN starred_id,
|
||||
RENAME COLUMN int_starred_id TO starred_id,
|
||||
ADD PRIMARY KEY (user_id, starred_id);
|
||||
|
||||
|
||||
ALTER TABLE rating_folder ADD int_rated_id INTEGER NOT NULL REFERENCES folder AFTER rated_id;
|
||||
UPDATE rating_folder SET int_rated_id = (SELECT id FROM folder_id_to_int WHERE uuid == rating_folder.rated_id);
|
||||
ALTER TABLE rating_folder
|
||||
DROP PRIMARY KEY,
|
||||
DROP COLUMN rated_id,
|
||||
RENAME COLUMN int_rated_id TO rated_id,
|
||||
ADD PRIMARY KEY (user_id, rated_id);
|
||||
|
||||
|
||||
CREATE INDEX IF NOT EXISTS index_folder_parent_id_fk ON folder(parent_id);
|
||||
CREATE INDEX IF NOT EXISTS index_track_folder_id_fk ON track(folder_id);
|
||||
CREATE INDEX IF NOT EXISTS index_track_root_folder_id_fk ON track(root_folder_id);
|
||||
CREATE INDEX IF NOT EXISTS index_starred_folder_starred_id_fk ON starred_folder(starred_id);
|
||||
CREATE INDEX IF NOT EXISTS index_rating_folder_rated_id_fk ON rating_folder(rated_id);
|
||||
|
||||
DROP TABLE folder_id_to_int;
|
||||
|
||||
COMMIT;
|
129
supysonic/schema/migration/sqlite/20190915.sql
Normal file
129
supysonic/schema/migration/sqlite/20190915.sql
Normal file
@ -0,0 +1,129 @@
|
||||
COMMIT;
|
||||
PRAGMA foreign_keys = OFF;
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
CREATE TEMPORARY TABLE IF NOT EXISTS folder_id_to_int (
|
||||
id INTEGER NOT NULL PRIMARY KEY,
|
||||
uuid CHAR(36) NOT NULL
|
||||
);
|
||||
|
||||
INSERT INTO folder_id_to_int(uuid) SELECT id FROM folder;
|
||||
|
||||
DROP INDEX index_folder_parent_id_fk;
|
||||
DROP INDEX index_folder_path;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS folder_new (
|
||||
id INTEGER NOT NULL PRIMARY KEY,
|
||||
root BOOLEAN NOT NULL,
|
||||
name VARCHAR(256) NOT NULL COLLATE NOCASE,
|
||||
path VARCHAR(4096) NOT NULL,
|
||||
path_hash BLOB NOT NULL,
|
||||
created DATETIME NOT NULL,
|
||||
cover_art VARCHAR(256),
|
||||
last_scan INTEGER NOT NULL,
|
||||
parent_id INTEGER REFERENCES folder
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS index_folder_parent_id_fk ON folder_new(parent_id);
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS index_folder_path ON folder_new(path_hash);
|
||||
|
||||
INSERT INTO folder_new(id, root, name, path, path_hash, created, cover_art, last_scan, parent_id)
|
||||
SELECT id_int.id, root, name, path, path_hash, created, cover_art, last_scan, parent_id_int.id
|
||||
FROM folder
|
||||
JOIN folder_id_to_int id_int ON folder.id == id_int.uuid
|
||||
JOIN folder_id_to_int parent_id_int ON folder.parent_id == parent_id_int.uuid;
|
||||
|
||||
DROP TABLE folder;
|
||||
ALTER TABLE folder_new RENAME TO folder;
|
||||
|
||||
|
||||
DROP INDEX index_track_album_id_fk;
|
||||
DROP INDEX index_track_artist_id_fk;
|
||||
DROP INDEX index_track_folder_id_fk;
|
||||
DROP INDEX index_track_root_folder_id_fk;
|
||||
DROP INDEX index_track_path;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS track_new (
|
||||
id CHAR(36) PRIMARY KEY,
|
||||
disc INTEGER NOT NULL,
|
||||
number INTEGER NOT NULL,
|
||||
title VARCHAR(256) NOT NULL COLLATE NOCASE,
|
||||
year INTEGER,
|
||||
genre VARCHAR(256),
|
||||
duration INTEGER NOT NULL,
|
||||
has_art BOOLEAN NOT NULL DEFAULT false,
|
||||
album_id CHAR(36) NOT NULL REFERENCES album,
|
||||
artist_id CHAR(36) NOT NULL REFERENCES artist,
|
||||
bitrate INTEGER NOT NULL,
|
||||
path VARCHAR(4096) NOT NULL,
|
||||
path_hash BLOB NOT NULL,
|
||||
created DATETIME NOT NULL,
|
||||
last_modification INTEGER NOT NULL,
|
||||
play_count INTEGER NOT NULL,
|
||||
last_play DATETIME,
|
||||
root_folder_id INTEGER NOT NULL REFERENCES folder,
|
||||
folder_id INTEGER NOT NULL REFERENCES folder
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS index_track_album_id_fk ON track_new(album_id);
|
||||
CREATE INDEX IF NOT EXISTS index_track_artist_id_fk ON track_new(artist_id);
|
||||
CREATE INDEX IF NOT EXISTS index_track_folder_id_fk ON track_new(folder_id);
|
||||
CREATE INDEX IF NOT EXISTS index_track_root_folder_id_fk ON track_new(root_folder_id);
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS index_track_path ON track_new(path_hash);
|
||||
|
||||
INSERT INTO track_new(id, disc, number, title, year, genre, duration, has_art, album_id, artist_id, bitrate, path, path_hash, created, last_modification, play_count, last_play, root_folder_id, folder_id)
|
||||
SELECT track.id, disc, number, title, year, genre, duration, has_art, album_id, artist_id, bitrate, path, path_hash, created, last_modification, play_count, last_play, root_id_int.id, folder_id_int.id
|
||||
FROM track
|
||||
JOIN folder_id_to_int root_id_int ON track.root_folder_id == root_id_int.uuid
|
||||
JOIN folder_id_to_int folder_id_int ON track.folder_id == folder_id_int.uuid;
|
||||
|
||||
DROP TABLE track;
|
||||
ALTER TABLE track_new RENAME TO track;
|
||||
|
||||
|
||||
DROP INDEX index_starred_folder_user_id_fk;
|
||||
DROP INDEX index_starred_folder_starred_id_fk;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS starred_folder_new (
|
||||
user_id CHAR(36) NOT NULL REFERENCES user,
|
||||
starred_id INTEGER NOT NULL REFERENCES folder,
|
||||
date DATETIME NOT NULL,
|
||||
PRIMARY KEY (user_id, starred_id)
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS index_starred_folder_user_id_fk ON starred_folder_new(user_id);
|
||||
CREATE INDEX IF NOT EXISTS index_starred_folder_starred_id_fk ON starred_folder_new(starred_id);
|
||||
|
||||
INSERT INTO starred_folder_new(user_id, starred_id, date)
|
||||
SELECT user_id, id_int.id, date
|
||||
FROM starred_folder
|
||||
JOIN folder_id_to_int id_int ON starred_folder_new.starred_id == id_int.uuid;
|
||||
|
||||
DROP TABLE starred_folder;
|
||||
ALTER TABLE starred_folder_new RENAME TO starred_folder;
|
||||
|
||||
|
||||
DROP INDEX index_rating_folder_user_id_fk;
|
||||
DROP INDEX index_rating_folder_rated_id_fk;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS rating_folder_new (
|
||||
user_id CHAR(36) NOT NULL REFERENCES user,
|
||||
rated_id INTEGER NOT NULL REFERENCES folder,
|
||||
rating INTEGER NOT NULL CHECK(rating BETWEEN 1 AND 5),
|
||||
PRIMARY KEY (user_id, rated_id)
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS index_rating_folder_user_id_fk ON rating_folder_new(user_id);
|
||||
CREATE INDEX IF NOT EXISTS index_rating_folder_rated_id_fk ON rating_folder_new(rated_id);
|
||||
|
||||
INSERT INTO rating_folder_new(user_id, rated_id, rating)
|
||||
SELECT user_id, id_int.id, rating
|
||||
FROM rating_folder
|
||||
JOIN folder_id_to_int id_int ON rating_folder.rated_id == id_int.uuid;
|
||||
|
||||
DROP TABLE rating_folder;
|
||||
ALTER TABLE rating_folder_new RENAME TO rating_folder;
|
||||
|
||||
|
||||
DROP TABLE folder_id_to_int;
|
||||
|
||||
COMMIT;
|
||||
VACUUM;
|
||||
PRAGMA foreign_keys = ON;
|
||||
BEGIN TRANSACTION;
|
@ -1,5 +1,5 @@
|
||||
CREATE TABLE IF NOT EXISTS folder (
|
||||
id BINARY(16) PRIMARY KEY,
|
||||
id INTEGER PRIMARY KEY AUTO_INCREMENT,
|
||||
root BOOLEAN NOT NULL,
|
||||
name VARCHAR(256) NOT NULL,
|
||||
path VARCHAR(4096) NOT NULL,
|
||||
@ -7,7 +7,7 @@ CREATE TABLE IF NOT EXISTS folder (
|
||||
created DATETIME NOT NULL,
|
||||
cover_art VARCHAR(256),
|
||||
last_scan INTEGER NOT NULL,
|
||||
parent_id BINARY(16) REFERENCES folder
|
||||
parent_id INTEGER REFERENCES folder
|
||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
CREATE INDEX IF NOT EXISTS index_folder_parent_id_fk ON folder(parent_id);
|
||||
|
||||
@ -41,8 +41,8 @@ CREATE TABLE IF NOT EXISTS track (
|
||||
last_modification INTEGER NOT NULL,
|
||||
play_count INTEGER NOT NULL,
|
||||
last_play DATETIME,
|
||||
root_folder_id BINARY(16) NOT NULL REFERENCES folder,
|
||||
folder_id BINARY(16) NOT NULL REFERENCES folder
|
||||
root_folder_id INTEGER NOT NULL REFERENCES folder,
|
||||
folder_id INTEGER NOT NULL REFERENCES folder
|
||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
CREATE INDEX IF NOT EXISTS index_track_album_id_fk ON track(album_id);
|
||||
CREATE INDEX IF NOT EXISTS index_track_artist_id_fk ON track(artist_id);
|
||||
@ -73,7 +73,7 @@ CREATE TABLE IF NOT EXISTS client_prefs (
|
||||
|
||||
CREATE TABLE IF NOT EXISTS starred_folder (
|
||||
user_id BINARY(16) NOT NULL REFERENCES user,
|
||||
starred_id BINARY(16) NOT NULL REFERENCES folder,
|
||||
starred_id INTEGER NOT NULL REFERENCES folder,
|
||||
date DATETIME NOT NULL,
|
||||
PRIMARY KEY (user_id, starred_id)
|
||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
@ -109,7 +109,7 @@ CREATE INDEX IF NOT EXISTS index_starred_track_starred_id_fk ON starred_track(st
|
||||
|
||||
CREATE TABLE IF NOT EXISTS rating_folder (
|
||||
user_id BINARY(16) NOT NULL REFERENCES user,
|
||||
rated_id BINARY(16) NOT NULL REFERENCES folder,
|
||||
rated_id INTEGER NOT NULL REFERENCES folder,
|
||||
rating INTEGER NOT NULL CHECK(rating BETWEEN 1 AND 5),
|
||||
PRIMARY KEY (user_id, rated_id)
|
||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
|
@ -1,5 +1,5 @@
|
||||
CREATE TABLE IF NOT EXISTS folder (
|
||||
id UUID PRIMARY KEY,
|
||||
id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
root BOOLEAN NOT NULL,
|
||||
name CITEXT NOT NULL,
|
||||
path VARCHAR(4096) NOT NULL,
|
||||
@ -7,7 +7,7 @@ CREATE TABLE IF NOT EXISTS folder (
|
||||
created TIMESTAMP NOT NULL,
|
||||
cover_art VARCHAR(256),
|
||||
last_scan INTEGER NOT NULL,
|
||||
parent_id UUID REFERENCES folder
|
||||
parent_id INTEGER REFERENCES folder
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS index_folder_parent_id_fk ON folder(parent_id);
|
||||
|
||||
@ -41,8 +41,8 @@ CREATE TABLE IF NOT EXISTS track (
|
||||
last_modification INTEGER NOT NULL,
|
||||
play_count INTEGER NOT NULL,
|
||||
last_play TIMESTAMP,
|
||||
root_folder_id UUID NOT NULL REFERENCES folder,
|
||||
folder_id UUID NOT NULL REFERENCES folder
|
||||
root_folder_id INTEGER NOT NULL REFERENCES folder,
|
||||
folder_id INTEGER NOT NULL REFERENCES folder
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS index_track_album_id_fk ON track(album_id);
|
||||
CREATE INDEX IF NOT EXISTS index_track_artist_id_fk ON track(artist_id);
|
||||
@ -73,7 +73,7 @@ CREATE TABLE IF NOT EXISTS client_prefs (
|
||||
|
||||
CREATE TABLE IF NOT EXISTS starred_folder (
|
||||
user_id UUID NOT NULL REFERENCES "user",
|
||||
starred_id UUID NOT NULL REFERENCES folder,
|
||||
starred_id INTEGER NOT NULL REFERENCES folder,
|
||||
date TIMESTAMP NOT NULL,
|
||||
PRIMARY KEY (user_id, starred_id)
|
||||
);
|
||||
@ -109,7 +109,7 @@ CREATE INDEX IF NOT EXISTS index_starred_track_starred_id_fk ON starred_track(st
|
||||
|
||||
CREATE TABLE IF NOT EXISTS rating_folder (
|
||||
user_id UUID NOT NULL REFERENCES "user",
|
||||
rated_id UUID NOT NULL REFERENCES folder,
|
||||
rated_id INTEGER NOT NULL REFERENCES folder,
|
||||
rating INTEGER NOT NULL CHECK(rating BETWEEN 1 AND 5),
|
||||
PRIMARY KEY (user_id, rated_id)
|
||||
);
|
||||
|
@ -6,12 +6,13 @@
|
||||
# Copyright (C) 2019 Alban 'spl0k' Féron
|
||||
#
|
||||
# Distributed under terms of the GNU AGPLv3 license.
|
||||
import uuid
|
||||
|
||||
from base64 import b64encode, b64decode
|
||||
from os import urandom
|
||||
from pony.orm import db_session, commit, ObjectNotFound
|
||||
|
||||
from supysonic.db import Meta
|
||||
from supysonic.db import Folder, Meta
|
||||
|
||||
|
||||
@db_session
|
||||
|
Loading…
Reference in New Issue
Block a user