示例#1
0
class ImportfeedsTestTest(unittest.TestCase):

    def setUp(self):
        config.clear()
        config.read(user=False)
        self.importfeeds = ImportFeedsPlugin()
        self.lib = Library(':memory:')
        self.feeds_dir = tempfile.mkdtemp()
        config['importfeeds']['dir'] = self.feeds_dir

    def tearDown(self):
        shutil.rmtree(self.feeds_dir)

    def test_multi_format_album_playlist(self):
        config['importfeeds']['formats'] = 'm3u_multi'
        album = Album(album='album/name', id=1)
        item_path = os.path.join('path', 'to', 'item')
        item = Item(title='song', album_id=1, path=item_path)
        self.lib.add(album)
        self.lib.add(item)

        self.importfeeds.album_imported(self.lib, album)
        playlist_path = os.path.join(self.feeds_dir,
                                     os.listdir(self.feeds_dir)[0])
        self.assertTrue(playlist_path.endswith('album_name.m3u'))
        with open(playlist_path) as playlist:
            self.assertIn(item_path, playlist.read())
示例#2
0
class ImportfeedsTestTest(unittest.TestCase):
    def setUp(self):
        config.clear()
        config.read(user=False)
        self.importfeeds = ImportFeedsPlugin()
        self.lib = Library(':memory:')
        self.feeds_dir = tempfile.mkdtemp()
        config['importfeeds']['dir'] = self.feeds_dir

    def tearDown(self):
        shutil.rmtree(self.feeds_dir)

    def test_multi_format_album_playlist(self):
        config['importfeeds']['formats'] = 'm3u_multi'
        album = Album(album='album/name', id=1)
        item_path = os.path.join('path', 'to', 'item')
        item = Item(title='song', album_id=1, path=item_path)
        self.lib.add(album)
        self.lib.add(item)

        self.importfeeds.album_imported(self.lib, album)
        playlist_path = os.path.join(self.feeds_dir,
                                     os.listdir(self.feeds_dir)[0])
        self.assertTrue(playlist_path.endswith('album_name.m3u'))
        with open(playlist_path) as playlist:
            self.assertIn(item_path, playlist.read())
示例#3
0
 def setUp(self):
     config.clear()
     config.read(user=False)
     self.importfeeds = ImportFeedsPlugin()
     self.lib = Library(':memory:')
     self.feeds_dir = tempfile.mkdtemp()
     config['importfeeds']['dir'] = self.feeds_dir
示例#4
0
class IntQueryTest(unittest.TestCase, TestHelper):

    def setUp(self):
        self.lib = Library(':memory:')

    def test_exact_value_match(self):
        item = self.add_item(bpm=120)
        matched = self.lib.items('bpm:120').get()
        self.assertEqual(item.id, matched.id)

    def test_range_match(self):
        item = self.add_item(bpm=120)
        self.add_item(bpm=130)

        matched = self.lib.items('bpm:110..125')
        self.assertEqual(1, len(matched))
        self.assertEqual(item.id, matched.get().id)

    def test_flex_range_match(self):
        Item._types = {'myint': types.Integer()}
        item = self.add_item(myint=2)
        matched = self.lib.items('myint:2').get()
        self.assertEqual(item.id, matched.id)

    def test_flex_dont_match_missing(self):
        Item._types = {'myint': types.Integer()}
        self.add_item()
        matched = self.lib.items('myint:2').get()
        self.assertIsNone(matched)

    def test_no_substring_match(self):
        self.add_item(bpm=120)
        matched = self.lib.items('bpm:12').get()
        self.assertIsNone(matched)
def prompt_tags(db_file, query):
    library = Library(db_file)
    for track in library.items(query=query):
        try:
            scan_version = int(float(track.scan_version))
        except Exception:
            scan_version = 0
        if scan_version < VERSION:
            _prompt_for_track(track, TAGS_MODEL)
            track.scan_version = VERSION
            track.store()
示例#6
0
def get_tracks(db_file, tag_list: List[str]) -> Dict[str, Track]:
    result = dict()
    library = Library(db_file)
    tag_list = [
        tag for tag in tag_list if tag != "rating" and not tag.startswith("_")
    ]
    for item in library.items():
        path = convert_attr_to_string(item.path).lower()
        tags = {tag: _get_attr_dont_throw(item, tag) for tag in tag_list}
        rating = _get_int_attr_dont_throw(item, "rating")
        if not (rating is not None and 0 <= rating <= 5):
            rating = None
        result[path] = Track(Path(path), tags, rating)

    return result
示例#7
0
 def setUp(self):
     config.clear()
     config.read(user=False)
     self.importfeeds = ImportFeedsPlugin()
     self.lib = Library(':memory:')
     self.feeds_dir = tempfile.mkdtemp()
     config['importfeeds']['dir'] = self.feeds_dir
示例#8
0
    def create(self, lib: Library, name: str, qs: str, playlist_dir: str,
               relative_to: str):
        if playlist_dir is None:
            playlist_dir = self.config_playlist_dir()
        if relative_to is None:
            relative_to = self.config_relative_to()

        # Try to parse the query
        try:
            if qs is None:
                query, sort = None, None
            else:
                query, sort = parse_query_string(qs, Item)
        except ParsingError as ex:
            self._log.warning(u'invalid query: {}', ex)
            return

        # Map items to their paths
        items = lib.items(query, sort)
        item_path: Callable[[Item], str] = lambda item: path.relpath(
            item.path.decode('utf-8'), relative_to)
        paths = [item_path(item) for item in items]

        filename = path.join(playlist_dir, name + '.m3u')
        with open(filename, 'w+') as file:
            write_str = '\n'.join(paths)
            file.write(write_str)
示例#9
0
    def setup_beets(self, disk=False):
        """Setup pristine global configuration and library for testing.

        Sets ``beets.config`` so we can safely use any functionality
        that uses the global configuration.  All paths used are
        contained in a temporary directory

        Sets the following properties on itself.

        - ``temp_dir`` Path to a temporary directory containing all
          files specific to beets

        - ``libdir`` Path to a subfolder of ``temp_dir``, containing the
          library's media files. Same as ``config['directory']``.

        - ``config`` The global configuration used by beets.

        - ``lib`` Library instance created with the settings from
          ``config``.

        Make sure you call ``teardown_beets()`` afterwards.
        """
        self.create_temp_dir()
        os.environ['BEETSDIR'] = util.py3_path(self.temp_dir)

        self.config = beets.config
        self.config.clear()
        self.config.read()

        self.config['plugins'] = []
        self.config['verbose'] = 1
        self.config['ui']['color'] = False
        self.config['threaded'] = False

        self.libdir = os.path.join(self.temp_dir, b'libdir')
        os.mkdir(self.libdir)
        self.config['directory'] = util.py3_path(self.libdir)

        if disk:
            dbpath = util.bytestring_path(
                self.config['library'].as_filename()
            )
        else:
            dbpath = ':memory:'
        self.lib = Library(dbpath, self.libdir)
示例#10
0
class NoneQueryTest(unittest.TestCase, TestHelper):
    def setUp(self):
        self.lib = Library(':memory:')

    def test_match_singletons(self):
        singleton = self.add_item()
        album_item = self.add_album().items().get()

        matched = self.lib.items(NoneQuery('album_id'))
        self.assertInResult(singleton, matched)
        self.assertNotInResult(album_item, matched)

    def test_match_after_set_none(self):
        item = self.add_item(rg_track_gain=0)
        matched = self.lib.items(NoneQuery('rg_track_gain'))
        self.assertNotInResult(item, matched)

        item['rg_track_gain'] = None
        item.store()
        matched = self.lib.items(NoneQuery('rg_track_gain'))
        self.assertInResult(item, matched)
