1
0
mirror of https://github.com/spl0k/supysonic.git synced 2024-12-22 17:06:17 +00:00

Adapting FolderManager and the folder part of the CLI

This commit is contained in:
spl0k 2014-03-09 19:12:11 +01:00
parent cf40286838
commit 74246a7659
5 changed files with 77 additions and 56 deletions

41
cli.py
View File

@ -22,6 +22,11 @@
import sys, cmd, argparse, getpass, time import sys, cmd, argparse, getpass, time
import config import config
from db import get_store, Folder
from managers.folder import FolderManager
from managers.user import UserManager
from scanner import Scanner
class CLIParser(argparse.ArgumentParser): class CLIParser(argparse.ArgumentParser):
def error(self, message): def error(self, message):
self.print_usage(sys.stderr) self.print_usage(sys.stderr)
@ -53,7 +58,7 @@ class CLI(cmd.Cmd):
return method return method
def __init__(self): def __init__(self, store):
cmd.Cmd.__init__(self) cmd.Cmd.__init__(self)
# Generate do_* and help_* methods # Generate do_* and help_* methods
@ -69,6 +74,8 @@ class CLI(cmd.Cmd):
for action, subparser in getattr(self.__class__, command + '_subparsers').choices.iteritems(): for action, subparser in getattr(self.__class__, command + '_subparsers').choices.iteritems():
setattr(self, 'help_{} {}'.format(command, action), subparser.print_help) setattr(self, 'help_{} {}'.format(command, action), subparser.print_help)
self.__store = store
def do_EOF(self, line): def do_EOF(self, line):
return True return True
@ -105,17 +112,17 @@ class CLI(cmd.Cmd):
def folder_list(self): def folder_list(self):
print 'Name\t\tPath\n----\t\t----' print 'Name\t\tPath\n----\t\t----'
print '\n'.join('{0: <16}{1}'.format(f.name, f.path) for f in db.Folder.query.filter(db.Folder.root == True)) print '\n'.join('{0: <16}{1}'.format(f.name, f.path) for f in self.__store.find(Folder, Folder.root == True))
def folder_add(self, name, path): def folder_add(self, name, path):
ret = FolderManager.add(name, path) ret = FolderManager.add(self.__store, name, path)
if ret != FolderManager.SUCCESS: if ret != FolderManager.SUCCESS:
print FolderManager.error_str(ret) print FolderManager.error_str(ret)
else: else:
print "Folder '{}' added".format(name) print "Folder '{}' added".format(name)
def folder_delete(self, name): def folder_delete(self, name):
ret = FolderManager.delete_by_name(name) ret = FolderManager.delete_by_name(self.__store, name)
if ret != FolderManager.SUCCESS: if ret != FolderManager.SUCCESS:
print FolderManager.error_str(ret) print FolderManager.error_str(ret)
else: else:
@ -134,19 +141,19 @@ class CLI(cmd.Cmd):
print "Scanning '{0}': {1}% ({2}/{3})".format(self.__name, (scanned * 100) / total, scanned, total) print "Scanning '{0}': {1}% ({2}/{3})".format(self.__name, (scanned * 100) / total, scanned, total)
self.__last_display = time.time() self.__last_display = time.time()
s = Scanner(db.session) s = Scanner(self.__store)
if folders: if folders:
folders = map(lambda n: db.Folder.query.filter(db.Folder.name == n and db.Folder.root == True).first() or n, folders) folders = map(lambda n: self.__store.find(Folder, Folder.name == n, Folder.root == True).one() or n, folders)
if any(map(lambda f: isinstance(f, basestring), folders)): if any(map(lambda f: isinstance(f, basestring), folders)):
print "No such folder(s): " + ' '.join(f for f in folders if isinstance(f, basestring)) print "No such folder(s): " + ' '.join(f for f in folders if isinstance(f, basestring))
for folder in filter(lambda f: isinstance(f, db.Folder), folders): for folder in filter(lambda f: isinstance(f, Folder), folders):
FolderManager.scan(folder.id, s, TimedProgressDisplay(folder.name)) FolderManager.scan(self.__store, folder.id, s, TimedProgressDisplay(folder.name))
else: else:
for folder in db.Folder.query.filter(db.Folder.root == True): for folder in self.__store.find(Folder, Folder.root == True):
FolderManager.scan(folder.id, s, TimedProgressDisplay(folder.name)) FolderManager.scan(self.__store, folder.id, s, TimedProgressDisplay(folder.name))
added, deleted = s.stats() added, deleted = s.stats()
db.session.commit() self.__store.commit()
print "Scanning done" print "Scanning done"
print 'Added: %i artists, %i albums, %i tracks' % (added[0], added[1], added[2]) print 'Added: %i artists, %i albums, %i tracks' % (added[0], added[1], added[2])
@ -219,15 +226,9 @@ if __name__ == "__main__":
if not config.check(): if not config.check():
sys.exit(1) sys.exit(1)
import db cli = CLI(get_store(config.get('base', 'database_uri')))
db.init_db()
from managers.folder import FolderManager
from managers.user import UserManager
from scanner import Scanner
if len(sys.argv) > 1: if len(sys.argv) > 1:
CLI().onecmd(' '.join(sys.argv[1:])) cli.onecmd(' '.join(sys.argv[1:]))
else: else:
CLI().cmdloop() cli.cmdloop()

