diff --git a/.travis.yml b/.travis.yml index 4a17ab2ea..f78612b7e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,6 @@ language: python sudo: false -branches: - only: - - master - matrix: include: - python: 2.7 diff --git a/beets/__init__.py b/beets/__init__.py index 89ab74708..57fa66b69 100644 --- a/beets/__init__.py +++ b/beets/__init__.py @@ -13,15 +13,15 @@ # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. -from __future__ import absolute_import, unicode_literals +from __future__ import division, absolute_import, print_function import os import beets.library from beets.util import confit -__version__ = '1.3.18' -__author__ = 'Adrian Sampson ' +__version__ = u'1.3.18' +__author__ = u'Adrian Sampson ' Library = beets.library.Library diff --git a/beets/autotag/__init__.py b/beets/autotag/__init__.py index 924eb85f2..f8233be61 100644 --- a/beets/autotag/__init__.py +++ b/beets/autotag/__init__.py @@ -16,8 +16,7 @@ """Facilities for automatically determining files' correct metadata. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from beets import logging from beets import config diff --git a/beets/autotag/hooks.py b/beets/autotag/hooks.py index 303ce3418..26b7f5819 100644 --- a/beets/autotag/hooks.py +++ b/beets/autotag/hooks.py @@ -14,8 +14,7 @@ # included in all copies or substantial portions of the Software. """Glue between metadata sources and the matching logic.""" -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from collections import namedtuple import re @@ -394,7 +393,7 @@ class Distance(object): """ if not isinstance(dist, Distance): raise ValueError( - '`dist` must be a Distance object, not {0}'.format(type(dist)) + u'`dist` must be a Distance object, not {0}'.format(type(dist)) ) for key, penalties in dist._penalties.iteritems(): self._penalties.setdefault(key, []).extend(penalties) @@ -418,7 +417,7 @@ class Distance(object): """ if not 0.0 <= dist <= 1.0: raise ValueError( - '`dist` must be between 0.0 and 1.0, not {0}'.format(dist) + u'`dist` must be between 0.0 and 1.0, not {0}'.format(dist) ) self._penalties.setdefault(key, []).append(dist) @@ -514,7 +513,7 @@ def album_for_mbid(release_id): try: album = mb.album_for_id(release_id) if album: - plugins.send('albuminfo_received', info=album) + plugins.send(u'albuminfo_received', info=album) return album except mb.MusicBrainzAPIError as exc: exc.log(log) @@ -527,7 +526,7 @@ def track_for_mbid(recording_id): try: track = mb.track_for_id(recording_id) if track: - plugins.send('trackinfo_received', info=track) + plugins.send(u'trackinfo_received', info=track) return track except mb.MusicBrainzAPIError as exc: exc.log(log) @@ -538,7 +537,7 @@ def albums_for_id(album_id): candidates = [album_for_mbid(album_id)] plugin_albums = plugins.album_for_id(album_id) for a in plugin_albums: - plugins.send('albuminfo_received', info=a) + plugins.send(u'albuminfo_received', info=a) candidates.extend(plugin_albums) return filter(None, candidates) @@ -548,7 +547,7 @@ def tracks_for_id(track_id): candidates = [track_for_mbid(track_id)] plugin_tracks = plugins.track_for_id(track_id) for t in plugin_tracks: - plugins.send('trackinfo_received', info=t) + plugins.send(u'trackinfo_received', info=t) candidates.extend(plugin_tracks) return filter(None, candidates) @@ -581,7 +580,7 @@ def album_candidates(items, artist, album, va_likely): # Notify subscribed plugins about fetched album info for a in out: - plugins.send('albuminfo_received', info=a) + plugins.send(u'albuminfo_received', info=a) return out @@ -605,6 +604,6 @@ def item_candidates(item, artist, title): # Notify subscribed plugins about fetched track info for i in out: - plugins.send('trackinfo_received', info=i) + plugins.send(u'trackinfo_received', info=i) return out diff --git a/beets/autotag/match.py b/beets/autotag/match.py index 3565dba3f..e16b0dfaa 100644 --- a/beets/autotag/match.py +++ b/beets/autotag/match.py @@ -17,8 +17,7 @@ releases and tracks. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import datetime import re @@ -337,7 +336,7 @@ def _add_candidate(items, results, info): # Discard albums with zero tracks. if not info.tracks: - log.debug('No tracks.') + log.debug(u'No tracks.') return # Don't duplicate. diff --git a/beets/autotag/mb.py b/beets/autotag/mb.py index cc1780365..e64da8d5c 100644 --- a/beets/autotag/mb.py +++ b/beets/autotag/mb.py @@ -15,8 +15,7 @@ """Searches for albums in the MusicBrainz database. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import musicbrainzngs import re @@ -43,7 +42,7 @@ class MusicBrainzAPIError(util.HumanReadableException): def __init__(self, reason, verb, query, tb=None): self.query = query if isinstance(reason, musicbrainzngs.WebServiceError): - reason = 'MusicBrainz not reachable' + reason = u'MusicBrainz not reachable' super(MusicBrainzAPIError, self).__init__(reason, verb, tb) def get_message(self): @@ -162,7 +161,7 @@ def track_info(recording, index=None, medium=None, medium_index=None, medium=medium, medium_index=medium_index, medium_total=medium_total, - data_source='MusicBrainz', + data_source=u'MusicBrainz', data_url=track_url(recording['id']), ) @@ -256,7 +255,7 @@ def album_info(release): mediums=len(release['medium-list']), artist_sort=artist_sort_name, artist_credit=artist_credit_name, - data_source='MusicBrainz', + data_source=u'MusicBrainz', data_url=album_url(release['id']), ) info.va = info.artist_id == VARIOUS_ARTISTS_ID @@ -377,7 +376,7 @@ def _parse_id(s): no ID can be found, return None. """ # Find the first thing that looks like a UUID/MBID. - match = re.search('[a-f0-9]{8}(-[a-f0-9]{4}){3}-[a-f0-9]{12}', s) + match = re.search(ur'[a-f0-9]{8}(-[a-f0-9]{4}){3}-[a-f0-9]{12}', s) if match: return match.group() @@ -398,7 +397,7 @@ def album_for_id(releaseid): log.debug(u'Album ID match failed.') return None except musicbrainzngs.MusicBrainzError as exc: - raise MusicBrainzAPIError(exc, 'get release by ID', albumid, + raise MusicBrainzAPIError(exc, u'get release by ID', albumid, traceback.format_exc()) return album_info(res['release']) @@ -417,6 +416,6 @@ def track_for_id(releaseid): log.debug(u'Track ID match failed.') return None except musicbrainzngs.MusicBrainzError as exc: - raise MusicBrainzAPIError(exc, 'get recording by ID', trackid, + raise MusicBrainzAPIError(exc, u'get recording by ID', trackid, traceback.format_exc()) return track_info(res['recording']) diff --git a/beets/dbcore/__init__.py b/beets/dbcore/__init__.py index 78b53c192..689e7202c 100644 --- a/beets/dbcore/__init__.py +++ b/beets/dbcore/__init__.py @@ -16,7 +16,7 @@ """DBCore is an abstract database package that forms the basis for beets' Library. """ -from __future__ import absolute_import +from __future__ import division, absolute_import, print_function from .db import Model, Database from .query import Query, FieldQuery, MatchQuery, AndQuery, OrQuery diff --git a/beets/dbcore/db.py b/beets/dbcore/db.py index d784ddcae..09a96d8c2 100644 --- a/beets/dbcore/db.py +++ b/beets/dbcore/db.py @@ -15,8 +15,7 @@ """The central Model and Database constructs for DBCore. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import time import os @@ -201,9 +200,11 @@ class Model(object): exception is raised otherwise. """ if not self._db: - raise ValueError('{0} has no database'.format(type(self).__name__)) + raise ValueError( + u'{0} has no database'.format(type(self).__name__) + ) if need_id and not self.id: - raise ValueError('{0} has no id'.format(type(self).__name__)) + raise ValueError(u'{0} has no id'.format(type(self).__name__)) # Essential field accessors. @@ -255,11 +256,11 @@ class Model(object): del self._values_flex[key] self._dirty.add(key) # Mark for dropping on store. elif key in self._getters(): # Computed. - raise KeyError('computed field {0} cannot be deleted'.format(key)) + raise KeyError(u'computed field {0} cannot be deleted'.format(key)) elif key in self._fields: # Fixed. - raise KeyError('fixed field {0} cannot be deleted'.format(key)) + raise KeyError(u'fixed field {0} cannot be deleted'.format(key)) else: - raise KeyError('no such field {0}'.format(key)) + raise KeyError(u'no such field {0}'.format(key)) def keys(self, computed=False): """Get a list of available field names for this object. The @@ -318,12 +319,12 @@ class Model(object): def __getattr__(self, key): if key.startswith('_'): - raise AttributeError('model has no attribute {0!r}'.format(key)) + raise AttributeError(u'model has no attribute {0!r}'.format(key)) else: try: return self[key] except KeyError: - raise AttributeError('no such field {0!r}'.format(key)) + raise AttributeError(u'no such field {0!r}'.format(key)) def __setattr__(self, key, value): if key.startswith('_'): @@ -390,7 +391,7 @@ class Model(object): """ self._check_db() stored_obj = self._db._get(type(self), self.id) - assert stored_obj is not None, "object {0} not in DB".format(self.id) + assert stored_obj is not None, u"object {0} not in DB".format(self.id) self._values_fixed = {} self._values_flex = {} self.update(dict(stored_obj)) @@ -463,7 +464,7 @@ class Model(object): """Parse a string as a value for the given key. """ if not isinstance(string, basestring): - raise TypeError("_parse() argument must be a string") + raise TypeError(u"_parse() argument must be a string") return cls._type(key).parse(string) @@ -611,7 +612,7 @@ class Results(object): it.next() return it.next() except StopIteration: - raise IndexError('result index {0} out of range'.format(n)) + raise IndexError(u'result index {0} out of range'.format(n)) def get(self): """Return the first matching object, or None if no objects diff --git a/beets/dbcore/query.py b/beets/dbcore/query.py index f91992712..8e3b7ca16 100644 --- a/beets/dbcore/query.py +++ b/beets/dbcore/query.py @@ -15,8 +15,7 @@ """The Query type hierarchy for DBCore. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import re from operator import mul @@ -39,7 +38,7 @@ class InvalidQueryError(ParsingError): def __init__(self, query, explanation): if isinstance(query, list): query = " ".join(query) - message = "'{0}': {1}".format(query, explanation) + message = u"'{0}': {1}".format(query, explanation) super(InvalidQueryError, self).__init__(message) @@ -50,9 +49,9 @@ class InvalidQueryArgumentTypeError(ParsingError): query) InvalidQueryError can be raised. """ def __init__(self, what, expected, detail=None): - message = "'{0}' is not {1}".format(what, expected) + message = u"'{0}' is not {1}".format(what, expected) if detail: - message = "{0}: {1}".format(message, detail) + message = u"{0}: {1}".format(message, detail) super(InvalidQueryArgumentTypeError, self).__init__(message) @@ -208,7 +207,7 @@ class RegexpQuery(StringFieldQuery): except re.error as exc: # Invalid regular expression. raise InvalidQueryArgumentTypeError(pattern, - "a regular expression", + u"a regular expression", format(exc)) @staticmethod @@ -283,7 +282,7 @@ class NumericQuery(FieldQuery): try: return float(s) except ValueError: - raise InvalidQueryArgumentTypeError(s, "an int or a float") + raise InvalidQueryArgumentTypeError(s, u"an int or a float") def __init__(self, field, pattern, fast=True): super(NumericQuery, self).__init__(field, pattern, fast) @@ -328,7 +327,7 @@ class NumericQuery(FieldQuery): elif self.rangemax is not None: return u'{0} <= ?'.format(self.field), (self.rangemax,) else: - return '1', () + return u'1', () class CollectionQuery(Query): @@ -369,7 +368,7 @@ class CollectionQuery(Query): return clause, subvals def __repr__(self): - return "{0.__class__.__name__}({0.subqueries})".format(self) + return "{0.__class__.__name__}({0.subqueries!r})".format(self) def __eq__(self, other): return super(CollectionQuery, self).__eq__(other) and \ @@ -407,7 +406,7 @@ class AnyFieldQuery(CollectionQuery): return False def __repr__(self): - return ("{0.__class__.__name__}({0.pattern!r}, {0.fields}, " + return ("{0.__class__.__name__}({0.pattern!r}, {0.fields!r}, " "{0.query_class.__name__})".format(self)) def __eq__(self, other): @@ -467,7 +466,7 @@ class NotQuery(Query): return not self.subquery.match(item) def __repr__(self): - return "{0.__class__.__name__}({0.subquery})".format(self) + return "{0.__class__.__name__}({0.subquery!r})".format(self) def __eq__(self, other): return super(NotQuery, self).__eq__(other) and \ @@ -535,7 +534,7 @@ class Period(object): precision (a string, one of "year", "month", or "day"). """ if precision not in Period.precisions: - raise ValueError('Invalid precision {0}'.format(precision)) + raise ValueError(u'Invalid precision {0}'.format(precision)) self.date = date self.precision = precision @@ -575,7 +574,7 @@ class Period(object): elif 'day' == precision: return date + timedelta(days=1) else: - raise ValueError('unhandled precision {0}'.format(precision)) + raise ValueError(u'unhandled precision {0}'.format(precision)) class DateInterval(object): @@ -587,7 +586,7 @@ class DateInterval(object): def __init__(self, start, end): if start is not None and end is not None and not start < end: - raise ValueError("start date {0} is not before end date {1}" + raise ValueError(u"start date {0} is not before end date {1}" .format(start, end)) self.start = start self.end = end @@ -608,7 +607,7 @@ class DateInterval(object): return True def __str__(self): - return'[{0}, {1})'.format(self.start, self.end) + return '[{0}, {1})'.format(self.start, self.end) class DateQuery(FieldQuery): @@ -677,7 +676,7 @@ class DurationQuery(NumericQuery): except ValueError: raise InvalidQueryArgumentTypeError( s, - "a M:SS string or a float") + u"a M:SS string or a float") # Sorting. @@ -769,7 +768,7 @@ class MultipleSort(Sort): return items def __repr__(self): - return u'MultipleSort({0})'.format(repr(self.sorts)) + return 'MultipleSort({!r})'.format(self.sorts) def __hash__(self): return hash(tuple(self.sorts)) @@ -802,7 +801,7 @@ class FieldSort(Sort): return sorted(objs, key=key, reverse=not self.ascending) def __repr__(self): - return u'<{0}: {1}{2}>'.format( + return '<{0}: {1}{2}>'.format( type(self).__name__, self.field, '+' if self.ascending else '-', diff --git a/beets/dbcore/types.py b/beets/dbcore/types.py index e90fd9d9b..2726969dd 100644 --- a/beets/dbcore/types.py +++ b/beets/dbcore/types.py @@ -15,8 +15,7 @@ """Representation of type information for DBCore model fields. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from . import query from beets.util import str2bool diff --git a/beets/importer.py b/beets/importer.py index f4dd4853d..e73a9e08f 100644 --- a/beets/importer.py +++ b/beets/importer.py @@ -13,8 +13,7 @@ # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function """Provides the basic, interface-agnostic workflow for importing and autotagging music files. @@ -251,17 +250,17 @@ class ImportSession(object): if duplicate: # Duplicate: log all three choices (skip, keep both, and trump). if task.should_remove_duplicates: - self.tag_log('duplicate-replace', paths) + self.tag_log(u'duplicate-replace', paths) elif task.choice_flag in (action.ASIS, action.APPLY): - self.tag_log('duplicate-keep', paths) + self.tag_log(u'duplicate-keep', paths) elif task.choice_flag is (action.SKIP): - self.tag_log('duplicate-skip', paths) + self.tag_log(u'duplicate-skip', paths) else: # Non-duplicate: log "skip" and "asis" choices. if task.choice_flag is action.ASIS: - self.tag_log('asis', paths) + self.tag_log(u'asis', paths) elif task.choice_flag is action.SKIP: - self.tag_log('skip', paths) + self.tag_log(u'skip', paths) def should_resume(self, path): raise NotImplementedError @@ -1150,7 +1149,7 @@ class ImportTaskFactory(object): if not (self.session.config['move'] or self.session.config['copy']): log.warn(u"Archive importing requires either " - "'copy' or 'move' to be enabled.") + u"'copy' or 'move' to be enabled.") return log.debug(u'Extracting archive: {0}', @@ -1325,7 +1324,7 @@ def resolve_duplicates(session, task): if task.choice_flag in (action.ASIS, action.APPLY, action.RETAG): found_duplicates = task.find_duplicates(session.lib) if found_duplicates: - log.debug('found duplicates: {}'.format( + log.debug(u'found duplicates: {}'.format( [o.id for o in found_duplicates] )) session.resolve_duplicate(task, found_duplicates) @@ -1342,7 +1341,7 @@ def import_asis(session, task): if task.skip: return - log.info('{}', displayable_path(task.paths)) + log.info(u'{}', displayable_path(task.paths)) task.set_choice(action.ASIS) apply_choice(session, task) diff --git a/beets/library.py b/beets/library.py index 1c2fac944..f2c3875b0 100644 --- a/beets/library.py +++ b/beets/library.py @@ -15,8 +15,7 @@ """The core data store and collection logic for beets. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import os import sys @@ -627,7 +626,7 @@ class Item(LibModel): self.write(path, tags) return True except FileOperationError as exc: - log.error("{0}", exc) + log.error(u"{0}", exc) return False def try_sync(self, write, move, with_album=True): @@ -647,7 +646,7 @@ class Item(LibModel): if move: # Check whether this file is inside the library directory. if self._db and self._db.directory in util.ancestry(self.path): - log.debug('moving {0} to synchronize path', + log.debug(u'moving {0} to synchronize path', util.displayable_path(self.path)) self.move(with_album=with_album) self.store() @@ -796,7 +795,7 @@ class Item(LibModel): if query == PF_KEY_DEFAULT: break else: - assert False, "no default path format" + assert False, u"no default path format" if isinstance(path_format, Template): subpath_tmpl = path_format else: @@ -826,9 +825,12 @@ class Item(LibModel): if fellback: # Print an error message if legalization fell back to # default replacements because of the maximum length. - log.warning('Fell back to default replacements when naming ' - 'file {}. Configure replacements to avoid lengthening ' - 'the filename.', subpath) + log.warning( + u'Fell back to default replacements when naming ' + u'file {}. Configure replacements to avoid lengthening ' + u'the filename.', + subpath + ) if fragment: return subpath @@ -1016,7 +1018,7 @@ class Album(LibModel): """ item = self.items().get() if not item: - raise ValueError('empty album') + raise ValueError(u'empty album') return os.path.dirname(item.path) def _albumtotal(self): @@ -1170,7 +1172,7 @@ def parse_query_string(s, model_cls): The string is split into components using shell-like syntax. """ - assert isinstance(s, unicode), "Query is not unicode: {0!r}".format(s) + assert isinstance(s, unicode), u"Query is not unicode: {0!r}".format(s) try: parts = util.shlex_split(s) except ValueError as exc: diff --git a/beets/logging.py b/beets/logging.py index 40748bc68..e4e628d69 100644 --- a/beets/logging.py +++ b/beets/logging.py @@ -21,8 +21,7 @@ that when getLogger(name) instantiates a logger that logger uses {}-style formatting. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from copy import copy from logging import * # noqa diff --git a/beets/mediafile.py b/beets/mediafile.py index c6d265b40..1bd7b8a47 100644 --- a/beets/mediafile.py +++ b/beets/mediafile.py @@ -33,8 +33,7 @@ Internally ``MediaFile`` uses ``MediaField`` descriptors to access the data from the tags. In turn ``MediaField`` uses a number of ``StorageStyle`` strategies to handle format specific logic. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import mutagen import mutagen.mp3 @@ -650,13 +649,13 @@ class MP4BoolStorageStyle(MP4StorageStyle): return None def get_list(self, mutagen_file): - raise NotImplementedError('MP4 bool storage does not support lists') + raise NotImplementedError(u'MP4 bool storage does not support lists') def set(self, mutagen_file, value): mutagen_file[self.key] = value def set_list(self, mutagen_file, values): - raise NotImplementedError('MP4 bool storage does not support lists') + raise NotImplementedError(u'MP4 bool storage does not support lists') class MP4ImageStorageStyle(MP4ListStorageStyle): @@ -674,7 +673,7 @@ class MP4ImageStorageStyle(MP4ListStorageStyle): elif image.mime_type == 'image/jpeg': kind = mutagen.mp4.MP4Cover.FORMAT_JPEG else: - raise ValueError('MP4 files only supports PNG and JPEG images') + raise ValueError(u'MP4 files only supports PNG and JPEG images') return mutagen.mp4.MP4Cover(image.data, kind) @@ -1364,11 +1363,11 @@ class MediaFile(object): # anywhere else. raise else: - log.debug('{}', traceback.format_exc()) + log.debug(u'{}', traceback.format_exc()) raise MutagenError(path, exc) except Exception as exc: # Isolate bugs in Mutagen. - log.debug('{}', traceback.format_exc()) + log.debug(u'{}', traceback.format_exc()) log.error(u'uncaught Mutagen exception in open: {0}', exc) raise MutagenError(path, exc) @@ -1441,7 +1440,7 @@ class MediaFile(object): # Propagate these through: they don't represent Mutagen bugs. raise except Exception as exc: - log.debug('{}', traceback.format_exc()) + log.debug(u'{}', traceback.format_exc()) log.error(u'uncaught Mutagen exception in save: {0}', exc) raise MutagenError(self.path, exc) diff --git a/beets/plugins.py b/beets/plugins.py index 4233003ea..ebc37796c 100755 --- a/beets/plugins.py +++ b/beets/plugins.py @@ -15,8 +15,7 @@ """Support for beets plugins.""" -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import inspect import traceback @@ -267,7 +266,7 @@ def load_plugins(names=()): except: log.warn( - '** error loading plugin {}:\n{}', + u'** error loading plugin {}:\n{}', name, traceback.format_exc(), ) @@ -322,8 +321,8 @@ def types(model_cls): if field in types and plugin_types[field] != types[field]: raise PluginConflictException( u'Plugin {0} defines flexible field {1} ' - 'which has already been defined with ' - 'another type.'.format(plugin.name, field) + u'which has already been defined with ' + u'another type.'.format(plugin.name, field) ) types.update(plugin_types) return types diff --git a/beets/ui/__init__.py b/beets/ui/__init__.py index d395fe465..8daefa12a 100644 --- a/beets/ui/__init__.py +++ b/beets/ui/__init__.py @@ -18,8 +18,7 @@ interface. To invoke the CLI, just call beets.ui.main(). The actual CLI commands are implemented in the ui.commands module. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import locale import optparse @@ -192,7 +191,7 @@ def input_(prompt=None): try: resp = raw_input() except EOFError: - raise UserError('stdin stream ended while input required') + raise UserError(u'stdin stream ended while input required') return resp.decode(sys.stdin.encoding or 'utf8', 'ignore') @@ -238,7 +237,7 @@ def input_options(options, require=False, prompt=None, fallback_prompt=None, found_letter = letter break else: - raise ValueError('no unambiguous lettering found') + raise ValueError(u'no unambiguous lettering found') letters[found_letter.lower()] = option index = option.index(found_letter) @@ -321,9 +320,9 @@ def input_options(options, require=False, prompt=None, fallback_prompt=None, # Make a fallback prompt too. This is displayed if the user enters # something that is not recognized. if not fallback_prompt: - fallback_prompt = 'Enter one of ' + fallback_prompt = u'Enter one of ' if numrange: - fallback_prompt += '%i-%i, ' % numrange + fallback_prompt += u'%i-%i, ' % numrange fallback_prompt += ', '.join(display_letters) + ':' resp = input_(prompt) @@ -362,9 +361,9 @@ def input_yn(prompt, require=False): "yes" unless `require` is `True`, in which case there is no default. """ sel = input_options( - ('y', 'n'), require, prompt, 'Enter Y or N:' + ('y', 'n'), require, prompt, u'Enter Y or N:' ) - return sel == 'y' + return sel == u'y' def input_select_objects(prompt, objs, rep): @@ -376,18 +375,18 @@ def input_select_objects(prompt, objs, rep): object to print it out when confirming objects individually. """ choice = input_options( - ('y', 'n', 's'), False, - '%s? (Yes/no/select)' % prompt) + (u'y', u'n', u's'), False, + u'%s? (Yes/no/select)' % prompt) print() # Blank line. - if choice == 'y': # Yes. + if choice == u'y': # Yes. return objs - elif choice == 's': # Select. + elif choice == u's': # Select. out = [] for obj in objs: rep(obj) - if input_yn('%s? (yes/no)' % prompt, True): + if input_yn(u'%s? (yes/no)' % prompt, True): out.append(obj) print() # go to a new line return out @@ -400,14 +399,14 @@ def input_select_objects(prompt, objs, rep): def human_bytes(size): """Formats size, a number of bytes, in a human-readable way.""" - powers = ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y', 'H'] + powers = [u'', u'K', u'M', u'G', u'T', u'P', u'E', u'Z', u'Y', u'H'] unit = 'B' for power in powers: if size < 1024: - return "%3.1f %s%s" % (size, power, unit) + return u"%3.1f %s%s" % (size, power, unit) size /= 1024.0 - unit = 'iB' - return "big" + unit = u'iB' + return u"big" def human_seconds(interval): @@ -415,13 +414,13 @@ def human_seconds(interval): interval using English words. """ units = [ - (1, 'second'), - (60, 'minute'), - (60, 'hour'), - (24, 'day'), - (7, 'week'), - (52, 'year'), - (10, 'decade'), + (1, u'second'), + (60, u'minute'), + (60, u'hour'), + (24, u'day'), + (7, u'week'), + (52, u'year'), + (10, u'decade'), ] for i in range(len(units) - 1): increment, suffix = units[i] @@ -434,7 +433,7 @@ def human_seconds(interval): increment, suffix = units[-1] interval /= float(increment) - return "%3.1f %ss" % (interval, suffix) + return u"%3.1f %ss" % (interval, suffix) def human_seconds_short(interval): @@ -495,7 +494,7 @@ def _colorize(color, text): elif color in LIGHT_COLORS: escape = COLOR_ESCAPE + "%i;01m" % (LIGHT_COLORS[color] + 30) else: - raise ValueError('no such color %s', color) + raise ValueError(u'no such color %s', color) return escape + text + RESET_COLOR @@ -777,7 +776,7 @@ class CommonOptionsParser(optparse.OptionParser, object): Sets the album property on the options extracted from the CLI. """ album = optparse.Option(*flags, action='store_true', - help='match albums instead of tracks') + help=u'match albums instead of tracks') self.add_option(album) self._album_flags = set(flags) @@ -822,7 +821,7 @@ class CommonOptionsParser(optparse.OptionParser, object): callback=self._set_format, callback_kwargs={'fmt': '$path', 'store_true': True}, - help='print paths for matched items or albums') + help=u'print paths for matched items or albums') self.add_option(path) def add_format_option(self, flags=('-f', '--format'), target=None): @@ -850,7 +849,7 @@ class CommonOptionsParser(optparse.OptionParser, object): opt = optparse.Option(*flags, action='callback', callback=self._set_format, callback_kwargs=kwargs, - help='print with custom format') + help=u'print with custom format') self.add_option(opt) def add_all_common_options(self): @@ -916,7 +915,7 @@ class SubcommandsOptionParser(CommonOptionsParser): """ # A more helpful default usage. if 'usage' not in kwargs: - kwargs['usage'] = """ + kwargs['usage'] = u""" %prog COMMAND [ARGS...] %prog help COMMAND""" kwargs['add_help_option'] = False @@ -1024,7 +1023,7 @@ class SubcommandsOptionParser(CommonOptionsParser): cmdname = args.pop(0) subcommand = self._subcommand_for_name(cmdname) if not subcommand: - raise UserError("unknown command '{0}'".format(cmdname)) + raise UserError(u"unknown command '{0}'".format(cmdname)) suboptions, subargs = subcommand.parse_args(args) return subcommand, suboptions, subargs @@ -1076,7 +1075,7 @@ def _load_plugins(config): """ paths = config['pluginpath'].get(confit.StrSeq(split=False)) paths = map(util.normpath, paths) - log.debug('plugin paths: {0}', util.displayable_path(paths)) + log.debug(u'plugin paths: {0}', util.displayable_path(paths)) import beetsplug beetsplug.__path__ = paths + beetsplug.__path__ @@ -1146,10 +1145,13 @@ def _configure(options): old_key = 'list_format_{0}'.format(elem) if config[old_key].exists(): new_key = 'format_{0}'.format(elem) - log.warning('Warning: configuration uses "{0}" which is deprecated' - ' in favor of "{1}" now that it affects all commands. ' - 'See changelog & documentation.'.format(old_key, - new_key)) + log.warning( + u'Warning: configuration uses "{0}" which is deprecated' + u' in favor of "{1}" now that it affects all commands. ' + u'See changelog & documentation.', + old_key, + new_key, + ) config[new_key].set(config[old_key]) config_path = config.user_config_path() @@ -1178,7 +1180,7 @@ def _open_library(config): ) lib.get_item(0) # Test database connection. except (sqlite3.OperationalError, sqlite3.DatabaseError): - log.debug('{}', traceback.format_exc()) + log.debug(u'{}', traceback.format_exc()) raise UserError(u"database file {0} could not be opened".format( util.displayable_path(dbpath) )) @@ -1197,15 +1199,15 @@ def _raw_main(args, lib=None): parser.add_format_option(flags=('--format-item',), target=library.Item) parser.add_format_option(flags=('--format-album',), target=library.Album) parser.add_option('-l', '--library', dest='library', - help='library database file to use') + help=u'library database file to use') parser.add_option('-d', '--directory', dest='directory', - help="destination music directory") + help=u"destination music directory") parser.add_option('-v', '--verbose', dest='verbose', action='count', - help='log more details (use twice for even more)') + help=u'log more details (use twice for even more)') parser.add_option('-c', '--config', dest='config', - help='path to configuration file') + help=u'path to configuration file') parser.add_option('-h', '--help', dest='help', action='store_true', - help='show this help message and exit') + help=u'show this help message and exit') parser.add_option('--version', dest='version', action='store_true', help=optparse.SUPPRESS_HELP) @@ -1261,4 +1263,4 @@ def main(args=None): raise except KeyboardInterrupt: # Silently ignore ^C except in verbose mode. - log.debug('{}', traceback.format_exc()) + log.debug(u'{}', traceback.format_exc()) diff --git a/beets/ui/commands.py b/beets/ui/commands.py index 641b1186f..a2669e688 100644 --- a/beets/ui/commands.py +++ b/beets/ui/commands.py @@ -17,8 +17,7 @@ interface. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import os import re @@ -72,9 +71,9 @@ def _do_query(lib, query, album, also_items=True): items = list(lib.items(query)) if album and not albums: - raise ui.UserError('No matching albums found.') + raise ui.UserError(u'No matching albums found.') elif not album and not items: - raise ui.UserError('No matching items found.') + raise ui.UserError(u'No matching items found.') return items, albums @@ -94,25 +93,25 @@ def fields_func(lib, opts, args): names.sort() print_(" " + "\n ".join(names)) - print_("Item fields:") + print_(u"Item fields:") _print_rows(library.Item.all_keys()) - print_("Album fields:") + print_(u"Album fields:") _print_rows(library.Album.all_keys()) with lib.transaction() as tx: # The SQL uses the DISTINCT to get unique values from the query unique_fields = 'SELECT DISTINCT key FROM (%s)' - print_("Item flexible attributes:") + print_(u"Item flexible attributes:") _print_keys(tx.query(unique_fields % library.Item._flex_table)) - print_("Album flexible attributes:") + print_(u"Album flexible attributes:") _print_keys(tx.query(unique_fields % library.Album._flex_table)) fields_cmd = ui.Subcommand( 'fields', - help='show fields available for queries and format strings' + help=u'show fields available for queries and format strings' ) fields_cmd.func = fields_func default_commands.append(fields_cmd) @@ -125,7 +124,7 @@ class HelpCommand(ui.Subcommand): def __init__(self): super(HelpCommand, self).__init__( 'help', aliases=('?',), - help='give detailed help on a specific sub-command', + help=u'give detailed help on a specific sub-command', ) def func(self, lib, opts, args): @@ -133,7 +132,7 @@ class HelpCommand(ui.Subcommand): cmdname = args[0] helpcommand = self.root_parser._subcommand_for_name(cmdname) if not helpcommand: - raise ui.UserError("unknown command '{0}'".format(cmdname)) + raise ui.UserError(u"unknown command '{0}'".format(cmdname)) helpcommand.print_help() else: self.root_parser.print_help() @@ -180,7 +179,7 @@ def dist_string(dist): """Formats a distance (a float) as a colorized similarity percentage string. """ - out = '%.1f%%' % ((1 - dist) * 100) + out = u'%.1f%%' % ((1 - dist) * 100) if dist <= config['match']['strong_rec_thresh'].as_number(): out = ui.colorize('text_success', out) elif dist <= config['match']['medium_rec_thresh'].as_number(): @@ -203,7 +202,7 @@ def penalty_string(distance, limit=None): if penalties: if limit and len(penalties) > limit: penalties = penalties[:limit] + ['...'] - return ui.colorize('text_warning', '(%s)' % ', '.join(penalties)) + return ui.colorize('text_warning', u'(%s)' % ', '.join(penalties)) def show_change(cur_artist, cur_album, match): @@ -254,21 +253,21 @@ def show_change(cur_artist, cur_album, match): artist_l, artist_r = ui.colordiff(artist_l, artist_r) album_l, album_r = ui.colordiff(album_l, album_r) - print_("Correcting tags from:") + print_(u"Correcting tags from:") show_album(artist_l, album_l) - print_("To:") + print_(u"To:") show_album(artist_r, album_r) else: print_(u"Tagging:\n {0.artist} - {0.album}".format(match.info)) # Data URL. if match.info.data_url: - print_('URL:\n %s' % match.info.data_url) + print_(u'URL:\n %s' % match.info.data_url) # Info line. info = [] # Similarity. - info.append('(Similarity: %s)' % dist_string(match.distance)) + info.append(u'(Similarity: %s)' % dist_string(match.distance)) # Penalties. penalties = penalty_string(match.distance) if penalties: @@ -276,7 +275,7 @@ def show_change(cur_artist, cur_album, match): # Disambiguation. disambig = disambig_string(match.info) if disambig: - info.append(ui.colorize('text_highlight_minor', '(%s)' % disambig)) + info.append(ui.colorize('text_highlight_minor', u'(%s)' % disambig)) print_(' '.join(info)) # Tracks. @@ -294,16 +293,16 @@ def show_change(cur_artist, cur_album, match): if medium != track_info.medium or disctitle != track_info.disctitle: media = match.info.media or 'Media' if match.info.mediums > 1 and track_info.disctitle: - lhs = '%s %s: %s' % (media, track_info.medium, - track_info.disctitle) + lhs = u'%s %s: %s' % (media, track_info.medium, + track_info.disctitle) elif match.info.mediums > 1: - lhs = '%s %s' % (media, track_info.medium) + lhs = u'%s %s' % (media, track_info.medium) elif track_info.disctitle: - lhs = '%s: %s' % (media, track_info.disctitle) + lhs = u'%s: %s' % (media, track_info.disctitle) else: lhs = None if lhs: - lines.append((lhs, '', 0)) + lines.append((lhs, u'', 0)) medium, disctitle = track_info.medium, track_info.disctitle # Titles. @@ -346,9 +345,9 @@ def show_change(cur_artist, cur_album, match): rhs += ' %s' % penalties if lhs != rhs: - lines.append((' * %s' % lhs, rhs, lhs_width)) + lines.append((u' * %s' % lhs, rhs, lhs_width)) elif config['import']['detail']: - lines.append((' * %s' % lhs, '', lhs_width)) + lines.append((u' * %s' % lhs, '', lhs_width)) # Print each track in two columns, or across two lines. col_width = (ui.term_width() - len(''.join([' * ', ' -> ']))) // 2 @@ -365,22 +364,22 @@ def show_change(cur_artist, cur_album, match): # Missing and unmatched tracks. if match.extra_tracks: - print_('Missing tracks ({0}/{1} - {2:.1%}):'.format( + print_(u'Missing tracks ({0}/{1} - {2:.1%}):'.format( len(match.extra_tracks), len(match.info.tracks), len(match.extra_tracks) / len(match.info.tracks) )) for track_info in match.extra_tracks: - line = ' ! %s (#%s)' % (track_info.title, format_index(track_info)) + line = u' ! %s (#%s)' % (track_info.title, format_index(track_info)) if track_info.length: - line += ' (%s)' % ui.human_seconds_short(track_info.length) + line += u' (%s)' % ui.human_seconds_short(track_info.length) print_(ui.colorize('text_warning', line)) if match.extra_items: - print_('Unmatched tracks ({0}):'.format(len(match.extra_items))) + print_(u'Unmatched tracks ({0}):'.format(len(match.extra_items))) for item in match.extra_items: - line = ' ! %s (#%s)' % (item.title, format_index(item)) + line = u' ! %s (#%s)' % (item.title, format_index(item)) if item.length: - line += ' (%s)' % ui.human_seconds_short(item.length) + line += u' (%s)' % ui.human_seconds_short(item.length) print_(ui.colorize('text_warning', line)) @@ -395,22 +394,22 @@ def show_item_change(item, match): cur_artist, new_artist = ui.colordiff(cur_artist, new_artist) cur_title, new_title = ui.colordiff(cur_title, new_title) - print_("Correcting track tags from:") - print_(" %s - %s" % (cur_artist, cur_title)) - print_("To:") - print_(" %s - %s" % (new_artist, new_title)) + print_(u"Correcting track tags from:") + print_(u" %s - %s" % (cur_artist, cur_title)) + print_(u"To:") + print_(u" %s - %s" % (new_artist, new_title)) else: - print_("Tagging track: %s - %s" % (cur_artist, cur_title)) + print_(u"Tagging track: %s - %s" % (cur_artist, cur_title)) # Data URL. if match.info.data_url: - print_('URL:\n %s' % match.info.data_url) + print_(u'URL:\n %s' % match.info.data_url) # Info line. info = [] # Similarity. - info.append('(Similarity: %s)' % dist_string(match.distance)) + info.append(u'(Similarity: %s)' % dist_string(match.distance)) # Penalties. penalties = penalty_string(match.distance) if penalties: @@ -418,7 +417,7 @@ def show_item_change(item, match): # Disambiguation. disambig = disambig_string(match.info) if disambig: - info.append(ui.colorize('text_highlight_minor', '(%s)' % disambig)) + info.append(ui.colorize('text_highlight_minor', u'(%s)' % disambig)) print_(' '.join(info)) @@ -432,7 +431,7 @@ def summarize_items(items, singleton): """ summary_parts = [] if not singleton: - summary_parts.append("{0} items".format(len(items))) + summary_parts.append(u"{0} items".format(len(items))) format_counts = {} for item in items: @@ -450,11 +449,11 @@ def summarize_items(items, singleton): average_bitrate = sum([item.bitrate for item in items]) / len(items) total_duration = sum([item.length for item in items]) total_filesize = sum([item.filesize for item in items]) - summary_parts.append('{0}kbps'.format(int(average_bitrate / 1000))) + summary_parts.append(u'{0}kbps'.format(int(average_bitrate / 1000))) summary_parts.append(ui.human_seconds_short(total_duration)) summary_parts.append(ui.human_bytes(total_filesize)) - return ', '.join(summary_parts) + return u', '.join(summary_parts) def _summary_judgment(rec): @@ -484,9 +483,9 @@ def _summary_judgment(rec): return None if action == importer.action.SKIP: - print_('Skipping.') + print_(u'Skipping.') elif action == importer.action.ASIS: - print_('Importing as-is.') + print_(u'Importing as-is.') return action @@ -525,31 +524,31 @@ def choose_candidate(candidates, singleton, rec, cur_artist=None, # Zero candidates. if not candidates: if singleton: - print_("No matching recordings found.") - opts = ('Use as-is', 'Skip', 'Enter search', 'enter Id', - 'aBort') + print_(u"No matching recordings found.") + opts = (u'Use as-is', u'Skip', u'Enter search', u'enter Id', + u'aBort') else: - print_("No matching release found for {0} tracks." + print_(u"No matching release found for {0} tracks." .format(itemcount)) - print_('For help, see: ' - 'http://beets.readthedocs.org/en/latest/faq.html#nomatch') - opts = ('Use as-is', 'as Tracks', 'Group albums', 'Skip', - 'Enter search', 'enter Id', 'aBort') + print_(u'For help, see: ' + u'http://beets.readthedocs.org/en/latest/faq.html#nomatch') + opts = (u'Use as-is', u'as Tracks', u'Group albums', u'Skip', + u'Enter search', u'enter Id', u'aBort') sel = ui.input_options(opts + extra_opts) - if sel == 'u': + if sel == u'u': return importer.action.ASIS - elif sel == 't': + elif sel == u't': assert not singleton return importer.action.TRACKS - elif sel == 'e': + elif sel == u'e': return importer.action.MANUAL - elif sel == 's': + elif sel == u's': return importer.action.SKIP - elif sel == 'b': + elif sel == u'b': raise importer.ImportAbort() - elif sel == 'i': + elif sel == u'i': return importer.action.MANUAL_ID - elif sel == 'g': + elif sel == u'g': return importer.action.ALBUMS elif sel in extra_actions: return sel @@ -595,35 +594,35 @@ def choose_candidate(candidates, singleton, rec, cur_artist=None, disambig = disambig_string(match.info) if disambig: line.append(ui.colorize('text_highlight_minor', - '(%s)' % disambig)) + u'(%s)' % disambig)) - print_(' '.join(line)) + print_(u' '.join(line)) # Ask the user for a choice. if singleton: - opts = ('Skip', 'Use as-is', 'Enter search', 'enter Id', - 'aBort') + opts = (u'Skip', u'Use as-is', u'Enter search', u'enter Id', + u'aBort') else: - opts = ('Skip', 'Use as-is', 'as Tracks', 'Group albums', - 'Enter search', 'enter Id', 'aBort') + opts = (u'Skip', u'Use as-is', u'as Tracks', u'Group albums', + u'Enter search', u'enter Id', u'aBort') sel = ui.input_options(opts + extra_opts, numrange=(1, len(candidates))) - if sel == 's': + if sel == u's': return importer.action.SKIP - elif sel == 'u': + elif sel == u'u': return importer.action.ASIS - elif sel == 'm': + elif sel == u'm': pass - elif sel == 'e': + elif sel == u'e': return importer.action.MANUAL - elif sel == 't': + elif sel == u't': assert not singleton return importer.action.TRACKS - elif sel == 'b': + elif sel == u'b': raise importer.ImportAbort() - elif sel == 'i': + elif sel == u'i': return importer.action.MANUAL_ID - elif sel == 'g': + elif sel == u'g': return importer.action.ALBUMS elif sel in extra_actions: return sel @@ -647,38 +646,38 @@ def choose_candidate(candidates, singleton, rec, cur_artist=None, # Ask for confirmation. if singleton: - opts = ('Apply', 'More candidates', 'Skip', 'Use as-is', - 'Enter search', 'enter Id', 'aBort') + opts = (u'Apply', u'More candidates', u'Skip', u'Use as-is', + u'Enter search', u'enter Id', u'aBort') else: - opts = ('Apply', 'More candidates', 'Skip', 'Use as-is', - 'as Tracks', 'Group albums', 'Enter search', 'enter Id', - 'aBort') + opts = (u'Apply', u'More candidates', u'Skip', u'Use as-is', + u'as Tracks', u'Group albums', u'Enter search', + u'enter Id', u'aBort') default = config['import']['default_action'].as_choice({ - 'apply': 'a', - 'skip': 's', - 'asis': 'u', - 'none': None, + u'apply': u'a', + u'skip': u's', + u'asis': u'u', + u'none': None, }) if default is None: require = True sel = ui.input_options(opts + extra_opts, require=require, default=default) - if sel == 'a': + if sel == u'a': return match - elif sel == 'g': + elif sel == u'g': return importer.action.ALBUMS - elif sel == 's': + elif sel == u's': return importer.action.SKIP - elif sel == 'u': + elif sel == u'u': return importer.action.ASIS - elif sel == 't': + elif sel == u't': assert not singleton return importer.action.TRACKS - elif sel == 'e': + elif sel == u'e': return importer.action.MANUAL - elif sel == 'b': + elif sel == u'b': raise importer.ImportAbort() - elif sel == 'i': + elif sel == u'i': return importer.action.MANUAL_ID elif sel in extra_actions: return sel @@ -688,15 +687,15 @@ def manual_search(singleton): """Input either an artist and album (for full albums) or artist and track name (for singletons) for manual search. """ - artist = input_('Artist:') - name = input_('Track:' if singleton else 'Album:') + artist = input_(u'Artist:') + name = input_(u'Track:' if singleton else u'Album:') return artist.strip(), name.strip() def manual_id(singleton): """Input an ID, either for an album ("release") or a track ("recording"). """ - prompt = u'Enter {0} ID:'.format('recording' if singleton else 'release') + prompt = u'Enter {0} ID:'.format(u'recording' if singleton else u'release') return input_(prompt).strip() @@ -821,37 +820,37 @@ class TerminalImportSession(importer.ImportSession): that's already in the library. """ log.warn(u"This {0} is already in the library!", - ("album" if task.is_album else "item")) + (u"album" if task.is_album else u"item")) if config['import']['quiet']: # In quiet mode, don't prompt -- just skip. log.info(u'Skipping.') - sel = 's' + sel = u's' else: # Print some detail about the existing and new items so the # user can make an informed decision. for duplicate in found_duplicates: - print_("Old: " + summarize_items( + print_(u"Old: " + summarize_items( list(duplicate.items()) if task.is_album else [duplicate], not task.is_album, )) - print_("New: " + summarize_items( + print_(u"New: " + summarize_items( task.imported_items(), not task.is_album, )) sel = ui.input_options( - ('Skip new', 'Keep both', 'Remove old') + (u'Skip new', u'Keep both', u'Remove old') ) - if sel == 's': + if sel == u's': # Skip new. task.set_choice(importer.action.SKIP) - elif sel == 'k': + elif sel == u'k': # Keep both. Do nothing; leave the choice intact. pass - elif sel == 'r': + elif sel == u'r': # Remove old. task.should_remove_duplicates = True else: @@ -859,7 +858,7 @@ class TerminalImportSession(importer.ImportSession): def should_resume(self, path): return ui.input_yn(u"Import of the directory:\n{0}\n" - "was interrupted. Resume (Y/n)?" + u"was interrupted. Resume (Y/n)?" .format(displayable_path(path))) def _get_plugin_choices(self, task): @@ -880,14 +879,14 @@ class TerminalImportSession(importer.ImportSession): extra_choices = list(chain(*plugins.send('before_choose_candidate', session=self, task=task))) # Take into account default options, for duplicate checking. - all_choices = [PromptChoice('a', 'Apply', None), - PromptChoice('s', 'Skip', None), - PromptChoice('u', 'Use as-is', None), - PromptChoice('t', 'as Tracks', None), - PromptChoice('g', 'Group albums', None), - PromptChoice('e', 'Enter search', None), - PromptChoice('i', 'enter Id', None), - PromptChoice('b', 'aBort', None)] +\ + all_choices = [PromptChoice(u'a', u'Apply', None), + PromptChoice(u's', u'Skip', None), + PromptChoice(u'u', u'Use as-is', None), + PromptChoice(u't', u'as Tracks', None), + PromptChoice(u'g', u'Group albums', None), + PromptChoice(u'e', u'Enter search', None), + PromptChoice(u'i', u'enter Id', None), + PromptChoice(u'b', u'aBort', None)] +\ extra_choices short_letters = [c.short for c in all_choices] @@ -921,7 +920,7 @@ def import_files(lib, paths, query): # Check parameter consistency. if config['import']['quiet'] and config['import']['timid']: - raise ui.UserError("can't be both quiet and timid") + raise ui.UserError(u"can't be both quiet and timid") # Open the log. if config['import']['log'].get() is not None: @@ -961,90 +960,90 @@ def import_func(lib, opts, args): query = None paths = args if not paths: - raise ui.UserError('no path specified') + raise ui.UserError(u'no path specified') import_files(lib, paths, query) import_cmd = ui.Subcommand( - 'import', help='import new music', aliases=('imp', 'im') + u'import', help=u'import new music', aliases=(u'imp', u'im') ) import_cmd.parser.add_option( - '-c', '--copy', action='store_true', default=None, - help="copy tracks into library directory (default)" + u'-c', u'--copy', action='store_true', default=None, + help=u"copy tracks into library directory (default)" ) import_cmd.parser.add_option( - '-C', '--nocopy', action='store_false', dest='copy', - help="don't copy tracks (opposite of -c)" + u'-C', u'--nocopy', action='store_false', dest='copy', + help=u"don't copy tracks (opposite of -c)" ) import_cmd.parser.add_option( - '-w', '--write', action='store_true', default=None, - help="write new metadata to files' tags (default)" + u'-w', u'--write', action='store_true', default=None, + help=u"write new metadata to files' tags (default)" ) import_cmd.parser.add_option( - '-W', '--nowrite', action='store_false', dest='write', - help="don't write metadata (opposite of -w)" + u'-W', u'--nowrite', action='store_false', dest='write', + help=u"don't write metadata (opposite of -w)" ) import_cmd.parser.add_option( - '-a', '--autotag', action='store_true', dest='autotag', - help="infer tags for imported files (default)" + u'-a', u'--autotag', action='store_true', dest='autotag', + help=u"infer tags for imported files (default)" ) import_cmd.parser.add_option( - '-A', '--noautotag', action='store_false', dest='autotag', - help="don't infer tags for imported files (opposite of -a)" + u'-A', u'--noautotag', action='store_false', dest='autotag', + help=u"don't infer tags for imported files (opposite of -a)" ) import_cmd.parser.add_option( - '-p', '--resume', action='store_true', default=None, - help="resume importing if interrupted" + u'-p', u'--resume', action='store_true', default=None, + help=u"resume importing if interrupted" ) import_cmd.parser.add_option( - '-P', '--noresume', action='store_false', dest='resume', - help="do not try to resume importing" + u'-P', u'--noresume', action='store_false', dest='resume', + help=u"do not try to resume importing" ) import_cmd.parser.add_option( - '-q', '--quiet', action='store_true', dest='quiet', - help="never prompt for input: skip albums instead" + u'-q', u'--quiet', action='store_true', dest='quiet', + help=u"never prompt for input: skip albums instead" ) import_cmd.parser.add_option( - '-l', '--log', dest='log', - help='file to log untaggable albums for later review' + u'-l', u'--log', dest='log', + help=u'file to log untaggable albums for later review' ) import_cmd.parser.add_option( - '-s', '--singletons', action='store_true', - help='import individual tracks instead of full albums' + u'-s', u'--singletons', action='store_true', + help=u'import individual tracks instead of full albums' ) import_cmd.parser.add_option( - '-t', '--timid', dest='timid', action='store_true', - help='always confirm all actions' + u'-t', u'--timid', dest='timid', action='store_true', + help=u'always confirm all actions' ) import_cmd.parser.add_option( - '-L', '--library', dest='library', action='store_true', - help='retag items matching a query' + u'-L', u'--library', dest='library', action='store_true', + help=u'retag items matching a query' ) import_cmd.parser.add_option( - '-i', '--incremental', dest='incremental', action='store_true', - help='skip already-imported directories' + u'-i', u'--incremental', dest='incremental', action='store_true', + help=u'skip already-imported directories' ) import_cmd.parser.add_option( - '-I', '--noincremental', dest='incremental', action='store_false', - help='do not skip already-imported directories' + u'-I', u'--noincremental', dest='incremental', action='store_false', + help=u'do not skip already-imported directories' ) import_cmd.parser.add_option( - '--flat', dest='flat', action='store_true', - help='import an entire tree as a single album' + u'--flat', dest='flat', action='store_true', + help=u'import an entire tree as a single album' ) import_cmd.parser.add_option( - '-g', '--group-albums', dest='group_albums', action='store_true', - help='group tracks in a folder into separate albums' + u'-g', u'--group-albums', dest='group_albums', action='store_true', + help=u'group tracks in a folder into separate albums' ) import_cmd.parser.add_option( - '--pretend', dest='pretend', action='store_true', - help='just print the files to import' + u'--pretend', dest='pretend', action='store_true', + help=u'just print the files to import' ) import_cmd.parser.add_option( - '-S', '--search-id', dest='search_ids', action='append', + u'-S', u'--search-id', dest='search_ids', action='append', metavar='BACKEND_ID', - help='restrict matching to a specific metadata backend ID' + help=u'restrict matching to a specific metadata backend ID' ) import_cmd.func = import_func default_commands.append(import_cmd) @@ -1068,9 +1067,9 @@ def list_func(lib, opts, args): list_items(lib, decargs(args), opts.album) -list_cmd = ui.Subcommand('list', help='query the library', aliases=('ls',)) -list_cmd.parser.usage += "\n" \ - 'Example: %prog -f \'$album: $title\' artist:beatles' +list_cmd = ui.Subcommand(u'list', help=u'query the library', aliases=(u'ls',)) +list_cmd.parser.usage += u"\n" \ + u'Example: %prog -f \'$album: $title\' artist:beatles' list_cmd.parser.add_all_common_options() list_cmd.func = list_func default_commands.append(list_cmd) @@ -1118,7 +1117,7 @@ def update_items(lib, query, album, move, pretend): old_item = lib.get_item(item.id) if old_item.albumartist == old_item.artist == item.artist: item.albumartist = old_item.albumartist - item._dirty.discard('albumartist') + item._dirty.discard(u'albumartist') # Check for and display changes. changed = ui.show_model_changes(item, @@ -1171,21 +1170,21 @@ def update_func(lib, opts, args): update_cmd = ui.Subcommand( - 'update', help='update the library', aliases=('upd', 'up',) + u'update', help=u'update the library', aliases=(u'upd', u'up',) ) update_cmd.parser.add_album_option() update_cmd.parser.add_format_option() update_cmd.parser.add_option( - '-m', '--move', action='store_true', dest='move', - help="move files in the library directory" + u'-m', u'--move', action='store_true', dest='move', + help=u"move files in the library directory" ) update_cmd.parser.add_option( - '-M', '--nomove', action='store_false', dest='move', - help="don't move files in library" + u'-M', u'--nomove', action='store_false', dest='move', + help=u"don't move files in library" ) update_cmd.parser.add_option( - '-p', '--pretend', action='store_true', - help="show all changes but do nothing" + u'-p', u'--pretend', action='store_true', + help=u"show all changes but do nothing" ) update_cmd.func = update_func default_commands.append(update_cmd) @@ -1204,11 +1203,11 @@ def remove_items(lib, query, album, delete): print_() if delete: fmt = u'$path - $title' - prompt = 'Really DELETE %i file%s (y/n)?' % \ + prompt = u'Really DELETE %i file%s (y/n)?' % \ (len(items), 's' if len(items) > 1 else '') else: fmt = '' - prompt = 'Really remove %i item%s from the library (y/n)?' % \ + prompt = u'Really remove %i item%s from the library (y/n)?' % \ (len(items), 's' if len(items) > 1 else '') # Show all the items. @@ -1230,11 +1229,11 @@ def remove_func(lib, opts, args): remove_cmd = ui.Subcommand( - 'remove', help='remove matching items from the library', aliases=('rm',) + u'remove', help=u'remove matching items from the library', aliases=(u'rm',) ) remove_cmd.parser.add_option( - "-d", "--delete", action="store_true", - help="also remove files from disk" + u"-d", u"--delete", action="store_true", + help=u"also remove files from disk" ) remove_cmd.parser.add_album_option() remove_cmd.func = remove_func @@ -1259,7 +1258,7 @@ def show_stats(lib, query, exact): try: total_size += os.path.getsize(syspath(item.path)) except OSError as exc: - log.info('could not get size of {}: {}', item.path, exc) + log.info(u'could not get size of {}: {}', item.path, exc) else: total_size += int(item.length * item.bitrate / 8) total_time += item.length @@ -1269,11 +1268,11 @@ def show_stats(lib, query, exact): if item.album_id: albums.add(item.album_id) - size_str = '' + ui.human_bytes(total_size) + size_str = u'' + ui.human_bytes(total_size) if exact: - size_str += ' ({0} bytes)'.format(total_size) + size_str += u' ({0} bytes)'.format(total_size) - print_("""Tracks: {0} + print_(u"""Tracks: {0} Total time: {1}{2} {3}: {4} Artists: {5} @@ -1281,8 +1280,8 @@ Albums: {6} Album artists: {7}""".format( total_items, ui.human_seconds(total_time), - ' ({0:.2f} seconds)'.format(total_time) if exact else '', - 'Total size' if exact else 'Approximate total size', + u' ({0:.2f} seconds)'.format(total_time) if exact else '', + u'Total size' if exact else u'Approximate total size', size_str, len(artists), len(albums), @@ -1295,11 +1294,11 @@ def stats_func(lib, opts, args): stats_cmd = ui.Subcommand( - 'stats', help='show statistics about the library or a query' + u'stats', help=u'show statistics about the library or a query' ) stats_cmd.parser.add_option( - '-e', '--exact', action='store_true', - help='exact size and time' + u'-e', u'--exact', action='store_true', + help=u'exact size and time' ) stats_cmd.func = stats_func default_commands.append(stats_cmd) @@ -1308,17 +1307,17 @@ default_commands.append(stats_cmd) # version: Show current beets version. def show_version(lib, opts, args): - print_('beets version %s' % beets.__version__) + print_(u'beets version %s' % beets.__version__) # Show plugins. names = sorted(p.name for p in plugins.find_plugins()) if names: - print_('plugins:', ', '.join(names)) + print_(u'plugins:', ', '.join(names)) else: - print_('no plugins loaded') + print_(u'no plugins loaded') version_cmd = ui.Subcommand( - 'version', help='output version information' + u'version', help=u'output version information' ) version_cmd.func = show_version default_commands.append(version_cmd) @@ -1345,8 +1344,8 @@ def modify_items(lib, mods, dels, query, write, move, album, confirm): # Apply changes *temporarily*, preview them, and collect modified # objects. - print_('Modifying {0} {1}s.' - .format(len(objs), 'album' if album else 'item')) + print_(u'Modifying {0} {1}s.' + .format(len(objs), u'album' if album else u'item')) changed = set() for obj in objs: if print_and_modify(obj, mods, dels): @@ -1354,22 +1353,22 @@ def modify_items(lib, mods, dels, query, write, move, album, confirm): # Still something to do? if not changed: - print_('No changes to make.') + print_(u'No changes to make.') return # Confirm action. if confirm: if write and move: - extra = ', move and write tags' + extra = u', move and write tags' elif write: - extra = ' and write tags' + extra = u' and write tags' elif move: - extra = ' and move' + extra = u' and move' else: - extra = '' + extra = u'' changed = ui.input_select_objects( - 'Really modify%s' % extra, changed, + u'Really modify%s' % extra, changed, lambda o: print_and_modify(o, mods, dels) ) @@ -1417,35 +1416,35 @@ def modify_parse_args(args): def modify_func(lib, opts, args): query, mods, dels = modify_parse_args(decargs(args)) if not mods and not dels: - raise ui.UserError('no modifications specified') + raise ui.UserError(u'no modifications specified') modify_items(lib, mods, dels, query, ui.should_write(opts.write), ui.should_move(opts.move), opts.album, not opts.yes) modify_cmd = ui.Subcommand( - 'modify', help='change metadata fields', aliases=('mod',) + u'modify', help=u'change metadata fields', aliases=(u'mod',) ) modify_cmd.parser.add_option( - '-m', '--move', action='store_true', dest='move', - help="move files in the library directory" + u'-m', u'--move', action='store_true', dest='move', + help=u"move files in the library directory" ) modify_cmd.parser.add_option( - '-M', '--nomove', action='store_false', dest='move', - help="don't move files in library" + u'-M', u'--nomove', action='store_false', dest='move', + help=u"don't move files in library" ) modify_cmd.parser.add_option( - '-w', '--write', action='store_true', default=None, - help="write new metadata to files' tags (default)" + u'-w', u'--write', action='store_true', default=None, + help=u"write new metadata to files' tags (default)" ) modify_cmd.parser.add_option( - '-W', '--nowrite', action='store_false', dest='write', - help="don't write metadata (opposite of -w)" + u'-W', u'--nowrite', action='store_false', dest='write', + help=u"don't write metadata (opposite of -w)" ) modify_cmd.parser.add_album_option() modify_cmd.parser.add_format_option(target='item') modify_cmd.parser.add_option( - '-y', '--yes', action='store_true', - help='skip confirmation' + u'-y', u'--yes', action='store_true', + help=u'skip confirmation' ) modify_cmd.func = modify_func default_commands.append(modify_cmd) @@ -1466,11 +1465,11 @@ def move_items(lib, dest, query, copy, album, pretend, confirm=False): isalbummoved = lambda album: any(isitemmoved(i) for i in album.items()) objs = [o for o in objs if (isalbummoved if album else isitemmoved)(o)] - action = 'Copying' if copy else 'Moving' - act = 'copy' if copy else 'move' - entity = 'album' if album else 'item' + action = u'Copying' if copy else u'Moving' + act = u'copy' if copy else u'move' + entity = u'album' if album else u'item' log.info(u'{0} {1} {2}{3}.', action, len(objs), entity, - 's' if len(objs) != 1 else '') + u's' if len(objs) != 1 else u'') if not objs: return @@ -1484,7 +1483,7 @@ def move_items(lib, dest, query, copy, album, pretend, confirm=False): else: if confirm: objs = ui.input_select_objects( - 'Really %s' % act, objs, + u'Really %s' % act, objs, lambda o: show_path_changes( [(o.path, o.destination(basedir=dest))])) @@ -1500,30 +1499,30 @@ def move_func(lib, opts, args): if dest is not None: dest = normpath(dest) if not os.path.isdir(dest): - raise ui.UserError('no such directory: %s' % dest) + raise ui.UserError(u'no such directory: %s' % dest) move_items(lib, dest, decargs(args), opts.copy, opts.album, opts.pretend, opts.timid) move_cmd = ui.Subcommand( - 'move', help='move or copy items', aliases=('mv',) + u'move', help=u'move or copy items', aliases=(u'mv',) ) move_cmd.parser.add_option( - '-d', '--dest', metavar='DIR', dest='dest', - help='destination directory' + u'-d', u'--dest', metavar='DIR', dest='dest', + help=u'destination directory' ) move_cmd.parser.add_option( - '-c', '--copy', default=False, action='store_true', - help='copy instead of moving' + u'-c', u'--copy', default=False, action='store_true', + help=u'copy instead of moving' ) move_cmd.parser.add_option( - '-p', '--pretend', default=False, action='store_true', - help='show how files would be moved, but don\'t touch anything' + u'-p', u'--pretend', default=False, action='store_true', + help=u'show how files would be moved, but don\'t touch anything' ) move_cmd.parser.add_option( - '-t', '--timid', dest='timid', action='store_true', - help='always confirm all actions' + u'-t', u'--timid', dest='timid', action='store_true', + help=u'always confirm all actions' ) move_cmd.parser.add_album_option() move_cmd.func = move_func @@ -1565,14 +1564,14 @@ def write_func(lib, opts, args): write_items(lib, decargs(args), opts.pretend, opts.force) -write_cmd = ui.Subcommand('write', help='write tag information to files') +write_cmd = ui.Subcommand(u'write', help=u'write tag information to files') write_cmd.parser.add_option( - '-p', '--pretend', action='store_true', - help="show all changes but do nothing" + u'-p', u'--pretend', action='store_true', + help=u"show all changes but do nothing" ) write_cmd.parser.add_option( - '-f', '--force', action='store_true', - help="write tags even if the existing tags match the database" + u'-f', u'--force', action='store_true', + help=u"write tags even if the existing tags match the database" ) write_cmd.func = write_func default_commands.append(write_cmd) @@ -1622,29 +1621,29 @@ def config_edit(): open(path, 'w+').close() util.interactive_open([path], editor) except OSError as exc: - message = "Could not edit configuration: {0}".format(exc) + message = u"Could not edit configuration: {0}".format(exc) if not editor: - message += ". Please set the EDITOR environment variable" + message += u". Please set the EDITOR environment variable" raise ui.UserError(message) -config_cmd = ui.Subcommand('config', - help='show or edit the user configuration') +config_cmd = ui.Subcommand(u'config', + help=u'show or edit the user configuration') config_cmd.parser.add_option( - '-p', '--paths', action='store_true', - help='show files that configuration was loaded from' + u'-p', u'--paths', action='store_true', + help=u'show files that configuration was loaded from' ) config_cmd.parser.add_option( - '-e', '--edit', action='store_true', - help='edit user configuration with $EDITOR' + u'-e', u'--edit', action='store_true', + help=u'edit user configuration with $EDITOR' ) config_cmd.parser.add_option( - '-d', '--defaults', action='store_true', - help='include the default configuration' + u'-d', u'--defaults', action='store_true', + help=u'include the default configuration' ) config_cmd.parser.add_option( - '-c', '--clear', action='store_false', + u'-c', u'--clear', action='store_false', dest='redact', default=True, - help='do not redact sensitive fields' + help=u'do not redact sensitive fields' ) config_cmd.func = config_func default_commands.append(config_cmd) @@ -1704,30 +1703,31 @@ def completion_script(commands): # Add global options options['_global'] = { - 'flags': ['-v', '--verbose'], - 'opts': '-l --library -c --config -d --directory -h --help'.split(' ') + 'flags': [u'-v', u'--verbose'], + 'opts': u'-l --library -c --config -d --directory -h --help'.split( + u' ') } # Add flags common to all commands options['_common'] = { - 'flags': ['-h', '--help'] + 'flags': [u'-h', u'--help'] } # Start generating the script - yield "_beet() {\n" + yield u"_beet() {\n" # Command names - yield " local commands='%s'\n" % ' '.join(command_names) - yield "\n" + yield u" local commands='%s'\n" % ' '.join(command_names) + yield u"\n" # Command aliases - yield " local aliases='%s'\n" % ' '.join(aliases.keys()) + yield u" local aliases='%s'\n" % ' '.join(aliases.keys()) for alias, cmd in aliases.items(): - yield " local alias__%s=%s\n" % (alias, cmd) - yield '\n' + yield u" local alias__%s=%s\n" % (alias, cmd) + yield u'\n' # Fields - yield " fields='%s'\n" % ' '.join( + yield u" fields='%s'\n" % ' '.join( set(library.Item._fields.keys() + library.Album._fields.keys()) ) @@ -1736,15 +1736,16 @@ def completion_script(commands): for option_type, option_list in opts.items(): if option_list: option_list = ' '.join(option_list) - yield " local %s__%s='%s'\n" % (option_type, cmd, option_list) + yield u" local %s__%s='%s'\n" % ( + option_type, cmd, option_list) - yield ' _beet_dispatch\n' - yield '}\n' + yield u' _beet_dispatch\n' + yield u'}\n' completion_cmd = ui.Subcommand( 'completion', - help='print shell script that provides command line completion' + help=u'print shell script that provides command line completion' ) completion_cmd.func = print_completion completion_cmd.hide = True diff --git a/beets/util/__init__.py b/beets/util/__init__.py index 0da68efc7..4d46aecd2 100644 --- a/beets/util/__init__.py +++ b/beets/util/__init__.py @@ -15,8 +15,7 @@ """Miscellaneous utility functions.""" -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import os import sys import re @@ -57,10 +56,10 @@ class HumanReadableException(Exception): def _gerund(self): """Generate a (likely) gerund form of the English verb. """ - if ' ' in self.verb: + if u' ' in self.verb: return self.verb - gerund = self.verb[:-1] if self.verb.endswith('e') else self.verb - gerund += 'ing' + gerund = self.verb[:-1] if self.verb.endswith(u'e') else self.verb + gerund += u'ing' return gerund def _reasonstr(self): @@ -415,7 +414,7 @@ def copy(path, dest, replace=False): path = syspath(path) dest = syspath(dest) if not replace and os.path.exists(dest): - raise FilesystemError('file exists', 'copy', (path, dest)) + raise FilesystemError(u'file exists', 'copy', (path, dest)) try: shutil.copyfile(path, dest) except (OSError, IOError) as exc: @@ -436,7 +435,7 @@ def move(path, dest, replace=False): path = syspath(path) dest = syspath(dest) if os.path.exists(dest) and not replace: - raise FilesystemError('file exists', 'rename', (path, dest), + raise FilesystemError(u'file exists', 'rename', (path, dest), traceback.format_exc()) # First, try renaming the file. @@ -462,13 +461,13 @@ def link(path, dest, replace=False): path = syspath(path) dest = syspath(dest) if os.path.exists(dest) and not replace: - raise FilesystemError('file exists', 'rename', (path, dest), + raise FilesystemError(u'file exists', 'rename', (path, dest), traceback.format_exc()) try: os.symlink(path, dest) except OSError: - raise FilesystemError('Operating system does not support symbolic ' - 'links.', 'link', (path, dest), + raise FilesystemError(u'Operating system does not support symbolic ' + u'links.', 'link', (path, dest), traceback.format_exc()) @@ -619,7 +618,7 @@ def legalize_path(path, replacements, length, extension, fragment): def str2bool(value): """Returns a boolean reflecting a human-entered string.""" - return value.lower() in ('yes', '1', 'true', 't', 'y') + return value.lower() in (u'yes', u'1', u'true', u't', u'y') def as_string(value): @@ -643,7 +642,7 @@ def plurality(objs): """ c = Counter(objs) if not c: - raise ValueError('sequence must be non-empty') + raise ValueError(u'sequence must be non-empty') return c.most_common(1)[0] @@ -766,7 +765,7 @@ def shlex_split(s): return [c.decode('utf8') for c in shlex.split(bs)] else: - raise TypeError('shlex_split called with non-string') + raise TypeError(u'shlex_split called with non-string') def interactive_open(targets, command): @@ -854,8 +853,8 @@ def raw_seconds_short(string): Raises ValueError if the conversion cannot take place due to `string` not being in the right format. """ - match = re.match('^(\d+):([0-5]\d)$', string) + match = re.match(r'^(\d+):([0-5]\d)$', string) if not match: - raise ValueError('String not in M:SS format') + raise ValueError(u'String not in M:SS format') minutes, seconds = map(int, match.groups()) return float(minutes * 60 + seconds) diff --git a/beets/util/artresizer.py b/beets/util/artresizer.py index 1b6a5903e..9d2ee5952 100644 --- a/beets/util/artresizer.py +++ b/beets/util/artresizer.py @@ -16,8 +16,7 @@ """Abstraction layer to resize images using PIL, ImageMagick, or a public resizing proxy if neither is available. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import urllib import subprocess @@ -125,10 +124,10 @@ def im_getsize(path_in): try: out = util.command_output(cmd) except subprocess.CalledProcessError as exc: - log.warn('ImageMagick size query failed') + log.warn(u'ImageMagick size query failed') log.debug( - '`convert` exited with (status {}) when ' - 'getting size with command {}:\n{}', + u'`convert` exited with (status {}) when ' + u'getting size with command {}:\n{}', exc.returncode, cmd, exc.output.strip() ) return diff --git a/beets/util/bluelet.py b/beets/util/bluelet.py index e736bab27..d81c2919a 100644 --- a/beets/util/bluelet.py +++ b/beets/util/bluelet.py @@ -7,8 +7,7 @@ asyncore. Bluelet: easy concurrency without all the messy parallelism. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import socket import select @@ -555,7 +554,7 @@ def spawn(coro): and child coroutines run concurrently. """ if not isinstance(coro, types.GeneratorType): - raise ValueError('%s is not a coroutine' % coro) + raise ValueError(u'%s is not a coroutine' % coro) return SpawnEvent(coro) @@ -565,7 +564,7 @@ def call(coro): returns a value using end(), then this event returns that value. """ if not isinstance(coro, types.GeneratorType): - raise ValueError('%s is not a coroutine' % coro) + raise ValueError(u'%s is not a coroutine' % coro) return DelegationEvent(coro) diff --git a/beets/util/confit.py b/beets/util/confit.py index 29b906cb6..0b29928c8 100644 --- a/beets/util/confit.py +++ b/beets/util/confit.py @@ -15,8 +15,7 @@ """Worry-free YAML configuration files. """ -from __future__ import (unicode_literals, absolute_import, print_function, - division) +from __future__ import division, absolute_import, print_function import platform import os @@ -101,17 +100,17 @@ class ConfigReadError(ConfigError): self.filename = filename self.reason = reason - message = 'file {0} could not be read'.format(filename) + message = u'file {0} could not be read'.format(filename) if isinstance(reason, yaml.scanner.ScannerError) and \ reason.problem == YAML_TAB_PROBLEM: # Special-case error message for tab indentation in YAML markup. - message += ': found tab character at line {0}, column {1}'.format( + message += u': found tab character at line {0}, column {1}'.format( reason.problem_mark.line + 1, reason.problem_mark.column + 1, ) elif reason: # Generic error message uses exception's message. - message += ': {0}'.format(reason) + message += u': {0}'.format(reason) super(ConfigReadError, self).__init__(message) @@ -125,15 +124,15 @@ class ConfigSource(dict): def __init__(self, value, filename=None, default=False): super(ConfigSource, self).__init__(value) if filename is not None and not isinstance(filename, BASESTRING): - raise TypeError('filename must be a string or None') + raise TypeError(u'filename must be a string or None') self.filename = filename self.default = default def __repr__(self): - return 'ConfigSource({0}, {1}, {2})'.format( - super(ConfigSource, self).__repr__(), - repr(self.filename), - repr(self.default) + return 'ConfigSource({0!r}, {1!r}, {2!r})'.format( + super(ConfigSource, self), + self.filename, + self.default, ) @classmethod @@ -147,7 +146,7 @@ class ConfigSource(dict): elif isinstance(value, dict): return ConfigSource(value) else: - raise TypeError('source value must be a dict') + raise TypeError(u'source value must be a dict') class ConfigView(object): @@ -182,7 +181,7 @@ class ConfigView(object): try: return iter_first(pairs) except ValueError: - raise NotFoundError("{0} not found".format(self.name)) + raise NotFoundError(u"{0} not found".format(self.name)) def exists(self): """Determine whether the view has a setting in any source. @@ -230,7 +229,7 @@ class ConfigView(object): collection = self.get() if not isinstance(collection, (list, tuple)): raise ConfigTypeError( - '{0} must be a dictionary or a list, not {1}'.format( + u'{0} must be a dictionary or a list, not {1}'.format( self.name, type(collection).__name__ ) ) @@ -308,7 +307,7 @@ class ConfigView(object): cur_keys = dic.keys() except AttributeError: raise ConfigTypeError( - '{0} must be a dict, not {1}'.format( + u'{0} must be a dict, not {1}'.format( self.name, type(dic).__name__ ) ) @@ -349,7 +348,7 @@ class ConfigView(object): it = iter(collection) except TypeError: raise ConfigTypeError( - '{0} must be an iterable, not {1}'.format( + u'{0} must be an iterable, not {1}'.format( self.name, type(collection).__name__ ) ) @@ -489,7 +488,7 @@ class Subview(ConfigView): if not isinstance(self.key, int): self.name += '.' if isinstance(self.key, int): - self.name += '#{0}'.format(self.key) + self.name += u'#{0}'.format(self.key) elif isinstance(self.key, BASESTRING): if isinstance(self.key, bytes): self.name += self.key.decode('utf8') @@ -511,7 +510,7 @@ class Subview(ConfigView): except TypeError: # Not subscriptable. raise ConfigTypeError( - "{0} must be a collection, not {1}".format( + u"{0} must be a collection, not {1}".format( self.parent.name, type(collection).__name__ ) ) @@ -621,7 +620,7 @@ class Loader(yaml.SafeLoader): else: raise yaml.constructor.ConstructorError( None, None, - 'expected a mapping node, but found %s' % node.id, + u'expected a mapping node, but found %s' % node.id, node.start_mark ) @@ -632,7 +631,7 @@ class Loader(yaml.SafeLoader): hash(key) except TypeError as exc: raise yaml.constructor.ConstructorError( - 'while constructing a mapping', + u'while constructing a mapping', node.start_mark, 'found unacceptable key (%s)' % exc, key_node.start_mark ) @@ -710,9 +709,9 @@ class Dumper(yaml.SafeDumper): """Represent bool as 'yes' or 'no' instead of 'true' or 'false'. """ if data: - value = 'yes' + value = u'yes' else: - value = 'no' + value = u'no' return self.represent_scalar('tag:yaml.org,2002:bool', value) def represent_none(self, data): @@ -837,7 +836,7 @@ class Configuration(RootView): appdir = os.environ[self._env_var] appdir = os.path.abspath(os.path.expanduser(appdir)) if os.path.isfile(appdir): - raise ConfigError('{0} must be a directory'.format( + raise ConfigError(u'{0} must be a directory'.format( self._env_var )) @@ -990,7 +989,7 @@ class Template(object): return self.convert(value, view) elif self.default is REQUIRED: # Missing required value. This is an error. - raise NotFoundError("{0} not found".format(view.name)) + raise NotFoundError(u"{0} not found".format(view.name)) else: # Missing value, but not required. return self.default @@ -1015,7 +1014,7 @@ class Template(object): """ exc_class = ConfigTypeError if type_error else ConfigValueError raise exc_class( - '{0}: {1}'.format(view.name, message) + u'{0}: {1}'.format(view.name, message) ) def __repr__(self): @@ -1036,7 +1035,7 @@ class Integer(Template): elif isinstance(value, float): return int(value) else: - self.fail('must be a number', view, True) + self.fail(u'must be a number', view, True) class Number(Template): @@ -1049,7 +1048,7 @@ class Number(Template): return value else: self.fail( - 'must be numeric, not {0}'.format(type(value).__name__), + u'must be numeric, not {0}'.format(type(value).__name__), view, True ) @@ -1111,12 +1110,12 @@ class String(Template): if isinstance(value, BASESTRING): if self.pattern and not self.regex.match(value): self.fail( - "must match the pattern {0}".format(self.pattern), + u"must match the pattern {0}".format(self.pattern), view ) return value else: - self.fail('must be a string', view, True) + self.fail(u'must be a string', view, True) class Choice(Template): @@ -1137,7 +1136,7 @@ class Choice(Template): """ if value not in self.choices: self.fail( - 'must be one of {0}, not {1}'.format( + u'must be one of {0}, not {1}'.format( repr(list(self.choices)), repr(value) ), view @@ -1206,7 +1205,7 @@ class OneOf(Template): raise ConfigTemplateError(exc) self.fail( - 'must be one of {0}, not {1}'.format( + u'must be one of {0}, not {1}'.format( repr(self.allowed), repr(value) ), view @@ -1242,7 +1241,7 @@ class StrSeq(Template): try: value = list(value) except TypeError: - self.fail('must be a whitespace-separated string or a list', + self.fail(u'must be a whitespace-separated string or a list', view, True) def convert(x): @@ -1251,7 +1250,7 @@ class StrSeq(Template): elif isinstance(x, bytes): return x.decode('utf8', 'ignore') else: - self.fail('must be a list of strings', view, True) + self.fail(u'must be a list of strings', view, True) return list(map(convert, value)) @@ -1301,19 +1300,19 @@ class Filename(Template): if not isinstance(template, (collections.Mapping, MappingTemplate)): # disallow config.get(Filename(relative_to='foo')) raise ConfigTemplateError( - 'relative_to may only be used when getting multiple values.' + u'relative_to may only be used when getting multiple values.' ) elif self.relative_to == view.key: raise ConfigTemplateError( - '{0} is relative to itself'.format(view.name) + u'{0} is relative to itself'.format(view.name) ) elif self.relative_to not in view.parent.keys(): # self.relative_to is not in the config self.fail( ( - 'needs sibling value "{0}" to expand relative path' + u'needs sibling value "{0}" to expand relative path' ).format(self.relative_to), view ) @@ -1335,12 +1334,12 @@ class Filename(Template): if next_relative in template.subtemplates: # we encountered this config key previously raise ConfigTemplateError(( - '{0} and {1} are recursively relative' + u'{0} and {1} are recursively relative' ).format(view.name, self.relative_to)) else: raise ConfigTemplateError(( - 'missing template for {0}, needed to expand {1}\'s' + - 'relative path' + u'missing template for {0}, needed to expand {1}\'s' + + u'relative path' ).format(self.relative_to, view.name)) next_template.subtemplates[next_relative] = rel_to_template @@ -1352,7 +1351,7 @@ class Filename(Template): path, source = view.first() if not isinstance(path, BASESTRING): self.fail( - 'must be a filename, not {0}'.format(type(path).__name__), + u'must be a filename, not {0}'.format(type(path).__name__), view, True ) @@ -1390,7 +1389,7 @@ class TypeTemplate(Template): def convert(self, value, view): if not isinstance(value, self.typ): self.fail( - 'must be a {0}, not {1}'.format( + u'must be a {0}, not {1}'.format( self.typ.__name__, type(value).__name__, ), @@ -1444,4 +1443,4 @@ def as_template(value): elif isinstance(value, type): return TypeTemplate(value) else: - raise ValueError('cannot convert to template: {0!r}'.format(value)) + raise ValueError(u'cannot convert to template: {0!r}'.format(value)) diff --git a/beets/util/enumeration.py b/beets/util/enumeration.py index 9dddf7f64..3e9467185 100644 --- a/beets/util/enumeration.py +++ b/beets/util/enumeration.py @@ -13,8 +13,7 @@ # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from enum import Enum diff --git a/beets/util/functemplate.py b/beets/util/functemplate.py index 68cb4cd76..5764807c3 100644 --- a/beets/util/functemplate.py +++ b/beets/util/functemplate.py @@ -27,8 +27,7 @@ This is sort of like a tiny, horrible degeneration of a real templating engine like Jinja2 or Mustache. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import re import ast @@ -79,7 +78,7 @@ def ex_literal(val): return ast.Name(bytes(val), ast.Load()) elif isinstance(val, basestring): return ast.Str(val) - raise TypeError('no literal for {0}'.format(type(val))) + raise TypeError(u'no literal for {0}'.format(type(val))) def ex_varassign(name, expr): @@ -571,4 +570,4 @@ if __name__ == b'__main__': 'from __main__ import _tmpl, _vars, _funcs', number=10000) print(comp_time) - print('Speedup:', interp_time / comp_time) + print(u'Speedup:', interp_time / comp_time) diff --git a/beets/util/pipeline.py b/beets/util/pipeline.py index deb431fa1..9b134d1e7 100644 --- a/beets/util/pipeline.py +++ b/beets/util/pipeline.py @@ -32,8 +32,7 @@ To do so, pass an iterable of coroutines to the Pipeline constructor in place of any single coroutine. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import Queue from threading import Thread, Lock @@ -362,7 +361,7 @@ class Pipeline(object): be at least two stages. """ if len(stages) < 2: - raise ValueError('pipeline must have at least two stages') + raise ValueError(u'pipeline must have at least two stages') self.stages = [] for stage in stages: if isinstance(stage, (list, tuple)): @@ -467,14 +466,14 @@ if __name__ == b'__main__': # in parallel. def produce(): for i in range(5): - print('generating %i' % i) + print(u'generating %i' % i) time.sleep(1) yield i def work(): num = yield while True: - print('processing %i' % num) + print(u'processing %i' % num) time.sleep(2) num = yield num * 2 @@ -482,7 +481,7 @@ if __name__ == b'__main__': while True: num = yield time.sleep(1) - print('received %i' % num) + print(u'received %i' % num) ts_start = time.time() Pipeline([produce(), work(), consume()]).run_sequential() @@ -491,22 +490,22 @@ if __name__ == b'__main__': ts_par = time.time() Pipeline([produce(), (work(), work()), consume()]).run_parallel() ts_end = time.time() - print('Sequential time:', ts_seq - ts_start) - print('Parallel time:', ts_par - ts_seq) - print('Multiply-parallel time:', ts_end - ts_par) + print(u'Sequential time:', ts_seq - ts_start) + print(u'Parallel time:', ts_par - ts_seq) + print(u'Multiply-parallel time:', ts_end - ts_par) print() # Test a pipeline that raises an exception. def exc_produce(): for i in range(10): - print('generating %i' % i) + print(u'generating %i' % i) time.sleep(1) yield i def exc_work(): num = yield while True: - print('processing %i' % num) + print(u'processing %i' % num) time.sleep(3) if num == 3: raise Exception() @@ -515,6 +514,6 @@ if __name__ == b'__main__': def exc_consume(): while True: num = yield - print('received %i' % num) + print(u'received %i' % num) Pipeline([exc_produce(), exc_work(), exc_consume()]).run_parallel(1) diff --git a/beets/vfs.py b/beets/vfs.py index d99031c63..7f9a049ee 100644 --- a/beets/vfs.py +++ b/beets/vfs.py @@ -16,8 +16,7 @@ """A simple utility for constructing filesystem-like trees from beets libraries. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from collections import namedtuple from beets import util diff --git a/beetsplug/__init__.py b/beetsplug/__init__.py index ea5e7fe40..febeb66f4 100644 --- a/beetsplug/__init__.py +++ b/beetsplug/__init__.py @@ -15,8 +15,8 @@ """A namespace package for beets plugins.""" -# Make this a namespace package. -from __future__ import absolute_import +from __future__ import division, absolute_import, print_function +# Make this a namespace package. from pkgutil import extend_path __path__ = extend_path(__path__, __name__) diff --git a/beetsplug/acousticbrainz.py b/beetsplug/acousticbrainz.py index 49f01ea21..6acea8140 100644 --- a/beetsplug/acousticbrainz.py +++ b/beetsplug/acousticbrainz.py @@ -15,8 +15,7 @@ """Fetch various AcousticBrainz metadata using MBID. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import requests import operator @@ -38,7 +37,7 @@ class AcousticPlugin(plugins.BeetsPlugin): def commands(self): cmd = ui.Subcommand('acousticbrainz', - help="fetch metadata from AcousticBrainz") + help=u"fetch metadata from AcousticBrainz") def func(lib, opts, args): items = lib.items(ui.decargs(args)) @@ -63,24 +62,24 @@ def fetch_info(log, items, write): try: return reduce(operator.getitem, map_path, data) except KeyError: - log.debug('Invalid Path: {}', map_path) + log.debug(u'Invalid Path: {}', map_path) for item in items: if item.mb_trackid: - log.info('getting data for: {}', item) + log.info(u'getting data for: {}', item) # Fetch the data from the AB API. urls = [generate_url(item.mb_trackid, path) for path in LEVELS] - log.debug('fetching URLs: {}', ' '.join(urls)) + log.debug(u'fetching URLs: {}', ' '.join(urls)) try: res = [requests.get(url) for url in urls] except requests.RequestException as exc: - log.info('request error: {}', exc) + log.info(u'request error: {}', exc) continue # Check for missing tracks. if any(r.status_code == 404 for r in res): - log.info('recording ID {} not found', item.mb_trackid) + log.info(u'recording ID {} not found', item.mb_trackid) continue # Parse the JSON response. @@ -88,7 +87,7 @@ def fetch_info(log, items, write): data = res[0].json() data.update(res[1].json()) except ValueError: - log.debug('Invalid Response: {} & {}', [r.text for r in res]) + log.debug(u'Invalid Response: {} & {}', [r.text for r in res]) # Get each field and assign it on the item. item.danceable = get_value( diff --git a/beetsplug/badfiles.py b/beetsplug/badfiles.py index c6877205c..f9704d484 100644 --- a/beetsplug/badfiles.py +++ b/beetsplug/badfiles.py @@ -16,8 +16,7 @@ """Use command-line tools to check for audio file corruption. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from beets.plugins import BeetsPlugin from beets.ui import Subcommand @@ -32,7 +31,7 @@ import sys class BadFiles(BeetsPlugin): def run_command(self, cmd): - self._log.debug("running command: {}", + self._log.debug(u"running command: {}", displayable_path(list2cmdline(cmd))) try: output = check_output(cmd, stderr=STDOUT) @@ -44,7 +43,7 @@ class BadFiles(BeetsPlugin): status = e.returncode except OSError as e: if e.errno == errno.ENOENT: - ui.print_("command not found: {}".format(cmd[0])) + ui.print_(u"command not found: {}".format(cmd[0])) sys.exit(1) else: raise @@ -87,9 +86,9 @@ class BadFiles(BeetsPlugin): # First, check whether the path exists. If not, the user # should probably run `beet update` to cleanup your library. dpath = displayable_path(item.path) - self._log.debug("checking path: {}", dpath) + self._log.debug(u"checking path: {}", dpath) if not os.path.exists(item.path): - ui.print_("{}: file does not exist".format( + ui.print_(u"{}: file does not exist".format( ui.colorize('text_error', dpath))) # Run the checker against the file if one is found @@ -102,20 +101,20 @@ class BadFiles(BeetsPlugin): path = item.path.decode(sys.getfilesystemencoding()) status, errors, output = checker(path) if status > 0: - ui.print_("{}: checker exited withs status {}" + ui.print_(u"{}: checker exited withs status {}" .format(ui.colorize('text_error', dpath), status)) for line in output: ui.print_(" {}".format(displayable_path(line))) elif errors > 0: - ui.print_("{}: checker found {} errors or warnings" + ui.print_(u"{}: checker found {} errors or warnings" .format(ui.colorize('text_warning', dpath), errors)) for line in output: - ui.print_(" {}".format(displayable_path(line))) + ui.print_(u" {}".format(displayable_path(line))) else: - ui.print_("{}: ok".format(ui.colorize('text_success', dpath))) + ui.print_(u"{}: ok".format(ui.colorize('text_success', dpath))) def commands(self): bad_command = Subcommand('bad', - help='check for corrupt or missing files') + help=u'check for corrupt or missing files') bad_command.func = self.check_bad return [bad_command] diff --git a/beetsplug/bpd/__init__.py b/beetsplug/bpd/__init__.py index 7e8694bac..33deda02c 100644 --- a/beetsplug/bpd/__init__.py +++ b/beetsplug/bpd/__init__.py @@ -18,8 +18,7 @@ Beets library. Attempts to implement a compatible protocol to allow use of the wide range of MPD clients. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import re from string import Template @@ -124,9 +123,9 @@ def make_bpd_error(s_code, s_message): pass return NewBPDError -ArgumentTypeError = make_bpd_error(ERROR_ARG, 'invalid type for argument') -ArgumentIndexError = make_bpd_error(ERROR_ARG, 'argument out of range') -ArgumentNotFoundError = make_bpd_error(ERROR_NO_EXIST, 'argument not found') +ArgumentTypeError = make_bpd_error(ERROR_ARG, u'invalid type for argument') +ArgumentIndexError = make_bpd_error(ERROR_ARG, u'argument out of range') +ArgumentNotFoundError = make_bpd_error(ERROR_NO_EXIST, u'argument not found') def cast_arg(t, val): @@ -269,7 +268,7 @@ class BaseServer(object): conn.authenticated = True else: conn.authenticated = False - raise BPDError(ERROR_PASSWORD, 'incorrect password') + raise BPDError(ERROR_PASSWORD, u'incorrect password') def cmd_commands(self, conn): """Lists the commands available to the user.""" @@ -807,9 +806,9 @@ class Server(BaseServer): """ # Path is ignored. Also, the real MPD does this asynchronously; # this is done inline. - print('Building directory tree...') + print(u'Building directory tree...') self.tree = vfs.libtree(self.lib) - print('... done.') + print(u'... done.') self.updated_time = time.time() # Path (directory tree) browsing. @@ -848,7 +847,7 @@ class Server(BaseServer): node = self._resolve_path(path) if isinstance(node, int): # Trying to list a track. - raise BPDError(ERROR_ARG, 'this is not a directory') + raise BPDError(ERROR_ARG, u'this is not a directory') else: for name, itemid in iter(sorted(node.files.items())): item = self.lib.get_item(itemid) @@ -1173,18 +1172,18 @@ class BPDPlugin(BeetsPlugin): def commands(self): cmd = beets.ui.Subcommand( - 'bpd', help='run an MPD-compatible music player server' + 'bpd', help=u'run an MPD-compatible music player server' ) cmd.parser.add_option( '-d', '--debug', action='store_true', - help='dump all MPD traffic to stdout' + help=u'dump all MPD traffic to stdout' ) def func(lib, opts, args): host = args.pop(0) if args else self.config['host'].get(unicode) port = args.pop(0) if args else self.config['port'].get(int) if args: - raise beets.ui.UserError('too many arguments') + raise beets.ui.UserError(u'too many arguments') password = self.config['password'].get(unicode) volume = self.config['volume'].get(int) debug = opts.debug or False diff --git a/beetsplug/bpd/gstplayer.py b/beetsplug/bpd/gstplayer.py index fa22b999d..70d0613d5 100644 --- a/beetsplug/bpd/gstplayer.py +++ b/beetsplug/bpd/gstplayer.py @@ -17,8 +17,7 @@ music player. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import sys import time @@ -91,7 +90,7 @@ class GstPlayer(object): # error self.player.set_state(gst.STATE_NULL) err, debug = message.parse_error() - print("Error: {0}".format(err)) + print(u"Error: {0}".format(err)) self.playing = False def _set_volume(self, volume): diff --git a/beetsplug/bpm.py b/beetsplug/bpm.py index e0fc7f4f8..ba284c042 100644 --- a/beetsplug/bpm.py +++ b/beetsplug/bpm.py @@ -15,8 +15,7 @@ """Determine BPM by pressing a key to the rhythm.""" -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import time @@ -59,8 +58,8 @@ class BPMPlugin(BeetsPlugin): def commands(self): cmd = ui.Subcommand('bpm', - help='determine bpm of a song by pressing \ - a key to the rhythm') + help=u'determine bpm of a song by pressing ' + u'a key to the rhythm') cmd.func = self.command return [cmd] @@ -70,7 +69,7 @@ class BPMPlugin(BeetsPlugin): def get_bpm(self, items, write=False): overwrite = self.config['overwrite'].get(bool) if len(items) > 1: - raise ValueError('Can only get bpm of one song at time') + raise ValueError(u'Can only get bpm of one song at time') item = items[0] if item['bpm']: diff --git a/beetsplug/bucket.py b/beetsplug/bucket.py index 7ddc90920..cfd4106d4 100644 --- a/beetsplug/bucket.py +++ b/beetsplug/bucket.py @@ -16,8 +16,7 @@ """Provides the %bucket{} function for path formatting. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from datetime import datetime import re @@ -46,7 +45,7 @@ def span_from_str(span_str): """Convert string to a 4 digits year """ if yearfrom < 100: - raise BucketError("%d must be expressed on 4 digits" % yearfrom) + raise BucketError(u"%d must be expressed on 4 digits" % yearfrom) # if two digits only, pick closest year that ends by these two # digits starting from yearfrom @@ -59,12 +58,12 @@ def span_from_str(span_str): years = [int(x) for x in re.findall('\d+', span_str)] if not years: - raise ui.UserError("invalid range defined for year bucket '%s': no " - "year found" % span_str) + raise ui.UserError(u"invalid range defined for year bucket '%s': no " + u"year found" % span_str) try: years = [normalize_year(x, years[0]) for x in years] except BucketError as exc: - raise ui.UserError("invalid range defined for year bucket '%s': %s" % + raise ui.UserError(u"invalid range defined for year bucket '%s': %s" % (span_str, exc)) res = {'from': years[0], 'str': span_str} @@ -119,8 +118,8 @@ def build_year_spans(year_spans_str): def str2fmt(s): """Deduces formatting syntax from a span string. """ - regex = re.compile("(?P\D*)(?P\d+)(?P\D*)" - "(?P\d*)(?P\D*)") + regex = re.compile(r"(?P\D*)(?P\d+)(?P\D*)" + r"(?P\d*)(?P\D*)") m = re.match(regex, s) res = {'fromnchars': len(m.group('fromyear')), @@ -166,8 +165,8 @@ def build_alpha_spans(alpha_spans_str, alpha_regexs): beginIdx = ASCII_DIGITS.index(bucket[0]) endIdx = ASCII_DIGITS.index(bucket[-1]) else: - raise ui.UserError("invalid range defined for alpha bucket " - "'%s': no alphanumeric character found" % + raise ui.UserError(u"invalid range defined for alpha bucket " + u"'%s': no alphanumeric character found" % elem) spans.append( re.compile( diff --git a/beetsplug/chroma.py b/beetsplug/chroma.py index cb0eaf24a..148e9c20c 100644 --- a/beetsplug/chroma.py +++ b/beetsplug/chroma.py @@ -16,8 +16,7 @@ """Adds Chromaprint/Acoustid acoustic fingerprinting support to the autotagger. Requires the pyacoustid library. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from beets import plugins from beets import ui @@ -178,19 +177,19 @@ class AcoustidPlugin(plugins.BeetsPlugin): def commands(self): submit_cmd = ui.Subcommand('submit', - help='submit Acoustid fingerprints') + help=u'submit Acoustid fingerprints') def submit_cmd_func(lib, opts, args): try: apikey = config['acoustid']['apikey'].get(unicode) except confit.NotFoundError: - raise ui.UserError('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_cmd.func = submit_cmd_func fingerprint_cmd = ui.Subcommand( 'fingerprint', - help='generate fingerprints for items without them' + help=u'generate fingerprints for items without them' ) def fingerprint_cmd_func(lib, opts, args): diff --git a/beetsplug/convert.py b/beetsplug/convert.py index ce475a19d..303a9e149 100644 --- a/beetsplug/convert.py +++ b/beetsplug/convert.py @@ -15,8 +15,7 @@ """Converts tracks or albums to external directory """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import os import threading @@ -140,21 +139,21 @@ class ConvertPlugin(BeetsPlugin): self.register_listener('import_task_files', self._cleanup) def commands(self): - cmd = ui.Subcommand('convert', help='convert to external location') + cmd = ui.Subcommand('convert', help=u'convert to external location') cmd.parser.add_option('-p', '--pretend', action='store_true', - help='show actions but do nothing') + help=u'show actions but do nothing') cmd.parser.add_option('-t', '--threads', action='store', type='int', - help='change the number of threads, \ + help=u'change the number of threads, \ defaults to maximum available processors') cmd.parser.add_option('-k', '--keep-new', action='store_true', - dest='keep_new', help='keep only the converted \ + dest='keep_new', help=u'keep only the converted \ and move the old files') cmd.parser.add_option('-d', '--dest', action='store', - help='set the destination directory') + help=u'set the destination directory') cmd.parser.add_option('-f', '--format', action='store', dest='format', - help='set the target format of the tracks') + help=u'set the target format of the tracks') cmd.parser.add_option('-y', '--yes', action='store_true', dest='yes', - help='do not ask for confirmation') + help=u'do not ask for confirmation') cmd.parser.add_album_option() cmd.func = self.convert_func return [cmd] @@ -294,7 +293,7 @@ class ConvertPlugin(BeetsPlugin): if self.config['embed']: album = item.get_album() if album and album.artpath: - self._log.debug('embedding album art from {}', + self._log.debug(u'embedding album art from {}', util.displayable_path(album.artpath)) art.embed_item(self._log, item, album.artpath, itempath=converted) @@ -373,7 +372,7 @@ class ConvertPlugin(BeetsPlugin): if not opts.dest: opts.dest = self.config['dest'].get() if not opts.dest: - raise ui.UserError('no convert destination set') + raise ui.UserError(u'no convert destination set') opts.dest = util.bytestring_path(opts.dest) if not opts.threads: @@ -393,7 +392,7 @@ class ConvertPlugin(BeetsPlugin): if not pretend: ui.commands.list_items(lib, ui.decargs(args), opts.album) - if not (opts.yes or ui.input_yn("Convert? (Y/n)")): + if not (opts.yes or ui.input_yn(u"Convert? (Y/n)")): return if opts.album: diff --git a/beetsplug/discogs.py b/beetsplug/discogs.py index 321fbd09e..62a78a5ff 100644 --- a/beetsplug/discogs.py +++ b/beetsplug/discogs.py @@ -16,8 +16,7 @@ """Adds Discogs album search support to the autotagger. Requires the discogs-client library. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import beets.ui from beets import logging @@ -101,24 +100,24 @@ class DiscogsPlugin(BeetsPlugin): try: _, _, url = auth_client.get_authorize_url() except CONNECTION_ERRORS as e: - self._log.debug('connection error: {0}', e) - raise beets.ui.UserError('communication with Discogs failed') + self._log.debug(u'connection error: {0}', e) + raise beets.ui.UserError(u'communication with Discogs failed') - beets.ui.print_("To authenticate with Discogs, visit:") + beets.ui.print_(u"To authenticate with Discogs, visit:") beets.ui.print_(url) # Ask for the code and validate it. - code = beets.ui.input_("Enter the code:") + code = beets.ui.input_(u"Enter the code:") try: token, secret = auth_client.get_access_token(code) except DiscogsAPIError: - raise beets.ui.UserError('Discogs authorization failed') + raise beets.ui.UserError(u'Discogs authorization failed') except CONNECTION_ERRORS as e: self._log.debug(u'connection error: {0}', e) - raise beets.ui.UserError('Discogs token request failed') + raise beets.ui.UserError(u'Discogs token request failed') # Save the token for later use. - self._log.debug('Discogs token {0}, secret {1}', token, secret) + self._log.debug(u'Discogs token {0}, secret {1}', token, secret) with open(self._tokenfile(), 'w') as f: json.dump({'token': token, 'secret': secret}, f) @@ -153,7 +152,7 @@ class DiscogsPlugin(BeetsPlugin): else: return [] except CONNECTION_ERRORS: - self._log.debug('Connection error in album search', exc_info=True) + self._log.debug(u'Connection error in album search', exc_info=True) return [] def album_for_id(self, album_id): @@ -184,7 +183,7 @@ class DiscogsPlugin(BeetsPlugin): return self.album_for_id(album_id) return None except CONNECTION_ERRORS: - self._log.debug('Connection error in album lookup', exc_info=True) + self._log.debug(u'Connection error in album lookup', exc_info=True) return None return self.get_album_info(result) @@ -206,7 +205,7 @@ class DiscogsPlugin(BeetsPlugin): releases = self.discogs_client.search(query, type='release').page(1) except CONNECTION_ERRORS: - self._log.debug("Communication error while searching for {0!r}", + self._log.debug(u"Communication error while searching for {0!r}", query, exc_info=True) return [] return [self.get_album_info(release) for release in releases[:5]] diff --git a/beetsplug/duplicates.py b/beetsplug/duplicates.py index 3a04557ca..4f0397171 100644 --- a/beetsplug/duplicates.py +++ b/beetsplug/duplicates.py @@ -15,8 +15,7 @@ """List duplicate tracks or albums. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import shlex @@ -54,52 +53,57 @@ class DuplicatesPlugin(BeetsPlugin): self._command = Subcommand('duplicates', help=__doc__, aliases=['dup']) - self._command.parser.add_option('-c', '--count', dest='count', - action='store_true', - help='show duplicate counts') - - self._command.parser.add_option('-C', '--checksum', dest='checksum', - action='store', metavar='PROG', - help='report duplicates based on' - ' arbitrary command') - - self._command.parser.add_option('-d', '--delete', dest='delete', - action='store_true', - help='delete items from library and ' - 'disk') - - self._command.parser.add_option('-F', '--full', dest='full', - action='store_true', - help='show all versions of duplicate' - ' tracks or albums') - - self._command.parser.add_option('-s', '--strict', dest='strict', - action='store_true', - help='report duplicates only if all' - ' attributes are set') - - self._command.parser.add_option('-k', '--keys', dest='keys', - action='callback', metavar='KEY1 KEY2', - callback=vararg_callback, - help='report duplicates based on keys') - - self._command.parser.add_option('-M', '--merge', dest='merge', - action='store_true', - help='merge duplicate items') - - self._command.parser.add_option('-m', '--move', dest='move', - action='store', metavar='DEST', - help='move items to dest') - - self._command.parser.add_option('-o', '--copy', dest='copy', - action='store', metavar='DEST', - help='copy items to dest') - - self._command.parser.add_option('-t', '--tag', dest='tag', - action='store', - help='tag matched items with \'k=v\'' - ' attribute') - + self._command.parser.add_option( + u'-c', u'--count', dest='count', + action='store_true', + help=u'show duplicate counts', + ) + self._command.parser.add_option( + u'-C', u'--checksum', dest='checksum', + action='store', metavar='PROG', + help=u'report duplicates based on arbitrary command', + ) + self._command.parser.add_option( + u'-d', u'--delete', dest='delete', + action='store_true', + help=u'delete items from library and disk', + ) + self._command.parser.add_option( + u'-F', u'--full', dest='full', + action='store_true', + help=u'show all versions of duplicate tracks or albums', + ) + self._command.parser.add_option( + u'-s', u'--strict', dest='strict', + action='store_true', + help=u'report duplicates only if all attributes are set', + ) + self._command.parser.add_option( + u'-k', u'--keys', dest='keys', + action='callback', metavar='KEY1 KEY2', + callback=vararg_callback, + help=u'report duplicates based on keys', + ) + self._command.parser.add_option( + u'-M', u'--merge', dest='merge', + action='store_true', + help=u'merge duplicate items', + ) + self._command.parser.add_option( + u'-m', u'--move', dest='move', + action='store', metavar='DEST', + help=u'move items to dest', + ) + self._command.parser.add_option( + u'-o', u'--copy', dest='copy', + action='store', metavar='DEST', + help=u'copy items to dest', + ) + self._command.parser.add_option( + u'-t', u'--tag', dest='tag', + action='store', + help=u'tag matched items with \'k=v\' attribute', + ) self._command.parser.add_all_common_options() def commands(self): @@ -181,7 +185,9 @@ class DuplicatesPlugin(BeetsPlugin): try: k, v = tag.split('=') except: - raise UserError('%s: can\'t parse k=v tag: %s' % (PLUGIN, tag)) + raise UserError( + u"{}: can't parse k=v tag: {}".format(PLUGIN, tag) + ) setattr(item, k, v) item.store() @@ -195,7 +201,7 @@ class DuplicatesPlugin(BeetsPlugin): checksum = getattr(item, key, False) if not checksum: self._log.debug(u'key {0} on item {1} not cached:' - 'computing checksum', + u'computing checksum', key, displayable_path(item.path)) try: checksum = command_output(args) @@ -208,7 +214,7 @@ class DuplicatesPlugin(BeetsPlugin): displayable_path(item.path), e) else: self._log.debug(u'key {0} on item {1} cached:' - 'not computing checksum', + u'not computing checksum', key, displayable_path(item.path)) return key, checksum @@ -225,11 +231,11 @@ class DuplicatesPlugin(BeetsPlugin): values = [v for v in values if v not in (None, '')] if strict and len(values) < len(keys): self._log.debug(u'some keys {0} on item {1} are null or empty:' - ' skipping', + u' skipping', keys, displayable_path(obj.path)) elif (not strict and not len(values)): self._log.debug(u'all keys {0} on item {1} are null or empty:' - ' skipping', + u' skipping', keys, displayable_path(obj.path)) else: key = tuple(values) @@ -279,7 +285,7 @@ class DuplicatesPlugin(BeetsPlugin): value = getattr(o, f, None) if value: self._log.debug(u'key {0} on item {1} is null ' - 'or empty: setting from item {2}', + u'or empty: setting from item {2}', f, displayable_path(objs[0].path), displayable_path(o.path)) setattr(objs[0], f, value) @@ -300,7 +306,7 @@ class DuplicatesPlugin(BeetsPlugin): missing.album_id = objs[0].id missing.add(i._db) self._log.debug(u'item {0} missing from album {1}:' - ' merging from {2} into {3}', + u' merging from {2} into {3}', missing, objs[0], displayable_path(o.path), diff --git a/beetsplug/echonest.py b/beetsplug/echonest.py index 182c7f9a2..a979972d8 100644 --- a/beetsplug/echonest.py +++ b/beetsplug/echonest.py @@ -15,8 +15,7 @@ """Fetch a variety of acoustic metrics from The Echo Nest. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import time import socket @@ -465,10 +464,11 @@ class EchonestMetadataPlugin(plugins.BeetsPlugin): def commands(self): fetch_cmd = ui.Subcommand('echonest', - help='fetch metadata from The Echo Nest') + help=u'fetch metadata from The Echo Nest') fetch_cmd.parser.add_option( - '-f', '--force', dest='force', action='store_true', default=False, - help='(re-)download information from the EchoNest' + u'-f', u'--force', dest='force', + action='store_true', default=False, + help=u'(re-)download information from the EchoNest' ) def fetch_func(lib, opts, args): @@ -483,10 +483,10 @@ class EchonestMetadataPlugin(plugins.BeetsPlugin): fetch_cmd.func = fetch_func - sim_cmd = ui.Subcommand('echosim', help='show related files') + sim_cmd = ui.Subcommand('echosim', help=u'show related files') sim_cmd.parser.add_option( - '-t', '--threshold', dest='threshold', action='store', - type='float', default=0.15, help='Set difference threshold' + u'-t', u'--threshold', dest='threshold', action='store', + type='float', default=0.15, help=u'Set difference threshold' ) sim_cmd.parser.add_format_option() diff --git a/beetsplug/edit.py b/beetsplug/edit.py index ee045664e..58d0828a5 100644 --- a/beetsplug/edit.py +++ b/beetsplug/edit.py @@ -14,8 +14,7 @@ """Open metadata information in a text editor to let the user edit it. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from beets import plugins from beets import util @@ -70,7 +69,7 @@ def load(s): for d in yaml.load_all(s): if not isinstance(d, dict): raise ParseError( - 'each entry must be a dictionary; found {}'.format( + u'each entry must be a dictionary; found {}'.format( type(d).__name__ ) ) @@ -80,7 +79,7 @@ def load(s): out.append({unicode(k): v for k, v in d.items()}) except yaml.YAMLError as e: - raise ParseError('invalid YAML: {}'.format(e)) + raise ParseError(u'invalid YAML: {}'.format(e)) return out @@ -159,18 +158,18 @@ class EditPlugin(plugins.BeetsPlugin): def commands(self): edit_command = ui.Subcommand( 'edit', - help='interactively edit metadata' + help=u'interactively edit metadata' ) edit_command.parser.add_option( - '-f', '--field', + u'-f', u'--field', metavar='FIELD', action='append', - help='edit this field also', + help=u'edit this field also', ) edit_command.parser.add_option( - '--all', + u'--all', action='store_true', dest='all', - help='edit all fields', + help=u'edit all fields', ) edit_command.parser.add_album_option() edit_command.func = self._edit_command @@ -184,7 +183,7 @@ class EditPlugin(plugins.BeetsPlugin): items, albums = _do_query(lib, query, opts.album, False) objs = albums if opts.album else items if not objs: - ui.print_('Nothing to edit.') + ui.print_(u'Nothing to edit.') return # Get the fields to edit. @@ -253,15 +252,15 @@ class EditPlugin(plugins.BeetsPlugin): with open(new.name) as f: new_str = f.read() if new_str == old_str: - ui.print_("No changes; aborting.") + ui.print_(u"No changes; aborting.") return False # Parse the updated data. try: new_data = load(new_str) except ParseError as e: - ui.print_("Could not read data: {}".format(e)) - if ui.input_yn("Edit again to fix? (Y/n)", True): + ui.print_(u"Could not read data: {}".format(e)) + if ui.input_yn(u"Edit again to fix? (Y/n)", True): continue else: return False @@ -276,18 +275,18 @@ class EditPlugin(plugins.BeetsPlugin): for obj, obj_old in zip(objs, objs_old): changed |= ui.show_model_changes(obj, obj_old) if not changed: - ui.print_('No changes to apply.') + ui.print_(u'No changes to apply.') return False # Confirm the changes. choice = ui.input_options( - ('continue Editing', 'apply', 'cancel') + (u'continue Editing', u'apply', u'cancel') ) - if choice == 'a': # Apply. + if choice == u'a': # Apply. return True - elif choice == 'c': # Cancel. + elif choice == u'c': # Cancel. return False - elif choice == 'e': # Keep editing. + elif choice == u'e': # Keep editing. # Reset the temporary changes to the objects. for obj in objs: obj.read() @@ -305,7 +304,7 @@ class EditPlugin(plugins.BeetsPlugin): are temporary. """ if len(old_data) != len(new_data): - self._log.warn('number of objects changed from {} to {}', + self._log.warn(u'number of objects changed from {} to {}', len(old_data), len(new_data)) obj_by_id = {o.id: o for o in objs} @@ -316,7 +315,7 @@ class EditPlugin(plugins.BeetsPlugin): forbidden = False for key in ignore_fields: if old_dict.get(key) != new_dict.get(key): - self._log.warn('ignoring object whose {} changed', key) + self._log.warn(u'ignoring object whose {} changed', key) forbidden = True break if forbidden: @@ -331,7 +330,7 @@ class EditPlugin(plugins.BeetsPlugin): # Save to the database and possibly write tags. for ob in objs: if ob._dirty: - self._log.debug('saving changes to {}', ob) + self._log.debug(u'saving changes to {}', ob) ob.try_sync(ui.should_write(), ui.should_move()) # Methods for interactive importer execution. diff --git a/beetsplug/embedart.py b/beetsplug/embedart.py index b27964874..71b05f370 100644 --- a/beetsplug/embedart.py +++ b/beetsplug/embedart.py @@ -14,8 +14,7 @@ # included in all copies or substantial portions of the Software. """Allows beets to embed album art into file metadata.""" -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import os.path @@ -56,10 +55,10 @@ class EmbedCoverArtPlugin(BeetsPlugin): def commands(self): # Embed command. embed_cmd = ui.Subcommand( - 'embedart', help='embed image files into file metadata' + 'embedart', help=u'embed image files into file metadata' ) embed_cmd.parser.add_option( - '-f', '--file', metavar='PATH', help='the image file to embed' + u'-f', u'--file', metavar='PATH', help=u'the image file to embed' ) maxwidth = self.config['maxwidth'].get(int) compare_threshold = self.config['compare_threshold'].get(int) @@ -84,17 +83,22 @@ class EmbedCoverArtPlugin(BeetsPlugin): embed_cmd.func = embed_func # Extract command. - extract_cmd = ui.Subcommand('extractart', - help='extract an image from file metadata') - extract_cmd.parser.add_option('-o', dest='outpath', - help='image output file') - extract_cmd.parser.add_option('-n', dest='filename', - help='image filename to create for all ' - 'matched albums') - extract_cmd.parser.add_option('-a', dest='associate', - action='store_true', - help='associate the extracted images ' - 'with the album') + extract_cmd = ui.Subcommand( + 'extractart', + help=u'extract an image from file metadata', + ) + extract_cmd.parser.add_option( + u'-o', dest='outpath', + help=u'image output file', + ) + extract_cmd.parser.add_option( + u'-n', dest='filename', + help=u'image filename to create for all matched albums', + ) + extract_cmd.parser.add_option( + '-a', dest='associate', action='store_true', + help='associate the extracted images with the album', + ) def extract_func(lib, opts, args): if opts.outpath: @@ -104,8 +108,8 @@ class EmbedCoverArtPlugin(BeetsPlugin): filename = bytestring_path(opts.filename or config['art_filename'].get()) if os.path.dirname(filename) != '': - self._log.error(u"Only specify a name rather than a path " - u"for -n") + self._log.error( + u"Only specify a name rather than a path for -n") return for album in lib.albums(decargs(args)): artpath = normpath(os.path.join(album.path, filename)) @@ -117,8 +121,10 @@ class EmbedCoverArtPlugin(BeetsPlugin): extract_cmd.func = extract_func # Clear command. - clear_cmd = ui.Subcommand('clearart', - help='remove images from file metadata') + clear_cmd = ui.Subcommand( + 'clearart', + help=u'remove images from file metadata', + ) def clear_func(lib, opts, args): art.clear(self._log, lib, decargs(args)) @@ -142,7 +148,7 @@ class EmbedCoverArtPlugin(BeetsPlugin): """ if self.config['remove_art_file'] and album.artpath: if os.path.isfile(album.artpath): - self._log.debug('Removing album art file for {0}', album) + self._log.debug(u'Removing album art file for {0}', album) os.remove(album.artpath) album.artpath = None album.store() diff --git a/beetsplug/embyupdate.py b/beetsplug/embyupdate.py index 3953afe2c..38f8929e5 100644 --- a/beetsplug/embyupdate.py +++ b/beetsplug/embyupdate.py @@ -8,8 +8,7 @@ username: user password: password """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from beets import config from beets.plugins import BeetsPlugin @@ -120,7 +119,8 @@ class EmbyUpdate(BeetsPlugin): token = get_token(host, port, headers, auth_data) if not token: self._log.warning( - u'Couldnt not get token for user {0}'.format(username)) + u'Could not get token for user {0}', username + ) return # Recreate headers with a token. diff --git a/beetsplug/fetchart.py b/beetsplug/fetchart.py index 57d8e4c46..ad51bb995 100644 --- a/beetsplug/fetchart.py +++ b/beetsplug/fetchart.py @@ -15,8 +15,7 @@ """Fetches album art. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from contextlib import closing import os @@ -206,14 +205,14 @@ class ITunesStore(ArtSource): try: results = itunes.search_album(search_string) except Exception as exc: - self._log.debug('iTunes search failed: {0}', exc) + self._log.debug(u'iTunes search failed: {0}', exc) return # Get the first match. if results: itunes_album = results[0] else: - self._log.debug('iTunes search for {:r} got no results', + self._log.debug(u'iTunes search for {:r} got no results', search_string) return @@ -276,9 +275,9 @@ class Wikipedia(ArtSource): cover_filename = 'File:' + results[0]['coverFilename']['value'] page_id = results[0]['pageId']['value'] else: - self._log.debug('wikipedia: album not found on dbpedia') + self._log.debug(u'wikipedia: album not found on dbpedia') except (ValueError, KeyError, IndexError): - self._log.debug('wikipedia: error scraping dbpedia response: {}', + self._log.debug(u'wikipedia: error scraping dbpedia response: {}', dbpedia_response.text) # Ensure we have a filename before attempting to query wikipedia @@ -293,7 +292,7 @@ class Wikipedia(ArtSource): if ' .' in cover_filename and \ '.' not in cover_filename.split(' .')[-1]: self._log.debug( - 'wikipedia: dbpedia provided incomplete cover_filename' + u'wikipedia: dbpedia provided incomplete cover_filename' ) lpart, rpart = cover_filename.rsplit(' .', 1) @@ -322,7 +321,7 @@ class Wikipedia(ArtSource): break except (ValueError, KeyError): self._log.debug( - 'wikipedia: failed to retrieve a cover_filename' + u'wikipedia: failed to retrieve a cover_filename' ) return @@ -347,7 +346,7 @@ class Wikipedia(ArtSource): image_url = result['imageinfo'][0]['url'] yield image_url except (ValueError, KeyError, IndexError): - self._log.debug('wikipedia: error scraping imageinfo') + self._log.debug(u'wikipedia: error scraping imageinfo') return @@ -493,9 +492,11 @@ class FetchArtPlugin(plugins.BeetsPlugin, RequestMixin): # Manual album art fetching. def commands(self): cmd = ui.Subcommand('fetchart', help='download album art') - cmd.parser.add_option('-f', '--force', dest='force', - action='store_true', default=False, - help='re-download art when already present') + cmd.parser.add_option( + u'-f', u'--force', dest='force', + action='store_true', default=False, + help=u're-download art when already present' + ) def func(lib, opts, args): self.batch_fetch_art(lib, lib.albums(ui.decargs(args)), opts.force) @@ -511,12 +512,12 @@ class FetchArtPlugin(plugins.BeetsPlugin, RequestMixin): """ try: with closing(self.request(url, stream=True, - message='downloading image')) as resp: + message=u'downloading image')) as resp: if 'Content-Type' not in resp.headers \ or resp.headers['Content-Type'] not in CONTENT_TYPES: self._log.debug( - 'not a supported image: {}', - resp.headers.get('Content-Type') or 'no content type', + u'not a supported image: {}', + resp.headers.get('Content-Type') or u'no content type', ) return None @@ -532,7 +533,7 @@ class FetchArtPlugin(plugins.BeetsPlugin, RequestMixin): except (IOError, requests.RequestException, TypeError) as exc: # Handling TypeError works around a urllib3 bug: # https://github.com/shazow/urllib3/issues/556 - self._log.debug('error fetching art: {}', exc) + self._log.debug(u'error fetching art: {}', exc) return None def _is_valid_image_candidate(self, candidate): @@ -551,7 +552,7 @@ class FetchArtPlugin(plugins.BeetsPlugin, RequestMixin): # get_size returns None if no local imaging backend is available size = ArtResizer.shared.get_size(candidate) - self._log.debug('image size: {}', size) + self._log.debug(u'image size: {}', size) if not size: self._log.warning(u'Could not get size of image (please see ' @@ -562,19 +563,19 @@ class FetchArtPlugin(plugins.BeetsPlugin, RequestMixin): # Check minimum size. if self.minwidth and size[0] < self.minwidth: - self._log.debug('image too small ({} < {})', + self._log.debug(u'image too small ({} < {})', size[0], self.minwidth) return CANDIDATE_BAD # Check aspect ratio. if self.enforce_ratio and size[0] != size[1]: - self._log.debug('image is not square ({} != {})', + self._log.debug(u'image is not square ({} != {})', size[0], size[1]) return CANDIDATE_BAD # Check maximum size. if self.maxwidth and size[0] > self.maxwidth: - self._log.debug('image needs resizing ({} > {})', + self._log.debug(u'image needs resizing ({} > {})', size[0], self.maxwidth) return CANDIDATE_DOWNSCALE @@ -600,7 +601,7 @@ class FetchArtPlugin(plugins.BeetsPlugin, RequestMixin): check = self._is_valid_image_candidate(candidate) if check: out = candidate - self._log.debug('found local image {}', out) + self._log.debug(u'found local image {}', out) break # Web art sources. @@ -613,7 +614,7 @@ class FetchArtPlugin(plugins.BeetsPlugin, RequestMixin): check = self._is_valid_image_candidate(candidate) if check: out = candidate - self._log.debug('using remote image {}', out) + self._log.debug(u'using remote image {}', out) break if self.maxwidth and out and check == CANDIDATE_DOWNSCALE: @@ -627,7 +628,7 @@ class FetchArtPlugin(plugins.BeetsPlugin, RequestMixin): """ for album in albums: if album.artpath and not force and os.path.isfile(album.artpath): - message = ui.colorize('text_highlight_minor', 'has album art') + message = ui.colorize('text_highlight_minor', u'has album art') else: # In ordinary invocations, look for images on the # filesystem. When forcing, however, always go to the Web @@ -638,9 +639,9 @@ class FetchArtPlugin(plugins.BeetsPlugin, RequestMixin): if path: album.set_art(path, False) album.store() - message = ui.colorize('text_success', 'found album art') + message = ui.colorize('text_success', u'found album art') else: - message = ui.colorize('text_error', 'no art found') + message = ui.colorize('text_error', u'no art found') self._log.info(u'{0}: {1}', album, message) @@ -654,7 +655,7 @@ class FetchArtPlugin(plugins.BeetsPlugin, RequestMixin): source_names = {v: k for k, v in ART_SOURCES.items()} for source in self.sources: self._log.debug( - 'trying source {0} for album {1.albumartist} - {1.album}', + u'trying source {0} for album {1.albumartist} - {1.album}', source_names[type(source)], album, ) diff --git a/beetsplug/freedesktop.py b/beetsplug/freedesktop.py index 33104fa13..a768be2d8 100644 --- a/beetsplug/freedesktop.py +++ b/beetsplug/freedesktop.py @@ -16,8 +16,7 @@ """Creates freedesktop.org-compliant .directory files on an album level. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from beets.plugins import BeetsPlugin from beets import ui @@ -25,13 +24,14 @@ from beets import ui class FreedesktopPlugin(BeetsPlugin): def commands(self): - deprecated = ui.Subcommand("freedesktop", help="Print a message to " - "redirect to thumbnails --dolphin") + deprecated = ui.Subcommand( + "freedesktop", + help=u"Print a message to redirect to thumbnails --dolphin") deprecated.func = self.deprecation_message return [deprecated] def deprecation_message(self, lib, opts, args): - ui.print_("This plugin is deprecated. Its functionality is superseded " - "by the 'thumbnails' plugin") - ui.print_("'thumbnails --dolphin' replaces freedesktop. See doc & " - "changelog for more information") + ui.print_(u"This plugin is deprecated. Its functionality is " + u"superseded by the 'thumbnails' plugin") + ui.print_(u"'thumbnails --dolphin' replaces freedesktop. See doc & " + u"changelog for more information") diff --git a/beetsplug/fromfilename.py b/beetsplug/fromfilename.py index 895cab9e4..e9c49bee3 100644 --- a/beetsplug/fromfilename.py +++ b/beetsplug/fromfilename.py @@ -16,8 +16,7 @@ """If the title is empty, try to extract track and title from the filename. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from beets import plugins from beets.util import displayable_path diff --git a/beetsplug/ftintitle.py b/beetsplug/ftintitle.py index 30892f0dc..eefdfcf15 100644 --- a/beetsplug/ftintitle.py +++ b/beetsplug/ftintitle.py @@ -15,8 +15,7 @@ """Moves "featured" artists to the title from the artist field. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import re @@ -87,12 +86,12 @@ class FtInTitlePlugin(plugins.BeetsPlugin): self._command = ui.Subcommand( 'ftintitle', - help='move featured artists to the title field') + help=u'move featured artists to the title field') self._command.parser.add_option( - '-d', '--drop', dest='drop', + u'-d', u'--drop', dest='drop', action='store_true', default=False, - help='drop featuring from artists and ignore title update') + help=u'drop featuring from artists and ignore title update') if self.config['auto']: self.import_stages = [self.imported] diff --git a/beetsplug/fuzzy.py b/beetsplug/fuzzy.py index 4e167217f..4a631a887 100644 --- a/beetsplug/fuzzy.py +++ b/beetsplug/fuzzy.py @@ -16,8 +16,7 @@ """Provides a fuzzy matching query. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from beets.plugins import BeetsPlugin from beets.dbcore.query import StringFieldQuery diff --git a/beetsplug/ihate.py b/beetsplug/ihate.py index 7285c8482..6ed250fe4 100644 --- a/beetsplug/ihate.py +++ b/beetsplug/ihate.py @@ -13,8 +13,7 @@ # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function """Warns you about things you hate (or even blocks import).""" diff --git a/beetsplug/importadded.py b/beetsplug/importadded.py index 70be1089e..1202e95de 100644 --- a/beetsplug/importadded.py +++ b/beetsplug/importadded.py @@ -5,8 +5,7 @@ modification time (mtime) of the item's source file before import. Reimported albums and items are skipped. """ -from __future__ import (unicode_literals, absolute_import, print_function, - division) +from __future__ import division, absolute_import, print_function import os diff --git a/beetsplug/importfeeds.py b/beetsplug/importfeeds.py index c3d677572..d046ddc47 100644 --- a/beetsplug/importfeeds.py +++ b/beetsplug/importfeeds.py @@ -13,8 +13,7 @@ # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function """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 @@ -135,9 +134,9 @@ class ImportFeedsPlugin(BeetsPlugin): os.symlink(syspath(path), syspath(dest)) if 'echo' in formats: - self._log.info("Location of imported music:") + self._log.info(u"Location of imported music:") for path in paths: - self._log.info(" {0}", path) + self._log.info(u" {0}", path) def library_opened(self, lib): if self.config['dir'].get() is None: diff --git a/beetsplug/info.py b/beetsplug/info.py index a29a6ccfc..29bff7a29 100644 --- a/beetsplug/info.py +++ b/beetsplug/info.py @@ -16,8 +16,7 @@ """Shows file metadata. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import os import re @@ -141,17 +140,25 @@ def print_data_keys(data, item=None): class InfoPlugin(BeetsPlugin): def commands(self): - cmd = ui.Subcommand('info', help='show file metadata') + cmd = ui.Subcommand('info', help=u'show file metadata') cmd.func = self.run - cmd.parser.add_option('-l', '--library', action='store_true', - help='show library fields instead of tags') - cmd.parser.add_option('-s', '--summarize', action='store_true', - help='summarize the tags of all files') - cmd.parser.add_option('-i', '--include-keys', default=[], - action='append', dest='included_keys', - help='comma separated list of keys to show') - cmd.parser.add_option('-k', '--keys-only', action='store_true', - help='show only the keys') + cmd.parser.add_option( + u'-l', u'--library', action='store_true', + help=u'show library fields instead of tags', + ) + cmd.parser.add_option( + u'-s', u'--summarize', action='store_true', + help=u'summarize the tags of all files', + ) + cmd.parser.add_option( + u'-i', u'--include-keys', default=[], + action='append', dest='included_keys', + help=u'comma separated list of keys to show', + ) + cmd.parser.add_option( + u'-k', u'--keys-only', action='store_true', + help=u'show only the keys', + ) cmd.parser.add_format_option(target='item') return [cmd] diff --git a/beetsplug/inline.py b/beetsplug/inline.py index 5c0c81b80..6e3771f2a 100644 --- a/beetsplug/inline.py +++ b/beetsplug/inline.py @@ -15,8 +15,7 @@ """Allows inline path template customization code in the config file. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import traceback import itertools diff --git a/beetsplug/keyfinder.py b/beetsplug/keyfinder.py index fc9c7b148..b6131a4b0 100644 --- a/beetsplug/keyfinder.py +++ b/beetsplug/keyfinder.py @@ -16,8 +16,7 @@ """Uses the `KeyFinder` program to add the `initial_key` field. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import subprocess @@ -41,7 +40,7 @@ class KeyFinderPlugin(BeetsPlugin): def commands(self): cmd = ui.Subcommand('keyfinder', - help='detect and add initial key from audio') + help=u'detect and add initial key from audio') cmd.func = self.command return [cmd] @@ -63,12 +62,12 @@ class KeyFinderPlugin(BeetsPlugin): output = util.command_output([bin, b'-f', util.syspath(item.path)]) except (subprocess.CalledProcessError, OSError) as exc: - self._log.error('execution failed: {0}', exc) + self._log.error(u'execution failed: {0}', exc) continue except UnicodeEncodeError: # Workaround for Python 2 Windows bug. # http://bugs.python.org/issue1759845 - self._log.error('execution failed for Unicode path: {0!r}', + self._log.error(u'execution failed for Unicode path: {0!r}', item.path) continue diff --git a/beetsplug/lastgenre/__init__.py b/beetsplug/lastgenre/__init__.py index 554369ced..ad051c45c 100644 --- a/beetsplug/lastgenre/__init__.py +++ b/beetsplug/lastgenre/__init__.py @@ -13,8 +13,7 @@ # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function """Gets genres for imported music based on Last.fm tags. @@ -239,25 +238,30 @@ class LastGenrePlugin(plugins.BeetsPlugin): def fetch_album_genre(self, obj): """Return the album genre for this Item or Album. """ - return self._last_lookup(u'album', LASTFM.get_album, obj.albumartist, - obj.album) + return self._last_lookup( + u'album', LASTFM.get_album, obj.albumartist, obj.album + ) def fetch_album_artist_genre(self, obj): """Return the album artist genre for this Item or Album. """ - return self._last_lookup(u'artist', LASTFM.get_artist, - obj.albumartist) + return self._last_lookup( + u'artist', LASTFM.get_artist, obj.albumartist + ) def fetch_artist_genre(self, item): """Returns the track artist genre for this Item. """ - return self._last_lookup(u'artist', LASTFM.get_artist, item.artist) + return self._last_lookup( + u'artist', LASTFM.get_artist, item.artist + ) def fetch_track_genre(self, obj): """Returns the track genre for this Item. """ - return self._last_lookup(u'track', LASTFM.get_track, obj.artist, - obj.title) + return self._last_lookup( + u'track', LASTFM.get_track, obj.artist, obj.title + ) def _get_genre(self, obj): """Get the genre string for an Album or Item object based on @@ -326,14 +330,15 @@ class LastGenrePlugin(plugins.BeetsPlugin): return None, None def commands(self): - lastgenre_cmd = ui.Subcommand('lastgenre', help='fetch genres') + lastgenre_cmd = ui.Subcommand('lastgenre', help=u'fetch genres') lastgenre_cmd.parser.add_option( - '-f', '--force', dest='force', action='store_true', default=False, - help='re-download genre when already present' + u'-f', u'--force', dest='force', + action='store_true', default=False, + help=u're-download genre when already present' ) lastgenre_cmd.parser.add_option( - '-s', '--source', dest='source', type='string', - help='genre source: artist, album, or track' + u'-s', u'--source', dest='source', type='string', + help=u'genre source: artist, album, or track' ) def lastgenre_func(lib, opts, args): @@ -406,8 +411,8 @@ class LastGenrePlugin(plugins.BeetsPlugin): return [] except Exception as exc: # Isolate bugs in pylast. - self._log.debug('{}', traceback.format_exc()) - self._log.error('error in pylast library: {0}', exc) + self._log.debug(u'{}', traceback.format_exc()) + self._log.error(u'error in pylast library: {0}', exc) return [] # Filter by weight (optionally). diff --git a/beetsplug/lastimport.py b/beetsplug/lastimport.py index 29560b7f2..2d8cc7008 100644 --- a/beetsplug/lastimport.py +++ b/beetsplug/lastimport.py @@ -13,8 +13,7 @@ # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import pylast from pylast import TopItem, _extract, _number @@ -44,7 +43,7 @@ class LastImportPlugin(plugins.BeetsPlugin): } def commands(self): - cmd = ui.Subcommand('lastimport', help='import last.fm play-count') + cmd = ui.Subcommand('lastimport', help=u'import last.fm play-count') def func(lib, opts, args): import_lastfm(lib, self._log) @@ -115,9 +114,9 @@ def import_lastfm(lib, log): per_page = config['lastimport']['per_page'].get(int) if not user: - raise ui.UserError('You must specify a user name for lastimport') + raise ui.UserError(u'You must specify a user name for lastimport') - log.info('Fetching last.fm library for @{0}', user) + log.info(u'Fetching last.fm library for @{0}', user) page_total = 1 page_current = 0 @@ -126,7 +125,7 @@ def import_lastfm(lib, log): retry_limit = config['lastimport']['retry_limit'].get(int) # Iterate through a yet to be known page total count while page_current < page_total: - log.info('Querying page #{0}{1}...', + log.info(u'Querying page #{0}{1}...', page_current + 1, '/{}'.format(page_total) if page_total > 1 else '') @@ -134,7 +133,7 @@ def import_lastfm(lib, log): tracks, page_total = fetch_tracks(user, page_current + 1, per_page) if page_total < 1: # It means nothing to us! - raise ui.UserError('Last.fm reported no data.') + raise ui.UserError(u'Last.fm reported no data.') if tracks: found, unknown = process_tracks(lib, tracks, log) @@ -142,22 +141,22 @@ def import_lastfm(lib, log): unknown_total += unknown break else: - log.error('ERROR: unable to read page #{0}', + log.error(u'ERROR: unable to read page #{0}', page_current + 1) if retry < retry_limit: log.info( - 'Retrying page #{0}... ({1}/{2} retry)', + u'Retrying page #{0}... ({1}/{2} retry)', page_current + 1, retry + 1, retry_limit ) else: - log.error('FAIL: unable to fetch page #{0}, ', - 'tried {1} times', page_current, retry + 1) + log.error(u'FAIL: unable to fetch page #{0}, ', + u'tried {1} times', page_current, retry + 1) page_current += 1 - log.info('... done!') - log.info('finished processing {0} song pages', page_total) - log.info('{0} unknown play-counts', unknown_total) - log.info('{0} play-counts imported', found_total) + log.info(u'... done!') + log.info(u'finished processing {0} song pages', page_total) + log.info(u'{0} unknown play-counts', unknown_total) + log.info(u'{0} play-counts imported', found_total) def fetch_tracks(user, page, limit): @@ -191,7 +190,7 @@ def process_tracks(lib, tracks, log): total = len(tracks) total_found = 0 total_fails = 0 - log.info('Received {0} tracks in this page, processing...', total) + log.info(u'Received {0} tracks in this page, processing...', total) for num in xrange(0, total): song = None @@ -244,7 +243,7 @@ def process_tracks(lib, tracks, log): artist, title, album) if total_fails > 0: - log.info('Acquired {0}/{1} play-counts ({2} unknown)', + log.info(u'Acquired {0}/{1} play-counts ({2} unknown)', total_found, total, total_fails) return total_found, total_fails diff --git a/beetsplug/lyrics.py b/beetsplug/lyrics.py index 9e5e2fad6..66b859f59 100644 --- a/beetsplug/lyrics.py +++ b/beetsplug/lyrics.py @@ -16,8 +16,7 @@ """Fetches, embeds, and displays lyrics. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import re import requests @@ -107,7 +106,7 @@ def extract_text_in(html, starttag): parts.append(html[pos:match.start()]) break else: - print('no closing tag found!') + print(u'no closing tag found!') return return u''.join(parts) @@ -237,7 +236,7 @@ class Genius(Backend): url = u'https://api.genius.com/search?q=%s' \ % (urllib.quote(query.encode('utf8'))) - self._log.debug('genius: requesting search {}', url) + self._log.debug(u'genius: requesting search {}', url) try: req = requests.get( url, @@ -246,19 +245,19 @@ class Genius(Backend): ) req.raise_for_status() except requests.RequestException as exc: - self._log.debug('genius: request error: {}', exc) + self._log.debug(u'genius: request error: {}', exc) return None try: return req.json() except ValueError: - self._log.debug('genius: invalid response: {}', req.text) + self._log.debug(u'genius: invalid response: {}', req.text) return None def get_lyrics(self, link): url = u'http://genius-api.com/api/lyricsInfo' - self._log.debug('genius: requesting lyrics for link {}', link) + self._log.debug(u'genius: requesting lyrics for link {}', link) try: req = requests.post( url, @@ -268,13 +267,13 @@ class Genius(Backend): ) req.raise_for_status() except requests.RequestException as exc: - self._log.debug('genius: request error: {}', exc) + self._log.debug(u'genius: request error: {}', exc) return None try: return req.json() except ValueError: - self._log.debug('genius: invalid response: {}', req.text) + self._log.debug(u'genius: invalid response: {}', req.text) return None def build_lyric_string(self, lyrics): @@ -576,12 +575,16 @@ class LyricsPlugin(plugins.BeetsPlugin): def commands(self): cmd = ui.Subcommand('lyrics', help='fetch song lyrics') - cmd.parser.add_option('-p', '--print', dest='printlyr', - action='store_true', default=False, - help='print lyrics to console') - cmd.parser.add_option('-f', '--force', dest='force_refetch', - action='store_true', default=False, - help='always re-download lyrics') + cmd.parser.add_option( + u'-p', u'--print', dest='printlyr', + action='store_true', default=False, + help=u'print lyrics to console', + ) + cmd.parser.add_option( + u'-f', u'--force', dest='force_refetch', + action='store_true', default=False, + help=u'always re-download lyrics', + ) def func(lib, opts, args): # The "write to files" option corresponds to the diff --git a/beetsplug/mbcollection.py b/beetsplug/mbcollection.py index 2e24ae59e..21944154e 100644 --- a/beetsplug/mbcollection.py +++ b/beetsplug/mbcollection.py @@ -13,8 +13,7 @@ # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from beets.plugins import BeetsPlugin from beets.ui import Subcommand @@ -34,11 +33,11 @@ def mb_call(func, *args, **kwargs): try: return func(*args, **kwargs) except musicbrainzngs.AuthenticationError: - raise ui.UserError('authentication with MusicBrainz failed') + raise ui.UserError(u'authentication with MusicBrainz failed') except (musicbrainzngs.ResponseError, musicbrainzngs.NetworkError) as exc: - raise ui.UserError('MusicBrainz API error: {0}'.format(exc)) + raise ui.UserError(u'MusicBrainz API error: {0}'.format(exc)) except musicbrainzngs.UsageError: - raise ui.UserError('MusicBrainz credentials missing') + raise ui.UserError(u'MusicBrainz credentials missing') def submit_albums(collection_id, release_ids): @@ -65,7 +64,8 @@ class MusicBrainzCollectionPlugin(BeetsPlugin): self.import_stages = [self.imported] def commands(self): - mbupdate = Subcommand('mbupdate', help='Update MusicBrainz collection') + mbupdate = Subcommand('mbupdate', + help=u'Update MusicBrainz collection') mbupdate.func = self.update_collection return [mbupdate] @@ -84,7 +84,7 @@ class MusicBrainzCollectionPlugin(BeetsPlugin): # Get the available collections. collections = mb_call(musicbrainzngs.get_collections) if not collections['collection-list']: - raise ui.UserError('no collections exist for user') + raise ui.UserError(u'no collections exist for user') # Get the first release collection. MusicBrainz also has event # collections, so we need to avoid adding to those. @@ -93,7 +93,7 @@ class MusicBrainzCollectionPlugin(BeetsPlugin): collection_id = collection['id'] break else: - raise ui.UserError('No collection found.') + raise ui.UserError(u'No collection found.') # Get a list of all the album IDs. album_ids = [] @@ -106,6 +106,8 @@ class MusicBrainzCollectionPlugin(BeetsPlugin): self._log.info(u'skipping invalid MBID: {0}', aid) # Submit to MusicBrainz. - self._log.info('Updating MusicBrainz collection {0}...', collection_id) + self._log.info( + u'Updating MusicBrainz collection {0}...', collection_id + ) submit_albums(collection_id, album_ids) - self._log.info('...MusicBrainz collection updated.') + self._log.info(u'...MusicBrainz collection updated.') diff --git a/beetsplug/mbsubmit.py b/beetsplug/mbsubmit.py index 947e4cfc6..91de6128e 100644 --- a/beetsplug/mbsubmit.py +++ b/beetsplug/mbsubmit.py @@ -22,8 +22,7 @@ implemented by MusicBrainz yet. [1] http://wiki.musicbrainz.org/History:How_To_Parse_Track_Listings """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from beets.autotag import Recommendation @@ -54,7 +53,7 @@ class MBSubmitPlugin(BeetsPlugin): def before_choose_candidate_event(self, session, task): if task.rec <= self.threshold: - return [PromptChoice('p', 'Print tracks', self.print_tracks)] + return [PromptChoice(u'p', u'Print tracks', self.print_tracks)] def print_tracks(self, session, task): for i in task.items: diff --git a/beetsplug/mbsync.py b/beetsplug/mbsync.py index 00eb966fa..56513353a 100644 --- a/beetsplug/mbsync.py +++ b/beetsplug/mbsync.py @@ -15,8 +15,7 @@ """Update library's tags using MusicBrainz. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from beets.plugins import BeetsPlugin from beets import autotag, library, ui, util @@ -43,18 +42,20 @@ class MBSyncPlugin(BeetsPlugin): def commands(self): cmd = ui.Subcommand('mbsync', - help='update metadata from musicbrainz') - cmd.parser.add_option('-p', '--pretend', action='store_true', - help='show all changes but do nothing') - cmd.parser.add_option('-m', '--move', action='store_true', - dest='move', - help="move files in the library directory") - cmd.parser.add_option('-M', '--nomove', action='store_false', - dest='move', - help="don't move files in library") - cmd.parser.add_option('-W', '--nowrite', action='store_false', - default=None, dest='write', - help="don't write updated metadata to files") + help=u'update metadata from musicbrainz') + cmd.parser.add_option( + u'-p', u'--pretend', action='store_true', + help=u'show all changes but do nothing') + cmd.parser.add_option( + u'-m', u'--move', action='store_true', dest='move', + help=u"move files in the library directory") + cmd.parser.add_option( + u'-M', u'--nomove', action='store_false', dest='move', + help=u"don't move files in library") + cmd.parser.add_option( + u'-W', u'--nowrite', action='store_false', + default=None, dest='write', + help=u"don't write updated metadata to files") cmd.parser.add_format_option() cmd.func = self.func return [cmd] @@ -140,7 +141,7 @@ class MBSyncPlugin(BeetsPlugin): break # Apply. - self._log.debug('applying changes to {}', album_formatted) + self._log.debug(u'applying changes to {}', album_formatted) with lib.transaction(): autotag.apply_metadata(album_info, mapping) changed = False diff --git a/beetsplug/missing.py b/beetsplug/missing.py index 05e66b7a8..8fff659fe 100644 --- a/beetsplug/missing.py +++ b/beetsplug/missing.py @@ -15,8 +15,7 @@ """List missing tracks. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from beets.autotag import hooks from beets.library import Item @@ -95,12 +94,12 @@ class MissingPlugin(BeetsPlugin): self._command = Subcommand('missing', help=__doc__, aliases=['miss']) - self._command.parser.add_option('-c', '--count', dest='count', - action='store_true', - help='count missing tracks per album') - self._command.parser.add_option('-t', '--total', dest='total', - action='store_true', - help='count total of missing tracks') + self._command.parser.add_option( + u'-c', u'--count', dest='count', action='store_true', + help=u'count missing tracks per album') + self._command.parser.add_option( + u'-t', u'--total', dest='total', action='store_true', + help=u'count total of missing tracks') self._command.parser.add_format_option() def commands(self): diff --git a/beetsplug/mpdstats.py b/beetsplug/mpdstats.py index 326afe4da..2b6422942 100644 --- a/beetsplug/mpdstats.py +++ b/beetsplug/mpdstats.py @@ -13,8 +13,7 @@ # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import mpd import socket @@ -80,7 +79,7 @@ class MPDClientWrapper(object): try: self.client.connect(host, port) except socket.error as e: - raise ui.UserError('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) if password: @@ -88,7 +87,7 @@ class MPDClientWrapper(object): self.client.password(password) except mpd.CommandError as e: raise ui.UserError( - 'could not authenticate to MPD: {0}'.format(e) + u'could not authenticate to MPD: {0}'.format(e) ) def disconnect(self): @@ -338,16 +337,16 @@ class MPDStatsPlugin(plugins.BeetsPlugin): def commands(self): cmd = ui.Subcommand( 'mpdstats', - help='run a MPD client to gather play statistics') + help=u'run a MPD client to gather play statistics') cmd.parser.add_option( - '--host', dest='host', type='string', - help='set the hostname of the server to connect to') + u'--host', dest='host', type='string', + help=u'set the hostname of the server to connect to') cmd.parser.add_option( - '--port', dest='port', type='int', - help='set the port of the MPD server to connect to') + u'--port', dest='port', type='int', + help=u'set the port of the MPD server to connect to') cmd.parser.add_option( - '--password', dest='password', type='string', - help='set the password of the MPD server to connect to') + u'--password', dest='password', type='string', + help=u'set the password of the MPD server to connect to') def func(lib, opts, args): mpd_config.set_args(opts) diff --git a/beetsplug/mpdupdate.py b/beetsplug/mpdupdate.py index 5e4e999aa..f828ba5d7 100644 --- a/beetsplug/mpdupdate.py +++ b/beetsplug/mpdupdate.py @@ -21,8 +21,7 @@ Put something like the following in your config.yaml to configure: port: 6600 password: seekrit """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from beets.plugins import BeetsPlugin import os @@ -126,4 +125,4 @@ class MPDUpdatePlugin(BeetsPlugin): s.send('close\n') s.close() - self._log.info('Database updated.') + self._log.info(u'Database updated.') diff --git a/beetsplug/permissions.py b/beetsplug/permissions.py index 8a4ab960b..0de8978c0 100644 --- a/beetsplug/permissions.py +++ b/beetsplug/permissions.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function """Fixes file permissions after the file gets written on import. Put something like the following in your config.yaml to configure: @@ -82,7 +81,7 @@ def permissions(lib, item=None, album=None): # Checks if the destination path has the permissions configured. if not check_permissions(util.bytestring_path(path), file_perm): - message = 'There was a problem setting permission on {}'.format( + message = u'There was a problem setting permission on {}'.format( path) print(message) @@ -98,6 +97,6 @@ def permissions(lib, item=None, album=None): # Checks if the destination path has the permissions configured. if not check_permissions(util.bytestring_path(path), dir_perm): - message = 'There was a problem setting permission on {}'.format( + message = u'There was a problem setting permission on {}'.format( path) print(message) diff --git a/beetsplug/play.py b/beetsplug/play.py index b52b7e635..fa70f2bc0 100644 --- a/beetsplug/play.py +++ b/beetsplug/play.py @@ -15,8 +15,7 @@ """Send the results of a query to the configured music player as a playlist. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from beets.plugins import BeetsPlugin from beets.ui import Subcommand @@ -49,13 +48,13 @@ class PlayPlugin(BeetsPlugin): def commands(self): play_command = Subcommand( 'play', - help='send music to a player as a playlist' + help=u'send music to a player as a playlist' ) play_command.parser.add_album_option() play_command.parser.add_option( - '-A', '--args', + u'-A', u'--args', action='store', - help='add additional arguments to the command', + help=u'add additional arguments to the command', ) play_command.func = self.play_music return [play_command] @@ -90,7 +89,7 @@ class PlayPlugin(BeetsPlugin): if ARGS_MARKER in command_str: command_str = command_str.replace(ARGS_MARKER, opts.args) else: - command_str = "{} {}".format(command_str, opts.args) + command_str = u"{} {}".format(command_str, opts.args) # Perform search by album and add folders rather than tracks to # playlist. @@ -119,16 +118,15 @@ class PlayPlugin(BeetsPlugin): if not selection: ui.print_(ui.colorize('text_warning', - 'No {0} to play.'.format(item_type))) + u'No {0} to play.'.format(item_type))) return # Warn user before playing any huge playlists. if warning_threshold and len(selection) > warning_threshold: ui.print_(ui.colorize( 'text_warning', - 'You are about to queue {0} {1}.'.format(len(selection), - item_type) - )) + u'You are about to queue {0} {1}.'.format( + len(selection), item_type))) if ui.input_options(('Continue', 'Abort')) == 'a': return @@ -139,13 +137,13 @@ class PlayPlugin(BeetsPlugin): else: open_args = [self._create_tmp_playlist(paths)] - self._log.debug('executing command: {} {}', command_str, + self._log.debug(u'executing command: {} {}', command_str, b' '.join(open_args)) try: util.interactive_open(open_args, command_str) except OSError as exc: - raise ui.UserError("Could not play the query: " - "{0}".format(exc)) + raise ui.UserError( + "Could not play the query: {0}".format(exc)) def _create_tmp_playlist(self, paths_list): """Create a temporary .m3u file. Return the filename. diff --git a/beetsplug/plexupdate.py b/beetsplug/plexupdate.py index 51ee4fd85..ef50fde73 100644 --- a/beetsplug/plexupdate.py +++ b/beetsplug/plexupdate.py @@ -9,8 +9,7 @@ Put something like the following in your config.yaml to configure: port: 32400 token: token """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import requests from urlparse import urljoin @@ -78,7 +77,7 @@ class PlexUpdate(BeetsPlugin): def update(self, lib): """When the client exists try to send refresh request to Plex server. """ - self._log.info('Updating Plex library...') + self._log.info(u'Updating Plex library...') # Try to send update request. try: @@ -87,7 +86,7 @@ class PlexUpdate(BeetsPlugin): config['plex']['port'].get(), config['plex']['token'].get(), config['plex']['library_name'].get()) - self._log.info('... started.') + self._log.info(u'... started.') except requests.exceptions.RequestException: - self._log.warning('Update failed.') + self._log.warning(u'Update failed.') diff --git a/beetsplug/random.py b/beetsplug/random.py index 22ae23252..e1c6fea4a 100644 --- a/beetsplug/random.py +++ b/beetsplug/random.py @@ -15,8 +15,7 @@ """Get a random song or album from the library. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from beets.plugins import BeetsPlugin from beets.ui import Subcommand, decargs, print_ @@ -66,11 +65,13 @@ def random_item(lib, opts, args): print_(format(item)) random_cmd = Subcommand('random', - help='chose a random track or album') -random_cmd.parser.add_option('-n', '--number', action='store', type="int", - help='number of objects to choose', default=1) -random_cmd.parser.add_option('-e', '--equal-chance', action='store_true', - help='each artist has the same chance') + help=u'chose a random track or album') +random_cmd.parser.add_option( + u'-n', u'--number', action='store', type="int", + help=u'number of objects to choose', default=1) +random_cmd.parser.add_option( + u'-e', u'--equal-chance', action='store_true', + help=u'each artist has the same chance') random_cmd.parser.add_all_common_options() random_cmd.func = random_item diff --git a/beetsplug/replaygain.py b/beetsplug/replaygain.py index 9e5bff4e0..7bb2aa39a 100644 --- a/beetsplug/replaygain.py +++ b/beetsplug/replaygain.py @@ -13,8 +13,7 @@ # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import subprocess import os @@ -56,13 +55,13 @@ def call(args): return command_output(args) except subprocess.CalledProcessError as e: raise ReplayGainError( - "{0} exited with status {1}".format(args[0], e.returncode) + u"{0} exited with status {1}".format(args[0], e.returncode) ) except UnicodeEncodeError: # Due to a bug in Python 2's subprocess on Windows, Unicode # filenames can fail to encode on that platform. See: # http://code.google.com/p/beets/issues/detail?id=499 - raise ReplayGainError("argument encoding failed") + raise ReplayGainError(u"argument encoding failed") # Backend base and plumbing classes. @@ -111,11 +110,11 @@ class Bs1770gainBackend(Backend): self.command = cmd except OSError: raise FatalReplayGainError( - 'Is bs1770gain installed? Is your method in config correct?' + u'Is bs1770gain installed? Is your method in config correct?' ) if not self.command: raise FatalReplayGainError( - 'no replaygain command found: install bs1770gain' + u'no replaygain command found: install bs1770gain' ) def compute_track_gain(self, items): @@ -137,7 +136,7 @@ class Bs1770gainBackend(Backend): output = self.compute_gain(supported_items, True) if not output: - raise ReplayGainError('no output from bs1770gain') + raise ReplayGainError(u'no output from bs1770gain') return AlbumGain(output[-1], output[:-1]) def isplitter(self, items, chunk_at): @@ -204,7 +203,9 @@ class Bs1770gainBackend(Backend): args = cmd + [syspath(i.path, prefix=False) for i in items] # Invoke the command. - self._log.debug("executing {0}", " ".join(map(displayable_path, args))) + self._log.debug( + u'executing {0}', u' '.join(map(displayable_path, args)) + ) output = call(args) self._log.debug(u'analysis finished: {0}', output) @@ -228,8 +229,8 @@ class Bs1770gainBackend(Backend): for parts in results[0:num_lines]: part = parts.split(b'\n') if len(part) == 0: - self._log.debug('bad tool output: {0!r}', text) - raise ReplayGainError('bs1770gain failed') + self._log.debug(u'bad tool output: {0!r}', text) + raise ReplayGainError(u'bs1770gain failed') try: song = { @@ -238,7 +239,7 @@ class Bs1770gainBackend(Backend): 'peak': float(part[2].split('/')[1]), } except IndexError: - self._log.info('bs1770gain reports (faulty file?): {}', parts) + self._log.info(u'bs1770gain reports (faulty file?): {}', parts) continue out.append(Gain(song['gain'], song['peak'])) @@ -261,9 +262,8 @@ class CommandBackend(Backend): # Explicit executable path. if not os.path.isfile(self.command): raise FatalReplayGainError( - 'replaygain command does not exist: {0}'.format( - self.command - ) + u'replaygain command does not exist: {0}'.format( + self.command) ) else: # Check whether the program is in $PATH. @@ -275,7 +275,7 @@ class CommandBackend(Backend): pass if not self.command: raise FatalReplayGainError( - 'no replaygain command found: install mp3gain or aacgain' + u'no replaygain command found: install mp3gain or aacgain' ) self.noclip = config['noclip'].get(bool) @@ -322,7 +322,7 @@ class CommandBackend(Backend): the album gain """ if len(items) == 0: - self._log.debug('no supported tracks to analyze') + self._log.debug(u'no supported tracks to analyze') return [] """Compute ReplayGain values and return a list of results @@ -361,7 +361,7 @@ class CommandBackend(Backend): parts = line.split(b'\t') if len(parts) != 6 or parts[0] == b'File': self._log.debug(u'bad tool output: {0}', text) - raise ReplayGainError('mp3gain failed') + raise ReplayGainError(u'mp3gain failed') d = { 'file': parts[0], 'mp3gain': int(parts[1]), @@ -397,7 +397,7 @@ class GStreamerBackend(Backend): if self._src is None or self._decbin is None or self._conv is None \ or self._res is None or self._rg is None: raise FatalGstreamerPluginReplayGainError( - "Failed to load required GStreamer plugins" + u"Failed to load required GStreamer plugins" ) # We check which files need gain ourselves, so all files given @@ -444,14 +444,14 @@ class GStreamerBackend(Backend): import gi except ImportError: raise FatalReplayGainError( - "Failed to load GStreamer: python-gi not found" + u"Failed to load GStreamer: python-gi not found" ) try: gi.require_version('Gst', '1.0') except ValueError as e: raise FatalReplayGainError( - "Failed to load GStreamer 1.0: {0}".format(e) + u"Failed to load GStreamer 1.0: {0}".format(e) ) from gi.repository import GObject, Gst, GLib @@ -486,7 +486,7 @@ class GStreamerBackend(Backend): def compute_track_gain(self, items): self.compute(items, False) if len(self._file_tags) != len(items): - raise ReplayGainError("Some tracks did not receive tags") + raise ReplayGainError(u"Some tracks did not receive tags") ret = [] for item in items: @@ -499,7 +499,7 @@ class GStreamerBackend(Backend): items = list(album.items()) self.compute(items, True) if len(self._file_tags) != len(items): - raise ReplayGainError("Some items in album did not receive tags") + raise ReplayGainError(u"Some items in album did not receive tags") # Collect track gains. track_gains = [] @@ -508,7 +508,7 @@ class GStreamerBackend(Backend): gain = self._file_tags[item]["TRACK_GAIN"] peak = self._file_tags[item]["TRACK_PEAK"] except KeyError: - raise ReplayGainError("results missing for track") + raise ReplayGainError(u"results missing for track") track_gains.append(Gain(gain, peak)) # Get album gain information from the last track. @@ -517,7 +517,7 @@ class GStreamerBackend(Backend): gain = last_tags["ALBUM_GAIN"] peak = last_tags["ALBUM_PEAK"] except KeyError: - raise ReplayGainError("results missing for album") + raise ReplayGainError(u"results missing for album") return AlbumGain(Gain(gain, peak), track_gains) @@ -539,7 +539,7 @@ class GStreamerBackend(Backend): f = self._src.get_property("location") # A GStreamer error, either an unsupported format or a bug. self._error = ReplayGainError( - "Error {0!r} - {1!r} on file {2!r}".format(err, debug, f) + u"Error {0!r} - {1!r} on file {2!r}".format(err, debug, f) ) def _on_tag(self, bus, message): @@ -663,7 +663,7 @@ class AudioToolsBackend(Backend): import audiotools.replaygain except ImportError: raise FatalReplayGainError( - "Failed to load audiotools: audiotools not found" + u"Failed to load audiotools: audiotools not found" ) self._mod_audiotools = audiotools self._mod_replaygain = audiotools.replaygain @@ -681,11 +681,11 @@ class AudioToolsBackend(Backend): audiofile = self._mod_audiotools.open(item.path) except IOError: raise ReplayGainError( - "File {} was not found".format(item.path) + u"File {} was not found".format(item.path) ) except self._mod_audiotools.UnsupportedFile: raise ReplayGainError( - "Unsupported file type {}".format(item.format) + u"Unsupported file type {}".format(item.format) ) return audiofile @@ -704,8 +704,7 @@ class AudioToolsBackend(Backend): rg = self._mod_replaygain.ReplayGain(audiofile.sample_rate()) except ValueError: raise ReplayGainError( - "Unsupported sample rate {}".format(item.samplerate) - ) + u"Unsupported sample rate {}".format(item.samplerate)) return return rg @@ -730,8 +729,8 @@ class AudioToolsBackend(Backend): except ValueError as exc: # `audiotools.replaygain` can raise a `ValueError` if the sample # rate is incorrect. - self._log.debug('error in rg.title_gain() call: {}', exc) - raise ReplayGainError('audiotools audio data error') + self._log.debug(u'error in rg.title_gain() call: {}', exc) + raise ReplayGainError(u'audiotools audio data error') def _compute_track_gain(self, item): """Compute ReplayGain value for the requested item. @@ -830,8 +829,7 @@ class ReplayGainPlugin(BeetsPlugin): ) except (ReplayGainError, FatalReplayGainError) as e: raise ui.UserError( - 'replaygain initialization failed: {0}'.format(e) - ) + u'replaygain initialization failed: {0}'.format(e)) def track_requires_gain(self, item): return self.overwrite or \ @@ -894,8 +892,7 @@ class ReplayGainPlugin(BeetsPlugin): self._log.info(u"ReplayGain error: {0}", e) except FatalReplayGainError as e: raise ui.UserError( - u"Fatal replay gain error: {0}".format(e) - ) + u"Fatal replay gain error: {0}".format(e)) def handle_track(self, item, write): """Compute track replay gain and store it in the item. @@ -924,8 +921,7 @@ class ReplayGainPlugin(BeetsPlugin): self._log.info(u"ReplayGain error: {0}", e) except FatalReplayGainError as e: raise ui.UserError( - u"Fatal replay gain error: {0}".format(e) - ) + u"Fatal replay gain error: {0}".format(e)) def imported(self, session, task): """Add replay gain info to items or albums of ``task``. @@ -951,7 +947,7 @@ class ReplayGainPlugin(BeetsPlugin): for item in lib.items(ui.decargs(args)): self.handle_track(item, write) - cmd = ui.Subcommand('replaygain', help='analyze for ReplayGain') + cmd = ui.Subcommand('replaygain', help=u'analyze for ReplayGain') cmd.parser.add_album_option() cmd.func = func return [cmd] diff --git a/beetsplug/rewrite.py b/beetsplug/rewrite.py index 2327bc780..b0104a118 100644 --- a/beetsplug/rewrite.py +++ b/beetsplug/rewrite.py @@ -16,8 +16,7 @@ """Uses user-specified rewriting rules to canonicalize names for path formats. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import re from collections import defaultdict @@ -56,9 +55,9 @@ class RewritePlugin(BeetsPlugin): try: fieldname, pattern = key.split(None, 1) except ValueError: - raise ui.UserError("invalid rewrite specification") + raise ui.UserError(u"invalid rewrite specification") if fieldname not in library.Item._fields: - raise ui.UserError("invalid field name (%s) in rewriter" % + raise ui.UserError(u"invalid field name (%s) in rewriter" % fieldname) self._log.debug(u'adding template field {0}', key) pattern = re.compile(pattern.lower()) diff --git a/beetsplug/scrub.py b/beetsplug/scrub.py index 34e6428ad..1c842f234 100644 --- a/beetsplug/scrub.py +++ b/beetsplug/scrub.py @@ -17,8 +17,7 @@ automatically whenever tags are written. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from beets.plugins import BeetsPlugin from beets import ui @@ -64,10 +63,11 @@ class ScrubPlugin(BeetsPlugin): util.displayable_path(item.path)) self._scrub_item(item, opts.write) - scrub_cmd = ui.Subcommand('scrub', help='clean audio tags') - scrub_cmd.parser.add_option('-W', '--nowrite', dest='write', - action='store_false', default=True, - help='leave tags empty') + scrub_cmd = ui.Subcommand('scrub', help=u'clean audio tags') + scrub_cmd.parser.add_option( + u'-W', u'--nowrite', dest='write', + action='store_false', default=True, + help=u'leave tags empty') scrub_cmd.func = scrub_func return [scrub_cmd] diff --git a/beetsplug/smartplaylist.py b/beetsplug/smartplaylist.py index cc988b22c..f6d7f7157 100644 --- a/beetsplug/smartplaylist.py +++ b/beetsplug/smartplaylist.py @@ -16,8 +16,7 @@ """Generates smart playlists based on beets queries. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from beets.plugins import BeetsPlugin from beets import ui @@ -46,9 +45,11 @@ class SmartPlaylistPlugin(BeetsPlugin): self.register_listener('database_change', self.db_change) def commands(self): - spl_update = ui.Subcommand('splupdate', - help='update the smart playlists. Playlist ' - 'names may be passed as arguments.') + spl_update = ui.Subcommand( + 'splupdate', + help=u'update the smart playlists. Playlist names may be ' + u'passed as arguments.' + ) spl_update.func = self.update_cmd return [spl_update] @@ -64,9 +65,10 @@ class SmartPlaylistPlugin(BeetsPlugin): for name, q, a_q in self._unmatched_playlists if name in args) if not playlists: - raise ui.UserError('No playlist matching any of {0} ' - 'found'.format([name for name, _, _ in - self._unmatched_playlists])) + raise ui.UserError( + u'No playlist matching any of {0} found'.format( + [name for name, _, _ in self._unmatched_playlists]) + ) self._matched_playlists = playlists self._unmatched_playlists -= playlists @@ -95,7 +97,7 @@ class SmartPlaylistPlugin(BeetsPlugin): for playlist in self.config['playlists'].get(list): if 'name' not in playlist: - self._log.warn("playlist configuration is missing name") + self._log.warn(u"playlist configuration is missing name") continue playlist_data = (playlist['name'],) @@ -131,7 +133,7 @@ class SmartPlaylistPlugin(BeetsPlugin): playlist_data += (query_and_sort,) except ParsingError as exc: - self._log.warn("invalid query in playlist {}: {}", + self._log.warn(u"invalid query in playlist {}: {}", playlist['name'], exc) continue @@ -151,14 +153,15 @@ class SmartPlaylistPlugin(BeetsPlugin): for playlist in self._unmatched_playlists: n, (q, _), (a_q, _) = playlist if self.matches(model, q, a_q): - self._log.debug("{0} will be updated because of {1}", n, model) + self._log.debug( + u"{0} will be updated because of {1}", n, model) self._matched_playlists.add(playlist) self.register_listener('cli_exit', self.update_playlists) self._unmatched_playlists -= self._matched_playlists def update_playlists(self, lib): - self._log.info("Updating {0} smart playlists...", + self._log.info(u"Updating {0} smart playlists...", len(self._matched_playlists)) playlist_dir = self.config['playlist_dir'].as_filename() @@ -196,4 +199,4 @@ class SmartPlaylistPlugin(BeetsPlugin): with open(syspath(m3u_path), 'w') as f: for path in m3us[m3u]: f.write(path + b'\n') - self._log.info("{0} playlists updated", len(self._matched_playlists)) + self._log.info(u"{0} playlists updated", len(self._matched_playlists)) diff --git a/beetsplug/spotify.py b/beetsplug/spotify.py index f77756dbc..081a027f2 100644 --- a/beetsplug/spotify.py +++ b/beetsplug/spotify.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import re import webbrowser @@ -41,17 +40,17 @@ class SpotifyPlugin(BeetsPlugin): self.output_results(results) spotify_cmd = ui.Subcommand( 'spotify', - help='build a Spotify playlist' + help=u'build a Spotify playlist' ) spotify_cmd.parser.add_option( - '-m', '--mode', action='store', - help='"open" to open Spotify with playlist, ' - '"list" to print (default)' + u'-m', u'--mode', action='store', + help=u'"open" to open Spotify with playlist, ' + u'"list" to print (default)' ) spotify_cmd.parser.add_option( - '-f', '--show-failures', action='store_true', - help='list tracks that did not match a Spotify ID', - dest='show_failures', + u'-f', u'--show-failures', + action='store_true', dest='show_failures', + help=u'list tracks that did not match a Spotify ID' ) spotify_cmd.func = queries return [spotify_cmd] diff --git a/beetsplug/the.py b/beetsplug/the.py index b6ffc945f..6bed4c6ed 100644 --- a/beetsplug/the.py +++ b/beetsplug/the.py @@ -15,8 +15,7 @@ """Moves patterns in path formats (suitable for moving articles).""" -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import re from beets.plugins import BeetsPlugin diff --git a/beetsplug/thumbnails.py b/beetsplug/thumbnails.py index ca2a942a9..da4a4027b 100644 --- a/beetsplug/thumbnails.py +++ b/beetsplug/thumbnails.py @@ -19,8 +19,7 @@ This plugin is POSIX-only. Spec: standards.freedesktop.org/thumbnail-spec/latest/index.html """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from hashlib import md5 import os @@ -58,14 +57,15 @@ class ThumbnailsPlugin(BeetsPlugin): def commands(self): thumbnails_command = Subcommand("thumbnails", - help="Create album thumbnails") + help=u"Create album thumbnails") thumbnails_command.parser.add_option( - '-f', '--force', dest='force', action='store_true', default=False, - help='force regeneration of thumbnails deemed fine (existing & ' - 'recent enough)') + u'-f', u'--force', + dest='force', action='store_true', default=False, + help=u'force regeneration of thumbnails deemed fine (existing & ' + u'recent enough)') thumbnails_command.parser.add_option( - '--dolphin', dest='dolphin', action='store_true', default=False, - help="create Dolphin-compatible thumbnail information (for KDE)") + u'--dolphin', dest='dolphin', action='store_true', default=False, + help=u"create Dolphin-compatible thumbnail information (for KDE)") thumbnails_command.func = self.process_query return [thumbnails_command] @@ -84,8 +84,8 @@ class ThumbnailsPlugin(BeetsPlugin): - detect whether we'll use GIO or Python to get URIs """ if not ArtResizer.shared.local: - self._log.warning("No local image resizing capabilities, " - "cannot generate thumbnails") + self._log.warning(u"No local image resizing capabilities, " + u"cannot generate thumbnails") return False for dir in (NORMAL_DIR, LARGE_DIR): @@ -99,12 +99,12 @@ class ThumbnailsPlugin(BeetsPlugin): assert has_PIL() # since we're local self.write_metadata = write_metadata_pil tool = "PIL" - self._log.debug("using {0} to write metadata", tool) + self._log.debug(u"using {0} to write metadata", tool) uri_getter = GioURI() if not uri_getter.available: uri_getter = PathlibURI() - self._log.debug("using {0.name} to compute URIs", uri_getter) + self._log.debug(u"using {0.name} to compute URIs", uri_getter) self.get_uri = uri_getter.uri return True @@ -122,7 +122,7 @@ class ThumbnailsPlugin(BeetsPlugin): size = ArtResizer.shared.get_size(album.artpath) if not size: - self._log.warning('problem getting the picture size for {0}', + self._log.warning(u'problem getting the picture size for {0}', album.artpath) return @@ -132,9 +132,9 @@ class ThumbnailsPlugin(BeetsPlugin): wrote &= self.make_cover_thumbnail(album, 128, NORMAL_DIR) if wrote: - self._log.info('wrote thumbnail for {0}', album) + self._log.info(u'wrote thumbnail for {0}', album) else: - self._log.info('nothing to do for {0}', album) + self._log.info(u'nothing to do for {0}', album) def make_cover_thumbnail(self, album, size, target_dir): """Make a thumbnail of given size for `album` and put it in @@ -145,11 +145,11 @@ class ThumbnailsPlugin(BeetsPlugin): if os.path.exists(target) and \ os.stat(target).st_mtime > os.stat(album.artpath).st_mtime: if self.config['force']: - self._log.debug("found a suitable {1}x{1} thumbnail for {0}, " - "forcing regeneration", album, size) + self._log.debug(u"found a suitable {1}x{1} thumbnail for {0}, " + u"forcing regeneration", album, size) else: - self._log.debug("{1}x{1} thumbnail for {0} exists and is " - "recent enough", album, size) + self._log.debug(u"{1}x{1} thumbnail for {0} exists and is " + u"recent enough", album, size) return False resized = ArtResizer.shared.resize(size, album.artpath, util.syspath(target)) @@ -174,7 +174,7 @@ class ThumbnailsPlugin(BeetsPlugin): try: self.write_metadata(image_path, metadata) except Exception: - self._log.exception("could not write metadata to {0}", + self._log.exception(u"could not write metadata to {0}", util.displayable_path(image_path)) def make_dolphin_cover_thumbnail(self, album): @@ -185,7 +185,7 @@ class ThumbnailsPlugin(BeetsPlugin): with open(outfilename, 'w') as f: f.write(b"[Desktop Entry]\nIcon=./{0}".format(artfile)) f.close() - self._log.debug("Wrote file {0}", util.displayable_path(outfilename)) + self._log.debug(u"Wrote file {0}", util.displayable_path(outfilename)) def write_metadata_im(file, metadata): @@ -266,7 +266,7 @@ class GioURI(URIGetter): def uri(self, path): g_file_ptr = self.libgio.g_file_new_for_path(path) if not g_file_ptr: - raise RuntimeError("No gfile pointer received for {0}".format( + raise RuntimeError(u"No gfile pointer received for {0}".format( util.displayable_path(path))) try: @@ -277,8 +277,8 @@ class GioURI(URIGetter): self.libgio.g_object_unref(g_file_ptr) if not uri_ptr: self.libgio.g_free(uri_ptr) - raise RuntimeError("No URI received from the gfile pointer for " - "{0}".format(util.displayable_path(path))) + raise RuntimeError(u"No URI received from the gfile pointer for " + u"{0}".format(util.displayable_path(path))) try: uri = copy_c_string(uri_ptr) diff --git a/beetsplug/types.py b/beetsplug/types.py index 4c5d20a45..0c078881c 100644 --- a/beetsplug/types.py +++ b/beetsplug/types.py @@ -13,8 +13,7 @@ # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from beets.plugins import BeetsPlugin from beets.dbcore import types diff --git a/beetsplug/web/__init__.py b/beetsplug/web/__init__.py index 377915626..ede4658a2 100644 --- a/beetsplug/web/__init__.py +++ b/beetsplug/web/__init__.py @@ -14,8 +14,7 @@ # included in all copies or substantial portions of the Software. """A Web interface to beets.""" -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from beets.plugins import BeetsPlugin from beets import ui @@ -264,9 +263,9 @@ class WebPlugin(BeetsPlugin): }) def commands(self): - cmd = ui.Subcommand('web', help='start a Web interface') - cmd.parser.add_option('-d', '--debug', action='store_true', - default=False, help='debug mode') + cmd = ui.Subcommand('web', help=u'start a Web interface') + cmd.parser.add_option(u'-d', u'--debug', action='store_true', + default=False, help=u'debug mode') def func(lib, opts, args): args = ui.decargs(args) @@ -278,7 +277,7 @@ class WebPlugin(BeetsPlugin): app.config['lib'] = lib # Enable CORS if required. if self.config['cors']: - self._log.info('Enabling CORS with origin: {0}', + self._log.info(u'Enabling CORS with origin: {0}', self.config['cors']) from flask.ext.cors import CORS app.config['CORS_ALLOW_HEADERS'] = "Content-Type" diff --git a/beetsplug/zero.py b/beetsplug/zero.py index b427bbe8a..d20f76166 100644 --- a/beetsplug/zero.py +++ b/beetsplug/zero.py @@ -15,8 +15,7 @@ """ Clears tag fields in media files.""" -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import re from beets.plugins import BeetsPlugin diff --git a/test/_common.py b/test/_common.py index 9f8b9f146..c64ff0b71 100644 --- a/test/_common.py +++ b/test/_common.py @@ -14,8 +14,7 @@ # included in all copies or substantial portions of the Software. """Some common functionality for beets' test cases.""" -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import time import sys @@ -102,11 +101,11 @@ def album(lib=None): _item_ident += 1 i = beets.library.Album( artpath=None, - albumartist='some album artist', - albumartist_sort='some sort album artist', - albumartist_credit='some album artist credit', - album='the album', - genre='the genre', + albumartist=u'some album artist', + albumartist_sort=u'some sort album artist', + albumartist_credit=u'some album artist credit', + album=u'the album', + genre=u'the genre', year=2014, month=2, day=5, @@ -170,11 +169,11 @@ class TestCase(unittest.TestCase): def assertExists(self, path): self.assertTrue(os.path.exists(path), - 'file does not exist: {!r}'.format(path)) + u'file does not exist: {!r}'.format(path)) def assertNotExists(self, path): self.assertFalse(os.path.exists(path), - 'file exists: {!r}'.format((path))) + u'file exists: {!r}'.format((path))) class LibTestCase(TestCase): @@ -228,7 +227,7 @@ class InputException(Exception): def __str__(self): msg = "Attempt to read with no input provided." if self.output is not None: - msg += " Output: %s" % self.output + msg += " Output: {!r}".format(self.output) return msg @@ -352,5 +351,5 @@ def slow_test(unused=None): def _id(obj): return obj if 'SKIP_SLOW_TESTS' in os.environ: - return unittest.skip('test is slow') + return unittest.skip(u'test is slow') return _id diff --git a/test/helper.py b/test/helper.py index e2bc42351..0f708b640 100644 --- a/test/helper.py +++ b/test/helper.py @@ -31,8 +31,7 @@ information or mock the environment. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import sys import os @@ -244,7 +243,7 @@ class TestHelper(object): track_no = 0 album_item_count = item_count while album_item_count: - title = 'track {0}'.format(track_no) + title = u'track {0}'.format(track_no) src = os.path.join(_common.RSRC, 'full.mp3') dest = os.path.join(album_dir, '{0}.mp3'.format(title)) if os.path.exists(dest): @@ -527,14 +526,14 @@ def generate_album_info(album_id, track_ids): """ tracks = [generate_track_info(id) for id in track_ids] album = AlbumInfo( - album_id='album info', - album='album info', - artist='album info', - artist_id='album info', + album_id=u'album info', + album=u'album info', + artist=u'album info', + artist_id=u'album info', tracks=tracks, ) for field in ALBUM_INFO_FIELDS: - setattr(album, field, 'album info') + setattr(album, field, u'album info') return album @@ -553,11 +552,11 @@ def generate_track_info(track_id='track info', values={}): string fields are set to "track info". """ track = TrackInfo( - title='track info', + title=u'track info', track_id=track_id, ) for field in TRACK_INFO_FIELDS: - setattr(track, field, 'track info') + setattr(track, field, u'track info') for field, value in values.items(): setattr(track, field, value) return track diff --git a/test/lyrics_download_samples.py b/test/lyrics_download_samples.py index 3a32577f9..280f076a2 100644 --- a/test/lyrics_download_samples.py +++ b/test/lyrics_download_samples.py @@ -13,8 +13,7 @@ # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import os import sys @@ -45,7 +44,7 @@ def main(argv=None): """ if argv is None: argv = sys.argv - print('Fetching samples from:') + print(u'Fetching samples from:') for s in test_lyrics.GOOGLE_SOURCES + test_lyrics.DEFAULT_SOURCES: print(s['url']) url = s['url'] + s['path'] diff --git a/test/rsrc/beetsplug/test.py b/test/rsrc/beetsplug/test.py index 85c6eb0c2..6dedd0e33 100644 --- a/test/rsrc/beetsplug/test.py +++ b/test/rsrc/beetsplug/test.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from beets.plugins import BeetsPlugin from beets import ui @@ -17,7 +16,7 @@ class TestPlugin(BeetsPlugin): test.func = lambda *args: None # Used in CompletionTest - test.parser.add_option('-o', '--option', dest='my_opt') + test.parser.add_option(u'-o', u'--option', dest='my_opt') plugin = ui.Subcommand('plugin') plugin.func = lambda *args: None diff --git a/test/test_art.py b/test/test_art.py index 7902bb213..ebfcd53f4 100644 --- a/test/test_art.py +++ b/test/test_art.py @@ -15,8 +15,7 @@ """Tests for the album art fetchers.""" -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import os import shutil @@ -298,10 +297,10 @@ class ArtImporterTest(UseThePlugin): self.task.is_album = True self.task.album = self.album info = AlbumInfo( - album='some album', - album_id='albumid', - artist='some artist', - artist_id='artistid', + album=u'some album', + album_id=u'albumid', + artist=u'some artist', + artist_id=u'artistid', tracks=[], ) self.task.set_choice(AlbumMatch(0, info, {}, set(), set())) @@ -439,7 +438,7 @@ class ArtForAlbumTest(UseThePlugin): PIL (so comparisons and measurements are unavailable). """ if ArtResizer.shared.method[0] == WEBPROXY: - self.skipTest("ArtResizer has no local imaging backend available") + self.skipTest(u"ArtResizer has no local imaging backend available") def test_respect_minwidth(self): self._require_backend() diff --git a/test/test_autotag.py b/test/test_autotag.py index 2aecfb559..30d60f8c4 100644 --- a/test/test_autotag.py +++ b/test/test_autotag.py @@ -15,8 +15,7 @@ """Tests for autotagging functionality. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import re import copy @@ -636,7 +635,7 @@ class ApplyTest(_common.TestCase, ApplyTestUtil): trackinfo = [] trackinfo.append(TrackInfo( u'oneNew', - 'dfa939ec-118c-4d0f-84a0-60f3d1e6522c', + u'dfa939ec-118c-4d0f-84a0-60f3d1e6522c', medium=1, medium_index=1, medium_total=1, @@ -646,7 +645,7 @@ class ApplyTest(_common.TestCase, ApplyTestUtil): )) trackinfo.append(TrackInfo( u'twoNew', - '40130ed1-a27c-42fd-a328-1ebefb6caef4', + u'40130ed1-a27c-42fd-a328-1ebefb6caef4', medium=2, medium_index=1, index=2, @@ -808,16 +807,16 @@ class ApplyCompilationTest(_common.TestCase, ApplyTestUtil): trackinfo = [] trackinfo.append(TrackInfo( u'oneNew', - 'dfa939ec-118c-4d0f-84a0-60f3d1e6522c', + u'dfa939ec-118c-4d0f-84a0-60f3d1e6522c', u'artistOneNew', - 'a05686fc-9db2-4c23-b99e-77f5db3e5282', + u'a05686fc-9db2-4c23-b99e-77f5db3e5282', index=1, )) trackinfo.append(TrackInfo( u'twoNew', - '40130ed1-a27c-42fd-a328-1ebefb6caef4', + u'40130ed1-a27c-42fd-a328-1ebefb6caef4', u'artistTwoNew', - '80b3cf5e-18fe-4c59-98c7-e5bb87210710', + u'80b3cf5e-18fe-4c59-98c7-e5bb87210710', index=2, )) self.info = AlbumInfo( diff --git a/test/test_bucket.py b/test/test_bucket.py index 81a5d4441..395d2a546 100644 --- a/test/test_bucket.py +++ b/test/test_bucket.py @@ -15,8 +15,7 @@ """Tests for the 'bucket' plugin.""" -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from test._common import unittest from beetsplug import bucket diff --git a/test/test_config_command.py b/test/test_config_command.py index 60cf9de25..f00594b80 100644 --- a/test/test_config_command.py +++ b/test/test_config_command.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import os import yaml diff --git a/test/test_convert.py b/test/test_convert.py index 72d52feaa..20ed6c743 100644 --- a/test/test_convert.py +++ b/test/test_convert.py @@ -13,8 +13,7 @@ # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import re import os.path diff --git a/test/test_datequery.py b/test/test_datequery.py index 9ad741ee0..6c9818b77 100644 --- a/test/test_datequery.py +++ b/test/test_datequery.py @@ -15,8 +15,7 @@ """Test for dbcore's date-based queries. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from test import _common from test._common import unittest diff --git a/test/test_dbcore.py b/test/test_dbcore.py index 39b7eea1e..0098dc375 100644 --- a/test/test_dbcore.py +++ b/test/test_dbcore.py @@ -15,8 +15,7 @@ """Tests for the DBCore database abstraction. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import os import shutil @@ -313,7 +312,7 @@ class ModelTest(unittest.TestCase): def test_computed_field(self): model = TestModelWithGetters() self.assertEqual(model.aComputedField, 'thing') - with self.assertRaisesRegexp(KeyError, 'computed field .+ deleted'): + with self.assertRaisesRegexp(KeyError, u'computed field .+ deleted'): del model.aComputedField def test_items(self): @@ -329,7 +328,7 @@ class ModelTest(unittest.TestCase): model._db def test_parse_nonstring(self): - with self.assertRaisesRegexp(TypeError, "must be a string"): + with self.assertRaisesRegexp(TypeError, u"must be a string"): dbcore.Model._parse(None, 42) diff --git a/test/test_echonest.py b/test/test_echonest.py index cf460e19c..f19b901d6 100644 --- a/test/test_echonest.py +++ b/test/test_echonest.py @@ -14,8 +14,7 @@ # included in all copies or substantial portions of the Software. -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import os.path from mock import Mock, patch @@ -31,7 +30,7 @@ class EchonestCliTest(unittest.TestCase, TestHelper): try: __import__('pyechonest') except ImportError: - self.skipTest('pyechonest not available') + self.skipTest(u'pyechonest not available') self.setup_beets() self.load_plugins('echonest') @@ -157,7 +156,7 @@ class EchonestCliTest(unittest.TestCase, TestHelper): def test_custom_field_range_query(self): item = Item(liveness=2.2) item.add(self.lib) - item = self.lib.items('liveness:2.2..3').get() + item = self.lib.items(u'liveness:2.2..3').get() self.assertEqual(item['liveness'], 2.2) def profile(self, item, **values): diff --git a/test/test_edit.py b/test/test_edit.py index c35c71c08..3bb817734 100644 --- a/test/test_edit.py +++ b/test/test_edit.py @@ -12,8 +12,7 @@ # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import codecs from mock import patch @@ -218,7 +217,7 @@ class EditCommandTest(unittest.TestCase, TestHelper, EditMixin): # Apply changes. ['a']) - self.assertEqual(self.lib.items('id:1')[0].foo, 'bar') + self.assertEqual(self.lib.items(u'id:1')[0].foo, 'bar') self.assertCounts(write_call_count=1, title_starts_with=u't\u00eftle') @@ -265,7 +264,7 @@ class EditCommandTest(unittest.TestCase, TestHelper, EditMixin): """Edit the yaml file incorrectly (resulting in a well-formed but invalid yaml document).""" # Edit the yaml file to an invalid but parseable file. - self.run_mocked_command({'contents': 'wellformed: yes, but invalid'}, + self.run_mocked_command({'contents': u'wellformed: yes, but invalid'}, # No stdin. []) diff --git a/test/test_embedart.py b/test/test_embedart.py index 8a21f55bc..145593829 100644 --- a/test/test_embedart.py +++ b/test/test_embedart.py @@ -13,8 +13,7 @@ # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import os.path import shutil @@ -101,7 +100,7 @@ class EmbedartCliTest(_common.TestCase, TestHelper): if os.path.isfile(tmp_path): os.remove(tmp_path) - self.fail('Artwork file {0} was not deleted'.format(tmp_path)) + self.fail(u'Artwork file {0} was not deleted'.format(tmp_path)) def test_art_file_missing(self): self.add_album_fixture() @@ -114,7 +113,7 @@ class EmbedartCliTest(_common.TestCase, TestHelper): logging.getLogger('beets.embedart').setLevel(logging.DEBUG) handle, tmp_path = tempfile.mkstemp() - os.write(handle, 'I am not an image.') + os.write(handle, u'I am not an image.') os.close(handle) try: @@ -136,7 +135,7 @@ class EmbedartCliTest(_common.TestCase, TestHelper): mediafile = MediaFile(syspath(item.path)) self.assertEqual(mediafile.images[0].data, self.image_data, - 'Image written is not {0}'.format( + u'Image written is not {0}'.format( self.abbey_artpath)) @require_artresizer_compare @@ -150,7 +149,7 @@ class EmbedartCliTest(_common.TestCase, TestHelper): mediafile = MediaFile(syspath(item.path)) self.assertEqual(mediafile.images[0].data, self.image_data, - 'Image written is not {0}'.format( + u'Image written is not {0}'.format( self.abbey_similarpath)) def test_non_ascii_album_path(self): diff --git a/test/test_embyupdate.py b/test/test_embyupdate.py index dad438491..3928ae390 100644 --- a/test/test_embyupdate.py +++ b/test/test_embyupdate.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from test._common import unittest from test.helper import TestHelper diff --git a/test/test_fetchart.py b/test/test_fetchart.py index f0dda4fce..065905a87 100644 --- a/test/test_fetchart.py +++ b/test/test_fetchart.py @@ -13,8 +13,7 @@ # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import os from test._common import unittest diff --git a/test/test_files.py b/test/test_files.py index 60bc8024a..e3e4857c9 100644 --- a/test/test_files.py +++ b/test/test_files.py @@ -15,8 +15,7 @@ """Test file manipulation functionality of Item. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import shutil import os @@ -73,7 +72,7 @@ class MoveTest(_common.TestCase): old_path = self.i.path self.assertExists(old_path) - self.i.artist = 'newArtist' + self.i.artist = u'newArtist' self.i.move() self.assertNotExists(old_path) self.assertNotExists(os.path.dirname(old_path)) @@ -196,7 +195,7 @@ class AlbumFileTest(_common.TestCase): self.otherdir = os.path.join(self.temp_dir, 'testotherdir') def test_albuminfo_move_changes_paths(self): - self.ai.album = 'newAlbumName' + self.ai.album = u'newAlbumName' self.ai.move() self.ai.store() self.i.load() @@ -205,7 +204,7 @@ class AlbumFileTest(_common.TestCase): def test_albuminfo_move_moves_file(self): oldpath = self.i.path - self.ai.album = 'newAlbumName' + self.ai.album = u'newAlbumName' self.ai.move() self.ai.store() self.i.load() @@ -215,7 +214,7 @@ class AlbumFileTest(_common.TestCase): def test_albuminfo_move_copies_file(self): oldpath = self.i.path - self.ai.album = 'newAlbumName' + self.ai.album = u'newAlbumName' self.ai.move(True) self.ai.store() self.i.load() @@ -261,7 +260,7 @@ class ArtFileTest(_common.TestCase): def test_art_moves_with_album(self): self.assertTrue(os.path.exists(self.art)) oldpath = self.i.path - self.ai.album = 'newAlbum' + self.ai.album = u'newAlbum' self.ai.move() self.i.load() @@ -289,7 +288,7 @@ class ArtFileTest(_common.TestCase): touch(newart) i2 = item() i2.path = self.i.path - i2.artist = 'someArtist' + i2.artist = u'someArtist' ai = self.lib.add_album((i2,)) i2.move(True) @@ -305,7 +304,7 @@ class ArtFileTest(_common.TestCase): touch(newart) i2 = item() i2.path = self.i.path - i2.artist = 'someArtist' + i2.artist = u'someArtist' ai = self.lib.add_album((i2,)) i2.move(True) ai.set_art(newart) @@ -319,7 +318,7 @@ class ArtFileTest(_common.TestCase): touch(newart) i2 = item() i2.path = self.i.path - i2.artist = 'someArtist' + i2.artist = u'someArtist' ai = self.lib.add_album((i2,)) i2.move(True) @@ -336,7 +335,7 @@ class ArtFileTest(_common.TestCase): touch(newart) i2 = item() i2.path = self.i.path - i2.artist = 'someArtist' + i2.artist = u'someArtist' ai = self.lib.add_album((i2,)) i2.move(True) @@ -360,7 +359,7 @@ class ArtFileTest(_common.TestCase): try: i2 = item() i2.path = self.i.path - i2.artist = 'someArtist' + i2.artist = u'someArtist' ai = self.lib.add_album((i2,)) i2.move(True) ai.set_art(newart) @@ -378,12 +377,12 @@ class ArtFileTest(_common.TestCase): oldartpath = self.lib.albums()[0].artpath self.assertExists(oldartpath) - self.ai.album = 'different_album' + self.ai.album = u'different_album' self.ai.store() self.ai.items()[0].move() artpath = self.lib.albums()[0].artpath - self.assertTrue('different_album' in artpath) + self.assertTrue(u'different_album' in artpath) self.assertExists(artpath) self.assertNotExists(oldartpath) @@ -395,12 +394,12 @@ class ArtFileTest(_common.TestCase): oldartpath = self.lib.albums()[0].artpath self.assertExists(oldartpath) - self.i.album = 'different_album' + self.i.album = u'different_album' self.i.album_id = None # detach from album self.i.move() artpath = self.lib.albums()[0].artpath - self.assertFalse('different_album' in artpath) + self.assertFalse(u'different_album' in artpath) self.assertEqual(artpath, oldartpath) self.assertExists(oldartpath) @@ -481,7 +480,7 @@ class SoftRemoveTest(_common.TestCase): try: util.remove(self.path + 'XXX', True) except OSError: - self.fail('OSError when removing path') + self.fail(u'OSError when removing path') class SafeMoveCopyTest(_common.TestCase): diff --git a/test/test_ftintitle.py b/test/test_ftintitle.py index 481917f85..b8fa90681 100644 --- a/test/test_ftintitle.py +++ b/test/test_ftintitle.py @@ -15,8 +15,7 @@ """Tests for the 'ftintitle' plugin.""" -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from test._common import unittest from test.helper import TestHelper @@ -150,33 +149,33 @@ class FtInTitlePluginTest(unittest.TestCase): self.assertEqual(feat_part, test_case['feat_part']) def test_split_on_feat(self): - parts = ftintitle.split_on_feat('Alice ft. Bob') - self.assertEqual(parts, ('Alice', 'Bob')) - parts = ftintitle.split_on_feat('Alice feat Bob') - self.assertEqual(parts, ('Alice', 'Bob')) - parts = ftintitle.split_on_feat('Alice feat. Bob') - self.assertEqual(parts, ('Alice', 'Bob')) - parts = ftintitle.split_on_feat('Alice featuring Bob') - self.assertEqual(parts, ('Alice', 'Bob')) - parts = ftintitle.split_on_feat('Alice & Bob') - self.assertEqual(parts, ('Alice', 'Bob')) - parts = ftintitle.split_on_feat('Alice and Bob') - self.assertEqual(parts, ('Alice', 'Bob')) - parts = ftintitle.split_on_feat('Alice With Bob') - self.assertEqual(parts, ('Alice', 'Bob')) - parts = ftintitle.split_on_feat('Alice defeat Bob') - self.assertEqual(parts, ('Alice defeat Bob', None)) + parts = ftintitle.split_on_feat(u'Alice ft. Bob') + self.assertEqual(parts, (u'Alice', u'Bob')) + parts = ftintitle.split_on_feat(u'Alice feat Bob') + self.assertEqual(parts, (u'Alice', u'Bob')) + parts = ftintitle.split_on_feat(u'Alice feat. Bob') + self.assertEqual(parts, (u'Alice', u'Bob')) + parts = ftintitle.split_on_feat(u'Alice featuring Bob') + self.assertEqual(parts, (u'Alice', u'Bob')) + parts = ftintitle.split_on_feat(u'Alice & Bob') + self.assertEqual(parts, (u'Alice', u'Bob')) + parts = ftintitle.split_on_feat(u'Alice and Bob') + self.assertEqual(parts, (u'Alice', u'Bob')) + parts = ftintitle.split_on_feat(u'Alice With Bob') + self.assertEqual(parts, (u'Alice', u'Bob')) + parts = ftintitle.split_on_feat(u'Alice defeat Bob') + self.assertEqual(parts, (u'Alice defeat Bob', None)) def test_contains_feat(self): - self.assertTrue(ftintitle.contains_feat('Alice ft. Bob')) - self.assertTrue(ftintitle.contains_feat('Alice feat. Bob')) - self.assertTrue(ftintitle.contains_feat('Alice feat Bob')) - self.assertTrue(ftintitle.contains_feat('Alice featuring Bob')) - self.assertTrue(ftintitle.contains_feat('Alice & Bob')) - self.assertTrue(ftintitle.contains_feat('Alice and Bob')) - self.assertTrue(ftintitle.contains_feat('Alice With Bob')) - self.assertFalse(ftintitle.contains_feat('Alice defeat Bob')) - self.assertFalse(ftintitle.contains_feat('Aliceft.Bob')) + self.assertTrue(ftintitle.contains_feat(u'Alice ft. Bob')) + self.assertTrue(ftintitle.contains_feat(u'Alice feat. Bob')) + self.assertTrue(ftintitle.contains_feat(u'Alice feat Bob')) + self.assertTrue(ftintitle.contains_feat(u'Alice featuring Bob')) + self.assertTrue(ftintitle.contains_feat(u'Alice & Bob')) + self.assertTrue(ftintitle.contains_feat(u'Alice and Bob')) + self.assertTrue(ftintitle.contains_feat(u'Alice With Bob')) + self.assertFalse(ftintitle.contains_feat(u'Alice defeat Bob')) + self.assertFalse(ftintitle.contains_feat(u'Aliceft.Bob')) def suite(): diff --git a/test/test_ihate.py b/test/test_ihate.py index 1ce4800b9..6567d13be 100644 --- a/test/test_ihate.py +++ b/test/test_ihate.py @@ -2,8 +2,7 @@ """Tests for the 'ihate' plugin""" -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from test._common import unittest from beets import importer @@ -17,7 +16,7 @@ class IHatePluginTest(unittest.TestCase): match_pattern = {} test_item = Item( - genre='TestGenre', + genre=u'TestGenre', album=u'TestAlbum', artist=u'TestArtist') task = importer.SingletonImportTask(None, test_item) @@ -26,25 +25,25 @@ class IHatePluginTest(unittest.TestCase): self.assertFalse(IHatePlugin.do_i_hate_this(task, match_pattern)) # 1 query match. - match_pattern = ["artist:bad_artist", "artist:TestArtist"] + match_pattern = [u"artist:bad_artist", u"artist:TestArtist"] self.assertTrue(IHatePlugin.do_i_hate_this(task, match_pattern)) # 2 query matches, either should trigger. - match_pattern = ["album:test", "artist:testartist"] + match_pattern = [u"album:test", u"artist:testartist"] self.assertTrue(IHatePlugin.do_i_hate_this(task, match_pattern)) # Query is blocked by AND clause. - match_pattern = ["album:notthis genre:testgenre"] + match_pattern = [u"album:notthis genre:testgenre"] self.assertFalse(IHatePlugin.do_i_hate_this(task, match_pattern)) # Both queries are blocked by AND clause with unmatched condition. - match_pattern = ["album:notthis genre:testgenre", - "artist:testartist album:notthis"] + match_pattern = [u"album:notthis genre:testgenre", + u"artist:testartist album:notthis"] self.assertFalse(IHatePlugin.do_i_hate_this(task, match_pattern)) # Only one query should fire. - match_pattern = ["album:testalbum genre:testgenre", - "artist:testartist album:notthis"] + match_pattern = [u"album:testalbum genre:testgenre", + u"artist:testartist album:notthis"] self.assertTrue(IHatePlugin.do_i_hate_this(task, match_pattern)) diff --git a/test/test_importadded.py b/test/test_importadded.py index b8801da60..9fa30f523 100644 --- a/test/test_importadded.py +++ b/test/test_importadded.py @@ -13,8 +13,7 @@ # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function """Tests for the `importadded` plugin.""" @@ -73,7 +72,7 @@ class ImportAddedTest(unittest.TestCase, ImportHelper): for m in self.media_files: if m.title.replace('Tag', 'Applied') == item.title: return m - raise AssertionError("No MediaFile found for Item " + + raise AssertionError(u"No MediaFile found for Item " + util.displayable_path(item.path)) def assertEqualTimes(self, first, second, msg=None): @@ -127,7 +126,7 @@ class ImportAddedTest(unittest.TestCase, ImportHelper): for item in album.items()) for item_path, added_after in items_added_after.iteritems(): self.assertEqualTimes(items_added_before[item_path], added_after, - "reimport modified Item.added for " + + u"reimport modified Item.added for " + item_path) def test_import_singletons_with_added_dates(self): @@ -165,7 +164,7 @@ class ImportAddedTest(unittest.TestCase, ImportHelper): for item in self.lib.items()) for item_path, added_after in items_added_after.iteritems(): self.assertEqualTimes(items_added_before[item_path], added_after, - "reimport modified Item.added for " + + u"reimport modified Item.added for " + item_path) diff --git a/test/test_importer.py b/test/test_importer.py index 56f4a17a5..d1ef6ef18 100644 --- a/test/test_importer.py +++ b/test/test_importer.py @@ -13,8 +13,7 @@ # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function """Tests for the general importer functionality. """ @@ -121,7 +120,7 @@ class AutotagStub(object): else: id = '' if artist is None: - artist = "Various Artists" + artist = u"Various Artists" else: artist = artist.replace('Tag', 'Applied') + id album = album.replace('Tag', 'Applied') + id @@ -150,9 +149,9 @@ class ImportHelper(TestHelper): def setup_beets(self, disk=False): super(ImportHelper, self).setup_beets(disk) self.lib.path_formats = [ - ('default', os.path.join('$artist', '$album', '$title')), - ('singleton:true', os.path.join('singletons', '$title')), - ('comp:true', os.path.join('compilations', '$album', '$title')), + (u'default', os.path.join('$artist', '$album', '$title')), + (u'singleton:true', os.path.join('singletons', '$title')), + (u'comp:true', os.path.join('compilations', '$album', '$title')), ] def _create_import_dir(self, count=3): @@ -179,8 +178,8 @@ class ImportHelper(TestHelper): resource_path = os.path.join(_common.RSRC, 'full.mp3') metadata = { - 'artist': 'Tag Artist', - 'album': 'Tag Album', + 'artist': u'Tag Artist', + 'album': u'Tag Album', 'albumartist': None, 'mb_trackid': None, 'mb_albumid': None, @@ -195,7 +194,7 @@ class ImportHelper(TestHelper): # Set metadata metadata['track'] = i + 1 - metadata['title'] = 'Tag Title %d' % (i + 1) + metadata['title'] = u'Tag Title %d' % (i + 1) for attr in metadata: setattr(medium, attr, metadata[attr]) medium.save() @@ -250,7 +249,7 @@ class NonAutotaggedImportTest(_common.TestCase, ImportHelper): self.importer.run() albums = self.lib.albums() self.assertEqual(len(albums), 1) - self.assertEqual(albums[0].albumartist, 'Tag Artist') + self.assertEqual(albums[0].albumartist, u'Tag Artist') def test_import_copy_arrives(self): self.importer.run() @@ -411,7 +410,7 @@ class ImportTarTest(ImportZipTest): return path -@unittest.skipIf(not has_program('unrar'), 'unrar program not found') +@unittest.skipIf(not has_program('unrar'), u'unrar program not found') class ImportRarTest(ImportZipTest): def create_archive(self): @@ -446,7 +445,7 @@ class ImportSingletonTest(_common.TestCase, ImportHelper): self.importer.add_choice(importer.action.ASIS) self.importer.run() - self.assertEqual(self.lib.items().get().title, 'Tag Title 1') + self.assertEqual(self.lib.items().get().title, u'Tag Title 1') def test_apply_asis_does_not_add_album(self): self.assertEqual(self.lib.albums().get(), None) @@ -467,7 +466,7 @@ class ImportSingletonTest(_common.TestCase, ImportHelper): self.importer.add_choice(importer.action.APPLY) self.importer.run() - self.assertEqual(self.lib.items().get().title, 'Applied Title 1') + self.assertEqual(self.lib.items().get().title, u'Applied Title 1') def test_apply_candidate_does_not_add_album(self): self.importer.add_choice(importer.action.APPLY) @@ -479,7 +478,7 @@ class ImportSingletonTest(_common.TestCase, ImportHelper): self.importer.add_choice(importer.action.APPLY) self.importer.run() - self.assert_file_in_lib('singletons', 'Applied Title 1.mp3') + self.assert_file_in_lib('singletons', u'Applied Title 1.mp3') def test_skip_does_not_add_first_track(self): self.importer.add_choice(importer.action.SKIP) @@ -532,13 +531,13 @@ class ImportTest(_common.TestCase, ImportHelper): self.importer.add_choice(importer.action.ASIS) self.importer.run() - self.assertEqual(self.lib.albums().get().album, 'Tag Album') + self.assertEqual(self.lib.albums().get().album, u'Tag Album') def test_apply_asis_adds_tracks(self): self.assertEqual(self.lib.items().get(), None) self.importer.add_choice(importer.action.ASIS) self.importer.run() - self.assertEqual(self.lib.items().get().title, 'Tag Title 1') + self.assertEqual(self.lib.items().get().title, u'Tag Title 1') def test_apply_asis_adds_album_path(self): self.assert_lib_dir_empty() @@ -552,14 +551,14 @@ class ImportTest(_common.TestCase, ImportHelper): self.importer.add_choice(importer.action.APPLY) self.importer.run() - self.assertEqual(self.lib.albums().get().album, 'Applied Album') + self.assertEqual(self.lib.albums().get().album, u'Applied Album') def test_apply_candidate_adds_tracks(self): self.assertEqual(self.lib.items().get(), None) self.importer.add_choice(importer.action.APPLY) self.importer.run() - self.assertEqual(self.lib.items().get().title, 'Applied Title 1') + self.assertEqual(self.lib.items().get().title, u'Applied Title 1') def test_apply_candidate_adds_album_path(self): self.assert_lib_dir_empty() @@ -617,7 +616,7 @@ class ImportTest(_common.TestCase, ImportHelper): with capture_log() as logs: self.importer.run() - self.assertIn('No files imported from {0}'.format(import_dir), logs) + self.assertIn(u'No files imported from {0}'.format(import_dir), logs) def test_empty_directory_singleton_warning(self): import_dir = os.path.join(self.temp_dir, 'empty') @@ -626,7 +625,7 @@ class ImportTest(_common.TestCase, ImportHelper): with capture_log() as logs: self.importer.run() - self.assertIn('No files imported from {0}'.format(import_dir), logs) + self.assertIn(u'No files imported from {0}'.format(import_dir), logs) def test_asis_no_data_source(self): self.assertEqual(self.lib.items().get(), None) @@ -659,7 +658,7 @@ class ImportTracksTest(_common.TestCase, ImportHelper): self.importer.add_choice(importer.action.APPLY) self.importer.add_choice(importer.action.APPLY) self.importer.run() - self.assertEqual(self.lib.items().get().title, 'Applied Title 1') + self.assertEqual(self.lib.items().get().title, u'Applied Title 1') self.assertEqual(self.lib.albums().get(), None) def test_apply_tracks_adds_singleton_path(self): @@ -688,27 +687,27 @@ class ImportCompilationTest(_common.TestCase, ImportHelper): def test_asis_homogenous_sets_albumartist(self): self.importer.add_choice(importer.action.ASIS) self.importer.run() - self.assertEqual(self.lib.albums().get().albumartist, 'Tag Artist') + self.assertEqual(self.lib.albums().get().albumartist, u'Tag Artist') for item in self.lib.items(): - self.assertEqual(item.albumartist, 'Tag Artist') + self.assertEqual(item.albumartist, u'Tag Artist') def test_asis_heterogenous_sets_various_albumartist(self): - self.import_media[0].artist = 'Other Artist' + self.import_media[0].artist = u'Other Artist' self.import_media[0].save() - self.import_media[1].artist = 'Another Artist' + self.import_media[1].artist = u'Another Artist' self.import_media[1].save() self.importer.add_choice(importer.action.ASIS) self.importer.run() self.assertEqual(self.lib.albums().get().albumartist, - 'Various Artists') + u'Various Artists') for item in self.lib.items(): - self.assertEqual(item.albumartist, 'Various Artists') + self.assertEqual(item.albumartist, u'Various Artists') def test_asis_heterogenous_sets_sompilation(self): - self.import_media[0].artist = 'Other Artist' + self.import_media[0].artist = u'Other Artist' self.import_media[0].save() - self.import_media[1].artist = 'Another Artist' + self.import_media[1].artist = u'Another Artist' self.import_media[1].save() self.importer.add_choice(importer.action.ASIS) @@ -717,33 +716,33 @@ class ImportCompilationTest(_common.TestCase, ImportHelper): self.assertTrue(item.comp) def test_asis_sets_majority_albumartist(self): - self.import_media[0].artist = 'Other Artist' + self.import_media[0].artist = u'Other Artist' self.import_media[0].save() - self.import_media[1].artist = 'Other Artist' + self.import_media[1].artist = u'Other Artist' self.import_media[1].save() self.importer.add_choice(importer.action.ASIS) self.importer.run() - self.assertEqual(self.lib.albums().get().albumartist, 'Other Artist') + self.assertEqual(self.lib.albums().get().albumartist, u'Other Artist') for item in self.lib.items(): - self.assertEqual(item.albumartist, 'Other Artist') + self.assertEqual(item.albumartist, u'Other Artist') def test_asis_albumartist_tag_sets_albumartist(self): - self.import_media[0].artist = 'Other Artist' - self.import_media[1].artist = 'Another Artist' + self.import_media[0].artist = u'Other Artist' + self.import_media[1].artist = u'Another Artist' for mediafile in self.import_media: - mediafile.albumartist = 'Album Artist' - mediafile.mb_albumartistid = 'Album Artist ID' + mediafile.albumartist = u'Album Artist' + mediafile.mb_albumartistid = u'Album Artist ID' mediafile.save() self.importer.add_choice(importer.action.ASIS) self.importer.run() - self.assertEqual(self.lib.albums().get().albumartist, 'Album Artist') + self.assertEqual(self.lib.albums().get().albumartist, u'Album Artist') self.assertEqual(self.lib.albums().get().mb_albumartistid, - 'Album Artist ID') + u'Album Artist ID') for item in self.lib.items(): - self.assertEqual(item.albumartist, 'Album Artist') - self.assertEqual(item.mb_albumartistid, 'Album Artist ID') + self.assertEqual(item.albumartist, u'Album Artist') + self.assertEqual(item.mb_albumartistid, u'Album Artist ID') class ImportExistingTest(_common.TestCase, ImportHelper): @@ -794,17 +793,17 @@ class ImportExistingTest(_common.TestCase, ImportHelper): def test_asis_updates_metadata(self): self.setup_importer.run() medium = MediaFile(self.lib.items().get().path) - medium.title = 'New Title' + medium.title = u'New Title' medium.save() self.importer.add_choice(importer.action.ASIS) self.importer.run() - self.assertEqual(self.lib.items().get().title, 'New Title') + self.assertEqual(self.lib.items().get().title, u'New Title') def test_asis_updated_moves_file(self): self.setup_importer.run() medium = MediaFile(self.lib.items().get().path) - medium.title = 'New Title' + medium.title = u'New Title' medium.save() old_path = os.path.join('Applied Artist', 'Applied Album', @@ -820,7 +819,7 @@ class ImportExistingTest(_common.TestCase, ImportHelper): def test_asis_updated_without_copy_does_not_move_file(self): self.setup_importer.run() medium = MediaFile(self.lib.items().get().path) - medium.title = 'New Title' + medium.title = u'New Title' medium.save() old_path = os.path.join('Applied Artist', 'Applied Album', @@ -881,8 +880,8 @@ class GroupAlbumsImportTest(_common.TestCase, ImportHelper): self.matcher.restore() def test_add_album_for_different_artist_and_different_album(self): - self.import_media[0].artist = "Artist B" - self.import_media[0].album = "Album B" + self.import_media[0].artist = u"Artist B" + self.import_media[0].album = u"Album B" self.import_media[0].save() self.importer.run() @@ -890,11 +889,11 @@ class GroupAlbumsImportTest(_common.TestCase, ImportHelper): self.assertEqual(albums, set(['Album B', 'Tag Album'])) def test_add_album_for_different_artist_and_same_albumartist(self): - self.import_media[0].artist = "Artist B" - self.import_media[0].albumartist = "Album Artist" + self.import_media[0].artist = u"Artist B" + self.import_media[0].albumartist = u"Album Artist" self.import_media[0].save() - self.import_media[1].artist = "Artist C" - self.import_media[1].albumartist = "Album Artist" + self.import_media[1].artist = u"Artist C" + self.import_media[1].albumartist = u"Album Artist" self.import_media[1].save() self.importer.run() @@ -902,7 +901,7 @@ class GroupAlbumsImportTest(_common.TestCase, ImportHelper): self.assertEqual(artists, set(['Album Artist', 'Tag Artist'])) def test_add_album_for_same_artist_and_different_album(self): - self.import_media[0].album = "Album B" + self.import_media[0].album = u"Album B" self.import_media[0].save() self.importer.run() @@ -910,7 +909,7 @@ class GroupAlbumsImportTest(_common.TestCase, ImportHelper): self.assertEqual(albums, set(['Album B', 'Tag Album'])) def test_add_album_for_same_album_and_different_artist(self): - self.import_media[0].artist = "Artist B" + self.import_media[0].artist = u"Artist B" self.import_media[0].save() self.importer.run() @@ -919,7 +918,7 @@ class GroupAlbumsImportTest(_common.TestCase, ImportHelper): def test_incremental(self): config['import']['incremental'] = True - self.import_media[0].album = "Album B" + self.import_media[0].album = u"Album B" self.import_media[0].save() self.importer.run() @@ -951,12 +950,12 @@ class ChooseCandidateTest(_common.TestCase, ImportHelper): def test_choose_first_candidate(self): self.importer.add_choice(1) self.importer.run() - self.assertEqual(self.lib.albums().get().album, 'Applied Album M') + self.assertEqual(self.lib.albums().get().album, u'Applied Album M') def test_choose_second_candidate(self): self.importer.add_choice(2) self.importer.run() - self.assertEqual(self.lib.albums().get().album, 'Applied Album MM') + self.assertEqual(self.lib.albums().get().album, u'Applied Album MM') class InferAlbumDataTest(_common.TestCase): @@ -966,9 +965,9 @@ class InferAlbumDataTest(_common.TestCase): i1 = _common.item() i2 = _common.item() i3 = _common.item() - i1.title = 'first item' - i2.title = 'second item' - i3.title = 'third item' + i1.title = u'first item' + i2.title = u'second item' + i3.title = u'third item' i1.comp = i2.comp = i3.comp = False i1.albumartist = i2.albumartist = i3.albumartist = '' i1.mb_albumartistid = i2.mb_albumartistid = i3.mb_albumartistid = '' @@ -984,28 +983,28 @@ class InferAlbumDataTest(_common.TestCase): self.assertEqual(self.items[0].albumartist, self.items[2].artist) def test_asis_heterogenous_va(self): - self.items[0].artist = 'another artist' - self.items[1].artist = 'some other artist' + self.items[0].artist = u'another artist' + self.items[1].artist = u'some other artist' self.task.set_choice(importer.action.ASIS) self.task.align_album_level_fields() self.assertTrue(self.items[0].comp) - self.assertEqual(self.items[0].albumartist, 'Various Artists') + self.assertEqual(self.items[0].albumartist, u'Various Artists') def test_asis_comp_applied_to_all_items(self): - self.items[0].artist = 'another artist' - self.items[1].artist = 'some other artist' + self.items[0].artist = u'another artist' + self.items[1].artist = u'some other artist' self.task.set_choice(importer.action.ASIS) self.task.align_album_level_fields() for item in self.items: self.assertTrue(item.comp) - self.assertEqual(item.albumartist, 'Various Artists') + self.assertEqual(item.albumartist, u'Various Artists') def test_asis_majority_artist_single_artist(self): - self.items[0].artist = 'another artist' + self.items[0].artist = u'another artist' self.task.set_choice(importer.action.ASIS) self.task.align_album_level_fields() @@ -1014,19 +1013,19 @@ class InferAlbumDataTest(_common.TestCase): self.assertEqual(self.items[0].albumartist, self.items[2].artist) def test_asis_track_albumartist_override(self): - self.items[0].artist = 'another artist' - self.items[1].artist = 'some other artist' + self.items[0].artist = u'another artist' + self.items[1].artist = u'some other artist' for item in self.items: - item.albumartist = 'some album artist' - item.mb_albumartistid = 'some album artist id' + item.albumartist = u'some album artist' + item.mb_albumartistid = u'some album artist id' self.task.set_choice(importer.action.ASIS) self.task.align_album_level_fields() self.assertEqual(self.items[0].albumartist, - 'some album artist') + u'some album artist') self.assertEqual(self.items[0].mb_albumartistid, - 'some album artist id') + u'some album artist id') def test_apply_gets_artist_and_id(self): self.task.set_choice(AlbumMatch(0, None, {}, set(), set())) # APPLY @@ -1039,16 +1038,16 @@ class InferAlbumDataTest(_common.TestCase): def test_apply_lets_album_values_override(self): for item in self.items: - item.albumartist = 'some album artist' - item.mb_albumartistid = 'some album artist id' + item.albumartist = u'some album artist' + item.mb_albumartistid = u'some album artist id' self.task.set_choice(AlbumMatch(0, None, {}, set(), set())) # APPLY self.task.align_album_level_fields() self.assertEqual(self.items[0].albumartist, - 'some album artist') + u'some album artist') self.assertEqual(self.items[0].mb_albumartistid, - 'some album artist id') + u'some album artist id') def test_small_single_artist_album(self): self.items = [self.items[0]] @@ -1272,11 +1271,11 @@ class ResumeImportTest(unittest.TestCase, TestHelper): self.importer.run() self.assertEqual(len(self.lib.albums()), 1) - self.assertIsNotNone(self.lib.albums('album:album 0').get()) + self.assertIsNotNone(self.lib.albums(u'album:album 0').get()) self.importer.run() self.assertEqual(len(self.lib.albums()), 2) - self.assertIsNotNone(self.lib.albums('album:album 1').get()) + self.assertIsNotNone(self.lib.albums(u'album:album 1').get()) @patch('beets.plugins.send') def test_resume_singleton(self, plugins_send): @@ -1293,11 +1292,11 @@ class ResumeImportTest(unittest.TestCase, TestHelper): self.importer.run() self.assertEqual(len(self.lib.items()), 1) - self.assertIsNotNone(self.lib.items('title:track 0').get()) + self.assertIsNotNone(self.lib.items(u'title:track 0').get()) self.importer.run() self.assertEqual(len(self.lib.items()), 2) - self.assertIsNotNone(self.lib.items('title:track 1').get()) + self.assertIsNotNone(self.lib.items(u'title:track 1').get()) class IncrementalImportTest(unittest.TestCase, TestHelper): @@ -1685,7 +1684,7 @@ class ImportPretendTest(_common.TestCase, ImportHelper): def test_import_pretend_empty(self): logs = self.__run([self.empty_path]) - self.assertEqual(logs, ['No files imported from {0}' + self.assertEqual(logs, [u'No files imported from {0}' .format(displayable_path(self.empty_path))]) diff --git a/test/test_importfeeds.py b/test/test_importfeeds.py index 276a26ff2..df293ce63 100644 --- a/test/test_importfeeds.py +++ b/test/test_importfeeds.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import os import os.path diff --git a/test/test_info.py b/test/test_info.py index fdf0b3861..77f88e7c4 100644 --- a/test/test_info.py +++ b/test/test_info.py @@ -13,8 +13,7 @@ # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from test._common import unittest from test.helper import TestHelper diff --git a/test/test_keyfinder.py b/test/test_keyfinder.py index 898bc566e..90d65bd26 100644 --- a/test/test_keyfinder.py +++ b/test/test_keyfinder.py @@ -13,8 +13,7 @@ # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from mock import patch from test._common import unittest diff --git a/test/test_lastgenre.py b/test/test_lastgenre.py index 9f61107e9..82396f7c7 100644 --- a/test/test_lastgenre.py +++ b/test/test_lastgenre.py @@ -15,8 +15,7 @@ """Tests for the 'lastgenre' plugin.""" -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from mock import Mock @@ -52,7 +51,7 @@ class LastGenrePluginTest(unittest.TestCase, TestHelper): """ self._setup_config() self.assertEqual(self.plugin._resolve_genres(['delta blues']), - 'Delta Blues') + u'Delta Blues') def test_c14n_only(self): """Default c14n tree funnels up to most common genre except for *wrong* @@ -60,16 +59,16 @@ class LastGenrePluginTest(unittest.TestCase, TestHelper): """ self._setup_config(canonical=True, count=99) self.assertEqual(self.plugin._resolve_genres(['delta blues']), - 'Blues') + u'Blues') self.assertEqual(self.plugin._resolve_genres(['iota blues']), - 'Iota Blues') + u'Iota Blues') def test_whitelist_only(self): """Default whitelist rejects *wrong* (non existing) genres. """ self._setup_config(whitelist=True) self.assertEqual(self.plugin._resolve_genres(['iota blues']), - '') + u'') def test_whitelist_c14n(self): """Default whitelist and c14n both activated result in all parents @@ -77,7 +76,7 @@ class LastGenrePluginTest(unittest.TestCase, TestHelper): """ self._setup_config(canonical=True, whitelist=True, count=99) self.assertEqual(self.plugin._resolve_genres(['delta blues']), - 'Delta Blues, Blues') + u'Delta Blues, Blues') def test_whitelist_custom(self): """Keep only genres that are in the whitelist. @@ -85,11 +84,11 @@ class LastGenrePluginTest(unittest.TestCase, TestHelper): self._setup_config(whitelist=set(['blues', 'rock', 'jazz']), count=2) self.assertEqual(self.plugin._resolve_genres(['pop', 'blues']), - 'Blues') + u'Blues') self._setup_config(canonical='', whitelist=set(['rock'])) self.assertEqual(self.plugin._resolve_genres(['delta blues']), - '') + u'') def test_count(self): """Keep the n first genres, as we expect them to be sorted from more to @@ -99,7 +98,7 @@ class LastGenrePluginTest(unittest.TestCase, TestHelper): count=2) self.assertEqual(self.plugin._resolve_genres( ['jazz', 'pop', 'rock', 'blues']), - 'Jazz, Rock') + u'Jazz, Rock') def test_count_c14n(self): """Keep the n first genres, after having applied c14n when necessary @@ -111,14 +110,14 @@ class LastGenrePluginTest(unittest.TestCase, TestHelper): # second slot self.assertEqual(self.plugin._resolve_genres( ['jazz', 'pop', 'country blues', 'rock']), - 'Jazz, Blues') + u'Jazz, Blues') def test_c14n_whitelist(self): """Genres first pass through c14n and are then filtered """ self._setup_config(canonical=True, whitelist=set(['rock'])) self.assertEqual(self.plugin._resolve_genres(['delta blues']), - '') + u'') def test_empty_string_enables_canonical(self): """For backwards compatibility, setting the `canonical` option @@ -126,7 +125,7 @@ class LastGenrePluginTest(unittest.TestCase, TestHelper): """ self._setup_config(canonical='', count=99) self.assertEqual(self.plugin._resolve_genres(['delta blues']), - 'Blues') + u'Blues') def test_empty_string_enables_whitelist(self): """Again for backwards compatibility, setting the `whitelist` @@ -134,14 +133,14 @@ class LastGenrePluginTest(unittest.TestCase, TestHelper): """ self._setup_config(whitelist='') self.assertEqual(self.plugin._resolve_genres(['iota blues']), - '') + u'') def test_no_duplicate(self): """Remove duplicated genres. """ self._setup_config(count=99) self.assertEqual(self.plugin._resolve_genres(['blues', 'blues']), - 'Blues') + u'Blues') def test_tags_for(self): class MockPylastElem(object): @@ -189,29 +188,29 @@ class LastGenrePluginTest(unittest.TestCase, TestHelper): config['lastgenre'] = {'force': False} res = self.plugin._get_genre(item) - self.assertEqual(res, (item.genre, 'keep')) + self.assertEqual(res, (item.genre, u'keep')) - config['lastgenre'] = {'force': True, 'source': 'track'} + config['lastgenre'] = {'force': True, 'source': u'track'} res = self.plugin._get_genre(item) - self.assertEqual(res, (MOCK_GENRES['track'], 'track')) + self.assertEqual(res, (MOCK_GENRES['track'], u'track')) - config['lastgenre'] = {'source': 'album'} + config['lastgenre'] = {'source': u'album'} res = self.plugin._get_genre(item) - self.assertEqual(res, (MOCK_GENRES['album'], 'album')) + self.assertEqual(res, (MOCK_GENRES['album'], u'album')) - config['lastgenre'] = {'source': 'artist'} + config['lastgenre'] = {'source': u'artist'} res = self.plugin._get_genre(item) - self.assertEqual(res, (MOCK_GENRES['artist'], 'artist')) + self.assertEqual(res, (MOCK_GENRES['artist'], u'artist')) MOCK_GENRES['artist'] = None res = self.plugin._get_genre(item) - self.assertEqual(res, (item.genre, 'original')) + self.assertEqual(res, (item.genre, u'original')) - config['lastgenre'] = {'fallback': 'rap'} + config['lastgenre'] = {'fallback': u'rap'} item.genre = None res = self.plugin._get_genre(item) self.assertEqual(res, (config['lastgenre']['fallback'].get(), - 'fallback')) + u'fallback')) def suite(): diff --git a/test/test_library.py b/test/test_library.py index 5fdb1f2ec..d57566f5f 100644 --- a/test/test_library.py +++ b/test/test_library.py @@ -15,8 +15,7 @@ """Tests for non-query database functions of Item. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import os import os.path @@ -47,12 +46,12 @@ np = util.normpath class LoadTest(_common.LibTestCase): def test_load_restores_data_from_db(self): original_title = self.i.title - self.i.title = 'something' + self.i.title = u'something' self.i.load() self.assertEqual(original_title, self.i.title) def test_load_clears_dirty_flags(self): - self.i.artist = 'something' + self.i.artist = u'something' self.assertTrue('artist' in self.i._dirty) self.i.load() self.assertTrue('artist' not in self.i._dirty) @@ -69,7 +68,7 @@ class StoreTest(_common.LibTestCase): def test_store_only_writes_dirty_fields(self): original_genre = self.i.genre - self.i._values_fixed['genre'] = 'beatboxing' # change w/o dirtying + self.i._values_fixed['genre'] = u'beatboxing' # change w/o dirtying self.i.store() new_genre = self.lib._connection().execute( 'select genre from items where ' @@ -77,7 +76,7 @@ class StoreTest(_common.LibTestCase): self.assertEqual(new_genre, original_genre) def test_store_clears_dirty_flags(self): - self.i.composer = 'tvp' + self.i.composer = u'tvp' self.i.store() self.assertTrue('composer' not in self.i._dirty) @@ -131,7 +130,7 @@ class GetSetTest(_common.TestCase): self.assertTrue('title' not in self.i._dirty) def test_invalid_field_raises_attributeerror(self): - self.assertRaises(AttributeError, getattr, self.i, 'xyzzy') + self.assertRaises(AttributeError, getattr, self.i, u'xyzzy') class DestinationTest(_common.TestCase): @@ -150,17 +149,17 @@ class DestinationTest(_common.TestCase): def test_directory_works_with_trailing_slash(self): self.lib.directory = 'one/' - self.lib.path_formats = [('default', 'two')] + self.lib.path_formats = [(u'default', u'two')] self.assertEqual(self.i.destination(), np('one/two')) def test_directory_works_without_trailing_slash(self): self.lib.directory = 'one' - self.lib.path_formats = [('default', 'two')] + self.lib.path_formats = [(u'default', u'two')] self.assertEqual(self.i.destination(), np('one/two')) def test_destination_substitues_metadata_values(self): self.lib.directory = 'base' - self.lib.path_formats = [('default', '$album/$artist $title')] + self.lib.path_formats = [(u'default', u'$album/$artist $title')] self.i.title = 'three' self.i.artist = 'two' self.i.album = 'one' @@ -169,22 +168,22 @@ class DestinationTest(_common.TestCase): def test_destination_preserves_extension(self): self.lib.directory = 'base' - self.lib.path_formats = [('default', '$title')] + self.lib.path_formats = [(u'default', u'$title')] self.i.path = 'hey.audioformat' self.assertEqual(self.i.destination(), np('base/the title.audioformat')) def test_lower_case_extension(self): self.lib.directory = 'base' - self.lib.path_formats = [('default', '$title')] + self.lib.path_formats = [(u'default', u'$title')] self.i.path = 'hey.MP3' self.assertEqual(self.i.destination(), np('base/the title.mp3')) def test_destination_pads_some_indices(self): self.lib.directory = 'base' - self.lib.path_formats = [('default', - '$track $tracktotal $disc $disctotal $bpm')] + self.lib.path_formats = [(u'default', + u'$track $tracktotal $disc $disctotal $bpm')] self.i.track = 1 self.i.tracktotal = 2 self.i.disc = 3 @@ -195,7 +194,7 @@ class DestinationTest(_common.TestCase): def test_destination_pads_date_values(self): self.lib.directory = 'base' - self.lib.path_formats = [('default', '$year-$month-$day')] + self.lib.path_formats = [(u'default', u'$year-$month-$day')] self.i.year = 1 self.i.month = 2 self.i.day = 3 @@ -222,13 +221,13 @@ class DestinationTest(_common.TestCase): self.assertTrue(os.path.join('one', 'two') in dest) def test_destination_long_names_truncated(self): - self.i.title = 'X' * 300 - self.i.artist = 'Y' * 300 + self.i.title = u'X' * 300 + self.i.artist = u'Y' * 300 for c in self.i.destination().split(os.path.sep): self.assertTrue(len(c) <= 255) def test_destination_long_names_keep_extension(self): - self.i.title = 'X' * 300 + self.i.title = u'X' * 300 self.i.path = 'something.extn' dest = self.i.destination() self.assertEqual(dest[-5:], '.extn') @@ -243,7 +242,7 @@ class DestinationTest(_common.TestCase): self.assertFalse('two / three' in p) def test_path_with_format(self): - self.lib.path_formats = [('default', '$artist/$album ($format)')] + self.lib.path_formats = [(u'default', u'$artist/$album ($format)')] p = self.i.destination() self.assert_('(FLAC)' in p) @@ -251,7 +250,7 @@ class DestinationTest(_common.TestCase): i1, i2 = item(), item() self.lib.add_album([i1, i2]) i1.year, i2.year = 2009, 2010 - self.lib.path_formats = [('default', '$album ($year)/$track $title')] + self.lib.path_formats = [(u'default', u'$album ($year)/$track $title')] dest1, dest2 = i1.destination(), i2.destination() self.assertEqual(os.path.dirname(dest1), os.path.dirname(dest2)) @@ -259,17 +258,17 @@ class DestinationTest(_common.TestCase): self.i.comp = False self.lib.add_album([self.i]) self.lib.directory = 'one' - self.lib.path_formats = [('default', 'two'), - ('comp:true', 'three')] + self.lib.path_formats = [(u'default', u'two'), + (u'comp:true', u'three')] self.assertEqual(self.i.destination(), np('one/two')) def test_singleton_path(self): i = item(self.lib) self.lib.directory = 'one' self.lib.path_formats = [ - ('default', 'two'), - ('singleton:true', 'four'), - ('comp:true', 'three'), + (u'default', u'two'), + (u'singleton:true', u'four'), + (u'comp:true', u'three'), ] self.assertEqual(i.destination(), np('one/four')) @@ -278,9 +277,9 @@ class DestinationTest(_common.TestCase): i.comp = True self.lib.directory = 'one' self.lib.path_formats = [ - ('default', 'two'), - ('comp:true', 'three'), - ('singleton:true', 'four'), + (u'default', u'two'), + (u'comp:true', u'three'), + (u'singleton:true', u'four'), ] self.assertEqual(i.destination(), np('one/three')) @@ -289,32 +288,32 @@ class DestinationTest(_common.TestCase): self.lib.add_album([self.i]) self.lib.directory = 'one' self.lib.path_formats = [ - ('default', 'two'), - ('comp:true', 'three'), + (u'default', u'two'), + (u'comp:true', u'three'), ] self.assertEqual(self.i.destination(), np('one/three')) def test_albumtype_query_path(self): self.i.comp = True self.lib.add_album([self.i]) - self.i.albumtype = 'sometype' + self.i.albumtype = u'sometype' self.lib.directory = 'one' self.lib.path_formats = [ - ('default', 'two'), - ('albumtype:sometype', 'four'), - ('comp:true', 'three'), + (u'default', u'two'), + (u'albumtype:sometype', u'four'), + (u'comp:true', u'three'), ] self.assertEqual(self.i.destination(), np('one/four')) def test_albumtype_path_fallback_to_comp(self): self.i.comp = True self.lib.add_album([self.i]) - self.i.albumtype = 'sometype' + self.i.albumtype = u'sometype' self.lib.directory = 'one' self.lib.path_formats = [ - ('default', 'two'), - ('albumtype:anothertype', 'four'), - ('comp:true', 'three'), + (u'default', u'two'), + (u'albumtype:anothertype', u'four'), + (u'comp:true', u'three'), ] self.assertEqual(self.i.destination(), np('one/three')) @@ -356,42 +355,42 @@ class DestinationTest(_common.TestCase): self.assertEqual(val, u'') def test_artist_falls_back_to_albumartist(self): - self.i.artist = '' - self.i.albumartist = 'something' - self.lib.path_formats = [('default', '$artist')] + self.i.artist = u'' + self.i.albumartist = u'something' + self.lib.path_formats = [(u'default', u'$artist')] p = self.i.destination() - self.assertEqual(p.rsplit(os.path.sep, 1)[1], 'something') + self.assertEqual(p.rsplit(os.path.sep, 1)[1], u'something') def test_albumartist_falls_back_to_artist(self): - self.i.artist = 'trackartist' - self.i.albumartist = '' - self.lib.path_formats = [('default', '$albumartist')] + self.i.artist = u'trackartist' + self.i.albumartist = u'' + self.lib.path_formats = [(u'default', u'$albumartist')] p = self.i.destination() - self.assertEqual(p.rsplit(os.path.sep, 1)[1], 'trackartist') + self.assertEqual(p.rsplit(os.path.sep, 1)[1], u'trackartist') def test_artist_overrides_albumartist(self): - self.i.artist = 'theartist' - self.i.albumartist = 'something' - self.lib.path_formats = [('default', '$artist')] + self.i.artist = u'theartist' + self.i.albumartist = u'something' + self.lib.path_formats = [(u'default', u'$artist')] p = self.i.destination() - self.assertEqual(p.rsplit(os.path.sep, 1)[1], 'theartist') + self.assertEqual(p.rsplit(os.path.sep, 1)[1], u'theartist') def test_albumartist_overrides_artist(self): - self.i.artist = 'theartist' - self.i.albumartist = 'something' - self.lib.path_formats = [('default', '$albumartist')] + self.i.artist = u'theartist' + self.i.albumartist = u'something' + self.lib.path_formats = [(u'default', u'$albumartist')] p = self.i.destination() - self.assertEqual(p.rsplit(os.path.sep, 1)[1], 'something') + self.assertEqual(p.rsplit(os.path.sep, 1)[1], u'something') def test_unicode_normalized_nfd_on_mac(self): instr = unicodedata.normalize('NFC', u'caf\xe9') - self.lib.path_formats = [('default', instr)] + self.lib.path_formats = [(u'default', instr)] dest = self.i.destination(platform='darwin', fragment=True) self.assertEqual(dest, unicodedata.normalize('NFD', instr)) def test_unicode_normalized_nfc_on_linux(self): instr = unicodedata.normalize('NFD', u'caf\xe9') - self.lib.path_formats = [('default', instr)] + self.lib.path_formats = [(u'default', instr)] dest = self.i.destination(platform='linux2', fragment=True) self.assertEqual(dest, unicodedata.normalize('NFC', instr)) @@ -400,7 +399,7 @@ class DestinationTest(_common.TestCase): sys.getfilesystemencoding = lambda: 'mbcs' try: self.i.title = u'h\u0259d' - self.lib.path_formats = [('default', '$title')] + self.lib.path_formats = [(u'default', u'$title')] p = self.i.destination() self.assertFalse(b'?' in p) # We use UTF-8 to encode Windows paths now. @@ -409,7 +408,7 @@ class DestinationTest(_common.TestCase): sys.getfilesystemencoding = oldfunc def test_unicode_extension_in_fragment(self): - self.lib.path_formats = [('default', u'foo')] + self.lib.path_formats = [(u'default', u'foo')] self.i.path = util.bytestring_path(u'bar.caf\xe9') dest = self.i.destination(platform='linux2', fragment=True) self.assertEqual(dest, u'foo.caf\xe9') @@ -418,16 +417,16 @@ class DestinationTest(_common.TestCase): config['asciify_paths'] = True self.lib.replacements = [(re.compile(u'"'), u'q')] self.lib.directory = 'lib' - self.lib.path_formats = [('default', '$title')] + self.lib.path_formats = [(u'default', u'$title')] self.i.title = u'\u201c\u00f6\u2014\u00cf\u201d' self.assertEqual(self.i.destination(), np('lib/qo--Iq')) def test_destination_with_replacements(self): self.lib.directory = 'base' self.lib.replacements = [(re.compile(r'a'), u'e')] - self.lib.path_formats = [('default', '$album/$title')] - self.i.title = 'foo' - self.i.album = 'bar' + self.lib.path_formats = [(u'default', u'$album/$title')] + self.i.title = u'foo' + self.i.album = u'bar' self.assertEqual(self.i.destination(), np('base/ber/foo')) @@ -435,11 +434,11 @@ class DestinationTest(_common.TestCase): def test_destination_with_empty_component(self): self.lib.directory = 'base' self.lib.replacements = [(re.compile(r'^$'), u'_')] - self.lib.path_formats = [('default', '$album/$artist/$title')] - self.i.title = 'three' - self.i.artist = '' - self.i.albumartist = '' - self.i.album = 'one' + self.lib.path_formats = [(u'default', u'$album/$artist/$title')] + self.i.title = u'three' + self.i.artist = u'' + self.i.albumartist = u'' + self.i.album = u'one' self.assertEqual(self.i.destination(), np('base/one/_/three')) @@ -447,9 +446,9 @@ class DestinationTest(_common.TestCase): def test_destination_with_empty_final_component(self): self.lib.directory = 'base' self.lib.replacements = [(re.compile(r'^$'), u'_')] - self.lib.path_formats = [('default', '$album/$title')] - self.i.title = '' - self.i.album = 'one' + self.lib.path_formats = [(u'default', u'$album/$title')] + self.i.title = u'' + self.i.album = u'one' self.i.path = 'foo.mp3' self.assertEqual(self.i.destination(), np('base/one/_.mp3')) @@ -463,11 +462,11 @@ class DestinationTest(_common.TestCase): # Construct an item whose untruncated path ends with a Y but whose # truncated version ends with an X. - self.i.title = 'X' * 300 + 'Y' + self.i.title = u'X' * 300 + u'Y' # The final path should reflect the replacement. dest = self.i.destination() - self.assertEqual(dest[-2:], 'XZ') + self.assertEqual(dest[-2:], u'XZ') def test_legalize_path_one_for_many_replacement(self): # Use a replacement that should always replace the last X in any @@ -478,18 +477,18 @@ class DestinationTest(_common.TestCase): # Construct an item whose untruncated path ends with a Y but whose # truncated version ends with an X. - self.i.title = 'X' * 300 + 'Y' + self.i.title = u'X' * 300 + u'Y' # The final path should ignore the user replacement and create a path # of the correct length, containing Xs. dest = self.i.destination() - self.assertEqual(dest[-2:], 'XX') + self.assertEqual(dest[-2:], u'XX') class ItemFormattedMappingTest(_common.LibTestCase): def test_formatted_item_value(self): formatted = self.i.formatted() - self.assertEqual(formatted['artist'], 'the artist') + self.assertEqual(formatted['artist'], u'the artist') def test_get_unset_field(self): formatted = self.i.formatted() @@ -502,53 +501,53 @@ class ItemFormattedMappingTest(_common.LibTestCase): def test_get_method_with_specified_default(self): formatted = self.i.formatted() - self.assertEqual(formatted.get('other_field', 'default'), 'default') + self.assertEqual(formatted.get('other_field', u'default'), u'default') def test_item_precedence(self): album = self.lib.add_album([self.i]) - album['artist'] = 'foo' + album['artist'] = u'foo' album.store() - self.assertNotEqual('foo', self.i.formatted().get('artist')) + self.assertNotEqual(u'foo', self.i.formatted().get('artist')) def test_album_flex_field(self): album = self.lib.add_album([self.i]) - album['flex'] = 'foo' + album['flex'] = u'foo' album.store() - self.assertEqual('foo', self.i.formatted().get('flex')) + self.assertEqual(u'foo', self.i.formatted().get('flex')) def test_album_field_overrides_item_field_for_path(self): # Make the album inconsistent with the item. album = self.lib.add_album([self.i]) - album.album = 'foo' + album.album = u'foo' album.store() - self.i.album = 'bar' + self.i.album = u'bar' self.i.store() # Ensure the album takes precedence. formatted = self.i.formatted(for_path=True) - self.assertEqual(formatted['album'], 'foo') + self.assertEqual(formatted['album'], u'foo') def test_artist_falls_back_to_albumartist(self): - self.i.artist = '' + self.i.artist = u'' formatted = self.i.formatted() - self.assertEqual(formatted['artist'], 'the album artist') + self.assertEqual(formatted['artist'], u'the album artist') def test_albumartist_falls_back_to_artist(self): - self.i.albumartist = '' + self.i.albumartist = u'' formatted = self.i.formatted() - self.assertEqual(formatted['albumartist'], 'the artist') + self.assertEqual(formatted['albumartist'], u'the artist') def test_both_artist_and_albumartist_empty(self): - self.i.artist = '' - self.i.albumartist = '' + self.i.artist = u'' + self.i.albumartist = u'' formatted = self.i.formatted() - self.assertEqual(formatted['albumartist'], '') + self.assertEqual(formatted['albumartist'], u'') class PathFormattingMixin(object): """Utilities for testing path formatting.""" def _setf(self, fmt): - self.lib.path_formats.insert(0, ('default', fmt)) + self.lib.path_formats.insert(0, (u'default', fmt)) def _assert_dest(self, dest, i=None): if i is None: @@ -563,7 +562,7 @@ class DestinationFunctionTest(_common.TestCase, PathFormattingMixin): super(DestinationFunctionTest, self).setUp() self.lib = beets.library.Library(':memory:') self.lib.directory = '/base' - self.lib.path_formats = [('default', u'path')] + self.lib.path_formats = [(u'default', u'path')] self.i = item(self.lib) def tearDown(self): @@ -624,7 +623,7 @@ class DisambiguationTest(_common.TestCase, PathFormattingMixin): super(DisambiguationTest, self).setUp() self.lib = beets.library.Library(':memory:') self.lib.directory = '/base' - self.lib.path_formats = [('default', u'path')] + self.lib.path_formats = [(u'default', u'path')] self.i1 = item() self.i1.year = 2001 @@ -645,14 +644,14 @@ class DisambiguationTest(_common.TestCase, PathFormattingMixin): def test_unique_with_default_arguments_uses_albumtype(self): album2 = self.lib.get_album(self.i1) - album2.albumtype = 'bar' + album2.albumtype = u'bar' album2.store() self._setf(u'foo%aunique{}/$title') self._assert_dest('/base/foo [bar]/the title', self.i1) def test_unique_expands_to_nothing_for_distinct_albums(self): album2 = self.lib.get_album(self.i2) - album2.album = 'different album' + album2.album = u'different album' album2.store() self._assert_dest('/base/foo/the title', self.i1) @@ -673,7 +672,7 @@ class DisambiguationTest(_common.TestCase, PathFormattingMixin): album2 = self.lib.get_album(self.i2) album2.year = 2001 album1 = self.lib.get_album(self.i1) - album1.albumtype = 'foo/bar' + album1.albumtype = u'foo/bar' album2.store() album1.store() self._setf(u'foo%aunique{albumartist album,albumtype}/$title') @@ -698,7 +697,7 @@ class PluginDestinationTest(_common.TestCase): self.lib = beets.library.Library(':memory:') self.lib.directory = '/base' - self.lib.path_formats = [('default', u'$artist $foo')] + self.lib.path_formats = [(u'default', u'$artist $foo')] self.i = item(self.lib) def tearDown(self): @@ -711,25 +710,25 @@ class PluginDestinationTest(_common.TestCase): self.assertEqual(the_dest, '/base/' + dest) def test_undefined_value_not_substituted(self): - self._assert_dest('the artist $foo') + self._assert_dest(u'the artist $foo') def test_plugin_value_not_substituted(self): self._tv_map = { 'foo': 'bar', } - self._assert_dest('the artist bar') + self._assert_dest(u'the artist bar') def test_plugin_value_overrides_attribute(self): self._tv_map = { 'artist': 'bar', } - self._assert_dest('bar $foo') + self._assert_dest(u'bar $foo') def test_plugin_value_sanitized(self): self._tv_map = { 'foo': 'bar/baz', } - self._assert_dest('the artist bar_baz') + self._assert_dest(u'the artist bar_baz') class AlbumInfoTest(_common.TestCase): @@ -766,7 +765,7 @@ class AlbumInfoTest(_common.TestCase): def test_individual_tracks_have_no_albuminfo(self): i2 = item() - i2.album = 'aTotallyDifferentAlbum' + i2.album = u'aTotallyDifferentAlbum' self.lib.add(i2) ai = self.lib.get_album(i2) self.assertEqual(ai, None) @@ -782,29 +781,29 @@ class AlbumInfoTest(_common.TestCase): if i.id == self.i.id: break else: - self.fail("item not found") + self.fail(u"item not found") def test_albuminfo_changes_affect_items(self): ai = self.lib.get_album(self.i) - ai.album = 'myNewAlbum' + ai.album = u'myNewAlbum' ai.store() i = self.lib.items()[0] - self.assertEqual(i.album, 'myNewAlbum') + self.assertEqual(i.album, u'myNewAlbum') def test_albuminfo_change_albumartist_changes_items(self): ai = self.lib.get_album(self.i) - ai.albumartist = 'myNewArtist' + ai.albumartist = u'myNewArtist' ai.store() i = self.lib.items()[0] - self.assertEqual(i.albumartist, 'myNewArtist') - self.assertNotEqual(i.artist, 'myNewArtist') + self.assertEqual(i.albumartist, u'myNewArtist') + self.assertNotEqual(i.artist, u'myNewArtist') def test_albuminfo_change_artist_does_not_change_items(self): ai = self.lib.get_album(self.i) - ai.artist = 'myNewArtist' + ai.artist = u'myNewArtist' ai.store() i = self.lib.items()[0] - self.assertNotEqual(i.artist, 'myNewArtist') + self.assertNotEqual(i.artist, u'myNewArtist') def test_albuminfo_remove_removes_items(self): item_id = self.i.id @@ -821,7 +820,7 @@ class AlbumInfoTest(_common.TestCase): def test_noop_albuminfo_changes_affect_items(self): i = self.lib.items()[0] - i.album = 'foobar' + i.album = u'foobar' i.store() ai = self.lib.get_album(self.i) ai.album = ai.album @@ -882,7 +881,7 @@ class PathStringTest(_common.TestCase): self.assert_(isinstance(i.path, bytes)) def test_special_chars_preserved_in_database(self): - path = 'b\xe1r'.encode('utf8') + path = u'b\xe1r'.encode('utf8') self.i.path = path self.i.store() i = list(self.lib.items())[0] @@ -890,7 +889,7 @@ class PathStringTest(_common.TestCase): def test_special_char_path_added_to_database(self): self.i.remove() - path = 'b\xe1r'.encode('utf8') + path = u'b\xe1r'.encode('utf8') i = item() i.path = path self.lib.add(i) @@ -962,16 +961,16 @@ class MtimeTest(_common.TestCase): self.assertGreaterEqual(self.i.mtime, self._mtime()) def test_mtime_reset_on_db_modify(self): - self.i.title = 'something else' + self.i.title = u'something else' self.assertLess(self.i.mtime, self._mtime()) def test_mtime_up_to_date_after_write(self): - self.i.title = 'something else' + self.i.title = u'something else' self.i.write() self.assertGreaterEqual(self.i.mtime, self._mtime()) def test_mtime_up_to_date_after_read(self): - self.i.title = 'something else' + self.i.title = u'something else' self.i.read() self.assertGreaterEqual(self.i.mtime, self._mtime()) @@ -996,19 +995,19 @@ class TemplateTest(_common.LibTestCase): def test_year_formatted_in_template(self): self.i.year = 123 self.i.store() - self.assertEqual(self.i.evaluate_template('$year'), '0123') + self.assertEqual(self.i.evaluate_template('$year'), u'0123') def test_album_flexattr_appears_in_item_template(self): self.album = self.lib.add_album([self.i]) - self.album.foo = 'baz' + self.album.foo = u'baz' self.album.store() - self.assertEqual(self.i.evaluate_template('$foo'), 'baz') + self.assertEqual(self.i.evaluate_template('$foo'), u'baz') def test_album_and_item_format(self): config['format_album'] = u'foö $foo' album = beets.library.Album() - album.foo = 'bar' - album.tagada = 'togodo' + album.foo = u'bar' + album.tagada = u'togodo' self.assertEqual(u"{0}".format(album), u"foö bar") self.assertEqual(u"{0:$tagada}".format(album), u"togodo") self.assertEqual(unicode(album), u"foö bar") @@ -1016,10 +1015,10 @@ class TemplateTest(_common.LibTestCase): config['format_item'] = 'bar $foo' item = beets.library.Item() - item.foo = 'bar' - item.tagada = 'togodo' - self.assertEqual("{0}".format(item), "bar bar") - self.assertEqual("{0:$tagada}".format(item), "togodo") + item.foo = u'bar' + item.tagada = u'togodo' + self.assertEqual("{0}".format(item), u"bar bar") + self.assertEqual("{0:$tagada}".format(item), u"togodo") class UnicodePathTest(_common.LibTestCase): @@ -1079,7 +1078,7 @@ class WriteTest(unittest.TestCase, TestHelper): # Since `date` is not a MediaField, this should do nothing. item = self.add_item_fixture() clean_year = item.year - item.date = 'foo' + item.date = u'foo' item.write() self.assertEqual(MediaFile(item.path).year, clean_year) @@ -1119,7 +1118,7 @@ class FilesizeTest(unittest.TestCase, TestHelper): class ParseQueryTest(unittest.TestCase): def test_parse_invalid_query_string(self): with self.assertRaises(beets.dbcore.InvalidQueryError) as raised: - beets.library.parse_query_string('foo"', None) + beets.library.parse_query_string(u'foo"', None) self.assertIsInstance(raised.exception, beets.dbcore.query.ParsingError) @@ -1139,9 +1138,9 @@ class LibraryFieldTypesTest(unittest.TestCase): self.assertEqual(time_local, t.format(123456789)) # parse self.assertEqual(123456789.0, t.parse(time_local)) - self.assertEqual(123456789.0, t.parse('123456789.0')) - self.assertEqual(t.null, t.parse('not123456789.0')) - self.assertEqual(t.null, t.parse('1973-11-29')) + self.assertEqual(123456789.0, t.parse(u'123456789.0')) + self.assertEqual(t.null, t.parse(u'not123456789.0')) + self.assertEqual(t.null, t.parse(u'1973-11-29')) def test_pathtype(self): t = beets.library.PathType() @@ -1157,23 +1156,23 @@ class LibraryFieldTypesTest(unittest.TestCase): t = beets.library.MusicalKey() # parse - self.assertEqual('C#m', t.parse('c#m')) - self.assertEqual('Gm', t.parse('g minor')) - self.assertEqual('Not c#m', t.parse('not C#m')) + self.assertEqual(u'C#m', t.parse(u'c#m')) + self.assertEqual(u'Gm', t.parse(u'g minor')) + self.assertEqual(u'Not c#m', t.parse(u'not C#m')) def test_durationtype(self): t = beets.library.DurationType() # format - self.assertEqual('1:01', t.format(61.23)) - self.assertEqual('60:01', t.format(3601.23)) - self.assertEqual('0:00', t.format(None)) + self.assertEqual(u'1:01', t.format(61.23)) + self.assertEqual(u'60:01', t.format(3601.23)) + self.assertEqual(u'0:00', t.format(None)) # parse - self.assertEqual(61.0, t.parse('1:01')) - self.assertEqual(61.23, t.parse('61.23')) - self.assertEqual(3601.0, t.parse('60:01')) - self.assertEqual(t.null, t.parse('1:00:01')) - self.assertEqual(t.null, t.parse('not61.23')) + self.assertEqual(61.0, t.parse(u'1:01')) + self.assertEqual(61.23, t.parse(u'61.23')) + self.assertEqual(3601.0, t.parse(u'60:01')) + self.assertEqual(t.null, t.parse(u'1:00:01')) + self.assertEqual(t.null, t.parse(u'not61.23')) # config format_raw_length beets.config['format_raw_length'] = True self.assertEqual(61.23, t.format(61.23)) diff --git a/test/test_logging.py b/test/test_logging.py index a3fe363b9..4cf6d1ccc 100644 --- a/test/test_logging.py +++ b/test/test_logging.py @@ -1,8 +1,7 @@ # -*- coding: utf-8 -*- """Stupid tests that ensure logging works as expected""" -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import sys import threading @@ -45,9 +44,9 @@ class LoggingTest(TestCase): l.addHandler(handler) l.propagate = False - l.warning("foo {0} {bar}", "oof", bar="baz") + l.warning(u"foo {0} {bar}", "oof", bar=u"baz") handler.flush() - self.assertTrue(stream.getvalue(), "foo oof baz") + self.assertTrue(stream.getvalue(), u"foo oof baz") class LoggingLevelTest(unittest.TestCase, helper.TestHelper): @@ -59,9 +58,9 @@ class LoggingLevelTest(unittest.TestCase, helper.TestHelper): self.register_listener('dummy_event', self.listener) def log_all(self, name): - self._log.debug('debug ' + name) - self._log.info('info ' + name) - self._log.warning('warning ' + name) + self._log.debug(u'debug ' + name) + self._log.info(u'info ' + name) + self._log.warning(u'warning ' + name) def commands(self): cmd = ui.Subcommand('dummy') @@ -92,76 +91,76 @@ class LoggingLevelTest(unittest.TestCase, helper.TestHelper): self.config['verbose'] = 0 with helper.capture_log() as logs: self.run_command('dummy') - self.assertIn('dummy: warning cmd', logs) - self.assertIn('dummy: info cmd', logs) - self.assertNotIn('dummy: debug cmd', logs) + self.assertIn(u'dummy: warning cmd', logs) + self.assertIn(u'dummy: info cmd', logs) + self.assertNotIn(u'dummy: debug cmd', logs) def test_command_level1(self): self.config['verbose'] = 1 with helper.capture_log() as logs: self.run_command('dummy') - self.assertIn('dummy: warning cmd', logs) - self.assertIn('dummy: info cmd', logs) - self.assertIn('dummy: debug cmd', logs) + self.assertIn(u'dummy: warning cmd', logs) + self.assertIn(u'dummy: info cmd', logs) + self.assertIn(u'dummy: debug cmd', logs) def test_command_level2(self): self.config['verbose'] = 2 with helper.capture_log() as logs: self.run_command('dummy') - self.assertIn('dummy: warning cmd', logs) - self.assertIn('dummy: info cmd', logs) - self.assertIn('dummy: debug cmd', logs) + self.assertIn(u'dummy: warning cmd', logs) + self.assertIn(u'dummy: info cmd', logs) + self.assertIn(u'dummy: debug cmd', logs) def test_listener_level0(self): self.config['verbose'] = 0 with helper.capture_log() as logs: plugins.send('dummy_event') - self.assertIn('dummy: warning listener', logs) - self.assertNotIn('dummy: info listener', logs) - self.assertNotIn('dummy: debug listener', logs) + self.assertIn(u'dummy: warning listener', logs) + self.assertNotIn(u'dummy: info listener', logs) + self.assertNotIn(u'dummy: debug listener', logs) def test_listener_level1(self): self.config['verbose'] = 1 with helper.capture_log() as logs: plugins.send('dummy_event') - self.assertIn('dummy: warning listener', logs) - self.assertIn('dummy: info listener', logs) - self.assertNotIn('dummy: debug listener', logs) + self.assertIn(u'dummy: warning listener', logs) + self.assertIn(u'dummy: info listener', logs) + self.assertNotIn(u'dummy: debug listener', logs) def test_listener_level2(self): self.config['verbose'] = 2 with helper.capture_log() as logs: plugins.send('dummy_event') - self.assertIn('dummy: warning listener', logs) - self.assertIn('dummy: info listener', logs) - self.assertIn('dummy: debug listener', logs) + self.assertIn(u'dummy: warning listener', logs) + self.assertIn(u'dummy: info listener', logs) + self.assertIn(u'dummy: debug listener', logs) def test_import_stage_level0(self): self.config['verbose'] = 0 with helper.capture_log() as logs: importer = self.create_importer() importer.run() - self.assertIn('dummy: warning import_stage', logs) - self.assertNotIn('dummy: info import_stage', logs) - self.assertNotIn('dummy: debug import_stage', logs) + self.assertIn(u'dummy: warning import_stage', logs) + self.assertNotIn(u'dummy: info import_stage', logs) + self.assertNotIn(u'dummy: debug import_stage', logs) def test_import_stage_level1(self): self.config['verbose'] = 1 with helper.capture_log() as logs: importer = self.create_importer() importer.run() - self.assertIn('dummy: warning import_stage', logs) - self.assertIn('dummy: info import_stage', logs) - self.assertNotIn('dummy: debug import_stage', logs) + self.assertIn(u'dummy: warning import_stage', logs) + self.assertIn(u'dummy: info import_stage', logs) + self.assertNotIn(u'dummy: debug import_stage', logs) def test_import_stage_level2(self): self.config['verbose'] = 2 with helper.capture_log() as logs: importer = self.create_importer() importer.run() - self.assertIn('dummy: warning import_stage', logs) - self.assertIn('dummy: info import_stage', logs) - self.assertIn('dummy: debug import_stage', logs) + self.assertIn(u'dummy: warning import_stage', logs) + self.assertIn(u'dummy: info import_stage', logs) + self.assertIn(u'dummy: debug import_stage', logs) @_common.slow_test() @@ -182,9 +181,9 @@ class ConcurrentEventsTest(TestCase, helper.TestHelper): self.t1_step = self.t2_step = 0 def log_all(self, name): - self._log.debug('debug ' + name) - self._log.info('info ' + name) - self._log.warning('warning ' + name) + self._log.debug(u'debug ' + name) + self._log.info(u'info ' + name) + self._log.warning(u'warning ' + name) def listener1(self): try: @@ -257,14 +256,14 @@ class ConcurrentEventsTest(TestCase, helper.TestHelper): self.assertFalse(t2.is_alive()) except: - print("Alive threads:", threading.enumerate()) + print(u"Alive threads:", threading.enumerate()) if dp.lock1.locked(): - print("Releasing lock1 after exception in test") + print(u"Releasing lock1 after exception in test") dp.lock1.release() if dp.lock2.locked(): - print("Releasing lock2 after exception in test") + print(u"Releasing lock2 after exception in test") dp.lock2.release() - print("Alive threads:", threading.enumerate()) + print(u"Alive threads:", threading.enumerate()) raise def test_root_logger_levels(self): @@ -283,14 +282,14 @@ class ConcurrentEventsTest(TestCase, helper.TestHelper): importer = self.create_importer() importer.run() for l in logs: - self.assertIn("import", l) - self.assertIn("album", l) + self.assertIn(u"import", l) + self.assertIn(u"album", l) blog.getLogger('beets').set_global_level(blog.DEBUG) with helper.capture_log() as logs: importer = self.create_importer() importer.run() - self.assertIn("Sending event: database_change", logs) + self.assertIn(u"Sending event: database_change", logs) def suite(): diff --git a/test/test_lyrics.py b/test/test_lyrics.py index bd2e69e97..2658232ae 100644 --- a/test/test_lyrics.py +++ b/test/test_lyrics.py @@ -15,8 +15,7 @@ """Tests for the 'lyrics' plugin.""" -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import os from test import _common @@ -385,7 +384,7 @@ class LyricsGooglePluginTest(unittest.TestCase): url = s['url'] + s['path'] url_title = u'foo' - google.is_page_candidate(url, url_title, s['title'], 'Sunn O)))') + google.is_page_candidate(url, url_title, s['title'], u'Sunn O)))') def suite(): diff --git a/test/test_mb.py b/test/test_mb.py index dae1003c9..5333b2b8c 100644 --- a/test/test_mb.py +++ b/test/test_mb.py @@ -15,8 +15,7 @@ """Tests for MusicBrainz API wrapper. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from test import _common from test._common import unittest diff --git a/test/test_mbsubmit.py b/test/test_mbsubmit.py index 808af9d8c..e89ba2748 100644 --- a/test/test_mbsubmit.py +++ b/test/test_mbsubmit.py @@ -13,8 +13,7 @@ # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from test._common import unittest from test.helper import capture_stdout, control_stdin, TestHelper @@ -46,9 +45,9 @@ class MBSubmitPluginTest(TerminalImportSessionSetup, unittest.TestCase, self.importer.run() # Manually build the string for comparing the output. - tracklist = ('Print tracks? ' - '01. Tag Title 1 - Tag Artist (0:01)\n' - '02. Tag Title 2 - Tag Artist (0:01)') + tracklist = (u'Print tracks? ' + u'01. Tag Title 1 - Tag Artist (0:01)\n' + u'02. Tag Title 2 - Tag Artist (0:01)') self.assertIn(tracklist, output.getvalue()) def test_print_tracks_output_as_tracks(self): @@ -61,8 +60,8 @@ class MBSubmitPluginTest(TerminalImportSessionSetup, unittest.TestCase, self.importer.run() # Manually build the string for comparing the output. - tracklist = ('Print tracks? ' - '02. Tag Title 2 - Tag Artist (0:01)') + tracklist = (u'Print tracks? ' + u'02. Tag Title 2 - Tag Artist (0:01)') self.assertIn(tracklist, output.getvalue()) diff --git a/test/test_mbsync.py b/test/test_mbsync.py index 1cfdf96a1..14d349a8f 100644 --- a/test/test_mbsync.py +++ b/test/test_mbsync.py @@ -13,8 +13,7 @@ # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from mock import patch @@ -44,20 +43,20 @@ class MbsyncCliTest(unittest.TestCase, TestHelper): album_for_mbid.return_value = \ generate_album_info('album id', ['track id']) track_for_mbid.return_value = \ - generate_track_info('singleton track id', - {'title': 'singleton info'}) + generate_track_info(u'singleton track id', + {'title': u'singleton info'}) album_item = Item( - album='old title', - mb_albumid='album id', - mb_trackid='track id', + album=u'old title', + mb_albumid=u'album id', + mb_trackid=u'track id', path='' ) album = self.lib.add_album([album_item]) item = Item( - title='old title', - mb_trackid='singleton track id', + title=u'old title', + mb_trackid=u'singleton track id', path='', ) self.lib.add(item) @@ -65,24 +64,24 @@ class MbsyncCliTest(unittest.TestCase, TestHelper): self.run_command('mbsync') item.load() - self.assertEqual(item.title, 'singleton info') + self.assertEqual(item.title, u'singleton info') album_item.load() - self.assertEqual(album_item.title, 'track info') + self.assertEqual(album_item.title, u'track info') album.load() - self.assertEqual(album.album, 'album info') + self.assertEqual(album.album, u'album info') def test_message_when_skipping(self): - config['format_item'] = '$artist - $album - $title' - config['format_album'] = '$albumartist - $album' + config['format_item'] = u'$artist - $album - $title' + config['format_album'] = u'$albumartist - $album' # Test album with no mb_albumid. # The default format for an album include $albumartist so # set that here, too. album_invalid = Item( - albumartist='album info', - album='album info', + albumartist=u'album info', + album=u'album info', path='' ) self.lib.add_album([album_invalid]) @@ -90,14 +89,14 @@ class MbsyncCliTest(unittest.TestCase, TestHelper): # default format with capture_log('beets.mbsync') as logs: self.run_command('mbsync') - e = 'mbsync: Skipping album with no mb_albumid: ' + \ - 'album info - album info' + e = u'mbsync: Skipping album with no mb_albumid: ' + \ + u'album info - album info' self.assertEqual(e, logs[0]) # custom format with capture_log('beets.mbsync') as logs: self.run_command('mbsync', '-f', "'$album'") - e = "mbsync: Skipping album with no mb_albumid: 'album info'" + e = u"mbsync: Skipping album with no mb_albumid: 'album info'" self.assertEqual(e, logs[0]) # restore the config @@ -108,9 +107,9 @@ class MbsyncCliTest(unittest.TestCase, TestHelper): # The default singleton format includes $artist and $album # so we need to stub them here item_invalid = Item( - artist='album info', - album='album info', - title='old title', + artist=u'album info', + album=u'album info', + title=u'old title', path='', ) self.lib.add(item_invalid) @@ -118,14 +117,14 @@ class MbsyncCliTest(unittest.TestCase, TestHelper): # default format with capture_log('beets.mbsync') as logs: self.run_command('mbsync') - e = 'mbsync: Skipping singleton with no mb_trackid: ' + \ - 'album info - album info - old title' + e = u'mbsync: Skipping singleton with no mb_trackid: ' + \ + u'album info - album info - old title' self.assertEqual(e, logs[0]) # custom format with capture_log('beets.mbsync') as logs: self.run_command('mbsync', '-f', "'$title'") - e = "mbsync: Skipping singleton with no mb_trackid: 'old title'" + e = u"mbsync: Skipping singleton with no mb_trackid: 'old title'" self.assertEqual(e, logs[0]) diff --git a/test/test_mediafile.py b/test/test_mediafile.py index ed5680982..71fd796bd 100644 --- a/test/test_mediafile.py +++ b/test/test_mediafile.py @@ -16,8 +16,7 @@ """Automatically-generated blanket testing for the MediaFile metadata layer. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import os import shutil @@ -109,18 +108,18 @@ class ImageStructureTestMixin(ArtTestMixin): image = next(i for i in mediafile.images if i.mime_type == 'image/png') self.assertEqual(image.data, self.png_data) - self.assertExtendedImageAttributes(image, desc='album cover', + self.assertExtendedImageAttributes(image, desc=u'album cover', type=ImageType.front) image = next(i for i in mediafile.images if i.mime_type == 'image/jpeg') self.assertEqual(image.data, self.jpg_data) - self.assertExtendedImageAttributes(image, desc='the artist', + self.assertExtendedImageAttributes(image, desc=u'the artist', type=ImageType.artist) def test_set_image_structure(self): mediafile = self._mediafile_fixture('empty') - image = Image(data=self.png_data, desc='album cover', + image = Image(data=self.png_data, desc=u'album cover', type=ImageType.front) mediafile.images = [image] mediafile.save() @@ -131,14 +130,14 @@ class ImageStructureTestMixin(ArtTestMixin): image = mediafile.images[0] self.assertEqual(image.data, self.png_data) self.assertEqual(image.mime_type, 'image/png') - self.assertExtendedImageAttributes(image, desc='album cover', + self.assertExtendedImageAttributes(image, desc=u'album cover', type=ImageType.front) def test_add_image_structure(self): mediafile = self._mediafile_fixture('image') self.assertEqual(len(mediafile.images), 2) - image = Image(data=self.png_data, desc='the composer', + image = Image(data=self.png_data, desc=u'the composer', type=ImageType.composer) mediafile.images += [image] mediafile.save() @@ -146,10 +145,10 @@ class ImageStructureTestMixin(ArtTestMixin): mediafile = MediaFile(mediafile.path) self.assertEqual(len(mediafile.images), 3) - images = (i for i in mediafile.images if i.desc == 'the composer') + images = (i for i in mediafile.images if i.desc == u'the composer') image = next(images, None) self.assertExtendedImageAttributes( - image, desc='the composer', type=ImageType.composer + image, desc=u'the composer', type=ImageType.composer ) def test_delete_image_structures(self): @@ -166,7 +165,7 @@ class ImageStructureTestMixin(ArtTestMixin): mediafile = self._mediafile_fixture('image') self.assertEqual(len(mediafile.images), 2) cover = CoverArtField.guess_cover_image(mediafile.images) - self.assertEqual(cover.desc, 'album cover') + self.assertEqual(cover.desc, u'album cover') self.assertEqual(mediafile.art, cover.data) def assertExtendedImageAttributes(self, image, **kwargs): @@ -186,7 +185,7 @@ class ExtendedImageStructureTestMixin(ImageStructureTestMixin): mediafile = self._mediafile_fixture('image') self.assertEqual(len(mediafile.images), 2) - image = Image(data=self.tiff_data, desc='the composer', + image = Image(data=self.tiff_data, desc=u'the composer', type=ImageType.composer) mediafile.images += [image] mediafile.save() @@ -198,14 +197,14 @@ class ExtendedImageStructureTestMixin(ImageStructureTestMixin): image = filter(lambda i: i.mime_type == 'image/tiff', mediafile.images)[0] self.assertExtendedImageAttributes( - image, desc='the composer', type=ImageType.composer) + image, desc=u'the composer', type=ImageType.composer) class LazySaveTestMixin(object): """Mediafile should only write changes when tags have changed """ - @unittest.skip('not yet implemented') + @unittest.skip(u'not yet implemented') def test_unmodified(self): mediafile = self._mediafile_fixture('full') mtime = self._set_past_mtime(mediafile.path) @@ -214,7 +213,7 @@ class LazySaveTestMixin(object): mediafile.save() self.assertEqual(os.stat(mediafile.path).st_mtime, mtime) - @unittest.skip('not yet implemented') + @unittest.skip(u'not yet implemented') def test_same_tag_value(self): mediafile = self._mediafile_fixture('full') mtime = self._set_past_mtime(mediafile.path) @@ -233,14 +232,14 @@ class LazySaveTestMixin(object): mediafile.save() self.assertEqual(os.stat(mediafile.path).st_mtime, mtime) - @unittest.skip('not yet implemented') + @unittest.skip(u'not yet implemented') def test_tag_value_change(self): mediafile = self._mediafile_fixture('full') mtime = self._set_past_mtime(mediafile.path) self.assertEqual(os.stat(mediafile.path).st_mtime, mtime) mediafile.title = mediafile.title - mediafile.album = 'another' + mediafile.album = u'another' mediafile.save() self.assertNotEqual(os.stat(mediafile.path).st_mtime, mtime) @@ -249,7 +248,7 @@ class LazySaveTestMixin(object): mtime = self._set_past_mtime(mediafile.path) self.assertEqual(os.stat(mediafile.path).st_mtime, mtime) - mediafile.update({'title': mediafile.title, 'album': 'another'}) + mediafile.update({'title': mediafile.title, 'album': u'another'}) mediafile.save() self.assertNotEqual(os.stat(mediafile.path).st_mtime, mtime) @@ -273,7 +272,7 @@ class GenreListTestMixin(object): mediafile.save() mediafile = MediaFile(mediafile.path) - self.assertItemsEqual(mediafile.genres, ['one', 'two']) + self.assertItemsEqual(mediafile.genres, [u'one', u'two']) def test_write_genre_list_get_first(self): mediafile = self._mediafile_fixture('empty') @@ -281,11 +280,11 @@ class GenreListTestMixin(object): mediafile.save() mediafile = MediaFile(mediafile.path) - self.assertEqual(mediafile.genre, 'one') + self.assertEqual(mediafile.genre, u'one') def test_append_genre_list(self): mediafile = self._mediafile_fixture('full') - self.assertEqual(mediafile.genre, 'the genre') + self.assertEqual(mediafile.genre, u'the genre') mediafile.genres += [u'another'] mediafile.save() @@ -308,11 +307,11 @@ class ExtendedFieldTestMixin(object): plugin.add_media_field('customtag', field_extension) mediafile = self._mediafile_fixture('empty') - mediafile.customtag = 'F#' + mediafile.customtag = u'F#' mediafile.save() mediafile = MediaFile(mediafile.path) - self.assertEqual(mediafile.customtag, 'F#') + self.assertEqual(mediafile.customtag, u'F#') delattr(MediaFile, 'customtag') Item._media_fields.remove('customtag') @@ -323,10 +322,10 @@ class ExtendedFieldTestMixin(object): mediafile = self._mediafile_fixture('empty') self.assertIsNone(mediafile.customtag) - item = Item(path=mediafile.path, customtag='Gb') + item = Item(path=mediafile.path, customtag=u'Gb') item.write() mediafile = MediaFile(mediafile.path) - self.assertEqual(mediafile.customtag, 'Gb') + self.assertEqual(mediafile.customtag, u'Gb') delattr(MediaFile, 'customtag') Item._media_fields.remove('customtag') @@ -336,11 +335,11 @@ class ExtendedFieldTestMixin(object): plugin.add_media_field('customtag', field_extension) mediafile = self._mediafile_fixture('empty') - mediafile.update({'customtag': 'F#'}) + mediafile.update({'customtag': u'F#'}) mediafile.save() item = Item.from_path(mediafile.path) - self.assertEqual(item['customtag'], 'F#') + self.assertEqual(item['customtag'], u'F#') delattr(MediaFile, 'customtag') Item._media_fields.remove('customtag') @@ -348,13 +347,13 @@ class ExtendedFieldTestMixin(object): def test_invalid_descriptor(self): with self.assertRaises(ValueError) as cm: MediaFile.add_field('somekey', True) - self.assertIn('must be an instance of MediaField', + self.assertIn(u'must be an instance of MediaField', unicode(cm.exception)) def test_overwrite_property(self): with self.assertRaises(ValueError) as cm: MediaFile.add_field('artist', MediaField()) - self.assertIn('property "artist" already exists', + self.assertIn(u'property "artist" already exists', unicode(cm.exception)) @@ -667,12 +666,12 @@ class ReadWriteTestBase(ArtTestMixin, GenreListTestMixin, try: value2 = getattr(mediafile, key) except AttributeError: - errors.append('Tag %s does not exist' % key) + errors.append(u'Tag %s does not exist' % key) else: if value2 != value: - errors.append('Tag %s: %r != %r' % (key, value2, value)) + errors.append(u'Tag %s: %r != %r' % (key, value2, value)) if any(errors): - errors = ['Tags did not match'] + errors + errors = [u'Tags did not match'] + errors self.fail('\n '.join(errors)) def _mediafile_fixture(self, name): @@ -788,7 +787,7 @@ class MusepackTest(ReadWriteTestBase, unittest.TestCase): audio_properties = { 'length': 1.0, 'bitrate': 23458, - 'format': 'Musepack', + 'format': u'Musepack', 'samplerate': 44100, 'bitdepth': 0, 'channels': 2, @@ -801,7 +800,7 @@ class WMATest(ReadWriteTestBase, ExtendedImageStructureTestMixin, audio_properties = { 'length': 1.0, 'bitrate': 128000, - 'format': 'Windows Media', + 'format': u'Windows Media', 'samplerate': 44100, 'bitdepth': 0, 'channels': 1, @@ -818,9 +817,9 @@ class WMATest(ReadWriteTestBase, ExtendedImageStructureTestMixin, def test_read_pure_tags(self): mediafile = self._mediafile_fixture('pure') - self.assertEqual(mediafile.comments, 'the comments') - self.assertEqual(mediafile.title, 'the title') - self.assertEqual(mediafile.artist, 'the artist') + self.assertEqual(mediafile.comments, u'the comments') + self.assertEqual(mediafile.title, u'the title') + self.assertEqual(mediafile.artist, u'the artist') class OggTest(ReadWriteTestBase, ExtendedImageStructureTestMixin, @@ -829,7 +828,7 @@ class OggTest(ReadWriteTestBase, ExtendedImageStructureTestMixin, audio_properties = { 'length': 1.0, 'bitrate': 48000, - 'format': 'OGG', + 'format': u'OGG', 'samplerate': 44100, 'bitdepth': 0, 'channels': 1, @@ -873,7 +872,7 @@ class FlacTest(ReadWriteTestBase, PartialTestMixin, audio_properties = { 'length': 1.0, 'bitrate': 175120, - 'format': 'FLAC', + 'format': u'FLAC', 'samplerate': 44100, 'bitdepth': 16, 'channels': 1, @@ -886,7 +885,7 @@ class ApeTest(ReadWriteTestBase, ExtendedImageStructureTestMixin, audio_properties = { 'length': 1.0, 'bitrate': 112040, - 'format': 'APE', + 'format': u'APE', 'samplerate': 44100, 'bitdepth': 16, 'channels': 1, @@ -898,7 +897,7 @@ class WavpackTest(ReadWriteTestBase, unittest.TestCase): audio_properties = { 'length': 1.0, 'bitrate': 108744, - 'format': 'WavPack', + 'format': u'WavPack', 'samplerate': 44100, 'bitdepth': 0, 'channels': 1, @@ -910,7 +909,7 @@ class OpusTest(ReadWriteTestBase, unittest.TestCase): audio_properties = { 'length': 1.0, 'bitrate': 57984, - 'format': 'Opus', + 'format': u'Opus', 'samplerate': 48000, 'bitdepth': 0, 'channels': 1, @@ -922,7 +921,7 @@ class AIFFTest(ReadWriteTestBase, unittest.TestCase): audio_properties = { 'length': 1.0, 'bitrate': 705600, - 'format': 'AIFF', + 'format': u'AIFF', 'samplerate': 44100, 'bitdepth': 0, 'channels': 1, diff --git a/test/test_mediafile_edge.py b/test/test_mediafile_edge.py index da522cd3d..17121565b 100644 --- a/test/test_mediafile_edge.py +++ b/test/test_mediafile_edge.py @@ -15,8 +15,7 @@ """Specific, edge-case tests for the MediaFile metadata layer. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import os import shutil @@ -101,28 +100,28 @@ class EdgeTest(unittest.TestCase): class InvalidValueToleranceTest(unittest.TestCase): def test_safe_cast_string_to_int(self): - self.assertEqual(_sc(int, 'something'), 0) + self.assertEqual(_sc(int, u'something'), 0) def test_safe_cast_int_string_to_int(self): - self.assertEqual(_sc(int, '20'), 20) + self.assertEqual(_sc(int, u'20'), 20) def test_safe_cast_string_to_bool(self): - self.assertEqual(_sc(bool, 'whatever'), False) + self.assertEqual(_sc(bool, u'whatever'), False) def test_safe_cast_intstring_to_bool(self): - self.assertEqual(_sc(bool, '5'), True) + self.assertEqual(_sc(bool, u'5'), True) def test_safe_cast_string_to_float(self): - self.assertAlmostEqual(_sc(float, '1.234'), 1.234) + self.assertAlmostEqual(_sc(float, u'1.234'), 1.234) def test_safe_cast_int_to_float(self): self.assertAlmostEqual(_sc(float, 2), 2.0) def test_safe_cast_string_with_cruft_to_float(self): - self.assertAlmostEqual(_sc(float, '1.234stuff'), 1.234) + self.assertAlmostEqual(_sc(float, u'1.234stuff'), 1.234) def test_safe_cast_negative_string_to_float(self): - self.assertAlmostEqual(_sc(float, '-1.234'), -1.234) + self.assertAlmostEqual(_sc(float, u'-1.234'), -1.234) def test_safe_cast_special_chars_to_unicode(self): us = _sc(unicode, 'caf\xc3\xa9') @@ -130,7 +129,7 @@ class InvalidValueToleranceTest(unittest.TestCase): self.assertTrue(us.startswith(u'caf')) def test_safe_cast_float_with_no_numbers(self): - v = _sc(float, '+') + v = _sc(float, u'+') self.assertEqual(v, 0.0) @@ -177,7 +176,7 @@ class SafetyTest(unittest.TestCase, TestHelper): self._exccheck('nothing.xml', beets.mediafile.UnreadableFileError, "ftyp") - @unittest.skipIf(not hasattr(os, 'symlink'), 'platform lacks symlink') + @unittest.skipIf(not hasattr(os, 'symlink'), u'platform lacks symlink') def test_broken_symlink(self): fn = os.path.join(_common.RSRC, 'brokenlink') os.symlink('does_not_exist', fn) @@ -262,7 +261,7 @@ class TypeTest(unittest.TestCase): self.mf = beets.mediafile.MediaFile(path) def test_year_integer_in_string(self): - self.mf.year = '2009' + self.mf.year = u'2009' self.assertEqual(self.mf.year, 2009) def test_set_replaygain_gain_to_none(self): diff --git a/test/test_mpdstats.py b/test/test_mpdstats.py index f28e29d68..0fa800dfd 100644 --- a/test/test_mpdstats.py +++ b/test/test_mpdstats.py @@ -13,9 +13,7 @@ # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. -from __future__ import (division, absolute_import, print_function, - unicode_literals) - +from __future__ import division, absolute_import, print_function from mock import Mock, patch, call, ANY from test._common import unittest @@ -35,7 +33,7 @@ class MPDStatsTest(unittest.TestCase, TestHelper): self.unload_plugins() def test_update_rating(self): - item = Item(title='title', path='', id=1) + item = Item(title=u'title', path='', id=1) item.add(self.lib) log = Mock() @@ -46,7 +44,7 @@ class MPDStatsTest(unittest.TestCase, TestHelper): def test_get_item(self): ITEM_PATH = '/foo/bar.flac' - item = Item(title='title', path=ITEM_PATH, id=1) + item = Item(title=u'title', path=ITEM_PATH, id=1) item.add(self.lib) log = Mock() @@ -54,13 +52,13 @@ class MPDStatsTest(unittest.TestCase, TestHelper): self.assertEqual(str(mpdstats.get_item(ITEM_PATH)), str(item)) self.assertIsNone(mpdstats.get_item('/some/non-existing/path')) - self.assertIn('item not found:', log.info.call_args[0][0]) + self.assertIn(u'item not found:', log.info.call_args[0][0]) FAKE_UNKNOWN_STATE = 'some-unknown-one' STATUSES = [{'state': FAKE_UNKNOWN_STATE}, - {'state': 'pause'}, - {'state': 'play', 'songid': 1, 'time': '0:1'}, - {'state': 'stop'}] + {'state': u'pause'}, + {'state': u'play', 'songid': 1, 'time': u'0:1'}, + {'state': u'stop'}] EVENTS = [["player"]] * (len(STATUSES) - 1) + [KeyboardInterrupt] ITEM_PATH = '/foo/bar.flac' @@ -68,7 +66,7 @@ class MPDStatsTest(unittest.TestCase, TestHelper): "events.side_effect": EVENTS, "status.side_effect": STATUSES, "playlist.return_value": {1: ITEM_PATH}})) def test_run_MPDStats(self, mpd_mock): - item = Item(title='title', path=self.ITEM_PATH, id=1) + item = Item(title=u'title', path=self.ITEM_PATH, id=1) item.add(self.lib) log = Mock() diff --git a/test/test_permissions.py b/test/test_permissions.py index c1777ed59..6dcf4d01c 100644 --- a/test/test_permissions.py +++ b/test/test_permissions.py @@ -2,8 +2,7 @@ """Tests for the 'permissions' plugin. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import os from mock import patch, Mock @@ -63,7 +62,7 @@ class PermissionsPluginTest(unittest.TestCase, TestHelper): for x in [(True, self.exp_perms[expectSuccess][typ], '!='), (False, self.exp_perms[not expectSuccess][typ], '==')]: self.assertEqual(x[0], check_permissions(path, x[1]), - msg='{} : {} {} {}'.format( + msg=u'{} : {} {} {}'.format( path, oct(os.stat(path).st_mode), x[2], oct(x[1]))) def test_convert_perm_from_string(self): diff --git a/test/test_pipeline.py b/test/test_pipeline.py index 705a7eb73..2f5395fb5 100644 --- a/test/test_pipeline.py +++ b/test/test_pipeline.py @@ -15,8 +15,7 @@ """Test the "pipeline.py" restricted parallel programming library. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from test._common import unittest from beets.util import pipeline diff --git a/test/test_play.py b/test/test_play.py index d0371cf15..a0f3a6e48 100644 --- a/test/test_play.py +++ b/test/test_play.py @@ -15,8 +15,7 @@ """Tests for the play plugin""" -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import os @@ -33,7 +32,7 @@ class PlayPluginTest(unittest.TestCase, TestHelper): def setUp(self): self.setup_beets() self.load_plugins('play') - self.item = self.add_item(album='a nice älbum', title='aNiceTitle') + self.item = self.add_item(album=u'a nice älbum', title=u'aNiceTitle') self.lib.add_album([self.item]) self.open_patcher = patch('beetsplug.play.util.interactive_open') self.open_mock = self.open_patcher.start() @@ -45,7 +44,7 @@ class PlayPluginTest(unittest.TestCase, TestHelper): self.unload_plugins() def do_test(self, args=('title:aNiceTitle',), expected_cmd='echo', - expected_playlist='{}\n'): + expected_playlist=u'{}\n'): self.run_command('play', *args) self.open_mock.assert_called_once_with(ANY, expected_cmd) @@ -57,21 +56,21 @@ class PlayPluginTest(unittest.TestCase, TestHelper): self.do_test() def test_album_option(self): - self.do_test(['-a', 'nice']) + self.do_test([u'-a', u'nice']) def test_args_option(self): - self.do_test(['-A', 'foo', 'title:aNiceTitle'], 'echo foo') + self.do_test([u'-A', u'foo', u'title:aNiceTitle'], u'echo foo') def test_args_option_in_middle(self): self.config['play']['command'] = 'echo $args other' - self.do_test(['-A', 'foo', 'title:aNiceTitle'], 'echo foo other') + self.do_test([u'-A', u'foo', u'title:aNiceTitle'], u'echo foo other') def test_relative_to(self): self.config['play']['command'] = 'echo' self.config['play']['relative_to'] = '/something' - self.do_test(expected_cmd='echo', expected_playlist='..{}\n') + self.do_test(expected_cmd='echo', expected_playlist=u'..{}\n') def test_use_folders(self): self.config['play']['command'] = None @@ -80,19 +79,19 @@ class PlayPluginTest(unittest.TestCase, TestHelper): self.open_mock.assert_called_once_with(ANY, open_anything()) playlist = open(self.open_mock.call_args[0][0][0], 'r') - self.assertEqual('{}\n'.format( + self.assertEqual(u'{}\n'.format( os.path.dirname(self.item.path.decode('utf-8'))), playlist.read().decode('utf-8')) def test_raw(self): self.config['play']['raw'] = True - self.run_command('play', 'nice') + self.run_command(u'play', u'nice') self.open_mock.assert_called_once_with([self.item.path], 'echo') def test_not_found(self): - self.run_command('play', 'not found') + self.run_command(u'play', u'not found') self.open_mock.assert_not_called() @@ -101,24 +100,24 @@ class PlayPluginTest(unittest.TestCase, TestHelper): self.add_item(title='another NiceTitle') with control_stdin("a"): - self.run_command('play', 'nice') + self.run_command(u'play', u'nice') self.open_mock.assert_not_called() def test_warning_threshold_backwards_compat(self): self.config['play']['warning_treshold'] = 1 - self.add_item(title='another NiceTitle') + self.add_item(title=u'another NiceTitle') with control_stdin("a"): - self.run_command('play', 'nice') + self.run_command(u'play', u'nice') self.open_mock.assert_not_called() def test_command_failed(self): - self.open_mock.side_effect = OSError("some reason") + self.open_mock.side_effect = OSError(u"some reason") with self.assertRaises(UserError): - self.run_command('play', 'title:aNiceTitle') + self.run_command(u'play', u'title:aNiceTitle') def suite(): diff --git a/test/test_player.py b/test/test_player.py index 4f2f6653a..7898fab68 100644 --- a/test/test_player.py +++ b/test/test_player.py @@ -15,8 +15,7 @@ """Tests for BPD and music playing. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from test._common import unittest from beetsplug import bpd diff --git a/test/test_plexupdate.py b/test/test_plexupdate.py index 27a24ea30..a6c8741b3 100644 --- a/test/test_plexupdate.py +++ b/test/test_plexupdate.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from test._common import unittest from test.helper import TestHelper diff --git a/test/test_plugins.py b/test/test_plugins.py index eaf2e83ed..ea1756852 100644 --- a/test/test_plugins.py +++ b/test/test_plugins.py @@ -13,8 +13,7 @@ # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import os from mock import patch, Mock, ANY @@ -72,22 +71,22 @@ class ItemTypesTest(unittest.TestCase, TestHelper): self.register_plugin(RatingPlugin) self.config['plugins'] = 'rating' - item = Item(path='apath', artist='aaa') + item = Item(path=u'apath', artist=u'aaa') item.add(self.lib) # Do not match unset values - out = self.run_with_output('ls', 'rating:1..3') - self.assertNotIn('aaa', out) + out = self.run_with_output(u'ls', u'rating:1..3') + self.assertNotIn(u'aaa', out) - self.run_command('modify', 'rating=2', '--yes') + self.run_command(u'modify', u'rating=2', u'--yes') # Match in range - out = self.run_with_output('ls', 'rating:1..3') - self.assertIn('aaa', out) + out = self.run_with_output(u'ls', u'rating:1..3') + self.assertIn(u'aaa', out) # Don't match out of range - out = self.run_with_output('ls', 'rating:3..5') - self.assertNotIn('aaa', out) + out = self.run_with_output(u'ls', u'rating:3..5') + self.assertNotIn(u'aaa', out) class ItemWriteTest(unittest.TestCase, TestHelper): @@ -108,16 +107,16 @@ class ItemWriteTest(unittest.TestCase, TestHelper): def test_change_tags(self): def on_write(item=None, path=None, tags=None): - if tags['artist'] == 'XXX': - tags['artist'] = 'YYY' + if tags['artist'] == u'XXX': + tags['artist'] = u'YYY' self.register_listener('write', on_write) - item = self.add_item_fixture(artist='XXX') + item = self.add_item_fixture(artist=u'XXX') item.write() mediafile = MediaFile(item.path) - self.assertEqual(mediafile.artist, 'YYY') + self.assertEqual(mediafile.artist, u'YYY') def register_listener(self, event, func): self.event_listener_plugin.register_listener(event, func) @@ -193,8 +192,8 @@ class EventsTest(unittest.TestCase, ImportHelper, TestHelper): os.makedirs(self.album_path) metadata = { - 'artist': 'Tag Artist', - 'album': 'Tag Album', + 'artist': u'Tag Artist', + 'album': u'Tag Album', 'albumartist': None, 'mb_trackid': None, 'mb_albumid': None, @@ -203,7 +202,7 @@ class EventsTest(unittest.TestCase, ImportHelper, TestHelper): self.file_paths = [] for i in range(count): metadata['track'] = i + 1 - metadata['title'] = 'Tag Title Album %d' % (i + 1) + metadata['title'] = u'Tag Title Album %d' % (i + 1) dest_path = os.path.join(self.album_path, '%02d - track.mp3' % (i + 1)) self.__copy_file(dest_path, metadata) @@ -220,13 +219,14 @@ class EventsTest(unittest.TestCase, ImportHelper, TestHelper): # Exactly one event should have been imported (for the album). # Sentinels do not get emitted. - self.assertEqual(logs.count('Sending event: import_task_created'), 1) + self.assertEqual(logs.count(u'Sending event: import_task_created'), 1) - logs = [line for line in logs if not line.startswith('Sending event:')] + logs = [line for line in logs if not line.startswith( + u'Sending event:')] self.assertEqual(logs, [ - 'Album: {0}'.format(os.path.join(self.import_dir, 'album')), - ' {0}'.format(self.file_paths[0]), - ' {0}'.format(self.file_paths[1]), + u'Album: {0}'.format(os.path.join(self.import_dir, 'album')), + u' {0}'.format(self.file_paths[0]), + u' {0}'.format(self.file_paths[1]), ]) def test_import_task_created_with_plugin(self): @@ -262,23 +262,27 @@ class EventsTest(unittest.TestCase, ImportHelper, TestHelper): # Exactly one event should have been imported (for the album). # Sentinels do not get emitted. - self.assertEqual(logs.count('Sending event: import_task_created'), 1) + self.assertEqual(logs.count(u'Sending event: import_task_created'), 1) - logs = [line for line in logs if not line.startswith('Sending event:')] + logs = [line for line in logs if not line.startswith( + u'Sending event:')] self.assertEqual(logs, [ - 'Singleton: {0}'.format(self.file_paths[0]), - 'Singleton: {0}'.format(self.file_paths[1]), + u'Singleton: {0}'.format(self.file_paths[0]), + u'Singleton: {0}'.format(self.file_paths[1]), ]) class HelpersTest(unittest.TestCase): def test_sanitize_choices(self): - self.assertEqual(plugins.sanitize_choices(['A', 'Z'], ('A', 'B')), - ['A']) - self.assertEqual(plugins.sanitize_choices(['A', 'A'], ('A')), ['A']) - self.assertEqual(plugins.sanitize_choices(['D', '*', 'A'], - ('A', 'B', 'C', 'D')), ['D', 'B', 'C', 'A']) + self.assertEqual( + plugins.sanitize_choices([u'A', u'Z'], (u'A', u'B')), [u'A']) + self.assertEqual( + plugins.sanitize_choices([u'A', u'A'], (u'A')), [u'A']) + self.assertEqual( + plugins.sanitize_choices([u'D', u'*', u'A'], + (u'A', u'B', u'C', u'D')), + [u'D', u'B', u'C', u'A']) class ListenersTest(unittest.TestCase, TestHelper): @@ -331,8 +335,8 @@ class ListenersTest(unittest.TestCase, TestHelper): d.foo.assert_has_calls([]) d.bar.assert_has_calls([]) - plugins.send('event_foo', var="tagada") - d.foo.assert_called_once_with(var="tagada") + plugins.send('event_foo', var=u"tagada") + d.foo.assert_called_once_with(var=u"tagada") d.bar.assert_has_calls([]) @patch('beets.plugins.find_plugins') @@ -430,14 +434,14 @@ class PromptChoicesTest(TerminalImportSessionSetup, unittest.TestCase, self.return_choices) def return_choices(self, session, task): - return [ui.commands.PromptChoice('f', 'Foo', None), - ui.commands.PromptChoice('r', 'baR', None)] + return [ui.commands.PromptChoice('f', u'Foo', None), + ui.commands.PromptChoice('r', u'baR', None)] self.register_plugin(DummyPlugin) # Default options + extra choices by the plugin ('Foo', 'Bar') opts = (u'Apply', u'More candidates', u'Skip', u'Use as-is', u'as Tracks', u'Group albums', u'Enter search', - u'enter Id', u'aBort') + ('Foo', 'baR') + u'enter Id', u'aBort') + (u'Foo', u'baR') self.importer.add_choice(action.SKIP) self.importer.run() @@ -453,14 +457,14 @@ class PromptChoicesTest(TerminalImportSessionSetup, unittest.TestCase, self.return_choices) def return_choices(self, session, task): - return [ui.commands.PromptChoice('f', 'Foo', None), - ui.commands.PromptChoice('r', 'baR', None)] + return [ui.commands.PromptChoice('f', u'Foo', None), + ui.commands.PromptChoice('r', u'baR', None)] self.register_plugin(DummyPlugin) # Default options + extra choices by the plugin ('Foo', 'Bar') opts = (u'Apply', u'More candidates', u'Skip', u'Use as-is', u'Enter search', - u'enter Id', u'aBort') + ('Foo', 'baR') + u'enter Id', u'aBort') + (u'Foo', u'baR') config['import']['singletons'] = True self.importer.add_choice(action.SKIP) @@ -477,16 +481,16 @@ class PromptChoicesTest(TerminalImportSessionSetup, unittest.TestCase, self.return_choices) def return_choices(self, session, task): - return [ui.commands.PromptChoice('a', 'A foo', None), # dupe - ui.commands.PromptChoice('z', 'baZ', None), # ok - ui.commands.PromptChoice('z', 'Zupe', None), # dupe - ui.commands.PromptChoice('z', 'Zoo', None)] # dupe + return [ui.commands.PromptChoice('a', u'A foo', None), # dupe + ui.commands.PromptChoice('z', u'baZ', None), # ok + ui.commands.PromptChoice('z', u'Zupe', None), # dupe + ui.commands.PromptChoice('z', u'Zoo', None)] # dupe self.register_plugin(DummyPlugin) # Default options + not dupe extra choices by the plugin ('baZ') opts = (u'Apply', u'More candidates', u'Skip', u'Use as-is', u'as Tracks', u'Group albums', u'Enter search', - u'enter Id', u'aBort') + ('baZ',) + u'enter Id', u'aBort') + (u'baZ',) self.importer.add_choice(action.SKIP) self.importer.run() self.mock_input_options.assert_called_once_with(opts, default='a', @@ -501,7 +505,7 @@ class PromptChoicesTest(TerminalImportSessionSetup, unittest.TestCase, self.return_choices) def return_choices(self, session, task): - return [ui.commands.PromptChoice('f', 'Foo', self.foo)] + return [ui.commands.PromptChoice('f', u'Foo', self.foo)] def foo(self, session, task): pass @@ -510,7 +514,7 @@ class PromptChoicesTest(TerminalImportSessionSetup, unittest.TestCase, # Default options + extra choices by the plugin ('Foo', 'Bar') opts = (u'Apply', u'More candidates', u'Skip', u'Use as-is', u'as Tracks', u'Group albums', u'Enter search', - u'enter Id', u'aBort') + ('Foo',) + u'enter Id', u'aBort') + (u'Foo',) # DummyPlugin.foo() should be called once with patch.object(DummyPlugin, 'foo', autospec=True) as mock_foo: @@ -532,7 +536,7 @@ class PromptChoicesTest(TerminalImportSessionSetup, unittest.TestCase, self.return_choices) def return_choices(self, session, task): - return [ui.commands.PromptChoice('f', 'Foo', self.foo)] + return [ui.commands.PromptChoice('f', u'Foo', self.foo)] def foo(self, session, task): return action.SKIP @@ -541,7 +545,7 @@ class PromptChoicesTest(TerminalImportSessionSetup, unittest.TestCase, # Default options + extra choices by the plugin ('Foo', 'Bar') opts = (u'Apply', u'More candidates', u'Skip', u'Use as-is', u'as Tracks', u'Group albums', u'Enter search', - u'enter Id', u'aBort') + ('Foo',) + u'enter Id', u'aBort') + (u'Foo',) # DummyPlugin.foo() should be called once with helper.control_stdin('f\n'): diff --git a/test/test_query.py b/test/test_query.py index bb9572a1b..7dd659313 100644 --- a/test/test_query.py +++ b/test/test_query.py @@ -15,8 +15,7 @@ """Various tests for querying the library database. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from functools import partial from mock import patch @@ -54,19 +53,19 @@ class AnyFieldQueryTest(_common.LibTestCase): self.assertEqual(self.lib.items(q).get().title, 'the title') def test_restriction_completeness(self): - q = dbcore.query.AnyFieldQuery('title', ['title'], + q = dbcore.query.AnyFieldQuery('title', [u'title'], dbcore.query.SubstringQuery) - self.assertEqual(self.lib.items(q).get().title, 'the title') + self.assertEqual(self.lib.items(q).get().title, u'the title') def test_restriction_soundness(self): - q = dbcore.query.AnyFieldQuery('title', ['artist'], + q = dbcore.query.AnyFieldQuery('title', [u'artist'], dbcore.query.SubstringQuery) self.assertEqual(self.lib.items(q).get(), None) def test_eq(self): - q1 = dbcore.query.AnyFieldQuery('foo', ['bar'], + q1 = dbcore.query.AnyFieldQuery('foo', [u'bar'], dbcore.query.SubstringQuery) - q2 = dbcore.query.AnyFieldQuery('foo', ['bar'], + q2 = dbcore.query.AnyFieldQuery('foo', [u'bar'], dbcore.query.SubstringQuery) self.assertEqual(q1, q2) @@ -89,19 +88,19 @@ class DummyDataTestCase(_common.TestCase, AssertsMixin): super(DummyDataTestCase, self).setUp() self.lib = beets.library.Library(':memory:') items = [_common.item() for _ in range(3)] - items[0].title = 'foo bar' - items[0].artist = 'one' - items[0].album = 'baz' + items[0].title = u'foo bar' + items[0].artist = u'one' + items[0].album = u'baz' items[0].year = 2001 items[0].comp = True - items[1].title = 'baz qux' - items[1].artist = 'two' - items[1].album = 'baz' + items[1].title = u'baz qux' + items[1].artist = u'two' + items[1].album = u'baz' items[1].year = 2002 items[1].comp = True - items[2].title = 'beets 4 eva' - items[2].artist = 'three' - items[2].album = 'foo' + items[2].title = u'beets 4 eva' + items[2].artist = u'three' + items[2].album = u'foo' items[2].year = 2003 items[2].comp = False for item in items: @@ -110,15 +109,15 @@ class DummyDataTestCase(_common.TestCase, AssertsMixin): def assert_items_matched_all(self, results): self.assert_items_matched(results, [ - 'foo bar', - 'baz qux', - 'beets 4 eva', + u'foo bar', + u'baz qux', + u'beets 4 eva', ]) class GetTest(DummyDataTestCase): def test_get_empty(self): - q = '' + q = u'' results = self.lib.items(q) self.assert_items_matched_all(results) @@ -128,152 +127,152 @@ class GetTest(DummyDataTestCase): self.assert_items_matched_all(results) def test_get_one_keyed_term(self): - q = 'title:qux' + q = u'title:qux' results = self.lib.items(q) - self.assert_items_matched(results, ['baz qux']) + self.assert_items_matched(results, [u'baz qux']) def test_get_one_keyed_regexp(self): - q = r'artist::t.+r' + q = u'artist::t.+r' results = self.lib.items(q) - self.assert_items_matched(results, ['beets 4 eva']) + self.assert_items_matched(results, [u'beets 4 eva']) def test_get_one_unkeyed_term(self): - q = 'three' + q = u'three' results = self.lib.items(q) - self.assert_items_matched(results, ['beets 4 eva']) + self.assert_items_matched(results, [u'beets 4 eva']) def test_get_one_unkeyed_regexp(self): - q = r':x$' + q = u':x$' results = self.lib.items(q) - self.assert_items_matched(results, ['baz qux']) + self.assert_items_matched(results, [u'baz qux']) def test_get_no_matches(self): - q = 'popebear' + q = u'popebear' results = self.lib.items(q) self.assert_items_matched(results, []) def test_invalid_key(self): - q = 'pope:bear' + q = u'pope:bear' results = self.lib.items(q) # Matches nothing since the flexattr is not present on the # objects. self.assert_items_matched(results, []) def test_term_case_insensitive(self): - q = 'oNE' + q = u'oNE' results = self.lib.items(q) - self.assert_items_matched(results, ['foo bar']) + self.assert_items_matched(results, [u'foo bar']) def test_regexp_case_sensitive(self): - q = r':oNE' + q = u':oNE' results = self.lib.items(q) self.assert_items_matched(results, []) - q = r':one' + q = u':one' results = self.lib.items(q) - self.assert_items_matched(results, ['foo bar']) + self.assert_items_matched(results, [u'foo bar']) def test_term_case_insensitive_with_key(self): - q = 'artist:thrEE' + q = u'artist:thrEE' results = self.lib.items(q) - self.assert_items_matched(results, ['beets 4 eva']) + self.assert_items_matched(results, [u'beets 4 eva']) def test_key_case_insensitive(self): - q = 'ArTiST:three' + q = u'ArTiST:three' results = self.lib.items(q) - self.assert_items_matched(results, ['beets 4 eva']) + self.assert_items_matched(results, [u'beets 4 eva']) def test_unkeyed_term_matches_multiple_columns(self): - q = 'baz' + q = u'baz' results = self.lib.items(q) self.assert_items_matched(results, [ - 'foo bar', - 'baz qux', + u'foo bar', + u'baz qux', ]) def test_unkeyed_regexp_matches_multiple_columns(self): - q = r':z$' + q = u':z$' results = self.lib.items(q) self.assert_items_matched(results, [ - 'foo bar', - 'baz qux', + u'foo bar', + u'baz qux', ]) def test_keyed_term_matches_only_one_column(self): - q = 'title:baz' + q = u'title:baz' results = self.lib.items(q) - self.assert_items_matched(results, ['baz qux']) + self.assert_items_matched(results, [u'baz qux']) def test_keyed_regexp_matches_only_one_column(self): - q = r'title::baz' + q = u'title::baz' results = self.lib.items(q) self.assert_items_matched(results, [ - 'baz qux', + u'baz qux', ]) def test_multiple_terms_narrow_search(self): - q = 'qux baz' + q = u'qux baz' results = self.lib.items(q) self.assert_items_matched(results, [ - 'baz qux', + u'baz qux', ]) def test_multiple_regexps_narrow_search(self): - q = r':baz :qux' + q = u':baz :qux' results = self.lib.items(q) - self.assert_items_matched(results, ['baz qux']) + self.assert_items_matched(results, [u'baz qux']) def test_mixed_terms_regexps_narrow_search(self): - q = r':baz qux' + q = u':baz qux' results = self.lib.items(q) - self.assert_items_matched(results, ['baz qux']) + self.assert_items_matched(results, [u'baz qux']) def test_single_year(self): - q = 'year:2001' + q = u'year:2001' results = self.lib.items(q) - self.assert_items_matched(results, ['foo bar']) + self.assert_items_matched(results, [u'foo bar']) def test_year_range(self): - q = 'year:2000..2002' + q = u'year:2000..2002' results = self.lib.items(q) self.assert_items_matched(results, [ - 'foo bar', - 'baz qux', + u'foo bar', + u'baz qux', ]) def test_singleton_true(self): - q = 'singleton:true' + q = u'singleton:true' results = self.lib.items(q) - self.assert_items_matched(results, ['beets 4 eva']) + self.assert_items_matched(results, [u'beets 4 eva']) def test_singleton_false(self): - q = 'singleton:false' + q = u'singleton:false' results = self.lib.items(q) - self.assert_items_matched(results, ['foo bar', 'baz qux']) + self.assert_items_matched(results, [u'foo bar', u'baz qux']) def test_compilation_true(self): - q = 'comp:true' + q = u'comp:true' results = self.lib.items(q) - self.assert_items_matched(results, ['foo bar', 'baz qux']) + self.assert_items_matched(results, [u'foo bar', u'baz qux']) def test_compilation_false(self): - q = 'comp:false' + q = u'comp:false' results = self.lib.items(q) - self.assert_items_matched(results, ['beets 4 eva']) + self.assert_items_matched(results, [u'beets 4 eva']) def test_unknown_field_name_no_results(self): - q = 'xyzzy:nonsense' + q = u'xyzzy:nonsense' results = self.lib.items(q) titles = [i.title for i in results] self.assertEqual(titles, []) def test_unknown_field_name_no_results_in_album_query(self): - q = 'xyzzy:nonsense' + q = u'xyzzy:nonsense' results = self.lib.albums(q) names = [a.album for a in results] self.assertEqual(names, []) def test_item_field_name_matches_nothing_in_album_query(self): - q = 'format:nonsense' + q = u'format:nonsense' results = self.lib.albums(q) names = [a.album for a in results] self.assertEqual(names, []) @@ -288,24 +287,24 @@ class GetTest(DummyDataTestCase): self.assert_items_matched(results, [u'caf\xe9']) def test_numeric_search_positive(self): - q = dbcore.query.NumericQuery('year', '2001') + q = dbcore.query.NumericQuery('year', u'2001') results = self.lib.items(q) self.assertTrue(results) def test_numeric_search_negative(self): - q = dbcore.query.NumericQuery('year', '1999') + q = dbcore.query.NumericQuery('year', u'1999') results = self.lib.items(q) self.assertFalse(results) def test_invalid_query(self): with self.assertRaises(InvalidQueryArgumentTypeError) as raised: - dbcore.query.NumericQuery('year', '199a') - self.assertIn('not an int', unicode(raised.exception)) + dbcore.query.NumericQuery('year', u'199a') + self.assertIn(u'not an int', unicode(raised.exception)) with self.assertRaises(InvalidQueryArgumentTypeError) as raised: - dbcore.query.RegexpQuery('year', '199(') - self.assertIn('not a regular expression', unicode(raised.exception)) - self.assertIn('unbalanced parenthesis', unicode(raised.exception)) + dbcore.query.RegexpQuery('year', u'199(') + self.assertIn(u'not a regular expression', unicode(raised.exception)) + self.assertIn(u'unbalanced parenthesis', unicode(raised.exception)) self.assertIsInstance(raised.exception, ParsingError) @@ -315,53 +314,53 @@ class MatchTest(_common.TestCase): self.item = _common.item() def test_regex_match_positive(self): - q = dbcore.query.RegexpQuery('album', '^the album$') + q = dbcore.query.RegexpQuery('album', u'^the album$') self.assertTrue(q.match(self.item)) def test_regex_match_negative(self): - q = dbcore.query.RegexpQuery('album', '^album$') + q = dbcore.query.RegexpQuery('album', u'^album$') self.assertFalse(q.match(self.item)) def test_regex_match_non_string_value(self): - q = dbcore.query.RegexpQuery('disc', '^6$') + q = dbcore.query.RegexpQuery('disc', u'^6$') self.assertTrue(q.match(self.item)) def test_substring_match_positive(self): - q = dbcore.query.SubstringQuery('album', 'album') + q = dbcore.query.SubstringQuery('album', u'album') self.assertTrue(q.match(self.item)) def test_substring_match_negative(self): - q = dbcore.query.SubstringQuery('album', 'ablum') + q = dbcore.query.SubstringQuery('album', u'ablum') self.assertFalse(q.match(self.item)) def test_substring_match_non_string_value(self): - q = dbcore.query.SubstringQuery('disc', '6') + q = dbcore.query.SubstringQuery('disc', u'6') self.assertTrue(q.match(self.item)) def test_year_match_positive(self): - q = dbcore.query.NumericQuery('year', '1') + q = dbcore.query.NumericQuery('year', u'1') self.assertTrue(q.match(self.item)) def test_year_match_negative(self): - q = dbcore.query.NumericQuery('year', '10') + q = dbcore.query.NumericQuery('year', u'10') self.assertFalse(q.match(self.item)) def test_bitrate_range_positive(self): - q = dbcore.query.NumericQuery('bitrate', '100000..200000') + q = dbcore.query.NumericQuery('bitrate', u'100000..200000') self.assertTrue(q.match(self.item)) def test_bitrate_range_negative(self): - q = dbcore.query.NumericQuery('bitrate', '200000..300000') + q = dbcore.query.NumericQuery('bitrate', u'200000..300000') self.assertFalse(q.match(self.item)) def test_open_range(self): - dbcore.query.NumericQuery('bitrate', '100000..') + dbcore.query.NumericQuery('bitrate', u'100000..') def test_eq(self): - q1 = dbcore.query.MatchQuery('foo', 'bar') - q2 = dbcore.query.MatchQuery('foo', 'bar') - q3 = dbcore.query.MatchQuery('foo', 'baz') - q4 = dbcore.query.StringFieldQuery('foo', 'bar') + q1 = dbcore.query.MatchQuery('foo', u'bar') + q2 = dbcore.query.MatchQuery('foo', u'bar') + q3 = dbcore.query.MatchQuery('foo', u'baz') + q4 = dbcore.query.StringFieldQuery('foo', u'bar') self.assertEqual(q1, q2) self.assertNotEqual(q1, q3) self.assertNotEqual(q1, q4) @@ -374,8 +373,8 @@ class PathQueryTest(_common.LibTestCase, TestHelper, AssertsMixin): # This is the item we'll try to match. self.i.path = '/a/b/c.mp3' - self.i.title = 'path item' - self.i.album = 'path album' + self.i.title = u'path item' + self.i.album = u'path album' self.i.store() self.lib.add_album([self.i]) @@ -406,31 +405,31 @@ class PathQueryTest(_common.LibTestCase, TestHelper, AssertsMixin): self.patcher_exists.stop() def test_path_exact_match(self): - q = 'path:/a/b/c.mp3' + q = u'path:/a/b/c.mp3' results = self.lib.items(q) - self.assert_items_matched(results, ['path item']) + self.assert_items_matched(results, [u'path item']) results = self.lib.albums(q) self.assert_albums_matched(results, []) def test_parent_directory_no_slash(self): - q = 'path:/a' + q = u'path:/a' results = self.lib.items(q) - self.assert_items_matched(results, ['path item']) + self.assert_items_matched(results, [u'path item']) results = self.lib.albums(q) - self.assert_albums_matched(results, ['path album']) + self.assert_albums_matched(results, [u'path album']) def test_parent_directory_with_slash(self): - q = 'path:/a/' + q = u'path:/a/' results = self.lib.items(q) - self.assert_items_matched(results, ['path item']) + self.assert_items_matched(results, [u'path item']) results = self.lib.albums(q) - self.assert_albums_matched(results, ['path album']) + self.assert_albums_matched(results, [u'path album']) def test_no_match(self): - q = 'path:/xyzzy/' + q = u'path:/xyzzy/' results = self.lib.items(q) self.assert_items_matched(results, []) @@ -438,7 +437,7 @@ class PathQueryTest(_common.LibTestCase, TestHelper, AssertsMixin): self.assert_albums_matched(results, []) def test_fragment_no_match(self): - q = 'path:/b/' + q = u'path:/b/' results = self.lib.items(q) self.assert_items_matched(results, []) @@ -446,20 +445,20 @@ class PathQueryTest(_common.LibTestCase, TestHelper, AssertsMixin): self.assert_albums_matched(results, []) def test_nonnorm_path(self): - q = 'path:/x/../a/b' + q = u'path:/x/../a/b' results = self.lib.items(q) - self.assert_items_matched(results, ['path item']) + self.assert_items_matched(results, [u'path item']) results = self.lib.albums(q) - self.assert_albums_matched(results, ['path album']) + self.assert_albums_matched(results, [u'path album']) def test_slashed_query_matches_path(self): - q = '/a/b' + q = u'/a/b' results = self.lib.items(q) - self.assert_items_matched(results, ['path item']) + self.assert_items_matched(results, [u'path item']) results = self.lib.albums(q) - self.assert_albums_matched(results, ['path album']) + self.assert_albums_matched(results, [u'path album']) @unittest.skip('unfixed (#1865)') def test_path_query_in_or_query(self): @@ -468,7 +467,7 @@ class PathQueryTest(_common.LibTestCase, TestHelper, AssertsMixin): self.assert_items_matched(results, ['path item']) def test_non_slashed_does_not_match_path(self): - q = 'c.mp3' + q = u'c.mp3' results = self.lib.items(q) self.assert_items_matched(results, []) @@ -476,60 +475,60 @@ class PathQueryTest(_common.LibTestCase, TestHelper, AssertsMixin): self.assert_albums_matched(results, []) def test_slashes_in_explicit_field_does_not_match_path(self): - q = 'title:/a/b' + q = u'title:/a/b' results = self.lib.items(q) self.assert_items_matched(results, []) def test_path_item_regex(self): - q = 'path::c\\.mp3$' + q = u'path::c\\.mp3$' results = self.lib.items(q) - self.assert_items_matched(results, ['path item']) + self.assert_items_matched(results, [u'path item']) def test_path_album_regex(self): - q = 'path::b' + q = u'path::b' results = self.lib.albums(q) - self.assert_albums_matched(results, ['path album']) + self.assert_albums_matched(results, [u'path album']) def test_escape_underscore(self): - self.add_album(path='/a/_/title.mp3', title='with underscore', - album='album with underscore') - q = 'path:/a/_' + self.add_album(path='/a/_/title.mp3', title=u'with underscore', + album=u'album with underscore') + q = u'path:/a/_' results = self.lib.items(q) - self.assert_items_matched(results, ['with underscore']) + self.assert_items_matched(results, [u'with underscore']) results = self.lib.albums(q) - self.assert_albums_matched(results, ['album with underscore']) + self.assert_albums_matched(results, [u'album with underscore']) def test_escape_percent(self): - self.add_album(path='/a/%/title.mp3', title='with percent', - album='album with percent') - q = 'path:/a/%' + self.add_album(path='/a/%/title.mp3', title=u'with percent', + album=u'album with percent') + q = u'path:/a/%' results = self.lib.items(q) - self.assert_items_matched(results, ['with percent']) + self.assert_items_matched(results, [u'with percent']) results = self.lib.albums(q) - self.assert_albums_matched(results, ['album with percent']) + self.assert_albums_matched(results, [u'album with percent']) def test_escape_backslash(self): - self.add_album(path=r'/a/\x/title.mp3', title='with backslash', - album='album with backslash') - q = r'path:/a/\\x' + self.add_album(path=r'/a/\x/title.mp3', title=u'with backslash', + album=u'album with backslash') + q = u'path:/a/\\\\x' results = self.lib.items(q) - self.assert_items_matched(results, ['with backslash']) + self.assert_items_matched(results, [u'with backslash']) results = self.lib.albums(q) - self.assert_albums_matched(results, ['album with backslash']) + self.assert_albums_matched(results, [u'album with backslash']) def test_case_sensitivity(self): - self.add_album(path='/A/B/C2.mp3', title='caps path') + self.add_album(path='/A/B/C2.mp3', title=u'caps path') - makeq = partial(beets.library.PathQuery, 'path', '/A/B') + makeq = partial(beets.library.PathQuery, u'path', '/A/B') results = self.lib.items(makeq(case_sensitive=True)) - self.assert_items_matched(results, ['caps path']) + self.assert_items_matched(results, [u'caps path']) results = self.lib.items(makeq(case_sensitive=False)) - self.assert_items_matched(results, ['path item', 'caps path']) + self.assert_items_matched(results, [u'path item', u'caps path']) # Check for correct case sensitivity selection (this check # only works on non-Windows OSes). @@ -613,32 +612,32 @@ class IntQueryTest(unittest.TestCase, TestHelper): def test_exact_value_match(self): item = self.add_item(bpm=120) - matched = self.lib.items('bpm:120').get() + matched = self.lib.items(u'bpm:120').get() self.assertEqual(item.id, matched.id) def test_range_match(self): item = self.add_item(bpm=120) self.add_item(bpm=130) - matched = self.lib.items('bpm:110..125') + matched = self.lib.items(u'bpm:110..125') self.assertEqual(1, len(matched)) self.assertEqual(item.id, matched.get().id) def test_flex_range_match(self): Item._types = {'myint': types.Integer()} item = self.add_item(myint=2) - matched = self.lib.items('myint:2').get() + matched = self.lib.items(u'myint:2').get() self.assertEqual(item.id, matched.id) def test_flex_dont_match_missing(self): Item._types = {'myint': types.Integer()} self.add_item() - matched = self.lib.items('myint:2').get() + matched = self.lib.items(u'myint:2').get() self.assertIsNone(matched) def test_no_substring_match(self): self.add_item(bpm=120) - matched = self.lib.items('bpm:12').get() + matched = self.lib.items(u'bpm:12').get() self.assertIsNone(matched) @@ -654,35 +653,35 @@ class BoolQueryTest(unittest.TestCase, TestHelper): def test_parse_true(self): item_true = self.add_item(comp=True) item_false = self.add_item(comp=False) - matched = self.lib.items('comp:true') + matched = self.lib.items(u'comp:true') self.assertInResult(item_true, matched) self.assertNotInResult(item_false, matched) def test_flex_parse_true(self): item_true = self.add_item(flexbool=True) item_false = self.add_item(flexbool=False) - matched = self.lib.items('flexbool:true') + matched = self.lib.items(u'flexbool:true') self.assertInResult(item_true, matched) self.assertNotInResult(item_false, matched) def test_flex_parse_false(self): item_true = self.add_item(flexbool=True) item_false = self.add_item(flexbool=False) - matched = self.lib.items('flexbool:false') + matched = self.lib.items(u'flexbool:false') self.assertInResult(item_false, matched) self.assertNotInResult(item_true, matched) def test_flex_parse_1(self): item_true = self.add_item(flexbool=True) item_false = self.add_item(flexbool=False) - matched = self.lib.items('flexbool:1') + matched = self.lib.items(u'flexbool:1') self.assertInResult(item_true, matched) self.assertNotInResult(item_false, matched) def test_flex_parse_0(self): item_true = self.add_item(flexbool=True) item_false = self.add_item(flexbool=False) - matched = self.lib.items('flexbool:0') + matched = self.lib.items(u'flexbool:0') self.assertInResult(item_false, matched) self.assertNotInResult(item_true, matched) @@ -690,26 +689,26 @@ class BoolQueryTest(unittest.TestCase, TestHelper): # TODO this should be the other way around item_true = self.add_item(flexbool=True) item_false = self.add_item(flexbool=False) - matched = self.lib.items('flexbool:something') + matched = self.lib.items(u'flexbool:something') self.assertInResult(item_false, matched) self.assertNotInResult(item_true, matched) class DefaultSearchFieldsTest(DummyDataTestCase): def test_albums_matches_album(self): - albums = list(self.lib.albums('baz')) + albums = list(self.lib.albums(u'baz')) self.assertEqual(len(albums), 1) def test_albums_matches_albumartist(self): - albums = list(self.lib.albums(['album artist'])) + albums = list(self.lib.albums([u'album artist'])) self.assertEqual(len(albums), 1) def test_items_matches_title(self): - items = self.lib.items('beets') - self.assert_items_matched(items, ['beets 4 eva']) + items = self.lib.items(u'beets') + self.assert_items_matched(items, [u'beets 4 eva']) def test_items_does_not_match_year(self): - items = self.lib.items('2001') + items = self.lib.items(u'2001') self.assert_items_matched(items, []) @@ -722,18 +721,18 @@ class NoneQueryTest(unittest.TestCase, TestHelper): singleton = self.add_item() album_item = self.add_album().items().get() - matched = self.lib.items(NoneQuery('album_id')) + matched = self.lib.items(NoneQuery(u'album_id')) self.assertInResult(singleton, matched) self.assertNotInResult(album_item, matched) def test_match_after_set_none(self): item = self.add_item(rg_track_gain=0) - matched = self.lib.items(NoneQuery('rg_track_gain')) + matched = self.lib.items(NoneQuery(u'rg_track_gain')) self.assertNotInResult(item, matched) item['rg_track_gain'] = None item.store() - matched = self.lib.items(NoneQuery('rg_track_gain')) + matched = self.lib.items(NoneQuery(u'rg_track_gain')) self.assertInResult(item, matched) @@ -747,57 +746,57 @@ class NotQueryMatchTest(_common.TestCase): self.item = _common.item() def test_regex_match_positive(self): - q = dbcore.query.RegexpQuery('album', '^the album$') + q = dbcore.query.RegexpQuery(u'album', u'^the album$') self.assertTrue(q.match(self.item)) self.assertFalse(dbcore.query.NotQuery(q).match(self.item)) def test_regex_match_negative(self): - q = dbcore.query.RegexpQuery('album', '^album$') + q = dbcore.query.RegexpQuery(u'album', u'^album$') self.assertFalse(q.match(self.item)) self.assertTrue(dbcore.query.NotQuery(q).match(self.item)) def test_regex_match_non_string_value(self): - q = dbcore.query.RegexpQuery('disc', '^6$') + q = dbcore.query.RegexpQuery(u'disc', u'^6$') self.assertTrue(q.match(self.item)) self.assertFalse(dbcore.query.NotQuery(q).match(self.item)) def test_substring_match_positive(self): - q = dbcore.query.SubstringQuery('album', 'album') + q = dbcore.query.SubstringQuery(u'album', u'album') self.assertTrue(q.match(self.item)) self.assertFalse(dbcore.query.NotQuery(q).match(self.item)) def test_substring_match_negative(self): - q = dbcore.query.SubstringQuery('album', 'ablum') + q = dbcore.query.SubstringQuery(u'album', u'ablum') self.assertFalse(q.match(self.item)) self.assertTrue(dbcore.query.NotQuery(q).match(self.item)) def test_substring_match_non_string_value(self): - q = dbcore.query.SubstringQuery('disc', '6') + q = dbcore.query.SubstringQuery(u'disc', u'6') self.assertTrue(q.match(self.item)) self.assertFalse(dbcore.query.NotQuery(q).match(self.item)) def test_year_match_positive(self): - q = dbcore.query.NumericQuery('year', '1') + q = dbcore.query.NumericQuery(u'year', u'1') self.assertTrue(q.match(self.item)) self.assertFalse(dbcore.query.NotQuery(q).match(self.item)) def test_year_match_negative(self): - q = dbcore.query.NumericQuery('year', '10') + q = dbcore.query.NumericQuery(u'year', u'10') self.assertFalse(q.match(self.item)) self.assertTrue(dbcore.query.NotQuery(q).match(self.item)) def test_bitrate_range_positive(self): - q = dbcore.query.NumericQuery('bitrate', '100000..200000') + q = dbcore.query.NumericQuery(u'bitrate', u'100000..200000') self.assertTrue(q.match(self.item)) self.assertFalse(dbcore.query.NotQuery(q).match(self.item)) def test_bitrate_range_negative(self): - q = dbcore.query.NumericQuery('bitrate', '200000..300000') + q = dbcore.query.NumericQuery(u'bitrate', u'200000..300000') self.assertFalse(q.match(self.item)) self.assertTrue(dbcore.query.NotQuery(q).match(self.item)) def test_open_range(self): - q = dbcore.query.NumericQuery('bitrate', '100000..') + q = dbcore.query.NumericQuery(u'bitrate', u'100000..') dbcore.query.NotQuery(q) @@ -833,27 +832,29 @@ class NotQueryTest(DummyDataTestCase): def test_type_and(self): # not(a and b) <-> not(a) or not(b) - q = dbcore.query.AndQuery([dbcore.query.BooleanQuery('comp', True), - dbcore.query.NumericQuery('year', '2002')]) + q = dbcore.query.AndQuery([ + dbcore.query.BooleanQuery(u'comp', True), + dbcore.query.NumericQuery(u'year', u'2002')], + ) not_results = self.lib.items(dbcore.query.NotQuery(q)) - self.assert_items_matched(not_results, ['foo bar', 'beets 4 eva']) + self.assert_items_matched(not_results, [u'foo bar', u'beets 4 eva']) self.assertNegationProperties(q) def test_type_anyfield(self): - q = dbcore.query.AnyFieldQuery('foo', ['title', 'artist', 'album'], + q = dbcore.query.AnyFieldQuery(u'foo', [u'title', u'artist', u'album'], dbcore.query.SubstringQuery) not_results = self.lib.items(dbcore.query.NotQuery(q)) - self.assert_items_matched(not_results, ['baz qux']) + self.assert_items_matched(not_results, [u'baz qux']) self.assertNegationProperties(q) def test_type_boolean(self): - q = dbcore.query.BooleanQuery('comp', True) + q = dbcore.query.BooleanQuery(u'comp', True) not_results = self.lib.items(dbcore.query.NotQuery(q)) - self.assert_items_matched(not_results, ['beets 4 eva']) + self.assert_items_matched(not_results, [u'beets 4 eva']) self.assertNegationProperties(q) def test_type_date(self): - q = dbcore.query.DateQuery('mtime', '0.0') + q = dbcore.query.DateQuery(u'mtime', u'0.0') not_results = self.lib.items(dbcore.query.NotQuery(q)) self.assert_items_matched(not_results, []) self.assertNegationProperties(q) @@ -865,41 +866,41 @@ class NotQueryTest(DummyDataTestCase): self.assertNegationProperties(q) def test_type_match(self): - q = dbcore.query.MatchQuery('year', '2003') + q = dbcore.query.MatchQuery(u'year', u'2003') not_results = self.lib.items(dbcore.query.NotQuery(q)) - self.assert_items_matched(not_results, ['foo bar', 'baz qux']) + self.assert_items_matched(not_results, [u'foo bar', u'baz qux']) self.assertNegationProperties(q) def test_type_none(self): - q = dbcore.query.NoneQuery('rg_track_gain') + q = dbcore.query.NoneQuery(u'rg_track_gain') not_results = self.lib.items(dbcore.query.NotQuery(q)) self.assert_items_matched(not_results, []) self.assertNegationProperties(q) def test_type_numeric(self): - q = dbcore.query.NumericQuery('year', '2001..2002') + q = dbcore.query.NumericQuery(u'year', u'2001..2002') not_results = self.lib.items(dbcore.query.NotQuery(q)) - self.assert_items_matched(not_results, ['beets 4 eva']) + self.assert_items_matched(not_results, [u'beets 4 eva']) self.assertNegationProperties(q) def test_type_or(self): # not(a or b) <-> not(a) and not(b) - q = dbcore.query.OrQuery([dbcore.query.BooleanQuery('comp', True), - dbcore.query.NumericQuery('year', '2002')]) + q = dbcore.query.OrQuery([dbcore.query.BooleanQuery(u'comp', True), + dbcore.query.NumericQuery(u'year', u'2002')]) not_results = self.lib.items(dbcore.query.NotQuery(q)) - self.assert_items_matched(not_results, ['beets 4 eva']) + self.assert_items_matched(not_results, [u'beets 4 eva']) self.assertNegationProperties(q) def test_type_regexp(self): - q = dbcore.query.RegexpQuery('artist', '^t') + q = dbcore.query.RegexpQuery(u'artist', u'^t') not_results = self.lib.items(dbcore.query.NotQuery(q)) - self.assert_items_matched(not_results, ['foo bar']) + self.assert_items_matched(not_results, [u'foo bar']) self.assertNegationProperties(q) def test_type_substring(self): - q = dbcore.query.SubstringQuery('album', 'ba') + q = dbcore.query.SubstringQuery(u'album', u'ba') not_results = self.lib.items(dbcore.query.NotQuery(q)) - self.assert_items_matched(not_results, ['beets 4 eva']) + self.assert_items_matched(not_results, [u'beets 4 eva']) self.assertNegationProperties(q) def test_type_true(self): @@ -910,41 +911,41 @@ class NotQueryTest(DummyDataTestCase): def test_get_prefixes_keyed(self): """Test both negation prefixes on a keyed query.""" - q0 = '-title:qux' - q1 = '^title:qux' + q0 = u'-title:qux' + q1 = u'^title:qux' results0 = self.lib.items(q0) results1 = self.lib.items(q1) - self.assert_items_matched(results0, ['foo bar', 'beets 4 eva']) - self.assert_items_matched(results1, ['foo bar', 'beets 4 eva']) + self.assert_items_matched(results0, [u'foo bar', u'beets 4 eva']) + self.assert_items_matched(results1, [u'foo bar', u'beets 4 eva']) def test_get_prefixes_unkeyed(self): """Test both negation prefixes on an unkeyed query.""" - q0 = '-qux' - q1 = '^qux' + q0 = u'-qux' + q1 = u'^qux' results0 = self.lib.items(q0) results1 = self.lib.items(q1) - self.assert_items_matched(results0, ['foo bar', 'beets 4 eva']) - self.assert_items_matched(results1, ['foo bar', 'beets 4 eva']) + self.assert_items_matched(results0, [u'foo bar', u'beets 4 eva']) + self.assert_items_matched(results1, [u'foo bar', u'beets 4 eva']) def test_get_one_keyed_regexp(self): - q = r'-artist::t.+r' + q = u'-artist::t.+r' results = self.lib.items(q) - self.assert_items_matched(results, ['foo bar', 'baz qux']) + self.assert_items_matched(results, [u'foo bar', u'baz qux']) def test_get_one_unkeyed_regexp(self): - q = r'-:x$' + q = u'-:x$' results = self.lib.items(q) - self.assert_items_matched(results, ['foo bar', 'beets 4 eva']) + self.assert_items_matched(results, [u'foo bar', u'beets 4 eva']) def test_get_multiple_terms(self): - q = 'baz -bar' + q = u'baz -bar' results = self.lib.items(q) - self.assert_items_matched(results, ['baz qux']) + self.assert_items_matched(results, [u'baz qux']) def test_get_mixed_terms(self): - q = 'baz -title:bar' + q = u'baz -title:bar' results = self.lib.items(q) - self.assert_items_matched(results, ['baz qux']) + self.assert_items_matched(results, [u'baz qux']) def test_fast_vs_slow(self): """Test that the results are the same regardless of the `fast` flag @@ -954,13 +955,13 @@ class NotQueryTest(DummyDataTestCase): AttributeError: type object 'NoneQuery' has no attribute 'field' at NoneQuery.match() (due to being @classmethod, and no self?) """ - classes = [(dbcore.query.DateQuery, ['mtime', '0.0']), - (dbcore.query.MatchQuery, ['artist', 'one']), + classes = [(dbcore.query.DateQuery, [u'mtime', u'0.0']), + (dbcore.query.MatchQuery, [u'artist', u'one']), # (dbcore.query.NoneQuery, ['rg_track_gain']), - (dbcore.query.NumericQuery, ['year', '2002']), - (dbcore.query.StringFieldQuery, ['year', '2001']), - (dbcore.query.RegexpQuery, ['album', '^.a']), - (dbcore.query.SubstringQuery, ['title', 'x'])] + (dbcore.query.NumericQuery, [u'year', u'2002']), + (dbcore.query.StringFieldQuery, [u'year', u'2001']), + (dbcore.query.RegexpQuery, [u'album', u'^.a']), + (dbcore.query.SubstringQuery, [u'title', u'x'])] for klass, args in classes: q_fast = dbcore.query.NotQuery(klass(*(args + [True]))) diff --git a/test/test_replaygain.py b/test/test_replaygain.py index 5b20f5f3b..d0ceaf709 100644 --- a/test/test_replaygain.py +++ b/test/test_replaygain.py @@ -14,8 +14,7 @@ # included in all copies or substantial portions of the Software. -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from test._common import unittest from test.helper import TestHelper, has_program @@ -95,7 +94,7 @@ class ReplayGainCliTestBase(TestHelper): # that it could only happen if the decoder plugins are missing. if all(i.rg_track_peak is None and i.rg_track_gain is None for i in self.lib.items()): - self.skipTest('decoder plugins could not be loaded.') + self.skipTest(u'decoder plugins could not be loaded.') for item in self.lib.items(): self.assertIsNotNone(item.rg_track_peak) @@ -107,11 +106,11 @@ class ReplayGainCliTestBase(TestHelper): mediafile.rg_track_gain, item.rg_track_gain, places=2) def test_cli_skips_calculated_tracks(self): - self.run_command('replaygain') + self.run_command(u'replaygain') item = self.lib.items()[0] peak = item.rg_track_peak item.rg_track_gain = 0.0 - self.run_command('replaygain') + self.run_command(u'replaygain') self.assertEqual(item.rg_track_gain, 0.0) self.assertEqual(item.rg_track_peak, peak) @@ -121,7 +120,7 @@ class ReplayGainCliTestBase(TestHelper): self.assertIsNone(mediafile.rg_album_peak) self.assertIsNone(mediafile.rg_album_gain) - self.run_command('replaygain', '-a') + self.run_command(u'replaygain', u'-a') peaks = [] gains = [] @@ -138,7 +137,7 @@ class ReplayGainCliTestBase(TestHelper): self.assertNotEqual(max(peaks), 0.0) -@unittest.skipIf(not GST_AVAILABLE, 'gstreamer cannot be found') +@unittest.skipIf(not GST_AVAILABLE, u'gstreamer cannot be found') class ReplayGainGstCliTest(ReplayGainCliTestBase, unittest.TestCase): backend = u'gstreamer' @@ -155,12 +154,12 @@ class ReplayGainGstCliTest(ReplayGainCliTestBase, unittest.TestCase): super(ReplayGainGstCliTest, self).setUp() -@unittest.skipIf(not GAIN_PROG_AVAILABLE, 'no *gain command found') +@unittest.skipIf(not GAIN_PROG_AVAILABLE, u'no *gain command found') class ReplayGainCmdCliTest(ReplayGainCliTestBase, unittest.TestCase): backend = u'command' -@unittest.skipIf(not LOUDNESS_PROG_AVAILABLE, 'bs1770gain cannot be found') +@unittest.skipIf(not LOUDNESS_PROG_AVAILABLE, u'bs1770gain cannot be found') class ReplayGainLdnsCliTest(ReplayGainCliTestBase, unittest.TestCase): backend = u'bs1770gain' diff --git a/test/test_smartplaylist.py b/test/test_smartplaylist.py index c5ac4fb5b..c30ba24d0 100644 --- a/test/test_smartplaylist.py +++ b/test/test_smartplaylist.py @@ -13,8 +13,7 @@ # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from os import path, remove from tempfile import mkdtemp @@ -46,36 +45,42 @@ class SmartPlaylistTest(unittest.TestCase): self.assertEqual(spl._unmatched_playlists, set()) config['smartplaylist']['playlists'].set([ - {'name': 'foo', - 'query': 'FOO foo'}, - {'name': 'bar', - 'album_query': ['BAR bar1', 'BAR bar2']}, - {'name': 'baz', - 'query': 'BAZ baz', - 'album_query': 'BAZ baz'} + {'name': u'foo', + 'query': u'FOO foo'}, + {'name': u'bar', + 'album_query': [u'BAR bar1', u'BAR bar2']}, + {'name': u'baz', + 'query': u'BAZ baz', + 'album_query': u'BAZ baz'} ]) spl.build_queries() self.assertEqual(spl._matched_playlists, set()) - foo_foo = parse_query_string('FOO foo', Item) - baz_baz = parse_query_string('BAZ baz', Item) - baz_baz2 = parse_query_string('BAZ baz', Album) - bar_bar = OrQuery((parse_query_string('BAR bar1', Album)[0], - parse_query_string('BAR bar2', Album)[0])) + foo_foo = parse_query_string(u'FOO foo', Item) + baz_baz = parse_query_string(u'BAZ baz', Item) + baz_baz2 = parse_query_string(u'BAZ baz', Album) + bar_bar = OrQuery((parse_query_string(u'BAR bar1', Album)[0], + parse_query_string(u'BAR bar2', Album)[0])) self.assertEqual(spl._unmatched_playlists, set([ - ('foo', foo_foo, (None, None)), - ('baz', baz_baz, baz_baz2), - ('bar', (None, None), (bar_bar, None)), + (u'foo', foo_foo, (None, None)), + (u'baz', baz_baz, baz_baz2), + (u'bar', (None, None), (bar_bar, None)), ])) def test_build_queries_with_sorts(self): spl = SmartPlaylistPlugin() config['smartplaylist']['playlists'].set([ - {'name': 'no_sort', 'query': 'foo'}, - {'name': 'one_sort', 'query': 'foo year+'}, - {'name': 'only_empty_sorts', 'query': ['foo', 'bar']}, - {'name': 'one_non_empty_sort', 'query': ['foo year+', 'bar']}, - {'name': 'multiple_sorts', 'query': ['foo year+', 'bar genre-']}, - {'name': 'mixed', 'query': ['foo year+', 'bar', 'baz genre+ id-']} + {'name': u'no_sort', + 'query': u'foo'}, + {'name': u'one_sort', + 'query': u'foo year+'}, + {'name': u'only_empty_sorts', + 'query': [u'foo', u'bar']}, + {'name': u'one_non_empty_sort', + 'query': [u'foo year+', u'bar']}, + {'name': u'multiple_sorts', + 'query': [u'foo year+', u'bar genre-']}, + {'name': u'mixed', + 'query': [u'foo year+', u'bar', u'baz genre+ id-']} ]) spl.build_queries() @@ -85,13 +90,13 @@ class SmartPlaylistTest(unittest.TestCase): asseq = self.assertEqual # less cluttered code S = FixedFieldSort # short cut since we're only dealing with this asseq(sorts["no_sort"], NullSort()) - asseq(sorts["one_sort"], S('year')) + asseq(sorts["one_sort"], S(u'year')) asseq(sorts["only_empty_sorts"], None) - asseq(sorts["one_non_empty_sort"], S('year')) + asseq(sorts["one_non_empty_sort"], S(u'year')) asseq(sorts["multiple_sorts"], - MultipleSort([S('year'), S('genre', False)])) + MultipleSort([S('year'), S(u'genre', False)])) asseq(sorts["mixed"], - MultipleSort([S('year'), S('genre'), S('id', False)])) + MultipleSort([S('year'), S(u'genre'), S(u'id', False)])) def test_matches(self): spl = SmartPlaylistPlugin() @@ -119,25 +124,25 @@ class SmartPlaylistTest(unittest.TestCase): spl = SmartPlaylistPlugin() nones = None, None - pl1 = '1', ('q1', None), nones - pl2 = '2', ('q2', None), nones - pl3 = '3', ('q3', None), nones + pl1 = '1', (u'q1', None), nones + pl2 = '2', (u'q2', None), nones + pl3 = '3', (u'q3', None), nones spl._unmatched_playlists = set([pl1, pl2, pl3]) spl._matched_playlists = set() spl.matches = Mock(return_value=False) - spl.db_change(None, "nothing") + spl.db_change(None, u"nothing") self.assertEqual(spl._unmatched_playlists, set([pl1, pl2, pl3])) self.assertEqual(spl._matched_playlists, set()) - spl.matches.side_effect = lambda _, q, __: q == 'q3' - spl.db_change(None, "matches 3") + spl.matches.side_effect = lambda _, q, __: q == u'q3' + spl.db_change(None, u"matches 3") self.assertEqual(spl._unmatched_playlists, set([pl1, pl2])) self.assertEqual(spl._matched_playlists, set([pl3])) - spl.matches.side_effect = lambda _, q, __: q == 'q1' - spl.db_change(None, "matches 3") + spl.matches.side_effect = lambda _, q, __: q == u'q1' + spl.db_change(None, u"matches 3") self.assertEqual(spl._matched_playlists, set([pl1, pl3])) self.assertEqual(spl._unmatched_playlists, set([pl2])) @@ -184,7 +189,7 @@ class SmartPlaylistCLITest(unittest.TestCase, TestHelper): {'name': 'my_playlist.m3u', 'query': self.item.title}, {'name': 'all.m3u', - 'query': ''} + 'query': u''} ]) config['smartplaylist']['playlist_dir'].set(self.temp_dir) self.load_plugins('smartplaylist') @@ -195,22 +200,22 @@ class SmartPlaylistCLITest(unittest.TestCase, TestHelper): def test_splupdate(self): with self.assertRaises(UserError): - self.run_with_output('splupdate', 'tagada') + self.run_with_output(u'splupdate', u'tagada') - self.run_with_output('splupdate', 'my_playlist') + self.run_with_output(u'splupdate', u'my_playlist') m3u_path = path.join(self.temp_dir, 'my_playlist.m3u') self.assertTrue(path.exists(m3u_path)) with open(m3u_path, 'r') as f: self.assertEqual(f.read(), self.item.path + b"\n") remove(m3u_path) - self.run_with_output('splupdate', 'my_playlist.m3u') + self.run_with_output(u'splupdate', u'my_playlist.m3u') with open(m3u_path, 'r') as f: self.assertEqual(f.read(), self.item.path + b"\n") remove(m3u_path) - self.run_with_output('splupdate') - for name in ('my_playlist.m3u', 'all.m3u'): + self.run_with_output(u'splupdate') + for name in (u'my_playlist.m3u', u'all.m3u'): with open(path.join(self.temp_dir, name), 'r') as f: self.assertEqual(f.read(), self.item.path + b"\n") diff --git a/test/test_sort.py b/test/test_sort.py index dc4e6d2b2..daaca262a 100644 --- a/test/test_sort.py +++ b/test/test_sort.py @@ -15,8 +15,7 @@ """Various tests for querying the library database. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from test import _common from test._common import unittest @@ -33,71 +32,71 @@ class DummyDataTestCase(_common.TestCase): self.lib = beets.library.Library(':memory:') albums = [_common.album() for _ in range(3)] - albums[0].album = "Album A" - albums[0].genre = "Rock" + albums[0].album = u"Album A" + albums[0].genre = u"Rock" albums[0].year = 2001 - albums[0].flex1 = "Flex1-1" - albums[0].flex2 = "Flex2-A" - albums[0].albumartist = "Foo" + albums[0].flex1 = u"Flex1-1" + albums[0].flex2 = u"Flex2-A" + albums[0].albumartist = u"Foo" albums[0].albumartist_sort = None - albums[1].album = "Album B" - albums[1].genre = "Rock" + albums[1].album = u"Album B" + albums[1].genre = u"Rock" albums[1].year = 2001 - albums[1].flex1 = "Flex1-2" - albums[1].flex2 = "Flex2-A" - albums[1].albumartist = "Bar" + albums[1].flex1 = u"Flex1-2" + albums[1].flex2 = u"Flex2-A" + albums[1].albumartist = u"Bar" albums[1].albumartist_sort = None - albums[2].album = "Album C" - albums[2].genre = "Jazz" + albums[2].album = u"Album C" + albums[2].genre = u"Jazz" albums[2].year = 2005 - albums[2].flex1 = "Flex1-1" - albums[2].flex2 = "Flex2-B" - albums[2].albumartist = "Baz" + albums[2].flex1 = u"Flex1-1" + albums[2].flex2 = u"Flex2-B" + albums[2].albumartist = u"Baz" albums[2].albumartist_sort = None for album in albums: self.lib.add(album) items = [_common.item() for _ in range(4)] - items[0].title = 'Foo bar' - items[0].artist = 'One' - items[0].album = 'Baz' + items[0].title = u'Foo bar' + items[0].artist = u'One' + items[0].album = u'Baz' items[0].year = 2001 items[0].comp = True - items[0].flex1 = "Flex1-0" - items[0].flex2 = "Flex2-A" + items[0].flex1 = u"Flex1-0" + items[0].flex2 = u"Flex2-A" items[0].album_id = albums[0].id items[0].artist_sort = None items[0].path = "/path0.mp3" items[0].track = 1 - items[1].title = 'Baz qux' - items[1].artist = 'Two' - items[1].album = 'Baz' + items[1].title = u'Baz qux' + items[1].artist = u'Two' + items[1].album = u'Baz' items[1].year = 2002 items[1].comp = True - items[1].flex1 = "Flex1-1" - items[1].flex2 = "Flex2-A" + items[1].flex1 = u"Flex1-1" + items[1].flex2 = u"Flex2-A" items[1].album_id = albums[0].id items[1].artist_sort = None items[1].path = "/patH1.mp3" items[1].track = 2 - items[2].title = 'Beets 4 eva' - items[2].artist = 'Three' - items[2].album = 'Foo' + items[2].title = u'Beets 4 eva' + items[2].artist = u'Three' + items[2].album = u'Foo' items[2].year = 2003 items[2].comp = False - items[2].flex1 = "Flex1-2" - items[2].flex2 = "Flex1-B" + items[2].flex1 = u"Flex1-2" + items[2].flex2 = u"Flex1-B" items[2].album_id = albums[1].id items[2].artist_sort = None items[2].path = "/paTH2.mp3" items[2].track = 3 - items[3].title = 'Beets 4 eva' - items[3].artist = 'Three' - items[3].album = 'Foo2' + items[3].title = u'Beets 4 eva' + items[3].artist = u'Three' + items[3].album = u'Foo2' items[3].year = 2004 items[3].comp = False - items[3].flex1 = "Flex1-2" - items[3].flex2 = "Flex1-C" + items[3].flex1 = u"Flex1-2" + items[3].flex2 = u"Flex1-C" items[3].album_id = albums[2].id items[3].artist_sort = None items[3].path = "/PATH3.mp3" @@ -108,50 +107,50 @@ class DummyDataTestCase(_common.TestCase): class SortFixedFieldTest(DummyDataTestCase): def test_sort_asc(self): - q = '' - sort = dbcore.query.FixedFieldSort("year", True) + q = u'' + sort = dbcore.query.FixedFieldSort(u"year", True) results = self.lib.items(q, sort) self.assertLessEqual(results[0]['year'], results[1]['year']) self.assertEqual(results[0]['year'], 2001) # same thing with query string - q = 'year+' + q = u'year+' results2 = self.lib.items(q) for r1, r2 in zip(results, results2): self.assertEqual(r1.id, r2.id) def test_sort_desc(self): - q = '' - sort = dbcore.query.FixedFieldSort("year", False) + q = u'' + sort = dbcore.query.FixedFieldSort(u"year", False) results = self.lib.items(q, sort) self.assertGreaterEqual(results[0]['year'], results[1]['year']) self.assertEqual(results[0]['year'], 2004) # same thing with query string - q = 'year-' + q = u'year-' results2 = self.lib.items(q) for r1, r2 in zip(results, results2): self.assertEqual(r1.id, r2.id) def test_sort_two_field_asc(self): - q = '' - s1 = dbcore.query.FixedFieldSort("album", True) - s2 = dbcore.query.FixedFieldSort("year", True) + q = u'' + s1 = dbcore.query.FixedFieldSort(u"album", True) + s2 = dbcore.query.FixedFieldSort(u"year", True) sort = dbcore.query.MultipleSort() sort.add_sort(s1) sort.add_sort(s2) results = self.lib.items(q, sort) self.assertLessEqual(results[0]['album'], results[1]['album']) self.assertLessEqual(results[1]['album'], results[2]['album']) - self.assertEqual(results[0]['album'], 'Baz') - self.assertEqual(results[1]['album'], 'Baz') + self.assertEqual(results[0]['album'], u'Baz') + self.assertEqual(results[1]['album'], u'Baz') self.assertLessEqual(results[0]['year'], results[1]['year']) # same thing with query string - q = 'album+ year+' + q = u'album+ year+' results2 = self.lib.items(q) for r1, r2 in zip(results, results2): self.assertEqual(r1.id, r2.id) def test_sort_path_field(self): - q = '' + q = u'' sort = dbcore.query.FixedFieldSort('path', True) results = self.lib.items(q, sort) self.assertEqual(results[0]['path'], '/path0.mp3') @@ -162,46 +161,46 @@ class SortFixedFieldTest(DummyDataTestCase): class SortFlexFieldTest(DummyDataTestCase): def test_sort_asc(self): - q = '' - sort = dbcore.query.SlowFieldSort("flex1", True) + q = u'' + sort = dbcore.query.SlowFieldSort(u"flex1", True) results = self.lib.items(q, sort) self.assertLessEqual(results[0]['flex1'], results[1]['flex1']) - self.assertEqual(results[0]['flex1'], 'Flex1-0') + self.assertEqual(results[0]['flex1'], u'Flex1-0') # same thing with query string - q = 'flex1+' + q = u'flex1+' results2 = self.lib.items(q) for r1, r2 in zip(results, results2): self.assertEqual(r1.id, r2.id) def test_sort_desc(self): - q = '' - sort = dbcore.query.SlowFieldSort("flex1", False) + q = u'' + sort = dbcore.query.SlowFieldSort(u"flex1", False) results = self.lib.items(q, sort) self.assertGreaterEqual(results[0]['flex1'], results[1]['flex1']) self.assertGreaterEqual(results[1]['flex1'], results[2]['flex1']) self.assertGreaterEqual(results[2]['flex1'], results[3]['flex1']) - self.assertEqual(results[0]['flex1'], 'Flex1-2') + self.assertEqual(results[0]['flex1'], u'Flex1-2') # same thing with query string - q = 'flex1-' + q = u'flex1-' results2 = self.lib.items(q) for r1, r2 in zip(results, results2): self.assertEqual(r1.id, r2.id) def test_sort_two_field(self): - q = '' - s1 = dbcore.query.SlowFieldSort("flex2", False) - s2 = dbcore.query.SlowFieldSort("flex1", True) + q = u'' + s1 = dbcore.query.SlowFieldSort(u"flex2", False) + s2 = dbcore.query.SlowFieldSort(u"flex1", True) sort = dbcore.query.MultipleSort() sort.add_sort(s1) sort.add_sort(s2) results = self.lib.items(q, sort) self.assertGreaterEqual(results[0]['flex2'], results[1]['flex2']) self.assertGreaterEqual(results[1]['flex2'], results[2]['flex2']) - self.assertEqual(results[0]['flex2'], 'Flex2-A') - self.assertEqual(results[1]['flex2'], 'Flex2-A') + self.assertEqual(results[0]['flex2'], u'Flex2-A') + self.assertEqual(results[1]['flex2'], u'Flex2-A') self.assertLessEqual(results[0]['flex1'], results[1]['flex1']) # same thing with query string - q = 'flex2- flex1+' + q = u'flex2- flex1+' results2 = self.lib.items(q) for r1, r2 in zip(results, results2): self.assertEqual(r1.id, r2.id) @@ -209,44 +208,44 @@ class SortFlexFieldTest(DummyDataTestCase): class SortAlbumFixedFieldTest(DummyDataTestCase): def test_sort_asc(self): - q = '' - sort = dbcore.query.FixedFieldSort("year", True) + q = u'' + sort = dbcore.query.FixedFieldSort(u"year", True) results = self.lib.albums(q, sort) self.assertLessEqual(results[0]['year'], results[1]['year']) self.assertEqual(results[0]['year'], 2001) # same thing with query string - q = 'year+' + q = u'year+' results2 = self.lib.albums(q) for r1, r2 in zip(results, results2): self.assertEqual(r1.id, r2.id) def test_sort_desc(self): - q = '' - sort = dbcore.query.FixedFieldSort("year", False) + q = u'' + sort = dbcore.query.FixedFieldSort(u"year", False) results = self.lib.albums(q, sort) self.assertGreaterEqual(results[0]['year'], results[1]['year']) self.assertEqual(results[0]['year'], 2005) # same thing with query string - q = 'year-' + q = u'year-' results2 = self.lib.albums(q) for r1, r2 in zip(results, results2): self.assertEqual(r1.id, r2.id) def test_sort_two_field_asc(self): - q = '' - s1 = dbcore.query.FixedFieldSort("genre", True) - s2 = dbcore.query.FixedFieldSort("album", True) + q = u'' + s1 = dbcore.query.FixedFieldSort(u"genre", True) + s2 = dbcore.query.FixedFieldSort(u"album", True) sort = dbcore.query.MultipleSort() sort.add_sort(s1) sort.add_sort(s2) results = self.lib.albums(q, sort) self.assertLessEqual(results[0]['genre'], results[1]['genre']) self.assertLessEqual(results[1]['genre'], results[2]['genre']) - self.assertEqual(results[1]['genre'], 'Rock') - self.assertEqual(results[2]['genre'], 'Rock') + self.assertEqual(results[1]['genre'], u'Rock') + self.assertEqual(results[2]['genre'], u'Rock') self.assertLessEqual(results[1]['album'], results[2]['album']) # same thing with query string - q = 'genre+ album+' + q = u'genre+ album+' results2 = self.lib.albums(q) for r1, r2 in zip(results, results2): self.assertEqual(r1.id, r2.id) @@ -254,44 +253,44 @@ class SortAlbumFixedFieldTest(DummyDataTestCase): class SortAlbumFlexFieldTest(DummyDataTestCase): def test_sort_asc(self): - q = '' - sort = dbcore.query.SlowFieldSort("flex1", True) + q = u'' + sort = dbcore.query.SlowFieldSort(u"flex1", True) results = self.lib.albums(q, sort) self.assertLessEqual(results[0]['flex1'], results[1]['flex1']) self.assertLessEqual(results[1]['flex1'], results[2]['flex1']) # same thing with query string - q = 'flex1+' + q = u'flex1+' results2 = self.lib.albums(q) for r1, r2 in zip(results, results2): self.assertEqual(r1.id, r2.id) def test_sort_desc(self): - q = '' - sort = dbcore.query.SlowFieldSort("flex1", False) + q = u'' + sort = dbcore.query.SlowFieldSort(u"flex1", False) results = self.lib.albums(q, sort) self.assertGreaterEqual(results[0]['flex1'], results[1]['flex1']) self.assertGreaterEqual(results[1]['flex1'], results[2]['flex1']) # same thing with query string - q = 'flex1-' + q = u'flex1-' results2 = self.lib.albums(q) for r1, r2 in zip(results, results2): self.assertEqual(r1.id, r2.id) def test_sort_two_field_asc(self): - q = '' - s1 = dbcore.query.SlowFieldSort("flex2", True) - s2 = dbcore.query.SlowFieldSort("flex1", True) + q = u'' + s1 = dbcore.query.SlowFieldSort(u"flex2", True) + s2 = dbcore.query.SlowFieldSort(u"flex1", True) sort = dbcore.query.MultipleSort() sort.add_sort(s1) sort.add_sort(s2) results = self.lib.albums(q, sort) self.assertLessEqual(results[0]['flex2'], results[1]['flex2']) self.assertLessEqual(results[1]['flex2'], results[2]['flex2']) - self.assertEqual(results[0]['flex2'], 'Flex2-A') - self.assertEqual(results[1]['flex2'], 'Flex2-A') + self.assertEqual(results[0]['flex2'], u'Flex2-A') + self.assertEqual(results[1]['flex2'], u'Flex2-A') self.assertLessEqual(results[0]['flex1'], results[1]['flex1']) # same thing with query string - q = 'flex2+ flex1+' + q = u'flex2+ flex1+' results2 = self.lib.albums(q) for r1, r2 in zip(results, results2): self.assertEqual(r1.id, r2.id) @@ -299,25 +298,25 @@ class SortAlbumFlexFieldTest(DummyDataTestCase): class SortAlbumComputedFieldTest(DummyDataTestCase): def test_sort_asc(self): - q = '' - sort = dbcore.query.SlowFieldSort("path", True) + q = u'' + sort = dbcore.query.SlowFieldSort(u"path", True) results = self.lib.albums(q, sort) self.assertLessEqual(results[0]['path'], results[1]['path']) self.assertLessEqual(results[1]['path'], results[2]['path']) # same thing with query string - q = 'path+' + q = u'path+' results2 = self.lib.albums(q) for r1, r2 in zip(results, results2): self.assertEqual(r1.id, r2.id) def test_sort_desc(self): - q = '' - sort = dbcore.query.SlowFieldSort("path", False) + q = u'' + sort = dbcore.query.SlowFieldSort(u"path", False) results = self.lib.albums(q, sort) self.assertGreaterEqual(results[0]['path'], results[1]['path']) self.assertGreaterEqual(results[1]['path'], results[2]['path']) # same thing with query string - q = 'path-' + q = u'path-' results2 = self.lib.albums(q) for r1, r2 in zip(results, results2): self.assertEqual(r1.id, r2.id) @@ -325,24 +324,24 @@ class SortAlbumComputedFieldTest(DummyDataTestCase): class SortCombinedFieldTest(DummyDataTestCase): def test_computed_first(self): - q = '' - s1 = dbcore.query.SlowFieldSort("path", True) - s2 = dbcore.query.FixedFieldSort("year", True) + q = u'' + s1 = dbcore.query.SlowFieldSort(u"path", True) + s2 = dbcore.query.FixedFieldSort(u"year", True) sort = dbcore.query.MultipleSort() sort.add_sort(s1) sort.add_sort(s2) results = self.lib.albums(q, sort) self.assertLessEqual(results[0]['path'], results[1]['path']) self.assertLessEqual(results[1]['path'], results[2]['path']) - q = 'path+ year+' + q = u'path+ year+' results2 = self.lib.albums(q) for r1, r2 in zip(results, results2): self.assertEqual(r1.id, r2.id) def test_computed_second(self): - q = '' - s1 = dbcore.query.FixedFieldSort("year", True) - s2 = dbcore.query.SlowFieldSort("path", True) + q = u'' + s1 = dbcore.query.FixedFieldSort(u"year", True) + s2 = dbcore.query.SlowFieldSort(u"path", True) sort = dbcore.query.MultipleSort() sort.add_sort(s1) sort.add_sort(s2) @@ -350,7 +349,7 @@ class SortCombinedFieldTest(DummyDataTestCase): self.assertLessEqual(results[0]['year'], results[1]['year']) self.assertLessEqual(results[1]['year'], results[2]['year']) self.assertLessEqual(results[0]['path'], results[1]['path']) - q = 'year+ path+' + q = u'year+ path+' results2 = self.lib.albums(q) for r1, r2 in zip(results, results2): self.assertEqual(r1.id, r2.id) @@ -385,23 +384,23 @@ class CaseSensitivityTest(DummyDataTestCase, _common.TestCase): super(CaseSensitivityTest, self).setUp() album = _common.album() - album.album = "album" - album.genre = "alternative" - album.year = "2001" - album.flex1 = "flex1" - album.flex2 = "flex2-A" - album.albumartist = "bar" + album.album = u"album" + album.genre = u"alternative" + album.year = u"2001" + album.flex1 = u"flex1" + album.flex2 = u"flex2-A" + album.albumartist = u"bar" album.albumartist_sort = None self.lib.add(album) item = _common.item() - item.title = 'another' - item.artist = 'lowercase' - item.album = 'album' + item.title = u'another' + item.artist = u'lowercase' + item.album = u'album' item.year = 2001 item.comp = True - item.flex1 = "flex1" - item.flex2 = "flex2-A" + item.flex1 = u"flex1" + item.flex2 = u"flex2-A" item.album_id = album.id item.artist_sort = None item.track = 10 @@ -417,49 +416,49 @@ class CaseSensitivityTest(DummyDataTestCase, _common.TestCase): def test_smart_artist_case_insensitive(self): config['sort_case_insensitive'] = True - q = 'artist+' + q = u'artist+' results = list(self.lib.items(q)) - self.assertEqual(results[0].artist, 'lowercase') - self.assertEqual(results[1].artist, 'One') + self.assertEqual(results[0].artist, u'lowercase') + self.assertEqual(results[1].artist, u'One') def test_smart_artist_case_sensitive(self): config['sort_case_insensitive'] = False - q = 'artist+' + q = u'artist+' results = list(self.lib.items(q)) - self.assertEqual(results[0].artist, 'One') - self.assertEqual(results[-1].artist, 'lowercase') + self.assertEqual(results[0].artist, u'One') + self.assertEqual(results[-1].artist, u'lowercase') def test_fixed_field_case_insensitive(self): config['sort_case_insensitive'] = True - q = 'album+' + q = u'album+' results = list(self.lib.albums(q)) - self.assertEqual(results[0].album, 'album') - self.assertEqual(results[1].album, 'Album A') + self.assertEqual(results[0].album, u'album') + self.assertEqual(results[1].album, u'Album A') def test_fixed_field_case_sensitive(self): config['sort_case_insensitive'] = False - q = 'album+' + q = u'album+' results = list(self.lib.albums(q)) - self.assertEqual(results[0].album, 'Album A') - self.assertEqual(results[-1].album, 'album') + self.assertEqual(results[0].album, u'Album A') + self.assertEqual(results[-1].album, u'album') def test_flex_field_case_insensitive(self): config['sort_case_insensitive'] = True - q = 'flex1+' + q = u'flex1+' results = list(self.lib.items(q)) - self.assertEqual(results[0].flex1, 'flex1') - self.assertEqual(results[1].flex1, 'Flex1-0') + self.assertEqual(results[0].flex1, u'flex1') + self.assertEqual(results[1].flex1, u'Flex1-0') def test_flex_field_case_sensitive(self): config['sort_case_insensitive'] = False - q = 'flex1+' + q = u'flex1+' results = list(self.lib.items(q)) - self.assertEqual(results[0].flex1, 'Flex1-0') - self.assertEqual(results[-1].flex1, 'flex1') + self.assertEqual(results[0].flex1, u'Flex1-0') + self.assertEqual(results[-1].flex1, u'flex1') def test_case_sensitive_only_affects_text(self): config['sort_case_insensitive'] = True - q = 'track+' + q = u'track+' results = list(self.lib.items(q)) # If the numerical values were sorted as strings, # then ['1', '10', '2'] would be valid. @@ -473,9 +472,10 @@ class NonExistingFieldTest(DummyDataTestCase): """Test sorting by non-existing fields""" def test_non_existing_fields_not_fail(self): - qs = ['foo+', 'foo-', '--', '-+', '+-', '++', '-foo-', '-foo+', '---'] + qs = [u'foo+', u'foo-', u'--', u'-+', u'+-', + u'++', u'-foo-', u'-foo+', u'---'] - q0 = 'foo+' + q0 = u'foo+' results0 = list(self.lib.items(q0)) for q1 in qs: results1 = list(self.lib.items(q1)) @@ -483,16 +483,16 @@ class NonExistingFieldTest(DummyDataTestCase): self.assertEqual(r1.id, r2.id) def test_combined_non_existing_field_asc(self): - all_results = list(self.lib.items('id+')) - q = 'foo+ id+' + all_results = list(self.lib.items(u'id+')) + q = u'foo+ id+' results = list(self.lib.items(q)) self.assertEqual(len(all_results), len(results)) for r1, r2 in zip(all_results, results): self.assertEqual(r1.id, r2.id) def test_combined_non_existing_field_desc(self): - all_results = list(self.lib.items('id+')) - q = 'foo- id+' + all_results = list(self.lib.items(u'id+')) + q = u'foo- id+' results = list(self.lib.items(q)) self.assertEqual(len(all_results), len(results)) for r1, r2 in zip(all_results, results): @@ -501,18 +501,18 @@ class NonExistingFieldTest(DummyDataTestCase): def test_field_present_in_some_items(self): """Test ordering by a field not present on all items.""" # append 'foo' to two to items (1,2) - items = self.lib.items('id+') + items = self.lib.items(u'id+') ids = [i.id for i in items] - items[1].foo = 'bar1' - items[2].foo = 'bar2' + items[1].foo = u'bar1' + items[2].foo = u'bar2' items[1].store() items[2].store() - results_asc = list(self.lib.items('foo+ id+')) + results_asc = list(self.lib.items(u'foo+ id+')) self.assertEqual([i.id for i in results_asc], # items without field first [ids[0], ids[3], ids[1], ids[2]]) - results_desc = list(self.lib.items('foo- id+')) + results_desc = list(self.lib.items(u'foo- id+')) self.assertEqual([i.id for i in results_desc], # items without field last [ids[2], ids[1], ids[0], ids[3]]) @@ -523,13 +523,13 @@ class NonExistingFieldTest(DummyDataTestCase): If a string ends with a sorting suffix, it takes precedence over the NotQuery parsing. """ - query, sort = beets.library.parse_query_string('-bar+', + query, sort = beets.library.parse_query_string(u'-bar+', beets.library.Item) self.assertEqual(len(query.subqueries), 1) self.assertTrue(isinstance(query.subqueries[0], dbcore.query.TrueQuery)) self.assertTrue(isinstance(sort, dbcore.query.SlowFieldSort)) - self.assertEqual(sort.field, '-bar') + self.assertEqual(sort.field, u'-bar') def suite(): diff --git a/test/test_spotify.py b/test/test_spotify.py index 895106845..6f218c339 100644 --- a/test/test_spotify.py +++ b/test/test_spotify.py @@ -2,8 +2,7 @@ """Tests for the 'spotify' plugin""" -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from test import _common import responses @@ -46,7 +45,7 @@ class SpotifyPluginTest(_common.TestCase, TestHelper): self.assertEqual(True, self.spotify.parse_opts(opts)) def test_empty_query(self): - self.assertEqual(None, self.spotify.query_spotify(self.lib, "1=2")) + self.assertEqual(None, self.spotify.query_spotify(self.lib, u"1=2")) @responses.activate def test_missing_request(self): @@ -68,21 +67,21 @@ class SpotifyPluginTest(_common.TestCase, TestHelper): body=response_body, status=200, content_type='application/json') item = Item( - mb_trackid='01234', - album='lkajsdflakjsd', - albumartist='ujydfsuihse', - title='duifhjslkef', + mb_trackid=u'01234', + album=u'lkajsdflakjsd', + albumartist=u'ujydfsuihse', + title=u'duifhjslkef', length=10 ) item.add(self.lib) - self.assertEqual([], self.spotify.query_spotify(self.lib, "")) + self.assertEqual([], self.spotify.query_spotify(self.lib, u"")) params = _params(responses.calls[0].request.url) self.assertEqual( params['q'], - ['duifhjslkef album:lkajsdflakjsd artist:ujydfsuihse'], + [u'duifhjslkef album:lkajsdflakjsd artist:ujydfsuihse'], ) - self.assertEqual(params['type'], ['track']) + self.assertEqual(params['type'], [u'track']) @responses.activate def test_track_request(self): @@ -186,24 +185,24 @@ class SpotifyPluginTest(_common.TestCase, TestHelper): body=response_body, status=200, content_type='application/json') item = Item( - mb_trackid='01234', - album='Despicable Me 2', - albumartist='Pharrell Williams', - title='Happy', + mb_trackid=u'01234', + album=u'Despicable Me 2', + albumartist=u'Pharrell Williams', + title=u'Happy', length=10 ) item.add(self.lib) - results = self.spotify.query_spotify(self.lib, "Happy") + results = self.spotify.query_spotify(self.lib, u"Happy") self.assertEqual(1, len(results)) - self.assertEqual("6NPVjNh8Jhru9xOmyQigds", results[0]['id']) + self.assertEqual(u"6NPVjNh8Jhru9xOmyQigds", results[0]['id']) self.spotify.output_results(results) params = _params(responses.calls[0].request.url) self.assertEqual( params['q'], - ['Happy album:Despicable Me 2 artist:Pharrell Williams'], + [u'Happy album:Despicable Me 2 artist:Pharrell Williams'], ) - self.assertEqual(params['type'], ['track']) + self.assertEqual(params['type'], [u'track']) def suite(): diff --git a/test/test_template.py b/test/test_template.py index 96100bdfe..efc900034 100644 --- a/test/test_template.py +++ b/test/test_template.py @@ -15,8 +15,7 @@ """Tests for template engine. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import warnings diff --git a/test/test_the.py b/test/test_the.py index 9cfb34d63..3d5c722be 100644 --- a/test/test_the.py +++ b/test/test_the.py @@ -2,8 +2,7 @@ """Tests for the 'the' plugin""" -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from test._common import unittest from test import _common @@ -14,51 +13,52 @@ from beetsplug.the import ThePlugin, PATTERN_A, PATTERN_THE, FORMAT class ThePluginTest(_common.TestCase): def test_unthe_with_default_patterns(self): - self.assertEqual(ThePlugin().unthe('', PATTERN_THE), '') - self.assertEqual(ThePlugin().unthe('The Something', PATTERN_THE), - 'Something, The') - self.assertEqual(ThePlugin().unthe('The The', PATTERN_THE), - 'The, The') - self.assertEqual(ThePlugin().unthe('The The', PATTERN_THE), - 'The, The') - self.assertEqual(ThePlugin().unthe('The The X', PATTERN_THE), - 'The X, The') - self.assertEqual(ThePlugin().unthe('the The', PATTERN_THE), - 'The, the') - self.assertEqual(ThePlugin().unthe('Protected The', PATTERN_THE), - 'Protected The') - self.assertEqual(ThePlugin().unthe('A Boy', PATTERN_A), - 'Boy, A') - self.assertEqual(ThePlugin().unthe('a girl', PATTERN_A), - 'girl, a') - self.assertEqual(ThePlugin().unthe('An Apple', PATTERN_A), - 'Apple, An') - self.assertEqual(ThePlugin().unthe('An A Thing', PATTERN_A), - 'A Thing, An') - self.assertEqual(ThePlugin().unthe('the An Arse', PATTERN_A), - 'the An Arse') + self.assertEqual(ThePlugin().unthe(u'', PATTERN_THE), '') + self.assertEqual(ThePlugin().unthe(u'The Something', PATTERN_THE), + u'Something, The') + self.assertEqual(ThePlugin().unthe(u'The The', PATTERN_THE), + u'The, The') + self.assertEqual(ThePlugin().unthe(u'The The', PATTERN_THE), + u'The, The') + self.assertEqual(ThePlugin().unthe(u'The The X', PATTERN_THE), + u'The X, The') + self.assertEqual(ThePlugin().unthe(u'the The', PATTERN_THE), + u'The, the') + self.assertEqual(ThePlugin().unthe(u'Protected The', PATTERN_THE), + u'Protected The') + self.assertEqual(ThePlugin().unthe(u'A Boy', PATTERN_A), + u'Boy, A') + self.assertEqual(ThePlugin().unthe(u'a girl', PATTERN_A), + u'girl, a') + self.assertEqual(ThePlugin().unthe(u'An Apple', PATTERN_A), + u'Apple, An') + self.assertEqual(ThePlugin().unthe(u'An A Thing', PATTERN_A), + u'A Thing, An') + self.assertEqual(ThePlugin().unthe(u'the An Arse', PATTERN_A), + u'the An Arse') def test_unthe_with_strip(self): config['the']['strip'] = True - self.assertEqual(ThePlugin().unthe('The Something', PATTERN_THE), - 'Something') - self.assertEqual(ThePlugin().unthe('An A', PATTERN_A), 'A') + self.assertEqual(ThePlugin().unthe(u'The Something', PATTERN_THE), + u'Something') + self.assertEqual(ThePlugin().unthe(u'An A', PATTERN_A), u'A') def test_template_function_with_defaults(self): ThePlugin().patterns = [PATTERN_THE, PATTERN_A] - self.assertEqual(ThePlugin().the_template_func('The The'), 'The, The') - self.assertEqual(ThePlugin().the_template_func('An A'), 'A, An') + self.assertEqual(ThePlugin().the_template_func(u'The The'), + u'The, The') + self.assertEqual(ThePlugin().the_template_func(u'An A'), u'A, An') def test_custom_pattern(self): config['the']['patterns'] = [u'^test\s'] config['the']['format'] = FORMAT - self.assertEqual(ThePlugin().the_template_func('test passed'), - 'passed, test') + self.assertEqual(ThePlugin().the_template_func(u'test passed'), + u'passed, test') def test_custom_format(self): config['the']['patterns'] = [PATTERN_THE, PATTERN_A] config['the']['format'] = u'{1} ({0})' - self.assertEqual(ThePlugin().the_template_func('The A'), 'The (A)') + self.assertEqual(ThePlugin().the_template_func(u'The A'), u'The (A)') def suite(): diff --git a/test/test_thumbnails.py b/test/test_thumbnails.py index 60297c68e..5dd9551b7 100644 --- a/test/test_thumbnails.py +++ b/test/test_thumbnails.py @@ -13,8 +13,7 @@ # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import os.path from mock import Mock, patch, call @@ -38,13 +37,13 @@ class ThumbnailsTest(unittest.TestCase, TestHelper): @patch('beetsplug.thumbnails.util') def test_write_metadata_im(self, mock_util): - metadata = {"a": "A", "b": "B"} + metadata = {"a": u"A", "b": u"B"} write_metadata_im("foo", metadata) try: - command = "convert foo -set a A -set b B foo".split(' ') + command = u"convert foo -set a A -set b B foo".split(' ') mock_util.command_output.assert_called_once_with(command) except AssertionError: - command = "convert foo -set b B -set a A foo".split(' ') + command = u"convert foo -set b B -set a A foo".split(' ') mock_util.command_output.assert_called_once_with(command) @patch('beetsplug.thumbnails.ThumbnailsPlugin._check_local_ok') @@ -60,7 +59,7 @@ class ThumbnailsTest(unittest.TestCase, TestHelper): plugin.add_tags(album, b"/path/to/thumbnail") metadata = {"Thumb::URI": b"COVER_URI", - "Thumb::MTime": "12345"} + "Thumb::MTime": u"12345"} plugin.write_metadata.assert_called_once_with(b"/path/to/thumbnail", metadata) mock_stat.assert_called_once_with(album.artpath) @@ -85,7 +84,7 @@ class ThumbnailsTest(unittest.TestCase, TestHelper): return False if path == LARGE_DIR: return True - raise ValueError("unexpected path {0!r}".format(path)) + raise ValueError(u"unexpected path {0!r}".format(path)) mock_os.path.exists = exists plugin = ThumbnailsPlugin() mock_os.makedirs.assert_called_once_with(NORMAL_DIR) @@ -143,7 +142,7 @@ class ThumbnailsTest(unittest.TestCase, TestHelper): elif target == path_to_art: return Mock(st_mtime=2) else: - raise ValueError("invalid target {0}".format(target)) + raise ValueError(u"invalid target {0}".format(target)) mock_os.stat.side_effect = os_stat plugin.make_cover_thumbnail(album, 12345, thumbnail_dir) @@ -169,7 +168,7 @@ class ThumbnailsTest(unittest.TestCase, TestHelper): elif target == path_to_art: return Mock(st_mtime=2) else: - raise ValueError("invalid target {0}".format(target)) + raise ValueError(u"invalid target {0}".format(target)) mock_os.stat.side_effect = os_stat plugin.make_cover_thumbnail(album, 12345, thumbnail_dir) @@ -266,7 +265,7 @@ class ThumbnailsTest(unittest.TestCase, TestHelper): @patch('beetsplug.thumbnails.BaseDirectory') def test_thumbnail_file_name(self, mock_basedir): plug = ThumbnailsPlugin() - plug.get_uri = Mock(return_value="file:///my/uri") + plug.get_uri = Mock(return_value=u"file:///my/uri") self.assertEqual(plug.thumbnail_file_name("idontcare"), b"9488f5797fbe12ffb316d607dfd93d04.png") @@ -274,9 +273,9 @@ class ThumbnailsTest(unittest.TestCase, TestHelper): gio = GioURI() plib = PathlibURI() if not gio.available: - self.skipTest("GIO library not found") + self.skipTest(u"GIO library not found") - self.assertEqual(gio.uri("/foo"), b"file:///") # silent fail + self.assertEqual(gio.uri(u"/foo"), b"file:///") # silent fail self.assertEqual(gio.uri(b"/foo"), b"file:///foo") self.assertEqual(gio.uri(b"/foo!"), b"file:///foo!") self.assertEqual(plib.uri(b"/foo!"), b"file:///foo%21") diff --git a/test/test_types_plugin.py b/test/test_types_plugin.py index ba3fa54e1..7af1a8d72 100644 --- a/test/test_types_plugin.py +++ b/test/test_types_plugin.py @@ -13,8 +13,7 @@ # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import time from datetime import datetime @@ -37,69 +36,69 @@ class TypesPluginTest(unittest.TestCase, TestHelper): def test_integer_modify_and_query(self): self.config['types'] = {'myint': 'int'} - item = self.add_item(artist='aaa') + item = self.add_item(artist=u'aaa') # Do not match unset values - out = self.list('myint:1..3') - self.assertEqual('', out) + out = self.list(u'myint:1..3') + self.assertEqual(u'', out) - self.modify('myint=2') + self.modify(u'myint=2') item.load() self.assertEqual(item['myint'], 2) # Match in range - out = self.list('myint:1..3') + out = self.list(u'myint:1..3') self.assertIn(b'aaa', out) def test_album_integer_modify_and_query(self): - self.config['types'] = {'myint': 'int'} - album = self.add_album(albumartist='aaa') + self.config['types'] = {'myint': u'int'} + album = self.add_album(albumartist=u'aaa') # Do not match unset values - out = self.list_album('myint:1..3') - self.assertEqual('', out) + out = self.list_album(u'myint:1..3') + self.assertEqual(u'', out) - self.modify('-a', 'myint=2') + self.modify(u'-a', u'myint=2') album.load() self.assertEqual(album['myint'], 2) # Match in range - out = self.list_album('myint:1..3') + out = self.list_album(u'myint:1..3') self.assertIn(b'aaa', out) def test_float_modify_and_query(self): - self.config['types'] = {'myfloat': 'float'} - item = self.add_item(artist='aaa') + self.config['types'] = {'myfloat': u'float'} + item = self.add_item(artist=u'aaa') - self.modify('myfloat=-9.1') + self.modify(u'myfloat=-9.1') item.load() self.assertEqual(item['myfloat'], -9.1) # Match in range - out = self.list('myfloat:-10..0') + out = self.list(u'myfloat:-10..0') self.assertIn(b'aaa', out) def test_bool_modify_and_query(self): - self.config['types'] = {'mybool': 'bool'} - true = self.add_item(artist='true') - false = self.add_item(artist='false') - self.add_item(artist='unset') + self.config['types'] = {'mybool': u'bool'} + true = self.add_item(artist=u'true') + false = self.add_item(artist=u'false') + self.add_item(artist=u'unset') # Set true - self.modify('mybool=1', 'artist:true') + self.modify(u'mybool=1', u'artist:true') true.load() self.assertEqual(true['mybool'], True) # Set false - self.modify('mybool=false', 'artist:false') + self.modify(u'mybool=false', u'artist:false') false.load() self.assertEqual(false['mybool'], False) # Query bools - out = self.list('mybool:true', '$artist $mybool') - self.assertEqual('true True', out) + out = self.list(u'mybool:true', u'$artist $mybool') + self.assertEqual(u'true True', out) - out = self.list('mybool:false', '$artist $mybool') + out = self.list(u'mybool:false', u'$artist $mybool') # Dealing with unset fields? # self.assertEqual('false False', out) @@ -107,23 +106,23 @@ class TypesPluginTest(unittest.TestCase, TestHelper): # self.assertIn('unset $mybool', out) def test_date_modify_and_query(self): - self.config['types'] = {'mydate': 'date'} + self.config['types'] = {'mydate': u'date'} # FIXME parsing should also work with default time format self.config['time_format'] = '%Y-%m-%d' - old = self.add_item(artist='prince') - new = self.add_item(artist='britney') + old = self.add_item(artist=u'prince') + new = self.add_item(artist=u'britney') - self.modify('mydate=1999-01-01', 'artist:prince') + self.modify(u'mydate=1999-01-01', u'artist:prince') old.load() self.assertEqual(old['mydate'], mktime(1999, 01, 01)) - self.modify('mydate=1999-12-30', 'artist:britney') + self.modify(u'mydate=1999-12-30', u'artist:britney') new.load() self.assertEqual(new['mydate'], mktime(1999, 12, 30)) # Match in range - out = self.list('mydate:..1999-07', '$artist $mydate') - self.assertEqual('prince 1999-01-01', out) + out = self.list(u'mydate:..1999-07', u'$artist $mydate') + self.assertEqual(u'prince 1999-01-01', out) # FIXME some sort of timezone issue here # out = self.list('mydate:1999-12-30', '$artist $mydate') @@ -132,17 +131,17 @@ class TypesPluginTest(unittest.TestCase, TestHelper): def test_unknown_type_error(self): self.config['types'] = {'flex': 'unkown type'} with self.assertRaises(ConfigValueError): - self.run_command('ls') + self.run_command(u'ls') def modify(self, *args): - return self.run_with_output('modify', '--yes', '--nowrite', - '--nomove', *args) + return self.run_with_output(u'modify', u'--yes', u'--nowrite', + u'--nomove', *args) - def list(self, query, fmt='$artist - $album - $title'): - return self.run_with_output('ls', '-f', fmt, query).strip() + def list(self, query, fmt=u'$artist - $album - $title'): + return self.run_with_output(u'ls', u'-f', fmt, query).strip() - def list_album(self, query, fmt='$albumartist - $album - $title'): - return self.run_with_output('ls', '-a', '-f', fmt, query).strip() + def list_album(self, query, fmt=u'$albumartist - $album - $title'): + return self.run_with_output(u'ls', u'-a', u'-f', fmt, query).strip() def mktime(*args): diff --git a/test/test_ui.py b/test/test_ui.py index 480e6ce03..fdc16aff9 100644 --- a/test/test_ui.py +++ b/test/test_ui.py @@ -15,8 +15,7 @@ """Tests for the command-line interface. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import os import shutil @@ -50,7 +49,7 @@ class ListTest(unittest.TestCase): self.lib.add(self.item) self.lib.add_album([self.item]) - def _run_list(self, query='', album=False, path=False, fmt=''): + def _run_list(self, query=u'', album=False, path=False, fmt=''): commands.list_items(self.lib, query, album, fmt) def test_list_outputs_item(self): @@ -135,14 +134,14 @@ class RemoveTest(_common.TestCase): def test_remove_items_no_delete(self): self.io.addinput('y') - commands.remove_items(self.lib, '', False, False) + commands.remove_items(self.lib, u'', False, False) items = self.lib.items() self.assertEqual(len(list(items)), 0) self.assertTrue(os.path.exists(self.i.path)) def test_remove_items_with_delete(self): self.io.addinput('y') - commands.remove_items(self.lib, '', False, True) + commands.remove_items(self.lib, u'', False, True) items = self.lib.items() self.assertEqual(len(list(items)), 0) self.assertFalse(os.path.exists(self.i.path)) @@ -168,58 +167,58 @@ class ModifyTest(unittest.TestCase, TestHelper): # Item tests def test_modify_item(self): - self.modify("title=newTitle") + self.modify(u"title=newTitle") item = self.lib.items().get() - self.assertEqual(item.title, 'newTitle') + self.assertEqual(item.title, u'newTitle') def test_modify_item_abort(self): item = self.lib.items().get() title = item.title - self.modify_inp('n', "title=newTitle") + self.modify_inp('n', u"title=newTitle") item = self.lib.items().get() self.assertEqual(item.title, title) def test_modify_item_no_change(self): - title = "Tracktitle" + title = u"Tracktitle" item = self.add_item_fixture(title=title) - self.modify_inp('y', "title", "title={0}".format(title)) + self.modify_inp('y', u"title", u"title={0}".format(title)) item = self.lib.items(title).get() self.assertEqual(item.title, title) def test_modify_write_tags(self): - self.modify("title=newTitle") + self.modify(u"title=newTitle") item = self.lib.items().get() item.read() - self.assertEqual(item.title, 'newTitle') + self.assertEqual(item.title, u'newTitle') def test_modify_dont_write_tags(self): - self.modify("--nowrite", "title=newTitle") + self.modify(u"--nowrite", u"title=newTitle") item = self.lib.items().get() item.read() self.assertNotEqual(item.title, 'newTitle') def test_move(self): - self.modify("title=newTitle") + self.modify(u"title=newTitle") item = self.lib.items().get() self.assertIn(b'newTitle', item.path) def test_not_move(self): - self.modify("--nomove", "title=newTitle") + self.modify(u"--nomove", u"title=newTitle") item = self.lib.items().get() self.assertNotIn(b'newTitle', item.path) def test_no_write_no_move(self): - self.modify("--nomove", "--nowrite", "title=newTitle") + self.modify(u"--nomove", u"--nowrite", u"title=newTitle") item = self.lib.items().get() item.read() self.assertNotIn(b'newTitle', item.path) - self.assertNotEqual(item.title, 'newTitle') + self.assertNotEqual(item.title, u'newTitle') def test_update_mtime(self): item = self.item old_mtime = item.mtime - self.modify("title=newTitle") + self.modify(u"title=newTitle") item.load() self.assertNotEqual(old_mtime, item.mtime) self.assertEqual(item.current_mtime(), item.mtime) @@ -227,53 +226,53 @@ class ModifyTest(unittest.TestCase, TestHelper): def test_reset_mtime_with_no_write(self): item = self.item - self.modify("--nowrite", "title=newTitle") + self.modify(u"--nowrite", u"title=newTitle") item.load() self.assertEqual(0, item.mtime) def test_selective_modify(self): - title = "Tracktitle" - album = "album" - origArtist = "composer" - newArtist = "coverArtist" + title = u"Tracktitle" + album = u"album" + origArtist = u"composer" + newArtist = u"coverArtist" for i in range(0, 10): - self.add_item_fixture(title="{0}{1}".format(title, i), + self.add_item_fixture(title=u"{0}{1}".format(title, i), artist=origArtist, album=album) self.modify_inp('s\ny\ny\ny\nn\nn\ny\ny\ny\ny\nn', - title, "artist={0}".format(newArtist)) - origItems = self.lib.items("artist:{0}".format(origArtist)) - newItems = self.lib.items("artist:{0}".format(newArtist)) + title, u"artist={0}".format(newArtist)) + origItems = self.lib.items(u"artist:{0}".format(origArtist)) + newItems = self.lib.items(u"artist:{0}".format(newArtist)) self.assertEqual(len(list(origItems)), 3) self.assertEqual(len(list(newItems)), 7) # Album Tests def test_modify_album(self): - self.modify("--album", "album=newAlbum") + self.modify(u"--album", u"album=newAlbum") album = self.lib.albums().get() - self.assertEqual(album.album, 'newAlbum') + self.assertEqual(album.album, u'newAlbum') def test_modify_album_write_tags(self): - self.modify("--album", "album=newAlbum") + self.modify(u"--album", u"album=newAlbum") item = self.lib.items().get() item.read() - self.assertEqual(item.album, 'newAlbum') + self.assertEqual(item.album, u'newAlbum') def test_modify_album_dont_write_tags(self): - self.modify("--album", "--nowrite", "album=newAlbum") + self.modify(u"--album", u"--nowrite", u"album=newAlbum") item = self.lib.items().get() item.read() - self.assertEqual(item.album, 'the album') + self.assertEqual(item.album, u'the album') def test_album_move(self): - self.modify("--album", "album=newAlbum") + self.modify(u"--album", u"album=newAlbum") item = self.lib.items().get() item.read() self.assertIn(b'newAlbum', item.path) def test_album_not_move(self): - self.modify("--nomove", "--album", "album=newAlbum") + self.modify(u"--nomove", u"--album", u"album=newAlbum") item = self.lib.items().get() item.read() self.assertNotIn(b'newAlbum', item.path) @@ -281,62 +280,62 @@ class ModifyTest(unittest.TestCase, TestHelper): # Misc def test_write_initial_key_tag(self): - self.modify("initial_key=C#m") + self.modify(u"initial_key=C#m") item = self.lib.items().get() mediafile = MediaFile(item.path) - self.assertEqual(mediafile.initial_key, 'C#m') + self.assertEqual(mediafile.initial_key, u'C#m') def test_set_flexattr(self): - self.modify("flexattr=testAttr") + self.modify(u"flexattr=testAttr") item = self.lib.items().get() - self.assertEqual(item.flexattr, 'testAttr') + self.assertEqual(item.flexattr, u'testAttr') def test_remove_flexattr(self): item = self.lib.items().get() - item.flexattr = 'testAttr' + item.flexattr = u'testAttr' item.store() - self.modify("flexattr!") + self.modify(u"flexattr!") item = self.lib.items().get() - self.assertNotIn("flexattr", item) + self.assertNotIn(u"flexattr", item) - @unittest.skip('not yet implemented') + @unittest.skip(u'not yet implemented') def test_delete_initial_key_tag(self): item = self.lib.items().get() - item.initial_key = 'C#m' + item.initial_key = u'C#m' item.write() item.store() mediafile = MediaFile(item.path) - self.assertEqual(mediafile.initial_key, 'C#m') + self.assertEqual(mediafile.initial_key, u'C#m') - self.modify("initial_key!") + self.modify(u"initial_key!") mediafile = MediaFile(item.path) self.assertIsNone(mediafile.initial_key) def test_arg_parsing_colon_query(self): - (query, mods, dels) = commands.modify_parse_args(["title:oldTitle", - "title=newTitle"]) - self.assertEqual(query, ["title:oldTitle"]) - self.assertEqual(mods, {"title": "newTitle"}) + (query, mods, dels) = commands.modify_parse_args([u"title:oldTitle", + u"title=newTitle"]) + self.assertEqual(query, [u"title:oldTitle"]) + self.assertEqual(mods, {"title": u"newTitle"}) def test_arg_parsing_delete(self): - (query, mods, dels) = commands.modify_parse_args(["title:oldTitle", - "title!"]) - self.assertEqual(query, ["title:oldTitle"]) + (query, mods, dels) = commands.modify_parse_args([u"title:oldTitle", + u"title!"]) + self.assertEqual(query, [u"title:oldTitle"]) self.assertEqual(dels, ["title"]) def test_arg_parsing_query_with_exclaimation(self): - (query, mods, dels) = commands.modify_parse_args(["title:oldTitle!", - "title=newTitle!"]) - self.assertEqual(query, ["title:oldTitle!"]) - self.assertEqual(mods, {"title": "newTitle!"}) + (query, mods, dels) = commands.modify_parse_args([u"title:oldTitle!", + u"title=newTitle!"]) + self.assertEqual(query, [u"title:oldTitle!"]) + self.assertEqual(mods, {"title": u"newTitle!"}) def test_arg_parsing_equals_in_value(self): - (query, mods, dels) = commands.modify_parse_args(["title:foo=bar", - "title=newTitle"]) - self.assertEqual(query, ["title:foo=bar"]) - self.assertEqual(mods, {"title": "newTitle"}) + (query, mods, dels) = commands.modify_parse_args([u"title:foo=bar", + u"title=newTitle"]) + self.assertEqual(query, [u"title:foo=bar"]) + self.assertEqual(mods, {"title": u"newTitle"}) class WriteTest(unittest.TestCase, TestHelper): @@ -352,7 +351,7 @@ class WriteTest(unittest.TestCase, TestHelper): def test_update_mtime(self): item = self.add_item_fixture() - item['title'] = 'a new title' + item['title'] = u'a new title' item.store() item = self.lib.items().get() @@ -384,13 +383,13 @@ class WriteTest(unittest.TestCase, TestHelper): item.read() old_title = item.title - item.title = 'new title' + item.title = u'new title' item.store() with capture_stdout() as stdout: self.write_cmd() - self.assertTrue('{0} -> new title'.format(old_title) + self.assertTrue(u'{0} -> new title'.format(old_title) in stdout.getvalue()) @@ -522,40 +521,40 @@ class UpdateTest(_common.TestCase): def test_modified_metadata_detected(self): mf = MediaFile(self.i.path) - mf.title = 'differentTitle' + mf.title = u'differentTitle' mf.save() self._update() item = self.lib.items().get() - self.assertEqual(item.title, 'differentTitle') + self.assertEqual(item.title, u'differentTitle') def test_modified_metadata_moved(self): mf = MediaFile(self.i.path) - mf.title = 'differentTitle' + mf.title = u'differentTitle' mf.save() self._update(move=True) item = self.lib.items().get() - self.assertTrue('differentTitle' in item.path) + self.assertTrue(u'differentTitle' in item.path) def test_modified_metadata_not_moved(self): mf = MediaFile(self.i.path) - mf.title = 'differentTitle' + mf.title = u'differentTitle' mf.save() self._update(move=False) item = self.lib.items().get() - self.assertTrue('differentTitle' not in item.path) + self.assertTrue(u'differentTitle' not in item.path) def test_modified_album_metadata_moved(self): mf = MediaFile(self.i.path) - mf.album = 'differentAlbum' + mf.album = u'differentAlbum' mf.save() self._update(move=True) item = self.lib.items().get() - self.assertTrue('differentAlbum' in item.path) + self.assertTrue(u'differentAlbum' in item.path) def test_modified_album_metadata_art_moved(self): artpath = self.album.artpath mf = MediaFile(self.i.path) - mf.album = 'differentAlbum' + mf.album = u'differentAlbum' mf.save() self._update(move=True) album = self.lib.albums()[0] @@ -563,7 +562,7 @@ class UpdateTest(_common.TestCase): def test_mtime_match_skips_update(self): mf = MediaFile(self.i.path) - mf.title = 'differentTitle' + mf.title = u'differentTitle' mf.save() # Make in-memory mtime match on-disk mtime. @@ -572,7 +571,7 @@ class UpdateTest(_common.TestCase): self._update(reset_mtime=False) item = self.lib.items().get() - self.assertEqual(item.title, 'full') + self.assertEqual(item.title, u'full') class PrintTest(_common.TestCase): @@ -588,7 +587,7 @@ class PrintTest(_common.TestCase): try: ui.print_(u'something') except TypeError: - self.fail('TypeError during print') + self.fail(u'TypeError during print') finally: if lang: os.environ['LANG'] = lang @@ -602,7 +601,7 @@ class PrintTest(_common.TestCase): try: ui.print_(u'something') except ValueError: - self.fail('ValueError during print') + self.fail(u'ValueError during print') finally: if old_lang: os.environ['LANG'] = old_lang @@ -677,7 +676,7 @@ class ConfigTest(unittest.TestCase, TestHelper): self.teardown_beets() def _make_test_cmd(self): - test_cmd = ui.Subcommand('test', help='test') + test_cmd = ui.Subcommand('test', help=u'test') def run(lib, options, args): test_cmd.lib = lib @@ -738,7 +737,7 @@ class ConfigTest(unittest.TestCase, TestHelper): ui._raw_main(['test']) replacements = self.test_cmd.lib.replacements - self.assertEqual(replacements, [(re.compile(r'[xy]'), b'z')]) + self.assertEqual(replacements, [(re.compile(ur'[xy]'), b'z')]) def test_multiple_replacements_parsed(self): with self.write_config_file() as config: @@ -747,8 +746,8 @@ class ConfigTest(unittest.TestCase, TestHelper): ui._raw_main(['test']) replacements = self.test_cmd.lib.replacements self.assertEqual(replacements, [ - (re.compile(r'[xy]'), 'z'), - (re.compile(r'foo'), 'bar'), + (re.compile(ur'[xy]'), u'z'), + (re.compile(ur'foo'), u'bar'), ]) def test_cli_config_option(self): @@ -929,34 +928,34 @@ class ShowModelChangeTest(_common.TestCase): self.b.title = 'x' change, out = self._show() self.assertTrue(change) - self.assertTrue('title' in out) + self.assertTrue(u'title' in out) def test_int_fixed_field_change(self): self.b.track = 9 change, out = self._show() self.assertTrue(change) - self.assertTrue('track' in out) + self.assertTrue(u'track' in out) def test_floats_close_to_identical(self): self.a.length = 1.00001 self.b.length = 1.00005 change, out = self._show() self.assertFalse(change) - self.assertEqual(out, '') + self.assertEqual(out, u'') def test_floats_different(self): self.a.length = 1.00001 self.b.length = 2.00001 change, out = self._show() self.assertTrue(change) - self.assertTrue('length' in out) + self.assertTrue(u'length' in out) def test_both_values_shown(self): - self.a.title = 'foo' - self.b.title = 'bar' + self.a.title = u'foo' + self.b.title = u'bar' change, out = self._show() - self.assertTrue('foo' in out) - self.assertTrue('bar' in out) + self.assertTrue(u'foo' in out) + self.assertTrue(u'bar' in out) class ShowChangeTest(_common.TestCase): @@ -1014,12 +1013,12 @@ class ShowChangeTest(_common.TestCase): def test_album_data_change_with_unicode(self): msg = self._show_change(cur_artist=u'caf\xe9', cur_album=u'another album') - self.assertTrue('correcting tags from:' in msg) + self.assertTrue(u'correcting tags from:' in msg) def test_item_data_change_title_missing(self): self.items[0].title = u'' msg = re.sub(r' +', ' ', self._show_change()) - self.assertTrue('file.mp3 -> the title' in msg) + self.assertTrue(u'file.mp3 -> the title' in msg) def test_item_data_change_title_missing_with_unicode_filename(self): self.items[0].title = u'' @@ -1042,28 +1041,28 @@ class SummarizeItemsTest(_common.TestCase): def test_summarize_item(self): summary = commands.summarize_items([], True) - self.assertEqual(summary, "") + self.assertEqual(summary, u"") summary = commands.summarize_items([self.item], True) - self.assertEqual(summary, "F, 4kbps, 10:54, 987.0 B") + self.assertEqual(summary, u"F, 4kbps, 10:54, 987.0 B") def test_summarize_items(self): summary = commands.summarize_items([], False) - self.assertEqual(summary, "0 items") + self.assertEqual(summary, u"0 items") summary = commands.summarize_items([self.item], False) - self.assertEqual(summary, "1 items, F, 4kbps, 10:54, 987.0 B") + self.assertEqual(summary, u"1 items, F, 4kbps, 10:54, 987.0 B") i2 = deepcopy(self.item) summary = commands.summarize_items([self.item, i2], False) - self.assertEqual(summary, "2 items, F, 4kbps, 21:48, 1.9 KiB") + self.assertEqual(summary, u"2 items, F, 4kbps, 21:48, 1.9 KiB") i2.format = "G" summary = commands.summarize_items([self.item, i2], False) - self.assertEqual(summary, "2 items, F 1, G 1, 4kbps, 21:48, 1.9 KiB") + self.assertEqual(summary, u"2 items, F 1, G 1, 4kbps, 21:48, 1.9 KiB") summary = commands.summarize_items([self.item, i2, i2], False) - self.assertEqual(summary, "3 items, G 2, F 1, 4kbps, 32:42, 2.9 KiB") + self.assertEqual(summary, u"3 items, G 2, F 1, 4kbps, 32:42, 2.9 KiB") class PathFormatTest(_common.TestCase): @@ -1073,8 +1072,8 @@ class PathFormatTest(_common.TestCase): config['paths'] = {u'foo': u'bar'} pf = ui.get_path_formats() key, tmpl = pf[0] - self.assertEqual(key, 'foo') - self.assertEqual(tmpl.original, 'bar') + self.assertEqual(key, u'foo') + self.assertEqual(tmpl.original, u'bar') self.assertEqual(pf[1:], default_formats) @@ -1096,7 +1095,7 @@ class CompletionTest(_common.TestCase): # Tests run in bash cmd = os.environ.get('BEETS_TEST_SHELL', '/bin/bash --norc').split() if not has_program(cmd[0]): - self.skipTest('bash not available') + self.skipTest(u'bash not available') tester = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE) @@ -1106,12 +1105,12 @@ class CompletionTest(_common.TestCase): bash_completion = path break else: - self.skipTest('bash-completion script not found') + self.skipTest(u'bash-completion script not found') try: with open(util.syspath(bash_completion), 'r') as f: tester.stdin.writelines(f) except IOError: - self.skipTest('could not read bash-completion script') + self.skipTest(u'could not read bash-completion script') # Load completion script. self.io.install() @@ -1125,9 +1124,9 @@ class CompletionTest(_common.TestCase): with open(test_script, 'r') as test_script: tester.stdin.writelines(test_script) (out, err) = tester.communicate() - if tester.returncode != 0 or out != "completion tests passed\n": + if tester.returncode != 0 or out != u"completion tests passed\n": print(out) - self.fail('test/test_completion.sh did not execute properly') + self.fail(u'test/test_completion.sh did not execute properly') class CommonOptionsParserCliTest(unittest.TestCase, TestHelper): @@ -1146,56 +1145,57 @@ class CommonOptionsParserCliTest(unittest.TestCase, TestHelper): self.teardown_beets() def test_base(self): - l = self.run_with_output('ls') - self.assertEqual(l, 'the artist - the album - the title\n') + l = self.run_with_output(u'ls') + self.assertEqual(l, u'the artist - the album - the title\n') - l = self.run_with_output('ls', '-a') - self.assertEqual(l, 'the album artist - the album\n') + l = self.run_with_output(u'ls', u'-a') + self.assertEqual(l, u'the album artist - the album\n') def test_path_option(self): - l = self.run_with_output('ls', '-p') - self.assertEqual(l, 'xxx/yyy\n') + l = self.run_with_output(u'ls', u'-p') + self.assertEqual(l, u'xxx/yyy\n') - l = self.run_with_output('ls', '-a', '-p') - self.assertEqual(l, 'xxx\n') + l = self.run_with_output(u'ls', u'-a', u'-p') + self.assertEqual(l, u'xxx\n') def test_format_option(self): - l = self.run_with_output('ls', '-f', '$artist') - self.assertEqual(l, 'the artist\n') + l = self.run_with_output(u'ls', u'-f', '$artist') + self.assertEqual(l, u'the artist\n') - l = self.run_with_output('ls', '-a', '-f', '$albumartist') - self.assertEqual(l, 'the album artist\n') + l = self.run_with_output(u'ls', u'-a', u'-f', '$albumartist') + self.assertEqual(l, u'the album artist\n') def test_root_format_option(self): - l = self.run_with_output('--format-item', '$artist', - '--format-album', 'foo', 'ls') - self.assertEqual(l, 'the artist\n') + l = self.run_with_output(u'--format-item', u'$artist', + u'--format-album', u'foo', u'ls') + self.assertEqual(l, u'the artist\n') - l = self.run_with_output('--format-item', 'foo', - '--format-album', '$albumartist', 'ls', '-a') - self.assertEqual(l, 'the album artist\n') + l = self.run_with_output(u'--format-item', u'foo', + u'--format-album', u'$albumartist', + u'ls', u'-a') + self.assertEqual(l, u'the album artist\n') def test_help(self): - l = self.run_with_output('help') - self.assertIn('Usage:', l) + l = self.run_with_output(u'help') + self.assertIn(u'Usage:', l) - l = self.run_with_output('help', 'list') - self.assertIn('Usage:', l) + l = self.run_with_output(u'help', u'list') + self.assertIn(u'Usage:', l) with self.assertRaises(ui.UserError): - self.run_command('help', 'this.is.not.a.real.command') + self.run_command(u'help', u'this.is.not.a.real.command') def test_stats(self): - l = self.run_with_output('stats') - self.assertIn('Approximate total size:', l) + l = self.run_with_output(u'stats') + self.assertIn(u'Approximate total size:', l) # # Need to have more realistic library setup for this to work # l = self.run_with_output('stats', '-e') # self.assertIn('Total size:', l) def test_version(self): - l = self.run_with_output('version') - self.assertIn('no plugins loaded', l) + l = self.run_with_output(u'version') + self.assertIn(u'no plugins loaded', l) # # Need to have plugin loaded # l = self.run_with_output('version') @@ -1216,8 +1216,9 @@ class CommonOptionsParserTest(unittest.TestCase, TestHelper): self.assertTrue(bool(parser._album_flags)) self.assertEqual(parser.parse_args([]), ({'album': None}, [])) - self.assertEqual(parser.parse_args(['-a']), ({'album': True}, [])) - self.assertEqual(parser.parse_args(['--album']), ({'album': True}, [])) + self.assertEqual(parser.parse_args([u'-a']), ({'album': True}, [])) + self.assertEqual(parser.parse_args([u'--album']), + ({'album': True}, [])) def test_path_option(self): parser = ui.CommonOptionsParser() @@ -1228,13 +1229,13 @@ class CommonOptionsParserTest(unittest.TestCase, TestHelper): self.assertEqual(parser.parse_args([]), ({'path': None}, [])) self.assertEqual(config['format_item'].get(unicode), u'$foo') - self.assertEqual(parser.parse_args(['-p']), - ({'path': True, 'format': '$path'}, [])) + self.assertEqual(parser.parse_args([u'-p']), + ({'path': True, 'format': u'$path'}, [])) self.assertEqual(parser.parse_args(['--path']), - ({'path': True, 'format': '$path'}, [])) + ({'path': True, 'format': u'$path'}, [])) - self.assertEqual(config['format_item'].get(unicode), '$path') - self.assertEqual(config['format_album'].get(unicode), '$path') + self.assertEqual(config['format_item'].get(unicode), u'$path') + self.assertEqual(config['format_album'].get(unicode), u'$path') def test_format_option(self): parser = ui.CommonOptionsParser() @@ -1245,13 +1246,13 @@ class CommonOptionsParserTest(unittest.TestCase, TestHelper): self.assertEqual(parser.parse_args([]), ({'format': None}, [])) self.assertEqual(config['format_item'].get(unicode), u'$foo') - self.assertEqual(parser.parse_args(['-f', '$bar']), - ({'format': '$bar'}, [])) - self.assertEqual(parser.parse_args(['--format', '$baz']), - ({'format': '$baz'}, [])) + self.assertEqual(parser.parse_args([u'-f', u'$bar']), + ({'format': u'$bar'}, [])) + self.assertEqual(parser.parse_args([u'--format', u'$baz']), + ({'format': u'$baz'}, [])) - self.assertEqual(config['format_item'].get(unicode), '$baz') - self.assertEqual(config['format_album'].get(unicode), '$baz') + self.assertEqual(config['format_item'].get(unicode), u'$baz') + self.assertEqual(config['format_album'].get(unicode), u'$baz') def test_format_option_with_target(self): with self.assertRaises(KeyError): @@ -1263,11 +1264,11 @@ class CommonOptionsParserTest(unittest.TestCase, TestHelper): config['format_item'].set('$item') config['format_album'].set('$album') - self.assertEqual(parser.parse_args(['-f', '$bar']), - ({'format': '$bar'}, [])) + self.assertEqual(parser.parse_args([u'-f', u'$bar']), + ({'format': u'$bar'}, [])) - self.assertEqual(config['format_item'].get(unicode), '$bar') - self.assertEqual(config['format_album'].get(unicode), '$album') + self.assertEqual(config['format_item'].get(unicode), u'$bar') + self.assertEqual(config['format_album'].get(unicode), u'$album') def test_format_option_with_album(self): parser = ui.CommonOptionsParser() @@ -1277,16 +1278,16 @@ class CommonOptionsParserTest(unittest.TestCase, TestHelper): config['format_item'].set('$item') config['format_album'].set('$album') - parser.parse_args(['-f', '$bar']) - self.assertEqual(config['format_item'].get(unicode), '$bar') - self.assertEqual(config['format_album'].get(unicode), '$album') + parser.parse_args([u'-f', u'$bar']) + self.assertEqual(config['format_item'].get(unicode), u'$bar') + self.assertEqual(config['format_album'].get(unicode), u'$album') - parser.parse_args(['-a', '-f', '$foo']) - self.assertEqual(config['format_item'].get(unicode), '$bar') - self.assertEqual(config['format_album'].get(unicode), '$foo') + parser.parse_args([u'-a', u'-f', u'$foo']) + self.assertEqual(config['format_item'].get(unicode), u'$bar') + self.assertEqual(config['format_album'].get(unicode), u'$foo') - parser.parse_args(['-f', '$foo2', '-a']) - self.assertEqual(config['format_album'].get(unicode), '$foo2') + parser.parse_args([u'-f', u'$foo2', u'-a']) + self.assertEqual(config['format_album'].get(unicode), u'$foo2') def test_add_all_common_options(self): parser = ui.CommonOptionsParser() diff --git a/test/test_ui_importer.py b/test/test_ui_importer.py index 4f0de1c92..7dbf1f533 100644 --- a/test/test_ui_importer.py +++ b/test/test_ui_importer.py @@ -19,8 +19,7 @@ test_importer module. But here the test importer inherits from ``TerminalImportSession``. So we test this class, too. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from test._common import unittest, DummyIO from test import test_importer @@ -59,21 +58,21 @@ class TestTerminalImportSession(TerminalImportSession): choice = self.default_choice if choice == importer.action.APPLY: - self.io.addinput('A') + self.io.addinput(u'A') elif choice == importer.action.ASIS: - self.io.addinput('U') + self.io.addinput(u'U') elif choice == importer.action.ALBUMS: - self.io.addinput('G') + self.io.addinput(u'G') elif choice == importer.action.TRACKS: - self.io.addinput('T') + self.io.addinput(u'T') elif choice == importer.action.SKIP: - self.io.addinput('S') + self.io.addinput(u'S') elif isinstance(choice, int): - self.io.addinput('M') + self.io.addinput(u'M') self.io.addinput(unicode(choice)) self._add_choice_input() else: - raise Exception('Unknown choice %s' % choice) + raise Exception(u'Unknown choice %s' % choice) class TerminalImportSessionSetup(object): diff --git a/test/test_util.py b/test/test_util.py index 6d4707273..f6c42a2da 100644 --- a/test/test_util.py +++ b/test/test_util.py @@ -14,8 +14,7 @@ # included in all copies or substantial portions of the Software. """Tests for base utils from the beets.util package. """ -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import sys import re @@ -43,39 +42,39 @@ class UtilTest(unittest.TestCase): @patch('os.execlp') @patch('beets.util.open_anything') def test_interactive_open(self, mock_open, mock_execlp): - mock_open.return_value = 'tagada' + mock_open.return_value = u'tagada' util.interactive_open(['foo'], util.open_anything()) - mock_execlp.assert_called_once_with('tagada', 'tagada', 'foo') + mock_execlp.assert_called_once_with(u'tagada', u'tagada', u'foo') mock_execlp.reset_mock() - util.interactive_open(['foo'], 'bar') - mock_execlp.assert_called_once_with('bar', 'bar', 'foo') + util.interactive_open(['foo'], u'bar') + mock_execlp.assert_called_once_with(u'bar', u'bar', u'foo') def test_sanitize_unix_replaces_leading_dot(self): with _common.platform_posix(): p = util.sanitize_path(u'one/.two/three') - self.assertFalse('.' in p) + self.assertFalse(u'.' in p) def test_sanitize_windows_replaces_trailing_dot(self): with _common.platform_windows(): p = util.sanitize_path(u'one/two./three') - self.assertFalse('.' in p) + self.assertFalse(u'.' in p) def test_sanitize_windows_replaces_illegal_chars(self): with _common.platform_windows(): p = util.sanitize_path(u':*?"<>|') - self.assertFalse(':' in p) - self.assertFalse('*' in p) - self.assertFalse('?' in p) - self.assertFalse('"' in p) - self.assertFalse('<' in p) - self.assertFalse('>' in p) - self.assertFalse('|' in p) + self.assertFalse(u':' in p) + self.assertFalse(u'*' in p) + self.assertFalse(u'?' in p) + self.assertFalse(u'"' in p) + self.assertFalse(u'<' in p) + self.assertFalse(u'>' in p) + self.assertFalse(u'|' in p) def test_sanitize_windows_replaces_trailing_space(self): with _common.platform_windows(): p = util.sanitize_path(u'one/two /three') - self.assertFalse(' ' in p) + self.assertFalse(u' ' in p) def test_sanitize_path_works_on_empty_string(self): with _common.platform_posix(): @@ -96,7 +95,7 @@ class UtilTest(unittest.TestCase): ]) self.assertEqual(p, u'bar/bar') - @unittest.skip('unimplemented: #359') + @unittest.skip(u'unimplemented: #359') def test_sanitize_empty_component(self): with _common.platform_posix(): p = util.sanitize_path(u'foo//bar', [ @@ -108,7 +107,7 @@ class UtilTest(unittest.TestCase): def test_command_output(self, mock_popen): def popen_fail(*args, **kwargs): m = Mock(returncode=1) - m.communicate.return_value = 'foo', 'bar' + m.communicate.return_value = u'foo', u'bar' return m mock_popen.side_effect = popen_fail @@ -121,7 +120,7 @@ class UtilTest(unittest.TestCase): class PathConversionTest(_common.TestCase): def test_syspath_windows_format(self): with _common.platform_windows(): - path = os.path.join('a', 'b', 'c') + path = os.path.join(u'a', u'b', u'c') outpath = util.syspath(path) self.assertTrue(isinstance(outpath, unicode)) self.assertTrue(outpath.startswith(u'\\\\?\\')) @@ -137,7 +136,7 @@ class PathConversionTest(_common.TestCase): def test_syspath_posix_unchanged(self): with _common.platform_posix(): - path = os.path.join('a', 'b', 'c') + path = os.path.join(u'a', u'b', u'c') outpath = util.syspath(path) self.assertEqual(path, outpath) diff --git a/test/test_vfs.py b/test/test_vfs.py index e11e04780..6ffaa859d 100644 --- a/test/test_vfs.py +++ b/test/test_vfs.py @@ -14,8 +14,7 @@ # included in all copies or substantial portions of the Software. """Tests for the virtual filesystem builder..""" -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from test import _common from test._common import unittest @@ -27,8 +26,8 @@ class VFSTest(_common.TestCase): def setUp(self): super(VFSTest, self).setUp() self.lib = library.Library(':memory:', path_formats=[ - ('default', 'albums/$album/$title'), - ('singleton:true', 'tracks/$artist/$title'), + (u'default', u'albums/$album/$title'), + (u'singleton:true', u'tracks/$artist/$title'), ]) self.lib.add(_common.item()) self.lib.add_album([_common.item()]) diff --git a/test/test_web.py b/test/test_web.py index 0299e82d4..51f32567d 100644 --- a/test/test_web.py +++ b/test/test_web.py @@ -2,8 +2,7 @@ """Tests for the 'web' plugin""" -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from test._common import unittest from test import _common @@ -22,10 +21,10 @@ class WebPluginTest(_common.LibTestCase): # Add fixtures for track in self.lib.items(): track.remove() - self.lib.add(Item(title='title', path='', id=1)) - self.lib.add(Item(title='another title', path='', id=2)) - self.lib.add(Album(album='album', id=3)) - self.lib.add(Album(album='another album', id=4)) + self.lib.add(Item(title=u'title', path='', id=1)) + self.lib.add(Item(title=u'another title', path='', id=2)) + self.lib.add(Album(album=u'album', id=3)) + self.lib.add(Album(album=u'another album', id=4)) web.app.config['TESTING'] = True web.app.config['lib'] = self.lib @@ -44,7 +43,7 @@ class WebPluginTest(_common.LibTestCase): self.assertEqual(response.status_code, 200) self.assertEqual(response.json['id'], 1) - self.assertEqual(response.json['title'], 'title') + self.assertEqual(response.json['title'], u'title') def test_get_multiple_items_by_id(self): response = self.client.get('/item/1,2') @@ -53,7 +52,7 @@ class WebPluginTest(_common.LibTestCase): self.assertEqual(response.status_code, 200) self.assertEqual(len(response.json['items']), 2) response_titles = [item['title'] for item in response.json['items']] - self.assertItemsEqual(response_titles, ['title', 'another title']) + self.assertItemsEqual(response_titles, [u'title', u'another title']) def test_get_single_item_not_found(self): response = self.client.get('/item/3') @@ -72,7 +71,8 @@ class WebPluginTest(_common.LibTestCase): self.assertEqual(response.status_code, 200) self.assertEqual(len(response.json['results']), 1) - self.assertEqual(response.json['results'][0]['title'], 'another title') + self.assertEqual(response.json['results'][0]['title'], + u'another title') def test_get_all_albums(self): response = self.client.get('/album/') @@ -80,7 +80,7 @@ class WebPluginTest(_common.LibTestCase): self.assertEqual(response.status_code, 200) response_albums = [album['album'] for album in response.json['albums']] - self.assertItemsEqual(response_albums, ['album', 'another album']) + self.assertItemsEqual(response_albums, [u'album', u'another album']) def test_get_single_album_by_id(self): response = self.client.get('/album/2') @@ -88,7 +88,7 @@ class WebPluginTest(_common.LibTestCase): self.assertEqual(response.status_code, 200) self.assertEqual(response.json['id'], 2) - self.assertEqual(response.json['album'], 'another album') + self.assertEqual(response.json['album'], u'another album') def test_get_multiple_albums_by_id(self): response = self.client.get('/album/1,2') @@ -96,7 +96,7 @@ class WebPluginTest(_common.LibTestCase): self.assertEqual(response.status_code, 200) response_albums = [album['album'] for album in response.json['albums']] - self.assertItemsEqual(response_albums, ['album', 'another album']) + self.assertItemsEqual(response_albums, [u'album', u'another album']) def test_get_album_empty_query(self): response = self.client.get('/album/query/') diff --git a/test/test_zero.py b/test/test_zero.py index 623a7801b..e223dd787 100644 --- a/test/test_zero.py +++ b/test/test_zero.py @@ -2,8 +2,7 @@ """Tests for the 'zero' plugin""" -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function from test._common import unittest from test.helper import TestHelper @@ -24,7 +23,7 @@ class ZeroPluginTest(unittest.TestCase, TestHelper): def test_no_patterns(self): tags = { - 'comments': 'test comment', + 'comments': u'test comment', 'day': 13, 'month': 3, 'year': 2012, @@ -32,9 +31,9 @@ class ZeroPluginTest(unittest.TestCase, TestHelper): z = ZeroPlugin() z.debug = False z.fields = ['comments', 'month', 'day'] - z.patterns = {'comments': ['.'], - 'month': ['.'], - 'day': ['.']} + z.patterns = {'comments': [u'.'], + 'month': [u'.'], + 'day': [u'.']} z.write_event(None, None, tags) self.assertEqual(tags['comments'], None) self.assertEqual(tags['day'], None) @@ -45,11 +44,11 @@ class ZeroPluginTest(unittest.TestCase, TestHelper): z = ZeroPlugin() z.debug = False z.fields = ['comments', 'year'] - z.patterns = {'comments': 'eac lame'.split(), - 'year': '2098 2099'.split()} + z.patterns = {'comments': u'eac lame'.split(), + 'year': u'2098 2099'.split()} tags = { - 'comments': 'from lame collection, ripped by eac', + 'comments': u'from lame collection, ripped by eac', 'year': 2012, } z.write_event(None, None, tags) @@ -97,7 +96,7 @@ class ZeroPluginTest(unittest.TestCase, TestHelper): self.assertEqual(2000, mediafile.year) config['zero'] = { - 'fields': ['year'], + 'fields': [u'year'], 'update_database': True, } self.load_plugins('zero') @@ -114,7 +113,7 @@ class ZeroPluginTest(unittest.TestCase, TestHelper): mediafile = MediaFile(item.path) self.assertNotEqual(0, len(mediafile.images)) - config['zero'] = {'fields': ['images']} + config['zero'] = {'fields': [u'images']} self.load_plugins('zero') item.write() diff --git a/test/testall.py b/test/testall.py index fa556e364..68475e379 100755 --- a/test/testall.py +++ b/test/testall.py @@ -15,8 +15,7 @@ # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. -from __future__ import (division, absolute_import, print_function, - unicode_literals) +from __future__ import division, absolute_import, print_function import os import re