示例#11
0
class NoneQueryTest(unittest.TestCase, TestHelper):
    def setUp(self):
        self.lib = Library(":memory:")

    def test_match_singletons(self):
        singleton = self.add_item()
        album_item = self.add_album().items().get()

        matched = self.lib.items(NoneQuery("album_id"))
        self.assertInResult(singleton, matched)
        self.assertNotInResult(album_item, matched)

    def test_match_after_set_none(self):
        item = self.add_item(rg_track_gain=0)
        matched = self.lib.items(NoneQuery("rg_track_gain"))
        self.assertNotInResult(item, matched)

        item["rg_track_gain"] = None
        item.store()
        matched = self.lib.items(NoneQuery("rg_track_gain"))
        self.assertInResult(item, matched)
示例#12
0
    def test_edit_invalid_config_file(self):
        self.lib = Library(':memory:')
        with open(self.config_path, 'w') as file:
            file.write('invalid: [')
        config.clear()
        config._materialized = False

        os.environ['EDITOR'] = 'myeditor'
        with patch('os.execlp') as execlp:
            self.run_command('config', '-e')
        execlp.assert_called_once_with('myeditor', 'myeditor',
                                       self.config_path)
示例#13
0
class BoolQueryTest(unittest.TestCase, TestHelper):

    def setUp(self):
        self.lib = Library(':memory:')
        Item._types = {'flexbool': types.Boolean()}

    def tearDown(self):
        Item._types = {}

    def test_parse_true(self):
        item_true = self.add_item(comp=True)
        item_false = self.add_item(comp=False)
        matched = self.lib.items('comp:true')
        self.assertInResult(item_true, matched)
        self.assertNotInResult(item_false, matched)

    def test_flex_parse_true(self):
        item_true = self.add_item(flexbool=True)
        item_false = self.add_item(flexbool=False)
        matched = self.lib.items('flexbool:true')
        self.assertInResult(item_true, matched)
        self.assertNotInResult(item_false, matched)

    def test_flex_parse_false(self):
        item_true = self.add_item(flexbool=True)
        item_false = self.add_item(flexbool=False)
        matched = self.lib.items('flexbool:false')
        self.assertInResult(item_false, matched)
        self.assertNotInResult(item_true, matched)

    def test_flex_parse_1(self):
        item_true = self.add_item(flexbool=True)
        item_false = self.add_item(flexbool=False)
        matched = self.lib.items('flexbool:1')
        self.assertInResult(item_true, matched)
        self.assertNotInResult(item_false, matched)

    def test_flex_parse_0(self):
        item_true = self.add_item(flexbool=True)
        item_false = self.add_item(flexbool=False)
        matched = self.lib.items('flexbool:0')
        self.assertInResult(item_false, matched)
        self.assertNotInResult(item_true, matched)

    def test_flex_parse_any_string(self):
        # TODO this should be the other way around
        item_true = self.add_item(flexbool=True)
        item_false = self.add_item(flexbool=False)
        matched = self.lib.items('flexbool:something')
        self.assertInResult(item_false, matched)
        self.assertNotInResult(item_true, matched)

    def assertInResult(self, item, results):
        result_ids = map(lambda i: i.id, results)
        self.assertIn(item.id, result_ids)

    def assertNotInResult(self, item, results):
        result_ids = map(lambda i: i.id, results)
        self.assertNotIn(item.id, result_ids)
示例#14
0
class IntQueryTest(unittest.TestCase, TestHelper):

    def setUp(self):
        self.lib = Library(':memory:')

    def tearDown(self):
        Item._types = {}

    def test_exact_value_match(self):
        item = self.add_item(bpm=120)
        matched = self.lib.items('bpm:120').get()
        self.assertEqual(item.id, matched.id)

    def test_range_match(self):
        item = self.add_item(bpm=120)
        self.add_item(bpm=130)

        matched = self.lib.items('bpm:110..125')
        self.assertEqual(1, len(matched))
        self.assertEqual(item.id, matched.get().id)

    def test_flex_range_match(self):
        Item._types = {'myint': types.Integer()}
        item = self.add_item(myint=2)
        matched = self.lib.items('myint:2').get()
        self.assertEqual(item.id, matched.id)

    def test_flex_dont_match_missing(self):
        Item._types = {'myint': types.Integer()}
        self.add_item()
        matched = self.lib.items('myint:2').get()
        self.assertIsNone(matched)

    def test_no_substring_match(self):
        self.add_item(bpm=120)
        matched = self.lib.items('bpm:12').get()
        self.assertIsNone(matched)
示例#15
0
def write_tracks_rating_and_tags(db_file, tracks: Dict[str, Track]):
    library = Library(db_file)
    conflicting_tracks = []
    traktor_modification_count = 0
    for i in library.items():
        path = convert_attr_to_string(i.path).lower()
        if path in tracks:

            if tracks.get(path).rating is not None:
                i.rating = tracks.get(path).rating

            conflicting_tags = []
            for tag_key, traktor_tag_value in tracks.get(path).tags.items():
                existing_tag_in_beets = _get_attr_dont_throw(i, tag_key)
                if existing_tag_in_beets is None or existing_tag_in_beets != traktor_tag_value:
                    traktor_modification_count += 1

                setattr(i, tag_key, traktor_tag_value)
                if existing_tag_in_beets is not None and existing_tag_in_beets != traktor_tag_value:
                    conflicting_tags.append(
                        (tag_key, existing_tag_in_beets, traktor_tag_value))
            if conflicting_tags:
                conflicting_tracks.append((path, conflicting_tags))

            i.store()

    if conflicting_tracks:
        for c in conflicting_tracks[:10]:
            print(
                "Conflict in '%s':\n  Conflicting tags (tag_key, beet_tags, traktor_tags):\n\t%s"
                % (c[0], c[1]))
        print("==========================")
        print(
            "Conflicting tags were overwritten in beets: Traktor tags have priority over beets"
        )
        print("Total conflicting tracks: %s" % len(conflicting_tracks))
    print("New tags coming from Traktor: %s" % traktor_modification_count)
示例#16
0
def ls(lib: Library, opts, args):
    items = lib.items(" ".join(args))
    item: Item
    for item in items:
        path = item.destination().decode("utf-8")
        flac: bool = any(ext in path for ext in ["flac", "alac", "wav"])
        bit_depth = item.bitdepth
        sample_rate = round(float(item["samplerate"]) / 1000, 1)
        if flac:
            print(
                f"{item} - {'FLAC' if flac else path[path.rfind('.')+1:].upper()} - {sample_rate}/{bit_depth}"
            )
        else:
            print(
                f"{item} - {path[path.rfind('.')+1:].upper()} - {item.bitrate//1000}kbps"
            )
