bytestring normalization

Make sure many/most strings that touch the filesystem are
converted explicitly to bytestrings rather than implictly.
This commit is contained in:
Johnny Robeson 2016-06-10 05:39:31 -04:00
parent 6745759ea5
commit ffa46a185c
21 changed files with 380 additions and 353 deletions

View file

@ -1439,8 +1439,8 @@ def group_albums(session):
task = pipeline.multiple(tasks)
MULTIDISC_MARKERS = (r'dis[ck]', r'cd')
MULTIDISC_PAT_FMT = r'^(.*%s[\W_]*)\d'
MULTIDISC_MARKERS = (br'dis[ck]', br'cd')
MULTIDISC_PAT_FMT = br'^(.*%s[\W_]*)\d'
def albums_in_dir(path):
@ -1483,7 +1483,9 @@ def albums_in_dir(path):
# named in this way.
start_collapsing = False
for marker in MULTIDISC_MARKERS:
marker_pat = re.compile(MULTIDISC_PAT_FMT % marker, re.I)
# We're using replace on %s due to lack of .format() on bytestrings
p = MULTIDISC_PAT_FMT.replace(b'%s', marker)
marker_pat = re.compile(p, re.I)
match = marker_pat.match(os.path.basename(root))
# Is this directory the root of a nested multi-disc album?
@ -1497,8 +1499,10 @@ def albums_in_dir(path):
if not subdir_pat:
match = marker_pat.match(subdir)
if match:
match_group = re.escape(match.group(1))
subdir_pat = re.compile(
br'^%s\d' % re.escape(match.group(1)), re.I
b''.join([b'^', match_group, br'\d']),
re.I
)
else:
start_collapsing = False
@ -1520,7 +1524,8 @@ def albums_in_dir(path):
# Set the current pattern to match directories with the same
# prefix as this one, followed by a digit.
collapse_pat = re.compile(
br'^%s\d' % re.escape(match.group(1)), re.I
b''.join([b'^', re.escape(match.group(1)), br'\d']),
re.I
)
break

View file

@ -48,7 +48,7 @@ class PathQuery(dbcore.FieldQuery):
and case-sensitive otherwise.
"""
escape_re = re.compile(r'[\\_%]')
escape_re = re.compile(br'[\\_%]')
escape_char = b'\\'
def __init__(self, field, pattern, fast=True, case_sensitive=None):

View file

@ -177,7 +177,7 @@ class TestHelper(object):
self.config['ui']['color'] = False
self.config['threaded'] = False
self.libdir = os.path.join(self.temp_dir, 'libdir')
self.libdir = os.path.join(self.temp_dir, b'libdir')
os.mkdir(self.libdir)
self.config['directory'] = self.libdir
@ -227,13 +227,13 @@ class TestHelper(object):
Copies the specified number of files to a subdirectory of
`self.temp_dir` and creates a `TestImportSession` for this path.
"""
import_dir = os.path.join(self.temp_dir, 'import')
import_dir = os.path.join(self.temp_dir, b'import')
if not os.path.isdir(import_dir):
os.mkdir(import_dir)
album_no = 0
while album_count:
album = u'album {0}'.format(album_no)
album = util.bytestring_path(u'album {0}'.format(album_no))
album_dir = os.path.join(import_dir, album)
if os.path.exists(album_dir):
album_no += 1
@ -245,8 +245,9 @@ class TestHelper(object):
album_item_count = item_count
while album_item_count:
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))
src = os.path.join(_common.RSRC, b'full.mp3')
title_file = util.bytestring_path('{0}.mp3'.format(title))
dest = os.path.join(album_dir, title_file)
if os.path.exists(dest):
track_no += 1
continue
@ -342,7 +343,7 @@ class TestHelper(object):
"""
# TODO base this on `add_item()`
items = []
path = os.path.join(_common.RSRC, 'full.' + ext)
path = os.path.join(_common.RSRC, b'full.' + ext)
for i in range(count):
item = Item.from_path(bytes(path))
item.album = u'\u00e4lbum {0}'.format(i) # Check unicode paths
@ -388,8 +389,8 @@ class TestHelper(object):
mediafile = MediaFile(path)
imgs = []
for img_ext in images:
img_path = os.path.join(_common.RSRC,
'image-2x3.{0}'.format(img_ext))
file = util.bytestring_path('image-2x3.{0}'.format(img_ext))
img_path = os.path.join(_common.RSRC, file)
with open(img_path, 'rb') as f:
imgs.append(Image(f.read()))
mediafile.images = imgs

View file

@ -58,7 +58,7 @@ class FetchImageTest(UseThePlugin):
def setUp(self):
super(FetchImageTest, self).setUp()
self.dpath = os.path.join(self.temp_dir, 'arttest')
self.dpath = os.path.join(self.temp_dir, b'arttest')
self.source = fetchart.RemoteArtSource(logger, self.plugin.config)
self.extra = {'maxwidth': 0}
@ -78,7 +78,7 @@ class FetchImageTest(UseThePlugin):
class FSArtTest(UseThePlugin):
def setUp(self):
super(FSArtTest, self).setUp()
self.dpath = os.path.join(self.temp_dir, 'arttest')
self.dpath = os.path.join(self.temp_dir, b'arttest')
os.mkdir(self.dpath)
self.source = fetchart.FileSystem(logger, self.plugin.config)
@ -87,23 +87,23 @@ class FSArtTest(UseThePlugin):
'paths': [self.dpath]}
def test_finds_jpg_in_directory(self):
_common.touch(os.path.join(self.dpath, 'a.jpg'))
_common.touch(os.path.join(self.dpath, b'a.jpg'))
candidate = next(self.source.get(None, self.extra))
self.assertEqual(candidate.path, os.path.join(self.dpath, 'a.jpg'))
self.assertEqual(candidate.path, os.path.join(self.dpath, b'a.jpg'))
def test_appropriately_named_file_takes_precedence(self):
_common.touch(os.path.join(self.dpath, 'a.jpg'))
_common.touch(os.path.join(self.dpath, 'art.jpg'))
_common.touch(os.path.join(self.dpath, b'a.jpg'))
_common.touch(os.path.join(self.dpath, b'art.jpg'))
candidate = next(self.source.get(None, self.extra))
self.assertEqual(candidate.path, os.path.join(self.dpath, 'art.jpg'))
self.assertEqual(candidate.path, os.path.join(self.dpath, b'art.jpg'))
def test_non_image_file_not_identified(self):
_common.touch(os.path.join(self.dpath, 'a.txt'))
_common.touch(os.path.join(self.dpath, b'a.txt'))
with self.assertRaises(StopIteration):
next(self.source.get(None, self.extra))
def test_cautious_skips_fallback(self):
_common.touch(os.path.join(self.dpath, 'a.jpg'))
_common.touch(os.path.join(self.dpath, b'a.jpg'))
self.extra['cautious'] = True
with self.assertRaises(StopIteration):
next(self.source.get(None, self.extra))
@ -135,7 +135,7 @@ class CombinedTest(UseThePlugin):
def setUp(self):
super(CombinedTest, self).setUp()
self.dpath = os.path.join(self.temp_dir, 'arttest')
self.dpath = os.path.join(self.temp_dir, b'arttest')
os.mkdir(self.dpath)
@responses.activate
@ -157,12 +157,12 @@ class CombinedTest(UseThePlugin):
self.assertIsNone(candidate)
def test_main_interface_gives_precedence_to_fs_art(self):
_common.touch(os.path.join(self.dpath, 'art.jpg'))
_common.touch(os.path.join(self.dpath, b'art.jpg'))
self.mock_response(self.AMAZON_URL)
album = _common.Bag(asin=self.ASIN)
candidate = self.plugin.art_for_album(album, [self.dpath])
self.assertIsNotNone(candidate)
self.assertEqual(candidate.path, os.path.join(self.dpath, 'art.jpg'))
self.assertEqual(candidate.path, os.path.join(self.dpath, b'art.jpg'))
def test_main_interface_falls_back_to_amazon(self):
self.mock_response(self.AMAZON_URL)
@ -198,12 +198,12 @@ class CombinedTest(UseThePlugin):
self.assertEqual(len(responses.calls), 0)
def test_local_only_gets_fs_image(self):
_common.touch(os.path.join(self.dpath, 'art.jpg'))
_common.touch(os.path.join(self.dpath, b'art.jpg'))
album = _common.Bag(mb_albumid=self.MBID, asin=self.ASIN)
candidate = self.plugin.art_for_album(album, [self.dpath],
local_only=True)
self.assertIsNotNone(candidate)
self.assertEqual(candidate.path, os.path.join(self.dpath, 'art.jpg'))
self.assertEqual(candidate.path, os.path.join(self.dpath, b'art.jpg'))
self.assertEqual(len(responses.calls), 0)
@ -387,7 +387,7 @@ class ArtImporterTest(UseThePlugin):
super(ArtImporterTest, self).setUp()
# Mock the album art fetcher to always return our test file.
self.art_file = os.path.join(self.temp_dir, 'tmpcover.jpg')
self.art_file = os.path.join(self.temp_dir, b'tmpcover.jpg')
_common.touch(self.art_file)
self.old_afa = self.plugin.art_for_album
self.afa_response = fetchart.Candidate(logger, path=self.art_file)
@ -401,9 +401,9 @@ class ArtImporterTest(UseThePlugin):
self.libpath = os.path.join(self.temp_dir, 'tmplib.blb')
self.libdir = os.path.join(self.temp_dir, 'tmplib')
os.mkdir(self.libdir)
os.mkdir(os.path.join(self.libdir, 'album'))
itempath = os.path.join(self.libdir, 'album', 'test.mp3')
shutil.copyfile(os.path.join(_common.RSRC, 'full.mp3'), itempath)
os.mkdir(os.path.join(self.libdir, b'album'))
itempath = os.path.join(self.libdir, b'album', b'test.mp3')
shutil.copyfile(os.path.join(_common.RSRC, b'full.mp3'), itempath)
self.lib = library.Library(self.libpath)
self.i = _common.item()
self.i.path = itempath
@ -445,7 +445,7 @@ class ArtImporterTest(UseThePlugin):
if should_exist:
self.assertEqual(
artpath,
os.path.join(os.path.dirname(self.i.path), 'cover.jpg')
os.path.join(os.path.dirname(self.i.path), b'cover.jpg')
)
self.assertExists(artpath)
else:
@ -474,7 +474,7 @@ class ArtImporterTest(UseThePlugin):
self.assertNotExists(self.art_file)
def test_do_not_delete_original_if_already_in_place(self):
artdest = os.path.join(os.path.dirname(self.i.path), 'cover.jpg')
artdest = os.path.join(os.path.dirname(self.i.path), b'cover.jpg')
shutil.copyfile(self.art_file, artdest)
self.afa_response = fetchart.Candidate(logger, path=artdest)
self._fetch_art(True)
@ -497,9 +497,9 @@ class ArtForAlbumTest(UseThePlugin):
configuration (e.g., minwidth, enforce_ratio)
"""
IMG_225x225 = os.path.join(_common.RSRC, 'abbey.jpg')
IMG_348x348 = os.path.join(_common.RSRC, 'abbey-different.jpg')
IMG_500x490 = os.path.join(_common.RSRC, 'abbey-similar.jpg')
IMG_225x225 = os.path.join(_common.RSRC, b'abbey.jpg')
IMG_348x348 = os.path.join(_common.RSRC, b'abbey-different.jpg')
IMG_500x490 = os.path.join(_common.RSRC, b'abbey-similar.jpg')
def setUp(self):
super(ArtForAlbumTest, self).setUp()

View file