22
db.py
View File

@ -19,7 +19,10 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
from storm.properties import * from storm.properties import *
from storm.references import * from storm.references import Reference, ReferenceSet
from storm.database import create_database
from storm.store import Store
from storm.variables import Variable
import uuid, datetime, time import uuid, datetime, time
import os.path import os.path
@ -27,6 +30,18 @@ import os.path
def now(): def now():
return datetime.datetime.now().replace(microsecond = 0) return datetime.datetime.now().replace(microsecond = 0)
class UnicodeOrStrVariable(Variable):
__slots__ = ()
def parse_set(self, value, from_db):
if isinstance(value, unicode):
return value
elif isinstance(value, str):
return unicode(value)
raise TypeError("Expected unicode, found %r: %r" % (type(value), value))
Unicode.variable_class = UnicodeOrStrVariable
class Folder(object): class Folder(object):
__storm_table__ = 'folder' __storm_table__ = 'folder'
@ -353,3 +368,8 @@ class PlaylistTrack(object):
Playlist.tracks = ReferenceSet(Playlist.id, PlaylistTrack.playlist_id, PlaylistTrack.track_id, Track.id) Playlist.tracks = ReferenceSet(Playlist.id, PlaylistTrack.playlist_id, PlaylistTrack.track_id, Track.id)
def get_store(database_uri):
database = create_database(database_uri)
store = Store(database)
return store

View File