示例#17
0
文件: helper.py 项目: ampg99/beets
    def setup_beets(self, disk=False):
        """Setup pristine global configuration and library for testing.

        Sets ``beets.config`` so we can safely use any functionality
        that uses the global configuration.  All paths used are
        contained in a temporary directory

        Sets the following properties on itself.

        - ``temp_dir`` Path to a temporary directory containing all
          files specific to beets

        - ``libdir`` Path to a subfolder of ``temp_dir``, containing the
          library's media files. Same as ``config['directory']``.

        - ``config`` The global configuration used by beets.

        - ``lib`` Library instance created with the settings from
          ``config``.

        Make sure you call ``teardown_beets()`` afterwards.
        """
        self.create_temp_dir()
        os.environ['BEETSDIR'] = util.py3_path(self.temp_dir)

        self.config = beets.config
        self.config.clear()
        self.config.read()

        self.config['plugins'] = []
        self.config['verbose'] = 1
        self.config['ui']['color'] = False
        self.config['threaded'] = False

        self.libdir = os.path.join(self.temp_dir, b'libdir')
        os.mkdir(self.libdir)
        self.config['directory'] = util.py3_path(self.libdir)

        if disk:
            dbpath = util.bytestring_path(
                self.config['library'].as_filename()
            )
        else:
            dbpath = ':memory:'
        self.lib = Library(dbpath, self.libdir)
示例#18
0
class BoolQueryTest(unittest.TestCase, TestHelper):

    def setUp(self):
        self.lib = Library(':memory:')
        Item._types = {'flexbool': types.Boolean()}

    def tearDown(self):
        Item._types = {}

    def test_parse_true(self):
        item_true = self.add_item(comp=True)
        item_false = self.add_item(comp=False)
        matched = self.lib.items('comp:true')
        self.assertInResult(item_true, matched)
        self.assertNotInResult(item_false, matched)

    def test_flex_parse_true(self):
        item_true = self.add_item(flexbool=True)
        item_false = self.add_item(flexbool=False)
        matched = self.lib.items('flexbool:true')
        self.assertInResult(item_true, matched)
        self.assertNotInResult(item_false, matched)

    def test_flex_parse_false(self):
        item_true = self.add_item(flexbool=True)
        item_false = self.add_item(flexbool=False)
        matched = self.lib.items('flexbool:false')
        self.assertInResult(item_false, matched)
        self.assertNotInResult(item_true, matched)

    def test_flex_parse_1(self):
        item_true = self.add_item(flexbool=True)
        item_false = self.add_item(flexbool=False)
        matched = self.lib.items('flexbool:1')
        self.assertInResult(item_true, matched)
        self.assertNotInResult(item_false, matched)

    def test_flex_parse_0(self):
        item_true = self.add_item(flexbool=True)
        item_false = self.add_item(flexbool=False)
        matched = self.lib.items('flexbool:0')
        self.assertInResult(item_false, matched)
        self.assertNotInResult(item_true, matched)

    def test_flex_parse_any_string(self):
        # TODO this should be the other way around
        item_true = self.add_item(flexbool=True)
        item_false = self.add_item(flexbool=False)
        matched = self.lib.items('flexbool:something')
        self.assertInResult(item_false, matched)
        self.assertNotInResult(item_true, matched)
示例#19
0
class BoolQueryTest(unittest.TestCase, TestHelper):
    def setUp(self):
        self.lib = Library(":memory:")
        Item._types = {"flexbool": types.Boolean()}

    def tearDown(self):
        Item._types = {}

    def test_parse_true(self):
        item_true = self.add_item(comp=True)
        item_false = self.add_item(comp=False)
        matched = self.lib.items("comp:true")
        self.assertInResult(item_true, matched)
        self.assertNotInResult(item_false, matched)

    def test_flex_parse_true(self):
        item_true = self.add_item(flexbool=True)
        item_false = self.add_item(flexbool=False)
        matched = self.lib.items("flexbool:true")
        self.assertInResult(item_true, matched)
        self.assertNotInResult(item_false, matched)

    def test_flex_parse_false(self):
        item_true = self.add_item(flexbool=True)
        item_false = self.add_item(flexbool=False)
        matched = self.lib.items("flexbool:false")
        self.assertInResult(item_false, matched)
        self.assertNotInResult(item_true, matched)

    def test_flex_parse_1(self):
        item_true = self.add_item(flexbool=True)
        item_false = self.add_item(flexbool=False)
        matched = self.lib.items("flexbool:1")
        self.assertInResult(item_true, matched)
        self.assertNotInResult(item_false, matched)

    def test_flex_parse_0(self):
        item_true = self.add_item(flexbool=True)
        item_false = self.add_item(flexbool=False)
        matched = self.lib.items("flexbool:0")
        self.assertInResult(item_false, matched)
        self.assertNotInResult(item_true, matched)

    def test_flex_parse_any_string(self):
        # TODO this should be the other way around
        item_true = self.add_item(flexbool=True)
        item_false = self.add_item(flexbool=False)
        matched = self.lib.items("flexbool:something")
        self.assertInResult(item_false, matched)
        self.assertNotInResult(item_true, matched)
示例#20
0
    def setUp(self):
        self.lib = Library(':memory:')
        self.temp_dir = mkdtemp()
        if 'EDITOR' in os.environ:
            del os.environ['EDITOR']

        os.environ['BEETSDIR'] = self.temp_dir
        self.config_path = os.path.join(self.temp_dir, 'config.yaml')
        with open(self.config_path, 'w') as file:
            file.write('library: lib\n')
            file.write('option: value\n')
            file.write('password: password_value')

        self.cli_config_path = os.path.join(self.temp_dir, 'cli_config.yaml')
        with open(self.cli_config_path, 'w') as file:
            file.write('option: cli overwrite')

        config.clear()
        config['password'].redact = True
        config._materialized = False
示例#21
0
 def setUp(self):
     self.lib = Library(":memory:")
     Item._types = {"flexbool": types.Boolean()}
示例#22
0
 def setUp(self):
     self.lib = Library(':memory:')
示例#23
0
 def setUp(self):
     self.lib = Library(':memory:')
     Item._types = {'flexbool': types.Boolean()}
示例#24
0
 def setUp(self):
     self.lib = Library(':memory:')
示例#25
0
 def setUp(self):
     self.lib = Library(":memory:")
示例#26
0
 def setUp(self):
     self.lib = Library(':memory:')
     Item._types = {'flexbool': types.Boolean()}