@ -38,7 +38,7 @@ class TestHelper(helper.TestHelper):
.format(tag))
# A Python script that copies the file and appends a tag.
stub = os.path.join(_common.RSRC, 'convert_stub.py')
stub = os.path.join(_common.RSRC, b'convert_stub.py').decode('utf-8')
return u"python '{}' $source $dest {}".format(stub, tag)
def assertFileTag(self, path, tag): # noqa
@ -75,7 +75,7 @@ class ImportConvertTest(unittest.TestCase, TestHelper):
self.load_plugins('convert')
self.config['convert'] = {
'dest': os.path.join(self.temp_dir, 'convert'),
'dest': os.path.join(self.temp_dir, b'convert'),
'command': self.tagged_copy_cmd('convert'),
# Enforce running convert
'max_bitrate': 1,
@ -130,7 +130,7 @@ class ConvertCliTest(unittest.TestCase, TestHelper, ConvertCommand):
self.load_plugins('convert')
self.convert_dest = util.bytestring_path(
os.path.join(self.temp_dir, 'convert_dest')
os.path.join(self.temp_dir, b'convert_dest')
)
self.config['convert'] = {
'dest': self.convert_dest,
@ -152,38 +152,38 @@ class ConvertCliTest(unittest.TestCase, TestHelper, ConvertCommand):
def test_convert(self):
with control_stdin('y'):
self.run_convert()
converted = os.path.join(self.convert_dest, 'converted.mp3')
converted = os.path.join(self.convert_dest, b'converted.mp3')
self.assertFileTag(converted, 'mp3')
def test_convert_with_auto_confirmation(self):
self.run_convert('--yes')
converted = os.path.join(self.convert_dest, 'converted.mp3')
converted = os.path.join(self.convert_dest, b'converted.mp3')
self.assertFileTag(converted, 'mp3')
def test_rejecet_confirmation(self):
with control_stdin('n'):
self.run_convert()
converted = os.path.join(self.convert_dest, 'converted.mp3')
converted = os.path.join(self.convert_dest, b'converted.mp3')
self.assertFalse(os.path.isfile(converted))
def test_convert_keep_new(self):
self.assertEqual(os.path.splitext(self.item.path)[1], '.ogg')
self.assertEqual(os.path.splitext(self.item.path)[1], b'.ogg')
with control_stdin('y'):
self.run_convert('--keep-new')
self.item.load()
self.assertEqual(os.path.splitext(self.item.path)[1], '.mp3')
self.assertEqual(os.path.splitext(self.item.path)[1], b'.mp3')
def test_format_option(self):
with control_stdin('y'):
self.run_convert('--format', 'opus')
converted = os.path.join(self.convert_dest, 'converted.ops')
converted = os.path.join(self.convert_dest, b'converted.ops')
self.assertFileTag(converted, 'opus')
def test_embed_album_art(self):
self.config['convert']['embed'] = True
image_path = os.path.join(_common.RSRC, 'image-2x3.jpg')
image_path = os.path.join(_common.RSRC, b'image-2x3.jpg')
self.album.artpath = image_path
self.album.store()
with open(os.path.join(image_path), 'rb') as f:
@ -191,12 +191,12 @@ class ConvertCliTest(unittest.TestCase, TestHelper, ConvertCommand):
with control_stdin('y'):
self.run_convert()
converted = os.path.join(self.convert_dest, 'converted.mp3')
converted = os.path.join(self.convert_dest, b'converted.mp3')
mediafile = MediaFile(converted)
self.assertEqual(mediafile.images[0].data, image_data)
def test_skip_existing(self):
converted = os.path.join(self.convert_dest, 'converted.mp3')
converted = os.path.join(self.convert_dest, b'converted.mp3')
self.touch(converted, content='XXX')
self.run_convert('--yes')
with open(converted, 'r') as f:
@ -204,7 +204,7 @@ class ConvertCliTest(unittest.TestCase, TestHelper, ConvertCommand):
def test_pretend(self):
self.run_convert('--pretend')
converted = os.path.join(self.convert_dest, 'converted.mp3')
converted = os.path.join(self.convert_dest, b'converted.mp3')
self.assertFalse(os.path.exists(converted))
@ -218,7 +218,7 @@ class NeverConvertLossyFilesTest(unittest.TestCase, TestHelper,
self.setup_beets(disk=True) # Converter is threaded
self.load_plugins('convert')
self.convert_dest = os.path.join(self.temp_dir, 'convert_dest')
self.convert_dest = os.path.join(self.temp_dir, b'convert_dest')
self.config['convert'] = {
'dest': self.convert_dest,
'paths': {'default': 'converted'},
@ -237,7 +237,7 @@ class NeverConvertLossyFilesTest(unittest.TestCase, TestHelper,
[item] = self.add_item_fixtures(ext='flac')
with control_stdin('y'):
self.run_convert_path(item.path)
converted = os.path.join(self.convert_dest, 'converted.mp3')
converted = os.path.join(self.convert_dest, b'converted.mp3')
self.assertFileTag(converted, 'mp3')
def test_transcode_from_lossy(self):
@ -245,14 +245,14 @@ class NeverConvertLossyFilesTest(unittest.TestCase, TestHelper,
[item] = self.add_item_fixtures(ext='ogg')
with control_stdin('y'):
self.run_convert_path(item.path)
converted = os.path.join(self.convert_dest, 'converted.mp3')
converted = os.path.join(self.convert_dest, b'converted.mp3')
self.assertFileTag(converted, 'mp3')
def test_transcode_from_lossy_prevented(self):
[item] = self.add_item_fixtures(ext='ogg')
with control_stdin('y'):
self.run_convert_path(item.path)
converted = os.path.join(self.convert_dest, 'converted.ogg')
converted = os.path.join(self.convert_dest, b'converted.ogg')
self.assertNoFileTag(converted, 'mp3')

View file

@ -153,7 +153,7 @@ class EmbedartCliTest(_common.TestCase, TestHelper):
self.abbey_similarpath))
def test_non_ascii_album_path(self):
resource_path = os.path.join(_common.RSRC, 'image.mp3').encode('utf8')
resource_path = os.path.join(_common.RSRC, b'image.mp3')
album = self.add_album_fixture()
trackpath = album.items()[0].path
albumpath = album.path

View file

@ -27,7 +27,7 @@ from test.helper import capture_log
from test.test_importer import ImportHelper
from beets import config
from beets.mediafile import MediaFile
from beets.util import displayable_path
from beets.util import displayable_path, bytestring_path
from beetsplug.filefilter import FileFilterPlugin
@ -43,7 +43,7 @@ class FileFilterPluginTest(unittest.TestCase, ImportHelper):
def __copy_file(self, dest_path, metadata):
# Copy files
resource_path = os.path.join(_common.RSRC, 'full.mp3')
resource_path = os.path.join(_common.RSRC, b'full.mp3')
shutil.copy(resource_path, dest_path)
medium = MediaFile(dest_path)
# Set metadata
@ -52,13 +52,13 @@ class FileFilterPluginTest(unittest.TestCase, ImportHelper):
medium.save()
def __create_import_dir(self, count):
self.import_dir = os.path.join(self.temp_dir, 'testsrcdir')
self.import_dir = os.path.join(self.temp_dir, b'testsrcdir')
if os.path.isdir(self.import_dir):
shutil.rmtree(self.import_dir)
self.artist_path = os.path.join(self.import_dir, 'artist')
self.album_path = os.path.join(self.artist_path, 'album')
self.misc_path = os.path.join(self.import_dir, 'misc')
self.artist_path = os.path.join(self.import_dir, b'artist')
self.album_path = os.path.join(self.artist_path, b'album')
self.misc_path = os.path.join(self.import_dir, b'misc')
os.makedirs(self.album_path)
os.makedirs(self.misc_path)
@ -74,8 +74,8 @@ class FileFilterPluginTest(unittest.TestCase, ImportHelper):
for i in range(count):
metadata['track'] = i + 1
metadata['title'] = 'Tag Title Album %d' % (i + 1)
dest_path = os.path.join(self.album_path,
'%02d - track.mp3' % (i + 1))
track_file = bytestring_path('%02d - track.mp3' % (i + 1))
dest_path = os.path.join(self.album_path, track_file)
self.__copy_file(dest_path, metadata)
self.album_paths.append(dest_path)
@ -84,8 +84,8 @@ class FileFilterPluginTest(unittest.TestCase, ImportHelper):
for i in range(count):
metadata['track'] = i + 10
metadata['title'] = 'Tag Title Artist %d' % (i + 1)
dest_path = os.path.join(self.artist_path,
'track_%d.mp3' % (i + 1))
track_file = bytestring_path('track_%d.mp3' % (i + 1))
dest_path = os.path.join(self.artist_path, track_file)
self.__copy_file(dest_path, metadata)
self.artist_paths.append(dest_path)
@ -94,7 +94,8 @@ class FileFilterPluginTest(unittest.TestCase, ImportHelper):
metadata['artist'] = 'Artist %d' % (i + 42)
metadata['track'] = i + 5
metadata['title'] = 'Tag Title Misc %d' % (i + 1)
dest_path = os.path.join(self.misc_path, 'track_%d.mp3' % (i + 1))
track_file = bytestring_path('track_%d.mp3' % (i + 1))
dest_path = os.path.join(self.misc_path, track_file)
self.__copy_file(dest_path, metadata)
self.misc_paths.append(dest_path)

View file

@ -34,8 +34,8 @@ class MoveTest(_common.TestCase):
super(MoveTest, self).setUp()
# make a temporary file
self.path = join(self.temp_dir, 'temp.mp3')
shutil.copy(join(_common.RSRC, 'full.mp3'), self.path)
self.path = join(self.temp_dir, b'temp.mp3')
shutil.copy(join(_common.RSRC, b'full.mp3'), self.path)
# add it to a temporary library
self.lib = beets.library.Library(':memory:')
@ -43,7 +43,7 @@ class MoveTest(_common.TestCase):
self.lib.add(self.i)
# set up the destination
self.libdir = join(self.temp_dir, 'testlibdir')
self.libdir = join(self.temp_dir, b'testlibdir')
os.mkdir(self.libdir)
self.lib.directory = self.libdir
self.lib.path_formats = [('default',
@ -51,9 +51,9 @@ class MoveTest(_common.TestCase):
self.i.artist = 'one'
self.i.album = 'two'
self.i.title = 'three'
self.dest = join(self.libdir, 'one', 'two', 'three.mp3')
self.dest = join(self.libdir, b'one', b'two', b'three.mp3')
self.otherdir = join(self.temp_dir, 'testotherdir')
self.otherdir = join(self.temp_dir, b'testotherdir')
def test_move_arrives(self):
self.i.move()
@ -61,7 +61,7 @@ class MoveTest(_common.TestCase):
def test_move_to_custom_dir(self):
self.i.move(basedir=self.otherdir)
self.assertExists(join(self.otherdir, 'one', 'two', 'three.mp3'))
self.assertExists(join(self.otherdir, b'one', b'two', b'three.mp3'))
def test_move_departs(self):
self.i.move()
@ -182,7 +182,7 @@ class AlbumFileTest(_common.TestCase):
self.lib = beets.library.Library(':memory:')
self.lib.path_formats = \
[('default', join('$albumartist', '$album', '$title'))]
self.libdir = os.path.join(self.temp_dir, 'testlibdir')
self.libdir = os.path.join(self.temp_dir, b'testlibdir')
self.lib.directory = self.libdir
self.i = item(self.lib)
# Make a file for the item.
@ -192,7 +192,7 @@ class AlbumFileTest(_common.TestCase):
# Make an album.
self.ai = self.lib.add_album((self.i,))
# Alternate destination dir.
self.otherdir = os.path.join(self.temp_dir, 'testotherdir')
self.otherdir = os.path.join(self.temp_dir, b'testotherdir')
def test_albuminfo_move_changes_paths(self):
self.ai.album = u'newAlbumName'
@ -200,7 +200,7 @@ class AlbumFileTest(_common.TestCase):
self.ai.store()
self.i.load()
self.assertTrue('newAlbumName' in self.i.path)
self.assertTrue(b'newAlbumName' in self.i.path)
def test_albuminfo_move_moves_file(self):
oldpath = self.i.path
@ -226,7 +226,7 @@ class AlbumFileTest(_common.TestCase):
self.ai.move(basedir=self.otherdir)
self.i.load()
self.ai.store()
self.assertTrue('testotherdir' in self.i.path)
self.assertTrue(b'testotherdir' in self.i.path)
class ArtFileTest(_common.TestCase):
@ -235,7 +235,7 @@ class ArtFileTest(_common.TestCase):
# Make library and item.
self.lib = beets.library.Library(':memory:')
self.libdir = os.path.join(self.temp_dir, 'testlibdir')
self.libdir = os.path.join(self.temp_dir, b'testlibdir')
self.lib.directory = self.libdir
self.i = item(self.lib)
self.i.path = self.i.destination()
@ -250,7 +250,7 @@ class ArtFileTest(_common.TestCase):
self.ai.artpath = self.art
self.ai.store()
# Alternate destination dir.
self.otherdir = os.path.join(self.temp_dir, 'testotherdir')
self.otherdir = os.path.join(self.temp_dir, b'testotherdir')
def test_art_deleted_when_items_deleted(self):
self.assertTrue(os.path.exists(self.art))
@ -279,12 +279,12 @@ class ArtFileTest(_common.TestCase):
self.assertNotExists(self.art)
newart = self.lib.get_album(self.i).artpath
self.assertExists(newart)
self.assertTrue('testotherdir' in newart)
self.assertTrue(b'testotherdir' in newart)
def test_setart_copies_image(self):
os.remove(self.art)
newart = os.path.join(self.libdir, 'newart.jpg')
newart = os.path.join(self.libdir, b'newart.jpg')
touch(newart)
i2 = item()
i2.path = self.i.path
@ -300,7 +300,7 @@ class ArtFileTest(_common.TestCase):
os.remove(self.art)
# Original art.
newart = os.path.join(self.libdir, 'newart.jpg')
newart = os.path.join(self.libdir, b'newart.jpg')
touch(newart)
i2 = item()
i2.path = self.i.path
@ -314,7 +314,7 @@ class ArtFileTest(_common.TestCase):
self.assertTrue(os.path.exists(ai.artpath))
def test_setart_to_existing_but_unset_art_works(self):
newart = os.path.join(self.libdir, 'newart.jpg')
newart = os.path.join(self.libdir, b'newart.jpg')
touch(newart)
i2 = item()
i2.path = self.i.path
@ -331,7 +331,7 @@ class ArtFileTest(_common.TestCase):
self.assertTrue(os.path.exists(ai.artpath))
def test_setart_to_conflicting_file_gets_new_path(self):
newart = os.path.join(self.libdir, 'newart.jpg')
newart = os.path.join(self.libdir, b'newart.jpg')
touch(newart)
i2 = item()
i2.path = self.i.path
@ -352,7 +352,7 @@ class ArtFileTest(_common.TestCase):
def test_setart_sets_permissions(self):
os.remove(self.art)
newart = os.path.join(self.libdir, 'newart.jpg')
newart = os.path.join(self.libdir, b'newart.jpg')
touch(newart)
os.chmod(newart, 0o400) # read-only
@ -382,7 +382,7 @@ class ArtFileTest(_common.TestCase):
self.ai.items()[0].move()
artpath = self.lib.albums()[0].artpath
self.assertTrue(u'different_album' in artpath)
self.assertTrue(b'different_album' in artpath)
self.assertExists(artpath)
self.assertNotExists(oldartpath)
@ -399,7 +399,7 @@ class ArtFileTest(_common.TestCase):
self.i.move()
artpath = self.lib.albums()[0].artpath
self.assertFalse(u'different_album' in artpath)
self.assertFalse(b'different_album' in artpath)
self.assertEqual(artpath, oldartpath)
self.assertExists(oldartpath)
@ -410,7 +410,7 @@ class RemoveTest(_common.TestCase):
# Make library and item.
self.lib = beets.library.Library(':memory:')
self.libdir = os.path.join(self.temp_dir, 'testlibdir')
self.libdir = os.path.join(self.temp_dir, b'testlibdir')
self.lib.directory = self.libdir
self.i = item(self.lib)
self.i.path = self.i.destination()
@ -428,13 +428,13 @@ class RemoveTest(_common.TestCase):
def test_removing_last_item_preserves_nonempty_dir(self):
parent = os.path.dirname(self.i.path)
touch(os.path.join(parent, 'dummy.txt'))
touch(os.path.join(parent, b'dummy.txt'))
self.i.remove(True)
self.assertExists(parent)
def test_removing_last_item_prunes_dir_with_blacklisted_file(self):
parent = os.path.dirname(self.i.path)
touch(os.path.join(parent, '.DS_Store'))
touch(os.path.join(parent, b'.DS_Store'))
self.i.remove(True)
self.assertNotExists(parent)
@ -448,13 +448,13 @@ class RemoveTest(_common.TestCase):
self.assertExists(self.libdir)
def test_removing_item_outside_of_library_deletes_nothing(self):
self.lib.directory = os.path.join(self.temp_dir, 'xxx')
self.lib.directory = os.path.join(self.temp_dir, b'xxx')
parent = os.path.dirname(self.i.path)
self.i.remove(True)
self.assertExists(parent)
def test_removing_last_item_in_album_with_albumart_prunes_dir(self):
artfile = os.path.join(self.temp_dir, 'testart.jpg')
artfile = os.path.join(self.temp_dir, b'testart.jpg')
touch(artfile)
self.ai.set_art(artfile)
self.ai.store()
@ -469,7 +469,7 @@ class SoftRemoveTest(_common.TestCase):
def setUp(self):
super(SoftRemoveTest, self).setUp()
self.path = os.path.join(self.temp_dir, 'testfile')
self.path = os.path.join(self.temp_dir, b'testfile')
touch(self.path)
def test_soft_remove_deletes_file(self):
@ -478,7 +478,7 @@ class SoftRemoveTest(_common.TestCase):
def test_soft_remove_silent_on_no_file(self):
try:
util.remove(self.path + 'XXX', True)
util.remove(self.path + b'XXX', True)
except OSError:
self.fail(u'OSError when removing path')
@ -487,11 +487,11 @@ class SafeMoveCopyTest(_common.TestCase):
def setUp(self):
super(SafeMoveCopyTest, self).setUp()
self.path = os.path.join(self.temp_dir, 'testfile')
self.path = os.path.join(self.temp_dir, b'testfile')
touch(self.path)
self.otherpath = os.path.join(self.temp_dir, 'testfile2')
self.otherpath = os.path.join(self.temp_dir, b'testfile2')
touch(self.otherpath)
self.dest = self.path + '.dest'
self.dest = self.path + b'.dest'
def test_successful_move(self):
util.move(self.path, self.dest)
@ -524,9 +524,9 @@ class PruneTest(_common.TestCase):
def setUp(self):
super(PruneTest, self).setUp()
self.base = os.path.join(self.temp_dir, 'testdir')
self.base = os.path.join(self.temp_dir, b'testdir')
os.mkdir(self.base)
self.sub = os.path.join(self.base, 'subdir')
self.sub = os.path.join(self.base, b'subdir')
os.mkdir(self.sub)
def test_prune_existent_directory(self):
@ -535,7 +535,7 @@ class PruneTest(_common.TestCase):
self.assertNotExists(self.sub)
def test_prune_nonexistent_directory(self):
util.prune_dirs(os.path.join(self.sub, 'another'), self.base)
util.prune_dirs(os.path.join(self.sub, b'another'), self.base)
self.assertExists(self.base)
self.assertNotExists(self.sub)
@ -544,37 +544,37 @@ class WalkTest(_common.TestCase):
def setUp(self):
super(WalkTest, self).setUp()
self.base = os.path.join(self.temp_dir, 'testdir')
self.base = os.path.join(self.temp_dir, b'testdir')
os.mkdir(self.base)
touch(os.path.join(self.base, 'y'))
touch(os.path.join(self.base, 'x'))
os.mkdir(os.path.join(self.base, 'd'))
touch(os.path.join(self.base, 'd', 'z'))
touch(os.path.join(self.base, b'y'))
touch(os.path.join(self.base, b'x'))
os.mkdir(os.path.join(self.base, b'd'))
touch(os.path.join(self.base, b'd', b'z'))
def test_sorted_files(self):
res = list(util.sorted_walk(self.base))
self.assertEqual(len(res), 2)
self.assertEqual(res[0],
(self.base, ['d'], ['x', 'y']))
(self.base, [b'd'], [b'x', b'y']))
self.assertEqual(res[1],
(os.path.join(self.base, 'd'), [], ['z']))
(os.path.join(self.base, b'd'), [], [b'z']))
def test_ignore_file(self):
res = list(util.sorted_walk(self.base, ('x',)))
res = list(util.sorted_walk(self.base, (b'x',)))
self.assertEqual(len(res), 2)
self.assertEqual(res[0],
(self.base, ['d'], ['y']))
(self.base, [b'd'], [b'y']))
self.assertEqual(res[1],
(os.path.join(self.base, 'd'), [], ['z']))
(os.path.join(self.base, b'd'), [], [b'z']))
def test_ignore_directory(self):
res = list(util.sorted_walk(self.base, ('d',)))
res = list(util.sorted_walk(self.base, (b'd',)))
self.assertEqual(len(res), 1)
self.assertEqual(res[0],
(self.base, [], ['x', 'y']))
(self.base, [], [b'x', b'y']))
def test_ignore_everything(self):
res = list(util.sorted_walk(self.base, ('*',)))
res = list(util.sorted_walk(self.base, (b'*',)))
self.assertEqual(len(res), 1)
self.assertEqual(res[0],
(self.base, [], []))
@ -584,43 +584,43 @@ class UniquePathTest(_common.TestCase):
def setUp(self):
super(UniquePathTest, self).setUp()
self.base = os.path.join(self.temp_dir, 'testdir')
self.base = os.path.join(self.temp_dir, b'testdir')
os.mkdir(self.base)
touch(os.path.join(self.base, 'x.mp3'))
touch(os.path.join(self.base, 'x.1.mp3'))
touch(os.path.join(self.base, 'x.2.mp3'))
touch(os.path.join(self.base, 'y.mp3'))
touch(os.path.join(self.base, b'x.mp3'))
touch(os.path.join(self.base, b'x.1.mp3'))
touch(os.path.join(self.base, b'x.2.mp3'))
touch(os.path.join(self.base, b'y.mp3'))
def test_new_file_unchanged(self):
path = util.unique_path(os.path.join(self.base, 'z.mp3'))
self.assertEqual(path, os.path.join(self.base, 'z.mp3'))
path = util.unique_path(os.path.join(self.base, b'z.mp3'))
self.assertEqual(path, os.path.join(self.base, b'z.mp3'))
def test_conflicting_file_appends_1(self):
path = util.unique_path(os.path.join(self.base, 'y.mp3'))
self.assertEqual(path, os.path.join(self.base, 'y.1.mp3'))
path = util.unique_path(os.path.join(self.base, b'y.mp3'))
self.assertEqual(path, os.path.join(self.base, b'y.1.mp3'))
def test_conflicting_file_appends_higher_number(self):
path = util.unique_path(os.path.join(self.base, 'x.mp3'))
self.assertEqual(path, os.path.join(self.base, 'x.3.mp3'))
path = util.unique_path(os.path.join(self.base, b'x.mp3'))
self.assertEqual(path, os.path.join(self.base, b'x.3.mp3'))
def test_conflicting_file_with_number_increases_number(self):
path = util.unique_path(os.path.join(self.base, 'x.1.mp3'))
self.assertEqual(path, os.path.join(self.base, 'x.3.mp3'))
path = util.unique_path(os.path.join(self.base, b'x.1.mp3'))
self.assertEqual(path, os.path.join(self.base, b'x.3.mp3'))
class MkDirAllTest(_common.TestCase):
def test_parent_exists(self):
path = os.path.join(self.temp_dir, 'foo', 'bar', 'baz', 'qux.mp3')
path = os.path.join(self.temp_dir, b'foo', b'bar', b'baz', b'qux.mp3')
util.mkdirall(path)
self.assertTrue(os.path.isdir(
os.path.join(self.temp_dir, 'foo', 'bar', 'baz')
os.path.join(self.temp_dir, b'foo', b'bar', b'baz')
))
def test_child_does_not_exist(self):
path = os.path.join(self.temp_dir, 'foo', 'bar', 'baz', 'qux.mp3')
path = os.path.join(self.temp_dir, b'foo', b'bar', b'baz', b'qux.mp3')
util.mkdirall(path)
self.assertTrue(not os.path.exists(
os.path.join(self.temp_dir, 'foo', 'bar', 'baz', 'qux.mp3')
os.path.join(self.temp_dir, b'foo', b'bar', b'baz', b'qux.mp3')
))

View file

@ -127,7 +127,7 @@ class ImportAddedTest(unittest.TestCase, ImportHelper):
for item_path, added_after in items_added_after.iteritems():
self.assertEqualTimes(items_added_before[item_path], added_after,
u"reimport modified Item.added for " +
item_path)
util.displayable_path(item_path))
def test_import_singletons_with_added_dates(self):
self.config['import']['singletons'] = True
@ -165,7 +165,7 @@ class ImportAddedTest(unittest.TestCase, ImportHelper):
for item_path, added_after in items_added_after.iteritems():
self.assertEqualTimes(items_added_before[item_path], added_after,
u"reimport modified Item.added for " +
item_path)
util.displayable_path(item_path))
def suite():

View file

@ -30,7 +30,7 @@ from mock import patch
from test import _common
from test._common import unittest
from beets.util import displayable_path
from beets.util import displayable_path, bytestring_path
from test.helper import TestImportSession, TestHelper, has_program, capture_log
from beets import importer
from beets.importer import albums_in_dir
@ -169,14 +169,14 @@ class ImportHelper(TestHelper):
:param count: Number of files to create
"""
self.import_dir = os.path.join(self.temp_dir, 'testsrcdir')
self.import_dir = os.path.join(self.temp_dir, b'testsrcdir')
if os.path.isdir(self.import_dir):
shutil.rmtree(self.import_dir)
album_path = os.path.join(self.import_dir, 'the_album')
album_path = os.path.join(self.import_dir, b'the_album')
os.makedirs(album_path)
resource_path = os.path.join(_common.RSRC, 'full.mp3')
resource_path = os.path.join(_common.RSRC, b'full.mp3')
metadata = {
'artist': u'Tag Artist',
@ -189,7 +189,10 @@ class ImportHelper(TestHelper):
self.media_files = []
for i in range(count):
# Copy files
medium_path = os.path.join(album_path, 'track_%d.mp3' % (i + 1))
medium_path = os.path.join(
album_path,
bytestring_path('track_%d.mp3' % (i + 1))
)
shutil.copy(resource_path, medium_path)
medium = MediaFile(medium_path)
@ -256,8 +259,8 @@ class NonAutotaggedImportTest(_common.TestCase, ImportHelper):
self.importer.run()
for mediafile in self.import_media:
self.assert_file_in_lib(
'Tag Artist', 'Tag Album', '%s.mp3' % mediafile.title
)
b'Tag Artist', b'Tag Album',
util.bytestring_path('{0}.mp3'.format(mediafile.title)))
def test_threaded_import_copy_arrives(self):
config['threaded'] = True
@ -265,8 +268,8 @@ class NonAutotaggedImportTest(_common.TestCase, ImportHelper):
self.importer.run()
for mediafile in self.import_media:
self.assert_file_in_lib(
'Tag Artist', 'Tag Album', '%s.mp3' % mediafile.title
)
b'Tag Artist', b'Tag Album',
util.bytestring_path('{0}.mp3'.format(mediafile.title)))
def test_import_with_move_deletes_import_files(self):
config['import']['move'] = True
@ -280,19 +283,19 @@ class NonAutotaggedImportTest(_common.TestCase, ImportHelper):
def test_import_with_move_prunes_directory_empty(self):
config['import']['move'] = True
self.assertExists(os.path.join(self.import_dir, 'the_album'))
self.assertExists(os.path.join(self.import_dir, b'the_album'))
self.importer.run()
self.assertNotExists(os.path.join(self.import_dir, 'the_album'))
self.assertNotExists(os.path.join(self.import_dir, b'the_album'))
def test_import_with_move_prunes_with_extra_clutter(self):
f = open(os.path.join(self.import_dir, 'the_album', 'alog.log'), 'w')
f = open(os.path.join(self.import_dir, b'the_album', b'alog.log'), 'w')
f.close()
config['clutter'] = ['*.log']
config['import']['move'] = True
self.assertExists(os.path.join(self.import_dir, 'the_album'))
self.assertExists(os.path.join(self.import_dir, b'the_album'))
self.importer.run()
self.assertNotExists(os.path.join(self.import_dir, 'the_album'))
self.assertNotExists(os.path.join(self.import_dir, b'the_album'))
def test_threaded_import_move_arrives(self):
config['import']['move'] = True
@ -301,8 +304,8 @@ class NonAutotaggedImportTest(_common.TestCase, ImportHelper):
self.importer.run()
for mediafile in self.import_media:
self.assert_file_in_lib(
'Tag Artist', 'Tag Album', '%s.mp3' % mediafile.title
)
b'Tag Artist', b'Tag Album',
util.bytestring_path('{0}.mp3'.format(mediafile.title)))
def test_threaded_import_move_deletes_import(self):
config['import']['move'] = True
@ -327,9 +330,9 @@ class NonAutotaggedImportTest(_common.TestCase, ImportHelper):
def test_import_with_delete_prunes_directory_empty(self):
config['import']['delete'] = True
self.assertExists(os.path.join(self.import_dir, 'the_album'))
self.assertExists(os.path.join(self.import_dir, b'the_album'))
self.importer.run()
self.assertNotExists(os.path.join(self.import_dir, 'the_album'))
self.assertNotExists(os.path.join(self.import_dir, b'the_album'))
@unittest.skipUnless(_common.HAVE_SYMLINK, "need symlinks")
def test_import_link_arrives(self):
@ -338,7 +341,8 @@ class NonAutotaggedImportTest(_common.TestCase, ImportHelper):
for mediafile in self.import_media:
filename = os.path.join(
self.libdir,
'Tag Artist', 'Tag Album', '%s.mp3' % mediafile.title
b'Tag Artist', b'Tag Album',
util.bytestring_path('{0}.mp3'.format(mediafile.title))
)
self.assertExists(filename)
self.assertTrue(os.path.islink(filename))
@ -460,7 +464,7 @@ class ImportSingletonTest(_common.TestCase, ImportHelper):
self.importer.add_choice(importer.action.ASIS)
self.importer.run()
self.assert_file_in_lib('singletons', 'Tag Title 1.mp3')
self.assert_file_in_lib(b'singletons', b'Tag Title 1.mp3')
def test_apply_candidate_adds_track(self):
self.assertEqual(self.lib.items().get(), None)
@ -479,7 +483,7 @@ class ImportSingletonTest(_common.TestCase, ImportHelper):
self.importer.add_choice(importer.action.APPLY)
self.importer.run()
self.assert_file_in_lib('singletons', u'Applied Title 1.mp3')
self.assert_file_in_lib(b'singletons', b'Applied Title 1.mp3')
def test_skip_does_not_add_first_track(self):
self.importer.add_choice(importer.action.SKIP)
@ -494,12 +498,12 @@ class ImportSingletonTest(_common.TestCase, ImportHelper):
self.assertEqual(len(self.lib.items()), 1)
def test_import_single_files(self):
resource_path = os.path.join(_common.RSRC, u'empty.mp3')
single_path = os.path.join(self.import_dir, u'track_2.mp3')
resource_path = os.path.join(_common.RSRC, b'empty.mp3')
single_path = os.path.join(self.import_dir, b'track_2.mp3')
shutil.copy(resource_path, single_path)
import_files = [
os.path.join(self.import_dir, u'the_album'),
os.path.join(self.import_dir, b'the_album'),
single_path
]
self._setup_import_session(singletons=False)
@ -545,7 +549,8 @@ class ImportTest(_common.TestCase, ImportHelper):
self.importer.add_choice(importer.action.ASIS)
self.importer.run()
self.assert_file_in_lib('Tag Artist', 'Tag Album', 'Tag Title 1.mp3')
self.assert_file_in_lib(
b'Tag Artist', b'Tag Album', b'Tag Title 1.mp3')
def test_apply_candidate_adds_album(self):
self.assertEqual(self.lib.albums().get(), None)
@ -567,13 +572,13 @@ class ImportTest(_common.TestCase, ImportHelper):
self.importer.add_choice(importer.action.APPLY)
self.importer.run()
self.assert_file_in_lib(
'Applied Artist', 'Applied Album', 'Applied Title 1.mp3'
)
b'Applied Artist', b'Applied Album', b'Applied Title 1.mp3')
def test_apply_with_move_deletes_import(self):
config['import']['move'] = True
import_file = os.path.join(self.import_dir, 'the_album', 'track_1.mp3')
import_file = os.path.join(
self.import_dir, b'the_album', b'track_1.mp3')
self.assertExists(import_file)
self.importer.add_choice(importer.action.APPLY)
@ -583,7 +588,8 @@ class ImportTest(_common.TestCase, ImportHelper):
def test_apply_with_delete_deletes_import(self):
config['import']['delete'] = True
import_file = os.path.join(self.import_dir, 'the_album', 'track_1.mp3')
import_file = os.path.join(self.import_dir,
b'the_album', b'track_1.mp3')
self.assertExists(import_file)
self.importer.add_choice(importer.action.APPLY)
@ -597,8 +603,8 @@ class ImportTest(_common.TestCase, ImportHelper):
def test_skip_non_album_dirs(self):
self.assertTrue(os.path.isdir(
os.path.join(self.import_dir, 'the_album')))
self.touch('cruft', dir=self.import_dir)
os.path.join(self.import_dir, b'the_album')))
self.touch(b'cruft', dir=self.import_dir)
self.importer.add_choice(importer.action.APPLY)
self.importer.run()
self.assertEqual(len(self.lib.albums()), 1)
@ -611,8 +617,8 @@ class ImportTest(_common.TestCase, ImportHelper):
self.assertEqual(len(self.lib.items()), 1)
def test_empty_directory_warning(self):
import_dir = os.path.join(self.temp_dir, 'empty')
self.touch('non-audio', dir=import_dir)
import_dir = os.path.join(self.temp_dir, b'empty')
self.touch(b'non-audio', dir=import_dir)
self._setup_import_session(import_dir=import_dir)
with capture_log() as logs:
self.importer.run()
@ -621,8 +627,8 @@ class ImportTest(_common.TestCase, ImportHelper):
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')
self.touch('non-audio', dir=import_dir)
import_dir = os.path.join(self.temp_dir, b'empty')
self.touch(b'non-audio', dir=import_dir)
self._setup_import_session(import_dir=import_dir, singletons=True)
with capture_log() as logs:
self.importer.run()
@ -671,7 +677,7 @@ class ImportTracksTest(_common.TestCase, ImportHelper):
self.importer.add_choice(importer.action.APPLY)
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(b'singletons', b'Applied Title 1.mp3')
class ImportCompilationTest(_common.TestCase, ImportHelper):
@ -809,14 +815,14 @@ class ImportExistingTest(_common.TestCase, ImportHelper):
medium.title = u'New Title'
medium.save()
old_path = os.path.join('Applied Artist', 'Applied Album',
'Applied Title 1.mp3')
old_path = os.path.join(b'Applied Artist', b'Applied Album',
b'Applied Title 1.mp3')
self.assert_file_in_lib(old_path)
self.importer.add_choice(importer.action.ASIS)
self.importer.run()
self.assert_file_in_lib('Applied Artist', 'Applied Album',
'New Title.mp3')
self.assert_file_in_lib(b'Applied Artist', b'Applied Album',
b'New Title.mp3')
self.assert_file_not_in_lib(old_path)
def test_asis_updated_without_copy_does_not_move_file(self):
@ -825,15 +831,15 @@ class ImportExistingTest(_common.TestCase, ImportHelper):
medium.title = u'New Title'
medium.save()
old_path = os.path.join('Applied Artist', 'Applied Album',
'Applied Title 1.mp3')
old_path = os.path.join(b'Applied Artist', b'Applied Album',
b'Applied Title 1.mp3')
self.assert_file_in_lib(old_path)
config['import']['copy'] = False
self.importer.add_choice(importer.action.ASIS)
self.importer.run()
self.assert_file_not_in_lib('Applied Artist', 'Applied Album',
'New Title.mp3')
self.assert_file_not_in_lib(b'Applied Artist', b'Applied Album',
b'New Title.mp3')
self.assert_file_in_lib(old_path)
def test_outside_file_is_copied(self):
@ -846,8 +852,8 @@ class ImportExistingTest(_common.TestCase, ImportHelper):
self._setup_import_session()
self.importer.add_choice(importer.action.APPLY)
self.importer.run()
new_path = os.path.join('Applied Artist', 'Applied Album',
'Applied Title 1.mp3')
new_path = os.path.join(b'Applied Artist', b'Applied Album',
b'Applied Title 1.mp3')
self.assert_file_in_lib(new_path)
self.assert_equal_path(self.lib.items().get().path,
@ -1122,7 +1128,7 @@ class ImportDuplicateAlbumTest(unittest.TestCase, TestHelper,
# Imported item has the same artist and album as the one in the
# library.
import_file = os.path.join(self.importer.paths[0],
'album 0', 'track 0.mp3')
b'album 0', b'track 0.mp3')
import_file = MediaFile(import_file)
import_file.artist = item['artist']
import_file.albumartist = item['artist']
@ -1351,7 +1357,7 @@ class IncrementalImportTest(unittest.TestCase, TestHelper):
def _mkmp3(path):
shutil.copyfile(os.path.join(_common.RSRC, 'min.mp3'), path)
shutil.copyfile(os.path.join(_common.RSRC, b'min.mp3'), path)
class AlbumsInDirTest(_common.TestCase):
@ -1359,20 +1365,20 @@ class AlbumsInDirTest(_common.TestCase):
super(AlbumsInDirTest, self).setUp()
# create a directory structure for testing
self.base = os.path.abspath(os.path.join(self.temp_dir, 'tempdir'))
self.base = os.path.abspath(os.path.join(self.temp_dir, b'tempdir'))
os.mkdir(self.base)
os.mkdir(os.path.join(self.base, 'album1'))
os.mkdir(os.path.join(self.base, 'album2'))
os.mkdir(os.path.join(self.base, 'more'))
os.mkdir(os.path.join(self.base, 'more', 'album3'))
os.mkdir(os.path.join(self.base, 'more', 'album4'))
os.mkdir(os.path.join(self.base, b'album1'))
os.mkdir(os.path.join(self.base, b'album2'))
os.mkdir(os.path.join(self.base, b'more'))
os.mkdir(os.path.join(self.base, b'more', b'album3'))
os.mkdir(os.path.join(self.base, b'more', b'album4'))
_mkmp3(os.path.join(self.base, 'album1', 'album1song1.mp3'))
_mkmp3(os.path.join(self.base, 'album1', 'album1song2.mp3'))
_mkmp3(os.path.join(self.base, 'album2', 'album2song.mp3'))
_mkmp3(os.path.join(self.base, 'more', 'album3', 'album3song.mp3'))
_mkmp3(os.path.join(self.base, 'more', 'album4', 'album4song.mp3'))
_mkmp3(os.path.join(self.base, b'album1', b'album1song1.mp3'))
_mkmp3(os.path.join(self.base, b'album1', b'album1song2.mp3'))
_mkmp3(os.path.join(self.base, b'album2', b'album2song.mp3'))
_mkmp3(os.path.join(self.base, b'more', b'album3', b'album3song.mp3'))
_mkmp3(os.path.join(self.base, b'more', b'album4', b'album4song.mp3'))
def test_finds_all_albums(self):
albums = list(albums_in_dir(self.base))
@ -1381,16 +1387,16 @@ class AlbumsInDirTest(_common.TestCase):
def test_separates_contents(self):
found = []
for _, album in albums_in_dir(self.base):
found.append(re.search(r'album(.)song', album[0]).group(1))
self.assertTrue('1' in found)
self.assertTrue('2' in found)
self.assertTrue('3' in found)
self.assertTrue('4' in found)
found.append(re.search(br'album(.)song', album[0]).group(1))
self.assertTrue(b'1' in found)
self.assertTrue(b'2' in found)
self.assertTrue(b'3' in found)
self.assertTrue(b'4' in found)
def test_finds_multiple_songs(self):
for _, album in albums_in_dir(self.base):
n = re.search(r'album(.)song', album[0]).group(1)
if n == '1':
n = re.search(br'album(.)song', album[0]).group(1)
if n == b'1':
self.assertEqual(len(album), 2)
else:
self.assertEqual(len(album), 1)
@ -1600,7 +1606,7 @@ class ReimportTest(unittest.TestCase, ImportHelper, _common.Assertions):
def test_reimported_item_preserves_art(self):
self._setup_session()
art_source = os.path.join(_common.RSRC, 'abbey.jpg')
art_source = os.path.join(_common.RSRC, b'abbey.jpg')
replaced_album = self._album()
replaced_album.set_art(art_source)
replaced_album.store()
@ -1638,21 +1644,21 @@ class ImportPretendTest(_common.TestCase, ImportHelper):
def __create_import_dir(self):
self._create_import_dir(1)
resource_path = os.path.join(_common.RSRC, u'empty.mp3')
single_path = os.path.join(self.import_dir, u'track_2.mp3')
resource_path = os.path.join(_common.RSRC, b'empty.mp3')
single_path = os.path.join(self.import_dir, b'track_2.mp3')
shutil.copy(resource_path, single_path)
self.import_paths = [
os.path.join(self.import_dir, u'the_album'),
os.path.join(self.import_dir, b'the_album'),
single_path
]
self.import_files = [
displayable_path(
os.path.join(self.import_paths[0], u'track_1.mp3')),
os.path.join(self.import_paths[0], b'track_1.mp3')),
displayable_path(single_path)
]
def __create_empty_import_dir(self):
path = os.path.join(self.temp_dir, 'empty')
path = os.path.join(self.temp_dir, b'empty')
os.makedirs(path)
self.empty_path = path

View file

@ -17,6 +17,7 @@ from __future__ import division, absolute_import, print_function
from mock import patch
from beets import library
from beets.util import bytestring_path
from beetsplug.ipfs import IPFSPlugin
from test import _common
@ -53,6 +54,7 @@ class IPFSPluginTest(unittest.TestCase, TestHelper):
want_path = '/ipfs/{0}/{1}'.format(test_album.ipfs,
os.path.basename(
want_item.path))
want_path = bytestring_path(want_path)
self.assertEqual(check_item.path, want_path)
self.assertEqual(check_item.ipfs, want_item.ipfs)
self.assertEqual(check_item.title, want_item.title)

View file

@ -36,7 +36,7 @@ from beets import util
from beets import plugins
from beets import config
from beets.mediafile import MediaFile
from beets.util import syspath
from beets.util import syspath, bytestring_path
from test.helper import TestHelper
# Shortcut to path normalization.
@ -96,7 +96,7 @@ class AddTest(_common.TestCase):
def test_library_add_path_inserts_row(self):
i = beets.library.Item.from_path(
os.path.join(_common.RSRC, 'full.mp3')
os.path.join(_common.RSRC, b'full.mp3')
)
self.lib.add(i)
new_grouping = self.lib._connection().execute(
@ -148,17 +148,17 @@ class DestinationTest(_common.TestCase):
config.read(user=False, defaults=True)
def test_directory_works_with_trailing_slash(self):
self.lib.directory = 'one/'
self.lib.directory = b'one/'
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.directory = b'one'
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.directory = b'base'
self.lib.path_formats = [(u'default', u'$album/$artist $title')]
self.i.title = 'three'
self.i.artist = 'two'
@ -167,21 +167,21 @@ class DestinationTest(_common.TestCase):
np('base/one/two three'))
def test_destination_preserves_extension(self):
self.lib.directory = 'base'
self.lib.directory = b'base'
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.directory = b'base'
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.directory = b'base'
self.lib.path_formats = [(u'default',
u'$track $tracktotal $disc $disctotal $bpm')]
self.i.track = 1
@ -193,7 +193,7 @@ class DestinationTest(_common.TestCase):
np('base/01 02 03 04 5'))
def test_destination_pads_date_values(self):
self.lib.directory = 'base'
self.lib.directory = b'base'
self.lib.path_formats = [(u'default', u'$year-$month-$day')]
self.i.year = 1
self.i.month = 2
@ -204,21 +204,21 @@ class DestinationTest(_common.TestCase):
def test_destination_escapes_slashes(self):
self.i.album = 'one/two'
dest = self.i.destination()
self.assertTrue('one' in dest)
self.assertTrue('two' in dest)
self.assertFalse('one/two' in dest)
self.assertTrue(b'one' in dest)
self.assertTrue(b'two' in dest)
self.assertFalse(b'one/two' in dest)
def test_destination_escapes_leading_dot(self):
self.i.album = '.something'
dest = self.i.destination()
self.assertTrue('something' in dest)
self.assertFalse('/.' in dest)
self.assertTrue(b'something' in dest)
self.assertFalse(b'/.' in dest)
def test_destination_preserves_legitimate_slashes(self):
self.i.artist = 'one'
self.i.album = 'two'
dest = self.i.destination()
self.assertTrue(os.path.join('one', 'two') in dest)
self.assertTrue(os.path.join(b'one', b'two') in dest)
def test_destination_long_names_truncated(self):
self.i.title = u'X' * 300
@ -228,23 +228,23 @@ class DestinationTest(_common.TestCase):
def test_destination_long_names_keep_extension(self):
self.i.title = u'X' * 300
self.i.path = 'something.extn'
self.i.path = b'something.extn'
dest = self.i.destination()
self.assertEqual(dest[-5:], '.extn')
self.assertEqual(dest[-5:], b'.extn')
def test_distination_windows_removes_both_separators(self):
self.i.title = 'one \\ two / three.mp3'
with _common.platform_windows():
p = self.i.destination()
self.assertFalse('one \\ two' in p)
self.assertFalse('one / two' in p)
self.assertFalse('two \\ three' in p)
self.assertFalse('two / three' in p)
self.assertFalse(b'one \\ two' in p)
self.assertFalse(b'one / two' in p)
self.assertFalse(b'two \\ three' in p)
self.assertFalse(b'two / three' in p)
def test_path_with_format(self):
self.lib.path_formats = [(u'default', u'$artist/$album ($format)')]
p = self.i.destination()
self.assertTrue('(FLAC)' in p)
self.assertTrue(b'(FLAC)' in p)
def test_heterogeneous_album_gets_single_directory(self):
i1, i2 = item(), item()
@ -257,14 +257,14 @@ class DestinationTest(_common.TestCase):
def test_default_path_for_non_compilations(self):
self.i.comp = False
self.lib.add_album([self.i])
self.lib.directory = 'one'
self.lib.directory = b'one'
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.directory = b'one'
self.lib.path_formats = [
(u'default', u'two'),
(u'singleton:true', u'four'),
@ -275,7 +275,7 @@ class DestinationTest(_common.TestCase):
def test_comp_before_singleton_path(self):
i = item(self.lib)
i.comp = True
self.lib.directory = 'one'
self.lib.directory = b'one'
self.lib.path_formats = [
(u'default', u'two'),
(u'comp:true', u'three'),
@ -286,7 +286,7 @@ class DestinationTest(_common.TestCase):
def test_comp_path(self):
self.i.comp = True
self.lib.add_album([self.i])
self.lib.directory = 'one'
self.lib.directory = b'one'
self.lib.path_formats = [
(u'default', u'two'),
(u'comp:true', u'three'),
@ -297,7 +297,7 @@ class DestinationTest(_common.TestCase):
self.i.comp = True
self.lib.add_album([self.i])
self.i.albumtype = u'sometype'
self.lib.directory = 'one'
self.lib.directory = b'one'
self.lib.path_formats = [
(u'default', u'two'),
(u'albumtype:sometype', u'four'),
@ -309,7 +309,7 @@ class DestinationTest(_common.TestCase):
self.i.comp = True
self.lib.add_album([self.i])
self.i.albumtype = u'sometype'
self.lib.directory = 'one'
self.lib.directory = b'one'
self.lib.path_formats = [
(u'default', u'two'),
(u'albumtype:anothertype', u'four'),
@ -416,13 +416,13 @@ class DestinationTest(_common.TestCase):
def test_asciify_and_replace(self):
config['asciify_paths'] = True
self.lib.replacements = [(re.compile(u'"'), u'q')]
self.lib.directory = 'lib'
self.lib.directory = b'lib'
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.directory = b'base'
self.lib.replacements = [(re.compile(r'a'), u'e')]
self.lib.path_formats = [(u'default', u'$album/$title')]
self.i.title = u'foo'
@ -432,7 +432,7 @@ class DestinationTest(_common.TestCase):
@unittest.skip('unimplemented: #359')
def test_destination_with_empty_component(self):
self.lib.directory = 'base'
self.lib.directory = b'base'
self.lib.replacements = [(re.compile(r'^$'), u'_')]
self.lib.path_formats = [(u'default', u'$album/$artist/$title')]
self.i.title = u'three'
@ -444,7 +444,7 @@ class DestinationTest(_common.TestCase):
@unittest.skip('unimplemented: #359')
def test_destination_with_empty_final_component(self):
self.lib.directory = 'base'
self.lib.directory = b'base'
self.lib.replacements = [(re.compile(r'^$'), u'_')]
self.lib.path_formats = [(u'default', u'$album/$title')]
self.i.title = u''
@ -466,7 +466,7 @@ class DestinationTest(_common.TestCase):
# The final path should reflect the replacement.
dest = self.i.destination()
self.assertEqual(dest[-2:], u'XZ')
self.assertEqual(dest[-2:], b'XZ')
def test_legalize_path_one_for_many_replacement(self):
# Use a replacement that should always replace the last X in any
@ -482,7 +482,7 @@ class DestinationTest(_common.TestCase):
# 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:], u'XX')
self.assertEqual(dest[-2:], b'XX')
class ItemFormattedMappingTest(_common.LibTestCase):
@ -561,7 +561,7 @@ class DestinationFunctionTest(_common.TestCase, PathFormattingMixin):
def setUp(self):
super(DestinationFunctionTest, self).setUp()
self.lib = beets.library.Library(':memory:')
self.lib.directory = '/base'
self.lib.directory = b'/base'
self.lib.path_formats = [(u'default', u'path')]
self.i = item(self.lib)
@ -571,98 +571,98 @@ class DestinationFunctionTest(_common.TestCase, PathFormattingMixin):
def test_upper_case_literal(self):
self._setf(u'%upper{foo}')
self._assert_dest('/base/FOO')
self._assert_dest(b'/base/FOO')
def test_upper_case_variable(self):
self._setf(u'%upper{$title}')
self._assert_dest('/base/THE TITLE')
self._assert_dest(b'/base/THE TITLE')
def test_title_case_variable(self):
self._setf(u'%title{$title}')
self._assert_dest('/base/The Title')
self._assert_dest(b'/base/The Title')
def test_left_variable(self):
self._setf(u'%left{$title, 3}')
self._assert_dest('/base/the')
self._assert_dest(b'/base/the')
def test_right_variable(self):
self._setf(u'%right{$title,3}')
self._assert_dest('/base/tle')
self._assert_dest(b'/base/tle')
def test_if_false(self):
self._setf(u'x%if{,foo}')
self._assert_dest('/base/x')
self._assert_dest(b'/base/x')
def test_if_false_value(self):
self._setf(u'x%if{false,foo}')
self._assert_dest('/base/x')
self._assert_dest(b'/base/x')
def test_if_true(self):
self._setf(u'%if{bar,foo}')
self._assert_dest('/base/foo')
self._assert_dest(b'/base/foo')
def test_if_else_false(self):
self._setf(u'%if{,foo,baz}')
self._assert_dest('/base/baz')
self._assert_dest(b'/base/baz')
def test_if_else_false_value(self):
self._setf(u'%if{false,foo,baz}')
self._assert_dest('/base/baz')
self._assert_dest(b'/base/baz')
def test_if_int_value(self):
self._setf(u'%if{0,foo,baz}')
self._assert_dest('/base/baz')
self._assert_dest(b'/base/baz')
def test_nonexistent_function(self):
self._setf(u'%foo{bar}')
self._assert_dest('/base/%foo{bar}')
self._assert_dest(b'/base/%foo{bar}')
def test_if_def_field_return_self(self):
self.i.bar = 3
self._setf(u'%ifdef{bar}')
self._assert_dest('/base/3')
self._assert_dest(b'/base/3')
def test_if_def_field_not_defined(self):
self._setf(u' %ifdef{bar}/$artist')
self._assert_dest('/base/the artist')
self._assert_dest(b'/base/the artist')
def test_if_def_field_not_defined_2(self):
self._setf(u'$artist/%ifdef{bar}')
self._assert_dest('/base/the artist')
self._assert_dest(b'/base/the artist')
def test_if_def_true(self):
self._setf(u'%ifdef{artist,cool}')
self._assert_dest('/base/cool')
self._assert_dest(b'/base/cool')
def test_if_def_true_complete(self):
self.i.series = "Now"
self._setf(u'%ifdef{series,$series Series,Albums}/$album')
self._assert_dest('/base/Now Series/the album')
self._assert_dest(b'/base/Now Series/the album')
def test_if_def_false_complete(self):
self._setf(u'%ifdef{plays,$plays,not_played}')
self._assert_dest('/base/not_played')
self._assert_dest(b'/base/not_played')
def test_first(self):
self.i.genres = "Pop; Rock; Classical Crossover"
self._setf(u'%first{$genres}')
self._assert_dest('/base/Pop')
self._assert_dest(b'/base/Pop')
def test_first_skip(self):
self.i.genres = "Pop; Rock; Classical Crossover"
self._setf(u'%first{$genres,1,2}')
self._assert_dest('/base/Classical Crossover')
self._assert_dest(b'/base/Classical Crossover')
def test_first_different_sep(self):
self._setf(u'%first{Alice / Bob / Eve,2,0, / , & }')
self._assert_dest('/base/Alice & Bob')
self._assert_dest(b'/base/Alice & Bob')
class DisambiguationTest(_common.TestCase, PathFormattingMixin):
def setUp(self):
super(DisambiguationTest, self).setUp()
self.lib = beets.library.Library(':memory:')
self.lib.directory = '/base'
self.lib.directory = b'/base'
self.lib.path_formats = [(u'default', u'path')]
self.i1 = item()
@ -680,33 +680,33 @@ class DisambiguationTest(_common.TestCase, PathFormattingMixin):
self.lib._connection().close()
def test_unique_expands_to_disambiguating_year(self):
self._assert_dest('/base/foo [2001]/the title', self.i1)
self._assert_dest(b'/base/foo [2001]/the title', self.i1)
def test_unique_with_default_arguments_uses_albumtype(self):
album2 = self.lib.get_album(self.i1)
album2.albumtype = u'bar'
album2.store()
self._setf(u'foo%aunique{}/$title')
self._assert_dest('/base/foo [bar]/the title', self.i1)
self._assert_dest(b'/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 = u'different album'
album2.store()
self._assert_dest('/base/foo/the title', self.i1)
self._assert_dest(b'/base/foo/the title', self.i1)
def test_use_fallback_numbers_when_identical(self):
album2 = self.lib.get_album(self.i2)
album2.year = 2001
album2.store()
self._assert_dest('/base/foo 1/the title', self.i1)
self._assert_dest('/base/foo 2/the title', self.i2)
self._assert_dest(b'/base/foo 1/the title', self.i1)
self._assert_dest(b'/base/foo 2/the title', self.i2)
def test_unique_falls_back_to_second_distinguishing_field(self):
self._setf(u'foo%aunique{albumartist album,month year}/$title')
self._assert_dest('/base/foo [2001]/the title', self.i1)
self._assert_dest(b'/base/foo [2001]/the title', self.i1)
def test_unique_sanitized(self):
album2 = self.lib.get_album(self.i2)
@ -716,7 +716,7 @@ class DisambiguationTest(_common.TestCase, PathFormattingMixin):
album2.store()
album1.store()
self._setf(u'foo%aunique{albumartist album,albumtype}/$title')
self._assert_dest('/base/foo [foo_bar]/the title', self.i1)
self._assert_dest(b'/base/foo [foo_bar]/the title', self.i1)
class PluginDestinationTest(_common.TestCase):
@ -736,7 +736,7 @@ class PluginDestinationTest(_common.TestCase):
plugins.item_field_getters = field_getters
self.lib = beets.library.Library(':memory:')
self.lib.directory = '/base'
self.lib.directory = b'/base'
self.lib.path_formats = [(u'default', u'$artist $foo')]
self.i = item(self.lib)
@ -747,28 +747,28 @@ class PluginDestinationTest(_common.TestCase):
def _assert_dest(self, dest):
with _common.platform_posix():
the_dest = self.i.destination()
self.assertEqual(the_dest, '/base/' + dest)
self.assertEqual(the_dest, b'/base/' + dest)
def test_undefined_value_not_substituted(self):
self._assert_dest(u'the artist $foo')
self._assert_dest(b'the artist $foo')
def test_plugin_value_not_substituted(self):
self._tv_map = {
'foo': 'bar',
}
self._assert_dest(u'the artist bar')
self._assert_dest(b'the artist bar')
def test_plugin_value_overrides_attribute(self):
self._tv_map = {
'artist': 'bar',
}
self._assert_dest(u'bar $foo')
self._assert_dest(b'bar $foo')
def test_plugin_value_sanitized(self):
self._tv_map = {
'foo': 'bar/baz',
}
self._assert_dest(u'the artist bar_baz')
self._assert_dest(b'the artist bar_baz')
class AlbumInfoTest(_common.TestCase):
@ -790,7 +790,7 @@ class AlbumInfoTest(_common.TestCase):
ai.artpath = '/my/great/art'
ai.store()
new_ai = self.lib.get_album(self.i)
self.assertEqual(new_ai.artpath, '/my/great/art')
self.assertEqual(new_ai.artpath, b'/my/great/art')
def test_albuminfo_for_two_items_doesnt_duplicate_row(self):
i2 = item(self.lib)
@ -883,7 +883,8 @@ class ArtDestinationTest(_common.TestCase):
def test_art_filename_respects_setting(self):
art = self.ai.art_destination('something.jpg')
self.assertTrue('%sartimage.jpg' % util.PATH_SEP in art)
new_art = bytestring_path('%sartimage.jpg' % os.path.sep)
self.assertTrue(new_art in art)
def test_art_path_in_item_dir(self):
art = self.ai.art_destination('something.jpg')
@ -893,7 +894,7 @@ class ArtDestinationTest(_common.TestCase):
def test_art_path_sanitized(self):
config['art_filename'] = u'artXimage'
art = self.ai.art_destination('something.jpg')
self.assertTrue('artYimage' in art)
self.assertTrue(b'artYimage' in art)
class PathStringTest(_common.TestCase):
@ -983,8 +984,8 @@ class PathStringTest(_common.TestCase):
class MtimeTest(_common.TestCase):
def setUp(self):
super(MtimeTest, self).setUp()
self.ipath = os.path.join(self.temp_dir, 'testfile.mp3')
shutil.copy(os.path.join(_common.RSRC, 'full.mp3'), self.ipath)
self.ipath = os.path.join(self.temp_dir, b'testfile.mp3')
shutil.copy(os.path.join(_common.RSRC, b'full.mp3'), self.ipath)
self.i = beets.library.Item.from_path(self.ipath)
self.lib = beets.library.Library(':memory:')
self.lib.add(self.i)
@ -1079,7 +1080,7 @@ class WriteTest(unittest.TestCase, TestHelper):
def test_write_nonexistant(self):
item = self.create_item()
item.path = '/path/does/not/exist'
item.path = b'/path/does/not/exist'
with self.assertRaises(beets.library.ReadError):
item.write()
@ -1097,7 +1098,7 @@ class WriteTest(unittest.TestCase, TestHelper):
def test_write_with_custom_path(self):
item = self.add_item_fixture()
custom_path = os.path.join(self.temp_dir, 'custom.mp3')
custom_path = os.path.join(self.temp_dir, b'custom.mp3')
shutil.copy(syspath(item.path), syspath(custom_path))
item['artist'] = 'new artist'
@ -1126,7 +1127,7 @@ class WriteTest(unittest.TestCase, TestHelper):
class ItemReadTest(unittest.TestCase):
def test_unreadable_raise_read_error(self):
unreadable = os.path.join(_common.RSRC, 'image-2x3.png')
unreadable = os.path.join(_common.RSRC, b'image-2x3.png')
item = beets.library.Item()
with self.assertRaises(beets.library.ReadError) as cm:
item.read(unreadable)

View file

@ -40,7 +40,8 @@ class ArtTestMixin(object):
@property
def png_data(self):
if not self._png_data:
with open(os.path.join(_common.RSRC, 'image-2x3.png'), 'rb') as f:
image_file = os.path.join(_common.RSRC, b'image-2x3.png')
with open(image_file, 'rb') as f:
self._png_data = f.read()
return self._png_data
_png_data = None
@ -48,7 +49,8 @@ class ArtTestMixin(object):
@property
def jpg_data(self):
if not self._jpg_data:
with open(os.path.join(_common.RSRC, 'image-2x3.jpg'), 'rb') as f:
image_file = os.path.join(_common.RSRC, b'image-2x3.jpg')
with open(image_file, 'rb') as f:
self._jpg_data = f.read()
return self._jpg_data
_jpg_data = None
@ -56,7 +58,8 @@ class ArtTestMixin(object):
@property
def tiff_data(self):
if not self._jpg_data:
with open(os.path.join(_common.RSRC, 'image-2x3.tiff'), 'rb') as f:
image_file = os.path.join(_common.RSRC, b'image-2x3.tiff')
with open(image_file, 'rb') as f:
self._jpg_data = f.read()
return self._jpg_data
_jpg_data = None
@ -931,13 +934,13 @@ class AIFFTest(ReadWriteTestBase, unittest.TestCase):
class MediaFieldTest(unittest.TestCase):
def test_properties_from_fields(self):
path = os.path.join(_common.RSRC, 'full.mp3')
path = os.path.join(_common.RSRC, b'full.mp3')
mediafile = MediaFile(path)
for field in MediaFile.fields():
self.assertTrue(hasattr(mediafile, field))
def test_properties_from_readable_fields(self):
path = os.path.join(_common.RSRC, 'full.mp3')
path = os.path.join(_common.RSRC, b'full.mp3')
mediafile = MediaFile(path)
for field in MediaFile.readable_fields():
self.assertTrue(hasattr(mediafile, field))

View file

@ -23,6 +23,8 @@ import shutil
from test import _common
from test._common import unittest
from test.helper import TestHelper
from beets.util import bytestring_path
import beets.mediafile
@ -35,7 +37,7 @@ class EdgeTest(unittest.TestCase):
# This is very hard to produce, so this is just the first 8192
# bytes of a file found "in the wild".
emptylist = beets.mediafile.MediaFile(
os.path.join(_common.RSRC, 'emptylist.mp3')
os.path.join(_common.RSRC, b'emptylist.mp3')
)
genre = emptylist.genre
self.assertEqual(genre, None)
@ -44,7 +46,7 @@ class EdgeTest(unittest.TestCase):
# Ensures that release times delimited by spaces are ignored.
# Amie Street produces such files.
space_time = beets.mediafile.MediaFile(
os.path.join(_common.RSRC, 'space_time.mp3')
os.path.join(_common.RSRC, b'space_time.mp3')
)
self.assertEqual(space_time.year, 2009)
self.assertEqual(space_time.month, 9)
@ -54,7 +56,7 @@ class EdgeTest(unittest.TestCase):
# Ensures that release times delimited by Ts are ignored.
# The iTunes Store produces such files.
t_time = beets.mediafile.MediaFile(
os.path.join(_common.RSRC, 't_time.m4a')
os.path.join(_common.RSRC, b't_time.m4a')
)
self.assertEqual(t_time.year, 1987)
self.assertEqual(t_time.month, 3)
@ -63,19 +65,20 @@ class EdgeTest(unittest.TestCase):
def test_tempo_with_bpm(self):
# Some files have a string like "128 BPM" in the tempo field
# rather than just a number.
f = beets.mediafile.MediaFile(os.path.join(_common.RSRC, 'bpm.mp3'))
f = beets.mediafile.MediaFile(os.path.join(_common.RSRC, b'bpm.mp3'))
self.assertEqual(f.bpm, 128)
def test_discc_alternate_field(self):
# Different taggers use different vorbis comments to reflect
# the disc and disc count fields: ensure that the alternative
# style works.
f = beets.mediafile.MediaFile(os.path.join(_common.RSRC, 'discc.ogg'))
f = beets.mediafile.MediaFile(os.path.join(_common.RSRC, b'discc.ogg'))
self.assertEqual(f.disc, 4)
self.assertEqual(f.disctotal, 5)
def test_old_ape_version_bitrate(self):
f = beets.mediafile.MediaFile(os.path.join(_common.RSRC, 'oldape.ape'))
media_file = os.path.join(_common.RSRC, b'oldape.ape')
f = beets.mediafile.MediaFile(media_file)
self.assertEqual(f.bitrate, 0)
def test_only_magic_bytes_jpeg(self):
@ -83,7 +86,7 @@ class EdgeTest(unittest.TestCase):
# such aren't recognized by imghdr. Ensure that this still works thanks
# to our own follow up mimetype detection based on
# https://github.com/file/file/blob/master/magic/Magdir/jpeg#L12
f = open(os.path.join(_common.RSRC, 'only-magic-bytes.jpg'), 'rb')
f = open(os.path.join(_common.RSRC, b'only-magic-bytes.jpg'), 'rb')
jpg_data = f.read()
self.assertEqual(
beets.mediafile._image_mime_type(jpg_data),
@ -93,7 +96,7 @@ class EdgeTest(unittest.TestCase):
# Make sure we don't crash when the iTunes SoundCheck field contains
# non-ASCII binary data.
f = beets.mediafile.MediaFile(os.path.join(_common.RSRC,
'soundcheck-nonascii.m4a'))
b'soundcheck-nonascii.m4a'))
self.assertEqual(f.rg_track_gain, 0.0)
@ -159,34 +162,34 @@ class SafetyTest(unittest.TestCase, TestHelper):
def test_corrupt_mp3_raises_unreadablefileerror(self):
# Make sure we catch Mutagen reading errors appropriately.
self._exccheck('corrupt.mp3', beets.mediafile.UnreadableFileError)
self._exccheck(b'corrupt.mp3', beets.mediafile.UnreadableFileError)
def test_corrupt_mp4_raises_unreadablefileerror(self):
self._exccheck('corrupt.m4a', beets.mediafile.UnreadableFileError)
self._exccheck(b'corrupt.m4a', beets.mediafile.UnreadableFileError)
def test_corrupt_flac_raises_unreadablefileerror(self):
self._exccheck('corrupt.flac', beets.mediafile.UnreadableFileError)
self._exccheck(b'corrupt.flac', beets.mediafile.UnreadableFileError)
def test_corrupt_ogg_raises_unreadablefileerror(self):
self._exccheck('corrupt.ogg', beets.mediafile.UnreadableFileError)
self._exccheck(b'corrupt.ogg', beets.mediafile.UnreadableFileError)
def test_invalid_ogg_header_raises_unreadablefileerror(self):
self._exccheck('corrupt.ogg', beets.mediafile.UnreadableFileError,
self._exccheck(b'corrupt.ogg', beets.mediafile.UnreadableFileError,
'OggS\x01vorbis')
def test_corrupt_monkeys_raises_unreadablefileerror(self):
self._exccheck('corrupt.ape', beets.mediafile.UnreadableFileError)
self._exccheck(b'corrupt.ape', beets.mediafile.UnreadableFileError)
def test_invalid_extension_raises_filetypeerror(self):
self._exccheck('something.unknown', beets.mediafile.FileTypeError)
self._exccheck(b'something.unknown', beets.mediafile.FileTypeError)
def test_magic_xml_raises_unreadablefileerror(self):
self._exccheck('nothing.xml', beets.mediafile.UnreadableFileError,
self._exccheck(b'nothing.xml', beets.mediafile.UnreadableFileError,
"ftyp")
@unittest.skipIf(not hasattr(os, 'symlink'), u'platform lacks symlink')
def test_broken_symlink(self):
fn = os.path.join(_common.RSRC, 'brokenlink')
fn = os.path.join(_common.RSRC, b'brokenlink')
os.symlink('does_not_exist', fn)
try:
self.assertRaises(IOError,
@ -197,7 +200,7 @@ class SafetyTest(unittest.TestCase, TestHelper):
class SideEffectsTest(unittest.TestCase):
def setUp(self):
self.empty = os.path.join(_common.RSRC, 'empty.mp3')
self.empty = os.path.join(_common.RSRC, b'empty.mp3')
def test_opening_tagless_file_leaves_untouched(self):
old_mtime = os.stat(self.empty).st_mtime
@ -209,8 +212,8 @@ class SideEffectsTest(unittest.TestCase):
class MP4EncodingTest(unittest.TestCase, TestHelper):
def setUp(self):
self.create_temp_dir()
src = os.path.join(_common.RSRC, 'full.m4a')
self.path = os.path.join(self.temp_dir, 'test.m4a')
src = os.path.join(_common.RSRC, b'full.m4a')
self.path = os.path.join(self.temp_dir, b'test.m4a')
shutil.copy(src, self.path)
self.mf = beets.mediafile.MediaFile(self.path)
@ -228,8 +231,8 @@ class MP4EncodingTest(unittest.TestCase, TestHelper):
class MP3EncodingTest(unittest.TestCase, TestHelper):
def setUp(self):
self.create_temp_dir()
src = os.path.join(_common.RSRC, 'full.mp3')
self.path = os.path.join(self.temp_dir, 'test.mp3')
src = os.path.join(_common.RSRC, b'full.mp3')
self.path = os.path.join(self.temp_dir, b'test.mp3')
shutil.copy(src, self.path)
self.mf = beets.mediafile.MediaFile(self.path)
@ -254,7 +257,7 @@ class ZeroLengthMediaFile(beets.mediafile.MediaFile):
class MissingAudioDataTest(unittest.TestCase):
def setUp(self):
super(MissingAudioDataTest, self).setUp()
path = os.path.join(_common.RSRC, 'full.mp3')
path = os.path.join(_common.RSRC, b'full.mp3')
self.mf = ZeroLengthMediaFile(path)
def test_bitrate_with_zero_length(self):
@ -265,7 +268,7 @@ class MissingAudioDataTest(unittest.TestCase):
class TypeTest(unittest.TestCase):
def setUp(self):
super(TypeTest, self).setUp()
path = os.path.join(_common.RSRC, 'full.mp3')
path = os.path.join(_common.RSRC, b'full.mp3')
self.mf = beets.mediafile.MediaFile(path)
def test_year_integer_in_string(self):
@ -331,8 +334,10 @@ class SoundCheckTest(unittest.TestCase):
class ID3v23Test(unittest.TestCase, TestHelper):
def _make_test(self, ext='mp3', id3v23=False):
self.create_temp_dir()
src = os.path.join(_common.RSRC, 'full.{0}'.format(ext))
self.path = os.path.join(self.temp_dir, 'test.{0}'.format(ext))
src = os.path.join(_common.RSRC,
bytestring_path('full.{0}'.format(ext)))
self.path = os.path.join(self.temp_dir,
bytestring_path('test.{0}'.format(ext)))
shutil.copy(src, self.path)
return beets.mediafile.MediaFile(self.path, id3v23=id3v23)

View file

@ -71,7 +71,7 @@ class PlayPluginTest(unittest.TestCase, TestHelper):
self.config['play']['command'] = 'echo'
self.config['play']['relative_to'] = '/something'
path = os.path.relpath(self.item.path, '/something')
path = os.path.relpath(self.item.path, b'/something')
playlist = path.decode('utf8')
self.do_test(expected_cmd='echo', expected_playlist=playlist)

View file

@ -26,7 +26,7 @@ from beets import plugins, config, ui
from beets.library import Item
from beets.dbcore import types
from beets.mediafile import MediaFile
from beets.util import displayable_path
from beets.util import displayable_path, bytestring_path
from test.test_importer import ImportHelper, AutotagStub
from test.test_ui_importer import TerminalImportSessionSetup
@ -177,7 +177,7 @@ class EventsTest(unittest.TestCase, ImportHelper, TestHelper):
def __copy_file(self, dest_path, metadata):
# Copy files
resource_path = os.path.join(RSRC, 'full.mp3')
resource_path = os.path.join(RSRC, b'full.mp3')
shutil.copy(resource_path, dest_path)
medium = MediaFile(dest_path)
# Set metadata
@ -186,11 +186,11 @@ class EventsTest(unittest.TestCase, ImportHelper, TestHelper):
medium.save()
def __create_import_dir(self, count):
self.import_dir = os.path.join(self.temp_dir, 'testsrcdir')
self.import_dir = os.path.join(self.temp_dir, b'testsrcdir')
if os.path.isdir(self.import_dir):
shutil.rmtree(self.import_dir)
self.album_path = os.path.join(self.import_dir, 'album')
self.album_path = os.path.join(self.import_dir, b'album')
os.makedirs(self.album_path)
metadata = {
@ -205,8 +205,8 @@ class EventsTest(unittest.TestCase, ImportHelper, TestHelper):
for i in range(count):
metadata['track'] = i + 1
metadata['title'] = u'Tag Title Album %d' % (i + 1)
dest_path = os.path.join(self.album_path,
'%02d - track.mp3' % (i + 1))
track_file = bytestring_path('%02d - track.mp3' % (i + 1))
dest_path = os.path.join(self.album_path, track_file)
self.__copy_file(dest_path, metadata)
self.file_paths.append(dest_path)

View file

@ -492,7 +492,7 @@ class PathQueryTest(_common.LibTestCase, TestHelper, AssertsMixin):
self.assert_albums_matched(results, [u'path album'])
def test_escape_underscore(self):
self.add_album(path='/a/_/title.mp3', title=u'with underscore',
self.add_album(path=b'/a/_/title.mp3', title=u'with underscore',
album=u'album with underscore')
q = u'path:/a/_'
results = self.lib.items(q)
@ -502,7 +502,7 @@ class PathQueryTest(_common.LibTestCase, TestHelper, AssertsMixin):
self.assert_albums_matched(results, [u'album with underscore'])
def test_escape_percent(self):
self.add_album(path='/a/%/title.mp3', title=u'with percent',
self.add_album(path=b'/a/%/title.mp3', title=u'with percent',
album=u'album with percent')
q = u'path:/a/%'
results = self.lib.items(q)
@ -512,7 +512,7 @@ class PathQueryTest(_common.LibTestCase, TestHelper, AssertsMixin):
self.assert_albums_matched(results, [u'album with percent'])
def test_escape_backslash(self):
self.add_album(path=r'/a/\x/title.mp3', title=u'with backslash',
self.add_album(path=br'/a/\x/title.mp3', title=u'with backslash',
album=u'album with backslash')
q = u'path:/a/\\\\x'
results = self.lib.items(q)
@ -522,7 +522,7 @@ class PathQueryTest(_common.LibTestCase, TestHelper, AssertsMixin):
self.assert_albums_matched(results, [u'album with backslash'])
def test_case_sensitivity(self):
self.add_album(path='/A/B/C2.mp3', title=u'caps path')
self.add_album(path=b'/A/B/C2.mp3', title=u'caps path')
makeq = partial(beets.library.PathQuery, u'path', '/A/B')
@ -615,7 +615,7 @@ class PathQueryTest(_common.LibTestCase, TestHelper, AssertsMixin):
is_path = beets.library.PathQuery.is_path_query
try:
self.touch(os.path.join('foo', 'bar'))
self.touch(os.path.join(b'foo', b'bar'))
# Temporarily change directory so relative paths work.
cur_dir = os.getcwd()

View file

@ -149,7 +149,7 @@ class SmartPlaylistTest(unittest.TestCase):
def test_playlist_update(self):
spl = SmartPlaylistPlugin()
i = Mock(path='/tagada.mp3')
i = Mock(path=b'/tagada.mp3')
i.evaluate_template.side_effect = lambda x, _: x
q = Mock()
a_q = Mock()

View file

@ -23,6 +23,7 @@ from shutil import rmtree
from test._common import unittest
from test.helper import TestHelper
from beets.util import bytestring_path
from beetsplug.thumbnails import (ThumbnailsPlugin, NORMAL_DIR, LARGE_DIR,
write_metadata_im, write_metadata_pil,
PathlibURI, GioURI)
@ -183,7 +184,7 @@ class ThumbnailsTest(unittest.TestCase, TestHelper):
@patch('beetsplug.thumbnails.ThumbnailsPlugin._check_local_ok')
def test_make_dolphin_cover_thumbnail(self, _):
plugin = ThumbnailsPlugin()
tmp = mkdtemp()
tmp = bytestring_path(mkdtemp())
album = Mock(path=tmp,
artpath=os.path.join(tmp, b"cover.jpg"))
plugin.make_dolphin_cover_thumbnail(album)

View file

@ -123,12 +123,13 @@ class RemoveTest(_common.TestCase):
self.io.install()
self.libdir = os.path.join(self.temp_dir, 'testlibdir')
self.libdir = os.path.join(self.temp_dir, b'testlibdir')
os.mkdir(self.libdir)
# Copy a file into the library.
self.lib = library.Library(':memory:', self.libdir)
self.i = library.Item.from_path(os.path.join(_common.RSRC, 'full.mp3'))
item_path = os.path.join(_common.RSRC, b'full.mp3')
self.i = library.Item.from_path(item_path)
self.lib.add(self.i)
self.i.move(True)
@ -411,11 +412,11 @@ class MoveTest(_common.TestCase):
self.io.install()
self.libdir = os.path.join(self.temp_dir, 'testlibdir')
self.libdir = os.path.join(self.temp_dir, b'testlibdir')
os.mkdir(self.libdir)
self.itempath = os.path.join(self.libdir, 'srcfile')
shutil.copy(os.path.join(_common.RSRC, 'full.mp3'), self.itempath)
self.itempath = os.path.join(self.libdir, b'srcfile')
shutil.copy(os.path.join(_common.RSRC, b'full.mp3'), self.itempath)
# Add a file to the library but don't copy it in yet.
self.lib = library.Library(':memory:', self.libdir)
@ -424,7 +425,7 @@ class MoveTest(_common.TestCase):
self.album = self.lib.add_album([self.i])
# Alternate destination directory.
self.otherdir = os.path.join(self.temp_dir, 'testotherdir')
self.otherdir = os.path.join(self.temp_dir, b'testotherdir')
def _move(self, query=(), dest=None, copy=False, album=False,
pretend=False):
@ -433,54 +434,54 @@ class MoveTest(_common.TestCase):
def test_move_item(self):
self._move()
self.i.load()
self.assertTrue('testlibdir' in self.i.path)
self.assertTrue(b'testlibdir' in self.i.path)
self.assertExists(self.i.path)
self.assertNotExists(self.itempath)
def test_copy_item(self):
self._move(copy=True)
self.i.load()
self.assertTrue('testlibdir' in self.i.path)
self.assertTrue(b'testlibdir' in self.i.path)
self.assertExists(self.i.path)
self.assertExists(self.itempath)
def test_move_album(self):
self._move(album=True)
self.i.load()
self.assertTrue('testlibdir' in self.i.path)
self.assertTrue(b'testlibdir' in self.i.path)
self.assertExists(self.i.path)
self.assertNotExists(self.itempath)
def test_copy_album(self):
self._move(copy=True, album=True)
self.i.load()
self.assertTrue('testlibdir' in self.i.path)
self.assertTrue(b'testlibdir' in self.i.path)
self.assertExists(self.i.path)
self.assertExists(self.itempath)
def test_move_item_custom_dir(self):
self._move(dest=self.otherdir)
self.i.load()
self.assertTrue('testotherdir' in self.i.path)
self.assertTrue(b'testotherdir' in self.i.path)
self.assertExists(self.i.path)
self.assertNotExists(self.itempath)
def test_move_album_custom_dir(self):
self._move(dest=self.otherdir, album=True)
self.i.load()
self.assertTrue('testotherdir' in self.i.path)
self.assertTrue(b'testotherdir' in self.i.path)
self.assertExists(self.i.path)
self.assertNotExists(self.itempath)
def test_pretend_move_item(self):
self._move(dest=self.otherdir, pretend=True)
self.i.load()
self.assertIn('srcfile', self.i.path)
self.assertIn(b'srcfile', self.i.path)
def test_pretend_move_album(self):
self._move(album=True, pretend=True)
self.i.load()
self.assertIn('srcfile', self.i.path)
self.assertIn(b'srcfile', self.i.path)
class UpdateTest(_common.TestCase):
@ -489,17 +490,18 @@ class UpdateTest(_common.TestCase):
self.io.install()
self.libdir = os.path.join(self.temp_dir, 'testlibdir')
self.libdir = os.path.join(self.temp_dir, b'testlibdir')
# Copy a file into the library.
self.lib = library.Library(':memory:', self.libdir)
self.i = library.Item.from_path(os.path.join(_common.RSRC, 'full.mp3'))
item_path = os.path.join(_common.RSRC, b'full.mp3')
self.i = library.Item.from_path(item_path)
self.lib.add(self.i)
self.i.move(True)
self.album = self.lib.add_album([self.i])
# Album art.
artfile = os.path.join(self.temp_dir, 'testart.jpg')
artfile = os.path.join(self.temp_dir, b'testart.jpg')
_common.touch(artfile)
self.album.set_art(artfile)
self.album.store()
@ -545,7 +547,7 @@ class UpdateTest(_common.TestCase):
mf.save()
self._update(move=True)
item = self.lib.items().get()
self.assertTrue(u'differentTitle' in item.path)
self.assertTrue(b'differentTitle' in item.path)
def test_modified_metadata_not_moved(self):
mf = MediaFile(self.i.path)
@ -553,7 +555,7 @@ class UpdateTest(_common.TestCase):
mf.save()
self._update(move=False)
item = self.lib.items().get()
self.assertTrue(u'differentTitle' not in item.path)
self.assertTrue(b'differentTitle' not in item.path)
def test_modified_album_metadata_moved(self):
mf = MediaFile(self.i.path)
@ -561,7 +563,7 @@ class UpdateTest(_common.TestCase):
mf.save()
self._update(move=True)
item = self.lib.items().get()
self.assertTrue(u'differentAlbum' in item.path)
self.assertTrue(b'differentAlbum' in item.path)
def test_modified_album_metadata_art_moved(self):
artpath = self.album.artpath
@ -758,7 +760,7 @@ class ConfigTest(unittest.TestCase, TestHelper, _common.Assertions):
ui._raw_main(['test'])
replacements = self.test_cmd.lib.replacements
self.assertEqual(replacements, [(re.compile(ur'[xy]'), b'z')])
self.assertEqual(replacements, [(re.compile(ur'[xy]'), 'z')])
def test_multiple_replacements_parsed(self):
with self.write_config_file() as config:
@ -988,7 +990,7 @@ class ShowChangeTest(_common.TestCase):
self.items = [_common.item()]
self.items[0].track = 1
self.items[0].path = '/path/to/file.mp3'
self.items[0].path = b'/path/to/file.mp3'
self.info = autotag.AlbumInfo(
u'the album', u'album id', u'the artist', u'artist id', [
autotag.TrackInfo(u'the title', u'track id', index=1)
@ -1143,7 +1145,7 @@ class CompletionTest(_common.TestCase):
tester.stdin.writelines(completion_script)
# Load test suite.
test_script = os.path.join(_common.RSRC, 'test_completion.sh')
test_script = os.path.join(_common.RSRC, b'test_completion.sh')
with open(test_script, 'r') as test_script:
tester.stdin.writelines(test_script)
(out, err) = tester.communicate()
@ -1160,7 +1162,7 @@ class CommonOptionsParserCliTest(unittest.TestCase, TestHelper):
self.setup_beets()
self.lib = library.Library(':memory:')
self.item = _common.item()
self.item.path = 'xxx/yyy'
self.item.path = b'xxx/yyy'
self.lib.add(self.item)
self.lib.add_album([self.item])

View file

@ -33,16 +33,16 @@ class QueryTest(_common.TestCase):
def setUp(self):
super(QueryTest, self).setUp()
self.libdir = os.path.join(self.temp_dir, 'testlibdir')
self.libdir = os.path.join(self.temp_dir, b'testlibdir')
os.mkdir(self.libdir)
# Add a file to the library but don't copy it in yet.
self.lib = library.Library(':memory:', self.libdir)
# Alternate destination directory.
self.otherdir = os.path.join(self.temp_dir, 'testotherdir')
self.otherdir = os.path.join(self.temp_dir, b'testotherdir')
def add_item(self, filename='srcfile', templatefile='full.mp3'):
def add_item(self, filename=b'srcfile', templatefile=b'full.mp3'):
itempath = os.path.join(self.libdir, filename)
shutil.copy(os.path.join(_common.RSRC, templatefile), itempath)
item = library.Item.from_path(itempath)