@ -19,7 +19,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import os.path, uuid import os.path, uuid
from db import Folder, Artist, session from db import Folder, Artist, Album, Track
class FolderManager: class FolderManager:
SUCCESS = 0 SUCCESS = 0
@ -30,7 +30,7 @@ class FolderManager:
NO_SUCH_FOLDER = 5 NO_SUCH_FOLDER = 5
@staticmethod @staticmethod
def get(uid): def get(store, uid):
if isinstance(uid, basestring): if isinstance(uid, basestring):
try: try:
uid = uuid.UUID(uid) uid = uuid.UUID(uid)
@ -41,33 +41,36 @@ class FolderManager:
else: else:
return FolderManager.INVALID_ID, None return FolderManager.INVALID_ID, None
folder = Folder.query.get(uid) folder = store.get(Folder, uid)
if not folder: if not folder:
return FolderManager.NO_SUCH_FOLDER, None return FolderManager.NO_SUCH_FOLDER, None
return FolderManager.SUCCESS, folder return FolderManager.SUCCESS, folder
@staticmethod @staticmethod
def add(name, path): def add(store, name, path):
if Folder.query.filter(Folder.name == name and Folder.root == True).first(): if not store.find(Folder, Folder.name == name, Folder.root == True).is_empty():
return FolderManager.NAME_EXISTS return FolderManager.NAME_EXISTS
path = os.path.abspath(path) path = os.path.abspath(path)
if not os.path.isdir(path): if not os.path.isdir(path):
return FolderManager.INVALID_PATH return FolderManager.INVALID_PATH
folder = Folder.query.filter(Folder.path == path).first() if not store.find(Folder, Folder.path == path).is_empty():
if folder:
return FolderManager.PATH_EXISTS return FolderManager.PATH_EXISTS
folder = Folder(root = True, name = name, path = path) folder = Folder()
session.add(folder) folder.root = True
session.commit() folder.name = name
folder.path = path
store.add(folder)
store.commit()
return FolderManager.SUCCESS return FolderManager.SUCCESS
@staticmethod @staticmethod
def delete(uid): def delete(store, uid):
status, folder = FolderManager.get(uid) status, folder = FolderManager.get(store, uid)
if status != FolderManager.SUCCESS: if status != FolderManager.SUCCESS:
return status return status
@ -75,37 +78,37 @@ class FolderManager:
return FolderManager.NO_SUCH_FOLDER return FolderManager.NO_SUCH_FOLDER
# delete associated tracks and prune empty albums/artists # delete associated tracks and prune empty albums/artists
for artist in Artist.query.all(): potentially_removed_albums = set()
for album in artist.albums[:]: for track in store.find(Track, Track.root_folder_id == folder.id):
for track in filter(lambda t: t.root_folder.id == folder.id, album.tracks): potentially_removed_albums.add(track.album)
album.tracks.remove(track) store.remove(track)
session.delete(track) potentially_removed_artists = set()
if len(album.tracks) == 0: for album in filter(lambda album: album.tracks.count() == 0, potentially_removed_albums):
artist.albums.remove(album) potentially_removed_artists.add(album.artist)
session.delete(album) store.remove(album)
if len(artist.albums) == 0: for artist in filter(lambda artist: artist.albums.count() == 0, potentially_removed_artists):
session.delete(artist) store.remove(artist)
def cleanup_folder(folder): def cleanup_folder(folder):
for f in folder.children: for f in folder.children:
cleanup_folder(f) cleanup_folder(f)
session.delete(folder) store.remove(folder)
cleanup_folder(folder) cleanup_folder(folder)
session.commit() store.commit()
return FolderManager.SUCCESS return FolderManager.SUCCESS
@staticmethod @staticmethod
def delete_by_name(name): def delete_by_name(store, name):
folder = Folder.query.filter(Folder.name == name and Folder.root == True).first() folder = store.find(Folder, Folder.name == name, Folder.root == True).one()
if not folder: if not folder:
return FolderManager.NO_SUCH_FOLDER return FolderManager.NO_SUCH_FOLDER
return FolderManager.delete(folder.id) return FolderManager.delete(store, folder.id)
@staticmethod @staticmethod
def scan(uid, scanner, progress_callback = None): def scan(store, uid, scanner, progress_callback = None):
status, folder = FolderManager.get(uid) status, folder = FolderManager.get(store, uid)
if status != FolderManager.SUCCESS: if status != FolderManager.SUCCESS:
return status return status

View File

@ -21,7 +21,7 @@
import string, random, hashlib import string, random, hashlib
import uuid import uuid
from db import User, session from db import User
class UserManager: class UserManager:
SUCCESS = 0 SUCCESS = 0

View File

@ -27,11 +27,8 @@ def get_mime(ext):
return mimetypes.guess_type('dummy.' + ext, False)[0] or config.get('mimetypes', ext) or 'application/octet-stream' return mimetypes.guess_type('dummy.' + ext, False)[0] or config.get('mimetypes', ext) or 'application/octet-stream'
class Scanner: class Scanner:
def __init__(self, session): def __init__(self, store):
self.__session = session self.__store = store
self.__tracks = db.Track.query.all()
self.__artists = db.Artist.query.all()
self.__folders = db.Folder.query.all()
self.__added_artists = 0 self.__added_artists = 0
self.__added_albums = 0 self.__added_albums = 0