示例#27
0
文件: helper.py 项目: imclab/beets
class TestHelper(object):
    """Helper mixin for high-level cli and plugin tests.

    This mixin provides methods to isolate beets' global state provide
    fixtures.
    """
    # TODO automate teardown through hook registration

    def setup_beets(self, disk=False):
        """Setup pristine global configuration and library for testing.

        Sets ``beets.config`` so we can safely use any functionality
        that uses the global configuration.  All paths used are
        contained in a temporary directory

        Sets the following properties on itself.

        - ``temp_dir`` Path to a temporary directory containing all
          files specific to beets

        - ``libdir`` Path to a subfolder of ``temp_dir``, containing the
          library's media files. Same as ``config['directory']``.

        - ``config`` The global configuration used by beets.

        - ``lib`` Library instance created with the settings from
          ``config``.

        Make sure you call ``teardown_beets()`` afterwards.
        """
        self.create_temp_dir()
        os.environ['BEETSDIR'] = self.temp_dir

        self.config = beets.config
        self.config.clear()
        self.config.read()

        self.config['plugins'] = []
        self.config['verbose'] = True
        self.config['color'] = False
        self.config['threaded'] = False

        self.libdir = os.path.join(self.temp_dir, 'libdir')
        os.mkdir(self.libdir)
        self.config['directory'] = self.libdir

        if disk:
            dbpath = self.config['library'].as_filename()
        else:
            dbpath = ':memory:'
        self.lib = Library(dbpath, self.libdir)

    def teardown_beets(self):
        self.lib._connection().close()
        del os.environ['BEETSDIR']
        # FIXME somehow close all open fd to the ilbrary
        self.remove_temp_dir()
        self.config.clear()
        beets.config.read(user=False, defaults=True)

    def load_plugins(self, *plugins):
        """Load and initialize plugins by names.

        Similar setting a list of plugins in the configuration. Make
        sure you call ``unload_plugins()`` afterwards.
        """
        beets.config['plugins'] = plugins
        beets.plugins.load_plugins(plugins)
        beets.plugins.find_plugins()

    def unload_plugins(self):
        """Unload all plugins and remove the from the configuration.
        """
        beets.config['plugins'] = []
        for plugin in beets.plugins._classes:
            plugin.listeners = None
        beets.plugins._classes = set()
        beets.plugins._instances = {}

    def create_importer(self, file_count=1):
        """Returns import session with fixtures.

        Copies the specified number of files to a subdirectory of
        ``self.temp_dir`` and creates a ``TestImportSession`` for this
        path.
        """
        import_dir = os.path.join(self.temp_dir, 'import')
        if not os.path.isdir(import_dir):
            os.mkdir(import_dir)

        for i in range(file_count):
            title = 'track {0}'.format(i)
            src = os.path.join(_common.RSRC, 'full.mp3')
            dest = os.path.join(import_dir, '{0}.mp3'.format(title))
            shutil.copy(src, dest)

        config['import']['quiet'] = True
        config['import']['autotag'] = False
        config['import']['resume'] = False

        return TestImportSession(self.lib, logfile=None, query=None,
                                 paths=[import_dir])

    def add_item_fixtures(self, ext='mp3', count=1):
        items = []
        paths = glob(os.path.join(_common.RSRC, '*.' + ext))
        for path in paths[0:count]:
            item = Item.from_path(str(path))
            item.add(self.lib)
            item.move(copy=True)
            item.store()
            items.append(item)
        return items

    def create_mediafile_fixture(self, ext='mp3'):
        """Copies a fixture mediafile with the extension to a temporary
        location and returns the path.

        It keeps track of the created locations and will delete the with
        `remove_mediafile_fixtures()`
        """
        src = os.path.join(_common.RSRC, 'full.' + ext)
        handle, path = mkstemp()
        os.close(handle)
        shutil.copyfile(src, path)

        if not hasattr(self, '_mediafile_fixtures'):
            self._mediafile_fixtures = []
        self._mediafile_fixtures.append(path)

        return path

    def remove_mediafile_fixtures(self):
        if hasattr(self, '_mediafile_fixtures'):
            for path in self._mediafile_fixtures:
                os.remove(path)

    def run_command(self, *args):
        if hasattr(self, 'lib'):
            lib = self.lib
        else:
            lib = Library(':memory:')
        beets.ui._raw_main(list(args), lib)

    def create_temp_dir(self):
        """Create a temporary directory and assign it into
        `self.temp_dir`. Call `remove_temp_dir` later to delete it.
        """
        self.temp_dir = mkdtemp()

    def remove_temp_dir(self):
        """Delete the temporary directory created by `create_temp_dir`.
        """
        shutil.rmtree(self.temp_dir)
示例#28
0
    gitAnnexLib.from_backup(beetsCommands.get_library())
    return redirect('/albums')


@app.route("/artists")
def artysci():
    return render_template('artists.html')


@app.route("/songs")
def muzyka():
    return render_template('songs.html')


local_repo = gitAnnexLib.Repo(path=beetsCommands.get_library(), local=1)
lib = Library(beetsCommands.get_database())
local_repo.annex_direct()
get_backup(local_repo.path)
import_to_beets(local_repo.path, first=1)
get_backup(local_repo.path)
local_repo.annex_indirect()
#print("local repo autopushing  sdsdfsdfdsfdsfsdfs")
#print(local_repo.autopushing)
for autopush in local_repo.autopushing:
    autopush.get_from(local_repo)
#print("local repo autogetting  sdsdfsdfdsfdsfsdfs")
#print(local_repo.autogetting)
for autoget in local_repo.autogetting:
    local_repo.get_from(autoget)

if __name__ == "__main__":
示例#29
0
 def run_command(self, *args):
     if hasattr(self, 'lib'):
         lib = self.lib
     else:
         lib = Library(':memory:')
     beets.ui._raw_main(list(args), lib)
