add missing syspath conversions (1/3, tests)

these are mostly in the tests, which didn't cause issues since the
affected directories usually have nice ASCII paths. For consistency, it
is nicer to always invoke syspath. That also avoids deprecation warnings
for the bytestring interfaces on Python <= 3.5. The bytestring
interfaces were undeprecated with PEP 529 in Python 3.6, such that we
didn't observe any actual failures.
This commit is contained in:
wisp3rwind 2021-01-19 19:21:36 +01:00
parent 854fec2634
commit 1ef6b90786
18 changed files with 220 additions and 176 deletions

View file

@ -29,6 +29,7 @@ import beets.library # noqa: E402
from beets import importer, logging # noqa: E402
from beets.ui import commands # noqa: E402
from beets import util # noqa: E402
from beets.util import bytestring_path, syspath # noqa: E402
import beets # noqa: E402
# Make sure the development versions of the plugins are used
@ -140,11 +141,11 @@ class Assertions:
"""A mixin with additional unit test assertions."""
def assertExists(self, path): # noqa
self.assertTrue(os.path.exists(util.syspath(path)),
self.assertTrue(os.path.exists(syspath(path)),
f'file does not exist: {path!r}')
def assertNotExists(self, path): # noqa
self.assertFalse(os.path.exists(util.syspath(path)),
self.assertFalse(os.path.exists(syspath(path)),
f'file exists: {path!r}')
def assert_equal_path(self, a, b):
@ -186,8 +187,8 @@ class TestCase(unittest.TestCase, Assertions):
self.io = DummyIO()
def tearDown(self):
if os.path.isdir(self.temp_dir):
shutil.rmtree(self.temp_dir)
if os.path.isdir(syspath(self.temp_dir)):
shutil.rmtree(syspath(self.temp_dir))
if self._old_home is None:
del os.environ['HOME']
else:
@ -325,7 +326,7 @@ class DummyIO:
# Utility.
def touch(path):
open(path, 'a').close()
open(syspath(path), 'a').close()
class Bag:
@ -351,16 +352,13 @@ class TempDirMixin:
"""Create a temporary directory and assign it into `self.temp_dir`.
Call `remove_temp_dir` later to delete it.
"""
path = tempfile.mkdtemp()
if not isinstance(path, bytes):
path = path.encode('utf8')
self.temp_dir = path
self.temp_dir = bytestring_path(tempfile.mkdtemp())
def remove_temp_dir(self):
"""Delete the temporary directory created by `create_temp_dir`.
"""
if os.path.isdir(self.temp_dir):
shutil.rmtree(self.temp_dir)
if os.path.isdir(syspath(self.temp_dir)):
shutil.rmtree(syspath(self.temp_dir))
# Platform mocking.

View file

@ -49,7 +49,7 @@ from beets import importer
from beets.autotag.hooks import AlbumInfo, TrackInfo
from mediafile import MediaFile, Image
from beets import util
from beets.util import MoveOperation
from beets.util import MoveOperation, syspath, bytestring_path
# TODO Move AutotagMock here
from test import _common
@ -181,7 +181,7 @@ class TestHelper:
self.config['threaded'] = False
self.libdir = os.path.join(self.temp_dir, b'libdir')
os.mkdir(self.libdir)
os.mkdir(syspath(self.libdir))
self.config['directory'] = util.py3_path(self.libdir)
if disk:
@ -242,17 +242,17 @@ class TestHelper:
`self.temp_dir` and creates a `ImportSessionFixture` for this path.
"""
import_dir = os.path.join(self.temp_dir, b'import')
if not os.path.isdir(import_dir):
os.mkdir(import_dir)
if not os.path.isdir(syspath(import_dir)):
os.mkdir(syspath(import_dir))
album_no = 0
while album_count:
album = util.bytestring_path(f'album {album_no}')
album_dir = os.path.join(import_dir, album)
if os.path.exists(album_dir):
if os.path.exists(syspath(album_dir)):
album_no += 1
continue
os.mkdir(album_dir)
os.mkdir(syspath(album_dir))
album_count -= 1
track_no = 0
@ -262,11 +262,11 @@ class TestHelper:
src = os.path.join(_common.RSRC, b'full.mp3')
title_file = util.bytestring_path(f'{title}.mp3')
dest = os.path.join(album_dir, title_file)
if os.path.exists(dest):
if os.path.exists(syspath(dest)):
track_no += 1
continue
album_item_count -= 1
shutil.copy(src, dest)
shutil.copy(syspath(src), syspath(dest))
mediafile = MediaFile(dest)
mediafile.update({
'artist': 'artist',
@ -405,8 +405,9 @@ class TestHelper:
"""
src = os.path.join(_common.RSRC, util.bytestring_path('full.' + ext))
handle, path = mkstemp()
path = bytestring_path(path)
os.close(handle)
shutil.copyfile(src, path)
shutil.copyfile(syspath(src), syspath(path))
if images:
mediafile = MediaFile(path)
@ -428,7 +429,7 @@ class TestHelper:
def remove_mediafile_fixtures(self):
if hasattr(self, '_mediafile_fixtures'):
for path in self._mediafile_fixtures:
os.remove(path)
os.remove(syspath(path))
def _get_item_count(self):
if not hasattr(self, '__item_count'):
@ -467,7 +468,7 @@ class TestHelper:
def remove_temp_dir(self):
"""Delete the temporary directory created by `create_temp_dir`.
"""
shutil.rmtree(self.temp_dir)
shutil.rmtree(syspath(self.temp_dir))
def touch(self, path, dir=None, content=''):
"""Create a file at `path` with given content.
@ -483,10 +484,10 @@ class TestHelper:
path = os.path.join(self.temp_dir, path)
parent = os.path.dirname(path)
if not os.path.isdir(parent):
os.makedirs(util.syspath(parent))
if not os.path.isdir(syspath(parent)):
os.makedirs(syspath(parent))
with open(util.syspath(path), 'a+') as f:
with open(syspath(path), 'a+') as f:
f.write(content)
return path

View file

@ -31,6 +31,7 @@ from beets import library
from beets import importer
from beets import logging
from beets import util
from beets.util import syspath
from beets.util.artresizer import ArtResizer
import confuse
@ -197,7 +198,7 @@ class FSArtTest(UseThePlugin):
def setUp(self):
super().setUp()
self.dpath = os.path.join(self.temp_dir, b'arttest')
os.mkdir(self.dpath)
os.mkdir(syspath(self.dpath))
self.source = fetchart.FileSystem(logger, self.plugin.config)
self.settings = Settings(cautious=False,
@ -251,7 +252,7 @@ class CombinedTest(FetchImageHelper, UseThePlugin, CAAHelper):
def setUp(self):
super().setUp()
self.dpath = os.path.join(self.temp_dir, b'arttest')
os.mkdir(self.dpath)
os.mkdir(syspath(self.dpath))
def test_main_interface_returns_amazon_art(self):
self.mock_response(self.AMAZON_URL)
@ -641,10 +642,13 @@ class ArtImporterTest(UseThePlugin):
# Test library.
self.libpath = os.path.join(self.temp_dir, b'tmplib.blb')
self.libdir = os.path.join(self.temp_dir, b'tmplib')
os.mkdir(self.libdir)
os.mkdir(os.path.join(self.libdir, b'album'))
os.mkdir(syspath(self.libdir))
os.mkdir(syspath(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)
shutil.copyfile(
syspath(os.path.join(_common.RSRC, b'full.mp3')),
syspath(itempath),
)
self.lib = library.Library(self.libpath)
self.i = _common.item()
self.i.path = itempath
@ -716,7 +720,7 @@ class ArtImporterTest(UseThePlugin):
def test_do_not_delete_original_if_already_in_place(self):
artdest = os.path.join(os.path.dirname(self.i.path), b'cover.jpg')
shutil.copyfile(self.art_file, artdest)
shutil.copyfile(syspath(self.art_file), syspath(artdest))
self.afa_response = fetchart.Candidate(logger, path=artdest)
self._fetch_art(True)

View file

@ -25,6 +25,7 @@ from test.helper import control_stdin, capture_log
from mediafile import MediaFile
from beets import util
from beets.util import bytestring_path, displayable_path, syspath
def shell_quote(text):
@ -53,15 +54,15 @@ class TestHelper(helper.TestHelper):
"""
display_tag = tag
tag = tag.encode('utf-8')
self.assertTrue(os.path.isfile(path),
self.assertTrue(os.path.isfile(syspath(path)),
'{} is not a file'.format(
util.displayable_path(path)))
displayable_path(path)))
with open(path, 'rb') as f:
f.seek(-len(display_tag), os.SEEK_END)
self.assertEqual(f.read(), tag,
'{} is not tagged with {}'
.format(
util.displayable_path(path),
displayable_path(path),
display_tag))
def assertNoFileTag(self, path, tag): # noqa
@ -70,15 +71,15 @@ class TestHelper(helper.TestHelper):
"""
display_tag = tag
tag = tag.encode('utf-8')
self.assertTrue(os.path.isfile(path),
self.assertTrue(os.path.isfile(syspath(path)),
'{} is not a file'.format(
util.displayable_path(path)))
displayable_path(path)))
with open(path, 'rb') as f:
f.seek(-len(tag), os.SEEK_END)
self.assertNotEqual(f.read(), tag,
'{} is unexpectedly tagged with {}'
.format(
util.displayable_path(path),
displayable_path(path),
display_tag))
@ -117,7 +118,7 @@ class ImportConvertTest(unittest.TestCase, TestHelper):
item = self.lib.items().get()
self.assertIsNotNone(item)
self.assertTrue(os.path.isfile(item.path))
self.assertTrue(os.path.isfile(syspath(item.path)))
def test_delete_originals(self):
self.config['convert']['delete_originals'] = True
@ -166,7 +167,7 @@ class ConvertCliTest(unittest.TestCase, TestHelper, ConvertCommand):
self.item = self.album.items()[0]
self.load_plugins('convert')
self.convert_dest = util.bytestring_path(
self.convert_dest = bytestring_path(
os.path.join(self.temp_dir, b'convert_dest')
)
self.config['convert'] = {
@ -202,7 +203,7 @@ class ConvertCliTest(unittest.TestCase, TestHelper, ConvertCommand):
with control_stdin('n'):
self.run_convert()
converted = os.path.join(self.convert_dest, b'converted.mp3')
self.assertFalse(os.path.isfile(converted))
self.assertFalse(os.path.isfile(syspath(converted)))
def test_convert_keep_new(self):
self.assertEqual(os.path.splitext(self.item.path)[1], b'.ogg')
@ -243,7 +244,7 @@ class ConvertCliTest(unittest.TestCase, TestHelper, ConvertCommand):
def test_pretend(self):
self.run_convert('--pretend')
converted = os.path.join(self.convert_dest, b'converted.mp3')
self.assertFalse(os.path.exists(converted))
self.assertFalse(os.path.exists(syspath(converted)))
def test_empty_query(self):
with capture_log('beets.convert') as logs:

View file

@ -25,7 +25,7 @@ from test.test_art_resize import DummyIMBackend
from mediafile import MediaFile
from beets import config, logging, ui
from beets.util import syspath, displayable_path
from beets.util import bytestring_path, displayable_path, syspath
from beets.util.artresizer import ArtResizer
from beets import art
from test.test_art import FetchImageHelper
@ -110,6 +110,7 @@ class EmbedartCliTest(TestHelper, FetchImageHelper):
logging.getLogger('beets.embedart').setLevel(logging.DEBUG)
handle, tmp_path = tempfile.mkstemp()
tmp_path = bytestring_path(tmp_path)
os.write(handle, self.image_data)
os.close(handle)
@ -119,9 +120,11 @@ class EmbedartCliTest(TestHelper, FetchImageHelper):
config['embedart']['remove_art_file'] = True
self.run_command('embedart', '-y')
if os.path.isfile(tmp_path):
os.remove(tmp_path)
self.fail(f'Artwork file {tmp_path} was not deleted')
if os.path.isfile(syspath(tmp_path)):
os.remove(syspath(tmp_path))
self.fail('Artwork file {} was not deleted'.format(
displayable_path(tmp_path)
))
def test_art_file_missing(self):
self.add_album_fixture()
@ -134,13 +137,14 @@ class EmbedartCliTest(TestHelper, FetchImageHelper):
logging.getLogger('beets.embedart').setLevel(logging.DEBUG)
handle, tmp_path = tempfile.mkstemp()
tmp_path = bytestring_path(tmp_path)
os.write(handle, b'I am not an image.')
os.close(handle)
try:
self.run_command('embedart', '-y', '-f', tmp_path)
finally:
os.remove(tmp_path)
os.remove(syspath(tmp_path))
mediafile = MediaFile(syspath(album.items()[0].path))
self.assertFalse(mediafile.images) # No image added.

View file

@ -25,7 +25,7 @@ from test.helper import capture_log
from test.test_importer import ImportHelper
from beets import config
from mediafile import MediaFile
from beets.util import displayable_path, bytestring_path
from beets.util import displayable_path, bytestring_path, syspath
from beetsplug.filefilter import FileFilterPlugin
@ -42,7 +42,7 @@ class FileFilterPluginTest(unittest.TestCase, ImportHelper):
def __copy_file(self, dest_path, metadata):
# Copy files
resource_path = os.path.join(_common.RSRC, b'full.mp3')
shutil.copy(resource_path, dest_path)
shutil.copy(syspath(resource_path), syspath(dest_path))
medium = MediaFile(dest_path)
# Set metadata
for attr in metadata:
@ -51,14 +51,14 @@ class FileFilterPluginTest(unittest.TestCase, ImportHelper):
def __create_import_dir(self, count):
self.import_dir = os.path.join(self.temp_dir, b'testsrcdir')
if os.path.isdir(self.import_dir):
shutil.rmtree(self.import_dir)
if os.path.isdir(syspath(self.import_dir)):
shutil.rmtree(syspath(self.import_dir))
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)
os.makedirs(syspath(self.album_path))
os.makedirs(syspath(self.misc_path))
metadata = {
'artist': 'Tag Artist',

View file

@ -25,7 +25,7 @@ from test import _common
from test._common import item, touch
import beets.library
from beets import util
from beets.util import MoveOperation
from beets.util import MoveOperation, bytestring_path, syspath
class MoveTest(_common.TestCase):
@ -34,7 +34,10 @@ class MoveTest(_common.TestCase):
# make a temporary file
self.path = join(self.temp_dir, b'temp.mp3')
shutil.copy(join(_common.RSRC, b'full.mp3'), self.path)
shutil.copy(
syspath(join(_common.RSRC, b'full.mp3')),
syspath(self.path),
)
# add it to a temporary library
self.lib = beets.library.Library(':memory:')
@ -43,7 +46,7 @@ class MoveTest(_common.TestCase):
# set up the destination
self.libdir = join(self.temp_dir, b'testlibdir')
os.mkdir(self.libdir)
os.mkdir(syspath(self.libdir))
self.lib.directory = self.libdir
self.lib.path_formats = [('default',
join('$artist', '$album', '$title'))]
@ -139,20 +142,20 @@ class MoveTest(_common.TestCase):
def test_read_only_file_copied_writable(self):
# Make the source file read-only.
os.chmod(self.path, 0o444)
os.chmod(syspath(self.path), 0o444)
try:
self.i.move(operation=MoveOperation.COPY)
self.assertTrue(os.access(self.i.path, os.W_OK))
self.assertTrue(os.access(syspath(self.i.path), os.W_OK))
finally:
# Make everything writable so it can be cleaned up.
os.chmod(self.path, 0o777)
os.chmod(self.i.path, 0o777)
os.chmod(syspath(self.path), 0o777)
os.chmod(syspath(self.i.path), 0o777)
def test_move_avoids_collision_with_existing_file(self):
# Make a conflicting file at the destination.
dest = self.i.destination()
os.makedirs(os.path.dirname(dest))
os.makedirs(syspath(os.path.dirname(dest)))
touch(dest)
self.i.move()
@ -164,8 +167,11 @@ class MoveTest(_common.TestCase):
def test_link_arrives(self):
self.i.move(operation=MoveOperation.LINK)
self.assertExists(self.dest)
self.assertTrue(os.path.islink(self.dest))
self.assertEqual(os.readlink(self.dest), self.path)
self.assertTrue(os.path.islink(syspath(self.dest)))
self.assertEqual(
bytestring_path(os.readlink(syspath(self.dest))),
self.path,
)
@unittest.skipUnless(_common.HAVE_SYMLINK, "need symlinks")
def test_link_does_not_depart(self):
@ -181,8 +187,8 @@ class MoveTest(_common.TestCase):
def test_hardlink_arrives(self):
self.i.move(operation=MoveOperation.HARDLINK)
self.assertExists(self.dest)
s1 = os.stat(self.path)
s2 = os.stat(self.dest)
s1 = os.stat(syspath(self.path))
s2 = os.stat(syspath(self.dest))
self.assertTrue(
(s1[stat.ST_INO], s1[stat.ST_DEV]) ==
(s2[stat.ST_INO], s2[stat.ST_DEV])
@ -271,8 +277,8 @@ class AlbumFileTest(_common.TestCase):
self.ai.store()
self.i.load()
self.assertFalse(os.path.exists(oldpath))
self.assertTrue(os.path.exists(self.i.path))
self.assertFalse(os.path.exists(syspath(oldpath)))
self.assertTrue(os.path.exists(syspath(self.i.path)))
def test_albuminfo_move_copies_file(self):
oldpath = self.i.path
@ -281,8 +287,8 @@ class AlbumFileTest(_common.TestCase):
self.ai.store()
self.i.load()
self.assertTrue(os.path.exists(oldpath))
self.assertTrue(os.path.exists(self.i.path))
self.assertTrue(os.path.exists(syspath(oldpath)))
self.assertTrue(os.path.exists(syspath(self.i.path)))
@unittest.skipUnless(_common.HAVE_REFLINK, "need reflink")
def test_albuminfo_move_reflinks_file(self):
@ -326,21 +332,21 @@ class ArtFileTest(_common.TestCase):
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))
self.assertTrue(os.path.exists(syspath(self.art)))
self.ai.remove(True)
self.assertFalse(os.path.exists(self.art))
self.assertFalse(os.path.exists(syspath(self.art)))
def test_art_moves_with_album(self):
self.assertTrue(os.path.exists(self.art))
self.assertTrue(os.path.exists(syspath(self.art)))
oldpath = self.i.path
self.ai.album = 'newAlbum'
self.ai.move()
self.i.load()
self.assertNotEqual(self.i.path, oldpath)
self.assertFalse(os.path.exists(self.art))
self.assertFalse(os.path.exists(syspath(self.art)))
newart = self.lib.get_album(self.i).art_destination(self.art)
self.assertTrue(os.path.exists(newart))
self.assertTrue(os.path.exists(syspath(newart)))
def test_art_moves_with_album_to_custom_dir(self):
# Move the album to another directory.
@ -355,7 +361,7 @@ class ArtFileTest(_common.TestCase):
self.assertTrue(b'testotherdir' in newart)
def test_setart_copies_image(self):
os.remove(self.art)
util.remove(self.art)
newart = os.path.join(self.libdir, b'newart.jpg')
touch(newart)
@ -367,10 +373,10 @@ class ArtFileTest(_common.TestCase):
self.assertEqual(ai.artpath, None)
ai.set_art(newart)
self.assertTrue(os.path.exists(ai.artpath))
self.assertTrue(os.path.exists(syspath(ai.artpath)))
def test_setart_to_existing_art_works(self):
os.remove(self.art)
util.remove(self.art)
# Original art.
newart = os.path.join(self.libdir, b'newart.jpg')
@ -384,7 +390,7 @@ class ArtFileTest(_common.TestCase):
# Set the art again.
ai.set_art(ai.artpath)
self.assertTrue(os.path.exists(ai.artpath))
self.assertTrue(os.path.exists(syspath(ai.artpath)))
def test_setart_to_existing_but_unset_art_works(self):
newart = os.path.join(self.libdir, b'newart.jpg')
@ -397,11 +403,11 @@ class ArtFileTest(_common.TestCase):
# Copy the art to the destination.
artdest = ai.art_destination(newart)
shutil.copy(newart, artdest)
shutil.copy(syspath(newart), syspath(artdest))
# Set the art again.
ai.set_art(artdest)
self.assertTrue(os.path.exists(ai.artpath))
self.assertTrue(os.path.exists(syspath(ai.artpath)))
def test_setart_to_conflicting_file_gets_new_path(self):
newart = os.path.join(self.libdir, b'newart.jpg')
@ -423,11 +429,11 @@ class ArtFileTest(_common.TestCase):
os.path.dirname(ai.artpath))
def test_setart_sets_permissions(self):
os.remove(self.art)
util.remove(self.art)
newart = os.path.join(self.libdir, b'newart.jpg')
touch(newart)
os.chmod(newart, 0o400) # read-only
os.chmod(syspath(newart), 0o400) # read-only
try:
i2 = item()
@ -437,14 +443,14 @@ class ArtFileTest(_common.TestCase):
i2.move(operation=MoveOperation.COPY)
ai.set_art(newart)
mode = stat.S_IMODE(os.stat(ai.artpath).st_mode)
mode = stat.S_IMODE(os.stat(syspath(ai.artpath)).st_mode)
self.assertTrue(mode & stat.S_IRGRP)
self.assertTrue(os.access(ai.artpath, os.W_OK))
self.assertTrue(os.access(syspath(ai.artpath), os.W_OK))
finally:
# Make everything writable so it can be cleaned up.
os.chmod(newart, 0o777)
os.chmod(ai.artpath, 0o777)
os.chmod(syspath(newart), 0o777)
os.chmod(syspath(ai.artpath), 0o777)
def test_move_last_file_moves_albumart(self):
oldartpath = self.lib.albums()[0].artpath
@ -609,9 +615,9 @@ class PruneTest(_common.TestCase):
super().setUp()
self.base = os.path.join(self.temp_dir, b'testdir')
os.mkdir(self.base)
os.mkdir(syspath(self.base))
self.sub = os.path.join(self.base, b'subdir')
os.mkdir(self.sub)
os.mkdir(syspath(self.sub))
def test_prune_existent_directory(self):
util.prune_dirs(self.sub, self.base)
@ -629,10 +635,10 @@ class WalkTest(_common.TestCase):
super().setUp()
self.base = os.path.join(self.temp_dir, b'testdir')
os.mkdir(self.base)
os.mkdir(syspath(self.base))
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'))
os.mkdir(syspath(os.path.join(self.base, b'd')))
touch(os.path.join(self.base, b'd', b'z'))
def test_sorted_files(self):
@ -669,7 +675,7 @@ class UniquePathTest(_common.TestCase):
super().setUp()
self.base = os.path.join(self.temp_dir, b'testdir')
os.mkdir(self.base)
os.mkdir(syspath(self.base))
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'))
@ -696,16 +702,16 @@ class MkDirAllTest(_common.TestCase):
def test_parent_exists(self):
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, b'foo', b'bar', b'baz')
))
self.assertTrue(os.path.isdir(syspath(
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, b'foo', b'bar', b'baz', b'qux.mp3')
util.mkdirall(path)
self.assertTrue(not os.path.exists(
os.path.join(self.temp_dir, b'foo', b'bar', b'baz', b'qux.mp3')
))
self.assertTrue(not os.path.exists(syspath(
os.path.join(self.temp_dir, b'foo', b'bar', b'baz', b'qux.mp3'),
)))
def suite():

View file

@ -20,7 +20,7 @@ import unittest
from test.test_importer import ImportHelper, AutotagStub
from beets import importer
from beets import util
from beets.util import displayable_path, syspath
from beetsplug.importadded import ImportAddedPlugin
_listeners = ImportAddedPlugin.listeners
@ -37,7 +37,7 @@ def preserve_plugin_listeners():
def modify_mtimes(paths, offset=-60000):
for i, path in enumerate(paths, start=1):
mstat = os.stat(path)
os.utime(path, (mstat.st_atime, mstat.st_mtime + offset * i))
os.utime(syspath(path), (mstat.st_atime, mstat.st_mtime + offset * i))
class ImportAddedTest(unittest.TestCase, ImportHelper):
@ -71,7 +71,7 @@ class ImportAddedTest(unittest.TestCase, ImportHelper):
if m.title.replace('Tag', 'Applied') == item.title:
return m
raise AssertionError("No MediaFile found for Item " +
util.displayable_path(item.path))
displayable_path(item.path))
def assertEqualTimes(self, first, second, msg=None): # noqa
"""For comparing file modification times at a sufficient precision"""
@ -126,7 +126,7 @@ class ImportAddedTest(unittest.TestCase, ImportHelper):
for item_path, added_after in items_added_after.items():
self.assertEqualTimes(items_added_before[item_path], added_after,
"reimport modified Item.added for " +
util.displayable_path(item_path))
displayable_path(item_path))
def test_import_singletons_with_added_dates(self):
self.config['import']['singletons'] = True
@ -164,7 +164,7 @@ class ImportAddedTest(unittest.TestCase, ImportHelper):
for item_path, added_after in items_added_after.items():
self.assertEqualTimes(items_added_before[item_path], added_after,
"reimport modified Item.added for " +
util.displayable_path(item_path))
displayable_path(item_path))
def suite():

View file

@ -29,7 +29,6 @@ from unittest.mock import patch, Mock
import unittest
from test import _common
from beets.util import displayable_path, bytestring_path, py3_path
from test.helper import TestHelper, has_program, capture_log
from test.helper import ImportSessionFixture
from beets import importer
@ -40,6 +39,7 @@ from beets.autotag import AlbumInfo, TrackInfo, AlbumMatch
from beets import config
from beets import logging
from beets import util
from beets.util import displayable_path, bytestring_path, py3_path, syspath
class AutotagStub:
@ -173,11 +173,11 @@ class ImportHelper(TestHelper):
:param count: Number of files to create
"""
self.import_dir = os.path.join(self.temp_dir, b'testsrcdir')
if os.path.isdir(self.import_dir):
shutil.rmtree(self.import_dir)
if os.path.isdir(syspath(self.import_dir)):
shutil.rmtree(syspath(self.import_dir))
album_path = os.path.join(self.import_dir, b'the_album')
os.makedirs(album_path)
os.makedirs(syspath(album_path))
resource_path = os.path.join(_common.RSRC, b'full.mp3')
@ -196,7 +196,7 @@ class ImportHelper(TestHelper):
album_path,
bytestring_path('track_%d.mp3' % (i + 1))
)
shutil.copy(resource_path, medium_path)
shutil.copy(syspath(resource_path), syspath(medium_path))
medium = MediaFile(medium_path)
# Set metadata
@ -241,7 +241,7 @@ class ImportHelper(TestHelper):
self.assertNotExists(os.path.join(self.libdir, *segments))
def assert_lib_dir_empty(self):
self.assertEqual(len(os.listdir(self.libdir)), 0)
self.assertEqual(len(os.listdir(syspath(self.libdir))), 0)
@_common.slow_test()
@ -293,8 +293,7 @@ class NonAutotaggedImportTest(_common.TestCase, ImportHelper):
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, b'the_album', b'alog.log'), 'w')
f.close()
self.touch(os.path.join(self.import_dir, b'the_album', b'alog.log'))
config['clutter'] = ['*.log']
config['import']['move'] = True
@ -350,9 +349,9 @@ class NonAutotaggedImportTest(_common.TestCase, ImportHelper):
util.bytestring_path(f'{mediafile.title}.mp3')
)
self.assertExists(filename)
self.assertTrue(os.path.islink(filename))
self.assertTrue(os.path.islink(syspath(filename)))
self.assert_equal_path(
util.bytestring_path(os.readlink(filename)),
util.bytestring_path(os.readlink(syspath(filename))),
mediafile.path
)
@ -367,8 +366,8 @@ class NonAutotaggedImportTest(_common.TestCase, ImportHelper):
util.bytestring_path(f'{mediafile.title}.mp3')
)
self.assertExists(filename)
s1 = os.stat(mediafile.path)
s2 = os.stat(filename)
s1 = os.stat(syspath(mediafile.path))
s2 = os.stat(syspath(filename))
self.assertTrue(
(s1[stat.ST_INO], s1[stat.ST_DEV]) ==
(s2[stat.ST_INO], s2[stat.ST_DEV])
@ -377,9 +376,10 @@ class NonAutotaggedImportTest(_common.TestCase, ImportHelper):
def create_archive(session):
(handle, path) = mkstemp(dir=py3_path(session.temp_dir))
path = bytestring_path(path)
os.close(handle)
archive = ZipFile(py3_path(path), mode='w')
archive.write(os.path.join(_common.RSRC, b'full.mp3'),
archive.write(syspath(os.path.join(_common.RSRC, b'full.mp3')),
'full.mp3')
archive.close()
path = bytestring_path(path)
@ -433,10 +433,11 @@ class ImportZipTest(unittest.TestCase, ImportHelper):
class ImportTarTest(ImportZipTest):
def create_archive(self):
(handle, path) = mkstemp(dir=self.temp_dir)
(handle, path) = mkstemp(dir=syspath(self.temp_dir))
path = bytestring_path(path)
os.close(handle)
archive = TarFile(py3_path(path), mode='w')
archive.add(os.path.join(_common.RSRC, b'full.mp3'),
archive.add(syspath(os.path.join(_common.RSRC, b'full.mp3')),
'full.mp3')
archive.close()
return path
@ -534,7 +535,7 @@ class ImportSingletonTest(_common.TestCase, ImportHelper):
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)
util.copy(resource_path, single_path)
import_files = [
os.path.join(self.import_dir, b'the_album'),
single_path
@ -696,8 +697,9 @@ class ImportTest(_common.TestCase, ImportHelper):
self.assertEqual(self.lib.items().get(), None)
def test_skip_non_album_dirs(self):
self.assertTrue(os.path.isdir(
os.path.join(self.import_dir, b'the_album')))
self.assertTrue(os.path.isdir(syspath(
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()
@ -1543,7 +1545,10 @@ class IncrementalImportTest(unittest.TestCase, TestHelper):
def _mkmp3(path):
shutil.copyfile(os.path.join(_common.RSRC, b'min.mp3'), path)
shutil.copyfile(
syspath(os.path.join(_common.RSRC, b'min.mp3')),
syspath(path),
)
class AlbumsInDirTest(_common.TestCase):
@ -1552,13 +1557,13 @@ class AlbumsInDirTest(_common.TestCase):
# create a directory structure for testing
self.base = os.path.abspath(os.path.join(self.temp_dir, b'tempdir'))
os.mkdir(self.base)
os.mkdir(syspath(self.base))
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'))
os.mkdir(syspath(os.path.join(self.base, b'album1')))
os.mkdir(syspath(os.path.join(self.base, b'album2')))
os.mkdir(syspath(os.path.join(self.base, b'more')))
os.mkdir(syspath(os.path.join(self.base, b'more', b'album3')))
os.mkdir(syspath(os.path.join(self.base, b'more', b'album4')))
_mkmp3(os.path.join(self.base, b'album1', b'album1song1.mp3'))
_mkmp3(os.path.join(self.base, b'album1', b'album1song2.mp3'))
@ -1597,7 +1602,7 @@ class MultiDiscAlbumsInDirTest(_common.TestCase):
otherwise, we use Unicode names.
"""
self.base = os.path.abspath(os.path.join(self.temp_dir, b'tempdir'))
os.mkdir(self.base)
os.mkdir(syspath(self.base))
name = b'CAT' if ascii else util.bytestring_path('C\xc1T')
name_alt_case = b'CAt' if ascii else util.bytestring_path('C\xc1t')
@ -1644,7 +1649,7 @@ class MultiDiscAlbumsInDirTest(_common.TestCase):
self.files = [self._normalize_path(p) for p in self.files]
for path in self.dirs:
os.mkdir(util.syspath(path))
os.mkdir(syspath(path))
if files:
for path in self.files:
_mkmp3(util.syspath(path))
@ -1839,7 +1844,7 @@ class ImportPretendTest(_common.TestCase, ImportHelper):
self._create_import_dir(1)
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)
shutil.copy(syspath(resource_path), syspath(single_path))
self.import_paths = [
os.path.join(self.import_dir, b'the_album'),
single_path
@ -1852,7 +1857,7 @@ class ImportPretendTest(_common.TestCase, ImportHelper):
def __create_empty_import_dir(self):
path = os.path.join(self.temp_dir, b'empty')
os.makedirs(path)
os.makedirs(syspath(path))
self.empty_path = path
def __run(self, import_paths, singletons=True):

View file

@ -41,7 +41,7 @@ class InfoTest(unittest.TestCase, TestHelper):
mediafile.save()
out = self.run_with_output('info', path)
self.assertIn(path, out)
self.assertIn(displayable_path(path), out)
self.assertIn('albumartist: AAA', out)
self.assertIn('disctitle: DDD', out)
self.assertIn('genres: a; b; c', out)

View file

@ -1169,7 +1169,10 @@ class MtimeTest(_common.TestCase):
def setUp(self):
super().setUp()
self.ipath = os.path.join(self.temp_dir, b'testfile.mp3')
shutil.copy(os.path.join(_common.RSRC, b'full.mp3'), self.ipath)
shutil.copy(
syspath(os.path.join(_common.RSRC, b'full.mp3')),
syspath(self.ipath),
)
self.i = beets.library.Item.from_path(self.ipath)
self.lib = beets.library.Library(':memory:')
self.lib.add(self.i)

View file

@ -23,7 +23,7 @@ from test import _common
from beets.library import Item
import mediafile
from beets.plugins import BeetsPlugin
from beets.util import bytestring_path
from beets.util import bytestring_path, syspath
field_extension = mediafile.MediaField(
@ -40,7 +40,7 @@ class ExtendedFieldTestMixin(_common.TestCase):
name = bytestring_path(name + '.' + extension)
src = os.path.join(_common.RSRC, name)
target = os.path.join(self.temp_dir, name)
shutil.copy(src, target)
shutil.copy(syspath(src), syspath(target))
return mediafile.MediaFile(target)
def test_extended_field_write(self):

View file

@ -180,7 +180,7 @@ class EventsTest(unittest.TestCase, ImportHelper, TestHelper):
def __copy_file(self, dest_path, metadata):
# Copy files
resource_path = os.path.join(RSRC, b'full.mp3')
shutil.copy(resource_path, dest_path)
shutil.copy(syspath(resource_path), syspath(dest_path))
medium = MediaFile(dest_path)
# Set metadata
for attr in metadata:
@ -189,8 +189,8 @@ class EventsTest(unittest.TestCase, ImportHelper, TestHelper):
def __create_import_dir(self, count):
self.import_dir = os.path.join(self.temp_dir, b'testsrcdir')
if os.path.isdir(self.import_dir):
shutil.rmtree(self.import_dir)
if os.path.isdir(syspath(self.import_dir)):
shutil.rmtree(syspath(self.import_dir))
self.album_path = os.path.join(self.import_dir, b'album')
os.makedirs(self.album_path)

View file

@ -31,6 +31,7 @@ from beets.dbcore.query import (NoneQuery, ParsingError,
InvalidQueryArgumentValueError)
from beets.library import Library, Item
from beets import util
from beets.util import syspath
# Because the absolute path begins with something like C:, we
# can't disambiguate it from an ordinary query.
@ -662,7 +663,7 @@ class PathQueryTest(_common.LibTestCase, TestHelper, AssertsMixin):
# Temporarily change directory so relative paths work.
cur_dir = os.getcwd()
try:
os.chdir(self.temp_dir)
os.chdir(syspath(self.temp_dir))
self.assertTrue(is_path_query('foo/'))
self.assertTrue(is_path_query('foo/bar'))
self.assertTrue(is_path_query('foo/bar:tagada'))

View file

@ -167,7 +167,7 @@ class SmartPlaylistTest(unittest.TestCase):
try:
spl.update_playlists(lib)
except Exception:
rmtree(dir)
rmtree(syspath(dir))
raise
lib.items.assert_called_once_with(q, None)
@ -177,7 +177,7 @@ class SmartPlaylistTest(unittest.TestCase):
self.assertTrue(path.exists(m3u_filepath))
with open(syspath(m3u_filepath), 'rb') as f:
content = f.read()
rmtree(dir)
rmtree(syspath(dir))
self.assertEqual(content, b'/tagada.mp3\n')
@ -207,14 +207,14 @@ class SmartPlaylistCLITest(unittest.TestCase, TestHelper):
self.run_with_output('splupdate', 'my_playlist')
m3u_path = path.join(self.temp_dir, b'my_playlist.m3u')
self.assertTrue(path.exists(m3u_path))
with open(m3u_path, 'rb') as f:
with open(syspath(m3u_path), 'rb') as f:
self.assertEqual(f.read(), self.item.path + b"\n")
remove(m3u_path)
remove(syspath(m3u_path))
self.run_with_output('splupdate', 'my_playlist.m3u')
with open(m3u_path, 'rb') as f:
with open(syspath(m3u_path), 'rb') as f:
self.assertEqual(f.read(), self.item.path + b"\n")
remove(m3u_path)
remove(syspath(m3u_path))
self.run_with_output('splupdate')
for name in (b'my_playlist.m3u', b'all.m3u'):

View file

@ -21,7 +21,7 @@ import unittest
from test.helper import TestHelper
from beets.util import bytestring_path
from beets.util import bytestring_path, syspath
from beetsplug.thumbnails import (ThumbnailsPlugin, NORMAL_DIR, LARGE_DIR,
PathlibURI, GioURI)
@ -51,6 +51,7 @@ class ThumbnailsTest(unittest.TestCase, TestHelper):
b"/path/to/thumbnail",
metadata,
)
# FIXME: Plugin should use syspath
mock_stat.assert_called_once_with(album.artpath)
@patch('beetsplug.thumbnails.os')
@ -68,13 +69,16 @@ class ThumbnailsTest(unittest.TestCase, TestHelper):
mock_artresizer.shared.can_write_metadata = True
def exists(path):
# FIXME: Plugin should use syspath
if path == NORMAL_DIR:
return False
# FIXME: Plugin should use syspath
if path == LARGE_DIR:
return True
raise ValueError(f"unexpected path {path!r}")
mock_os.path.exists = exists
plugin = ThumbnailsPlugin()
# FIXME: Plugin should use syspath
mock_os.makedirs.assert_called_once_with(NORMAL_DIR)
self.assertTrue(plugin._check_local_ok())
@ -109,6 +113,7 @@ class ThumbnailsTest(unittest.TestCase, TestHelper):
thumbnail_dir = os.path.normpath(b"/thumbnail/dir")
md5_file = os.path.join(thumbnail_dir, b"md5")
path_to_art = os.path.normpath(b"/path/to/art")
path_to_resized_art = os.path.normpath(b'/path/to/resized/artwork')
mock_os.path.join = os.path.join # don't mock that function
plugin = ThumbnailsPlugin()
@ -120,34 +125,43 @@ class ThumbnailsTest(unittest.TestCase, TestHelper):
mock_os.path.exists.return_value = False
def os_stat(target):
# FIXME: Plugin should use syspath
if target == md5_file:
return Mock(st_mtime=1)
# FIXME: Plugin should use syspath
elif target == path_to_art:
return Mock(st_mtime=2)
else:
raise ValueError(f"invalid target {target}")
mock_os.stat.side_effect = os_stat
mock_resize = mock_artresizer.shared.resize
mock_resize.return_value = path_to_resized_art
plugin.make_cover_thumbnail(album, 12345, thumbnail_dir)
# FIXME: Plugin should use syspath
mock_os.path.exists.assert_called_once_with(md5_file)
mock_os.stat.has_calls([call(md5_file), call(path_to_art)],
mock_os.stat.has_calls([call(syspath(md5_file)),
call(syspath(path_to_art))],
any_order=True)
resize = mock_artresizer.shared.resize
resize.assert_called_once_with(12345, path_to_art, md5_file)
plugin.add_tags.assert_called_once_with(album, resize.return_value)
mock_shutils.move.assert_called_once_with(resize.return_value,
mock_resize.assert_called_once_with(12345, path_to_art, md5_file)
plugin.add_tags.assert_called_once_with(album, path_to_resized_art)
# FIXME: Plugin should use syspath
mock_shutils.move.assert_called_once_with(path_to_resized_art,
md5_file)
# now test with recent thumbnail & with force
mock_os.path.exists.return_value = True
plugin.force = False
resize.reset_mock()
mock_resize.reset_mock()
def os_stat(target):
# FIXME: Plugin should use syspath
if target == md5_file:
return Mock(st_mtime=3)
# FIXME: Plugin should use syspath
elif target == path_to_art:
return Mock(st_mtime=2)
else:
@ -155,12 +169,12 @@ class ThumbnailsTest(unittest.TestCase, TestHelper):
mock_os.stat.side_effect = os_stat
plugin.make_cover_thumbnail(album, 12345, thumbnail_dir)
self.assertEqual(resize.call_count, 0)
self.assertEqual(mock_resize.call_count, 0)
# and with force
plugin.config['force'] = True
plugin.make_cover_thumbnail(album, 12345, thumbnail_dir)
resize.assert_called_once_with(12345, path_to_art, md5_file)
mock_resize.assert_called_once_with(12345, path_to_art, md5_file)
@patch('beetsplug.thumbnails.ThumbnailsPlugin._check_local_ok')
def test_make_dolphin_cover_thumbnail(self, _):
@ -184,7 +198,7 @@ class ThumbnailsTest(unittest.TestCase, TestHelper):
[b"[Desktop Entry]", b"Icon=./cover.jpg"]
)
rmtree(tmp)
rmtree(syspath(tmp))
@patch('beetsplug.thumbnails.ThumbnailsPlugin._check_local_ok')
@patch('beetsplug.thumbnails.ArtResizer')

View file

@ -114,7 +114,7 @@ class RemoveTest(_common.TestCase, TestHelper):
self.io.install()
self.libdir = os.path.join(self.temp_dir, b'testlibdir')
os.mkdir(self.libdir)
os.mkdir(syspath(self.libdir))
# Copy a file into the library.
self.lib = library.Library(':memory:', self.libdir)
@ -128,26 +128,26 @@ class RemoveTest(_common.TestCase, TestHelper):
commands.remove_items(self.lib, '', False, False, False)
items = self.lib.items()
self.assertEqual(len(list(items)), 0)
self.assertTrue(os.path.exists(self.i.path))
self.assertTrue(os.path.exists(syspath(self.i.path)))
def test_remove_items_with_delete(self):
self.io.addinput('y')
commands.remove_items(self.lib, '', False, True, False)
items = self.lib.items()
self.assertEqual(len(list(items)), 0)
self.assertFalse(os.path.exists(self.i.path))
self.assertFalse(os.path.exists(syspath(self.i.path)))
def test_remove_items_with_force_no_delete(self):
commands.remove_items(self.lib, '', False, False, True)
items = self.lib.items()
self.assertEqual(len(list(items)), 0)
self.assertTrue(os.path.exists(self.i.path))
self.assertTrue(os.path.exists(syspath(self.i.path)))
def test_remove_items_with_force_delete(self):
commands.remove_items(self.lib, '', False, True, True)
items = self.lib.items()
self.assertEqual(len(list(items)), 0)
self.assertFalse(os.path.exists(self.i.path))
self.assertFalse(os.path.exists(syspath(self.i.path)))
def test_remove_items_select_with_delete(self):
i2 = library.Item.from_path(self.item_path)
@ -458,10 +458,13 @@ class MoveTest(_common.TestCase):
self.io.install()
self.libdir = os.path.join(self.temp_dir, b'testlibdir')
os.mkdir(self.libdir)
os.mkdir(syspath(self.libdir))
self.itempath = os.path.join(self.libdir, b'srcfile')
shutil.copy(os.path.join(_common.RSRC, b'full.mp3'), self.itempath)
shutil.copy(
syspath(os.path.join(_common.RSRC, b'full.mp3')),
syspath(self.itempath),
)
# Add a file to the library but don't copy it in yet.
self.lib = library.Library(':memory:', self.libdir)
@ -573,7 +576,7 @@ class UpdateTest(_common.TestCase):
_common.touch(artfile)
self.album.set_art(artfile)
self.album.store()
os.remove(artfile)
util.remove(artfile)
def _update(self, query=(), album=False, move=False, reset_mtime=True,
fields=None):
@ -586,23 +589,23 @@ class UpdateTest(_common.TestCase):
def test_delete_removes_item(self):
self.assertTrue(list(self.lib.items()))
os.remove(self.i.path)
os.remove(self.i2.path)
util.remove(self.i.path)
util.remove(self.i2.path)
self._update()
self.assertFalse(list(self.lib.items()))
def test_delete_removes_album(self):
self.assertTrue(self.lib.albums())
os.remove(self.i.path)
os.remove(self.i2.path)
util.remove(self.i.path)
util.remove(self.i2.path)
self._update()
self.assertFalse(self.lib.albums())
def test_delete_removes_album_art(self):
artpath = self.album.artpath
self.assertExists(artpath)
os.remove(self.i.path)
os.remove(self.i2.path)
util.remove(self.i.path)
util.remove(self.i2.path)
self._update()
self.assertNotExists(artpath)
@ -694,7 +697,7 @@ class UpdateTest(_common.TestCase):
mf.save()
# Make in-memory mtime match on-disk mtime.
self.i.mtime = os.path.getmtime(self.i.path)
self.i.mtime = os.path.getmtime(syspath(self.i.path))
self.i.store()
self._update(reset_mtime=False)
@ -837,20 +840,20 @@ class ConfigTest(unittest.TestCase, TestHelper, _common.Assertions):
self.user_config_dir = os.path.join(
self.temp_dir, b'.config', b'beets'
)
os.makedirs(self.user_config_dir)
os.makedirs(syspath(self.user_config_dir))
self.user_config_path = os.path.join(self.user_config_dir,
b'config.yaml')
# Custom BEETSDIR
self.beetsdir = os.path.join(self.temp_dir, b'beetsdir')
os.makedirs(self.beetsdir)
os.makedirs(syspath(self.beetsdir))
self._reset_config()
self.load_plugins()
def tearDown(self):
commands.default_commands.pop()
os.chdir(self._orig_cwd)
os.chdir(syspath(self._orig_cwd))
if self._old_home is not None:
os.environ['HOME'] = self._old_home
if self._old_appdata is None:
@ -1034,7 +1037,7 @@ class ConfigTest(unittest.TestCase, TestHelper, _common.Assertions):
def test_command_line_option_relative_to_working_dir(self):
config.read()
os.chdir(self.temp_dir)
os.chdir(syspath(self.temp_dir))
self.run_command('--library', 'foo.db', 'test', lib=None)
self.assert_equal_path(config['library'].as_filename(),
os.path.join(os.getcwd(), 'foo.db'))
@ -1308,7 +1311,7 @@ class CompletionTest(_common.TestCase, TestHelper):
# Load bash_completion library.
for path in commands.BASH_COMPLETION_PATHS:
if os.path.exists(util.syspath(path)):
if os.path.exists(syspath(path)):
bash_completion = path
break
else:

View file

@ -25,6 +25,7 @@ from test import _common
from beets import library
from beets import ui
from beets.ui import commands
from beets.util import syspath
class QueryTest(_common.TestCase):
@ -32,7 +33,7 @@ class QueryTest(_common.TestCase):
super().setUp()
self.libdir = os.path.join(self.temp_dir, b'testlibdir')
os.mkdir(self.libdir)
os.mkdir(syspath(self.libdir))
# Add a file to the library but don't copy it in yet.
self.lib = library.Library(':memory:', self.libdir)
@ -42,7 +43,10 @@ class QueryTest(_common.TestCase):
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)
shutil.copy(
syspath(os.path.join(_common.RSRC, templatefile)),
syspath(itempath),
)
item = library.Item.from_path(itempath)
self.lib.add(item)
return item, itempath