1
0
mirror of https://github.com/spl0k/supysonic.git synced 2024-09-19 19:01:03 +00:00

Py3: basestring

Ref #75
This commit is contained in:
spl0k 2018-01-08 23:13:50 +01:00
parent 8674965c03
commit 1a79fe3d70
12 changed files with 143 additions and 113 deletions

View File

@ -28,6 +28,7 @@ from xml.dom import minidom
from xml.etree import ElementTree
from ..managers.user import UserManager
from ..py23 import strtype
from builtins import dict
@ -191,7 +192,7 @@ class ResponseHelper:
"""
if not isinstance(dictionary, 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')
for name, value in dictionary.items():
@ -214,7 +215,7 @@ class ResponseHelper:
def value_tostring(value):
if value is None:
return None
if isinstance(value, basestring):
if isinstance(value, strtype):
return value
if isinstance(value, bool):
return str(value).lower()

View File

@ -28,6 +28,8 @@ from pony.orm import ObjectNotFound
from pony.orm import min, max, avg, sum
from uuid import UUID, uuid4
from .py23 import strtype
from builtins import dict
try:
from urllib.parse import urlparse
@ -420,7 +422,7 @@ class Playlist(db.Entity):
tid = track
elif isinstance(track, Track):
tid = track.id
elif isinstance(track, basestring):
elif isinstance(track, strtype):
tid = UUID(track)
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)
def parse_uri(database_uri):
if not isinstance(database_uri, basestring):
if not isinstance(database_uri, strtype):
raise TypeError('Expecting a string')
uri = urlparse(database_uri)

View File

@ -20,6 +20,8 @@
import requests, hashlib
from .py23 import strtype
class LastFm:
def __init__(self, config, user, logger):
self.__api_key = config['api_key']
@ -71,9 +73,9 @@ class LastFm:
kwargs['api_key'] = self.__api_key
sig_str = ''
sig_str = b''
for k, v in sorted(kwargs.items()):
if type(v) is unicode:
if isinstance(v, strtype):
sig_str += k + v.encode('utf-8')
else:
sig_str += k + str(v)

View File

@ -3,7 +3,7 @@
# This file is part of Supysonic.
#
# 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
# 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 ..db import Folder, Artist, Album, Track, StarredFolder, RatingFolder
from ..py23 import strtype
from ..scanner import Scanner
class FolderManager:
@ -39,12 +40,12 @@ class FolderManager:
@staticmethod
@db_session
def get(uid):
if isinstance(uid, basestring):
if isinstance(uid, strtype):
try:
uid = uuid.UUID(uid)
except:
return FolderManager.INVALID_ID, None
elif type(uid) is uuid.UUID:
elif isinstance(uid, uuid.UUID):
pass
else:
return FolderManager.INVALID_ID, None
@ -61,7 +62,7 @@ class FolderManager:
if Folder.get(name = name, root = True) is not None:
return FolderManager.NAME_EXISTS
path = unicode(os.path.abspath(path))
path = os.path.abspath(path)
if not os.path.isdir(path):
return FolderManager.INVALID_PATH
if Folder.get(path = path) is not None:

View File

@ -4,7 +4,7 @@
# This file is part of Supysonic.
# 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
#
# 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 StarredFolder, StarredArtist, StarredAlbum, StarredTrack
from ..db import RatingFolder, RatingTrack
from ..py23 import strtype
class UserManager:
SUCCESS = 0
@ -31,12 +32,12 @@ class UserManager:
@staticmethod
@db_session
def get(uid):
if type(uid) in (str, unicode):
if isinstance(uid, strtype):
try:
uid = uuid.UUID(uid)
except:
return UserManager.INVALID_ID, None
elif type(uid) is uuid.UUID:
elif isinstance(uid, uuid.UUID):
pass
else:
return UserManager.INVALID_ID, None

16
supysonic/py23.py Normal file
View 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

View File

@ -3,7 +3,7 @@
# This file is part of Supysonic.
#
# 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
# 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 StarredFolder, StarredArtist, StarredAlbum, StarredTrack
from .db import RatingFolder, RatingTrack
from .py23 import strtype
class Scanner:
def __init__(self, force = False, extensions = None):
@ -119,7 +120,7 @@ class Scanner:
@db_session
def scan_file(self, path):
if not isinstance(path, basestring):
if not isinstance(path, strtype):
raise TypeError('Expecting string, got ' + str(type(path)))
tr = Track.get(path = path)
@ -181,7 +182,7 @@ class Scanner:
@db_session
def remove_file(self, path):
if not isinstance(path, basestring):
if not isinstance(path, strtype):
raise TypeError('Expecting string, got ' + str(type(path)))
tr = Track.get(path = path)
@ -196,9 +197,9 @@ class Scanner:
@db_session
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)))
if not isinstance(dst_path, basestring):
if not isinstance(dst_path, strtype):
raise TypeError('Expecting string, got ' + str(type(dst_path)))
if src_path == dst_path:

View File

@ -4,7 +4,7 @@
# This file is part of Supysonic.
# 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.
@ -12,6 +12,7 @@ import re
from lxml import etree
from supysonic.managers.user import UserManager
from supysonic.py23 import strtype
from ..testbase import TestBase
@ -65,7 +66,7 @@ class ApiTestBase(TestBase):
if not isinstance(args, dict):
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__)
args.update({ 'c': 'tests', 'v': '1.8.0' })

View File

@ -14,6 +14,8 @@ import unittest
import simplejson
from xml.etree import ElementTree
from supysonic.py23 import strtype
from ..testbase import TestBase
class ResponseHelperBaseCase(TestBase):
@ -26,108 +28,108 @@ class ResponseHelperBaseCase(TestBase):
class ResponseHelperJsonTestCase(ResponseHelperBaseCase):
def serialize_and_deserialize(self, d, error = False):
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)
return simplejson.loads(json)
def process_and_extract(self, d, error = False):
# 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):
empty = self.serialize_and_deserialize({})
self.assertEqual(len(empty), 1)
self.assertIn(u'subsonic-response', empty)
self.assertIsInstance(empty[u'subsonic-response'], dict)
self.assertIn('subsonic-response', empty)
self.assertIsInstance(empty['subsonic-response'], dict)
resp = empty[u'subsonic-response']
resp = empty['subsonic-response']
self.assertEqual(len(resp), 2)
self.assertIn(u'status', resp)
self.assertIn(u'version', resp)
self.assertEqual(resp[u'status'], u'ok')
self.assertIn('status', resp)
self.assertIn('version', resp)
self.assertEqual(resp['status'], 'ok')
resp = self.process_and_extract({}, True)
self.assertEqual(resp[u'status'], u'failed')
self.assertEqual(resp['status'], 'failed')
some_dict = {
u'intValue': 2,
u'someString': u'Hello world!'
'intValue': 2,
'someString': 'Hello world!'
}
resp = self.process_and_extract(some_dict)
self.assertIn(u'intValue', resp)
self.assertIn(u'someString', resp)
self.assertIn('intValue', resp)
self.assertIn('someString', resp)
def test_lists(self):
resp = self.process_and_extract({
u'someList': [ 2, 4, 8, 16 ],
u'emptyList': []
'someList': [ 2, 4, 8, 16 ],
'emptyList': []
})
self.assertIn(u'someList', resp)
self.assertNotIn(u'emptyList', resp)
self.assertListEqual(resp[u'someList'], [ 2, 4, 8, 16 ])
self.assertIn('someList', resp)
self.assertNotIn('emptyList', resp)
self.assertListEqual(resp['someList'], [ 2, 4, 8, 16 ])
def test_dicts(self):
resp = self.process_and_extract({
u'dict': { u's': u'Blah', u'i': 20 },
u'empty': {}
'dict': { 's': 'Blah', 'i': 20 },
'empty': {}
})
self.assertIn(u'dict', resp)
self.assertIn(u'empty', resp)
self.assertDictEqual(resp[u'dict'], { u's': u'Blah', u'i': 20 })
self.assertDictEqual(resp[u'empty'], {})
self.assertIn('dict', resp)
self.assertIn('empty', resp)
self.assertDictEqual(resp['dict'], { 's': 'Blah', 'i': 20 })
self.assertDictEqual(resp['empty'], {})
def test_nesting(self):
resp = self.process_and_extract({
u'dict': {
u'value': u'hey look! a string',
u'list': [ 1, 2, 3 ],
u'emptyList': [],
u'subdict': { u'a': u'A' }
'dict': {
'value': 'hey look! a string',
'list': [ 1, 2, 3 ],
'emptyList': [],
'subdict': { 'a': 'A' }
},
u'list': [
{ u'b': u'B' },
{ u'c': u'C' },
'list': [
{ 'b': 'B' },
{ 'c': 'C' },
[ 4, 5, 6 ],
u'final string'
'final string'
]
})
self.assertEqual(len(resp), 4) # dict, list, status and version
self.assertIn(u'dict', resp)
self.assertIn(u'list', resp)
self.assertIn('dict', resp)
self.assertIn('list', resp)
d = resp[u'dict']
l = resp[u'list']
d = resp['dict']
l = resp['list']
self.assertIn(u'value', d)
self.assertIn(u'list', d)
self.assertIn('value', d)
self.assertIn('list', d)
self.assertNotIn('emptyList', d)
self.assertIn(u'subdict', d)
self.assertIsInstance(d[u'value'], basestring)
self.assertIsInstance(d[u'list'], list)
self.assertIsInstance(d[u'subdict'], dict)
self.assertIn('subdict', d)
self.assertIsInstance(d['value'], strtype)
self.assertIsInstance(d['list'], list)
self.assertIsInstance(d['subdict'], dict)
self.assertEqual(l, [
{ u'b': u'B' },
{ u'c': u'C' },
{ 'b': 'B' },
{ 'c': 'C' },
[ 4, 5, 6 ],
u'final string'
'final string'
])
class ResponseHelperJsonpTestCase(ResponseHelperBaseCase):
def test_basic(self):
result = self.helper.responsize_jsonp({}, u'callback')
self.assertTrue(result.startswith(u'callback({'))
self.assertTrue(result.endswith(u'})'))
result = self.helper.responsize_jsonp({}, 'callback')
self.assertTrue(result.startswith('callback({'))
self.assertTrue(result.endswith('})'))
json = simplejson.loads(result[9:-1])
self.assertIn(u'subsonic-response', json)
self.assertIn('subsonic-response', json)
class ResponseHelperXMLTestCase(ResponseHelperBaseCase):
def serialize_and_deserialize(self, d, error = False):
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)
return root
@ -137,80 +139,80 @@ class ResponseHelperXMLTestCase(ResponseHelperBaseCase):
def test_root(self):
xml = self.helper.responsize_xml({ 'tag': {}})
self.assertIn(u'<subsonic-response ', xml)
self.assertIn(u'xmlns="http://subsonic.org/restapi"', xml)
self.assertTrue(xml.strip().endswith(u'</subsonic-response>'))
self.assertIn('<subsonic-response ', xml)
self.assertIn('xmlns="http://subsonic.org/restapi"', xml)
self.assertTrue(xml.strip().endswith('</subsonic-response>'))
def test_basic(self):
empty = self.serialize_and_deserialize({})
self.assertIsNotNone(empty.find(u'.[@version]'))
self.assertIsNotNone(empty.find(u".[@status='ok']"))
self.assertIsNotNone(empty.find('.[@version]'))
self.assertIsNotNone(empty.find(".[@status='ok']"))
resp = self.serialize_and_deserialize({}, True)
self.assertIsNotNone(resp.find(u".[@status='failed']"))
self.assertIsNotNone(resp.find(".[@status='failed']"))
some_dict = {
u'intValue': 2,
u'someString': u'Hello world!'
'intValue': 2,
'someString': 'Hello world!'
}
resp = self.serialize_and_deserialize(some_dict)
self.assertIsNotNone(resp.find(u'.[@intValue]'))
self.assertIsNotNone(resp.find(u'.[@someString]'))
self.assertIsNotNone(resp.find('.[@intValue]'))
self.assertIsNotNone(resp.find('.[@someString]'))
def test_lists(self):
resp = self.serialize_and_deserialize({
u'someList': [ 2, 4, 8, 16 ],
u'emptyList': []
'someList': [ 2, 4, 8, 16 ],
'emptyList': []
})
elems = resp.findall(u'./someList')
elems = resp.findall('./someList')
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 ]):
self.assertEqual(int(e.text), i)
def test_dicts(self):
resp = self.serialize_and_deserialize({
u'dict': { u's': u'Blah', u'i': 20 },
u'empty': {}
'dict': { 's': 'Blah', 'i': 20 },
'empty': {}
})
d = resp.find(u'./dict')
d = resp.find('./dict')
self.assertIsNotNone(d)
self.assertIsNotNone(resp.find(u'./empty'))
self.assertAttributesMatchDict(d, { u's': u'Blah', u'i': 20 })
self.assertIsNotNone(resp.find('./empty'))
self.assertAttributesMatchDict(d, { 's': 'Blah', 'i': 20 })
def test_nesting(self):
resp = self.serialize_and_deserialize({
u'dict': {
u'value': u'hey look! a string',
u'list': [ 1, 2, 3 ],
u'emptyList': [],
u'subdict': { u'a': u'A' }
'dict': {
'value': 'hey look! a string',
'list': [ 1, 2, 3 ],
'emptyList': [],
'subdict': { 'a': 'A' }
},
u'list': [
{ u'b': u'B' },
{ u'c': u'C' },
u'final string'
'list': [
{ 'b': 'B' },
{ 'c': 'C' },
'final string'
]
})
self.assertEqual(len(resp), 4) # 'dict' and 3 'list's
d = resp.find(u'./dict')
lists = resp.findall(u'./list')
d = resp.find('./dict')
lists = resp.findall('./list')
self.assertIsNotNone(d)
self.assertAttributesMatchDict(d, { u'value': u'hey look! a string' })
self.assertEqual(len(d.findall(u'./list')), 3)
self.assertEqual(len(d.findall(u'./emptyList')), 0)
self.assertIsNotNone(d.find(u'./subdict'))
self.assertAttributesMatchDict(d, { 'value': 'hey look! a string' })
self.assertEqual(len(d.findall('./list')), 3)
self.assertEqual(len(d.findall('./emptyList')), 0)
self.assertIsNotNone(d.find('./subdict'))
self.assertEqual(len(lists), 3)
self.assertAttributesMatchDict(lists[0], { u'b': u'B' })
self.assertAttributesMatchDict(lists[1], { u'c': u'C' })
self.assertEqual(lists[2].text, u'final string')
self.assertAttributesMatchDict(lists[0], { 'b': 'B' })
self.assertAttributesMatchDict(lists[1], { 'c': 'C' })
self.assertEqual(lists[2].text, 'final string')
def suite():
suite = unittest.TestSuite()

View File

@ -11,6 +11,7 @@
import unittest
from supysonic.config import IniConfig
from supysonic.py23 import strtype
class ConfigTestCase(unittest.TestCase):
def test_sections(self):
@ -24,7 +25,7 @@ class ConfigTestCase(unittest.TestCase):
self.assertIsInstance(conf.TYPES['float'], float)
self.assertIsInstance(conf.TYPES['int'], int)
self.assertIsInstance(conf.TYPES['string'], basestring)
self.assertIsInstance(conf.TYPES['string'], strtype)
for t in ('bool', 'switch', 'yn'):
self.assertIsInstance(conf.BOOLEANS[t + '_false'], bool)

View File

@ -5,13 +5,14 @@
# This file is part of Supysonic.
# 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
#
# Distributed under terms of the GNU AGPLv3 license.
from supysonic import db
from supysonic.managers.folder import FolderManager
from supysonic.py23 import strtype
import os
import io
@ -153,7 +154,7 @@ class FolderManagerTestCase(unittest.TestCase):
FolderManager.INVALID_PATH, FolderManager.PATH_EXISTS, FolderManager.NO_SUCH_FOLDER,
FolderManager.SUBPATH_EXISTS, 1594826, 'string', uuid.uuid4() ]
for value in values:
self.assertIsInstance(FolderManager.error_str(value), basestring)
self.assertIsInstance(FolderManager.error_str(value), strtype)
if __name__ == '__main__':
unittest.main()

View File

@ -5,13 +5,14 @@
# This file is part of Supysonic.
# 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
#
# Distributed under terms of the GNU AGPLv3 license.
from supysonic import db
from supysonic.managers.user import UserManager
from supysonic.py23 import strtype
import io
import unittest
@ -180,7 +181,7 @@ class UserManagerTestCase(unittest.TestCase):
values = [ UserManager.SUCCESS, UserManager.INVALID_ID, UserManager.NO_SUCH_USER, UserManager.NAME_EXISTS,
UserManager.WRONG_PASS, 1594826, 'string', uuid.uuid4() ]
for value in values:
self.assertIsInstance(UserManager.error_str(value), basestring)
self.assertIsInstance(UserManager.error_str(value), strtype)
if __name__ == '__main__':
unittest.main()