示例#30
0
文件: helper.py 项目: sbruce/beets
class TestHelper(object):
    """Helper mixin for high-level cli and plugin tests.

    This mixin provides methods to isolate beets' global state provide
    fixtures.
    """
    # TODO automate teardown through hook registration

    def setup_beets(self, disk=False):
        """Setup pristine global configuration and library for testing.

        Sets ``beets.config`` so we can safely use any functionality
        that uses the global configuration.  All paths used are
        contained in a temporary directory

        Sets the following properties on itself.

        - ``temp_dir`` Path to a temporary directory containing all
          files specific to beets

        - ``libdir`` Path to a subfolder of ``temp_dir``, containing the
          library's media files. Same as ``config['directory']``.

        - ``config`` The global configuration used by beets.

        - ``lib`` Library instance created with the settings from
          ``config``.

        Make sure you call ``teardown_beets()`` afterwards.
        """
        self.create_temp_dir()
        os.environ['BEETSDIR'] = self.temp_dir

        self.config = beets.config
        self.config.clear()
        self.config.read()

        self.config['plugins'] = []
        self.config['verbose'] = 1
        self.config['ui']['color'] = False
        self.config['threaded'] = False

        self.libdir = os.path.join(self.temp_dir, 'libdir')
        os.mkdir(self.libdir)
        self.config['directory'] = self.libdir

        if disk:
            dbpath = self.config['library'].as_filename()
        else:
            dbpath = ':memory:'
        self.lib = Library(dbpath, self.libdir)

    def teardown_beets(self):
        self.lib._close()
        if 'BEETSDIR' in os.environ:
            del os.environ['BEETSDIR']
        self.remove_temp_dir()
        self.config.clear()
        beets.config.read(user=False, defaults=True)

    def load_plugins(self, *plugins):
        """Load and initialize plugins by names.

        Similar setting a list of plugins in the configuration. Make
        sure you call ``unload_plugins()`` afterwards.
        """
        # FIXME this should eventually be handled by a plugin manager
        beets.config['plugins'] = plugins
        beets.plugins.load_plugins(plugins)
        beets.plugins.find_plugins()
        # Take a backup of the original _types to restore when unloading
        Item._original_types = dict(Item._types)
        Album._original_types = dict(Album._types)
        Item._types.update(beets.plugins.types(Item))
        Album._types.update(beets.plugins.types(Album))

    def unload_plugins(self):
        """Unload all plugins and remove the from the configuration.
        """
        # FIXME this should eventually be handled by a plugin manager
        beets.config['plugins'] = []
        beets.plugins._classes = set()
        beets.plugins._instances = {}
        Item._types = Item._original_types
        Album._types = Album._original_types

    def create_importer(self, item_count=1, album_count=1):
        """Create files to import and return corresponding session.

        Copies the specified number of files to a subdirectory of
        `self.temp_dir` and creates a `TestImportSession` for this path.
        """
        import_dir = os.path.join(self.temp_dir, 'import')
        if not os.path.isdir(import_dir):
            os.mkdir(import_dir)

        album_no = 0
        while album_count:
            album = u'album {0}'.format(album_no)
            album_dir = os.path.join(import_dir, album)
            if os.path.exists(album_dir):
                album_no += 1
                continue
            os.mkdir(album_dir)
            album_count -= 1

            track_no = 0
            album_item_count = item_count
            while album_item_count:
                title = u'track {0}'.format(track_no)
                src = os.path.join(_common.RSRC, 'full.mp3')
                dest = os.path.join(album_dir, '{0}.mp3'.format(title))
                if os.path.exists(dest):
                    track_no += 1
                    continue
                album_item_count -= 1
                shutil.copy(src, dest)
                mediafile = MediaFile(dest)
                mediafile.update({
                    'artist': 'artist',
                    'albumartist': 'album artist',
                    'title': title,
                    'album': album,
                    'mb_albumid': None,
                    'mb_trackid': None,
                })
                mediafile.save()

        config['import']['quiet'] = True
        config['import']['autotag'] = False
        config['import']['resume'] = False

        return TestImportSession(self.lib, loghandler=None, query=None,
                                 paths=[import_dir])

    # Library fixtures methods

    def create_item(self, **values):
        """Return an `Item` instance with sensible default values.

        The item receives its attributes from `**values` paratmeter. The
        `title`, `artist`, `album`, `track`, `format` and `path`
        attributes have defaults if they are not given as parameters.
        The `title` attribute is formated with a running item count to
        prevent duplicates. The default for the `path` attribute
        respects the `format` value.

        The item is attached to the database from `self.lib`.
        """
        item_count = self._get_item_count()
        values_ = {
            'title': u't\u00eftle {0}',
            'artist': u'the \u00e4rtist',
            'album': u'the \u00e4lbum',
            'track': item_count,
            'format': 'MP3',
        }
        values_.update(values)
        values_['title'] = values_['title'].format(item_count)
        values_['db'] = self.lib
        item = Item(**values_)
        if 'path' not in values:
            item['path'] = 'audio.' + item['format'].lower()
        return item

    def add_item(self, **values):
        """Add an item to the library and return it.

        Creates the item by passing the parameters to `create_item()`.

        If `path` is not set in `values` it is set to `item.destination()`.
        """
        # When specifying a path, store it normalized (as beets does
        # ordinarily).
        if 'path' in values:
            values['path'] = util.normpath(values['path'])

        item = self.create_item(**values)
        item.add(self.lib)

        # Ensure every item has a path.
        if 'path' not in values:
            item['path'] = item.destination()
            item.store()

        return item

    def add_item_fixture(self, **values):
        """Add an item with an actual audio file to the library.
        """
        item = self.create_item(**values)
        extension = item['format'].lower()
        item['path'] = os.path.join(_common.RSRC, 'min.' + extension)
        item.add(self.lib)
        item.move(copy=True)
        item.store()
        return item

    def add_album(self, **values):
        item = self.add_item(**values)
        return self.lib.add_album([item])

    def add_item_fixtures(self, ext='mp3', count=1):
        """Add a number of items with files to the database.
        """
        # TODO base this on `add_item()`
        items = []
        path = os.path.join(_common.RSRC, 'full.' + ext)
        for i in range(count):
            item = Item.from_path(bytes(path))
            item.album = u'\u00e4lbum {0}'.format(i)  # Check unicode paths
            item.title = u't\u00eftle {0}'.format(i)
            item.add(self.lib)
            item.move(copy=True)
            item.store()
            items.append(item)
        return items

    def add_album_fixture(self, track_count=1, ext='mp3'):
        """Add an album with files to the database.
        """
        items = []
        path = os.path.join(_common.RSRC, 'full.' + ext)
        for i in range(track_count):
            item = Item.from_path(bytes(path))
            item.album = u'\u00e4lbum'  # Check unicode paths
            item.title = u't\u00eftle {0}'.format(i)
            item.add(self.lib)
            item.move(copy=True)
            item.store()
            items.append(item)
        return self.lib.add_album(items)

    def create_mediafile_fixture(self, ext='mp3', images=[]):
        """Copies a fixture mediafile with the extension to a temporary
        location and returns the path.

        It keeps track of the created locations and will delete the with
        `remove_mediafile_fixtures()`

        `images` is a subset of 'png', 'jpg', and 'tiff'. For each
        specified extension a cover art image is added to the media
        file.
        """
        src = os.path.join(_common.RSRC, 'full.' + ext)
        handle, path = mkstemp()
        os.close(handle)
        shutil.copyfile(src, path)

        if images:
            mediafile = MediaFile(path)
            imgs = []
            for img_ext in images:
                img_path = os.path.join(_common.RSRC,
                                        'image-2x3.{0}'.format(img_ext))
                with open(img_path, 'rb') as f:
                    imgs.append(Image(f.read()))
            mediafile.images = imgs
            mediafile.save()

        if not hasattr(self, '_mediafile_fixtures'):
            self._mediafile_fixtures = []
        self._mediafile_fixtures.append(path)

        return path

    def remove_mediafile_fixtures(self):
        if hasattr(self, '_mediafile_fixtures'):
            for path in self._mediafile_fixtures:
                os.remove(path)

    def _get_item_count(self):
        if not hasattr(self, '__item_count'):
            count = 0
        self.__item_count = count + 1
        return count

    # Running beets commands

    def run_command(self, *args):
        if hasattr(self, 'lib'):
            lib = self.lib
        else:
            lib = Library(':memory:')
        beets.ui._raw_main(list(args), lib)

    def run_with_output(self, *args):
        with capture_stdout() as out:
            self.run_command(*args)
        return out.getvalue().decode('utf-8')

    # Safe file operations

    def create_temp_dir(self):
        """Create a temporary directory and assign it into
        `self.temp_dir`. Call `remove_temp_dir` later to delete it.
        """
        self.temp_dir = mkdtemp()

    def remove_temp_dir(self):
        """Delete the temporary directory created by `create_temp_dir`.
        """
        shutil.rmtree(self.temp_dir)

    def touch(self, path, dir=None, content=''):
        """Create a file at `path` with given content.

        If `dir` is given, it is prepended to `path`. After that, if the
        path is relative, it is resolved with respect to
        `self.temp_dir`.
        """
        if dir:
            path = os.path.join(dir, path)

        if not os.path.isabs(path):
            path = os.path.join(self.temp_dir, path)

        parent = os.path.dirname(path)
        if not os.path.isdir(parent):
            os.makedirs(parent)

        with open(path, 'a+') as f:
            f.write(content)
        return path
示例#31
0
 def setUp(self):
     self.importfeeds = ImportFeedsPlugin()
     self.lib = Library(':memory:')
     self.feeds_dir = tempfile.mkdtemp()
     config['importfeeds']['dir'] = self.feeds_dir
示例#32
0
def beets_init(path):
    return Library(path)
