mirror of
https://github.com/beetbox/beets.git
synced 2025-12-06 16:42:42 +01:00
replace unicode with six.text_type
This commit is contained in:
parent
7b66dfec4b
commit
e8afcbe7ec
56 changed files with 269 additions and 203 deletions
|
|
@ -27,6 +27,7 @@ from beets.util import as_string
|
||||||
from beets.autotag import mb
|
from beets.autotag import mb
|
||||||
from jellyfish import levenshtein_distance
|
from jellyfish import levenshtein_distance
|
||||||
from unidecode import unidecode
|
from unidecode import unidecode
|
||||||
|
import six
|
||||||
|
|
||||||
log = logging.getLogger('beets')
|
log = logging.getLogger('beets')
|
||||||
|
|
||||||
|
|
@ -205,8 +206,8 @@ def _string_dist_basic(str1, str2):
|
||||||
transliteration/lowering to ASCII characters. Normalized by string
|
transliteration/lowering to ASCII characters. Normalized by string
|
||||||
length.
|
length.
|
||||||
"""
|
"""
|
||||||
assert isinstance(str1, unicode)
|
assert isinstance(str1, six.text_type)
|
||||||
assert isinstance(str2, unicode)
|
assert isinstance(str2, six.text_type)
|
||||||
str1 = as_string(unidecode(str1))
|
str1 = as_string(unidecode(str1))
|
||||||
str2 = as_string(unidecode(str2))
|
str2 = as_string(unidecode(str2))
|
||||||
str1 = re.sub(r'[^a-z0-9]', '', str1.lower())
|
str1 = re.sub(r'[^a-z0-9]', '', str1.lower())
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ import beets.autotag.hooks
|
||||||
import beets
|
import beets
|
||||||
from beets import util
|
from beets import util
|
||||||
from beets import config
|
from beets import config
|
||||||
|
import six
|
||||||
|
|
||||||
VARIOUS_ARTISTS_ID = '89ad4ac3-39f7-470e-963a-56509c546377'
|
VARIOUS_ARTISTS_ID = '89ad4ac3-39f7-470e-963a-56509c546377'
|
||||||
BASE_URL = 'http://musicbrainz.org/'
|
BASE_URL = 'http://musicbrainz.org/'
|
||||||
|
|
@ -69,7 +70,8 @@ def configure():
|
||||||
"""Set up the python-musicbrainz-ngs module according to settings
|
"""Set up the python-musicbrainz-ngs module according to settings
|
||||||
from the beets configuration. This should be called at startup.
|
from the beets configuration. This should be called at startup.
|
||||||
"""
|
"""
|
||||||
musicbrainzngs.set_hostname(config['musicbrainz']['host'].get(unicode))
|
hostname = config['musicbrainz']['host'].get(six.text_type)
|
||||||
|
musicbrainzngs.set_hostname(hostname)
|
||||||
musicbrainzngs.set_rate_limit(
|
musicbrainzngs.set_rate_limit(
|
||||||
config['musicbrainz']['ratelimit_interval'].as_number(),
|
config['musicbrainz']['ratelimit_interval'].as_number(),
|
||||||
config['musicbrainz']['ratelimit'].get(int),
|
config['musicbrainz']['ratelimit'].get(int),
|
||||||
|
|
@ -260,7 +262,7 @@ def album_info(release):
|
||||||
)
|
)
|
||||||
info.va = info.artist_id == VARIOUS_ARTISTS_ID
|
info.va = info.artist_id == VARIOUS_ARTISTS_ID
|
||||||
if info.va:
|
if info.va:
|
||||||
info.artist = config['va_name'].get(unicode)
|
info.artist = config['va_name'].get(six.text_type)
|
||||||
info.asin = release.get('asin')
|
info.asin = release.get('asin')
|
||||||
info.releasegroup_id = release['release-group']['id']
|
info.releasegroup_id = release['release-group']['id']
|
||||||
info.country = release.get('country')
|
info.country = release.get('country')
|
||||||
|
|
@ -329,7 +331,7 @@ def match_album(artist, album, tracks=None):
|
||||||
# Various Artists search.
|
# Various Artists search.
|
||||||
criteria['arid'] = VARIOUS_ARTISTS_ID
|
criteria['arid'] = VARIOUS_ARTISTS_ID
|
||||||
if tracks is not None:
|
if tracks is not None:
|
||||||
criteria['tracks'] = unicode(tracks)
|
criteria['tracks'] = six.text_type(tracks)
|
||||||
|
|
||||||
# Abort if we have no search terms.
|
# Abort if we have no search terms.
|
||||||
if not any(criteria.itervalues()):
|
if not any(criteria.itervalues()):
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ import beets
|
||||||
from beets.util.functemplate import Template
|
from beets.util.functemplate import Template
|
||||||
from beets.dbcore import types
|
from beets.dbcore import types
|
||||||
from .query import MatchQuery, NullSort, TrueQuery
|
from .query import MatchQuery, NullSort, TrueQuery
|
||||||
|
import six
|
||||||
|
|
||||||
|
|
||||||
class FormattedMapping(collections.Mapping):
|
class FormattedMapping(collections.Mapping):
|
||||||
|
|
@ -69,7 +70,7 @@ class FormattedMapping(collections.Mapping):
|
||||||
value = value.decode('utf8', 'ignore')
|
value = value.decode('utf8', 'ignore')
|
||||||
|
|
||||||
if self.for_path:
|
if self.for_path:
|
||||||
sep_repl = beets.config['path_sep_replace'].get(unicode)
|
sep_repl = beets.config['path_sep_replace'].get(six.text_type)
|
||||||
for sep in (os.path.sep, os.path.altsep):
|
for sep in (os.path.sep, os.path.altsep):
|
||||||
if sep:
|
if sep:
|
||||||
value = value.replace(sep, sep_repl)
|
value = value.replace(sep, sep_repl)
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ from beets import util
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
import unicodedata
|
import unicodedata
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
|
import six
|
||||||
|
|
||||||
|
|
||||||
class ParsingError(ValueError):
|
class ParsingError(ValueError):
|
||||||
|
|
@ -246,8 +247,8 @@ class BytesQuery(MatchQuery):
|
||||||
# Use a buffer representation of the pattern for SQLite
|
# Use a buffer representation of the pattern for SQLite
|
||||||
# matching. This instructs SQLite to treat the blob as binary
|
# matching. This instructs SQLite to treat the blob as binary
|
||||||
# rather than encoded Unicode.
|
# rather than encoded Unicode.
|
||||||
if isinstance(self.pattern, (unicode, bytes)):
|
if isinstance(self.pattern, (six.text_type, bytes)):
|
||||||
if isinstance(self.pattern, unicode):
|
if isinstance(self.pattern, six.text_type):
|
||||||
self.pattern = self.pattern.encode('utf8')
|
self.pattern = self.pattern.encode('utf8')
|
||||||
self.buf_pattern = buffer(self.pattern)
|
self.buf_pattern = buffer(self.pattern)
|
||||||
elif isinstance(self.pattern, buffer):
|
elif isinstance(self.pattern, buffer):
|
||||||
|
|
@ -793,7 +794,7 @@ class FieldSort(Sort):
|
||||||
|
|
||||||
def key(item):
|
def key(item):
|
||||||
field_val = item.get(self.field, '')
|
field_val = item.get(self.field, '')
|
||||||
if self.case_insensitive and isinstance(field_val, unicode):
|
if self.case_insensitive and isinstance(field_val, six.text_type):
|
||||||
field_val = field_val.lower()
|
field_val = field_val.lower()
|
||||||
return field_val
|
return field_val
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ from __future__ import division, absolute_import, print_function
|
||||||
|
|
||||||
from . import query
|
from . import query
|
||||||
from beets.util import str2bool
|
from beets.util import str2bool
|
||||||
|
import six
|
||||||
|
|
||||||
|
|
||||||
# Abstract base.
|
# Abstract base.
|
||||||
|
|
@ -37,7 +38,7 @@ class Type(object):
|
||||||
"""The `Query` subclass to be used when querying the field.
|
"""The `Query` subclass to be used when querying the field.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
model_type = unicode
|
model_type = six.text_type
|
||||||
"""The Python type that is used to represent the value in the model.
|
"""The Python type that is used to represent the value in the model.
|
||||||
|
|
||||||
The model is guaranteed to return a value of this type if the field
|
The model is guaranteed to return a value of this type if the field
|
||||||
|
|
@ -63,7 +64,7 @@ class Type(object):
|
||||||
if isinstance(value, bytes):
|
if isinstance(value, bytes):
|
||||||
value = value.decode('utf8', 'ignore')
|
value = value.decode('utf8', 'ignore')
|
||||||
|
|
||||||
return unicode(value)
|
return six.text_type(value)
|
||||||
|
|
||||||
def parse(self, string):
|
def parse(self, string):
|
||||||
"""Parse a (possibly human-written) string and return the
|
"""Parse a (possibly human-written) string and return the
|
||||||
|
|
@ -102,7 +103,7 @@ class Type(object):
|
||||||
"""
|
"""
|
||||||
if isinstance(sql_value, buffer):
|
if isinstance(sql_value, buffer):
|
||||||
sql_value = bytes(sql_value).decode('utf8', 'ignore')
|
sql_value = bytes(sql_value).decode('utf8', 'ignore')
|
||||||
if isinstance(sql_value, unicode):
|
if isinstance(sql_value, six.text_type):
|
||||||
return self.parse(sql_value)
|
return self.parse(sql_value)
|
||||||
else:
|
else:
|
||||||
return self.normalize(sql_value)
|
return self.normalize(sql_value)
|
||||||
|
|
@ -194,7 +195,7 @@ class Boolean(Type):
|
||||||
model_type = bool
|
model_type = bool
|
||||||
|
|
||||||
def format(self, value):
|
def format(self, value):
|
||||||
return unicode(bool(value))
|
return six.text_type(bool(value))
|
||||||
|
|
||||||
def parse(self, string):
|
def parse(self, string):
|
||||||
return str2bool(string)
|
return str2bool(string)
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
# included in all copies or substantial portions of the Software.
|
# included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
from __future__ import division, absolute_import, print_function
|
from __future__ import division, absolute_import, print_function
|
||||||
|
import six
|
||||||
|
|
||||||
"""Provides the basic, interface-agnostic workflow for importing and
|
"""Provides the basic, interface-agnostic workflow for importing and
|
||||||
autotagging music files.
|
autotagging music files.
|
||||||
|
|
@ -640,7 +641,7 @@ class ImportTask(BaseImportTask):
|
||||||
changes['comp'] = False
|
changes['comp'] = False
|
||||||
else:
|
else:
|
||||||
# VA.
|
# VA.
|
||||||
changes['albumartist'] = config['va_name'].get(unicode)
|
changes['albumartist'] = config['va_name'].get(six.text_type)
|
||||||
changes['comp'] = True
|
changes['comp'] = True
|
||||||
|
|
||||||
elif self.choice_flag in (action.APPLY, action.RETAG):
|
elif self.choice_flag in (action.APPLY, action.RETAG):
|
||||||
|
|
|
||||||
|
|
@ -124,14 +124,15 @@ class DateType(types.Float):
|
||||||
query = dbcore.query.DateQuery
|
query = dbcore.query.DateQuery
|
||||||
|
|
||||||
def format(self, value):
|
def format(self, value):
|
||||||
return time.strftime(beets.config['time_format'].get(unicode),
|
return time.strftime(beets.config['time_format'].get(six.text_type),
|
||||||
time.localtime(value or 0))
|
time.localtime(value or 0))
|
||||||
|
|
||||||
def parse(self, string):
|
def parse(self, string):
|
||||||
try:
|
try:
|
||||||
# Try a formatted date string.
|
# Try a formatted date string.
|
||||||
return time.mktime(
|
return time.mktime(
|
||||||
time.strptime(string, beets.config['time_format'].get(unicode))
|
time.strptime(string,
|
||||||
|
beets.config['time_format'].get(six.text_type))
|
||||||
)
|
)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
# Fall back to a plain timestamp number.
|
# Fall back to a plain timestamp number.
|
||||||
|
|
@ -153,7 +154,7 @@ class PathType(types.Type):
|
||||||
return normpath(bytestring_path(string))
|
return normpath(bytestring_path(string))
|
||||||
|
|
||||||
def normalize(self, value):
|
def normalize(self, value):
|
||||||
if isinstance(value, unicode):
|
if isinstance(value, six.text_type):
|
||||||
# Paths stored internally as encoded bytes.
|
# Paths stored internally as encoded bytes.
|
||||||
return bytestring_path(value)
|
return bytestring_path(value)
|
||||||
|
|
||||||
|
|
@ -281,11 +282,11 @@ class FileOperationError(Exception):
|
||||||
"""
|
"""
|
||||||
return u'{0}: {1}'.format(
|
return u'{0}: {1}'.format(
|
||||||
util.displayable_path(self.path),
|
util.displayable_path(self.path),
|
||||||
unicode(self.reason)
|
six.text_type(self.reason)
|
||||||
)
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return unicode(self).encode('utf8')
|
return six.text_type(self).encode('utf8')
|
||||||
|
|
||||||
|
|
||||||
class ReadError(FileOperationError):
|
class ReadError(FileOperationError):
|
||||||
|
|
@ -331,7 +332,7 @@ class LibModel(dbcore.Model):
|
||||||
|
|
||||||
def __format__(self, spec):
|
def __format__(self, spec):
|
||||||
if not spec:
|
if not spec:
|
||||||
spec = beets.config[self._format_config_key].get(unicode)
|
spec = beets.config[self._format_config_key].get(six.text_type)
|
||||||
result = self.evaluate_template(spec)
|
result = self.evaluate_template(spec)
|
||||||
if isinstance(spec, bytes):
|
if isinstance(spec, bytes):
|
||||||
# if spec is a byte string then we must return a one as well
|
# if spec is a byte string then we must return a one as well
|
||||||
|
|
@ -517,7 +518,7 @@ class Item(LibModel):
|
||||||
"""
|
"""
|
||||||
# Encode unicode paths and read buffers.
|
# Encode unicode paths and read buffers.
|
||||||
if key == 'path':
|
if key == 'path':
|
||||||
if isinstance(value, unicode):
|
if isinstance(value, six.text_type):
|
||||||
value = bytestring_path(value)
|
value = bytestring_path(value)
|
||||||
elif isinstance(value, buffer):
|
elif isinstance(value, buffer):
|
||||||
value = bytes(value)
|
value = bytes(value)
|
||||||
|
|
@ -1061,7 +1062,8 @@ class Album(LibModel):
|
||||||
image = bytestring_path(image)
|
image = bytestring_path(image)
|
||||||
item_dir = item_dir or self.item_dir()
|
item_dir = item_dir or self.item_dir()
|
||||||
|
|
||||||
filename_tmpl = Template(beets.config['art_filename'].get(unicode))
|
filename_tmpl = Template(
|
||||||
|
beets.config['art_filename'].get(six.text_type))
|
||||||
subpath = self.evaluate_template(filename_tmpl, True)
|
subpath = self.evaluate_template(filename_tmpl, True)
|
||||||
if beets.config['asciify_paths']:
|
if beets.config['asciify_paths']:
|
||||||
subpath = unidecode(subpath)
|
subpath = unidecode(subpath)
|
||||||
|
|
@ -1179,7 +1181,8 @@ def parse_query_string(s, model_cls):
|
||||||
|
|
||||||
The string is split into components using shell-like syntax.
|
The string is split into components using shell-like syntax.
|
||||||
"""
|
"""
|
||||||
assert isinstance(s, unicode), u"Query is not unicode: {0!r}".format(s)
|
message = u"Query is not unicode: {0!r}".format(s)
|
||||||
|
assert isinstance(s, six.text_type), message
|
||||||
try:
|
try:
|
||||||
parts = util.shlex_split(s)
|
parts = util.shlex_split(s)
|
||||||
except ValueError as exc:
|
except ValueError as exc:
|
||||||
|
|
@ -1405,7 +1408,7 @@ class DefaultTemplateFunctions(object):
|
||||||
def tmpl_time(s, fmt):
|
def tmpl_time(s, fmt):
|
||||||
"""Format a time value using `strftime`.
|
"""Format a time value using `strftime`.
|
||||||
"""
|
"""
|
||||||
cur_fmt = beets.config['time_format'].get(unicode)
|
cur_fmt = beets.config['time_format'].get(six.text_type)
|
||||||
return time.strftime(fmt, time.strptime(s, cur_fmt))
|
return time.strftime(fmt, time.strptime(s, cur_fmt))
|
||||||
|
|
||||||
def tmpl_aunique(self, keys=None, disam=None):
|
def tmpl_aunique(self, keys=None, disam=None):
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ from copy import copy
|
||||||
from logging import * # noqa
|
from logging import * # noqa
|
||||||
import subprocess
|
import subprocess
|
||||||
import threading
|
import threading
|
||||||
|
import six
|
||||||
|
|
||||||
|
|
||||||
def logsafe(val):
|
def logsafe(val):
|
||||||
|
|
@ -42,7 +43,7 @@ def logsafe(val):
|
||||||
example.
|
example.
|
||||||
"""
|
"""
|
||||||
# Already Unicode.
|
# Already Unicode.
|
||||||
if isinstance(val, unicode):
|
if isinstance(val, six.text_type):
|
||||||
return val
|
return val
|
||||||
|
|
||||||
# Bytestring: needs decoding.
|
# Bytestring: needs decoding.
|
||||||
|
|
@ -56,7 +57,7 @@ def logsafe(val):
|
||||||
# A "problem" object: needs a workaround.
|
# A "problem" object: needs a workaround.
|
||||||
elif isinstance(val, subprocess.CalledProcessError):
|
elif isinstance(val, subprocess.CalledProcessError):
|
||||||
try:
|
try:
|
||||||
return unicode(val)
|
return six.text_type(val)
|
||||||
except UnicodeDecodeError:
|
except UnicodeDecodeError:
|
||||||
# An object with a broken __unicode__ formatter. Use __str__
|
# An object with a broken __unicode__ formatter. Use __str__
|
||||||
# instead.
|
# instead.
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,7 @@ import enum
|
||||||
|
|
||||||
from beets import logging
|
from beets import logging
|
||||||
from beets.util import displayable_path, syspath, as_string
|
from beets.util import displayable_path, syspath, as_string
|
||||||
|
import six
|
||||||
|
|
||||||
|
|
||||||
__all__ = ['UnreadableFileError', 'FileTypeError', 'MediaFile']
|
__all__ = ['UnreadableFileError', 'FileTypeError', 'MediaFile']
|
||||||
|
|
@ -131,7 +132,7 @@ def _safe_cast(out_type, val):
|
||||||
else:
|
else:
|
||||||
# Process any other type as a string.
|
# Process any other type as a string.
|
||||||
if not isinstance(val, basestring):
|
if not isinstance(val, basestring):
|
||||||
val = unicode(val)
|
val = six.text_type(val)
|
||||||
# Get a number from the front of the string.
|
# Get a number from the front of the string.
|
||||||
val = re.match(r'[0-9]*', val.strip()).group(0)
|
val = re.match(r'[0-9]*', val.strip()).group(0)
|
||||||
if not val:
|
if not val:
|
||||||
|
|
@ -146,13 +147,13 @@ def _safe_cast(out_type, val):
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
elif out_type == unicode:
|
elif out_type == six.text_type:
|
||||||
if isinstance(val, bytes):
|
if isinstance(val, bytes):
|
||||||
return val.decode('utf8', 'ignore')
|
return val.decode('utf8', 'ignore')
|
||||||
elif isinstance(val, unicode):
|
elif isinstance(val, six.text_type):
|
||||||
return val
|
return val
|
||||||
else:
|
else:
|
||||||
return unicode(val)
|
return six.text_type(val)
|
||||||
|
|
||||||
elif out_type == float:
|
elif out_type == float:
|
||||||
if isinstance(val, int) or isinstance(val, float):
|
if isinstance(val, int) or isinstance(val, float):
|
||||||
|
|
@ -161,7 +162,7 @@ def _safe_cast(out_type, val):
|
||||||
if isinstance(val, bytes):
|
if isinstance(val, bytes):
|
||||||
val = val.decode('utf8', 'ignore')
|
val = val.decode('utf8', 'ignore')
|
||||||
else:
|
else:
|
||||||
val = unicode(val)
|
val = six.text_type(val)
|
||||||
match = re.match(r'[\+-]?([0-9]+\.?[0-9]*|[0-9]*\.[0-9]+)',
|
match = re.match(r'[\+-]?([0-9]+\.?[0-9]*|[0-9]*\.[0-9]+)',
|
||||||
val.strip())
|
val.strip())
|
||||||
if match:
|
if match:
|
||||||
|
|
@ -220,7 +221,7 @@ def _sc_decode(soundcheck):
|
||||||
"""
|
"""
|
||||||
# We decode binary data. If one of the formats gives us a text
|
# We decode binary data. If one of the formats gives us a text
|
||||||
# string, interpret it as UTF-8.
|
# string, interpret it as UTF-8.
|
||||||
if isinstance(soundcheck, unicode):
|
if isinstance(soundcheck, six.text_type):
|
||||||
soundcheck = soundcheck.encode('utf8')
|
soundcheck = soundcheck.encode('utf8')
|
||||||
|
|
||||||
# SoundCheck tags consist of 10 numbers, each represented by 8
|
# SoundCheck tags consist of 10 numbers, each represented by 8
|
||||||
|
|
@ -407,7 +408,8 @@ class StorageStyle(object):
|
||||||
"""List of mutagen classes the StorageStyle can handle.
|
"""List of mutagen classes the StorageStyle can handle.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, key, as_type=unicode, suffix=None, float_places=2):
|
def __init__(self, key, as_type=six.text_type, suffix=None,
|
||||||
|
float_places=2):
|
||||||
"""Create a basic storage strategy. Parameters:
|
"""Create a basic storage strategy. Parameters:
|
||||||
|
|
||||||
- `key`: The key on the Mutagen file object used to access the
|
- `key`: The key on the Mutagen file object used to access the
|
||||||
|
|
@ -426,8 +428,8 @@ class StorageStyle(object):
|
||||||
self.float_places = float_places
|
self.float_places = float_places
|
||||||
|
|
||||||
# Convert suffix to correct string type.
|
# Convert suffix to correct string type.
|
||||||
if self.suffix and self.as_type is unicode \
|
if self.suffix and self.as_type is six.text_type \
|
||||||
and not isinstance(self.suffix, unicode):
|
and not isinstance(self.suffix, six.text_type):
|
||||||
self.suffix = self.suffix.decode('utf8')
|
self.suffix = self.suffix.decode('utf8')
|
||||||
|
|
||||||
# Getter.
|
# Getter.
|
||||||
|
|
@ -450,7 +452,7 @@ class StorageStyle(object):
|
||||||
"""Given a raw value stored on a Mutagen object, decode and
|
"""Given a raw value stored on a Mutagen object, decode and
|
||||||
return the represented value.
|
return the represented value.
|
||||||
"""
|
"""
|
||||||
if self.suffix and isinstance(mutagen_value, unicode) \
|
if self.suffix and isinstance(mutagen_value, six.text_type) \
|
||||||
and mutagen_value.endswith(self.suffix):
|
and mutagen_value.endswith(self.suffix):
|
||||||
return mutagen_value[:-len(self.suffix)]
|
return mutagen_value[:-len(self.suffix)]
|
||||||
else:
|
else:
|
||||||
|
|
@ -472,17 +474,17 @@ class StorageStyle(object):
|
||||||
"""Convert the external Python value to a type that is suitable for
|
"""Convert the external Python value to a type that is suitable for
|
||||||
storing in a Mutagen file object.
|
storing in a Mutagen file object.
|
||||||
"""
|
"""
|
||||||
if isinstance(value, float) and self.as_type is unicode:
|
if isinstance(value, float) and self.as_type is six.text_type:
|
||||||
value = u'{0:.{1}f}'.format(value, self.float_places)
|
value = u'{0:.{1}f}'.format(value, self.float_places)
|
||||||
value = self.as_type(value)
|
value = self.as_type(value)
|
||||||
elif self.as_type is unicode:
|
elif self.as_type is six.text_type:
|
||||||
if isinstance(value, bool):
|
if isinstance(value, bool):
|
||||||
# Store bools as 1/0 instead of True/False.
|
# Store bools as 1/0 instead of True/False.
|
||||||
value = unicode(int(bool(value)))
|
value = six.text_type(int(bool(value)))
|
||||||
elif isinstance(value, bytes):
|
elif isinstance(value, bytes):
|
||||||
value = value.decode('utf8', 'ignore')
|
value = value.decode('utf8', 'ignore')
|
||||||
else:
|
else:
|
||||||
value = unicode(value)
|
value = six.text_type(value)
|
||||||
else:
|
else:
|
||||||
value = self.as_type(value)
|
value = self.as_type(value)
|
||||||
|
|
||||||
|
|
@ -592,7 +594,7 @@ class MP4StorageStyle(StorageStyle):
|
||||||
|
|
||||||
def serialize(self, value):
|
def serialize(self, value):
|
||||||
value = super(MP4StorageStyle, self).serialize(value)
|
value = super(MP4StorageStyle, self).serialize(value)
|
||||||
if self.key.startswith('----:') and isinstance(value, unicode):
|
if self.key.startswith('----:') and isinstance(value, six.text_type):
|
||||||
value = value.encode('utf8')
|
value = value.encode('utf8')
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
@ -807,7 +809,7 @@ class MP3SlashPackStorageStyle(MP3StorageStyle):
|
||||||
def _fetch_unpacked(self, mutagen_file):
|
def _fetch_unpacked(self, mutagen_file):
|
||||||
data = self.fetch(mutagen_file)
|
data = self.fetch(mutagen_file)
|
||||||
if data:
|
if data:
|
||||||
items = unicode(data).split('/')
|
items = six.text_type(data).split('/')
|
||||||
else:
|
else:
|
||||||
items = []
|
items = []
|
||||||
packing_length = 2
|
packing_length = 2
|
||||||
|
|
@ -823,7 +825,7 @@ class MP3SlashPackStorageStyle(MP3StorageStyle):
|
||||||
items[0] = ''
|
items[0] = ''
|
||||||
if items[1] is None:
|
if items[1] is None:
|
||||||
items.pop() # Do not store last value
|
items.pop() # Do not store last value
|
||||||
self.store(mutagen_file, '/'.join(map(unicode, items)))
|
self.store(mutagen_file, '/'.join(map(six.text_type, items)))
|
||||||
|
|
||||||
def delete(self, mutagen_file):
|
def delete(self, mutagen_file):
|
||||||
if self.pack_pos == 0:
|
if self.pack_pos == 0:
|
||||||
|
|
@ -1074,7 +1076,7 @@ class MediaField(object):
|
||||||
getting this property.
|
getting this property.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
self.out_type = kwargs.get('out_type', unicode)
|
self.out_type = kwargs.get('out_type', six.text_type)
|
||||||
self._styles = styles
|
self._styles = styles
|
||||||
|
|
||||||
def styles(self, mutagen_file):
|
def styles(self, mutagen_file):
|
||||||
|
|
@ -1113,7 +1115,7 @@ class MediaField(object):
|
||||||
return 0.0
|
return 0.0
|
||||||
elif self.out_type == bool:
|
elif self.out_type == bool:
|
||||||
return False
|
return False
|
||||||
elif self.out_type == unicode:
|
elif self.out_type == six.text_type:
|
||||||
return u''
|
return u''
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1195,8 +1197,8 @@ class DateField(MediaField):
|
||||||
# Get the underlying data and split on hyphens and slashes.
|
# Get the underlying data and split on hyphens and slashes.
|
||||||
datestring = super(DateField, self).__get__(mediafile, None)
|
datestring = super(DateField, self).__get__(mediafile, None)
|
||||||
if isinstance(datestring, basestring):
|
if isinstance(datestring, basestring):
|
||||||
datestring = re.sub(r'[Tt ].*$', '', unicode(datestring))
|
datestring = re.sub(r'[Tt ].*$', '', six.text_type(datestring))
|
||||||
items = re.split('[-/]', unicode(datestring))
|
items = re.split('[-/]', six.text_type(datestring))
|
||||||
else:
|
else:
|
||||||
items = []
|
items = []
|
||||||
|
|
||||||
|
|
@ -1233,7 +1235,7 @@ class DateField(MediaField):
|
||||||
date.append(u'{0:02d}'.format(int(month)))
|
date.append(u'{0:02d}'.format(int(month)))
|
||||||
if month and day:
|
if month and day:
|
||||||
date.append(u'{0:02d}'.format(int(day)))
|
date.append(u'{0:02d}'.format(int(day)))
|
||||||
date = map(unicode, date)
|
date = map(six.text_type, date)
|
||||||
super(DateField, self).__set__(mediafile, u'-'.join(date))
|
super(DateField, self).__set__(mediafile, u'-'.join(date))
|
||||||
|
|
||||||
if hasattr(self, '_year_field'):
|
if hasattr(self, '_year_field'):
|
||||||
|
|
@ -1360,7 +1362,7 @@ class MediaFile(object):
|
||||||
try:
|
try:
|
||||||
self.mgfile = mutagen.File(path)
|
self.mgfile = mutagen.File(path)
|
||||||
except unreadable_exc as exc:
|
except unreadable_exc as exc:
|
||||||
log.debug(u'header parsing failed: {0}', unicode(exc))
|
log.debug(u'header parsing failed: {0}', six.text_type(exc))
|
||||||
raise UnreadableFileError(path)
|
raise UnreadableFileError(path)
|
||||||
except IOError as exc:
|
except IOError as exc:
|
||||||
if type(exc) == IOError:
|
if type(exc) == IOError:
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ from beets import config
|
||||||
from beets.util import confit, as_string
|
from beets.util import confit, as_string
|
||||||
from beets.autotag import mb
|
from beets.autotag import mb
|
||||||
from beets.dbcore import query as db_query
|
from beets.dbcore import query as db_query
|
||||||
|
import six
|
||||||
|
|
||||||
# On Windows platforms, use colorama to support "ANSI" terminal colors.
|
# On Windows platforms, use colorama to support "ANSI" terminal colors.
|
||||||
if sys.platform == 'win32':
|
if sys.platform == 'win32':
|
||||||
|
|
@ -140,7 +141,7 @@ def print_(*strings, **kwargs):
|
||||||
"""
|
"""
|
||||||
end = kwargs.get('end')
|
end = kwargs.get('end')
|
||||||
|
|
||||||
if not strings or isinstance(strings[0], unicode):
|
if not strings or isinstance(strings[0], six.text_type):
|
||||||
txt = u' '.join(strings)
|
txt = u' '.join(strings)
|
||||||
txt += u'\n' if end is None else end
|
txt += u'\n' if end is None else end
|
||||||
else:
|
else:
|
||||||
|
|
@ -148,7 +149,7 @@ def print_(*strings, **kwargs):
|
||||||
txt += b'\n' if end is None else end
|
txt += b'\n' if end is None else end
|
||||||
|
|
||||||
# Always send bytes to the stdout stream.
|
# Always send bytes to the stdout stream.
|
||||||
if isinstance(txt, unicode):
|
if isinstance(txt, six.text_type):
|
||||||
txt = txt.encode(_out_encoding(), 'replace')
|
txt = txt.encode(_out_encoding(), 'replace')
|
||||||
|
|
||||||
sys.stdout.write(txt)
|
sys.stdout.write(txt)
|
||||||
|
|
@ -298,11 +299,11 @@ def input_options(options, require=False, prompt=None, fallback_prompt=None,
|
||||||
prompt_part_lengths = []
|
prompt_part_lengths = []
|
||||||
if numrange:
|
if numrange:
|
||||||
if isinstance(default, int):
|
if isinstance(default, int):
|
||||||
default_name = unicode(default)
|
default_name = six.text_type(default)
|
||||||
default_name = colorize('action_default', default_name)
|
default_name = colorize('action_default', default_name)
|
||||||
tmpl = '# selection (default %s)'
|
tmpl = '# selection (default %s)'
|
||||||
prompt_parts.append(tmpl % default_name)
|
prompt_parts.append(tmpl % default_name)
|
||||||
prompt_part_lengths.append(len(tmpl % unicode(default)))
|
prompt_part_lengths.append(len(tmpl % six.text_type(default)))
|
||||||
else:
|
else:
|
||||||
prompt_parts.append('# selection')
|
prompt_parts.append('# selection')
|
||||||
prompt_part_lengths.append(len(prompt_parts[-1]))
|
prompt_part_lengths.append(len(prompt_parts[-1]))
|
||||||
|
|
@ -522,7 +523,8 @@ def colorize(color_name, text):
|
||||||
if config['ui']['color']:
|
if config['ui']['color']:
|
||||||
global COLORS
|
global COLORS
|
||||||
if not COLORS:
|
if not COLORS:
|
||||||
COLORS = dict((name, config['ui']['colors'][name].get(unicode))
|
COLORS = dict((name,
|
||||||
|
config['ui']['colors'][name].get(six.text_type))
|
||||||
for name in COLOR_NAMES)
|
for name in COLOR_NAMES)
|
||||||
# In case a 3rd party plugin is still passing the actual color ('red')
|
# In case a 3rd party plugin is still passing the actual color ('red')
|
||||||
# instead of the abstract color name ('text_error')
|
# instead of the abstract color name ('text_error')
|
||||||
|
|
@ -544,8 +546,8 @@ def _colordiff(a, b, highlight='text_highlight',
|
||||||
"""
|
"""
|
||||||
if not isinstance(a, basestring) or not isinstance(b, basestring):
|
if not isinstance(a, basestring) or not isinstance(b, basestring):
|
||||||
# Non-strings: use ordinary equality.
|
# Non-strings: use ordinary equality.
|
||||||
a = unicode(a)
|
a = six.text_type(a)
|
||||||
b = unicode(b)
|
b = six.text_type(b)
|
||||||
if a == b:
|
if a == b:
|
||||||
return a, b
|
return a, b
|
||||||
else:
|
else:
|
||||||
|
|
@ -593,7 +595,7 @@ def colordiff(a, b, highlight='text_highlight'):
|
||||||
if config['ui']['color']:
|
if config['ui']['color']:
|
||||||
return _colordiff(a, b, highlight)
|
return _colordiff(a, b, highlight)
|
||||||
else:
|
else:
|
||||||
return unicode(a), unicode(b)
|
return six.text_type(a), six.text_type(b)
|
||||||
|
|
||||||
|
|
||||||
def get_path_formats(subview=None):
|
def get_path_formats(subview=None):
|
||||||
|
|
@ -604,7 +606,7 @@ def get_path_formats(subview=None):
|
||||||
subview = subview or config['paths']
|
subview = subview or config['paths']
|
||||||
for query, view in subview.items():
|
for query, view in subview.items():
|
||||||
query = PF_KEY_QUERIES.get(query, query) # Expand common queries.
|
query = PF_KEY_QUERIES.get(query, query) # Expand common queries.
|
||||||
path_formats.append((query, Template(view.get(unicode))))
|
path_formats.append((query, Template(view.get(six.text_type))))
|
||||||
return path_formats
|
return path_formats
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ from beets import library
|
||||||
from beets import config
|
from beets import config
|
||||||
from beets import logging
|
from beets import logging
|
||||||
from beets.util.confit import _package_path
|
from beets.util.confit import _package_path
|
||||||
|
import six
|
||||||
|
|
||||||
VARIOUS_ARTISTS = u'Various Artists'
|
VARIOUS_ARTISTS = u'Various Artists'
|
||||||
PromptChoice = namedtuple('ExtraChoice', ['short', 'long', 'callback'])
|
PromptChoice = namedtuple('ExtraChoice', ['short', 'long', 'callback'])
|
||||||
|
|
@ -163,7 +164,7 @@ def disambig_string(info):
|
||||||
else:
|
else:
|
||||||
disambig.append(info.media)
|
disambig.append(info.media)
|
||||||
if info.year:
|
if info.year:
|
||||||
disambig.append(unicode(info.year))
|
disambig.append(six.text_type(info.year))
|
||||||
if info.country:
|
if info.country:
|
||||||
disambig.append(info.country)
|
disambig.append(info.country)
|
||||||
if info.label:
|
if info.label:
|
||||||
|
|
@ -236,9 +237,9 @@ def show_change(cur_artist, cur_album, match):
|
||||||
if mediums > 1:
|
if mediums > 1:
|
||||||
return u'{0}-{1}'.format(medium, medium_index)
|
return u'{0}-{1}'.format(medium, medium_index)
|
||||||
else:
|
else:
|
||||||
return unicode(medium_index)
|
return six.text_type(medium_index)
|
||||||
else:
|
else:
|
||||||
return unicode(index)
|
return six.text_type(index)
|
||||||
|
|
||||||
# Identify the album in question.
|
# Identify the album in question.
|
||||||
if cur_artist != match.info.artist or \
|
if cur_artist != match.info.artist or \
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ import subprocess
|
||||||
import platform
|
import platform
|
||||||
import shlex
|
import shlex
|
||||||
from beets.util import hidden
|
from beets.util import hidden
|
||||||
|
import six
|
||||||
|
|
||||||
|
|
||||||
MAX_FILENAME_LENGTH = 200
|
MAX_FILENAME_LENGTH = 200
|
||||||
|
|
@ -65,14 +66,14 @@ class HumanReadableException(Exception):
|
||||||
|
|
||||||
def _reasonstr(self):
|
def _reasonstr(self):
|
||||||
"""Get the reason as a string."""
|
"""Get the reason as a string."""
|
||||||
if isinstance(self.reason, unicode):
|
if isinstance(self.reason, six.text_type):
|
||||||
return self.reason
|
return self.reason
|
||||||
elif isinstance(self.reason, bytes):
|
elif isinstance(self.reason, bytes):
|
||||||
return self.reason.decode('utf8', 'ignore')
|
return self.reason.decode('utf8', 'ignore')
|
||||||
elif hasattr(self.reason, 'strerror'): # i.e., EnvironmentError
|
elif hasattr(self.reason, 'strerror'): # i.e., EnvironmentError
|
||||||
return self.reason.strerror
|
return self.reason.strerror
|
||||||
else:
|
else:
|
||||||
return u'"{0}"'.format(unicode(self.reason))
|
return u'"{0}"'.format(six.text_type(self.reason))
|
||||||
|
|
||||||
def get_message(self):
|
def get_message(self):
|
||||||
"""Create the human-readable description of the error, sans
|
"""Create the human-readable description of the error, sans
|
||||||
|
|
@ -346,11 +347,11 @@ def displayable_path(path, separator=u'; '):
|
||||||
"""
|
"""
|
||||||
if isinstance(path, (list, tuple)):
|
if isinstance(path, (list, tuple)):
|
||||||
return separator.join(displayable_path(p) for p in path)
|
return separator.join(displayable_path(p) for p in path)
|
||||||
elif isinstance(path, unicode):
|
elif isinstance(path, six.text_type):
|
||||||
return path
|
return path
|
||||||
elif not isinstance(path, bytes):
|
elif not isinstance(path, bytes):
|
||||||
# A non-string object: just get its unicode representation.
|
# A non-string object: just get its unicode representation.
|
||||||
return unicode(path)
|
return six.text_type(path)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return path.decode(_fsencoding(), 'ignore')
|
return path.decode(_fsencoding(), 'ignore')
|
||||||
|
|
@ -369,7 +370,7 @@ def syspath(path, prefix=True):
|
||||||
if os.path.__name__ != 'ntpath':
|
if os.path.__name__ != 'ntpath':
|
||||||
return path
|
return path
|
||||||
|
|
||||||
if not isinstance(path, unicode):
|
if not isinstance(path, six.text_type):
|
||||||
# Beets currently represents Windows paths internally with UTF-8
|
# Beets currently represents Windows paths internally with UTF-8
|
||||||
# arbitrarily. But earlier versions used MBCS because it is
|
# arbitrarily. But earlier versions used MBCS because it is
|
||||||
# reported as the FS encoding by Windows. Try both.
|
# reported as the FS encoding by Windows. Try both.
|
||||||
|
|
@ -639,7 +640,7 @@ def as_string(value):
|
||||||
elif isinstance(value, bytes):
|
elif isinstance(value, bytes):
|
||||||
return value.decode('utf8', 'ignore')
|
return value.decode('utf8', 'ignore')
|
||||||
else:
|
else:
|
||||||
return unicode(value)
|
return six.text_type(value)
|
||||||
|
|
||||||
|
|
||||||
def plurality(objs):
|
def plurality(objs):
|
||||||
|
|
@ -765,7 +766,7 @@ def shlex_split(s):
|
||||||
# Shlex works fine.
|
# Shlex works fine.
|
||||||
return shlex.split(s)
|
return shlex.split(s)
|
||||||
|
|
||||||
elif isinstance(s, unicode):
|
elif isinstance(s, six.text_type):
|
||||||
# Work around a Python bug.
|
# Work around a Python bug.
|
||||||
# http://bugs.python.org/issue6988
|
# http://bugs.python.org/issue6988
|
||||||
bs = s.encode('utf8')
|
bs = s.encode('utf8')
|
||||||
|
|
@ -801,7 +802,7 @@ def _windows_long_path_name(short_path):
|
||||||
"""Use Windows' `GetLongPathNameW` via ctypes to get the canonical,
|
"""Use Windows' `GetLongPathNameW` via ctypes to get the canonical,
|
||||||
long path given a short filename.
|
long path given a short filename.
|
||||||
"""
|
"""
|
||||||
if not isinstance(short_path, unicode):
|
if not isinstance(short_path, six.text_type):
|
||||||
short_path = short_path.decode(_fsencoding())
|
short_path = short_path.decode(_fsencoding())
|
||||||
|
|
||||||
import ctypes
|
import ctypes
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ import yaml
|
||||||
import collections
|
import collections
|
||||||
import re
|
import re
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
import six
|
||||||
|
|
||||||
UNIX_DIR_VAR = 'XDG_CONFIG_HOME'
|
UNIX_DIR_VAR = 'XDG_CONFIG_HOME'
|
||||||
UNIX_DIR_FALLBACK = '~/.config'
|
UNIX_DIR_FALLBACK = '~/.config'
|
||||||
|
|
@ -44,7 +45,7 @@ REDACTED_TOMBSTONE = 'REDACTED'
|
||||||
# Utilities.
|
# Utilities.
|
||||||
|
|
||||||
PY3 = sys.version_info[0] == 3
|
PY3 = sys.version_info[0] == 3
|
||||||
STRING = str if PY3 else unicode # noqa
|
STRING = str if PY3 else six.text_type # noqa
|
||||||
BASESTRING = str if PY3 else basestring # noqa
|
BASESTRING = str if PY3 else basestring # noqa
|
||||||
NUMERIC_TYPES = (int, float) if PY3 else (int, float, long) # noqa
|
NUMERIC_TYPES = (int, float) if PY3 else (int, float, long) # noqa
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ import dis
|
||||||
import types
|
import types
|
||||||
|
|
||||||
from .confit import NUMERIC_TYPES
|
from .confit import NUMERIC_TYPES
|
||||||
|
import six
|
||||||
|
|
||||||
SYMBOL_DELIM = u'$'
|
SYMBOL_DELIM = u'$'
|
||||||
FUNC_DELIM = u'%'
|
FUNC_DELIM = u'%'
|
||||||
|
|
@ -190,8 +191,8 @@ class Call(object):
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
# Function raised exception! Maybe inlining the name of
|
# Function raised exception! Maybe inlining the name of
|
||||||
# the exception will help debug.
|
# the exception will help debug.
|
||||||
return u'<%s>' % unicode(exc)
|
return u'<%s>' % six.text_type(exc)
|
||||||
return unicode(out)
|
return six.text_type(out)
|
||||||
else:
|
else:
|
||||||
return self.original
|
return self.original
|
||||||
|
|
||||||
|
|
@ -246,7 +247,7 @@ class Expression(object):
|
||||||
out.append(part)
|
out.append(part)
|
||||||
else:
|
else:
|
||||||
out.append(part.evaluate(env))
|
out.append(part.evaluate(env))
|
||||||
return u''.join(map(unicode, out))
|
return u''.join(map(six.text_type, out))
|
||||||
|
|
||||||
def translate(self):
|
def translate(self):
|
||||||
"""Compile the expression to a list of Python AST expressions, a
|
"""Compile the expression to a list of Python AST expressions, a
|
||||||
|
|
@ -563,7 +564,7 @@ if __name__ == '__main__':
|
||||||
import timeit
|
import timeit
|
||||||
_tmpl = Template(u'foo $bar %baz{foozle $bar barzle} $bar')
|
_tmpl = Template(u'foo $bar %baz{foozle $bar barzle} $bar')
|
||||||
_vars = {'bar': 'qux'}
|
_vars = {'bar': 'qux'}
|
||||||
_funcs = {'baz': unicode.upper}
|
_funcs = {'baz': six.text_type.upper}
|
||||||
interp_time = timeit.timeit('_tmpl.interpret(_vars, _funcs)',
|
interp_time = timeit.timeit('_tmpl.interpret(_vars, _funcs)',
|
||||||
'from __main__ import _tmpl, _vars, _funcs',
|
'from __main__ import _tmpl, _vars, _funcs',
|
||||||
number=10000)
|
number=10000)
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import os
|
||||||
import stat
|
import stat
|
||||||
import ctypes
|
import ctypes
|
||||||
import sys
|
import sys
|
||||||
|
import six
|
||||||
|
|
||||||
|
|
||||||
def _is_hidden_osx(path):
|
def _is_hidden_osx(path):
|
||||||
|
|
@ -74,7 +75,7 @@ def is_hidden(path):
|
||||||
work out if a file is hidden.
|
work out if a file is hidden.
|
||||||
"""
|
"""
|
||||||
# Convert the path to unicode if it is not already.
|
# Convert the path to unicode if it is not already.
|
||||||
if not isinstance(path, unicode):
|
if not isinstance(path, six.text_type):
|
||||||
path = path.decode('utf-8')
|
path = path.decode('utf-8')
|
||||||
|
|
||||||
# Run platform specific functions depending on the platform
|
# Run platform specific functions depending on the platform
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ import shlex
|
||||||
import os
|
import os
|
||||||
import errno
|
import errno
|
||||||
import sys
|
import sys
|
||||||
|
import six
|
||||||
|
|
||||||
|
|
||||||
class BadFiles(BeetsPlugin):
|
class BadFiles(BeetsPlugin):
|
||||||
|
|
@ -97,7 +98,7 @@ class BadFiles(BeetsPlugin):
|
||||||
if not checker:
|
if not checker:
|
||||||
continue
|
continue
|
||||||
path = item.path
|
path = item.path
|
||||||
if not isinstance(path, unicode):
|
if not isinstance(path, six.text_type):
|
||||||
path = item.path.decode(sys.getfilesystemencoding())
|
path = item.path.decode(sys.getfilesystemencoding())
|
||||||
status, errors, output = checker(path)
|
status, errors, output = checker(path)
|
||||||
if status > 0:
|
if status > 0:
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ from __future__ import division, absolute_import, print_function
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
|
import six
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
from requests_oauthlib import OAuth1Session
|
from requests_oauthlib import OAuth1Session
|
||||||
|
|
@ -42,15 +43,15 @@ class BeatportAPIError(Exception):
|
||||||
class BeatportObject(object):
|
class BeatportObject(object):
|
||||||
def __init__(self, data):
|
def __init__(self, data):
|
||||||
self.beatport_id = data['id']
|
self.beatport_id = data['id']
|
||||||
self.name = unicode(data['name'])
|
self.name = six.text_type(data['name'])
|
||||||
if 'releaseDate' in data:
|
if 'releaseDate' in data:
|
||||||
self.release_date = datetime.strptime(data['releaseDate'],
|
self.release_date = datetime.strptime(data['releaseDate'],
|
||||||
'%Y-%m-%d')
|
'%Y-%m-%d')
|
||||||
if 'artists' in data:
|
if 'artists' in data:
|
||||||
self.artists = [(x['id'], unicode(x['name']))
|
self.artists = [(x['id'], six.text_type(x['name']))
|
||||||
for x in data['artists']]
|
for x in data['artists']]
|
||||||
if 'genres' in data:
|
if 'genres' in data:
|
||||||
self.genres = [unicode(x['name'])
|
self.genres = [six.text_type(x['name'])
|
||||||
for x in data['genres']]
|
for x in data['genres']]
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -209,7 +210,7 @@ class BeatportRelease(BeatportObject):
|
||||||
)
|
)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return unicode(self).encode('utf8')
|
return six.text_type(self).encode('utf8')
|
||||||
|
|
||||||
def __init__(self, data):
|
def __init__(self, data):
|
||||||
BeatportObject.__init__(self, data)
|
BeatportObject.__init__(self, data)
|
||||||
|
|
@ -231,14 +232,14 @@ class BeatportTrack(BeatportObject):
|
||||||
.format(artist_str, self.name, self.mix_name))
|
.format(artist_str, self.name, self.mix_name))
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return unicode(self).encode('utf8')
|
return six.text_type(self).encode('utf8')
|
||||||
|
|
||||||
def __init__(self, data):
|
def __init__(self, data):
|
||||||
BeatportObject.__init__(self, data)
|
BeatportObject.__init__(self, data)
|
||||||
if 'title' in data:
|
if 'title' in data:
|
||||||
self.title = unicode(data['title'])
|
self.title = six.text_type(data['title'])
|
||||||
if 'mixName' in data:
|
if 'mixName' in data:
|
||||||
self.mix_name = unicode(data['mixName'])
|
self.mix_name = six.text_type(data['mixName'])
|
||||||
self.length = timedelta(milliseconds=data.get('lengthMs', 0) or 0)
|
self.length = timedelta(milliseconds=data.get('lengthMs', 0) or 0)
|
||||||
if not self.length:
|
if not self.length:
|
||||||
try:
|
try:
|
||||||
|
|
@ -266,8 +267,8 @@ class BeatportPlugin(BeetsPlugin):
|
||||||
self.register_listener('import_begin', self.setup)
|
self.register_listener('import_begin', self.setup)
|
||||||
|
|
||||||
def setup(self, session=None):
|
def setup(self, session=None):
|
||||||
c_key = self.config['apikey'].get(unicode)
|
c_key = self.config['apikey'].get(six.text_type)
|
||||||
c_secret = self.config['apisecret'].get(unicode)
|
c_secret = self.config['apisecret'].get(six.text_type)
|
||||||
|
|
||||||
# Get the OAuth token from a file or log in.
|
# Get the OAuth token from a file or log in.
|
||||||
try:
|
try:
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ from beets.util import bluelet
|
||||||
from beets.library import Item
|
from beets.library import Item
|
||||||
from beets import dbcore
|
from beets import dbcore
|
||||||
from beets.mediafile import MediaFile
|
from beets.mediafile import MediaFile
|
||||||
|
import six
|
||||||
|
|
||||||
PROTOCOL_VERSION = '0.13.0'
|
PROTOCOL_VERSION = '0.13.0'
|
||||||
BUFSIZE = 1024
|
BUFSIZE = 1024
|
||||||
|
|
@ -305,12 +306,12 @@ class BaseServer(object):
|
||||||
playlist, playlistlength, and xfade.
|
playlist, playlistlength, and xfade.
|
||||||
"""
|
"""
|
||||||
yield (
|
yield (
|
||||||
u'volume: ' + unicode(self.volume),
|
u'volume: ' + six.text_type(self.volume),
|
||||||
u'repeat: ' + unicode(int(self.repeat)),
|
u'repeat: ' + six.text_type(int(self.repeat)),
|
||||||
u'random: ' + unicode(int(self.random)),
|
u'random: ' + six.text_type(int(self.random)),
|
||||||
u'playlist: ' + unicode(self.playlist_version),
|
u'playlist: ' + six.text_type(self.playlist_version),
|
||||||
u'playlistlength: ' + unicode(len(self.playlist)),
|
u'playlistlength: ' + six.text_type(len(self.playlist)),
|
||||||
u'xfade: ' + unicode(self.crossfade),
|
u'xfade: ' + six.text_type(self.crossfade),
|
||||||
)
|
)
|
||||||
|
|
||||||
if self.current_index == -1:
|
if self.current_index == -1:
|
||||||
|
|
@ -323,8 +324,8 @@ class BaseServer(object):
|
||||||
|
|
||||||
if self.current_index != -1: # i.e., paused or playing
|
if self.current_index != -1: # i.e., paused or playing
|
||||||
current_id = self._item_id(self.playlist[self.current_index])
|
current_id = self._item_id(self.playlist[self.current_index])
|
||||||
yield u'song: ' + unicode(self.current_index)
|
yield u'song: ' + six.text_type(self.current_index)
|
||||||
yield u'songid: ' + unicode(current_id)
|
yield u'songid: ' + six.text_type(current_id)
|
||||||
|
|
||||||
if self.error:
|
if self.error:
|
||||||
yield u'error: ' + self.error
|
yield u'error: ' + self.error
|
||||||
|
|
@ -468,8 +469,8 @@ class BaseServer(object):
|
||||||
Also a dummy implementation.
|
Also a dummy implementation.
|
||||||
"""
|
"""
|
||||||
for idx, track in enumerate(self.playlist):
|
for idx, track in enumerate(self.playlist):
|
||||||
yield u'cpos: ' + unicode(idx)
|
yield u'cpos: ' + six.text_type(idx)
|
||||||
yield u'Id: ' + unicode(track.id)
|
yield u'Id: ' + six.text_type(track.id)
|
||||||
|
|
||||||
def cmd_currentsong(self, conn):
|
def cmd_currentsong(self, conn):
|
||||||
"""Sends information about the currently-playing song.
|
"""Sends information about the currently-playing song.
|
||||||
|
|
@ -573,7 +574,7 @@ class Connection(object):
|
||||||
lines = [lines]
|
lines = [lines]
|
||||||
out = NEWLINE.join(lines) + NEWLINE
|
out = NEWLINE.join(lines) + NEWLINE
|
||||||
log.debug('{}', out[:-1]) # Don't log trailing newline.
|
log.debug('{}', out[:-1]) # Don't log trailing newline.
|
||||||
if isinstance(out, unicode):
|
if isinstance(out, six.text_type):
|
||||||
out = out.encode('utf8')
|
out = out.encode('utf8')
|
||||||
return self.sock.sendall(out)
|
return self.sock.sendall(out)
|
||||||
|
|
||||||
|
|
@ -771,28 +772,28 @@ class Server(BaseServer):
|
||||||
def _item_info(self, item):
|
def _item_info(self, item):
|
||||||
info_lines = [
|
info_lines = [
|
||||||
u'file: ' + item.destination(fragment=True),
|
u'file: ' + item.destination(fragment=True),
|
||||||
u'Time: ' + unicode(int(item.length)),
|
u'Time: ' + six.text_type(int(item.length)),
|
||||||
u'Title: ' + item.title,
|
u'Title: ' + item.title,
|
||||||
u'Artist: ' + item.artist,
|
u'Artist: ' + item.artist,
|
||||||
u'Album: ' + item.album,
|
u'Album: ' + item.album,
|
||||||
u'Genre: ' + item.genre,
|
u'Genre: ' + item.genre,
|
||||||
]
|
]
|
||||||
|
|
||||||
track = unicode(item.track)
|
track = six.text_type(item.track)
|
||||||
if item.tracktotal:
|
if item.tracktotal:
|
||||||
track += u'/' + unicode(item.tracktotal)
|
track += u'/' + six.text_type(item.tracktotal)
|
||||||
info_lines.append(u'Track: ' + track)
|
info_lines.append(u'Track: ' + track)
|
||||||
|
|
||||||
info_lines.append(u'Date: ' + unicode(item.year))
|
info_lines.append(u'Date: ' + six.text_type(item.year))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
pos = self._id_to_index(item.id)
|
pos = self._id_to_index(item.id)
|
||||||
info_lines.append(u'Pos: ' + unicode(pos))
|
info_lines.append(u'Pos: ' + six.text_type(pos))
|
||||||
except ArgumentNotFoundError:
|
except ArgumentNotFoundError:
|
||||||
# Don't include position if not in playlist.
|
# Don't include position if not in playlist.
|
||||||
pass
|
pass
|
||||||
|
|
||||||
info_lines.append(u'Id: ' + unicode(item.id))
|
info_lines.append(u'Id: ' + six.text_type(item.id))
|
||||||
|
|
||||||
return info_lines
|
return info_lines
|
||||||
|
|
||||||
|
|
@ -917,7 +918,7 @@ class Server(BaseServer):
|
||||||
for item in self._all_items(self._resolve_path(path)):
|
for item in self._all_items(self._resolve_path(path)):
|
||||||
self.playlist.append(item)
|
self.playlist.append(item)
|
||||||
if send_id:
|
if send_id:
|
||||||
yield u'Id: ' + unicode(item.id)
|
yield u'Id: ' + six.text_type(item.id)
|
||||||
self.playlist_version += 1
|
self.playlist_version += 1
|
||||||
|
|
||||||
def cmd_add(self, conn, path):
|
def cmd_add(self, conn, path):
|
||||||
|
|
@ -938,11 +939,11 @@ class Server(BaseServer):
|
||||||
if self.current_index > -1:
|
if self.current_index > -1:
|
||||||
item = self.playlist[self.current_index]
|
item = self.playlist[self.current_index]
|
||||||
|
|
||||||
yield u'bitrate: ' + unicode(item.bitrate / 1000)
|
yield u'bitrate: ' + six.text_type(item.bitrate / 1000)
|
||||||
# Missing 'audio'.
|
# Missing 'audio'.
|
||||||
|
|
||||||
(pos, total) = self.player.time()
|
(pos, total) = self.player.time()
|
||||||
yield u'time: ' + unicode(pos) + u':' + unicode(total)
|
yield u'time: ' + six.text_type(pos) + u':' + six.text_type(total)
|
||||||
|
|
||||||
# Also missing 'updating_db'.
|
# Also missing 'updating_db'.
|
||||||
|
|
||||||
|
|
@ -957,13 +958,13 @@ class Server(BaseServer):
|
||||||
artists, albums, songs, totaltime = tx.query(statement)[0]
|
artists, albums, songs, totaltime = tx.query(statement)[0]
|
||||||
|
|
||||||
yield (
|
yield (
|
||||||
u'artists: ' + unicode(artists),
|
u'artists: ' + six.text_type(artists),
|
||||||
u'albums: ' + unicode(albums),
|
u'albums: ' + six.text_type(albums),
|
||||||
u'songs: ' + unicode(songs),
|
u'songs: ' + six.text_type(songs),
|
||||||
u'uptime: ' + unicode(int(time.time() - self.startup_time)),
|
u'uptime: ' + six.text_type(int(time.time() - self.startup_time)),
|
||||||
u'playtime: ' + u'0', # Missing.
|
u'playtime: ' + u'0', # Missing.
|
||||||
u'db_playtime: ' + unicode(int(totaltime)),
|
u'db_playtime: ' + six.text_type(int(totaltime)),
|
||||||
u'db_update: ' + unicode(int(self.updated_time)),
|
u'db_update: ' + six.text_type(int(self.updated_time)),
|
||||||
)
|
)
|
||||||
|
|
||||||
# Searching.
|
# Searching.
|
||||||
|
|
@ -1059,7 +1060,7 @@ class Server(BaseServer):
|
||||||
rows = tx.query(statement, subvals)
|
rows = tx.query(statement, subvals)
|
||||||
|
|
||||||
for row in rows:
|
for row in rows:
|
||||||
yield show_tag_canon + u': ' + unicode(row[0])
|
yield show_tag_canon + u': ' + six.text_type(row[0])
|
||||||
|
|
||||||
def cmd_count(self, conn, tag, value):
|
def cmd_count(self, conn, tag, value):
|
||||||
"""Returns the number and total time of songs matching the
|
"""Returns the number and total time of songs matching the
|
||||||
|
|
@ -1071,8 +1072,8 @@ class Server(BaseServer):
|
||||||
for item in self.lib.items(dbcore.query.MatchQuery(key, value)):
|
for item in self.lib.items(dbcore.query.MatchQuery(key, value)):
|
||||||
songs += 1
|
songs += 1
|
||||||
playtime += item.length
|
playtime += item.length
|
||||||
yield u'songs: ' + unicode(songs)
|
yield u'songs: ' + six.text_type(songs)
|
||||||
yield u'playtime: ' + unicode(int(playtime))
|
yield u'playtime: ' + six.text_type(int(playtime))
|
||||||
|
|
||||||
# "Outputs." Just a dummy implementation because we don't control
|
# "Outputs." Just a dummy implementation because we don't control
|
||||||
# any outputs.
|
# any outputs.
|
||||||
|
|
@ -1180,11 +1181,12 @@ class BPDPlugin(BeetsPlugin):
|
||||||
)
|
)
|
||||||
|
|
||||||
def func(lib, opts, args):
|
def func(lib, opts, args):
|
||||||
host = args.pop(0) if args else self.config['host'].get(unicode)
|
host = self.config['host'].get(six.text_type)
|
||||||
|
host = args.pop(0) if args else host
|
||||||
port = args.pop(0) if args else self.config['port'].get(int)
|
port = args.pop(0) if args else self.config['port'].get(int)
|
||||||
if args:
|
if args:
|
||||||
raise beets.ui.UserError(u'too many arguments')
|
raise beets.ui.UserError(u'too many arguments')
|
||||||
password = self.config['password'].get(unicode)
|
password = self.config['password'].get(six.text_type)
|
||||||
volume = self.config['volume'].get(int)
|
volume = self.config['volume'].get(int)
|
||||||
debug = opts.debug or False
|
debug = opts.debug or False
|
||||||
self.start_bpd(lib, host, int(port), password, volume, debug)
|
self.start_bpd(lib, host, int(port), password, volume, debug)
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ music player.
|
||||||
|
|
||||||
from __future__ import division, absolute_import, print_function
|
from __future__ import division, absolute_import, print_function
|
||||||
|
|
||||||
|
import six
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
from six.moves import _thread
|
from six.moves import _thread
|
||||||
|
|
@ -128,7 +129,7 @@ class GstPlayer(object):
|
||||||
path.
|
path.
|
||||||
"""
|
"""
|
||||||
self.player.set_state(Gst.State.NULL)
|
self.player.set_state(Gst.State.NULL)
|
||||||
if isinstance(path, unicode):
|
if isinstance(path, six.text_type):
|
||||||
path = path.encode('utf8')
|
path = path.encode('utf8')
|
||||||
uri = 'file://' + urllib.parse.quote(path)
|
uri = 'file://' + urllib.parse.quote(path)
|
||||||
self.player.set_property("uri", uri)
|
self.player.set_property("uri", uri)
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ from beets.util import confit
|
||||||
from beets.autotag import hooks
|
from beets.autotag import hooks
|
||||||
import acoustid
|
import acoustid
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
import six
|
||||||
|
|
||||||
API_KEY = '1vOwZtEn'
|
API_KEY = '1vOwZtEn'
|
||||||
SCORE_THRESH = 0.5
|
SCORE_THRESH = 0.5
|
||||||
|
|
@ -181,7 +182,7 @@ class AcoustidPlugin(plugins.BeetsPlugin):
|
||||||
|
|
||||||
def submit_cmd_func(lib, opts, args):
|
def submit_cmd_func(lib, opts, args):
|
||||||
try:
|
try:
|
||||||
apikey = config['acoustid']['apikey'].get(unicode)
|
apikey = config['acoustid']['apikey'].get(six.text_type)
|
||||||
except confit.NotFoundError:
|
except confit.NotFoundError:
|
||||||
raise ui.UserError(u'no Acoustid user API key provided')
|
raise ui.UserError(u'no Acoustid user API key provided')
|
||||||
submit_items(self._log, apikey, lib.items(ui.decargs(args)))
|
submit_items(self._log, apikey, lib.items(ui.decargs(args)))
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ from beets.plugins import BeetsPlugin
|
||||||
from beets.util.confit import ConfigTypeError
|
from beets.util.confit import ConfigTypeError
|
||||||
from beets import art
|
from beets import art
|
||||||
from beets.util.artresizer import ArtResizer
|
from beets.util.artresizer import ArtResizer
|
||||||
|
import six
|
||||||
|
|
||||||
_fs_lock = threading.Lock()
|
_fs_lock = threading.Lock()
|
||||||
_temp_files = [] # Keep track of temporary transcoded files for deletion.
|
_temp_files = [] # Keep track of temporary transcoded files for deletion.
|
||||||
|
|
@ -55,7 +56,7 @@ def get_format(fmt=None):
|
||||||
"""Return the command template and the extension from the config.
|
"""Return the command template and the extension from the config.
|
||||||
"""
|
"""
|
||||||
if not fmt:
|
if not fmt:
|
||||||
fmt = config['convert']['format'].get(unicode).lower()
|
fmt = config['convert']['format'].get(six.text_type).lower()
|
||||||
fmt = ALIASES.get(fmt, fmt)
|
fmt = ALIASES.get(fmt, fmt)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
@ -74,14 +75,14 @@ def get_format(fmt=None):
|
||||||
# Convenience and backwards-compatibility shortcuts.
|
# Convenience and backwards-compatibility shortcuts.
|
||||||
keys = config['convert'].keys()
|
keys = config['convert'].keys()
|
||||||
if 'command' in keys:
|
if 'command' in keys:
|
||||||
command = config['convert']['command'].get(unicode)
|
command = config['convert']['command'].get(six.text_type)
|
||||||
elif 'opts' in keys:
|
elif 'opts' in keys:
|
||||||
# Undocumented option for backwards compatibility with < 1.3.1.
|
# Undocumented option for backwards compatibility with < 1.3.1.
|
||||||
command = u'ffmpeg -i $source -y {0} $dest'.format(
|
command = u'ffmpeg -i $source -y {0} $dest'.format(
|
||||||
config['convert']['opts'].get(unicode)
|
config['convert']['opts'].get(six.text_type)
|
||||||
)
|
)
|
||||||
if 'extension' in keys:
|
if 'extension' in keys:
|
||||||
extension = config['convert']['extension'].get(unicode)
|
extension = config['convert']['extension'].get(six.text_type)
|
||||||
|
|
||||||
return (command.encode('utf8'), extension.encode('utf8'))
|
return (command.encode('utf8'), extension.encode('utf8'))
|
||||||
|
|
||||||
|
|
@ -389,7 +390,7 @@ class ConvertPlugin(BeetsPlugin):
|
||||||
path_formats = ui.get_path_formats()
|
path_formats = ui.get_path_formats()
|
||||||
|
|
||||||
if not opts.format:
|
if not opts.format:
|
||||||
opts.format = self.config['format'].get(unicode).lower()
|
opts.format = self.config['format'].get(six.text_type).lower()
|
||||||
|
|
||||||
pretend = opts.pretend if opts.pretend is not None else \
|
pretend = opts.pretend if opts.pretend is not None else \
|
||||||
self.config['pretend'].get(bool)
|
self.config['pretend'].get(bool)
|
||||||
|
|
@ -422,7 +423,7 @@ class ConvertPlugin(BeetsPlugin):
|
||||||
"""Transcode a file automatically after it is imported into the
|
"""Transcode a file automatically after it is imported into the
|
||||||
library.
|
library.
|
||||||
"""
|
"""
|
||||||
fmt = self.config['format'].get(unicode).lower()
|
fmt = self.config['format'].get(six.text_type).lower()
|
||||||
if should_transcode(item, fmt):
|
if should_transcode(item, fmt):
|
||||||
command, ext = get_format()
|
command, ext = get_format()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ import time
|
||||||
import json
|
import json
|
||||||
import socket
|
import socket
|
||||||
import os
|
import os
|
||||||
|
import six
|
||||||
|
|
||||||
|
|
||||||
# Silence spurious INFO log lines generated by urllib3.
|
# Silence spurious INFO log lines generated by urllib3.
|
||||||
|
|
@ -66,8 +67,8 @@ class DiscogsPlugin(BeetsPlugin):
|
||||||
def setup(self, session=None):
|
def setup(self, session=None):
|
||||||
"""Create the `discogs_client` field. Authenticate if necessary.
|
"""Create the `discogs_client` field. Authenticate if necessary.
|
||||||
"""
|
"""
|
||||||
c_key = self.config['apikey'].get(unicode)
|
c_key = self.config['apikey'].get(six.text_type)
|
||||||
c_secret = self.config['apisecret'].get(unicode)
|
c_secret = self.config['apisecret'].get(six.text_type)
|
||||||
|
|
||||||
# Get the OAuth token from a file or log in.
|
# Get the OAuth token from a file or log in.
|
||||||
try:
|
try:
|
||||||
|
|
@ -225,7 +226,7 @@ class DiscogsPlugin(BeetsPlugin):
|
||||||
result.data['formats'][0].get('descriptions', [])) or None
|
result.data['formats'][0].get('descriptions', [])) or None
|
||||||
va = result.data['artists'][0]['name'].lower() == 'various'
|
va = result.data['artists'][0]['name'].lower() == 'various'
|
||||||
if va:
|
if va:
|
||||||
artist = config['va_name'].get(unicode)
|
artist = config['va_name'].get(six.text_type)
|
||||||
year = result.data['year']
|
year = result.data['year']
|
||||||
label = result.data['labels'][0]['name']
|
label = result.data['labels'][0]['name']
|
||||||
mediums = len(set(t.medium for t in tracks))
|
mediums = len(set(t.medium for t in tracks))
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ from beets.plugins import BeetsPlugin
|
||||||
from beets.ui import decargs, print_, vararg_callback, Subcommand, UserError
|
from beets.ui import decargs, print_, vararg_callback, Subcommand, UserError
|
||||||
from beets.util import command_output, displayable_path, subprocess
|
from beets.util import command_output, displayable_path, subprocess
|
||||||
from beets.library import Item, Album
|
from beets.library import Item, Album
|
||||||
|
import six
|
||||||
|
|
||||||
PLUGIN = 'duplicates'
|
PLUGIN = 'duplicates'
|
||||||
|
|
||||||
|
|
@ -264,7 +265,7 @@ class DuplicatesPlugin(BeetsPlugin):
|
||||||
# between a bytes object and the empty Unicode
|
# between a bytes object and the empty Unicode
|
||||||
# string ''.
|
# string ''.
|
||||||
return v is not None and \
|
return v is not None and \
|
||||||
(v != '' if isinstance(v, unicode) else True)
|
(v != '' if isinstance(v, six.text_type) else True)
|
||||||
fields = kind.all_keys()
|
fields = kind.all_keys()
|
||||||
key = lambda x: sum(1 for f in fields if truthy(getattr(x, f)))
|
key = lambda x: sum(1 for f in fields if truthy(getattr(x, f)))
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ import subprocess
|
||||||
import yaml
|
import yaml
|
||||||
from tempfile import NamedTemporaryFile
|
from tempfile import NamedTemporaryFile
|
||||||
import os
|
import os
|
||||||
|
import six
|
||||||
|
|
||||||
|
|
||||||
# These "safe" types can avoid the format/parse cycle that most fields go
|
# These "safe" types can avoid the format/parse cycle that most fields go
|
||||||
|
|
@ -82,7 +83,7 @@ def load(s):
|
||||||
|
|
||||||
# Convert all keys to strings. They started out as strings,
|
# Convert all keys to strings. They started out as strings,
|
||||||
# but the user may have inadvertently messed this up.
|
# but the user may have inadvertently messed this up.
|
||||||
out.append({unicode(k): v for k, v in d.items()})
|
out.append({six.text_type(k): v for k, v in d.items()})
|
||||||
|
|
||||||
except yaml.YAMLError as e:
|
except yaml.YAMLError as e:
|
||||||
raise ParseError(u'invalid YAML: {}'.format(e))
|
raise ParseError(u'invalid YAML: {}'.format(e))
|
||||||
|
|
@ -141,7 +142,7 @@ def apply_(obj, data):
|
||||||
else:
|
else:
|
||||||
# Either the field was stringified originally or the user changed
|
# Either the field was stringified originally or the user changed
|
||||||
# it from a safe type to an unsafe one. Parse it as a string.
|
# it from a safe type to an unsafe one. Parse it as a string.
|
||||||
obj.set_parse(key, unicode(value))
|
obj.set_parse(key, six.text_type(value))
|
||||||
|
|
||||||
|
|
||||||
class EditPlugin(plugins.BeetsPlugin):
|
class EditPlugin(plugins.BeetsPlugin):
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ from beets import config
|
||||||
from beets.util.artresizer import ArtResizer
|
from beets.util.artresizer import ArtResizer
|
||||||
from beets.util import confit
|
from beets.util import confit
|
||||||
from beets.util import syspath, bytestring_path
|
from beets.util import syspath, bytestring_path
|
||||||
|
import six
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import itunes
|
import itunes
|
||||||
|
|
@ -696,7 +697,7 @@ class FetchArtPlugin(plugins.BeetsPlugin, RequestMixin):
|
||||||
confit.String(pattern=self.PAT_PERCENT)]))
|
confit.String(pattern=self.PAT_PERCENT)]))
|
||||||
self.margin_px = None
|
self.margin_px = None
|
||||||
self.margin_percent = None
|
self.margin_percent = None
|
||||||
if type(self.enforce_ratio) is unicode:
|
if type(self.enforce_ratio) is six.text_type:
|
||||||
if self.enforce_ratio[-1] == u'%':
|
if self.enforce_ratio[-1] == u'%':
|
||||||
self.margin_percent = float(self.enforce_ratio[:-1]) / 100
|
self.margin_percent = float(self.enforce_ratio[:-1]) / 100
|
||||||
elif self.enforce_ratio[-2:] == u'px':
|
elif self.enforce_ratio[-2:] == u'px':
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ from beets import plugins
|
||||||
from beets.util import displayable_path
|
from beets.util import displayable_path
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
import six
|
||||||
|
|
||||||
|
|
||||||
# Filename field extraction patterns.
|
# Filename field extraction patterns.
|
||||||
|
|
@ -132,7 +133,7 @@ def apply_matches(d):
|
||||||
# Apply the title and track.
|
# Apply the title and track.
|
||||||
for item in d:
|
for item in d:
|
||||||
if bad_title(item.title):
|
if bad_title(item.title):
|
||||||
item.title = unicode(d[item][title_field])
|
item.title = six.text_type(d[item][title_field])
|
||||||
if 'track' in d[item] and item.track == 0:
|
if 'track' in d[item] and item.track == 0:
|
||||||
item.track = int(d[item]['track'])
|
item.track = int(d[item]['track'])
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import re
|
||||||
from beets import plugins
|
from beets import plugins
|
||||||
from beets import ui
|
from beets import ui
|
||||||
from beets.util import displayable_path
|
from beets.util import displayable_path
|
||||||
|
import six
|
||||||
|
|
||||||
|
|
||||||
def split_on_feat(artist):
|
def split_on_feat(artist):
|
||||||
|
|
@ -137,7 +138,7 @@ class FtInTitlePlugin(plugins.BeetsPlugin):
|
||||||
# Only update the title if it does not already contain a featured
|
# Only update the title if it does not already contain a featured
|
||||||
# artist and if we do not drop featuring information.
|
# artist and if we do not drop featuring information.
|
||||||
if not drop_feat and not contains_feat(item.title):
|
if not drop_feat and not contains_feat(item.title):
|
||||||
feat_format = self.config['format'].get(unicode)
|
feat_format = self.config['format'].get(six.text_type)
|
||||||
new_format = feat_format.format(feat_part)
|
new_format = feat_format.format(feat_part)
|
||||||
new_title = u"{0} {1}".format(item.title, new_format)
|
new_title = u"{0} {1}".format(item.title, new_format)
|
||||||
self._log.info(u'title: {0} -> {1}', item.title, new_title)
|
self._log.info(u'title: {0} -> {1}', item.title, new_title)
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import subprocess
|
||||||
from beets.plugins import BeetsPlugin
|
from beets.plugins import BeetsPlugin
|
||||||
from beets.ui import _arg_encoding
|
from beets.ui import _arg_encoding
|
||||||
from beets.util import shlex_split
|
from beets.util import shlex_split
|
||||||
|
import six
|
||||||
|
|
||||||
|
|
||||||
class CodingFormatter(string.Formatter):
|
class CodingFormatter(string.Formatter):
|
||||||
|
|
@ -79,8 +80,8 @@ class HookPlugin(BeetsPlugin):
|
||||||
for hook_index in range(len(hooks)):
|
for hook_index in range(len(hooks)):
|
||||||
hook = self.config['hooks'][hook_index]
|
hook = self.config['hooks'][hook_index]
|
||||||
|
|
||||||
hook_event = hook['event'].get(unicode)
|
hook_event = hook['event'].get(six.text_type)
|
||||||
hook_command = hook['command'].get(unicode)
|
hook_command = hook['command'].get(six.text_type)
|
||||||
|
|
||||||
self.create_and_register_hook(hook_event, hook_command)
|
self.create_and_register_hook(hook_event, hook_command)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
# included in all copies or substantial portions of the Software.
|
# included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
from __future__ import division, absolute_import, print_function
|
from __future__ import division, absolute_import, print_function
|
||||||
|
import six
|
||||||
|
|
||||||
"""Write paths of imported files in various formats to ease later import in a
|
"""Write paths of imported files in various formats to ease later import in a
|
||||||
music player. Also allow printing the new file locations to stdout in case
|
music player. Also allow printing the new file locations to stdout in case
|
||||||
|
|
@ -119,7 +120,7 @@ class ImportFeedsPlugin(BeetsPlugin):
|
||||||
|
|
||||||
if 'm3u' in formats:
|
if 'm3u' in formats:
|
||||||
m3u_basename = bytestring_path(
|
m3u_basename = bytestring_path(
|
||||||
self.config['m3u_name'].get(unicode))
|
self.config['m3u_name'].get(six.text_type))
|
||||||
m3u_path = os.path.join(feedsdir, m3u_basename)
|
m3u_path = os.path.join(feedsdir, m3u_basename)
|
||||||
_write_m3u(m3u_path, paths)
|
_write_m3u(m3u_path, paths)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import itertools
|
||||||
|
|
||||||
from beets.plugins import BeetsPlugin
|
from beets.plugins import BeetsPlugin
|
||||||
from beets import config
|
from beets import config
|
||||||
|
import six
|
||||||
|
|
||||||
FUNC_NAME = u'__INLINE_FUNC__'
|
FUNC_NAME = u'__INLINE_FUNC__'
|
||||||
|
|
||||||
|
|
@ -32,7 +33,7 @@ class InlineError(Exception):
|
||||||
def __init__(self, code, exc):
|
def __init__(self, code, exc):
|
||||||
super(InlineError, self).__init__(
|
super(InlineError, self).__init__(
|
||||||
(u"error in inline path field code:\n"
|
(u"error in inline path field code:\n"
|
||||||
u"%s\n%s: %s") % (code, type(exc).__name__, unicode(exc))
|
u"%s\n%s: %s") % (code, type(exc).__name__, six.text_type(exc))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -64,14 +65,14 @@ class InlinePlugin(BeetsPlugin):
|
||||||
for key, view in itertools.chain(config['item_fields'].items(),
|
for key, view in itertools.chain(config['item_fields'].items(),
|
||||||
config['pathfields'].items()):
|
config['pathfields'].items()):
|
||||||
self._log.debug(u'adding item field {0}', key)
|
self._log.debug(u'adding item field {0}', key)
|
||||||
func = self.compile_inline(view.get(unicode), False)
|
func = self.compile_inline(view.get(six.text_type), False)
|
||||||
if func is not None:
|
if func is not None:
|
||||||
self.template_fields[key] = func
|
self.template_fields[key] = func
|
||||||
|
|
||||||
# Album fields.
|
# Album fields.
|
||||||
for key, view in config['album_fields'].items():
|
for key, view in config['album_fields'].items():
|
||||||
self._log.debug(u'adding album field {0}', key)
|
self._log.debug(u'adding album field {0}', key)
|
||||||
func = self.compile_inline(view.get(unicode), True)
|
func = self.compile_inline(view.get(six.text_type), True)
|
||||||
if func is not None:
|
if func is not None:
|
||||||
self.album_template_fields[key] = func
|
self.album_template_fields[key] = func
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import subprocess
|
||||||
from beets import ui
|
from beets import ui
|
||||||
from beets import util
|
from beets import util
|
||||||
from beets.plugins import BeetsPlugin
|
from beets.plugins import BeetsPlugin
|
||||||
|
import six
|
||||||
|
|
||||||
|
|
||||||
class KeyFinderPlugin(BeetsPlugin):
|
class KeyFinderPlugin(BeetsPlugin):
|
||||||
|
|
@ -52,7 +53,7 @@ class KeyFinderPlugin(BeetsPlugin):
|
||||||
|
|
||||||
def find_key(self, items, write=False):
|
def find_key(self, items, write=False):
|
||||||
overwrite = self.config['overwrite'].get(bool)
|
overwrite = self.config['overwrite'].get(bool)
|
||||||
bin = util.bytestring_path(self.config['bin'].get(unicode))
|
bin = util.bytestring_path(self.config['bin'].get(six.text_type))
|
||||||
|
|
||||||
for item in items:
|
for item in items:
|
||||||
if item['initial_key'] and not overwrite:
|
if item['initial_key'] and not overwrite:
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
# included in all copies or substantial portions of the Software.
|
# included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
from __future__ import division, absolute_import, print_function
|
from __future__ import division, absolute_import, print_function
|
||||||
|
import six
|
||||||
|
|
||||||
"""Gets genres for imported music based on Last.fm tags.
|
"""Gets genres for imported music based on Last.fm tags.
|
||||||
|
|
||||||
|
|
@ -71,7 +72,7 @@ def flatten_tree(elem, path, branches):
|
||||||
for sub in elem:
|
for sub in elem:
|
||||||
flatten_tree(sub, path, branches)
|
flatten_tree(sub, path, branches)
|
||||||
else:
|
else:
|
||||||
branches.append(path + [unicode(elem)])
|
branches.append(path + [six.text_type(elem)])
|
||||||
|
|
||||||
|
|
||||||
def find_parents(candidate, branches):
|
def find_parents(candidate, branches):
|
||||||
|
|
@ -186,7 +187,7 @@ class LastGenrePlugin(plugins.BeetsPlugin):
|
||||||
# the original tags list
|
# the original tags list
|
||||||
tags = [x.title() for x in tags if self._is_allowed(x)]
|
tags = [x.title() for x in tags if self._is_allowed(x)]
|
||||||
|
|
||||||
return self.config['separator'].get(unicode).join(
|
return self.config['separator'].get(six.text_type).join(
|
||||||
tags[:self.config['count'].get(int)]
|
tags[:self.config['count'].get(int)]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -221,7 +222,8 @@ class LastGenrePlugin(plugins.BeetsPlugin):
|
||||||
if any(not s for s in args):
|
if any(not s for s in args):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
key = u'{0}.{1}'.format(entity, u'-'.join(unicode(a) for a in args))
|
key = u'{0}.{1}'.format(entity,
|
||||||
|
u'-'.join(six.text_type(a) for a in args))
|
||||||
if key in self._genre_cache:
|
if key in self._genre_cache:
|
||||||
return self._genre_cache[key]
|
return self._genre_cache[key]
|
||||||
else:
|
else:
|
||||||
|
|
@ -297,7 +299,7 @@ class LastGenrePlugin(plugins.BeetsPlugin):
|
||||||
result = None
|
result = None
|
||||||
if isinstance(obj, library.Item):
|
if isinstance(obj, library.Item):
|
||||||
result = self.fetch_artist_genre(obj)
|
result = self.fetch_artist_genre(obj)
|
||||||
elif obj.albumartist != config['va_name'].get(unicode):
|
elif obj.albumartist != config['va_name'].get(six.text_type):
|
||||||
result = self.fetch_album_artist_genre(obj)
|
result = self.fetch_album_artist_genre(obj)
|
||||||
else:
|
else:
|
||||||
# For "Various Artists", pick the most popular track genre.
|
# For "Various Artists", pick the most popular track genre.
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ from beets import dbcore
|
||||||
from beets import config
|
from beets import config
|
||||||
from beets import plugins
|
from beets import plugins
|
||||||
from beets.dbcore import types
|
from beets.dbcore import types
|
||||||
|
import six
|
||||||
|
|
||||||
API_URL = 'http://ws.audioscrobbler.com/2.0/'
|
API_URL = 'http://ws.audioscrobbler.com/2.0/'
|
||||||
|
|
||||||
|
|
@ -111,7 +112,7 @@ class CustomUser(pylast.User):
|
||||||
|
|
||||||
|
|
||||||
def import_lastfm(lib, log):
|
def import_lastfm(lib, log):
|
||||||
user = config['lastfm']['user'].get(unicode)
|
user = config['lastfm']['user'].get(six.text_type)
|
||||||
per_page = config['lastimport']['per_page'].get(int)
|
per_page = config['lastimport']['per_page'].get(int)
|
||||||
|
|
||||||
if not user:
|
if not user:
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ import unicodedata
|
||||||
import warnings
|
import warnings
|
||||||
from six.moves.html_parser import HTMLParseError
|
from six.moves.html_parser import HTMLParseError
|
||||||
from six.moves import urllib
|
from six.moves import urllib
|
||||||
|
import six
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from bs4 import SoupStrainer, BeautifulSoup
|
from bs4 import SoupStrainer, BeautifulSoup
|
||||||
|
|
@ -177,7 +178,7 @@ class Backend(object):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _encode(s):
|
def _encode(s):
|
||||||
"""Encode the string for inclusion in a URL"""
|
"""Encode the string for inclusion in a URL"""
|
||||||
if isinstance(s, unicode):
|
if isinstance(s, six.text_type):
|
||||||
for char, repl in URL_CHARACTERS.items():
|
for char, repl in URL_CHARACTERS.items():
|
||||||
s = s.replace(char, repl)
|
s = s.replace(char, repl)
|
||||||
s = s.encode('utf8', 'ignore')
|
s = s.encode('utf8', 'ignore')
|
||||||
|
|
@ -250,7 +251,7 @@ class Genius(Backend):
|
||||||
"""Fetch lyrics from Genius via genius-api."""
|
"""Fetch lyrics from Genius via genius-api."""
|
||||||
def __init__(self, config, log):
|
def __init__(self, config, log):
|
||||||
super(Genius, self).__init__(config, log)
|
super(Genius, self).__init__(config, log)
|
||||||
self.api_key = config['genius_api_key'].get(unicode)
|
self.api_key = config['genius_api_key'].get(six.text_type)
|
||||||
self.headers = {'Authorization': "Bearer %s" % self.api_key}
|
self.headers = {'Authorization': "Bearer %s" % self.api_key}
|
||||||
|
|
||||||
def search_genius(self, artist, title):
|
def search_genius(self, artist, title):
|
||||||
|
|
@ -461,8 +462,8 @@ class Google(Backend):
|
||||||
"""Fetch lyrics from Google search results."""
|
"""Fetch lyrics from Google search results."""
|
||||||
def __init__(self, config, log):
|
def __init__(self, config, log):
|
||||||
super(Google, self).__init__(config, log)
|
super(Google, self).__init__(config, log)
|
||||||
self.api_key = config['google_API_key'].get(unicode)
|
self.api_key = config['google_API_key'].get(six.text_type)
|
||||||
self.engine_id = config['google_engine_ID'].get(unicode)
|
self.engine_id = config['google_engine_ID'].get(six.text_type)
|
||||||
|
|
||||||
def is_lyrics(self, text, artist=None):
|
def is_lyrics(self, text, artist=None):
|
||||||
"""Determine whether the text seems to be valid lyrics.
|
"""Determine whether the text seems to be valid lyrics.
|
||||||
|
|
@ -503,7 +504,7 @@ class Google(Backend):
|
||||||
try:
|
try:
|
||||||
text = unicodedata.normalize('NFKD', text).encode('ascii',
|
text = unicodedata.normalize('NFKD', text).encode('ascii',
|
||||||
'ignore')
|
'ignore')
|
||||||
text = unicode(re.sub('[-\s]+', ' ', text.decode('utf-8')))
|
text = six.text_type(re.sub('[-\s]+', ' ', text.decode('utf-8')))
|
||||||
except UnicodeDecodeError:
|
except UnicodeDecodeError:
|
||||||
self._log.exception(u"Failing to normalize '{0}'", text)
|
self._log.exception(u"Failing to normalize '{0}'", text)
|
||||||
return text
|
return text
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ from beets import config
|
||||||
import musicbrainzngs
|
import musicbrainzngs
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
import six
|
||||||
|
|
||||||
SUBMISSION_CHUNK_SIZE = 200
|
SUBMISSION_CHUNK_SIZE = 200
|
||||||
UUID_REGEX = r'^[a-f0-9]{8}(-[a-f0-9]{4}){3}-[a-f0-9]{12}$'
|
UUID_REGEX = r'^[a-f0-9]{8}(-[a-f0-9]{4}){3}-[a-f0-9]{12}$'
|
||||||
|
|
@ -57,8 +58,8 @@ class MusicBrainzCollectionPlugin(BeetsPlugin):
|
||||||
super(MusicBrainzCollectionPlugin, self).__init__()
|
super(MusicBrainzCollectionPlugin, self).__init__()
|
||||||
config['musicbrainz']['pass'].redact = True
|
config['musicbrainz']['pass'].redact = True
|
||||||
musicbrainzngs.auth(
|
musicbrainzngs.auth(
|
||||||
config['musicbrainz']['user'].get(unicode),
|
config['musicbrainz']['user'].get(six.text_type),
|
||||||
config['musicbrainz']['pass'].get(unicode),
|
config['musicbrainz']['pass'].get(six.text_type),
|
||||||
)
|
)
|
||||||
self.config.add({'auto': False})
|
self.config.add({'auto': False})
|
||||||
if self.config['auto']:
|
if self.config['auto']:
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ from beets import plugins
|
||||||
from beets import library
|
from beets import library
|
||||||
from beets.util import displayable_path
|
from beets.util import displayable_path
|
||||||
from beets.dbcore import types
|
from beets.dbcore import types
|
||||||
|
import six
|
||||||
|
|
||||||
# If we lose the connection, how many times do we want to retry and how
|
# If we lose the connection, how many times do we want to retry and how
|
||||||
# much time should we wait between retries?
|
# much time should we wait between retries?
|
||||||
|
|
@ -49,7 +50,7 @@ def is_url(path):
|
||||||
# see http://www.tarmack.eu/code/mpdunicode.py for the general idea
|
# see http://www.tarmack.eu/code/mpdunicode.py for the general idea
|
||||||
class MPDClient(mpd.MPDClient):
|
class MPDClient(mpd.MPDClient):
|
||||||
def _write_command(self, command, args=[]):
|
def _write_command(self, command, args=[]):
|
||||||
args = [unicode(arg).encode('utf-8') for arg in args]
|
args = [six.text_type(arg).encode('utf-8') for arg in args]
|
||||||
super(MPDClient, self)._write_command(command, args)
|
super(MPDClient, self)._write_command(command, args)
|
||||||
|
|
||||||
def _read_line(self):
|
def _read_line(self):
|
||||||
|
|
@ -64,14 +65,14 @@ class MPDClientWrapper(object):
|
||||||
self._log = log
|
self._log = log
|
||||||
|
|
||||||
self.music_directory = (
|
self.music_directory = (
|
||||||
mpd_config['music_directory'].get(unicode))
|
mpd_config['music_directory'].get(six.text_type))
|
||||||
|
|
||||||
self.client = MPDClient()
|
self.client = MPDClient()
|
||||||
|
|
||||||
def connect(self):
|
def connect(self):
|
||||||
"""Connect to the MPD.
|
"""Connect to the MPD.
|
||||||
"""
|
"""
|
||||||
host = mpd_config['host'].get(unicode)
|
host = mpd_config['host'].get(six.text_type)
|
||||||
port = mpd_config['port'].get(int)
|
port = mpd_config['port'].get(int)
|
||||||
|
|
||||||
if host[0] in ['/', '~']:
|
if host[0] in ['/', '~']:
|
||||||
|
|
@ -83,7 +84,7 @@ class MPDClientWrapper(object):
|
||||||
except socket.error as e:
|
except socket.error as e:
|
||||||
raise ui.UserError(u'could not connect to MPD: {0}'.format(e))
|
raise ui.UserError(u'could not connect to MPD: {0}'.format(e))
|
||||||
|
|
||||||
password = mpd_config['password'].get(unicode)
|
password = mpd_config['password'].get(six.text_type)
|
||||||
if password:
|
if password:
|
||||||
try:
|
try:
|
||||||
self.client.password(password)
|
self.client.password(password)
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ from beets.plugins import BeetsPlugin
|
||||||
import os
|
import os
|
||||||
import socket
|
import socket
|
||||||
from beets import config
|
from beets import config
|
||||||
|
import six
|
||||||
|
|
||||||
|
|
||||||
# No need to introduce a dependency on an MPD library for such a
|
# No need to introduce a dependency on an MPD library for such a
|
||||||
|
|
@ -86,9 +87,9 @@ class MPDUpdatePlugin(BeetsPlugin):
|
||||||
|
|
||||||
def update(self, lib):
|
def update(self, lib):
|
||||||
self.update_mpd(
|
self.update_mpd(
|
||||||
config['mpd']['host'].get(unicode),
|
config['mpd']['host'].get(six.text_type),
|
||||||
config['mpd']['port'].get(int),
|
config['mpd']['port'].get(int),
|
||||||
config['mpd']['password'].get(unicode),
|
config['mpd']['password'].get(six.text_type),
|
||||||
)
|
)
|
||||||
|
|
||||||
def update_mpd(self, host='localhost', port=6600, password=None):
|
def update_mpd(self, host='localhost', port=6600, password=None):
|
||||||
|
|
@ -101,7 +102,7 @@ class MPDUpdatePlugin(BeetsPlugin):
|
||||||
s = BufferedSocket(host, port)
|
s = BufferedSocket(host, port)
|
||||||
except socket.error as e:
|
except socket.error as e:
|
||||||
self._log.warning(u'MPD connection failed: {0}',
|
self._log.warning(u'MPD connection failed: {0}',
|
||||||
unicode(e.strerror))
|
six.text_type(e.strerror))
|
||||||
return
|
return
|
||||||
|
|
||||||
resp = s.readline()
|
resp = s.readline()
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ from beets import logging
|
||||||
from beets import ui
|
from beets import ui
|
||||||
from beets.plugins import BeetsPlugin
|
from beets.plugins import BeetsPlugin
|
||||||
from beets.util import syspath, command_output, displayable_path
|
from beets.util import syspath, command_output, displayable_path
|
||||||
|
import six
|
||||||
|
|
||||||
|
|
||||||
# Utilities.
|
# Utilities.
|
||||||
|
|
@ -102,7 +103,7 @@ class Bs1770gainBackend(Backend):
|
||||||
'method': 'replaygain',
|
'method': 'replaygain',
|
||||||
})
|
})
|
||||||
self.chunk_at = config['chunk_at'].as_number()
|
self.chunk_at = config['chunk_at'].as_number()
|
||||||
self.method = b'--' + bytes(config['method'].get(unicode))
|
self.method = b'--' + bytes(config['method'].get(six.text_type))
|
||||||
|
|
||||||
cmd = b'bs1770gain'
|
cmd = b'bs1770gain'
|
||||||
try:
|
try:
|
||||||
|
|
@ -256,7 +257,7 @@ class CommandBackend(Backend):
|
||||||
'noclip': True,
|
'noclip': True,
|
||||||
})
|
})
|
||||||
|
|
||||||
self.command = config["command"].get(unicode)
|
self.command = config["command"].get(six.text_type)
|
||||||
|
|
||||||
if self.command:
|
if self.command:
|
||||||
# Explicit executable path.
|
# Explicit executable path.
|
||||||
|
|
@ -809,7 +810,7 @@ class ReplayGainPlugin(BeetsPlugin):
|
||||||
})
|
})
|
||||||
|
|
||||||
self.overwrite = self.config['overwrite'].get(bool)
|
self.overwrite = self.config['overwrite'].get(bool)
|
||||||
backend_name = self.config['backend'].get(unicode)
|
backend_name = self.config['backend'].get(six.text_type)
|
||||||
if backend_name not in self.backends:
|
if backend_name not in self.backends:
|
||||||
raise ui.UserError(
|
raise ui.UserError(
|
||||||
u"Selected ReplayGain backend {0} is not supported. "
|
u"Selected ReplayGain backend {0} is not supported. "
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ from collections import defaultdict
|
||||||
from beets.plugins import BeetsPlugin
|
from beets.plugins import BeetsPlugin
|
||||||
from beets import ui
|
from beets import ui
|
||||||
from beets import library
|
from beets import library
|
||||||
|
import six
|
||||||
|
|
||||||
|
|
||||||
def rewriter(field, rules):
|
def rewriter(field, rules):
|
||||||
|
|
@ -51,7 +52,7 @@ class RewritePlugin(BeetsPlugin):
|
||||||
# Gather all the rewrite rules for each field.
|
# Gather all the rewrite rules for each field.
|
||||||
rules = defaultdict(list)
|
rules = defaultdict(list)
|
||||||
for key, view in self.config.items():
|
for key, view in self.config.items():
|
||||||
value = view.get(unicode)
|
value = view.get(six.text_type)
|
||||||
try:
|
try:
|
||||||
fieldname, pattern = key.split(None, 1)
|
fieldname, pattern = key.split(None, 1)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ from beets.plugins import BeetsPlugin
|
||||||
from beets.ui import decargs
|
from beets.ui import decargs
|
||||||
from beets import ui
|
from beets import ui
|
||||||
from requests.exceptions import HTTPError
|
from requests.exceptions import HTTPError
|
||||||
|
import six
|
||||||
|
|
||||||
|
|
||||||
class SpotifyPlugin(BeetsPlugin):
|
class SpotifyPlugin(BeetsPlugin):
|
||||||
|
|
@ -170,6 +171,6 @@ class SpotifyPlugin(BeetsPlugin):
|
||||||
|
|
||||||
else:
|
else:
|
||||||
for item in ids:
|
for item in ids:
|
||||||
print(unicode.encode(self.open_url + item))
|
print(six.text_type.encode(self.open_url + item))
|
||||||
else:
|
else:
|
||||||
self._log.warn(u'No Spotify tracks found from beets query')
|
self._log.warn(u'No Spotify tracks found from beets query')
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ from __future__ import division, absolute_import, print_function
|
||||||
|
|
||||||
import re
|
import re
|
||||||
from beets.plugins import BeetsPlugin
|
from beets.plugins import BeetsPlugin
|
||||||
|
import six
|
||||||
|
|
||||||
__author__ = 'baobab@heresiarch.info'
|
__author__ = 'baobab@heresiarch.info'
|
||||||
__version__ = '1.1'
|
__version__ = '1.1'
|
||||||
|
|
@ -81,7 +82,7 @@ class ThePlugin(BeetsPlugin):
|
||||||
if self.config['strip']:
|
if self.config['strip']:
|
||||||
return r
|
return r
|
||||||
else:
|
else:
|
||||||
fmt = self.config['format'].get(unicode)
|
fmt = self.config['format'].get(six.text_type)
|
||||||
return fmt.format(r, t.strip()).strip()
|
return fmt.format(r, t.strip()).strip()
|
||||||
else:
|
else:
|
||||||
return u''
|
return u''
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ from beets.plugins import BeetsPlugin
|
||||||
from beets.ui import Subcommand, decargs
|
from beets.ui import Subcommand, decargs
|
||||||
from beets import util
|
from beets import util
|
||||||
from beets.util.artresizer import ArtResizer, get_im_version, get_pil_version
|
from beets.util.artresizer import ArtResizer, get_im_version, get_pil_version
|
||||||
|
import six
|
||||||
|
|
||||||
|
|
||||||
BASE_DIR = os.path.join(BaseDirectory.xdg_cache_home, "thumbnails")
|
BASE_DIR = os.path.join(BaseDirectory.xdg_cache_home, "thumbnails")
|
||||||
|
|
@ -169,8 +170,9 @@ class ThumbnailsPlugin(BeetsPlugin):
|
||||||
"""Write required metadata to the thumbnail
|
"""Write required metadata to the thumbnail
|
||||||
See http://standards.freedesktop.org/thumbnail-spec/latest/x142.html
|
See http://standards.freedesktop.org/thumbnail-spec/latest/x142.html
|
||||||
"""
|
"""
|
||||||
|
mtime = os.stat(album.artpath).st_mtime
|
||||||
metadata = {"Thumb::URI": self.get_uri(album.artpath),
|
metadata = {"Thumb::URI": self.get_uri(album.artpath),
|
||||||
"Thumb::MTime": unicode(os.stat(album.artpath).st_mtime)}
|
"Thumb::MTime": six.text_type(mtime)}
|
||||||
try:
|
try:
|
||||||
self.write_metadata(image_path, metadata)
|
self.write_metadata(image_path, metadata)
|
||||||
except Exception:
|
except Exception:
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ from flask import g
|
||||||
from werkzeug.routing import BaseConverter, PathConverter
|
from werkzeug.routing import BaseConverter, PathConverter
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
|
import six
|
||||||
|
|
||||||
|
|
||||||
# Utilities.
|
# Utilities.
|
||||||
|
|
@ -321,7 +322,7 @@ class WebPlugin(BeetsPlugin):
|
||||||
}
|
}
|
||||||
CORS(app)
|
CORS(app)
|
||||||
# Start the web application.
|
# Start the web application.
|
||||||
app.run(host=self.config['host'].get(unicode),
|
app.run(host=self.config['host'].get(six.text_type),
|
||||||
port=self.config['port'].get(int),
|
port=self.config['port'].get(int),
|
||||||
debug=opts.debug, threaded=True)
|
debug=opts.debug, threaded=True)
|
||||||
cmd.func = func
|
cmd.func = func
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ from beets.plugins import BeetsPlugin
|
||||||
from beets.mediafile import MediaFile
|
from beets.mediafile import MediaFile
|
||||||
from beets.importer import action
|
from beets.importer import action
|
||||||
from beets.util import confit
|
from beets.util import confit
|
||||||
|
import six
|
||||||
|
|
||||||
__author__ = 'baobab@heresiarch.info'
|
__author__ = 'baobab@heresiarch.info'
|
||||||
__version__ = '0.10'
|
__version__ = '0.10'
|
||||||
|
|
@ -113,7 +114,7 @@ class ZeroPlugin(BeetsPlugin):
|
||||||
if patterns is True:
|
if patterns is True:
|
||||||
return True
|
return True
|
||||||
for p in patterns:
|
for p in patterns:
|
||||||
if re.search(p, unicode(field), flags=re.IGNORECASE):
|
if re.search(p, six.text_type(field), flags=re.IGNORECASE):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,7 @@ from beets import util
|
||||||
|
|
||||||
# TODO Move AutotagMock here
|
# TODO Move AutotagMock here
|
||||||
from test import _common
|
from test import _common
|
||||||
|
import six
|
||||||
|
|
||||||
|
|
||||||
class LogCapture(logging.Handler):
|
class LogCapture(logging.Handler):
|
||||||
|
|
@ -65,7 +66,7 @@ class LogCapture(logging.Handler):
|
||||||
self.messages = []
|
self.messages = []
|
||||||
|
|
||||||
def emit(self, record):
|
def emit(self, record):
|
||||||
self.messages.append(unicode(record.msg))
|
self.messages.append(six.text_type(record.msg))
|
||||||
|
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
|
|
@ -121,7 +122,7 @@ def has_program(cmd, args=['--version']):
|
||||||
"""
|
"""
|
||||||
full_cmd = [cmd] + args
|
full_cmd = [cmd] + args
|
||||||
for i, elem in enumerate(full_cmd):
|
for i, elem in enumerate(full_cmd):
|
||||||
if isinstance(elem, unicode):
|
if isinstance(elem, six.text_type):
|
||||||
full_cmd[i] = elem.encode(_arg_encoding())
|
full_cmd[i] = elem.encode(_arg_encoding())
|
||||||
try:
|
try:
|
||||||
with open(os.devnull, 'wb') as devnull:
|
with open(os.devnull, 'wb') as devnull:
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ from beets import config
|
||||||
from test._common import unittest
|
from test._common import unittest
|
||||||
from test.helper import TestHelper, capture_stdout
|
from test.helper import TestHelper, capture_stdout
|
||||||
from beets.library import Library
|
from beets.library import Library
|
||||||
|
import six
|
||||||
|
|
||||||
|
|
||||||
class ConfigCommandTest(unittest.TestCase, TestHelper):
|
class ConfigCommandTest(unittest.TestCase, TestHelper):
|
||||||
|
|
@ -114,8 +115,8 @@ class ConfigCommandTest(unittest.TestCase, TestHelper):
|
||||||
execlp.side_effect = OSError('here is problem')
|
execlp.side_effect = OSError('here is problem')
|
||||||
self.run_command('config', '-e')
|
self.run_command('config', '-e')
|
||||||
self.assertIn('Could not edit configuration',
|
self.assertIn('Could not edit configuration',
|
||||||
unicode(user_error.exception))
|
six.text_type(user_error.exception))
|
||||||
self.assertIn('here is problem', unicode(user_error.exception))
|
self.assertIn('here is problem', six.text_type(user_error.exception))
|
||||||
|
|
||||||
def test_edit_invalid_config_file(self):
|
def test_edit_invalid_config_file(self):
|
||||||
self.lib = Library(':memory:')
|
self.lib = Library(':memory:')
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ from test import _common
|
||||||
from test._common import unittest
|
from test._common import unittest
|
||||||
from beets import dbcore
|
from beets import dbcore
|
||||||
from tempfile import mkstemp
|
from tempfile import mkstemp
|
||||||
|
import six
|
||||||
|
|
||||||
|
|
||||||
# Fixture: concrete database and model classes. For migration tests, we
|
# Fixture: concrete database and model classes. For migration tests, we
|
||||||
|
|
@ -350,7 +351,7 @@ class FormatTest(unittest.TestCase):
|
||||||
model = TestModel1()
|
model = TestModel1()
|
||||||
model.other_field = u'caf\xe9'.encode('utf8')
|
model.other_field = u'caf\xe9'.encode('utf8')
|
||||||
value = model.formatted().get('other_field')
|
value = model.formatted().get('other_field')
|
||||||
self.assertTrue(isinstance(value, unicode))
|
self.assertTrue(isinstance(value, six.text_type))
|
||||||
self.assertEqual(value, u'caf\xe9')
|
self.assertEqual(value, u'caf\xe9')
|
||||||
|
|
||||||
def test_format_unset_field(self):
|
def test_format_unset_field(self):
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ from beets import config
|
||||||
from beets.mediafile import MediaFile
|
from beets.mediafile import MediaFile
|
||||||
from beets.util import syspath, bytestring_path
|
from beets.util import syspath, bytestring_path
|
||||||
from test.helper import TestHelper
|
from test.helper import TestHelper
|
||||||
|
import six
|
||||||
|
|
||||||
# Shortcut to path normalization.
|
# Shortcut to path normalization.
|
||||||
np = util.normpath
|
np = util.normpath
|
||||||
|
|
@ -964,7 +965,7 @@ class PathStringTest(_common.TestCase):
|
||||||
def test_sanitize_path_returns_unicode(self):
|
def test_sanitize_path_returns_unicode(self):
|
||||||
path = u'b\xe1r?'
|
path = u'b\xe1r?'
|
||||||
new_path = util.sanitize_path(path)
|
new_path = util.sanitize_path(path)
|
||||||
self.assertTrue(isinstance(new_path, unicode))
|
self.assertTrue(isinstance(new_path, six.text_type))
|
||||||
|
|
||||||
def test_unicode_artpath_becomes_bytestring(self):
|
def test_unicode_artpath_becomes_bytestring(self):
|
||||||
alb = self.lib.add_album([self.i])
|
alb = self.lib.add_album([self.i])
|
||||||
|
|
@ -1051,7 +1052,7 @@ class TemplateTest(_common.LibTestCase):
|
||||||
album.tagada = u'togodo'
|
album.tagada = u'togodo'
|
||||||
self.assertEqual(u"{0}".format(album), u"foö bar")
|
self.assertEqual(u"{0}".format(album), u"foö bar")
|
||||||
self.assertEqual(u"{0:$tagada}".format(album), u"togodo")
|
self.assertEqual(u"{0:$tagada}".format(album), u"togodo")
|
||||||
self.assertEqual(unicode(album), u"foö bar")
|
self.assertEqual(six.text_type(album), u"foö bar")
|
||||||
self.assertEqual(bytes(album), b"fo\xc3\xb6 bar")
|
self.assertEqual(bytes(album), b"fo\xc3\xb6 bar")
|
||||||
|
|
||||||
config['format_item'] = 'bar $foo'
|
config['format_item'] = 'bar $foo'
|
||||||
|
|
@ -1174,7 +1175,8 @@ class LibraryFieldTypesTest(unittest.TestCase):
|
||||||
t = beets.library.DateType()
|
t = beets.library.DateType()
|
||||||
|
|
||||||
# format
|
# format
|
||||||
time_local = time.strftime(beets.config['time_format'].get(unicode),
|
time_format = beets.config['time_format'].get(six.text_type)
|
||||||
|
time_local = time.strftime(time_format,
|
||||||
time.localtime(123456789))
|
time.localtime(123456789))
|
||||||
self.assertEqual(time_local, t.format(123456789))
|
self.assertEqual(time_local, t.format(123456789))
|
||||||
# parse
|
# parse
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ from beetsplug import lyrics
|
||||||
from beets.library import Item
|
from beets.library import Item
|
||||||
from beets.util import confit, bytestring_path
|
from beets.util import confit, bytestring_path
|
||||||
from beets import logging
|
from beets import logging
|
||||||
|
import six
|
||||||
|
|
||||||
log = logging.getLogger('beets.test_lyrics')
|
log = logging.getLogger('beets.test_lyrics')
|
||||||
raw_backend = lyrics.Backend({}, log)
|
raw_backend = lyrics.Backend({}, log)
|
||||||
|
|
@ -354,7 +355,7 @@ class LyricsGooglePluginTest(unittest.TestCase):
|
||||||
present in the title."""
|
present in the title."""
|
||||||
from bs4 import SoupStrainer, BeautifulSoup
|
from bs4 import SoupStrainer, BeautifulSoup
|
||||||
s = self.source
|
s = self.source
|
||||||
url = unicode(s['url'] + s['path'])
|
url = six.text_type(s['url'] + s['path'])
|
||||||
html = raw_backend.fetch_url(url)
|
html = raw_backend.fetch_url(url)
|
||||||
soup = BeautifulSoup(html, "html.parser",
|
soup = BeautifulSoup(html, "html.parser",
|
||||||
parse_only=SoupStrainer('title'))
|
parse_only=SoupStrainer('title'))
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ from beets.mediafile import MediaFile, MediaField, Image, \
|
||||||
from beets.library import Item
|
from beets.library import Item
|
||||||
from beets.plugins import BeetsPlugin
|
from beets.plugins import BeetsPlugin
|
||||||
from beets.util import bytestring_path
|
from beets.util import bytestring_path
|
||||||
|
import six
|
||||||
|
|
||||||
|
|
||||||
class ArtTestMixin(object):
|
class ArtTestMixin(object):
|
||||||
|
|
@ -353,13 +354,13 @@ class ExtendedFieldTestMixin(object):
|
||||||
with self.assertRaises(ValueError) as cm:
|
with self.assertRaises(ValueError) as cm:
|
||||||
MediaFile.add_field('somekey', True)
|
MediaFile.add_field('somekey', True)
|
||||||
self.assertIn(u'must be an instance of MediaField',
|
self.assertIn(u'must be an instance of MediaField',
|
||||||
unicode(cm.exception))
|
six.text_type(cm.exception))
|
||||||
|
|
||||||
def test_overwrite_property(self):
|
def test_overwrite_property(self):
|
||||||
with self.assertRaises(ValueError) as cm:
|
with self.assertRaises(ValueError) as cm:
|
||||||
MediaFile.add_field('artist', MediaField())
|
MediaFile.add_field('artist', MediaField())
|
||||||
self.assertIn(u'property "artist" already exists',
|
self.assertIn(u'property "artist" already exists',
|
||||||
unicode(cm.exception))
|
six.text_type(cm.exception))
|
||||||
|
|
||||||
|
|
||||||
class ReadWriteTestBase(ArtTestMixin, GenreListTestMixin,
|
class ReadWriteTestBase(ArtTestMixin, GenreListTestMixin,
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ from test.helper import TestHelper
|
||||||
|
|
||||||
from beets.util import bytestring_path
|
from beets.util import bytestring_path
|
||||||
import beets.mediafile
|
import beets.mediafile
|
||||||
|
import six
|
||||||
|
|
||||||
|
|
||||||
_sc = beets.mediafile._safe_cast
|
_sc = beets.mediafile._safe_cast
|
||||||
|
|
@ -127,8 +128,8 @@ class InvalidValueToleranceTest(unittest.TestCase):
|
||||||
self.assertAlmostEqual(_sc(float, u'-1.234'), -1.234)
|
self.assertAlmostEqual(_sc(float, u'-1.234'), -1.234)
|
||||||
|
|
||||||
def test_safe_cast_special_chars_to_unicode(self):
|
def test_safe_cast_special_chars_to_unicode(self):
|
||||||
us = _sc(unicode, 'caf\xc3\xa9')
|
us = _sc(six.text_type, 'caf\xc3\xa9')
|
||||||
self.assertTrue(isinstance(us, unicode))
|
self.assertTrue(isinstance(us, six.text_type))
|
||||||
self.assertTrue(us.startswith(u'caf'))
|
self.assertTrue(us.startswith(u'caf'))
|
||||||
|
|
||||||
def test_safe_cast_float_with_no_numbers(self):
|
def test_safe_cast_float_with_no_numbers(self):
|
||||||
|
|
@ -350,7 +351,7 @@ class ID3v23Test(unittest.TestCase, TestHelper):
|
||||||
mf.year = 2013
|
mf.year = 2013
|
||||||
mf.save()
|
mf.save()
|
||||||
frame = mf.mgfile['TDRC']
|
frame = mf.mgfile['TDRC']
|
||||||
self.assertTrue('2013' in unicode(frame))
|
self.assertTrue('2013' in six.text_type(frame))
|
||||||
self.assertTrue('TYER' not in mf.mgfile)
|
self.assertTrue('TYER' not in mf.mgfile)
|
||||||
finally:
|
finally:
|
||||||
self._delete_test()
|
self._delete_test()
|
||||||
|
|
@ -361,7 +362,7 @@ class ID3v23Test(unittest.TestCase, TestHelper):
|
||||||
mf.year = 2013
|
mf.year = 2013
|
||||||
mf.save()
|
mf.save()
|
||||||
frame = mf.mgfile['TYER']
|
frame = mf.mgfile['TYER']
|
||||||
self.assertTrue('2013' in unicode(frame))
|
self.assertTrue('2013' in six.text_type(frame))
|
||||||
self.assertTrue('TDRC' not in mf.mgfile)
|
self.assertTrue('TDRC' not in mf.mgfile)
|
||||||
finally:
|
finally:
|
||||||
self._delete_test()
|
self._delete_test()
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ from beets.dbcore.query import (NoneQuery, ParsingError,
|
||||||
from beets.library import Library, Item
|
from beets.library import Library, Item
|
||||||
from beets import util
|
from beets import util
|
||||||
import platform
|
import platform
|
||||||
|
import six
|
||||||
|
|
||||||
|
|
||||||
class TestHelper(helper.TestHelper):
|
class TestHelper(helper.TestHelper):
|
||||||
|
|
@ -301,12 +302,13 @@ class GetTest(DummyDataTestCase):
|
||||||
def test_invalid_query(self):
|
def test_invalid_query(self):
|
||||||
with self.assertRaises(InvalidQueryArgumentTypeError) as raised:
|
with self.assertRaises(InvalidQueryArgumentTypeError) as raised:
|
||||||
dbcore.query.NumericQuery('year', u'199a')
|
dbcore.query.NumericQuery('year', u'199a')
|
||||||
self.assertIn(u'not an int', unicode(raised.exception))
|
self.assertIn(u'not an int', six.text_type(raised.exception))
|
||||||
|
|
||||||
with self.assertRaises(InvalidQueryArgumentTypeError) as raised:
|
with self.assertRaises(InvalidQueryArgumentTypeError) as raised:
|
||||||
dbcore.query.RegexpQuery('year', u'199(')
|
dbcore.query.RegexpQuery('year', u'199(')
|
||||||
self.assertIn(u'not a regular expression', unicode(raised.exception))
|
exception = six.text_type(raised.exception)
|
||||||
self.assertIn(u'unbalanced parenthesis', unicode(raised.exception))
|
self.assertIn(u'not a regular expression', exception)
|
||||||
|
self.assertIn(u'unbalanced parenthesis', exception)
|
||||||
self.assertIsInstance(raised.exception, ParsingError)
|
self.assertIsInstance(raised.exception, ParsingError)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import warnings
|
||||||
|
|
||||||
from test._common import unittest
|
from test._common import unittest
|
||||||
from beets.util import functemplate
|
from beets.util import functemplate
|
||||||
|
import six
|
||||||
|
|
||||||
|
|
||||||
def _normexpr(expr):
|
def _normexpr(expr):
|
||||||
|
|
@ -227,7 +228,7 @@ class EvalTest(unittest.TestCase):
|
||||||
u'baz': u'BaR',
|
u'baz': u'BaR',
|
||||||
}
|
}
|
||||||
functions = {
|
functions = {
|
||||||
u'lower': unicode.lower,
|
u'lower': six.text_type.lower,
|
||||||
u'len': len,
|
u'len': len,
|
||||||
}
|
}
|
||||||
return functemplate.Template(template).substitute(values, functions)
|
return functemplate.Template(template).substitute(values, functions)
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ from beets import config
|
||||||
from beets import plugins
|
from beets import plugins
|
||||||
from beets.util.confit import ConfigError
|
from beets.util.confit import ConfigError
|
||||||
from beets import util
|
from beets import util
|
||||||
|
import six
|
||||||
|
|
||||||
|
|
||||||
class ListTest(unittest.TestCase):
|
class ListTest(unittest.TestCase):
|
||||||
|
|
@ -1257,15 +1258,15 @@ class CommonOptionsParserTest(unittest.TestCase, TestHelper):
|
||||||
|
|
||||||
config['format_item'].set('$foo')
|
config['format_item'].set('$foo')
|
||||||
self.assertEqual(parser.parse_args([]), ({'path': None}, []))
|
self.assertEqual(parser.parse_args([]), ({'path': None}, []))
|
||||||
self.assertEqual(config['format_item'].get(unicode), u'$foo')
|
self.assertEqual(config['format_item'].get(six.text_type), u'$foo')
|
||||||
|
|
||||||
self.assertEqual(parser.parse_args([u'-p']),
|
self.assertEqual(parser.parse_args([u'-p']),
|
||||||
({'path': True, 'format': u'$path'}, []))
|
({'path': True, 'format': u'$path'}, []))
|
||||||
self.assertEqual(parser.parse_args(['--path']),
|
self.assertEqual(parser.parse_args(['--path']),
|
||||||
({'path': True, 'format': u'$path'}, []))
|
({'path': True, 'format': u'$path'}, []))
|
||||||
|
|
||||||
self.assertEqual(config['format_item'].get(unicode), u'$path')
|
self.assertEqual(config['format_item'].get(six.text_type), u'$path')
|
||||||
self.assertEqual(config['format_album'].get(unicode), u'$path')
|
self.assertEqual(config['format_album'].get(six.text_type), u'$path')
|
||||||
|
|
||||||
def test_format_option(self):
|
def test_format_option(self):
|
||||||
parser = ui.CommonOptionsParser()
|
parser = ui.CommonOptionsParser()
|
||||||
|
|
@ -1274,15 +1275,15 @@ class CommonOptionsParserTest(unittest.TestCase, TestHelper):
|
||||||
|
|
||||||
config['format_item'].set('$foo')
|
config['format_item'].set('$foo')
|
||||||
self.assertEqual(parser.parse_args([]), ({'format': None}, []))
|
self.assertEqual(parser.parse_args([]), ({'format': None}, []))
|
||||||
self.assertEqual(config['format_item'].get(unicode), u'$foo')
|
self.assertEqual(config['format_item'].get(six.text_type), u'$foo')
|
||||||
|
|
||||||
self.assertEqual(parser.parse_args([u'-f', u'$bar']),
|
self.assertEqual(parser.parse_args([u'-f', u'$bar']),
|
||||||
({'format': u'$bar'}, []))
|
({'format': u'$bar'}, []))
|
||||||
self.assertEqual(parser.parse_args([u'--format', u'$baz']),
|
self.assertEqual(parser.parse_args([u'--format', u'$baz']),
|
||||||
({'format': u'$baz'}, []))
|
({'format': u'$baz'}, []))
|
||||||
|
|
||||||
self.assertEqual(config['format_item'].get(unicode), u'$baz')
|
self.assertEqual(config['format_item'].get(six.text_type), u'$baz')
|
||||||
self.assertEqual(config['format_album'].get(unicode), u'$baz')
|
self.assertEqual(config['format_album'].get(six.text_type), u'$baz')
|
||||||
|
|
||||||
def test_format_option_with_target(self):
|
def test_format_option_with_target(self):
|
||||||
with self.assertRaises(KeyError):
|
with self.assertRaises(KeyError):
|
||||||
|
|
@ -1297,8 +1298,8 @@ class CommonOptionsParserTest(unittest.TestCase, TestHelper):
|
||||||
self.assertEqual(parser.parse_args([u'-f', u'$bar']),
|
self.assertEqual(parser.parse_args([u'-f', u'$bar']),
|
||||||
({'format': u'$bar'}, []))
|
({'format': u'$bar'}, []))
|
||||||
|
|
||||||
self.assertEqual(config['format_item'].get(unicode), u'$bar')
|
self.assertEqual(config['format_item'].get(six.text_type), u'$bar')
|
||||||
self.assertEqual(config['format_album'].get(unicode), u'$album')
|
self.assertEqual(config['format_album'].get(six.text_type), u'$album')
|
||||||
|
|
||||||
def test_format_option_with_album(self):
|
def test_format_option_with_album(self):
|
||||||
parser = ui.CommonOptionsParser()
|
parser = ui.CommonOptionsParser()
|
||||||
|
|
@ -1309,15 +1310,15 @@ class CommonOptionsParserTest(unittest.TestCase, TestHelper):
|
||||||
config['format_album'].set('$album')
|
config['format_album'].set('$album')
|
||||||
|
|
||||||
parser.parse_args([u'-f', u'$bar'])
|
parser.parse_args([u'-f', u'$bar'])
|
||||||
self.assertEqual(config['format_item'].get(unicode), u'$bar')
|
self.assertEqual(config['format_item'].get(six.text_type), u'$bar')
|
||||||
self.assertEqual(config['format_album'].get(unicode), u'$album')
|
self.assertEqual(config['format_album'].get(six.text_type), u'$album')
|
||||||
|
|
||||||
parser.parse_args([u'-a', u'-f', u'$foo'])
|
parser.parse_args([u'-a', u'-f', u'$foo'])
|
||||||
self.assertEqual(config['format_item'].get(unicode), u'$bar')
|
self.assertEqual(config['format_item'].get(six.text_type), u'$bar')
|
||||||
self.assertEqual(config['format_album'].get(unicode), u'$foo')
|
self.assertEqual(config['format_album'].get(six.text_type), u'$foo')
|
||||||
|
|
||||||
parser.parse_args([u'-f', u'$foo2', u'-a'])
|
parser.parse_args([u'-f', u'$foo2', u'-a'])
|
||||||
self.assertEqual(config['format_album'].get(unicode), u'$foo2')
|
self.assertEqual(config['format_album'].get(six.text_type), u'$foo2')
|
||||||
|
|
||||||
def test_add_all_common_options(self):
|
def test_add_all_common_options(self):
|
||||||
parser = ui.CommonOptionsParser()
|
parser = ui.CommonOptionsParser()
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ from test import test_importer
|
||||||
from beets.ui.commands import TerminalImportSession
|
from beets.ui.commands import TerminalImportSession
|
||||||
from beets import importer
|
from beets import importer
|
||||||
from beets import config
|
from beets import config
|
||||||
|
import six
|
||||||
|
|
||||||
|
|
||||||
class TestTerminalImportSession(TerminalImportSession):
|
class TestTerminalImportSession(TerminalImportSession):
|
||||||
|
|
@ -69,7 +70,7 @@ class TestTerminalImportSession(TerminalImportSession):
|
||||||
self.io.addinput(u'S')
|
self.io.addinput(u'S')
|
||||||
elif isinstance(choice, int):
|
elif isinstance(choice, int):
|
||||||
self.io.addinput(u'M')
|
self.io.addinput(u'M')
|
||||||
self.io.addinput(unicode(choice))
|
self.io.addinput(six.text_type(choice))
|
||||||
self._add_choice_input()
|
self._add_choice_input()
|
||||||
else:
|
else:
|
||||||
raise Exception(u'Unknown choice %s' % choice)
|
raise Exception(u'Unknown choice %s' % choice)
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ from mock import patch, Mock
|
||||||
from test._common import unittest
|
from test._common import unittest
|
||||||
from test import _common
|
from test import _common
|
||||||
from beets import util
|
from beets import util
|
||||||
|
import six
|
||||||
|
|
||||||
|
|
||||||
class UtilTest(unittest.TestCase):
|
class UtilTest(unittest.TestCase):
|
||||||
|
|
@ -122,7 +123,7 @@ class PathConversionTest(_common.TestCase):
|
||||||
with _common.platform_windows():
|
with _common.platform_windows():
|
||||||
path = os.path.join(u'a', u'b', u'c')
|
path = os.path.join(u'a', u'b', u'c')
|
||||||
outpath = util.syspath(path)
|
outpath = util.syspath(path)
|
||||||
self.assertTrue(isinstance(outpath, unicode))
|
self.assertTrue(isinstance(outpath, six.text_type))
|
||||||
self.assertTrue(outpath.startswith(u'\\\\?\\'))
|
self.assertTrue(outpath.startswith(u'\\\\?\\'))
|
||||||
|
|
||||||
def test_syspath_windows_format_unc_path(self):
|
def test_syspath_windows_format_unc_path(self):
|
||||||
|
|
@ -131,7 +132,7 @@ class PathConversionTest(_common.TestCase):
|
||||||
path = '\\\\server\\share\\file.mp3'
|
path = '\\\\server\\share\\file.mp3'
|
||||||
with _common.platform_windows():
|
with _common.platform_windows():
|
||||||
outpath = util.syspath(path)
|
outpath = util.syspath(path)
|
||||||
self.assertTrue(isinstance(outpath, unicode))
|
self.assertTrue(isinstance(outpath, six.text_type))
|
||||||
self.assertEqual(outpath, u'\\\\?\\UNC\\server\\share\\file.mp3')
|
self.assertEqual(outpath, u'\\\\?\\UNC\\server\\share\\file.mp3')
|
||||||
|
|
||||||
def test_syspath_posix_unchanged(self):
|
def test_syspath_posix_unchanged(self):
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue