diff --git a/beets/importer.py b/beets/importer.py index ca035dc7d..b190329ce 100644 --- a/beets/importer.py +++ b/beets/importer.py @@ -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 diff --git a/beets/library.py b/beets/library.py index 5ae0182e3..b9d9d4ffc 100644 --- a/beets/library.py +++ b/beets/library.py @@ -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): diff --git a/test/helper.py b/test/helper.py index 3196e265e..db3de22aa 100644 --- a/test/helper.py +++ b/test/helper.py @@ -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 diff --git a/test/test_art.py b/test/test_art.py index 1b12b76f6..348835c4c 100644 --- a/test/test_art.py +++ b/test/test_art.py @@ -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() diff --git a/test/test_convert.py b/test/test_convert.py index 2959fc582..d3a1206be 100644 --- a/test/test_convert.py +++ b/test/test_convert.py @@ -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') diff --git a/test/test_embedart.py b/test/test_embedart.py index 27939112b..2bb357001 100644 --- a/test/test_embedart.py +++ b/test/test_embedart.py @@ -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 diff --git a/test/test_filefilter.py b/test/test_filefilter.py index 56da5ef25..09b6d94a4 100644 --- a/test/test_filefilter.py +++ b/test/test_filefilter.py @@ -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) diff --git a/test/test_files.py b/test/test_files.py index 5af8bd5ef..884aa40d0 100644 --- a/test/test_files.py +++ b/test/test_files.py @@ -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') )) diff --git a/test/test_importadded.py b/test/test_importadded.py index 80491aa0a..474f56384 100644 --- a/test/test_importadded.py +++ b/test/test_importadded.py @@ -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(): diff --git a/test/test_importer.py b/test/test_importer.py index 73d1ceb1d..93a034ee6 100644 --- a/test/test_importer.py +++ b/test/test_importer.py @@ -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 diff --git a/test/test_ipfs.py b/test/test_ipfs.py index 1c2972000..61f10dc92 100644 --- a/test/test_ipfs.py +++ b/test/test_ipfs.py @@ -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) diff --git a/test/test_library.py b/test/test_library.py index 3afe3c0dd..19b987d58 100644 --- a/test/test_library.py +++ b/test/test_library.py @@ -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) diff --git a/test/test_mediafile.py b/test/test_mediafile.py index 0ee93ef42..8e8d0a2bf 100644 --- a/test/test_mediafile.py +++ b/test/test_mediafile.py @@ -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)) diff --git a/test/test_mediafile_edge.py b/test/test_mediafile_edge.py index bf86e7f2a..26d88ae74 100644 --- a/test/test_mediafile_edge.py +++ b/test/test_mediafile_edge.py @@ -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) diff --git a/test/test_play.py b/test/test_play.py index cd0f4211c..469377c75 100644 --- a/test/test_play.py +++ b/test/test_play.py @@ -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) diff --git a/test/test_plugins.py b/test/test_plugins.py index f02a55cf1..d45e317ca 100644 --- a/test/test_plugins.py +++ b/test/test_plugins.py @@ -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) diff --git a/test/test_query.py b/test/test_query.py index 4595cf827..2f8014015 100644 --- a/test/test_query.py +++ b/test/test_query.py @@ -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() diff --git a/test/test_smartplaylist.py b/test/test_smartplaylist.py index e1ce36951..dd8d7ca36 100644 --- a/test/test_smartplaylist.py +++ b/test/test_smartplaylist.py @@ -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() diff --git a/test/test_thumbnails.py b/test/test_thumbnails.py index f3e2858ad..06dd0a8e9 100644 --- a/test/test_thumbnails.py +++ b/test/test_thumbnails.py @@ -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) diff --git a/test/test_ui.py b/test/test_ui.py index 7c46afc2f..0ca4f7115 100644 --- a/test/test_ui.py +++ b/test/test_ui.py @@ -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]) diff --git a/test/test_ui_commands.py b/test/test_ui_commands.py index 29da4f456..5cd1131eb 100644 --- a/test/test_ui_commands.py +++ b/test/test_ui_commands.py @@ -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)