示例#33
0
文件: helper.py 项目: wickism/beets
class TestHelper(object):
    """Helper mixin for high-level cli and plugin tests.

    This mixin provides methods to isolate beets' global state provide
    fixtures.
    """

    # TODO automate teardown through hook registration

    def setup_beets(self, disk=False):
        """Setup pristine global configuration and library for testing.

        Sets ``beets.config`` so we can safely use any functionality
        that uses the global configuration.  All paths used are
        contained in a temporary directory

        Sets the following properties on itself.

        - ``temp_dir`` Path to a temporary directory containing all
          files specific to beets

        - ``libdir`` Path to a subfolder of ``temp_dir``, containing the
          library's media files. Same as ``config['directory']``.

        - ``config`` The global configuration used by beets.

        - ``lib`` Library instance created with the settings from
          ``config``.

        Make sure you call ``teardown_beets()`` afterwards.
        """
        self.create_temp_dir()
        os.environ['BEETSDIR'] = util.py3_path(self.temp_dir)

        self.config = beets.config
        self.config.clear()
        self.config.read()

        self.config['plugins'] = []
        self.config['verbose'] = 1
        self.config['ui']['color'] = False
        self.config['threaded'] = False

        self.libdir = os.path.join(self.temp_dir, b'libdir')
        os.mkdir(self.libdir)
        self.config['directory'] = util.py3_path(self.libdir)

        if disk:
            dbpath = util.bytestring_path(self.config['library'].as_filename())
        else:
            dbpath = ':memory:'
        self.lib = Library(dbpath, self.libdir)

    def teardown_beets(self):
        self.lib._close()
        if 'BEETSDIR' in os.environ:
            del os.environ['BEETSDIR']
        self.remove_temp_dir()
        self.config.clear()
        beets.config.read(user=False, defaults=True)

    def load_plugins(self, *plugins):
        """Load and initialize plugins by names.

        Similar setting a list of plugins in the configuration. Make
        sure you call ``unload_plugins()`` afterwards.
        """
        # FIXME this should eventually be handled by a plugin manager
        beets.config['plugins'] = plugins
        beets.plugins.load_plugins(plugins)
        beets.plugins.find_plugins()

        # Take a backup of the original _types and _queries to restore
        # when unloading.
        Item._original_types = dict(Item._types)
        Album._original_types = dict(Album._types)
        Item._types.update(beets.plugins.types(Item))
        Album._types.update(beets.plugins.types(Album))

        Item._original_queries = dict(Item._queries)
        Album._original_queries = dict(Album._queries)
        Item._queries.update(beets.plugins.named_queries(Item))
        Album._queries.update(beets.plugins.named_queries(Album))

    def unload_plugins(self):
        """Unload all plugins and remove the from the configuration.
        """
        # FIXME this should eventually be handled by a plugin manager
        beets.config['plugins'] = []
        beets.plugins._classes = set()
        beets.plugins._instances = {}
        Item._types = Item._original_types
        Album._types = Album._original_types
        Item._queries = Item._original_queries
        Album._queries = Album._original_queries

    def create_importer(self, item_count=1, album_count=1):
        """Create files to import and return corresponding session.

        Copies the specified number of files to a subdirectory of
        `self.temp_dir` and creates a `TestImportSession` for this path.
        """
        import_dir = os.path.join(self.temp_dir, b'import')
        if not os.path.isdir(import_dir):
            os.mkdir(import_dir)

        album_no = 0
        while album_count:
            album = util.bytestring_path(u'album {0}'.format(album_no))
            album_dir = os.path.join(import_dir, album)
            if os.path.exists(album_dir):
                album_no += 1
                continue
            os.mkdir(album_dir)
            album_count -= 1

            track_no = 0
            album_item_count = item_count
            while album_item_count:
                title = u'track {0}'.format(track_no)
                src = os.path.join(_common.RSRC, b'full.mp3')
                title_file = util.bytestring_path('{0}.mp3'.format(title))
                dest = os.path.join(album_dir, title_file)
                if os.path.exists(dest):
                    track_no += 1
                    continue
                album_item_count -= 1
                shutil.copy(src, dest)
                mediafile = MediaFile(dest)
                mediafile.update({
                    'artist': 'artist',
                    'albumartist': 'album artist',
                    'title': title,
                    'album': album,
                    'mb_albumid': None,
                    'mb_trackid': None,
                })
                mediafile.save()

        config['import']['quiet'] = True
        config['import']['autotag'] = False
        config['import']['resume'] = False

        return TestImportSession(self.lib,
                                 loghandler=None,
                                 query=None,
                                 paths=[import_dir])

    # Library fixtures methods

    def create_item(self, **values):
        """Return an `Item` instance with sensible default values.

        The item receives its attributes from `**values` paratmeter. The
        `title`, `artist`, `album`, `track`, `format` and `path`
        attributes have defaults if they are not given as parameters.
        The `title` attribute is formated with a running item count to
        prevent duplicates. The default for the `path` attribute
        respects the `format` value.

        The item is attached to the database from `self.lib`.
        """
        item_count = self._get_item_count()
        values_ = {
            'title': u't\u00eftle {0}',
            'artist': u'the \u00e4rtist',
            'album': u'the \u00e4lbum',
            'track': item_count,
            'format': 'MP3',
        }
        values_.update(values)
        values_['title'] = values_['title'].format(item_count)
        values_['db'] = self.lib
        item = Item(**values_)
        if 'path' not in values:
            item['path'] = 'audio.' + item['format'].lower()
        # mtime needs to be set last since other assignments reset it.
        item.mtime = 12345
        return item

    def add_item(self, **values):
        """Add an item to the library and return it.

        Creates the item by passing the parameters to `create_item()`.

        If `path` is not set in `values` it is set to `item.destination()`.
        """
        # When specifying a path, store it normalized (as beets does
        # ordinarily).
        if 'path' in values:
            values['path'] = util.normpath(values['path'])

        item = self.create_item(**values)
        item.add(self.lib)

        # Ensure every item has a path.
        if 'path' not in values:
            item['path'] = item.destination()
            item.store()

        return item

    def add_item_fixture(self, **values):
        """Add an item with an actual audio file to the library.
        """
        item = self.create_item(**values)
        extension = item['format'].lower()
        item['path'] = os.path.join(_common.RSRC,
                                    util.bytestring_path('min.' + extension))
        item.add(self.lib)
        item.move(operation=MoveOperation.COPY)
        item.store()
        return item

    def add_album(self, **values):
        item = self.add_item(**values)
        return self.lib.add_album([item])

    def add_item_fixtures(self, ext='mp3', count=1):
        """Add a number of items with files to the database.
        """
        # TODO base this on `add_item()`
        items = []
        path = os.path.join(_common.RSRC, util.bytestring_path('full.' + ext))
        for i in range(count):
            item = Item.from_path(path)
            item.album = u'\u00e4lbum {0}'.format(i)  # Check unicode paths
            item.title = u't\u00eftle {0}'.format(i)
            # mtime needs to be set last since other assignments reset it.
            item.mtime = 12345
            item.add(self.lib)
            item.move(operation=MoveOperation.COPY)
            item.store()
            items.append(item)
        return items

    def add_album_fixture(self, track_count=1, ext='mp3'):
        """Add an album with files to the database.
        """
        items = []
        path = os.path.join(_common.RSRC, util.bytestring_path('full.' + ext))
        for i in range(track_count):
            item = Item.from_path(path)
            item.album = u'\u00e4lbum'  # Check unicode paths
            item.title = u't\u00eftle {0}'.format(i)
            # mtime needs to be set last since other assignments reset it.
            item.mtime = 12345
            item.add(self.lib)
            item.move(operation=MoveOperation.COPY)
            item.store()
            items.append(item)
        return self.lib.add_album(items)

    def create_mediafile_fixture(self, ext='mp3', images=[]):
        """Copies a fixture mediafile with the extension to a temporary
        location and returns the path.

        It keeps track of the created locations and will delete the with
        `remove_mediafile_fixtures()`

        `images` is a subset of 'png', 'jpg', and 'tiff'. For each
        specified extension a cover art image is added to the media
        file.
        """
        src = os.path.join(_common.RSRC, util.bytestring_path('full.' + ext))
        handle, path = mkstemp()
        os.close(handle)
        shutil.copyfile(src, path)

        if images:
            mediafile = MediaFile(path)
            imgs = []
            for img_ext in images:
                file = util.bytestring_path('image-2x3.{0}'.format(img_ext))
                img_path = os.path.join(_common.RSRC, file)
                with open(img_path, 'rb') as f:
                    imgs.append(Image(f.read()))
            mediafile.images = imgs
            mediafile.save()

        if not hasattr(self, '_mediafile_fixtures'):
            self._mediafile_fixtures = []
        self._mediafile_fixtures.append(path)

        return path

    def remove_mediafile_fixtures(self):
        if hasattr(self, '_mediafile_fixtures'):
            for path in self._mediafile_fixtures:
                os.remove(path)

    def _get_item_count(self):
        if not hasattr(self, '__item_count'):
            count = 0
        self.__item_count = count + 1
        return count

    # Running beets commands

    def run_command(self, *args, **kwargs):
        """Run a beets command with an arbitrary amount of arguments. The
           Library` defaults to `self.lib`, but can be overridden with
           the keyword argument `lib`.
        """
        sys.argv = ['beet']  # avoid leakage from test suite args
        lib = None
        if hasattr(self, 'lib'):
            lib = self.lib
        lib = kwargs.get('lib', lib)
        beets.ui._raw_main(_convert_args(list(args)), lib)

    def run_with_output(self, *args):
        with capture_stdout() as out:
            self.run_command(*args)
        return util.text_string(out.getvalue())

    # Safe file operations

    def create_temp_dir(self):
        """Create a temporary directory and assign it into
        `self.temp_dir`. Call `remove_temp_dir` later to delete it.
        """
        temp_dir = mkdtemp()
        self.temp_dir = util.bytestring_path(temp_dir)

    def remove_temp_dir(self):
        """Delete the temporary directory created by `create_temp_dir`.
        """
        shutil.rmtree(self.temp_dir)

    def touch(self, path, dir=None, content=''):
        """Create a file at `path` with given content.

        If `dir` is given, it is prepended to `path`. After that, if the
        path is relative, it is resolved with respect to
        `self.temp_dir`.
        """
        if dir:
            path = os.path.join(dir, path)

        if not os.path.isabs(path):
            path = os.path.join(self.temp_dir, path)

        parent = os.path.dirname(path)
        if not os.path.isdir(parent):
            os.makedirs(util.syspath(parent))

        with open(util.syspath(path), 'a+') as f:
            f.write(content)
        return path
