mirror of
https://github.com/spl0k/supysonic.git
synced 2024-12-23 01:16:18 +00:00
parent
8674965c03
commit
1a79fe3d70
@ -28,6 +28,7 @@ from xml.dom import minidom
|
|||||||
from xml.etree import ElementTree
|
from xml.etree import ElementTree
|
||||||
|
|
||||||
from ..managers.user import UserManager
|
from ..managers.user import UserManager
|
||||||
|
from ..py23 import strtype
|
||||||
|
|
||||||
from builtins import dict
|
from builtins import dict
|
||||||
|
|
||||||
@ -191,7 +192,7 @@ class ResponseHelper:
|
|||||||
"""
|
"""
|
||||||
if not isinstance(dictionary, dict):
|
if not isinstance(dictionary, dict):
|
||||||
raise TypeError('Expecting a dict')
|
raise TypeError('Expecting a dict')
|
||||||
if not all(map(lambda x: isinstance(x, basestring), dictionary)):
|
if not all(map(lambda x: isinstance(x, strtype), dictionary)):
|
||||||
raise TypeError('Dictionary keys must be strings')
|
raise TypeError('Dictionary keys must be strings')
|
||||||
|
|
||||||
for name, value in dictionary.items():
|
for name, value in dictionary.items():
|
||||||
@ -214,7 +215,7 @@ class ResponseHelper:
|
|||||||
def value_tostring(value):
|
def value_tostring(value):
|
||||||
if value is None:
|
if value is None:
|
||||||
return None
|
return None
|
||||||
if isinstance(value, basestring):
|
if isinstance(value, strtype):
|
||||||
return value
|
return value
|
||||||
if isinstance(value, bool):
|
if isinstance(value, bool):
|
||||||
return str(value).lower()
|
return str(value).lower()
|
||||||
|
@ -28,6 +28,8 @@ from pony.orm import ObjectNotFound
|
|||||||
from pony.orm import min, max, avg, sum
|
from pony.orm import min, max, avg, sum
|
||||||
from uuid import UUID, uuid4
|
from uuid import UUID, uuid4
|
||||||
|
|
||||||
|
from .py23 import strtype
|
||||||
|
|
||||||
from builtins import dict
|
from builtins import dict
|
||||||
try:
|
try:
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
@ -420,7 +422,7 @@ class Playlist(db.Entity):
|
|||||||
tid = track
|
tid = track
|
||||||
elif isinstance(track, Track):
|
elif isinstance(track, Track):
|
||||||
tid = track.id
|
tid = track.id
|
||||||
elif isinstance(track, basestring):
|
elif isinstance(track, strtype):
|
||||||
tid = UUID(track)
|
tid = UUID(track)
|
||||||
|
|
||||||
if self.tracks and len(self.tracks) > 0:
|
if self.tracks and len(self.tracks) > 0:
|
||||||
@ -438,7 +440,7 @@ class Playlist(db.Entity):
|
|||||||
self.tracks = ','.join(t for t in tracks if t)
|
self.tracks = ','.join(t for t in tracks if t)
|
||||||
|
|
||||||
def parse_uri(database_uri):
|
def parse_uri(database_uri):
|
||||||
if not isinstance(database_uri, basestring):
|
if not isinstance(database_uri, strtype):
|
||||||
raise TypeError('Expecting a string')
|
raise TypeError('Expecting a string')
|
||||||
|
|
||||||
uri = urlparse(database_uri)
|
uri = urlparse(database_uri)
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
|
|
||||||
import requests, hashlib
|
import requests, hashlib
|
||||||
|
|
||||||
|
from .py23 import strtype
|
||||||
|
|
||||||
class LastFm:
|
class LastFm:
|
||||||
def __init__(self, config, user, logger):
|
def __init__(self, config, user, logger):
|
||||||
self.__api_key = config['api_key']
|
self.__api_key = config['api_key']
|
||||||
@ -71,9 +73,9 @@ class LastFm:
|
|||||||
|
|
||||||
kwargs['api_key'] = self.__api_key
|
kwargs['api_key'] = self.__api_key
|
||||||
|
|
||||||
sig_str = ''
|
sig_str = b''
|
||||||
for k, v in sorted(kwargs.items()):
|
for k, v in sorted(kwargs.items()):
|
||||||
if type(v) is unicode:
|
if isinstance(v, strtype):
|
||||||
sig_str += k + v.encode('utf-8')
|
sig_str += k + v.encode('utf-8')
|
||||||
else:
|
else:
|
||||||
sig_str += k + str(v)
|
sig_str += k + str(v)
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
# This file is part of Supysonic.
|
# This file is part of Supysonic.
|
||||||
#
|
#
|
||||||
# Supysonic is a Python implementation of the Subsonic server API.
|
# Supysonic is a Python implementation of the Subsonic server API.
|
||||||
# Copyright (C) 2013-2017 Alban 'spl0k' Féron
|
# Copyright (C) 2013-2018 Alban 'spl0k' Féron
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU Affero General Public License as published by
|
# it under the terms of the GNU Affero General Public License as published by
|
||||||
@ -25,6 +25,7 @@ from pony.orm import db_session, select
|
|||||||
from pony.orm import ObjectNotFound
|
from pony.orm import ObjectNotFound
|
||||||
|
|
||||||
from ..db import Folder, Artist, Album, Track, StarredFolder, RatingFolder
|
from ..db import Folder, Artist, Album, Track, StarredFolder, RatingFolder
|
||||||
|
from ..py23 import strtype
|
||||||
from ..scanner import Scanner
|
from ..scanner import Scanner
|
||||||
|
|
||||||
class FolderManager:
|
class FolderManager:
|
||||||
@ -39,12 +40,12 @@ class FolderManager:
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
@db_session
|
@db_session
|
||||||
def get(uid):
|
def get(uid):
|
||||||
if isinstance(uid, basestring):
|
if isinstance(uid, strtype):
|
||||||
try:
|
try:
|
||||||
uid = uuid.UUID(uid)
|
uid = uuid.UUID(uid)
|
||||||
except:
|
except:
|
||||||
return FolderManager.INVALID_ID, None
|
return FolderManager.INVALID_ID, None
|
||||||
elif type(uid) is uuid.UUID:
|
elif isinstance(uid, uuid.UUID):
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
return FolderManager.INVALID_ID, None
|
return FolderManager.INVALID_ID, None
|
||||||
@ -61,7 +62,7 @@ class FolderManager:
|
|||||||
if Folder.get(name = name, root = True) is not None:
|
if Folder.get(name = name, root = True) is not None:
|
||||||
return FolderManager.NAME_EXISTS
|
return FolderManager.NAME_EXISTS
|
||||||
|
|
||||||
path = unicode(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
|
||||||
if Folder.get(path = path) is not None:
|
if Folder.get(path = path) is not None:
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
# This file is part of Supysonic.
|
# This file is part of Supysonic.
|
||||||
# Supysonic is a Python implementation of the Subsonic server API.
|
# Supysonic is a Python implementation of the Subsonic server API.
|
||||||
#
|
#
|
||||||
# Copyright (C) 2013-2017 Alban 'spl0k' Féron
|
# Copyright (C) 2013-2018 Alban 'spl0k' Féron
|
||||||
# 2017 Óscar García Amor
|
# 2017 Óscar García Amor
|
||||||
#
|
#
|
||||||
# Distributed under terms of the GNU AGPLv3 license.
|
# Distributed under terms of the GNU AGPLv3 license.
|
||||||
@ -20,6 +20,7 @@ from pony.orm import ObjectNotFound
|
|||||||
from ..db import User, ChatMessage, Playlist
|
from ..db import User, ChatMessage, Playlist
|
||||||
from ..db import StarredFolder, StarredArtist, StarredAlbum, StarredTrack
|
from ..db import StarredFolder, StarredArtist, StarredAlbum, StarredTrack
|
||||||
from ..db import RatingFolder, RatingTrack
|
from ..db import RatingFolder, RatingTrack
|
||||||
|
from ..py23 import strtype
|
||||||
|
|
||||||
class UserManager:
|
class UserManager:
|
||||||
SUCCESS = 0
|
SUCCESS = 0
|
||||||
@ -31,12 +32,12 @@ class UserManager:
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
@db_session
|
@db_session
|
||||||
def get(uid):
|
def get(uid):
|
||||||
if type(uid) in (str, unicode):
|
if isinstance(uid, strtype):
|
||||||
try:
|
try:
|
||||||
uid = uuid.UUID(uid)
|
uid = uuid.UUID(uid)
|
||||||
except:
|
except:
|
||||||
return UserManager.INVALID_ID, None
|
return UserManager.INVALID_ID, None
|
||||||
elif type(uid) is uuid.UUID:
|
elif isinstance(uid, uuid.UUID):
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
return UserManager.INVALID_ID, None
|
return UserManager.INVALID_ID, None
|
||||||
|
16
supysonic/py23.py
Normal file
16
supysonic/py23.py
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# coding: utf-8
|
||||||
|
#
|
||||||
|
# This file is part of Supysonic.
|
||||||
|
# Supysonic is a Python implementation of the Subsonic server API.
|
||||||
|
#
|
||||||
|
# Copyright (C) 2018 Alban 'spl0k' Féron
|
||||||
|
#
|
||||||
|
# Distributed under terms of the GNU AGPLv3 license.
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Python 2
|
||||||
|
strtype = basestring
|
||||||
|
except NameError:
|
||||||
|
# Python 3
|
||||||
|
strtype = str
|
||||||
|
|
@ -3,7 +3,7 @@
|
|||||||
# This file is part of Supysonic.
|
# This file is part of Supysonic.
|
||||||
#
|
#
|
||||||
# Supysonic is a Python implementation of the Subsonic server API.
|
# Supysonic is a Python implementation of the Subsonic server API.
|
||||||
# Copyright (C) 2013-2017 Alban 'spl0k' Féron
|
# Copyright (C) 2013-2018 Alban 'spl0k' Féron
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU Affero General Public License as published by
|
# it under the terms of the GNU Affero General Public License as published by
|
||||||
@ -28,6 +28,7 @@ from pony.orm import db_session
|
|||||||
from .db import Folder, Artist, Album, Track, User
|
from .db import Folder, Artist, Album, Track, User
|
||||||
from .db import StarredFolder, StarredArtist, StarredAlbum, StarredTrack
|
from .db import StarredFolder, StarredArtist, StarredAlbum, StarredTrack
|
||||||
from .db import RatingFolder, RatingTrack
|
from .db import RatingFolder, RatingTrack
|
||||||
|
from .py23 import strtype
|
||||||
|
|
||||||
class Scanner:
|
class Scanner:
|
||||||
def __init__(self, force = False, extensions = None):
|
def __init__(self, force = False, extensions = None):
|
||||||
@ -119,7 +120,7 @@ class Scanner:
|
|||||||
|
|
||||||
@db_session
|
@db_session
|
||||||
def scan_file(self, path):
|
def scan_file(self, path):
|
||||||
if not isinstance(path, basestring):
|
if not isinstance(path, strtype):
|
||||||
raise TypeError('Expecting string, got ' + str(type(path)))
|
raise TypeError('Expecting string, got ' + str(type(path)))
|
||||||
|
|
||||||
tr = Track.get(path = path)
|
tr = Track.get(path = path)
|
||||||
@ -181,7 +182,7 @@ class Scanner:
|
|||||||
|
|
||||||
@db_session
|
@db_session
|
||||||
def remove_file(self, path):
|
def remove_file(self, path):
|
||||||
if not isinstance(path, basestring):
|
if not isinstance(path, strtype):
|
||||||
raise TypeError('Expecting string, got ' + str(type(path)))
|
raise TypeError('Expecting string, got ' + str(type(path)))
|
||||||
|
|
||||||
tr = Track.get(path = path)
|
tr = Track.get(path = path)
|
||||||
@ -196,9 +197,9 @@ class Scanner:
|
|||||||
|
|
||||||
@db_session
|
@db_session
|
||||||
def move_file(self, src_path, dst_path):
|
def move_file(self, src_path, dst_path):
|
||||||
if not isinstance(src_path, basestring):
|
if not isinstance(src_path, strtype):
|
||||||
raise TypeError('Expecting string, got ' + str(type(src_path)))
|
raise TypeError('Expecting string, got ' + str(type(src_path)))
|
||||||
if not isinstance(dst_path, basestring):
|
if not isinstance(dst_path, strtype):
|
||||||
raise TypeError('Expecting string, got ' + str(type(dst_path)))
|
raise TypeError('Expecting string, got ' + str(type(dst_path)))
|
||||||
|
|
||||||
if src_path == dst_path:
|
if src_path == dst_path:
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
# This file is part of Supysonic.
|
# This file is part of Supysonic.
|
||||||
# Supysonic is a Python implementation of the Subsonic server API.
|
# Supysonic is a Python implementation of the Subsonic server API.
|
||||||
#
|
#
|
||||||
# Copyright (C) 2017 Alban 'spl0k' Féron
|
# Copyright (C) 2017-2018 Alban 'spl0k' Féron
|
||||||
#
|
#
|
||||||
# Distributed under terms of the GNU AGPLv3 license.
|
# Distributed under terms of the GNU AGPLv3 license.
|
||||||
|
|
||||||
@ -12,6 +12,7 @@ import re
|
|||||||
|
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
from supysonic.managers.user import UserManager
|
from supysonic.managers.user import UserManager
|
||||||
|
from supysonic.py23 import strtype
|
||||||
|
|
||||||
from ..testbase import TestBase
|
from ..testbase import TestBase
|
||||||
|
|
||||||
@ -65,7 +66,7 @@ class ApiTestBase(TestBase):
|
|||||||
|
|
||||||
if not isinstance(args, dict):
|
if not isinstance(args, dict):
|
||||||
raise TypeError("'args', expecting a dict, got " + type(args).__name__)
|
raise TypeError("'args', expecting a dict, got " + type(args).__name__)
|
||||||
if tag and not isinstance(tag, basestring):
|
if tag and not isinstance(tag, strtype):
|
||||||
raise TypeError("'tag', expecting a str, got " + type(tag).__name__)
|
raise TypeError("'tag', expecting a str, got " + type(tag).__name__)
|
||||||
|
|
||||||
args.update({ 'c': 'tests', 'v': '1.8.0' })
|
args.update({ 'c': 'tests', 'v': '1.8.0' })
|
||||||
|
@ -14,6 +14,8 @@ import unittest
|
|||||||
import simplejson
|
import simplejson
|
||||||
from xml.etree import ElementTree
|
from xml.etree import ElementTree
|
||||||
|
|
||||||
|
from supysonic.py23 import strtype
|
||||||
|
|
||||||
from ..testbase import TestBase
|
from ..testbase import TestBase
|
||||||
|
|
||||||
class ResponseHelperBaseCase(TestBase):
|
class ResponseHelperBaseCase(TestBase):
|
||||||
@ -26,108 +28,108 @@ class ResponseHelperBaseCase(TestBase):
|
|||||||
class ResponseHelperJsonTestCase(ResponseHelperBaseCase):
|
class ResponseHelperJsonTestCase(ResponseHelperBaseCase):
|
||||||
def serialize_and_deserialize(self, d, error = False):
|
def serialize_and_deserialize(self, d, error = False):
|
||||||
if not isinstance(d, dict):
|
if not isinstance(d, dict):
|
||||||
raise TypeError(u'Invalid tested value, expecting a dict')
|
raise TypeError('Invalid tested value, expecting a dict')
|
||||||
|
|
||||||
json = self.helper.responsize_json(d, error)
|
json = self.helper.responsize_json(d, error)
|
||||||
return simplejson.loads(json)
|
return simplejson.loads(json)
|
||||||
|
|
||||||
def process_and_extract(self, d, error = False):
|
def process_and_extract(self, d, error = False):
|
||||||
# Basically returns d with additional version and status
|
# Basically returns d with additional version and status
|
||||||
return self.serialize_and_deserialize(d, error)[u'subsonic-response']
|
return self.serialize_and_deserialize(d, error)['subsonic-response']
|
||||||
|
|
||||||
def test_basic(self):
|
def test_basic(self):
|
||||||
empty = self.serialize_and_deserialize({})
|
empty = self.serialize_and_deserialize({})
|
||||||
self.assertEqual(len(empty), 1)
|
self.assertEqual(len(empty), 1)
|
||||||
self.assertIn(u'subsonic-response', empty)
|
self.assertIn('subsonic-response', empty)
|
||||||
self.assertIsInstance(empty[u'subsonic-response'], dict)
|
self.assertIsInstance(empty['subsonic-response'], dict)
|
||||||
|
|
||||||
resp = empty[u'subsonic-response']
|
resp = empty['subsonic-response']
|
||||||
self.assertEqual(len(resp), 2)
|
self.assertEqual(len(resp), 2)
|
||||||
self.assertIn(u'status', resp)
|
self.assertIn('status', resp)
|
||||||
self.assertIn(u'version', resp)
|
self.assertIn('version', resp)
|
||||||
self.assertEqual(resp[u'status'], u'ok')
|
self.assertEqual(resp['status'], 'ok')
|
||||||
|
|
||||||
resp = self.process_and_extract({}, True)
|
resp = self.process_and_extract({}, True)
|
||||||
self.assertEqual(resp[u'status'], u'failed')
|
self.assertEqual(resp['status'], 'failed')
|
||||||
|
|
||||||
some_dict = {
|
some_dict = {
|
||||||
u'intValue': 2,
|
'intValue': 2,
|
||||||
u'someString': u'Hello world!'
|
'someString': 'Hello world!'
|
||||||
}
|
}
|
||||||
resp = self.process_and_extract(some_dict)
|
resp = self.process_and_extract(some_dict)
|
||||||
self.assertIn(u'intValue', resp)
|
self.assertIn('intValue', resp)
|
||||||
self.assertIn(u'someString', resp)
|
self.assertIn('someString', resp)
|
||||||
|
|
||||||
def test_lists(self):
|
def test_lists(self):
|
||||||
resp = self.process_and_extract({
|
resp = self.process_and_extract({
|
||||||
u'someList': [ 2, 4, 8, 16 ],
|
'someList': [ 2, 4, 8, 16 ],
|
||||||
u'emptyList': []
|
'emptyList': []
|
||||||
})
|
})
|
||||||
self.assertIn(u'someList', resp)
|
self.assertIn('someList', resp)
|
||||||
self.assertNotIn(u'emptyList', resp)
|
self.assertNotIn('emptyList', resp)
|
||||||
self.assertListEqual(resp[u'someList'], [ 2, 4, 8, 16 ])
|
self.assertListEqual(resp['someList'], [ 2, 4, 8, 16 ])
|
||||||
|
|
||||||
def test_dicts(self):
|
def test_dicts(self):
|
||||||
resp = self.process_and_extract({
|
resp = self.process_and_extract({
|
||||||
u'dict': { u's': u'Blah', u'i': 20 },
|
'dict': { 's': 'Blah', 'i': 20 },
|
||||||
u'empty': {}
|
'empty': {}
|
||||||
})
|
})
|
||||||
self.assertIn(u'dict', resp)
|
self.assertIn('dict', resp)
|
||||||
self.assertIn(u'empty', resp)
|
self.assertIn('empty', resp)
|
||||||
self.assertDictEqual(resp[u'dict'], { u's': u'Blah', u'i': 20 })
|
self.assertDictEqual(resp['dict'], { 's': 'Blah', 'i': 20 })
|
||||||
self.assertDictEqual(resp[u'empty'], {})
|
self.assertDictEqual(resp['empty'], {})
|
||||||
|
|
||||||
def test_nesting(self):
|
def test_nesting(self):
|
||||||
resp = self.process_and_extract({
|
resp = self.process_and_extract({
|
||||||
u'dict': {
|
'dict': {
|
||||||
u'value': u'hey look! a string',
|
'value': 'hey look! a string',
|
||||||
u'list': [ 1, 2, 3 ],
|
'list': [ 1, 2, 3 ],
|
||||||
u'emptyList': [],
|
'emptyList': [],
|
||||||
u'subdict': { u'a': u'A' }
|
'subdict': { 'a': 'A' }
|
||||||
},
|
},
|
||||||
u'list': [
|
'list': [
|
||||||
{ u'b': u'B' },
|
{ 'b': 'B' },
|
||||||
{ u'c': u'C' },
|
{ 'c': 'C' },
|
||||||
[ 4, 5, 6 ],
|
[ 4, 5, 6 ],
|
||||||
u'final string'
|
'final string'
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
self.assertEqual(len(resp), 4) # dict, list, status and version
|
self.assertEqual(len(resp), 4) # dict, list, status and version
|
||||||
self.assertIn(u'dict', resp)
|
self.assertIn('dict', resp)
|
||||||
self.assertIn(u'list', resp)
|
self.assertIn('list', resp)
|
||||||
|
|
||||||
d = resp[u'dict']
|
d = resp['dict']
|
||||||
l = resp[u'list']
|
l = resp['list']
|
||||||
|
|
||||||
self.assertIn(u'value', d)
|
self.assertIn('value', d)
|
||||||
self.assertIn(u'list', d)
|
self.assertIn('list', d)
|
||||||
self.assertNotIn('emptyList', d)
|
self.assertNotIn('emptyList', d)
|
||||||
self.assertIn(u'subdict', d)
|
self.assertIn('subdict', d)
|
||||||
self.assertIsInstance(d[u'value'], basestring)
|
self.assertIsInstance(d['value'], strtype)
|
||||||
self.assertIsInstance(d[u'list'], list)
|
self.assertIsInstance(d['list'], list)
|
||||||
self.assertIsInstance(d[u'subdict'], dict)
|
self.assertIsInstance(d['subdict'], dict)
|
||||||
|
|
||||||
self.assertEqual(l, [
|
self.assertEqual(l, [
|
||||||
{ u'b': u'B' },
|
{ 'b': 'B' },
|
||||||
{ u'c': u'C' },
|
{ 'c': 'C' },
|
||||||
[ 4, 5, 6 ],
|
[ 4, 5, 6 ],
|
||||||
u'final string'
|
'final string'
|
||||||
])
|
])
|
||||||
|
|
||||||
class ResponseHelperJsonpTestCase(ResponseHelperBaseCase):
|
class ResponseHelperJsonpTestCase(ResponseHelperBaseCase):
|
||||||
def test_basic(self):
|
def test_basic(self):
|
||||||
result = self.helper.responsize_jsonp({}, u'callback')
|
result = self.helper.responsize_jsonp({}, 'callback')
|
||||||
self.assertTrue(result.startswith(u'callback({'))
|
self.assertTrue(result.startswith('callback({'))
|
||||||
self.assertTrue(result.endswith(u'})'))
|
self.assertTrue(result.endswith('})'))
|
||||||
|
|
||||||
json = simplejson.loads(result[9:-1])
|
json = simplejson.loads(result[9:-1])
|
||||||
self.assertIn(u'subsonic-response', json)
|
self.assertIn('subsonic-response', json)
|
||||||
|
|
||||||
class ResponseHelperXMLTestCase(ResponseHelperBaseCase):
|
class ResponseHelperXMLTestCase(ResponseHelperBaseCase):
|
||||||
def serialize_and_deserialize(self, d, error = False):
|
def serialize_and_deserialize(self, d, error = False):
|
||||||
xml = self.helper.responsize_xml(d, error)
|
xml = self.helper.responsize_xml(d, error)
|
||||||
xml = xml.replace(u'xmlns="http://subsonic.org/restapi"', u'')
|
xml = xml.replace('xmlns="http://subsonic.org/restapi"', '')
|
||||||
root = ElementTree.fromstring(xml)
|
root = ElementTree.fromstring(xml)
|
||||||
return root
|
return root
|
||||||
|
|
||||||
@ -137,80 +139,80 @@ class ResponseHelperXMLTestCase(ResponseHelperBaseCase):
|
|||||||
|
|
||||||
def test_root(self):
|
def test_root(self):
|
||||||
xml = self.helper.responsize_xml({ 'tag': {}})
|
xml = self.helper.responsize_xml({ 'tag': {}})
|
||||||
self.assertIn(u'<subsonic-response ', xml)
|
self.assertIn('<subsonic-response ', xml)
|
||||||
self.assertIn(u'xmlns="http://subsonic.org/restapi"', xml)
|
self.assertIn('xmlns="http://subsonic.org/restapi"', xml)
|
||||||
self.assertTrue(xml.strip().endswith(u'</subsonic-response>'))
|
self.assertTrue(xml.strip().endswith('</subsonic-response>'))
|
||||||
|
|
||||||
def test_basic(self):
|
def test_basic(self):
|
||||||
empty = self.serialize_and_deserialize({})
|
empty = self.serialize_and_deserialize({})
|
||||||
self.assertIsNotNone(empty.find(u'.[@version]'))
|
self.assertIsNotNone(empty.find('.[@version]'))
|
||||||
self.assertIsNotNone(empty.find(u".[@status='ok']"))
|
self.assertIsNotNone(empty.find(".[@status='ok']"))
|
||||||
|
|
||||||
resp = self.serialize_and_deserialize({}, True)
|
resp = self.serialize_and_deserialize({}, True)
|
||||||
self.assertIsNotNone(resp.find(u".[@status='failed']"))
|
self.assertIsNotNone(resp.find(".[@status='failed']"))
|
||||||
|
|
||||||
some_dict = {
|
some_dict = {
|
||||||
u'intValue': 2,
|
'intValue': 2,
|
||||||
u'someString': u'Hello world!'
|
'someString': 'Hello world!'
|
||||||
}
|
}
|
||||||
resp = self.serialize_and_deserialize(some_dict)
|
resp = self.serialize_and_deserialize(some_dict)
|
||||||
self.assertIsNotNone(resp.find(u'.[@intValue]'))
|
self.assertIsNotNone(resp.find('.[@intValue]'))
|
||||||
self.assertIsNotNone(resp.find(u'.[@someString]'))
|
self.assertIsNotNone(resp.find('.[@someString]'))
|
||||||
|
|
||||||
def test_lists(self):
|
def test_lists(self):
|
||||||
resp = self.serialize_and_deserialize({
|
resp = self.serialize_and_deserialize({
|
||||||
u'someList': [ 2, 4, 8, 16 ],
|
'someList': [ 2, 4, 8, 16 ],
|
||||||
u'emptyList': []
|
'emptyList': []
|
||||||
})
|
})
|
||||||
|
|
||||||
elems = resp.findall(u'./someList')
|
elems = resp.findall('./someList')
|
||||||
self.assertEqual(len(elems), 4)
|
self.assertEqual(len(elems), 4)
|
||||||
self.assertIsNone(resp.find(u'./emptyList'))
|
self.assertIsNone(resp.find('./emptyList'))
|
||||||
|
|
||||||
for e, i in zip(elems, [ 2, 4, 8, 16 ]):
|
for e, i in zip(elems, [ 2, 4, 8, 16 ]):
|
||||||
self.assertEqual(int(e.text), i)
|
self.assertEqual(int(e.text), i)
|
||||||
|
|
||||||
def test_dicts(self):
|
def test_dicts(self):
|
||||||
resp = self.serialize_and_deserialize({
|
resp = self.serialize_and_deserialize({
|
||||||
u'dict': { u's': u'Blah', u'i': 20 },
|
'dict': { 's': 'Blah', 'i': 20 },
|
||||||
u'empty': {}
|
'empty': {}
|
||||||
})
|
})
|
||||||
|
|
||||||
d = resp.find(u'./dict')
|
d = resp.find('./dict')
|
||||||
self.assertIsNotNone(d)
|
self.assertIsNotNone(d)
|
||||||
self.assertIsNotNone(resp.find(u'./empty'))
|
self.assertIsNotNone(resp.find('./empty'))
|
||||||
self.assertAttributesMatchDict(d, { u's': u'Blah', u'i': 20 })
|
self.assertAttributesMatchDict(d, { 's': 'Blah', 'i': 20 })
|
||||||
|
|
||||||
def test_nesting(self):
|
def test_nesting(self):
|
||||||
resp = self.serialize_and_deserialize({
|
resp = self.serialize_and_deserialize({
|
||||||
u'dict': {
|
'dict': {
|
||||||
u'value': u'hey look! a string',
|
'value': 'hey look! a string',
|
||||||
u'list': [ 1, 2, 3 ],
|
'list': [ 1, 2, 3 ],
|
||||||
u'emptyList': [],
|
'emptyList': [],
|
||||||
u'subdict': { u'a': u'A' }
|
'subdict': { 'a': 'A' }
|
||||||
},
|
},
|
||||||
u'list': [
|
'list': [
|
||||||
{ u'b': u'B' },
|
{ 'b': 'B' },
|
||||||
{ u'c': u'C' },
|
{ 'c': 'C' },
|
||||||
u'final string'
|
'final string'
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
self.assertEqual(len(resp), 4) # 'dict' and 3 'list's
|
self.assertEqual(len(resp), 4) # 'dict' and 3 'list's
|
||||||
|
|
||||||
d = resp.find(u'./dict')
|
d = resp.find('./dict')
|
||||||
lists = resp.findall(u'./list')
|
lists = resp.findall('./list')
|
||||||
|
|
||||||
self.assertIsNotNone(d)
|
self.assertIsNotNone(d)
|
||||||
self.assertAttributesMatchDict(d, { u'value': u'hey look! a string' })
|
self.assertAttributesMatchDict(d, { 'value': 'hey look! a string' })
|
||||||
self.assertEqual(len(d.findall(u'./list')), 3)
|
self.assertEqual(len(d.findall('./list')), 3)
|
||||||
self.assertEqual(len(d.findall(u'./emptyList')), 0)
|
self.assertEqual(len(d.findall('./emptyList')), 0)
|
||||||
self.assertIsNotNone(d.find(u'./subdict'))
|
self.assertIsNotNone(d.find('./subdict'))
|
||||||
|
|
||||||
self.assertEqual(len(lists), 3)
|
self.assertEqual(len(lists), 3)
|
||||||
self.assertAttributesMatchDict(lists[0], { u'b': u'B' })
|
self.assertAttributesMatchDict(lists[0], { 'b': 'B' })
|
||||||
self.assertAttributesMatchDict(lists[1], { u'c': u'C' })
|
self.assertAttributesMatchDict(lists[1], { 'c': 'C' })
|
||||||
self.assertEqual(lists[2].text, u'final string')
|
self.assertEqual(lists[2].text, 'final string')
|
||||||
|
|
||||||
def suite():
|
def suite():
|
||||||
suite = unittest.TestSuite()
|
suite = unittest.TestSuite()
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from supysonic.config import IniConfig
|
from supysonic.config import IniConfig
|
||||||
|
from supysonic.py23 import strtype
|
||||||
|
|
||||||
class ConfigTestCase(unittest.TestCase):
|
class ConfigTestCase(unittest.TestCase):
|
||||||
def test_sections(self):
|
def test_sections(self):
|
||||||
@ -24,7 +25,7 @@ class ConfigTestCase(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertIsInstance(conf.TYPES['float'], float)
|
self.assertIsInstance(conf.TYPES['float'], float)
|
||||||
self.assertIsInstance(conf.TYPES['int'], int)
|
self.assertIsInstance(conf.TYPES['int'], int)
|
||||||
self.assertIsInstance(conf.TYPES['string'], basestring)
|
self.assertIsInstance(conf.TYPES['string'], strtype)
|
||||||
|
|
||||||
for t in ('bool', 'switch', 'yn'):
|
for t in ('bool', 'switch', 'yn'):
|
||||||
self.assertIsInstance(conf.BOOLEANS[t + '_false'], bool)
|
self.assertIsInstance(conf.BOOLEANS[t + '_false'], bool)
|
||||||
|
@ -5,13 +5,14 @@
|
|||||||
# This file is part of Supysonic.
|
# This file is part of Supysonic.
|
||||||
# Supysonic is a Python implementation of the Subsonic server API.
|
# Supysonic is a Python implementation of the Subsonic server API.
|
||||||
#
|
#
|
||||||
# Copyright (C) 2013-2017 Alban 'spl0k' Féron
|
# Copyright (C) 2013-2018 Alban 'spl0k' Féron
|
||||||
# 2017 Óscar García Amor
|
# 2017 Óscar García Amor
|
||||||
#
|
#
|
||||||
# Distributed under terms of the GNU AGPLv3 license.
|
# Distributed under terms of the GNU AGPLv3 license.
|
||||||
|
|
||||||
from supysonic import db
|
from supysonic import db
|
||||||
from supysonic.managers.folder import FolderManager
|
from supysonic.managers.folder import FolderManager
|
||||||
|
from supysonic.py23 import strtype
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import io
|
import io
|
||||||
@ -153,7 +154,7 @@ class FolderManagerTestCase(unittest.TestCase):
|
|||||||
FolderManager.INVALID_PATH, FolderManager.PATH_EXISTS, FolderManager.NO_SUCH_FOLDER,
|
FolderManager.INVALID_PATH, FolderManager.PATH_EXISTS, FolderManager.NO_SUCH_FOLDER,
|
||||||
FolderManager.SUBPATH_EXISTS, 1594826, 'string', uuid.uuid4() ]
|
FolderManager.SUBPATH_EXISTS, 1594826, 'string', uuid.uuid4() ]
|
||||||
for value in values:
|
for value in values:
|
||||||
self.assertIsInstance(FolderManager.error_str(value), basestring)
|
self.assertIsInstance(FolderManager.error_str(value), strtype)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
@ -5,13 +5,14 @@
|
|||||||
# This file is part of Supysonic.
|
# This file is part of Supysonic.
|
||||||
# Supysonic is a Python implementation of the Subsonic server API.
|
# Supysonic is a Python implementation of the Subsonic server API.
|
||||||
#
|
#
|
||||||
# Copyright (C) 2013-2017 Alban 'spl0k' Féron
|
# Copyright (C) 2013-2018 Alban 'spl0k' Féron
|
||||||
# 2017 Óscar García Amor
|
# 2017 Óscar García Amor
|
||||||
#
|
#
|
||||||
# Distributed under terms of the GNU AGPLv3 license.
|
# Distributed under terms of the GNU AGPLv3 license.
|
||||||
|
|
||||||
from supysonic import db
|
from supysonic import db
|
||||||
from supysonic.managers.user import UserManager
|
from supysonic.managers.user import UserManager
|
||||||
|
from supysonic.py23 import strtype
|
||||||
|
|
||||||
import io
|
import io
|
||||||
import unittest
|
import unittest
|
||||||
@ -180,7 +181,7 @@ class UserManagerTestCase(unittest.TestCase):
|
|||||||
values = [ UserManager.SUCCESS, UserManager.INVALID_ID, UserManager.NO_SUCH_USER, UserManager.NAME_EXISTS,
|
values = [ UserManager.SUCCESS, UserManager.INVALID_ID, UserManager.NO_SUCH_USER, UserManager.NAME_EXISTS,
|
||||||
UserManager.WRONG_PASS, 1594826, 'string', uuid.uuid4() ]
|
UserManager.WRONG_PASS, 1594826, 'string', uuid.uuid4() ]
|
||||||
for value in values:
|
for value in values:
|
||||||
self.assertIsInstance(UserManager.error_str(value), basestring)
|
self.assertIsInstance(UserManager.error_str(value), strtype)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
Loading…
Reference in New Issue
Block a user