mirror of
https://github.com/beetbox/beets.git
synced 2026-01-06 16:02:53 +01:00
Merge pull request #5068 from sumpfralle/reusable-test-code
Allow reuse of test code in other projects
This commit is contained in:
commit
5c964ce77d
70 changed files with 466 additions and 409 deletions
19
beets/test/__init__.py
Normal file
19
beets/test/__init__.py
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# This file is part of beets.
|
||||
# Copyright 2024, Lars Kruse
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
# a copy of this software and associated documentation files (the
|
||||
# "Software"), to deal in the Software without restriction, including
|
||||
# without limitation the rights to use, copy, modify, merge, publish,
|
||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
||||
# permit persons to whom the Software is furnished to do so, subject to
|
||||
# the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
|
||||
"""This module contains components of beets' test environment, which
|
||||
may be of use for testing procedures of external libraries or programs.
|
||||
For example the 'TestHelper' class may be useful for creating an
|
||||
in-memory beets library filled with a few example items.
|
||||
"""
|
||||
|
|
@ -22,8 +22,6 @@ import time
|
|||
import unittest
|
||||
from contextlib import contextmanager
|
||||
|
||||
# Mangle the search path to include the beets sources.
|
||||
sys.path.insert(0, "..")
|
||||
import beets # noqa: E402
|
||||
import beets.library # noqa: E402
|
||||
|
||||
|
|
@ -35,12 +33,29 @@ from beets.ui import commands # noqa: E402
|
|||
from beets.util import bytestring_path, syspath # noqa: E402
|
||||
|
||||
beetsplug.__path__ = [
|
||||
os.path.abspath(os.path.join(__file__, "..", "..", "beetsplug"))
|
||||
os.path.abspath(
|
||||
os.path.join(
|
||||
os.path.dirname(__file__),
|
||||
os.path.pardir,
|
||||
os.path.pardir,
|
||||
"beetsplug",
|
||||
)
|
||||
)
|
||||
]
|
||||
|
||||
# Test resources path.
|
||||
RSRC = util.bytestring_path(os.path.join(os.path.dirname(__file__), "rsrc"))
|
||||
PLUGINPATH = os.path.join(os.path.dirname(__file__), "rsrc", "beetsplug")
|
||||
RSRC = util.bytestring_path(
|
||||
os.path.abspath(
|
||||
os.path.join(
|
||||
os.path.dirname(__file__),
|
||||
os.path.pardir,
|
||||
os.path.pardir,
|
||||
"test",
|
||||
"rsrc",
|
||||
)
|
||||
)
|
||||
)
|
||||
PLUGINPATH = os.path.join(RSRC.decode(), "beetsplug")
|
||||
|
||||
# Propagate to root logger so the test runner can capture it
|
||||
log = logging.getLogger("beets")
|
||||
|
|
@ -40,16 +40,15 @@ from enum import Enum
|
|||
from io import StringIO
|
||||
from tempfile import mkdtemp, mkstemp
|
||||
|
||||
# TODO Move AutotagMock here
|
||||
from test import _common
|
||||
|
||||
from mediafile import Image, MediaFile
|
||||
|
||||
import beets
|
||||
import beets.plugins
|
||||
from beets import config, importer, logging, util
|
||||
from beets import autotag, config, importer, logging, util
|
||||
from beets.autotag.hooks import AlbumInfo, TrackInfo
|
||||
from beets.library import Album, Item, Library
|
||||
from beets.test import _common
|
||||
from beets.ui.commands import TerminalImportSession
|
||||
from beets.util import MoveOperation, bytestring_path, syspath
|
||||
|
||||
|
||||
|
|
@ -496,6 +495,115 @@ class TestHelper:
|
|||
return path
|
||||
|
||||
|
||||
class ImportHelper(TestHelper):
|
||||
"""Provides tools to setup a library, a directory containing files that are
|
||||
to be imported and an import session. The class also provides stubs for the
|
||||
autotagging library and several assertions for the library.
|
||||
"""
|
||||
|
||||
def setup_beets(self, disk=False):
|
||||
super().setup_beets(disk)
|
||||
self.lib.path_formats = [
|
||||
("default", os.path.join("$artist", "$album", "$title")),
|
||||
("singleton:true", os.path.join("singletons", "$title")),
|
||||
("comp:true", os.path.join("compilations", "$album", "$title")),
|
||||
]
|
||||
|
||||
def _create_import_dir(self, count=3):
|
||||
"""Creates a directory with media files to import.
|
||||
Sets ``self.import_dir`` to the path of the directory. Also sets
|
||||
``self.import_media`` to a list :class:`MediaFile` for all the files in
|
||||
the directory.
|
||||
|
||||
The directory has following layout
|
||||
the_album/
|
||||
track_1.mp3
|
||||
track_2.mp3
|
||||
track_3.mp3
|
||||
|
||||
:param count: Number of files to create
|
||||
"""
|
||||
self.import_dir = os.path.join(self.temp_dir, b"testsrcdir")
|
||||
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(syspath(album_path))
|
||||
|
||||
resource_path = os.path.join(_common.RSRC, b"full.mp3")
|
||||
|
||||
metadata = {
|
||||
"artist": "Tag Artist",
|
||||
"album": "Tag Album",
|
||||
"albumartist": None,
|
||||
"mb_trackid": None,
|
||||
"mb_albumid": None,
|
||||
"comp": None,
|
||||
}
|
||||
self.media_files = []
|
||||
for i in range(count):
|
||||
# Copy files
|
||||
medium_path = os.path.join(
|
||||
album_path, bytestring_path("track_%d.mp3" % (i + 1))
|
||||
)
|
||||
shutil.copy(syspath(resource_path), syspath(medium_path))
|
||||
medium = MediaFile(medium_path)
|
||||
|
||||
# Set metadata
|
||||
metadata["track"] = i + 1
|
||||
metadata["title"] = "Tag Title %d" % (i + 1)
|
||||
for attr in metadata:
|
||||
setattr(medium, attr, metadata[attr])
|
||||
medium.save()
|
||||
self.media_files.append(medium)
|
||||
self.import_media = self.media_files
|
||||
|
||||
def _setup_import_session(
|
||||
self,
|
||||
import_dir=None,
|
||||
delete=False,
|
||||
threaded=False,
|
||||
copy=True,
|
||||
singletons=False,
|
||||
move=False,
|
||||
autotag=True,
|
||||
link=False,
|
||||
hardlink=False,
|
||||
):
|
||||
config["import"]["copy"] = copy
|
||||
config["import"]["delete"] = delete
|
||||
config["import"]["timid"] = True
|
||||
config["threaded"] = False
|
||||
config["import"]["singletons"] = singletons
|
||||
config["import"]["move"] = move
|
||||
config["import"]["autotag"] = autotag
|
||||
config["import"]["resume"] = False
|
||||
config["import"]["link"] = link
|
||||
config["import"]["hardlink"] = hardlink
|
||||
|
||||
self.importer = ImportSessionFixture(
|
||||
self.lib,
|
||||
loghandler=None,
|
||||
query=None,
|
||||
paths=[import_dir or self.import_dir],
|
||||
)
|
||||
|
||||
def assert_file_in_lib(self, *segments):
|
||||
"""Join the ``segments`` and assert that this path exists in the
|
||||
library directory.
|
||||
"""
|
||||
self.assertExists(os.path.join(self.libdir, *segments))
|
||||
|
||||
def assert_file_not_in_lib(self, *segments):
|
||||
"""Join the ``segments`` and assert that this path does not
|
||||
exist in the library directory.
|
||||
"""
|
||||
self.assertNotExists(os.path.join(self.libdir, *segments))
|
||||
|
||||
def assert_lib_dir_empty(self):
|
||||
self.assertEqual(len(os.listdir(syspath(self.libdir))), 0)
|
||||
|
||||
|
||||
class ImportSessionFixture(importer.ImportSession):
|
||||
"""ImportSession that can be controlled programaticaly.
|
||||
|
||||
|
|
@ -561,6 +669,86 @@ class ImportSessionFixture(importer.ImportSession):
|
|||
task.should_merge_duplicates = True
|
||||
|
||||
|
||||
class TerminalImportSessionFixture(TerminalImportSession):
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.io = kwargs.pop("io")
|
||||
super().__init__(*args, **kwargs)
|
||||
self._choices = []
|
||||
|
||||
default_choice = importer.action.APPLY
|
||||
|
||||
def add_choice(self, choice):
|
||||
self._choices.append(choice)
|
||||
|
||||
def clear_choices(self):
|
||||
self._choices = []
|
||||
|
||||
def choose_match(self, task):
|
||||
self._add_choice_input()
|
||||
return super().choose_match(task)
|
||||
|
||||
def choose_item(self, task):
|
||||
self._add_choice_input()
|
||||
return super().choose_item(task)
|
||||
|
||||
def _add_choice_input(self):
|
||||
try:
|
||||
choice = self._choices.pop(0)
|
||||
except IndexError:
|
||||
choice = self.default_choice
|
||||
|
||||
if choice == importer.action.APPLY:
|
||||
self.io.addinput("A")
|
||||
elif choice == importer.action.ASIS:
|
||||
self.io.addinput("U")
|
||||
elif choice == importer.action.ALBUMS:
|
||||
self.io.addinput("G")
|
||||
elif choice == importer.action.TRACKS:
|
||||
self.io.addinput("T")
|
||||
elif choice == importer.action.SKIP:
|
||||
self.io.addinput("S")
|
||||
elif isinstance(choice, int):
|
||||
self.io.addinput("M")
|
||||
self.io.addinput(str(choice))
|
||||
self._add_choice_input()
|
||||
else:
|
||||
raise Exception("Unknown choice %s" % choice)
|
||||
|
||||
|
||||
class TerminalImportSessionSetup:
|
||||
"""Overwrites ImportHelper._setup_import_session to provide a terminal importer"""
|
||||
|
||||
def _setup_import_session(
|
||||
self,
|
||||
import_dir=None,
|
||||
delete=False,
|
||||
threaded=False,
|
||||
copy=True,
|
||||
singletons=False,
|
||||
move=False,
|
||||
autotag=True,
|
||||
):
|
||||
config["import"]["copy"] = copy
|
||||
config["import"]["delete"] = delete
|
||||
config["import"]["timid"] = True
|
||||
config["threaded"] = False
|
||||
config["import"]["singletons"] = singletons
|
||||
config["import"]["move"] = move
|
||||
config["import"]["autotag"] = autotag
|
||||
config["import"]["resume"] = False
|
||||
|
||||
if not hasattr(self, "io"):
|
||||
self.io = _common.DummyIO()
|
||||
self.io.install()
|
||||
self.importer = TerminalImportSessionFixture(
|
||||
self.lib,
|
||||
loghandler=None,
|
||||
query=None,
|
||||
io=self.io,
|
||||
paths=[import_dir or self.import_dir],
|
||||
)
|
||||
|
||||
|
||||
def generate_album_info(album_id, track_values):
|
||||
"""Return `AlbumInfo` populated with mock data.
|
||||
|
||||
|
|
@ -634,3 +822,105 @@ TRACK_INFO_FIELDS = [
|
|||
"data_source",
|
||||
"data_url",
|
||||
]
|
||||
|
||||
|
||||
class AutotagStub:
|
||||
"""Stub out MusicBrainz album and track matcher and control what the
|
||||
autotagger returns.
|
||||
"""
|
||||
|
||||
NONE = "NONE"
|
||||
IDENT = "IDENT"
|
||||
GOOD = "GOOD"
|
||||
BAD = "BAD"
|
||||
MISSING = "MISSING"
|
||||
"""Generate an album match for all but one track
|
||||
"""
|
||||
|
||||
length = 2
|
||||
matching = IDENT
|
||||
|
||||
def install(self):
|
||||
self.mb_match_album = autotag.mb.match_album
|
||||
self.mb_match_track = autotag.mb.match_track
|
||||
self.mb_album_for_id = autotag.mb.album_for_id
|
||||
self.mb_track_for_id = autotag.mb.track_for_id
|
||||
|
||||
autotag.mb.match_album = self.match_album
|
||||
autotag.mb.match_track = self.match_track
|
||||
autotag.mb.album_for_id = self.album_for_id
|
||||
autotag.mb.track_for_id = self.track_for_id
|
||||
|
||||
return self
|
||||
|
||||
def restore(self):
|
||||
autotag.mb.match_album = self.mb_match_album
|
||||
autotag.mb.match_track = self.mb_match_track
|
||||
autotag.mb.album_for_id = self.mb_album_for_id
|
||||
autotag.mb.track_for_id = self.mb_track_for_id
|
||||
|
||||
def match_album(self, albumartist, album, tracks, extra_tags):
|
||||
if self.matching == self.IDENT:
|
||||
yield self._make_album_match(albumartist, album, tracks)
|
||||
|
||||
elif self.matching == self.GOOD:
|
||||
for i in range(self.length):
|
||||
yield self._make_album_match(albumartist, album, tracks, i)
|
||||
|
||||
elif self.matching == self.BAD:
|
||||
for i in range(self.length):
|
||||
yield self._make_album_match(albumartist, album, tracks, i + 1)
|
||||
|
||||
elif self.matching == self.MISSING:
|
||||
yield self._make_album_match(albumartist, album, tracks, missing=1)
|
||||
|
||||
def match_track(self, artist, title):
|
||||
yield TrackInfo(
|
||||
title=title.replace("Tag", "Applied"),
|
||||
track_id="trackid",
|
||||
artist=artist.replace("Tag", "Applied"),
|
||||
artist_id="artistid",
|
||||
length=1,
|
||||
index=0,
|
||||
)
|
||||
|
||||
def album_for_id(self, mbid):
|
||||
return None
|
||||
|
||||
def track_for_id(self, mbid):
|
||||
return None
|
||||
|
||||
def _make_track_match(self, artist, album, number):
|
||||
return TrackInfo(
|
||||
title="Applied Title %d" % number,
|
||||
track_id="match %d" % number,
|
||||
artist=artist,
|
||||
length=1,
|
||||
index=0,
|
||||
)
|
||||
|
||||
def _make_album_match(self, artist, album, tracks, distance=0, missing=0):
|
||||
if distance:
|
||||
id = " " + "M" * distance
|
||||
else:
|
||||
id = ""
|
||||
if artist is None:
|
||||
artist = "Various Artists"
|
||||
else:
|
||||
artist = artist.replace("Tag", "Applied") + id
|
||||
album = album.replace("Tag", "Applied") + id
|
||||
|
||||
track_infos = []
|
||||
for i in range(tracks - missing):
|
||||
track_infos.append(self._make_track_match(artist, album, i + 1))
|
||||
|
||||
return AlbumInfo(
|
||||
artist=artist,
|
||||
album=album,
|
||||
tracks=track_infos,
|
||||
va=False,
|
||||
album_id="albumid" + id,
|
||||
artist_id="artistid" + id,
|
||||
albumtype="soundtrack",
|
||||
data_source="match_source",
|
||||
)
|
||||
|
|
@ -290,6 +290,10 @@ For plugin developers:
|
|||
overwrite the function defined by the other plugin.
|
||||
Now, beets will raise an exception when this happens.
|
||||
:bug:`5002`
|
||||
* Allow reuse of some parts of beets' testing components. This may ease the
|
||||
work for externally developed plugins or related software (e.g. the beets
|
||||
plugin for Mopidy), if they need to create an in-memory instance of a beets
|
||||
music library for their tests.
|
||||
|
||||
For packagers:
|
||||
|
||||
|
|
|
|||
|
|
@ -117,6 +117,7 @@ per-file-ignores =
|
|||
./beets/__main__.py:D
|
||||
./beets/importer.py:D
|
||||
./beets/plugins.py:D
|
||||
./beets/test/*:D
|
||||
./beets/util/bluelet.py:D
|
||||
./beets/util/enumeration.py:D
|
||||
./beets/util/artresizer.py:D
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@
|
|||
import json
|
||||
import os.path
|
||||
import unittest
|
||||
from test._common import RSRC
|
||||
|
||||
from beets.test._common import RSRC
|
||||
from beetsplug.acousticbrainz import ABSCHEME, AcousticPlugin
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@
|
|||
"""
|
||||
|
||||
import unittest
|
||||
from test.helper import TestHelper
|
||||
|
||||
from beets.test.helper import TestHelper
|
||||
from beets.ui import UserError
|
||||
|
||||
PLUGIN_NAME = "advancedrewrite"
|
||||
|
|
|
|||
|
|
@ -16,9 +16,9 @@
|
|||
|
||||
|
||||
import unittest
|
||||
from test.helper import TestHelper
|
||||
|
||||
from beets.autotag.mb import VARIOUS_ARTISTS_ID
|
||||
from beets.test.helper import TestHelper
|
||||
from beetsplug.albumtypes import AlbumTypesPlugin
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -18,8 +18,6 @@
|
|||
import os
|
||||
import shutil
|
||||
import unittest
|
||||
from test import _common
|
||||
from test.helper import capture_log
|
||||
from unittest.mock import patch
|
||||
|
||||
import confuse
|
||||
|
|
@ -27,6 +25,8 @@ import responses
|
|||
|
||||
from beets import config, importer, library, logging, util
|
||||
from beets.autotag import AlbumInfo, AlbumMatch
|
||||
from beets.test import _common
|
||||
from beets.test.helper import capture_log
|
||||
from beets.util import syspath
|
||||
from beets.util.artresizer import ArtResizer
|
||||
from beetsplug import fetchart
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@
|
|||
|
||||
|
||||
import unittest
|
||||
from test.helper import TestHelper, capture_stdout
|
||||
|
||||
from beets import logging
|
||||
from beets.test.helper import TestHelper, capture_stdout
|
||||
|
||||
|
||||
class BareascPluginTest(unittest.TestCase, TestHelper):
|
||||
|
|
|
|||
|
|
@ -17,10 +17,10 @@
|
|||
|
||||
import unittest
|
||||
from datetime import timedelta
|
||||
from test import _common
|
||||
from test.helper import TestHelper
|
||||
|
||||
from beets import library
|
||||
from beets.test import _common
|
||||
from beets.test.helper import TestHelper
|
||||
from beetsplug import beatport
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -16,9 +16,9 @@
|
|||
|
||||
|
||||
import unittest
|
||||
from test.helper import TestHelper
|
||||
|
||||
from beets import config, ui
|
||||
from beets.test.helper import TestHelper
|
||||
from beetsplug import bucket
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -18,12 +18,12 @@ import os.path
|
|||
import re
|
||||
import sys
|
||||
import unittest
|
||||
from test import _common, helper
|
||||
from test.helper import capture_log, control_stdin
|
||||
|
||||
from mediafile import MediaFile
|
||||
|
||||
from beets import util
|
||||
from beets.test import _common, helper
|
||||
from beets.test.helper import capture_log, control_stdin
|
||||
from beets.util import bytestring_path, displayable_path
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -16,11 +16,11 @@
|
|||
"""
|
||||
|
||||
import unittest
|
||||
from test import _common
|
||||
from test._common import Bag
|
||||
from test.helper import capture_log
|
||||
|
||||
from beets import config
|
||||
from beets.test import _common
|
||||
from beets.test._common import Bag
|
||||
from beets.test.helper import capture_log
|
||||
from beets.util.id_extractors import extract_discogs_id_regex
|
||||
from beetsplug.discogs import DiscogsPlugin
|
||||
|
||||
|
|
|
|||
|
|
@ -14,14 +14,18 @@
|
|||
|
||||
import codecs
|
||||
import unittest
|
||||
from test import _common
|
||||
from test.helper import TestHelper, control_stdin
|
||||
from test.test_importer import AutotagStub, ImportHelper
|
||||
from test.test_ui_importer import TerminalImportSessionSetup
|
||||
from unittest.mock import patch
|
||||
|
||||
from beets.dbcore.query import TrueQuery
|
||||
from beets.library import Item
|
||||
from beets.test import _common
|
||||
from beets.test.helper import (
|
||||
AutotagStub,
|
||||
ImportHelper,
|
||||
TerminalImportSessionSetup,
|
||||
TestHelper,
|
||||
control_stdin,
|
||||
)
|
||||
from beetsplug.edit import EditPlugin
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -17,8 +17,6 @@ import os.path
|
|||
import shutil
|
||||
import tempfile
|
||||
import unittest
|
||||
from test import _common
|
||||
from test.helper import TestHelper
|
||||
from test.plugins.test_art import FetchImageHelper
|
||||
from test.test_art_resize import DummyIMBackend
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
|
@ -26,6 +24,8 @@ from unittest.mock import MagicMock, patch
|
|||
from mediafile import MediaFile
|
||||
|
||||
from beets import art, config, logging, ui
|
||||
from beets.test import _common
|
||||
from beets.test.helper import TestHelper
|
||||
from beets.util import bytestring_path, displayable_path, syspath
|
||||
from beets.util.artresizer import ArtResizer
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import unittest
|
||||
from test.helper import TestHelper
|
||||
|
||||
import responses
|
||||
|
||||
from beets.test.helper import TestHelper
|
||||
from beetsplug import embyupdate
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -19,10 +19,11 @@
|
|||
import json
|
||||
import re # used to test csv format
|
||||
import unittest
|
||||
from test.helper import TestHelper
|
||||
from xml.etree import ElementTree
|
||||
from xml.etree.ElementTree import Element
|
||||
|
||||
from beets.test.helper import TestHelper
|
||||
|
||||
|
||||
class ExportPluginTest(unittest.TestCase, TestHelper):
|
||||
def setUp(self):
|
||||
|
|
|
|||
|
|
@ -17,9 +17,9 @@ import ctypes
|
|||
import os
|
||||
import sys
|
||||
import unittest
|
||||
from test.helper import TestHelper
|
||||
|
||||
from beets import util
|
||||
from beets.test.helper import TestHelper
|
||||
|
||||
|
||||
class FetchartCliTest(unittest.TestCase, TestHelper):
|
||||
|
|
|
|||
|
|
@ -19,13 +19,12 @@
|
|||
import os
|
||||
import shutil
|
||||
import unittest
|
||||
from test import _common
|
||||
from test.helper import capture_log
|
||||
from test.test_importer import ImportHelper
|
||||
|
||||
from mediafile import MediaFile
|
||||
|
||||
from beets import config
|
||||
from beets.test import _common
|
||||
from beets.test.helper import ImportHelper, capture_log
|
||||
from beets.util import bytestring_path, displayable_path, syspath
|
||||
from beetsplug.filefilter import FileFilterPlugin
|
||||
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@
|
|||
|
||||
|
||||
import unittest
|
||||
from test.helper import TestHelper
|
||||
|
||||
from beets.test.helper import TestHelper
|
||||
from beetsplug import ftintitle
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -17,10 +17,10 @@ import os.path
|
|||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
from test import _common
|
||||
from test.helper import TestHelper, capture_log
|
||||
|
||||
from beets import config, plugins
|
||||
from beets.test import _common
|
||||
from beets.test.helper import TestHelper, capture_log
|
||||
|
||||
|
||||
def get_temporary_path():
|
||||
|
|
|
|||
|
|
@ -17,9 +17,9 @@
|
|||
|
||||
import os
|
||||
import unittest
|
||||
from test.test_importer import AutotagStub, ImportHelper
|
||||
|
||||
from beets import importer
|
||||
from beets.test.helper import AutotagStub, ImportHelper
|
||||
from beets.util import displayable_path, syspath
|
||||
from beetsplug.importadded import ImportAddedPlugin
|
||||
|
||||
|
|
|
|||
|
|
@ -14,10 +14,10 @@
|
|||
|
||||
|
||||
import unittest
|
||||
from test.helper import TestHelper
|
||||
|
||||
from mediafile import MediaFile
|
||||
|
||||
from beets.test.helper import TestHelper
|
||||
from beets.util import displayable_path
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -14,11 +14,11 @@
|
|||
|
||||
import os
|
||||
import unittest
|
||||
from test import _common
|
||||
from test.helper import TestHelper
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
from beets import library
|
||||
from beets.test import _common
|
||||
from beets.test.helper import TestHelper
|
||||
from beets.util import _fsencoding, bytestring_path
|
||||
from beetsplug.ipfs import IPFSPlugin
|
||||
|
||||
|
|
|
|||
|
|
@ -14,11 +14,11 @@
|
|||
|
||||
|
||||
import unittest
|
||||
from test.helper import TestHelper
|
||||
from unittest.mock import patch
|
||||
|
||||
from beets import util
|
||||
from beets.library import Item
|
||||
from beets.test.helper import TestHelper
|
||||
|
||||
|
||||
@patch("beets.util.command_output")
|
||||
|
|
|
|||
|
|
@ -16,11 +16,11 @@
|
|||
|
||||
|
||||
import unittest
|
||||
from test import _common
|
||||
from test.helper import TestHelper
|
||||
from unittest.mock import Mock
|
||||
|
||||
from beets import config
|
||||
from beets.test import _common
|
||||
from beets.test.helper import TestHelper
|
||||
from beetsplug import lastgenre
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,8 @@
|
|||
"""Tests for the 'limit' plugin."""
|
||||
|
||||
import unittest
|
||||
from test.helper import TestHelper
|
||||
|
||||
from beets.test.helper import TestHelper
|
||||
|
||||
|
||||
class LimitPluginTest(unittest.TestCase, TestHelper):
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ import itertools
|
|||
import os
|
||||
import re
|
||||
import unittest
|
||||
from test import _common
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import confuse
|
||||
|
|
@ -27,6 +26,7 @@ import requests
|
|||
|
||||
from beets import logging
|
||||
from beets.library import Item
|
||||
from beets.test import _common
|
||||
from beets.util import bytestring_path
|
||||
from beetsplug import lyrics
|
||||
|
||||
|
|
|
|||
|
|
@ -14,9 +14,15 @@
|
|||
|
||||
|
||||
import unittest
|
||||
from test.helper import TestHelper, capture_stdout, control_stdin
|
||||
from test.test_importer import AutotagStub, ImportHelper
|
||||
from test.test_ui_importer import TerminalImportSessionSetup
|
||||
|
||||
from beets.test.helper import (
|
||||
AutotagStub,
|
||||
ImportHelper,
|
||||
TerminalImportSessionSetup,
|
||||
TestHelper,
|
||||
capture_stdout,
|
||||
control_stdin,
|
||||
)
|
||||
|
||||
|
||||
class MBSubmitPluginTest(
|
||||
|
|
|
|||
|
|
@ -14,16 +14,16 @@
|
|||
|
||||
|
||||
import unittest
|
||||
from test.helper import (
|
||||
from unittest.mock import patch
|
||||
|
||||
from beets import config
|
||||
from beets.library import Item
|
||||
from beets.test.helper import (
|
||||
TestHelper,
|
||||
capture_log,
|
||||
generate_album_info,
|
||||
generate_track_info,
|
||||
)
|
||||
from unittest.mock import patch
|
||||
|
||||
from beets import config
|
||||
from beets.library import Item
|
||||
|
||||
|
||||
class MbsyncCliTest(unittest.TestCase, TestHelper):
|
||||
|
|
|
|||
|
|
@ -14,11 +14,11 @@
|
|||
|
||||
|
||||
import unittest
|
||||
from test.helper import TestHelper
|
||||
from unittest.mock import ANY, Mock, call, patch
|
||||
|
||||
from beets import util
|
||||
from beets.library import Item
|
||||
from beets.test.helper import TestHelper
|
||||
from beetsplug.mpdstats import MPDStats
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -17,10 +17,10 @@
|
|||
|
||||
import os
|
||||
import unittest
|
||||
from test.helper import TestHelper
|
||||
from unittest.mock import patch
|
||||
|
||||
from beets.library import Item
|
||||
from beets.test.helper import TestHelper
|
||||
from beetsplug import parentwork
|
||||
|
||||
work = {
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@
|
|||
import os
|
||||
import platform
|
||||
import unittest
|
||||
from test._common import touch
|
||||
from test.helper import TestHelper
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
from beets.test._common import touch
|
||||
from beets.test.helper import TestHelper
|
||||
from beets.util import displayable_path
|
||||
from beetsplug.permissions import (
|
||||
check_permissions,
|
||||
|
|
|
|||
|
|
@ -18,9 +18,9 @@
|
|||
import os
|
||||
import sys
|
||||
import unittest
|
||||
from test.helper import TestHelper, control_stdin
|
||||
from unittest.mock import ANY, patch
|
||||
|
||||
from beets.test.helper import TestHelper, control_stdin
|
||||
from beets.ui import UserError
|
||||
from beets.util import open_anything
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ import threading
|
|||
import time
|
||||
import unittest
|
||||
from contextlib import contextmanager
|
||||
from test.helper import TestHelper
|
||||
|
||||
# Mock GstPlayer so that the forked process doesn't attempt to import gi:
|
||||
from unittest import mock
|
||||
|
|
@ -33,6 +32,7 @@ from unittest import mock
|
|||
import confuse
|
||||
import yaml
|
||||
|
||||
from beets.test.helper import TestHelper
|
||||
from beets.util import bluelet, py3_path
|
||||
from beetsplug import bpd
|
||||
|
||||
|
|
|
|||
|
|
@ -18,9 +18,9 @@ import shutil
|
|||
import tempfile
|
||||
import unittest
|
||||
from shlex import quote
|
||||
from test import _common, helper
|
||||
|
||||
import beets
|
||||
from beets.test import _common, helper
|
||||
|
||||
|
||||
class PlaylistTestHelper(helper.TestHelper):
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import unittest
|
||||
from test.helper import TestHelper
|
||||
|
||||
import responses
|
||||
|
||||
from beets.test.helper import TestHelper
|
||||
from beetsplug.plexupdate import get_music_section, update_plex
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -18,12 +18,12 @@
|
|||
import os
|
||||
import shutil
|
||||
import unittest
|
||||
from test import _common
|
||||
|
||||
import mediafile
|
||||
|
||||
from beets.library import Item
|
||||
from beets.plugins import BeetsPlugin
|
||||
from beets.test import _common
|
||||
from beets.util import bytestring_path, syspath
|
||||
|
||||
field_extension = mediafile.MediaField(
|
||||
|
|
|
|||
|
|
@ -19,9 +19,9 @@
|
|||
import math
|
||||
import unittest
|
||||
from random import Random
|
||||
from test.helper import TestHelper
|
||||
|
||||
from beets import random
|
||||
from beets.test.helper import TestHelper
|
||||
|
||||
|
||||
class RandomTest(unittest.TestCase, TestHelper):
|
||||
|
|
|
|||
|
|
@ -14,11 +14,11 @@
|
|||
|
||||
|
||||
import unittest
|
||||
from test.helper import TestHelper, has_program
|
||||
|
||||
from mediafile import MediaFile
|
||||
|
||||
from beets import config
|
||||
from beets.test.helper import TestHelper, has_program
|
||||
from beetsplug.replaygain import (
|
||||
FatalGstreamerPluginReplayGainError,
|
||||
GStreamerBackend,
|
||||
|
|
|
|||
|
|
@ -17,14 +17,14 @@ import unittest
|
|||
from os import path, remove
|
||||
from shutil import rmtree
|
||||
from tempfile import mkdtemp
|
||||
from test import _common
|
||||
from test.helper import TestHelper
|
||||
from unittest.mock import MagicMock, Mock, PropertyMock
|
||||
|
||||
from beets import config
|
||||
from beets.dbcore import OrQuery
|
||||
from beets.dbcore.query import FixedFieldSort, MultipleSort, NullSort
|
||||
from beets.library import Album, Item, parse_query_string
|
||||
from beets.test import _common
|
||||
from beets.test.helper import TestHelper
|
||||
from beets.ui import UserError
|
||||
from beets.util import CHAR_REPLACE, bytestring_path, py3_path, syspath
|
||||
from beetsplug.smartplaylist import SmartPlaylistPlugin
|
||||
|
|
|
|||
|
|
@ -3,14 +3,14 @@
|
|||
|
||||
import os
|
||||
import unittest
|
||||
from test import _common
|
||||
from test.helper import TestHelper
|
||||
from urllib.parse import parse_qs, urlparse
|
||||
|
||||
import responses
|
||||
|
||||
from beets import config
|
||||
from beets.library import Item
|
||||
from beets.test import _common
|
||||
from beets.test.helper import TestHelper
|
||||
from beetsplug import spotify
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,13 +2,13 @@
|
|||
|
||||
|
||||
import unittest
|
||||
from test import _common
|
||||
from test.helper import TestHelper
|
||||
from urllib.parse import parse_qs, urlparse
|
||||
|
||||
import responses
|
||||
|
||||
from beets import config
|
||||
from beets.test import _common
|
||||
from beets.test.helper import TestHelper
|
||||
from beetsplug import subsonicupdate
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
|
||||
import unittest
|
||||
from test import _common
|
||||
|
||||
from beets import config
|
||||
from beets.test import _common
|
||||
from beetsplug.the import FORMAT, PATTERN_A, PATTERN_THE, ThePlugin
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -17,9 +17,9 @@ import os.path
|
|||
import unittest
|
||||
from shutil import rmtree
|
||||
from tempfile import mkdtemp
|
||||
from test.helper import TestHelper
|
||||
from unittest.mock import Mock, call, patch
|
||||
|
||||
from beets.test.helper import TestHelper
|
||||
from beets.util import bytestring_path, syspath
|
||||
from beetsplug.thumbnails import (
|
||||
LARGE_DIR,
|
||||
|
|
|
|||
|
|
@ -16,10 +16,11 @@
|
|||
import time
|
||||
import unittest
|
||||
from datetime import datetime
|
||||
from test.helper import TestHelper
|
||||
|
||||
from confuse import ConfigValueError
|
||||
|
||||
from beets.test.helper import TestHelper
|
||||
|
||||
|
||||
class TypesPluginTest(unittest.TestCase, TestHelper):
|
||||
def setUp(self):
|
||||
|
|
|
|||
|
|
@ -6,10 +6,10 @@ import os.path
|
|||
import platform
|
||||
import shutil
|
||||
import unittest
|
||||
from test import _common
|
||||
|
||||
from beets import logging
|
||||
from beets.library import Album, Item
|
||||
from beets.test import _common
|
||||
from beetsplug import web
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@
|
|||
|
||||
|
||||
import unittest
|
||||
from test.helper import TestHelper, control_stdin
|
||||
|
||||
from mediafile import MediaFile
|
||||
|
||||
from beets.library import Item
|
||||
from beets.test.helper import TestHelper, control_stdin
|
||||
from beets.util import syspath
|
||||
from beetsplug.zero import ZeroPlugin
|
||||
|
||||
|
|
|
|||
|
|
@ -17,10 +17,10 @@
|
|||
|
||||
import os
|
||||
import unittest
|
||||
from test import _common
|
||||
from test.helper import TestHelper
|
||||
from unittest.mock import patch
|
||||
|
||||
from beets.test import _common
|
||||
from beets.test.helper import TestHelper
|
||||
from beets.util import command_output, syspath
|
||||
from beets.util.artresizer import IMBackend, PILBackend
|
||||
|
||||
|
|
|
|||
|
|
@ -17,12 +17,12 @@
|
|||
|
||||
import re
|
||||
import unittest
|
||||
from test import _common
|
||||
|
||||
from beets import autotag, config
|
||||
from beets.autotag import AlbumInfo, TrackInfo, match
|
||||
from beets.autotag.hooks import Distance, string_dist
|
||||
from beets.library import Item
|
||||
from beets.test import _common
|
||||
from beets.util import plurality
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,13 +2,13 @@ import os
|
|||
import unittest
|
||||
from shutil import rmtree
|
||||
from tempfile import mkdtemp
|
||||
from test.helper import TestHelper
|
||||
from unittest.mock import patch
|
||||
|
||||
import yaml
|
||||
|
||||
from beets import config, ui
|
||||
from beets.library import Library
|
||||
from beets.test.helper import TestHelper
|
||||
|
||||
|
||||
class ConfigCommandTest(unittest.TestCase, TestHelper):
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@
|
|||
import time
|
||||
import unittest
|
||||
from datetime import datetime, timedelta
|
||||
from test import _common
|
||||
|
||||
from beets.dbcore.query import (
|
||||
DateInterval,
|
||||
|
|
@ -26,6 +25,7 @@ from beets.dbcore.query import (
|
|||
InvalidQueryArgumentValueError,
|
||||
_parse_periods,
|
||||
)
|
||||
from beets.test import _common
|
||||
|
||||
|
||||
def _date(string):
|
||||
|
|
|
|||
|
|
@ -20,9 +20,9 @@ import shutil
|
|||
import sqlite3
|
||||
import unittest
|
||||
from tempfile import mkstemp
|
||||
from test import _common
|
||||
|
||||
from beets import dbcore
|
||||
from beets.test import _common
|
||||
|
||||
# Fixture: concrete database and model classes. For migration tests, we
|
||||
# have multiple models with different numbers of fields.
|
||||
|
|
|
|||
|
|
@ -20,11 +20,11 @@ import shutil
|
|||
import stat
|
||||
import unittest
|
||||
from os.path import join
|
||||
from test import _common
|
||||
from test._common import item, touch
|
||||
|
||||
import beets.library
|
||||
from beets import util
|
||||
from beets.test import _common
|
||||
from beets.test._common import item, touch
|
||||
from beets.util import MoveOperation, bytestring_path, syspath
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -25,235 +25,25 @@ import unittest
|
|||
from io import StringIO
|
||||
from tarfile import TarFile
|
||||
from tempfile import mkstemp
|
||||
from test import _common
|
||||
from test.helper import (
|
||||
ImportSessionFixture,
|
||||
TestHelper,
|
||||
capture_log,
|
||||
has_program,
|
||||
)
|
||||
from unittest.mock import Mock, patch
|
||||
from zipfile import ZipFile
|
||||
|
||||
from mediafile import MediaFile
|
||||
|
||||
from beets import autotag, config, importer, logging, util
|
||||
from beets import config, importer, logging, util
|
||||
from beets.autotag import AlbumInfo, AlbumMatch, TrackInfo
|
||||
from beets.importer import albums_in_dir
|
||||
from beets.test import _common
|
||||
from beets.test.helper import (
|
||||
AutotagStub,
|
||||
ImportHelper,
|
||||
TestHelper,
|
||||
capture_log,
|
||||
has_program,
|
||||
)
|
||||
from beets.util import bytestring_path, displayable_path, py3_path, syspath
|
||||
|
||||
|
||||
class AutotagStub:
|
||||
"""Stub out MusicBrainz album and track matcher and control what the
|
||||
autotagger returns.
|
||||
"""
|
||||
|
||||
NONE = "NONE"
|
||||
IDENT = "IDENT"
|
||||
GOOD = "GOOD"
|
||||
BAD = "BAD"
|
||||
MISSING = "MISSING"
|
||||
"""Generate an album match for all but one track
|
||||
"""
|
||||
|
||||
length = 2
|
||||
matching = IDENT
|
||||
|
||||
def install(self):
|
||||
self.mb_match_album = autotag.mb.match_album
|
||||
self.mb_match_track = autotag.mb.match_track
|
||||
self.mb_album_for_id = autotag.mb.album_for_id
|
||||
self.mb_track_for_id = autotag.mb.track_for_id
|
||||
|
||||
autotag.mb.match_album = self.match_album
|
||||
autotag.mb.match_track = self.match_track
|
||||
autotag.mb.album_for_id = self.album_for_id
|
||||
autotag.mb.track_for_id = self.track_for_id
|
||||
|
||||
return self
|
||||
|
||||
def restore(self):
|
||||
autotag.mb.match_album = self.mb_match_album
|
||||
autotag.mb.match_track = self.mb_match_track
|
||||
autotag.mb.album_for_id = self.mb_album_for_id
|
||||
autotag.mb.track_for_id = self.mb_track_for_id
|
||||
|
||||
def match_album(self, albumartist, album, tracks, extra_tags):
|
||||
if self.matching == self.IDENT:
|
||||
yield self._make_album_match(albumartist, album, tracks)
|
||||
|
||||
elif self.matching == self.GOOD:
|
||||
for i in range(self.length):
|
||||
yield self._make_album_match(albumartist, album, tracks, i)
|
||||
|
||||
elif self.matching == self.BAD:
|
||||
for i in range(self.length):
|
||||
yield self._make_album_match(albumartist, album, tracks, i + 1)
|
||||
|
||||
elif self.matching == self.MISSING:
|
||||
yield self._make_album_match(albumartist, album, tracks, missing=1)
|
||||
|
||||
def match_track(self, artist, title):
|
||||
yield TrackInfo(
|
||||
title=title.replace("Tag", "Applied"),
|
||||
track_id="trackid",
|
||||
artist=artist.replace("Tag", "Applied"),
|
||||
artist_id="artistid",
|
||||
length=1,
|
||||
index=0,
|
||||
)
|
||||
|
||||
def album_for_id(self, mbid):
|
||||
return None
|
||||
|
||||
def track_for_id(self, mbid):
|
||||
return None
|
||||
|
||||
def _make_track_match(self, artist, album, number):
|
||||
return TrackInfo(
|
||||
title="Applied Title %d" % number,
|
||||
track_id="match %d" % number,
|
||||
artist=artist,
|
||||
length=1,
|
||||
index=0,
|
||||
)
|
||||
|
||||
def _make_album_match(self, artist, album, tracks, distance=0, missing=0):
|
||||
if distance:
|
||||
id = " " + "M" * distance
|
||||
else:
|
||||
id = ""
|
||||
if artist is None:
|
||||
artist = "Various Artists"
|
||||
else:
|
||||
artist = artist.replace("Tag", "Applied") + id
|
||||
album = album.replace("Tag", "Applied") + id
|
||||
|
||||
track_infos = []
|
||||
for i in range(tracks - missing):
|
||||
track_infos.append(self._make_track_match(artist, album, i + 1))
|
||||
|
||||
return AlbumInfo(
|
||||
artist=artist,
|
||||
album=album,
|
||||
tracks=track_infos,
|
||||
va=False,
|
||||
album_id="albumid" + id,
|
||||
artist_id="artistid" + id,
|
||||
albumtype="soundtrack",
|
||||
data_source="match_source",
|
||||
)
|
||||
|
||||
|
||||
class ImportHelper(TestHelper):
|
||||
"""Provides tools to setup a library, a directory containing files that are
|
||||
to be imported and an import session. The class also provides stubs for the
|
||||
autotagging library and several assertions for the library.
|
||||
"""
|
||||
|
||||
def setup_beets(self, disk=False):
|
||||
super().setup_beets(disk)
|
||||
self.lib.path_formats = [
|
||||
("default", os.path.join("$artist", "$album", "$title")),
|
||||
("singleton:true", os.path.join("singletons", "$title")),
|
||||
("comp:true", os.path.join("compilations", "$album", "$title")),
|
||||
]
|
||||
|
||||
def _create_import_dir(self, count=3):
|
||||
"""Creates a directory with media files to import.
|
||||
Sets ``self.import_dir`` to the path of the directory. Also sets
|
||||
``self.import_media`` to a list :class:`MediaFile` for all the files in
|
||||
the directory.
|
||||
|
||||
The directory has following layout
|
||||
the_album/
|
||||
track_1.mp3
|
||||
track_2.mp3
|
||||
track_3.mp3
|
||||
|
||||
:param count: Number of files to create
|
||||
"""
|
||||
self.import_dir = os.path.join(self.temp_dir, b"testsrcdir")
|
||||
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(syspath(album_path))
|
||||
|
||||
resource_path = os.path.join(_common.RSRC, b"full.mp3")
|
||||
|
||||
metadata = {
|
||||
"artist": "Tag Artist",
|
||||
"album": "Tag Album",
|
||||
"albumartist": None,
|
||||
"mb_trackid": None,
|
||||
"mb_albumid": None,
|
||||
"comp": None,
|
||||
}
|
||||
self.media_files = []
|
||||
for i in range(count):
|
||||
# Copy files
|
||||
medium_path = os.path.join(
|
||||
album_path, bytestring_path("track_%d.mp3" % (i + 1))
|
||||
)
|
||||
shutil.copy(syspath(resource_path), syspath(medium_path))
|
||||
medium = MediaFile(medium_path)
|
||||
|
||||
# Set metadata
|
||||
metadata["track"] = i + 1
|
||||
metadata["title"] = "Tag Title %d" % (i + 1)
|
||||
for attr in metadata:
|
||||
setattr(medium, attr, metadata[attr])
|
||||
medium.save()
|
||||
self.media_files.append(medium)
|
||||
self.import_media = self.media_files
|
||||
|
||||
def _setup_import_session(
|
||||
self,
|
||||
import_dir=None,
|
||||
delete=False,
|
||||
threaded=False,
|
||||
copy=True,
|
||||
singletons=False,
|
||||
move=False,
|
||||
autotag=True,
|
||||
link=False,
|
||||
hardlink=False,
|
||||
):
|
||||
config["import"]["copy"] = copy
|
||||
config["import"]["delete"] = delete
|
||||
config["import"]["timid"] = True
|
||||
config["threaded"] = False
|
||||
config["import"]["singletons"] = singletons
|
||||
config["import"]["move"] = move
|
||||
config["import"]["autotag"] = autotag
|
||||
config["import"]["resume"] = False
|
||||
config["import"]["link"] = link
|
||||
config["import"]["hardlink"] = hardlink
|
||||
|
||||
self.importer = ImportSessionFixture(
|
||||
self.lib,
|
||||
loghandler=None,
|
||||
query=None,
|
||||
paths=[import_dir or self.import_dir],
|
||||
)
|
||||
|
||||
def assert_file_in_lib(self, *segments):
|
||||
"""Join the ``segments`` and assert that this path exists in the
|
||||
library directory.
|
||||
"""
|
||||
self.assertExists(os.path.join(self.libdir, *segments))
|
||||
|
||||
def assert_file_not_in_lib(self, *segments):
|
||||
"""Join the ``segments`` and assert that this path does not
|
||||
exist in the library directory.
|
||||
"""
|
||||
self.assertNotExists(os.path.join(self.libdir, *segments))
|
||||
|
||||
def assert_lib_dir_empty(self):
|
||||
self.assertEqual(len(os.listdir(syspath(self.libdir))), 0)
|
||||
|
||||
|
||||
class ScrubbedImportTest(_common.TestCase, ImportHelper):
|
||||
def setUp(self):
|
||||
self.setup_beets(disk=True)
|
||||
|
|
|
|||
|
|
@ -24,15 +24,15 @@ import sys
|
|||
import time
|
||||
import unicodedata
|
||||
import unittest
|
||||
from test import _common
|
||||
from test._common import item
|
||||
from test.helper import TestHelper
|
||||
|
||||
from mediafile import MediaFile, UnreadableFileError
|
||||
|
||||
import beets.dbcore.query
|
||||
import beets.library
|
||||
from beets import config, plugins, util
|
||||
from beets.test import _common
|
||||
from beets.test._common import item
|
||||
from beets.test.helper import TestHelper
|
||||
from beets.util import bytestring_path, syspath
|
||||
|
||||
# Shortcut to path normalization.
|
||||
|
|
|
|||
|
|
@ -5,12 +5,12 @@ import sys
|
|||
import threading
|
||||
import unittest
|
||||
from io import StringIO
|
||||
from test import _common, helper
|
||||
from test._common import TestCase
|
||||
|
||||
import beets.logging as blog
|
||||
import beetsplug
|
||||
from beets import plugins, ui
|
||||
from beets.test import _common, helper
|
||||
from beets.test._common import TestCase
|
||||
|
||||
|
||||
class LoggingTest(TestCase):
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@ import unittest
|
|||
from os import path
|
||||
from shutil import rmtree
|
||||
from tempfile import mkdtemp
|
||||
from test._common import RSRC
|
||||
|
||||
from beets.test._common import RSRC
|
||||
from beets.util import bytestring_path
|
||||
from beets.util.m3u import EmptyPlaylistError, M3UFile
|
||||
|
||||
|
|
|
|||
|
|
@ -16,11 +16,11 @@
|
|||
"""
|
||||
|
||||
import unittest
|
||||
from test import _common
|
||||
from unittest import mock
|
||||
|
||||
from beets import config
|
||||
from beets.autotag import mb
|
||||
from beets.test import _common
|
||||
|
||||
|
||||
class MBAlbumInfoTest(_common.TestCase):
|
||||
|
|
|
|||
|
|
@ -18,10 +18,10 @@ import platform
|
|||
import time
|
||||
import unittest
|
||||
from datetime import datetime
|
||||
from test import _common
|
||||
from test.helper import TestHelper
|
||||
|
||||
from beets.library import Item
|
||||
from beets.test import _common
|
||||
from beets.test.helper import TestHelper
|
||||
from beets.util import py3_path
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -17,10 +17,6 @@ import itertools
|
|||
import os
|
||||
import shutil
|
||||
import unittest
|
||||
from test import helper
|
||||
from test._common import RSRC
|
||||
from test.test_importer import AutotagStub, ImportHelper
|
||||
from test.test_ui_importer import TerminalImportSessionSetup
|
||||
from unittest.mock import ANY, Mock, patch
|
||||
|
||||
from mediafile import MediaFile
|
||||
|
|
@ -35,6 +31,13 @@ from beets.importer import (
|
|||
)
|
||||
from beets.library import Item
|
||||
from beets.plugins import MetadataSourcePlugin
|
||||
from beets.test import helper
|
||||
from beets.test._common import RSRC
|
||||
from beets.test.helper import (
|
||||
AutotagStub,
|
||||
ImportHelper,
|
||||
TerminalImportSessionSetup,
|
||||
)
|
||||
from beets.util import bytestring_path, displayable_path, syspath
|
||||
from beets.util.id_extractors import (
|
||||
beatport_id_regex,
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ import sys
|
|||
import unittest
|
||||
from contextlib import contextmanager
|
||||
from functools import partial
|
||||
from test import _common, helper
|
||||
|
||||
import beets.library
|
||||
from beets import dbcore, util
|
||||
|
|
@ -31,6 +30,7 @@ from beets.dbcore.query import (
|
|||
ParsingError,
|
||||
)
|
||||
from beets.library import Item, Library
|
||||
from beets.test import _common, helper
|
||||
from beets.util import syspath
|
||||
|
||||
# Because the absolute path begins with something like C:, we
|
||||
|
|
|
|||
|
|
@ -16,10 +16,10 @@
|
|||
"""
|
||||
|
||||
import unittest
|
||||
from test import _common
|
||||
|
||||
import beets.library
|
||||
from beets import config, dbcore
|
||||
from beets.test import _common
|
||||
|
||||
|
||||
# A test case class providing a library with some dummy data and some
|
||||
|
|
|
|||
|
|
@ -22,8 +22,6 @@ import shutil
|
|||
import subprocess
|
||||
import sys
|
||||
import unittest
|
||||
from test import _common
|
||||
from test.helper import TestHelper, capture_stdout, control_stdin, has_program
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
from confuse import ConfigError
|
||||
|
|
@ -31,6 +29,13 @@ from mediafile import MediaFile
|
|||
|
||||
from beets import autotag, config, library, plugins, ui, util
|
||||
from beets.autotag.match import distance
|
||||
from beets.test import _common
|
||||
from beets.test.helper import (
|
||||
TestHelper,
|
||||
capture_stdout,
|
||||
control_stdin,
|
||||
has_program,
|
||||
)
|
||||
from beets.ui import commands
|
||||
from beets.util import MoveOperation, syspath
|
||||
|
||||
|
|
|
|||
|
|
@ -19,9 +19,9 @@
|
|||
import os
|
||||
import shutil
|
||||
import unittest
|
||||
from test import _common
|
||||
|
||||
from beets import library, ui
|
||||
from beets.test import _common
|
||||
from beets.ui import commands
|
||||
from beets.util import syspath
|
||||
|
||||
|
|
|
|||
|
|
@ -20,90 +20,8 @@ test_importer module. But here the test importer inherits from
|
|||
|
||||
import unittest
|
||||
from test import test_importer
|
||||
from test._common import DummyIO
|
||||
|
||||
from beets import config, importer
|
||||
from beets.ui.commands import TerminalImportSession
|
||||
|
||||
|
||||
class TerminalImportSessionFixture(TerminalImportSession):
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.io = kwargs.pop("io")
|
||||
super().__init__(*args, **kwargs)
|
||||
self._choices = []
|
||||
|
||||
default_choice = importer.action.APPLY
|
||||
|
||||
def add_choice(self, choice):
|
||||
self._choices.append(choice)
|
||||
|
||||
def clear_choices(self):
|
||||
self._choices = []
|
||||
|
||||
def choose_match(self, task):
|
||||
self._add_choice_input()
|
||||
return super().choose_match(task)
|
||||
|
||||
def choose_item(self, task):
|
||||
self._add_choice_input()
|
||||
return super().choose_item(task)
|
||||
|
||||
def _add_choice_input(self):
|
||||
try:
|
||||
choice = self._choices.pop(0)
|
||||
except IndexError:
|
||||
choice = self.default_choice
|
||||
|
||||
if choice == importer.action.APPLY:
|
||||
self.io.addinput("A")
|
||||
elif choice == importer.action.ASIS:
|
||||
self.io.addinput("U")
|
||||
elif choice == importer.action.ALBUMS:
|
||||
self.io.addinput("G")
|
||||
elif choice == importer.action.TRACKS:
|
||||
self.io.addinput("T")
|
||||
elif choice == importer.action.SKIP:
|
||||
self.io.addinput("S")
|
||||
elif isinstance(choice, int):
|
||||
self.io.addinput("M")
|
||||
self.io.addinput(str(choice))
|
||||
self._add_choice_input()
|
||||
else:
|
||||
raise Exception("Unknown choice %s" % choice)
|
||||
|
||||
|
||||
class TerminalImportSessionSetup:
|
||||
"""Overwrites test_importer.ImportHelper to provide a terminal importer"""
|
||||
|
||||
def _setup_import_session(
|
||||
self,
|
||||
import_dir=None,
|
||||
delete=False,
|
||||
threaded=False,
|
||||
copy=True,
|
||||
singletons=False,
|
||||
move=False,
|
||||
autotag=True,
|
||||
):
|
||||
config["import"]["copy"] = copy
|
||||
config["import"]["delete"] = delete
|
||||
config["import"]["timid"] = True
|
||||
config["threaded"] = False
|
||||
config["import"]["singletons"] = singletons
|
||||
config["import"]["move"] = move
|
||||
config["import"]["autotag"] = autotag
|
||||
config["import"]["resume"] = False
|
||||
|
||||
if not hasattr(self, "io"):
|
||||
self.io = DummyIO()
|
||||
self.io.install()
|
||||
self.importer = TerminalImportSessionFixture(
|
||||
self.lib,
|
||||
loghandler=None,
|
||||
query=None,
|
||||
io=self.io,
|
||||
paths=[import_dir or self.import_dir],
|
||||
)
|
||||
from beets.test.helper import TerminalImportSessionSetup
|
||||
|
||||
|
||||
class NonAutotaggedImportTest(
|
||||
|
|
|
|||
|
|
@ -20,10 +20,10 @@ import shutil
|
|||
import unittest
|
||||
from copy import deepcopy
|
||||
from random import random
|
||||
from test import _common
|
||||
from test.helper import control_stdin
|
||||
|
||||
from beets import config, ui
|
||||
from beets.test import _common
|
||||
from beets.test.helper import control_stdin
|
||||
|
||||
|
||||
class InputMethodsTest(_common.TestCase):
|
||||
|
|
|
|||
|
|
@ -20,10 +20,10 @@ import re
|
|||
import subprocess
|
||||
import sys
|
||||
import unittest
|
||||
from test import _common
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
from beets import util
|
||||
from beets.test import _common
|
||||
|
||||
|
||||
class UtilTest(unittest.TestCase):
|
||||
|
|
|
|||
|
|
@ -15,9 +15,9 @@
|
|||
"""Tests for the virtual filesystem builder.."""
|
||||
|
||||
import unittest
|
||||
from test import _common
|
||||
|
||||
from beets import library, vfs
|
||||
from beets.test import _common
|
||||
|
||||
|
||||
class VFSTest(_common.TestCase):
|
||||
|
|
|
|||
Loading…
Reference in a new issue