示例#34
0
文件: helper.py 项目: SRITANU/beets
class TestHelper(object):
    """Helper mixin for high-level cli and plugin tests.

    This mixin provides methods to isolate beets' global state provide
    fixtures.
    """
    # TODO automate teardown through hook registration

    def setup_beets(self, disk=False):
        """Setup pristine global configuration and library for testing.

        Sets ``beets.config`` so we can safely use any functionality
        that uses the global configuration.  All paths used are
        contained in a temporary directory

        Sets the following properties on itself.

        - ``temp_dir`` Path to a temporary directory containing all
          files specific to beets

        - ``libdir`` Path to a subfolder of ``temp_dir``, containing the
          library's media files. Same as ``config['directory']``.

        - ``config`` The global configuration used by beets.

        - ``lib`` Library instance created with the settings from
          ``config``.

        Make sure you call ``teardown_beets()`` afterwards.
        """
        self.create_temp_dir()
        os.environ['BEETSDIR'] = self.temp_dir

        self.config = beets.config
        self.config.clear()
        self.config.read()

        self.config['plugins'] = []
        self.config['verbose'] = True
        self.config['color'] = False
        self.config['threaded'] = False

        self.libdir = os.path.join(self.temp_dir, 'libdir')
        os.mkdir(self.libdir)
        self.config['directory'] = self.libdir

        if disk:
            dbpath = self.config['library'].as_filename()
        else:
            dbpath = ':memory:'
        self.lib = Library(dbpath, self.libdir)

    def teardown_beets(self):
        del self.lib._connections
        if 'BEETSDIR' in os.environ:
            del os.environ['BEETSDIR']
        self.remove_temp_dir()
        self.config.clear()
        beets.config.read(user=False, defaults=True)

    def load_plugins(self, *plugins):
        """Load and initialize plugins by names.

        Similar setting a list of plugins in the configuration. Make
        sure you call ``unload_plugins()`` afterwards.
        """
        beets.config['plugins'] = plugins
        beets.plugins.load_plugins(plugins)
        beets.plugins.find_plugins()

    def unload_plugins(self):
        """Unload all plugins and remove the from the configuration.
        """
        beets.config['plugins'] = []
        for plugin in beets.plugins._classes:
            plugin.listeners = None
        beets.plugins._classes = set()
        beets.plugins._instances = {}

    def create_importer(self, item_count=1, album_count=1):
        """Create files to import and return corresponding session.

        Copies the specified number of files to a subdirectory of
        `self.temp_dir` and creates a `TestImportSession` for this path.
        """
        import_dir = os.path.join(self.temp_dir, 'import')
        if not os.path.isdir(import_dir):
            os.mkdir(import_dir)

        album_no = 0
        while album_count:
            album = u'album {0}'.format(album_no)
            album_dir = os.path.join(import_dir, album)
            if os.path.exists(album_dir):
                album_no += 1
                continue
            os.mkdir(album_dir)
            album_count -= 1

            track_no = 0
            album_item_count = item_count
            while album_item_count:
                title = 'track {0}'.format(track_no)
                src = os.path.join(_common.RSRC, 'full.mp3')
                dest = os.path.join(album_dir, '{0}.mp3'.format(title))
                if os.path.exists(dest):
                    track_no += 1
                    continue
                album_item_count -= 1
                shutil.copy(src, dest)
                mediafile = MediaFile(dest)
                mediafile.update({
                    'artist': 'artist',
                    'albumartist': 'album artist',
                    'title': title,
                    'album': album,
                    'mb_albumid': None,
                    'mb_trackid': None,
                })
                mediafile.save()

        config['import']['quiet'] = True
        config['import']['autotag'] = False
        config['import']['resume'] = False

        return TestImportSession(self.lib, logfile=None, query=None,
                                 paths=[import_dir])

    def add_item_fixtures(self, ext='mp3', count=1):
        """Add a number of items with files to the database.
        """
        items = []
        path = os.path.join(_common.RSRC, 'full.' + ext)
        for i in range(count):
            item = Item.from_path(str(path))
            item.album = u'\u00e4lbum {0}'.format(i)  # Check unicode paths
            item.title = u't\u00eftle {0}'.format(i)
            item.add(self.lib)
            item.move(copy=True)
            item.store()
            items.append(item)
        return items

    def add_album_fixture(self, track_count=1, ext='mp3'):
        """Add an album with files to the database.
        """
        items = []
        path = os.path.join(_common.RSRC, 'full.' + ext)
        for i in range(track_count):
            item = Item.from_path(str(path))
            item.album = u'\u00e4lbum'  # Check unicode paths
            item.title = u't\u00eftle {0}'.format(i)
            item.add(self.lib)
            item.move(copy=True)
            item.store()
            items.append(item)
        return self.lib.add_album(items)

    def create_mediafile_fixture(self, ext='mp3'):
        """Copies a fixture mediafile with the extension to a temporary
        location and returns the path.

        It keeps track of the created locations and will delete the with
        `remove_mediafile_fixtures()`
        """
        src = os.path.join(_common.RSRC, 'full.' + ext)
        handle, path = mkstemp()
        os.close(handle)
        shutil.copyfile(src, path)

        if not hasattr(self, '_mediafile_fixtures'):
            self._mediafile_fixtures = []
        self._mediafile_fixtures.append(path)

        return path

    def remove_mediafile_fixtures(self):
        if hasattr(self, '_mediafile_fixtures'):
            for path in self._mediafile_fixtures:
                os.remove(path)

    def run_command(self, *args):
        if hasattr(self, 'lib'):
            lib = self.lib
        else:
            lib = Library(':memory:')
        beets.ui._raw_main(list(args), lib)

    def run_with_output(self, *args):
        with capture_stdout() as out:
            self.run_command(*args)
        return out.getvalue()

    def create_temp_dir(self):
        """Create a temporary directory and assign it into
        `self.temp_dir`. Call `remove_temp_dir` later to delete it.
        """
        self.temp_dir = mkdtemp()

    def remove_temp_dir(self):
        """Delete the temporary directory created by `create_temp_dir`.
        """
        shutil.rmtree(self.temp_dir)
