aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md2
-rw-r--r--backend/zmusic/database.py37
-rw-r--r--backend/zmusic/endpoints/error.py2
-rw-r--r--backend/zmusic/endpoints/login.py2
-rw-r--r--backend/zmusic/endpoints/scan.py12
-rw-r--r--backend/zmusic/endpoints/zip.py73
-rw-r--r--backend/zmusic/login.py4
-rw-r--r--backend/zmusic/picard/file.py4
-rw-r--r--backend/zmusic/picard/formats/apev2.py6
-rw-r--r--backend/zmusic/picard/formats/asf.py4
-rw-r--r--backend/zmusic/picard/formats/id3.py22
-rw-r--r--backend/zmusic/picard/formats/mp4.py17
-rw-r--r--backend/zmusic/picard/formats/mutagenext/compatid3.py6
-rw-r--r--backend/zmusic/picard/formats/vorbis.py6
-rw-r--r--backend/zmusic/picard/metadata.py8
-rw-r--r--backend/zmusic/picard/util/__init__.py23
-rw-r--r--backend/zmusic/streams.py4
17 files changed, 104 insertions, 128 deletions
diff --git a/README.md b/README.md
index a290e6f..58f9e81 100644
--- a/README.md
+++ b/README.md
@@ -40,7 +40,7 @@ All frontend dependencies are included in the source.
* [Flask-Login](http://packages.python.org/Flask-Login/) (`pip install Flask-Login`)
* [Mutagen](https://code.google.com/p/mutagen/) (`pip install mutagen`)
* [ffmpeg](http://ffmpeg.org/) (`apt-get install ffmpeg`)
-* [Python](http://python.org/) >= 2.7 (`apt-get install python`)
+* [Python](http://python.org/) >= 3.4 (`apt-get install python`)
All backend dependencies must be present on system.
diff --git a/backend/zmusic/database.py b/backend/zmusic/database.py
index 6935a45..8050ab8 100644
--- a/backend/zmusic/database.py
+++ b/backend/zmusic/database.py
@@ -2,24 +2,15 @@ from zmusic import db
from uuid import uuid4
import time
-# This is indeed ugly, but it was suggested by the SQLAlchemy documention
-# verbatim as a way of dealing with str-centric apps.
-class CoerceUTF8(db.TypeDecorator):
- impl = db.Unicode
- def process_bind_param(self, value, dialect):
- if isinstance(value, str):
- value = value.decode('utf-8')
- return value
-
class Song(db.Model):
__tablename__ = 'songs'
- filename = db.Column(CoerceUTF8, primary_key=True)
- id = db.Column(CoerceUTF8, nullable=False, index=True)
- title = db.Column(CoerceUTF8)
- album = db.Column(CoerceUTF8)
- artist = db.Column(CoerceUTF8)
- mimetype = db.Column(CoerceUTF8)
+ filename = db.Column(db.Unicode, primary_key=True)
+ id = db.Column(db.Unicode, nullable=False, index=True)
+ title = db.Column(db.Unicode)
+ album = db.Column(db.Unicode)
+ artist = db.Column(db.Unicode)
+ mimetype = db.Column(db.Unicode)
year = db.Column(db.Integer)
track = db.Column(db.Integer)
disc = db.Column(db.Integer)
@@ -58,15 +49,15 @@ class Song(db.Model):
class Download(db.Model):
__tablename__ = 'downloads'
- id = db.Column(CoerceUTF8, primary_key=True)
- leader_id = db.Column(CoerceUTF8)
+ id = db.Column(db.Unicode, primary_key=True)
+ leader_id = db.Column(db.Unicode)
time = db.Column(db.Integer)
- ip = db.Column(CoerceUTF8, index=True)
- useragent = db.Column(CoerceUTF8)
- song_id = db.Column(CoerceUTF8, db.ForeignKey(Song.id))
- artist = db.Column(CoerceUTF8)
- album = db.Column(CoerceUTF8)
- title = db.Column(CoerceUTF8)
+ ip = db.Column(db.Unicode, index=True)
+ useragent = db.Column(db.Unicode)
+ song_id = db.Column(db.Unicode, db.ForeignKey(Song.id))
+ artist = db.Column(db.Unicode)
+ album = db.Column(db.Unicode)
+ title = db.Column(db.Unicode)
is_zip = db.Column(db.Boolean)
def __init__(self, song, request):
diff --git a/backend/zmusic/endpoints/error.py b/backend/zmusic/endpoints/error.py
index c356c3d..de43caf 100644
--- a/backend/zmusic/endpoints/error.py
+++ b/backend/zmusic/endpoints/error.py
@@ -9,5 +9,5 @@ def json_error(ex):
response.status_code = status_code
return response
-for code in default_exceptions.iterkeys():
+for code in default_exceptions.keys():
app.register_error_handler(code, json_error)
diff --git a/backend/zmusic/endpoints/login.py b/backend/zmusic/endpoints/login.py
index fdf481d..fd7cde2 100644
--- a/backend/zmusic/endpoints/login.py
+++ b/backend/zmusic/endpoints/login.py
@@ -16,7 +16,7 @@ def login():
@app.route('/login', methods=['GET'])
def login_check():
- response = jsonify(loggedin=current_user.is_authenticated())
+ response = jsonify(loggedin=current_user.is_authenticated)
response.cache_control.no_cache = True
return response
diff --git a/backend/zmusic/endpoints/scan.py b/backend/zmusic/endpoints/scan.py
index 275c7a8..d1a3078 100644
--- a/backend/zmusic/endpoints/scan.py
+++ b/backend/zmusic/endpoints/scan.py
@@ -14,11 +14,11 @@ def scan_music():
def do_scan():
yield "%i | Begin.\n" % int(time.time())
all_files = {}
- for root, dirs, files in os.walk(unicode(app.config["MUSIC_PATH"])):
+ for root, dirs, files in os.walk(app.config["MUSIC_PATH"]):
if len(files) != 0:
- yield "%i | Scanning [%s].\n" % (int(time.time()), encode_filename(root))
+ yield "%i | Scanning [%s].\n" % (int(time.time()), root)
for name in files:
- name = encode_filename(os.path.join(root, name))
+ name = os.path.join(root, name)
all_files[name] = True
song = Song.query.get(name)
if song != None:
@@ -36,14 +36,14 @@ def scan_music():
continue
song.sync_picard(tags)
db.session.add(song)
- yield "%i | Adding [%s].\n" % (int(time.time()), encode_filename(song.filename))
+ yield "%i | Adding [%s].\n" % (int(time.time()), song.filename)
for song in db.session.query(Song.filename):
if song.filename not in all_files:
Song.query.filter(Song.filename == song.filename).delete(False)
- yield "%i | Removing [%s].\n" % (int(time.time()), encode_filename(song.filename))
+ yield "%i | Removing [%s].\n" % (int(time.time()), song.filename)
db.session.commit()
yield "%i | Done.\n" % int(time.time())
- response = Response(do_scan(), mimetype="text/plain", direct_passthrough=True)
+ response = Response(do_scan(), mimetype="text/plain")
response.headers.add("X-Accel-Buffering", "no")
response.cache_control.no_cache = True
return response
diff --git a/backend/zmusic/endpoints/zip.py b/backend/zmusic/endpoints/zip.py
index e281f6f..d2e4d45 100644
--- a/backend/zmusic/endpoints/zip.py
+++ b/backend/zmusic/endpoints/zip.py
@@ -36,7 +36,7 @@ def zipfile():
db.session.commit()
def do_zip():
- central_directory = ""
+ central_directory = b""
offset = 0
count = 0
for song in songs:
@@ -48,12 +48,12 @@ def zipfile():
ext = ext[1:]
filename = generate_download_filename(song, ext)
file = open(song.filename, 'rb')
- yield "\x50\x4b\x03\x04" #local file header signature
- yield "\x14\x00" #version needed to extract
- yield "\x00\x00" #general purpose bit flag
- yield "\x00\x00" #compression method
- yield "\x00\x00" #last mod file time
- yield "\x00\x00" #last mod file date
+ yield b"\x50\x4b\x03\x04" #local file header signature
+ yield b"\x14\x00" #version needed to extract
+ yield b"\x00\x00" #general purpose bit flag
+ yield b"\x00\x00" #compression method
+ yield b"\x00\x00" #last mod file time
+ yield b"\x00\x00" #last mod file date
crc32 = 0
while True:
data = file.read(8192)
@@ -64,45 +64,46 @@ def zipfile():
crc32 = pack("<I", crc32 & 0xffffffff)
yield crc32 #crc-32
size = os.path.getsize(song.filename)
+ filename_encoded = filename.encode('utf-8')
yield pack("<I", size) #compressed size
- yield pack("<I", size) #uncompressed size
- yield pack("<H", len(filename)) #file name length
- yield "\x00\x00" #extra field length
- yield filename #file name
+ yield pack("<I", size) #uncompressed size
+ yield pack("<H", len(filename_encoded)) #file name length
+ yield b"\x00\x00" #extra field length
+ yield filename_encoded #file name
while True:
data = file.read(8192)
if not data:
break
- yield data #file data
- central_directory += "\x50\x4b\x01\x02"
- central_directory += "\x00\x00" #version made by
- central_directory += "\x14\x00" #version needed to extract
- central_directory += "\x00\x00" #gen purpose bit flag
- central_directory += "\x00\x00" #compression method
- central_directory += "\x00\x00" #last mod file time
- central_directory += "\x00\x00" #last mod file date
- central_directory += crc32 #crc-32
- central_directory += pack("<I", size) #compressed filesize
- central_directory += pack("<I", size) #uncompressed filesize
- central_directory += pack("<H", len(filename)) #length of filename
- central_directory += "\x00\x00" #extra field length
- central_directory += "\x00\x00" #file comment length
- central_directory += "\x00\x00" #disk number start
- central_directory += "\x00\x00" #internal file attributes
- central_directory += "\x20\x00\x00\x00" #external file attributes - 'archive' bit set (32)
- central_directory += pack("<I", offset) #relative offset of local header
- offset += 30 + len(filename) + size
- central_directory += filename
+ yield data #file data
+ central_directory += b"\x50\x4b\x01\x02"
+ central_directory += b"\x00\x00" #version made by
+ central_directory += b"\x14\x00" #version needed to extract
+ central_directory += b"\x00\x00" #gen purpose bit flag
+ central_directory += b"\x00\x00" #compression method
+ central_directory += b"\x00\x00" #last mod file time
+ central_directory += b"\x00\x00" #last mod file date
+ central_directory += crc32 #crc-32
+ central_directory += pack("<I", size) #compressed filesize
+ central_directory += pack("<I", size) #uncompressed filesize
+ central_directory += pack("<H", len(filename_encoded)) #length of filename
+ central_directory += b"\x00\x00" #extra field length
+ central_directory += b"\x00\x00" #file comment length
+ central_directory += b"\x00\x00" #disk number start
+ central_directory += b"\x00\x00" #internal file attributes
+ central_directory += b"\x20\x00\x00\x00" #external file attributes - 'archive' bit set (32)
+ central_directory += pack("<I", offset) #relative offset of local header
+ offset += 30 + len(filename_encoded) + size
+ central_directory += filename_encoded
file.close()
yield central_directory #central directory
- yield "\x50\x4b\x05\x06" #end of central directory signature
- yield "\x00\x00" #number of this disk
- yield "\x00\x00" #number of the disk with the start of the central directory
+ yield b"\x50\x4b\x05\x06" #end of central directory signature
+ yield b"\x00\x00" #number of this disk
+ yield b"\x00\x00" #number of the disk with the start of the central directory
yield pack("<H", count) #number of entries on disk
yield pack("<H", count) #number of entries
yield pack("<I", len(central_directory)) #size of central directory
yield pack("<I", offset) #offset to start of central directory
- yield "\x00\x00" #zip comment size
- response = Response(do_zip(), mimetype="application/zip", direct_passthrough=True)
+ yield b"\x00\x00" #zip comment size
+ response = Response(do_zip(), mimetype="application/zip")
response.headers.add('Content-Disposition', 'attachment', filename="ZX2C4Music-Download-" + str(int(time.time())) + ".zip")
return response
diff --git a/backend/zmusic/login.py b/backend/zmusic/login.py
index 6e7b270..18e471a 100644
--- a/backend/zmusic/login.py
+++ b/backend/zmusic/login.py
@@ -26,7 +26,7 @@ def unauthorized():
def login_required(fn):
@wraps(fn)
def decorated_view(*args, **kwargs):
- if query_is_admin_user(request.args) or query_is_music_user(request.args) or current_user.is_authenticated():
+ if query_is_admin_user(request.args) or query_is_music_user(request.args) or current_user.is_authenticated:
return fn(*args, **kwargs)
return app.login_manager.unauthorized()
return decorated_view
@@ -40,7 +40,7 @@ def admin_required(fn):
return decorated_view
def is_admin():
- return query_is_admin_user(request.args) or (current_user.is_authenticated() and current_user.admin)
+ return query_is_admin_user(request.args) or (current_user.is_authenticated and current_user.admin)
def query_is_music_user(query):
username = query.get("username", None)
diff --git a/backend/zmusic/picard/file.py b/backend/zmusic/picard/file.py
index 0e246eb..beb0dac 100644
--- a/backend/zmusic/picard/file.py
+++ b/backend/zmusic/picard/file.py
@@ -41,8 +41,8 @@ class File(dict, object):
self["length"] = file.info.length
- hash = hashlib.new("sha1")
- hash.update(str(metadata) + self["filename"])
+ hash = hashlib.new("sha256")
+ hash.update((str(metadata) + self["filename"]).encode('utf-8'))
self["id"] = hash.hexdigest()
def __missing__(self, key):
diff --git a/backend/zmusic/picard/formats/apev2.py b/backend/zmusic/picard/formats/apev2.py
index 15c4808..2a0c62e 100644
--- a/backend/zmusic/picard/formats/apev2.py
+++ b/backend/zmusic/picard/formats/apev2.py
@@ -22,7 +22,7 @@ import mutagen.monkeysaudio
import mutagen.musepack
import mutagen.wavpack
import mutagen.optimfrog
-import mutagenext.tak
+from zmusic.picard.formats.mutagenext import tak
from zmusic.picard.file import File
from zmusic.picard.metadata import Metadata
from zmusic.picard.util import encode_filename, sanitize_date, mimetype
@@ -46,7 +46,7 @@ class APEv2File(File):
"MUSICBRAINZ_ALBUMSTATUS": "releasestatus",
"MUSICBRAINZ_ALBUMTYPE": "releasetype",
}
- __rtranslate = dict([(v, k) for k, v in __translate.iteritems()])
+ __rtranslate = dict([(v, k) for k, v in __translate.items()])
def _load(self, filename):
self.log.debug("Loading file %r", filename)
@@ -200,7 +200,7 @@ class TAKFile(APEv2File):
"""TAK file."""
EXTENSIONS = [".tak"]
NAME = "Tom's lossless Audio Kompressor"
- _File = mutagenext.tak.TAK
+ _File = tak.TAK
def _info(self, metadata, file):
super(TAKFile, self)._info(metadata, file)
metadata['~format'] = self.NAME
diff --git a/backend/zmusic/picard/formats/asf.py b/backend/zmusic/picard/formats/asf.py
index 0be2c2a..ff2a3d6 100644
--- a/backend/zmusic/picard/formats/asf.py
+++ b/backend/zmusic/picard/formats/asf.py
@@ -136,9 +136,9 @@ class ASFFile(File):
continue
elif name == 'WM/SharedUserRating':
# Rating in WMA ranges from 0 to 99, normalize this to the range 0 to 5
- values[0] = int(round(int(unicode(values[0])) / 99.0 * (5 - 1)))
+ values[0] = int(round(int(str(values[0])) / 99.0 * (5 - 1)))
name = self.__RTRANS[name]
- values = filter(bool, map(unicode, values))
+ values = list(filter(bool, map(str, values)))
if values:
metadata[name] = values
self._info(metadata, file)
diff --git a/backend/zmusic/picard/formats/id3.py b/backend/zmusic/picard/formats/id3.py
index 8e955d5..b7185b8 100644
--- a/backend/zmusic/picard/formats/id3.py
+++ b/backend/zmusic/picard/formats/id3.py
@@ -25,7 +25,7 @@ from zmusic.picard.metadata import Metadata
from zmusic.picard.file import File
from zmusic.picard.formats.mutagenext import compatid3
from zmusic.picard.util import encode_filename, sanitize_date
-from urlparse import urlparse
+from urllib.parse import urlparse
# Ugly, but... I need to save the text in ISO-8859-1 even if it contains
@@ -104,7 +104,7 @@ class ID3File(File):
'TPUB': 'label',
'TLAN': 'language',
}
- __rtranslate = dict([(v, k) for k, v in __translate.iteritems()])
+ __rtranslate = dict([(v, k) for k, v in __translate.items()])
__translate_freetext = {
'MusicBrainz Artist Id': 'musicbrainz_artistid',
@@ -127,7 +127,7 @@ class ID3File(File):
'ASIN': 'asin',
'MusicMagic Fingerprint': 'musicip_fingerprint',
}
- __rtranslate_freetext = dict([(v, k) for k, v in __translate_freetext.iteritems()])
+ __rtranslate_freetext = dict([(v, k) for k, v in __translate_freetext.items()])
__tipl_roles = {
'engineer': 'engineer',
@@ -136,7 +136,7 @@ class ID3File(File):
'DJ-mix': 'djmixer',
'mix': 'mixer',
}
- __rtipl_roles = dict([(v, k) for k, v in __tipl_roles.iteritems()])
+ __rtipl_roles = dict([(v, k) for k, v in __tipl_roles.items()])
__other_supported_tags = ("discnumber", "tracknumber",
"totaldiscs", "totaltracks")
@@ -158,13 +158,13 @@ class ID3File(File):
if frameid.startswith('T'):
for text in frame.text:
if text:
- metadata.add(name, unicode(text))
+ metadata.add(name, str(text))
elif frameid == 'COMM':
for text in frame.text:
if text:
- metadata.add('%s:%s' % (name, frame.desc), unicode(text))
+ metadata.add('%s:%s' % (name, frame.desc), str(text))
else:
- metadata.add(name, unicode(frame))
+ metadata.add(name, str(frame))
elif frameid == "TMCL":
for role, name in frame.people:
if role or name:
@@ -179,14 +179,14 @@ class ID3File(File):
else:
name = str(frame.desc.lower())
for text in frame.text:
- metadata.add(name, unicode(text))
+ metadata.add(name, str(text))
elif frameid == 'USLT':
name = 'lyrics'
if frame.desc:
name += ':%s' % frame.desc
- metadata.add(name, unicode(frame.text))
+ metadata.add(name, str(frame.text))
elif frameid == 'UFID' and frame.owner == 'http://musicbrainz.org':
- metadata['musicbrainz_trackid'] = unicode(frame.data)
+ metadata['musicbrainz_trackid'] = str(frame.data)
elif frameid == 'TRCK':
value = frame.text[0].split('/')
if len(value) > 1:
@@ -204,7 +204,7 @@ class ID3File(File):
elif frameid == 'POPM':
# Rating in ID3 ranges from 0 to 255, normalize this to the range 0 to 5
if False:
- rating = unicode(int(round(frame.rating / 255.0 * (5 - 1))))
+ rating = str(int(round(frame.rating / 255.0 * (5 - 1))))
metadata.add('~rating', rating)
if 'date' in metadata:
diff --git a/backend/zmusic/picard/formats/mp4.py b/backend/zmusic/picard/formats/mp4.py
index 2d1763f..edb1822 100644
--- a/backend/zmusic/picard/formats/mp4.py
+++ b/backend/zmusic/picard/formats/mp4.py
@@ -48,19 +48,19 @@ class MP4File(File):
"tvsh": "show",
"purl": "podcasturl",
}
- __r_text_tags = dict([(v, k) for k, v in __text_tags.iteritems()])
+ __r_text_tags = dict([(v, k) for k, v in __text_tags.items()])
__bool_tags = {
"pcst": "podcast",
"cpil": "compilation",
"pgap": "gapless",
}
- __r_bool_tags = dict([(v, k) for k, v in __bool_tags.iteritems()])
+ __r_bool_tags = dict([(v, k) for k, v in __bool_tags.items()])
__int_tags = {
"tmpo": "bpm",
}
- __r_int_tags = dict([(v, k) for k, v in __int_tags.iteritems()])
+ __r_int_tags = dict([(v, k) for k, v in __int_tags.items()])
__freeform_tags = {
"----:com.apple.iTunes:MusicBrainz Track Id": "musicbrainz_trackid",
@@ -97,7 +97,7 @@ class MP4File(File):
"----:com.apple.iTunes:SCRIPT": "script",
"----:com.apple.iTunes:LANGUAGE": "language",
}
- __r_freeform_tags = dict([(v, k) for k, v in __freeform_tags.iteritems()])
+ __r_freeform_tags = dict([(v, k) for k, v in __freeform_tags.items()])
__other_supported_tags = ("discnumber", "tracknumber",
"totaldiscs", "totaltracks")
@@ -117,14 +117,12 @@ class MP4File(File):
metadata.add(self.__bool_tags[name], values and '1' or '0')
elif name in self.__int_tags:
for value in values:
- metadata.add(self.__int_tags[name], unicode(value))
+ metadata.add(self.__int_tags[name], str(value))
elif name in self.__freeform_tags:
for value in values:
- value = value.strip("\x00").decode("utf-8", "replace")
metadata.add(self.__freeform_tags[name], value)
elif name == "----:com.apple.iTunes:fingerprint":
for value in values:
- value = value.strip("\x00").decode("utf-8", "replace")
if value.startswith("MusicMagic Fingerprint"):
metadata.add("musicip_fingerprint", value[22:])
elif name == "trkn":
@@ -135,9 +133,9 @@ class MP4File(File):
metadata["totaldiscs"] = str(values[0][1])
elif name == "covr":
for value in values:
- if value.format == value.FORMAT_JPEG:
+ if value.imageformat == value.FORMAT_JPEG:
metadata.add_image("image/jpeg", value)
- elif value.format == value.FORMAT_PNG:
+ elif value.imageformat == value.FORMAT_PNG:
metadata.add_image("image/png", value)
self._info(metadata, file)
@@ -165,7 +163,6 @@ class MP4File(File):
except ValueError:
pass
elif name in self.__r_freeform_tags:
- values = [v.encode("utf-8") for v in values]
file.tags[self.__r_freeform_tags[name]] = values
elif name == "musicip_fingerprint":
file.tags["----:com.apple.iTunes:fingerprint"] = ["MusicMagic Fingerprint%s" % str(v) for v in values]
diff --git a/backend/zmusic/picard/formats/mutagenext/compatid3.py b/backend/zmusic/picard/formats/mutagenext/compatid3.py
index 8ca98a6..815106c 100644
--- a/backend/zmusic/picard/formats/mutagenext/compatid3.py
+++ b/backend/zmusic/picard/formats/mutagenext/compatid3.py
@@ -88,7 +88,7 @@ class CompatID3(ID3):
if not framedata:
try:
self.delete(filename)
- except EnvironmentError, err:
+ except EnvironmentError as err:
from errno import ENOENT
if err.errno != ENOENT: raise
return
@@ -98,7 +98,7 @@ class CompatID3(ID3):
if filename is None: filename = self.filename
try: f = open(filename, 'rb+')
- except IOError, err:
+ except IOError as err:
from errno import ENOENT
if err.errno != ENOENT: raise
f = open(filename, 'ab') # create, then reopen
@@ -126,7 +126,7 @@ class CompatID3(ID3):
try:
f.seek(-128, 2)
- except IOError, err:
+ except IOError as err:
from errno import EINVAL
if err.errno != EINVAL: raise
f.seek(0, 2) # ensure read won't get "TAG"
diff --git a/backend/zmusic/picard/formats/vorbis.py b/backend/zmusic/picard/formats/vorbis.py
index f52bf06..3b1b8b0 100644
--- a/backend/zmusic/picard/formats/vorbis.py
+++ b/backend/zmusic/picard/formats/vorbis.py
@@ -61,11 +61,11 @@ class VCommentFile(File):
elif name.startswith('rating'):
try: name, email = name.split(':', 1)
except ValueError: email = ''
- continue
+ continue
if email != self.config.setting['rating_user_email']:
continue
name = '~rating'
- value = unicode(int(round((float(value) * (5 - 1)))))
+ value = str(int(round((float(value) * (5 - 1)))))
elif name == "fingerprint" and value.startswith("MusicMagic Fingerprint"):
name = "musicip_fingerprint"
value = value[22:]
@@ -115,7 +115,7 @@ class VCommentFile(File):
name = 'rating:%s' % settings['rating_user_email']
else:
name = 'rating'
- value = unicode(float(value) / (settings['rating_steps'] - 1))
+ value = str(float(value) / (settings['rating_steps'] - 1))
# don't save private tags
elif name.startswith("~"):
continue
diff --git a/backend/zmusic/picard/metadata.py b/backend/zmusic/picard/metadata.py
index 5074edf..4d556a2 100644
--- a/backend/zmusic/picard/metadata.py
+++ b/backend/zmusic/picard/metadata.py
@@ -70,7 +70,7 @@ class Metadata(object):
values = self._items.get(name, None)
if values:
if len(values) > 1:
- return MULTI_VALUED_JOINER.join(values)
+ return MULTI_VALUED_JOINER.join(map(str, values))
else:
return values[0]
else:
@@ -109,8 +109,8 @@ class Metadata(object):
def keys(self):
return self._items.keys()
- def iteritems(self):
- for name, values in self._items.iteritems():
+ def items(self):
+ for name, values in self._items.items():
for value in values:
yield name, value
@@ -120,7 +120,7 @@ class Metadata(object):
>>> m.items()
[("key1", "value1"), ("key1", "value2"), ("key2", "value3")]
"""
- return list(self.iteritems())
+ return list(self.items())
def rawitems(self):
"""Returns the metadata items.
diff --git a/backend/zmusic/picard/util/__init__.py b/backend/zmusic/picard/util/__init__.py
index e0ad871..1b6d6cb 100644
--- a/backend/zmusic/picard/util/__init__.py
+++ b/backend/zmusic/picard/util/__init__.py
@@ -46,30 +46,17 @@ def asciipunct(s):
u"—": u"-",
u"―": u"--",
}
- for orig, repl in mapping.iteritems():
+ for orig, repl in mapping.items():
s = s.replace(orig, repl)
return s
-_io_encoding = sys.getfilesystemencoding()
-
def encode_filename(filename):
- """Encode unicode strings to filesystem encoding."""
- if isinstance(filename, unicode):
- if os.path.supports_unicode_filenames and sys.platform != "darwin":
- return filename
- else:
- return filename.encode(_io_encoding, 'replace')
- else:
- return filename
+ return filename
def decode_filename(filename):
- """Decode strings from filesystem encoding to unicode."""
- if isinstance(filename, unicode):
- return filename
- else:
- return filename.decode(_io_encoding)
+ return filename
def pathcmp(a, b):
return os.path.normcase(a) == os.path.normcase(b)
@@ -177,7 +164,7 @@ def make_short_filename(prefix, filename, max_path_length=240, max_length=200,
break
if left > 0:
- raise IOError, "File name is too long."
+ raise IOError("File name is too long.")
return os.path.join(*[a.strip() for a in reversed(parts)])
@@ -284,4 +271,4 @@ def load_release_type_scores(setting):
def save_release_type_scores(scores):
- return " ".join(["%s %.2f" % v for v in scores.iteritems()])
+ return " ".join(["%s %.2f" % v for v in scores.items()])
diff --git a/backend/zmusic/streams.py b/backend/zmusic/streams.py
index 3dca20d..c654155 100644
--- a/backend/zmusic/streams.py
+++ b/backend/zmusic/streams.py
@@ -20,7 +20,7 @@ class ProcessWrapper(object):
return self
def __del__(self):
self.close()
- def next(self):
+ def __next__(self):
try:
data = self.process.stdout.read(self.buffer_size)
except:
@@ -52,7 +52,7 @@ class PartialFileWrapper(object):
self.file.close()
def __iter__(self):
return self
- def next(self):
+ def __next__(self):
if self.length is not None:
if self.length <= 0:
raise StopIteration()