示例#35
0
class TestHelper(object):
    """Helper mixin for high-level cli and plugin tests.

    This mixin provides methods to isolate beets' global state provide
    fixtures.
    """
    # TODO automate teardown through hook registration

    def setup_beets(self, disk=False):
        """Setup pristine global configuration and library for testing.

        Sets ``beets.config`` so we can safely use any functionality
        that uses the global configuration.  All paths used are
        contained in a temporary directory

        Sets the following properties on itself.

        - ``temp_dir`` Path to a temporary directory containing all
          files specific to beets

        - ``libdir`` Path to a subfolder of ``temp_dir``, containing the
          library's media files. Same as ``config['directory']``.

        - ``config`` The global configuration used by beets.

        - ``lib`` Library instance created with the settings from
          ``config``.

        Make sure you call ``teardown_beets()`` afterwards.
        """
        self.create_temp_dir()
        os.environ['BEETSDIR'] = self.temp_dir

        self.config = beets.config
        self.config.clear()
        self.config.read()

        self.config['plugins'] = []
        self.config['verbose'] = True
        self.config['color'] = False
        self.config['threaded'] = False

        self.libdir = os.path.join(self.temp_dir, 'libdir')
        os.mkdir(self.libdir)
        self.config['directory'] = self.libdir

        if disk:
            dbpath = self.config['library'].as_filename()
        else:
            dbpath = ':memory:'
        self.lib = Library(dbpath, self.libdir)

    def teardown_beets(self):
        del self.lib._connections
        del os.environ['BEETSDIR']
        self.remove_temp_dir()
        self.config.clear()
        beets.config.read(user=False, defaults=True)

    def load_plugins(self, *plugins):
        """Load and initialize plugins by names.

        Similar setting a list of plugins in the configuration. Make
        sure you call ``unload_plugins()`` afterwards.
        """
        beets.config['plugins'] = plugins
        beets.plugins.load_plugins(plugins)
        beets.plugins.find_plugins()

    def unload_plugins(self):
        """Unload all plugins and remove the from the configuration.
        """
        beets.config['plugins'] = []
        for plugin in beets.plugins._classes:
            plugin.listeners = None
        beets.plugins._classes = set()
        beets.plugins._instances = {}

    def create_importer(self, item_count=1, album_count=1):
        """Returns import session with fixtures.

        Copies the specified number of files to a subdirectory of
        ``self.temp_dir`` and creates a ``TestImportSession`` for this
        path.
        """
        import_dir = os.path.join(self.temp_dir, 'import')
        if not os.path.isdir(import_dir):
            os.mkdir(import_dir)

        for i in range(album_count):
            album = u'album {0}'.format(i)
            album_dir = os.path.join(import_dir, album)
            os.mkdir(album_dir)
            for j in range(item_count):
                title = 'track {0}'.format(j)
                src = os.path.join(_common.RSRC, 'full.mp3')
                dest = os.path.join(album_dir, '{0}.mp3'.format(title))
                shutil.copy(src, dest)
                mediafile = MediaFile(dest)
                mediafile.update({
                    'artist': 'artist',
                    'albumartist': 'album artist',
                    'title': title,
                    'album': album,
                    'mb_albumid': None,
                    'mb_trackid': None,
                })
                mediafile.save()

        config['import']['quiet'] = True
        config['import']['autotag'] = False
        config['import']['resume'] = False

        return TestImportSession(self.lib, logfile=None, query=None,
                                 paths=[import_dir])

    def add_item_fixtures(self, ext='mp3', count=1):
        """Add a number of items with files to the database.
        """
        items = []
        path = os.path.join(_common.RSRC, 'full.' + ext)
        for i in range(count):
            item = Item.from_path(str(path))
            item.album = u'\xc3\xa4lbum {0}'.format(i)  # Check unicode paths
            item.title = u't\xc3\x8ftle {0}'.format(i)
            item.add(self.lib)
            item.move(copy=True)
            item.store()
            items.append(item)
        return items

    def add_album_fixture(self, track_count=1):
        """Add an album with files to the database.
        """
        items = []
        path = os.path.join(_common.RSRC, 'full.mp3')
        for i in range(track_count):
            item = Item.from_path(str(path))
            item.album = u'\u00e4lbum'  # Check unicode paths
            item.title = u't\u00eftle {0}'.format(i)
            item.add(self.lib)
            item.move(copy=True)
            item.store()
            items.append(item)
        return self.lib.add_album(items)

    def create_mediafile_fixture(self, ext='mp3'):
        """Copies a fixture mediafile with the extension to a temporary
        location and returns the path.

        It keeps track of the created locations and will delete the with
        `remove_mediafile_fixtures()`
        """
        src = os.path.join(_common.RSRC, 'full.' + ext)
        handle, path = mkstemp()
        os.close(handle)
        shutil.copyfile(src, path)

        if not hasattr(self, '_mediafile_fixtures'):
            self._mediafile_fixtures = []
        self._mediafile_fixtures.append(path)

        return path

    def remove_mediafile_fixtures(self):
        if hasattr(self, '_mediafile_fixtures'):
            for path in self._mediafile_fixtures:
                os.remove(path)

    def run_command(self, *args):
        if hasattr(self, 'lib'):
            lib = self.lib
        else:
            lib = Library(':memory:')
        beets.ui._raw_main(list(args), lib)

    def create_temp_dir(self):
        """Create a temporary directory and assign it into
        `self.temp_dir`. Call `remove_temp_dir` later to delete it.
        """
        self.temp_dir = mkdtemp()

    def remove_temp_dir(self):
        """Delete the temporary directory created by `create_temp_dir`.
        """
        shutil.rmtree(self.temp_dir)