Exemple #1
0
    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
Exemple #2
0
    def test_missing_request(self):
        json_file = os.path.join(_common.RSRC, b'spotify',
                                 b'missing_request.json')
        with open(json_file, 'rb') as f:
            response_body = f.read()

        responses.add(responses.GET, 'https://api.spotify.com/v1/search',
                      body=response_body, status=200,
                      content_type='application/json')
        item = Item(
            mb_trackid=u'01234',
            album=u'lkajsdflakjsd',
            albumartist=u'ujydfsuihse',
            title=u'duifhjslkef',
            length=10
        )
        item.add(self.lib)
        self.assertEqual([], self.spotify.query_spotify(self.lib, u""))

        params = _params(responses.calls[0].request.url)
        self.assertEqual(
            params['q'],
            [u'duifhjslkef album:lkajsdflakjsd artist:ujydfsuihse'],
        )
        self.assertEqual(params['type'], [u'track'])
 def test_missing_request(self):
     response_body = str(
         '{'
         '"tracks" : {'
         '"href" : "https://api.spotify.com/v1/search?query=duifhjslkef'
         '+album%3Alkajsdflakjsd+artist%3A&offset=0&limit=20&type=track",'
         '"items" : [ ],'
         '"limit" : 20,'
         '"next" : null,'
         '"offset" : 0,'
         '"previous" : null,'
         '"total" : 0'
         '}'
         '}'
     )
     responses.add(responses.GET,
                   'https://api.spotify.com/v1/search?q=duifhjslkef+album'
                   '%3Alkajsdflakjsd+artist%3A&type=track',
                   body=response_body, status=200,
                   content_type='application/json')
     item = Item(
         mb_trackid='01234',
         album='lkajsdflakjsd',
         albumartist='ujydfsuihse',
         title='duifhjslkef',
         length=10
     )
     item.add(self.lib)
     self.assertEquals([], self.spotify.query_spotify(self.lib, ""))
Exemple #4
0
    def test_missing_request(self):
        response_body = bytes(
            '{'
            '"tracks" : {'
            '"href" : "https://api.spotify.com/v1/search?query=duifhjslkef'
            '+album%3Alkajsdflakjsd+artist%3A&offset=0&limit=20&type=track",'
            '"items" : [ ],'
            '"limit" : 20,'
            '"next" : null,'
            '"offset" : 0,'
            '"previous" : null,'
            '"total" : 0'
            '}'
            '}'
        )
        responses.add(responses.GET, 'https://api.spotify.com/v1/search',
                      body=response_body, status=200,
                      content_type='application/json')
        item = Item(
            mb_trackid=u'01234',
            album=u'lkajsdflakjsd',
            albumartist=u'ujydfsuihse',
            title=u'duifhjslkef',
            length=10
        )
        item.add(self.lib)
        self.assertEqual([], self.spotify.query_spotify(self.lib, u""))

        params = _params(responses.calls[0].request.url)
        self.assertEqual(
            params['q'],
            [u'duifhjslkef album:lkajsdflakjsd artist:ujydfsuihse'],
        )
        self.assertEqual(params['type'], [u'track'])
Exemple #5
0
    def test_store_data(self, echonest_track, echonest_profile, item_write):
        profile = Mock(
            artist_name='artist',
            title='title',
            id='echonestid',
            audio_summary={
                'duration': 10,
                'energy': 0.5,
                'liveness': 0.5,
                'loudness': 0.5,
                'speechiness': 0.5,
                'danceability': 0.5,
                'tempo': 120,
                'key': 2,
                'mode': 0
            },
        )
        echonest_profile.return_value = [profile]
        echonest_track.return_value = Mock(song_id='echonestid')

        item = Item(
            mb_trackid='01234',
            artist='artist',
            title='title',
            length=10,
        )
        item.add(self.lib)
        self.assertNotIn('danceability', item)
        self.assertNotIn('initialkey', item)

        self.run_command('echonest')
        item.load()
        self.assertEqual(item['danceability'], '0.5')
        self.assertEqual(item['initial_key'], 'C#m')
Exemple #6
0
    def test_track_request(self):

        json_file = os.path.join(_common.RSRC, b'spotify',
                                 b'track_request.json')
        with open(json_file, 'rb') as f:
            response_body = f.read()

        responses.add(responses.GET, 'https://api.spotify.com/v1/search',
                      body=response_body, status=200,
                      content_type='application/json')
        item = Item(
            mb_trackid=u'01234',
            album=u'Despicable Me 2',
            albumartist=u'Pharrell Williams',
            title=u'Happy',
            length=10
        )
        item.add(self.lib)
        results = self.spotify.query_spotify(self.lib, u"Happy")
        self.assertEqual(1, len(results))
        self.assertEqual(u"6NPVjNh8Jhru9xOmyQigds", results[0]['id'])
        self.spotify.output_results(results)

        params = _params(responses.calls[0].request.url)
        self.assertEqual(
            params['q'],
            [u'Happy album:Despicable Me 2 artist:Pharrell Williams'],
        )
        self.assertEqual(params['type'], [u'track'])
Exemple #7
0
    def test_do_not_overwrite(self):
        item = Item(path='/file', initial_key='F')
        item.add(self.lib)

        self.command_output.return_value = 'dbm'
        self.run_command('keyfinder')

        item.load()
        self.assertEqual(item['initial_key'], 'F')
Exemple #8
0
    def test_do_not_overwrite(self):
        item = Item(path="/file", initial_key="F")
        item.add(self.lib)

        self.command_output.return_value = "dbm"
        self.run_command("keyfinder")

        item.load()
        self.assertEqual(item["initial_key"], "F")
Exemple #9
0
    def test_update_rating(self):
        item = Item(title=u'title', path='', id=1)
        item.add(self.lib)

        log = Mock()
        mpdstats = MPDStats(self.lib, log)

        self.assertFalse(mpdstats.update_rating(item, True))
        self.assertFalse(mpdstats.update_rating(None, True))
Exemple #10
0
    def test_add_key(self):
        item = Item(path="/file")
        item.add(self.lib)

        self.command_output.return_value = "dbm"
        self.run_command("keyfinder")

        item.load()
        self.assertEqual(item["initial_key"], "C#m")
        self.command_output.assert_called_with(["KeyFinder", "-f", item.path])
Exemple #11
0
    def test_get_item(self):
        item_path = '/foo/bar.flac'
        item = Item(title=u'title', path=item_path, id=1)
        item.add(self.lib)

        log = Mock()
        mpdstats = MPDStats(self.lib, log)

        self.assertEqual(str(mpdstats.get_item(item_path)), str(item))
        self.assertIsNone(mpdstats.get_item('/some/non-existing/path'))
        self.assertIn(u'item not found:', log.info.call_args[0][0])
Exemple #12
0
    def test_force_overwrite(self):
        self.config['keyfinder']['overwrite'] = True

        item = Item(path='/file', initial_key='F')
        item.add(self.lib)

        self.command_output.return_value = 'C#m'
        self.run_command('keyfinder')

        item.load()
        self.assertEqual(item['initial_key'], 'C#m')
Exemple #13
0
    def test_force_overwrite(self):
        self.config["keyfinder"]["overwrite"] = True

        item = Item(path="/file", initial_key="F")
        item.add(self.lib)

        self.command_output.return_value = "C#m"
        self.run_command("keyfinder")

        item.load()
        self.assertEqual(item["initial_key"], "C#m")
Exemple #14
0
    def test_add_key(self):
        item = Item(path='/file')
        item.add(self.lib)

        self.command_output.return_value = 'dbm'
        self.run_command('keyfinder')

        item.load()
        self.assertEqual(item['initial_key'], 'C#m')
        self.command_output.assert_called_with(
            ['KeyFinder', '-f', item.path])
Exemple #15
0
    def test_write_extended_tag_from_item(self):
        plugin = BeetsPlugin()
        plugin.add_media_field('customtag', field_extension)

        mediafile = self._mediafile_fixture('empty')
        self.assertIsNone(mediafile.customtag)

        item = Item(path=mediafile.path, customtag=u'Gb')
        item.write()
        mediafile = MediaFile(mediafile.path)
        self.assertEqual(mediafile.customtag, u'Gb')

        delattr(MediaFile, 'customtag')
        Item._media_fields.remove('customtag')
Exemple #16
0
    def test_write_extended_tag_from_item(self):
        plugin = BeetsPlugin()
        plugin.add_media_field('initialkey', field_extension)

        mediafile = self._mediafile_fixture('empty')
        self.assertEqual(mediafile.initialkey, '')

        item = Item(path=mediafile.path, initialkey='Gb')
        item.write()
        mediafile = MediaFile(mediafile.path)
        self.assertEqual(mediafile.initialkey, 'Gb')

        delattr(MediaFile, 'initialkey')
        Item.media_fields.remove('initialkey')
Exemple #17
0
    def test_run_mpdstats(self, mpd_mock):
        item = Item(title=u'title', path=self.item_path, id=1)
        item.add(self.lib)

        log = Mock()
        try:
            MPDStats(self.lib, log).run()
        except KeyboardInterrupt:
            pass

        log.debug.assert_has_calls(
            [call(u'unhandled status "{0}"', ANY)])
        log.info.assert_has_calls(
            [call(u'pause'), call(u'playing {0}', ANY), call(u'stop')])
Exemple #18
0
 def addItemFixture(self, basename='ok.ogg'):
     src = os.path.join(self.fixture_dir, basename)
     dst = os.path.join(self.libdir, basename)
     shutil.copy(src, dst)
     item = Item.from_path(dst)
     item.add(self.lib)
     return item
Exemple #19
0
    def test_get_single_item_by_path(self):
        data_path = os.path.join(_common.RSRC, b'full.mp3')
        self.lib.add(Item.from_path(data_path))
        response = self.client.get('/item/path/' + data_path.decode('utf-8'))
        res_json = json.loads(response.data.decode('utf-8'))

        self.assertEqual(response.status_code, 200)
        self.assertEqual(res_json['title'], u'full')
Exemple #20
0
 def setupFixtureLibrary(self):
     self.import_dir = os.path.join(self.temp_dir, 'import')
     for file in os.listdir(self.fixture_dir):
         src = os.path.join(self.fixture_dir, file)
         dst = os.path.join(self.libdir, file)
         shutil.copy(src, dst)
         item = Item.from_path(dst)
         item.add(self.lib)
         check.set_checksum(item)
Exemple #21
0
 def setUp(self):
     self.setup_beets()
     self.load_plugins('edit')
     # Create some mediafiles, and store them for comparison.
     self._create_import_dir(3)
     self.items_orig = [Item.from_path(f.path) for f in self.media_files]
     self.matcher = AutotagStub().install()
     self.matcher.matching = AutotagStub.GOOD
     self.config['import']['timid'] = True
Exemple #22
0
    def add_item(self, **values_):
        """Add an item to the library and return it.

        The item receives sensible default values for the title, artist,
        and album fields. These default values contain unicode
        characters to test for encoding issues. The track title also
        includes a counter to make sure we do not create items with the
        same attributes.
        """
        values = {
            'title': u't\u00eftle {0}'.format(self._get_item_count()),
            'artist': u'the \u00e4rtist',
            'album': u'the \u00e4lbum',
        }
        values.update(values_)
        item = Item(**values)
        if hasattr(self, 'lib'):
            item.add(self.lib)
        return item
Exemple #23
0
 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
Exemple #24
0
def pre_process_folder(folder):
    p = Path(folder)
    assert p.isdir(), "Got non directory input, breaking"

    paths = _collect_files_from_folder(p)
    items = [Item.from_path(str(f)) for f in paths]
    tempdir = tempfile.mkdtemp(prefix="temp_")
    for item in items:
        filename = os.path.basename(item.path)
        item.move_file(os.path.join(tempdir, filename), copy=True)
    yield AlbumTask(items)
Exemple #25
0
    def test_album_art(self):
        self.config['zero']['fields'] = ['images']

        path = self.create_mediafile_fixture(images=['jpg'])
        item = Item.from_path(path)

        self.load_plugins('zero')
        item.write()

        mf = MediaFile(syspath(path))
        self.assertEqual(0, len(mf.images))
Exemple #26
0
    def test_read_flexible_attribute_from_file(self):
        plugin = BeetsPlugin()
        plugin.add_media_field('initialkey', field_extension)

        mediafile = self._mediafile_fixture('empty')
        mediafile.update({'initialkey': 'F#'})

        item = Item.from_path(mediafile.path)
        self.assertEqual(item['initialkey'], 'F#')

        delattr(MediaFile, 'initialkey')
        Item.media_fields.remove('initialkey')
Exemple #27
0
    def emitter():
        fields = list(mediafile.MediaFile.readable_fields())
        fields.remove('images')
        mf = mediafile.MediaFile(syspath(path))
        tags = {}
        for field in fields:
            tags[field] = getattr(mf, field)
        tags['art'] = mf.art is not None
        # create a temporary Item to take advantage of __format__
        item = Item.from_path(syspath(path))

        return tags, item
Exemple #28
0
    def test_update_library(self, track_for_mbid, album_for_mbid):
        album_for_mbid.return_value = \
            generate_album_info('album id', ['track id'])
        track_for_mbid.return_value = \
            generate_track_info(u'singleton track id',
                                {'title': u'singleton info'})

        album_item = Item(
            album=u'old title',
            mb_albumid=u'album id',
            mb_trackid=u'track id',
            path=''
        )
        album = self.lib.add_album([album_item])

        item = Item(
            title=u'old title',
            mb_trackid=u'singleton track id',
            path='',
        )
        self.lib.add(item)

        self.run_command('mbsync')

        item.load()
        self.assertEqual(item.title, u'singleton info')

        album_item.load()
        self.assertEqual(album_item.title, u'track info')

        album.load()
        self.assertEqual(album.album, u'album info')
Exemple #29
0
    def test_album_art(self):
        path = self.create_mediafile_fixture(images=['jpg'])
        item = Item.from_path(path)

        mediafile = MediaFile(syspath(item.path))
        self.assertNotEqual(0, len(mediafile.images))

        config['zero'] = {'fields': [u'images']}
        self.load_plugins('zero')

        item.write()
        mediafile = MediaFile(syspath(item.path))
        self.assertEqual(0, len(mediafile.images))
Exemple #30
0
    def test_read_flexible_attribute_from_file(self):
        plugin = BeetsPlugin()
        plugin.add_media_field('customtag', field_extension)

        mediafile = self._mediafile_fixture('empty')
        mediafile.update({'customtag': u'F#'})
        mediafile.save()

        item = Item.from_path(mediafile.path)
        self.assertEqual(item['customtag'], u'F#')

        delattr(MediaFile, 'customtag')
        Item._media_fields.remove('customtag')
Exemple #31
0
def _item(track_info, album_info, album_id):
    """Build and return `item` from `track_info` and `album info`
    objects. `item` is missing what fields cannot be obtained from
    MusicBrainz alone (encoder, rg_track_gain, rg_track_peak,
    rg_album_gain, rg_album_peak, original_year, original_month,
    original_day, length, bitrate, format, samplerate, bitdepth,
    channels, mtime.)
    """
    t = track_info
    a = album_info

    return Item(
        **{
            'album_id': album_id,
            'album': a.album,
            'albumartist': a.artist,
            'albumartist_credit': a.artist_credit,
            'albumartist_sort': a.artist_sort,
            'albumdisambig': a.albumdisambig,
            'albumstatus': a.albumstatus,
            'albumtype': a.albumtype,
            'artist': t.artist,
            'artist_credit': t.artist_credit,
            'artist_sort': t.artist_sort,
            'asin': a.asin,
            'catalognum': a.catalognum,
            'comp': a.va,
            'country': a.country,
            'day': a.day,
            'disc': t.medium,
            'disctitle': t.disctitle,
            'disctotal': a.mediums,
            'label': a.label,
            'language': a.language,
            'length': t.length,
            'mb_albumid': a.album_id,
            'mb_artistid': t.artist_id,
            'mb_releasegroupid': a.releasegroup_id,
            'mb_trackid': t.track_id,
            'media': t.media,
            'month': a.month,
            'script': a.script,
            'title': t.title,
            'track': t.index,
            'tracktotal': len(a.tracks),
            'year': a.year,
        })
Exemple #32
0
    def test_force_overwrite(self):
        self.config['keyfinder']['overwrite'] = True

        item = Item(path='/file', initial_key='F')
        item.add(self.lib)

        self.command_output.return_value = 'C#m'
        self.run_command('keyfinder')

        item.load()
        self.assertEqual(item['initial_key'], 'C#m')
Exemple #33
0
    def process_item(self, item: Item):
        self._say("Fixing item: {}".format(item), log_only=True)
        current_genre = item.get("genre")

        tag_groups = []

        qtypes = (self.config["types"].keys())
        metadata = {
            'artist': item.get("artist"),
            'artistid': item.get("mb_artistid:"),
            'album': item.get("album"),
            'albumid': item.get("mb_releasegroupid"),
            'year': item.get("year")
        }

        for dp in self.dataproviders:
            # self._say("{}: {}".format("=" * 60, dp.name))
            for qtype in qtypes:
                tags = self.get_tags_from_provider(dp, qtype, metadata)
                # self._say("tags[{}]: {}".format(qtype, tags), log_only=False)
                if tags:
                    tag_groups.append({
                        'provider': dp.name,
                        'qtype': qtype,
                        'tags': tags
                    })

        # self._say("Tags: {}".format(tag_groups), log_only=False)

        tags = self.create_unified_tag_list(tag_groups)
        # self._say("Unified Tags: {}".format(tags), log_only=False)

        tags = self.get_scored_tags(tags)
        # self._say("Scored Tags: {}".format(tags), log_only=False)

        tags = sorted(tags.items(), key=operator.itemgetter(1), reverse=True)
        self._say("Ordered Tags: {}".format(tags), log_only=False)

        _max = self.config["max_tags"].as_number()
        _glue = self.config["tag_glue"].as_str()
        top_tags = [v[0] for v in tags][:_max]
        # self._say("Top Tags: {}".format(top_tags), log_only=False)

        changed = False
        if top_tags:
            new_genre = _glue.join(top_tags)
            if new_genre != current_genre:
                self._say("Setting new genre: '{}' -> '{}'".format(
                    current_genre, new_genre),
                          log_only=False)
                item["genre"] = new_genre
                changed = True

        return changed
Exemple #34
0
    def test_add_key(self, command_output):
        item = Item(path='/file')
        item.add(self.lib)

        command_output.return_value = 'dbm'
        self.run_command('keyfinder')

        item.load()
        self.assertEqual(item['initial_key'], 'C#m')
        command_output.assert_called_with(
            ['KeyFinder', '-f', util.syspath(item.path)])
Exemple #35
0
    def test_normal_case(self, command_output):
        item = Item(path='/file',
                    mb_workid=u'e27bda6e-531e-36d3-9cd7-b8ebc18e8c53')
        item.add(self.lib)

        command_output.return_value = u'32c8943f-1b27-3a23-8660-4567f4847c94'
        self.run_command('parentwork')

        item.load()
        self.assertEqual(item['mb_parentworkid'],
                         u'32c8943f-1b27-3a23-8660-4567f4847c94')
Exemple #36
0
def _item(track_info, album_info, album_id):
    """Build and return `item` from `track_info` and `album info`
    objects. `item` is missing what fields cannot be obtained from
    MusicBrainz alone (encoder, rg_track_gain, rg_track_peak,
    rg_album_gain, rg_album_peak, original_year, original_month,
    original_day, length, bitrate, format, samplerate, bitdepth,
    channels, mtime.)
    """
    t = track_info
    a = album_info

    return Item(
        album_id=album_id,
        album=a.album,
        albumartist=a.artist,
        albumartist_credit=a.artist_credit,
        albumartist_sort=a.artist_sort,
        albumdisambig=a.albumdisambig,
        albumstatus=a.albumstatus,
        albumtype=a.albumtype,
        artist=t.artist,
        artist_credit=t.artist_credit,
        artist_sort=t.artist_sort,
        asin=a.asin,
        catalognum=a.catalognum,
        comp=a.va,
        country=a.country,
        day=a.day,
        disc=t.medium,
        disctitle=t.disctitle,
        disctotal=a.mediums,
        label=a.label,
        language=a.language,
        length=t.length,
        mb_albumid=a.album_id,
        mb_artistid=t.artist_id,
        mb_releasegroupid=a.releasegroup_id,
        mb_trackid=t.track_id,
        media=a.media,
        month=a.month,
        script=a.script,
        title=t.title,
        track=t.index,
        tracktotal=len(a.tracks),
        year=a.year,
    )
Exemple #37
0
 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
Exemple #38
0
 def add_album_fixture(self, track_count=1, ext='mp3', filename='full'):
     """Add an album with files to the database.
     """
     items = []
     path = os.path.join(_common.RSRC,
                         util.bytestring_path(filename + '.' + 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)
Exemple #39
0
def _album_item(album_info):
    """Build and return `item` from `album info`
    objects. `item` is missing what fields cannot be obtained from
    MusicBrainz alone (encoder, rg_track_gain, rg_track_peak,
    rg_album_gain, rg_album_peak, original_year, original_month,
    original_day, length, bitrate, format, samplerate, bitdepth,
    channels, mtime.)
    """
    a = album_info

    return Item(**{
        'album_id':           a.get("id"),
        'album':              a.get("release-group", {}).get("title"),
        'albumartist':        a.get("release-group", {}).get("artist-credit", [])[0].get("artist", {}).get("name") if len(a.get("release-group", {}).get("artist-credit", [])) > 0 else None,
        'albumartist_credit': a.get("release-group", {}).get("artist-credit-phrase"),
        'albumartist_sort':   a.get("release-group", {}).get("artist-credit", [])[0].get("artist", {}).get("sort-name") if len(a.get("release-group", {}).get("artist-credit", [])) > 0 else None,
        'albumdisambig':      a.get("release-group", {}).get("artist-credit", [])[0].get("artist", {}).get("disambiguation") if len(a.get("release-group", {}).get("artist-credit", [])) > 0 else None,
        'albumstatus':        a.get("status"),
        'albumtype':          a.get("release-group", {}).get("primary-type"),
        'albumsubtype':       a.get("release-group", {}).get("secondary-type-list", [])[0] if len(a.get("release-group", {}).get("secondary-type-list", [])) > 0 else None,
        'artist':             a.get("artist-credit", [])[0].get("artist", {}).get("name") if len(a.get("artist-credit", [])) > 0 else None,
        'artist_credit':      a.get("artist-credit-phrase"),
        'artist_sort':        a.get("artist-credit", [])[0].get("artist", {}).get("sort-name") if len(a.get("artist-credit", [])) > 0 else None,
        'asin':               a.get("asin"),
        'catalognum':         a.get("label-info-list", [])[0].get("catalog-number") if len(a.get("label-info-list", [])) > 0 else None,
        'comp':               a.get("artist-credit", [])[0].get("artist", {}).get("name") if len(a.get("artist-credit", [])) > 0 else None,
        'country':            a.get("country"),
        'day':                a.get("date", "")[8:10] if len(a.get("date", "")) == 10 else None,
        'disc':               None,
        'disctitle':          None,
        'disctotal':          None,
        'label':              a.get("label-info-list", [])[0].get("label", {}).get("name") if len(a.get("label-info-list", [])) > 0 else None,
        'language':           a.get("text-representation", {}).get("language"),
        'length':             None,
        'mb_albumid':         a.get("id"),
        'mb_artistid':        a.get("artist-credit", [])[0].get("artist", {}).get("id") if len(a.get("artist-credit", [])) > 0 else None,
        'mb_releasegroupid':  a.get("release-group", {}).get("id"),
        'mb_trackid':         None,
        'media':              a.get("packaging"),
        'month':              a.get("date", "")[5:7] if len(a.get("date", "")) >= 7 else None,
        'script':             a.get("text-representation", {}).get("script"),
        'title':              None,
        'track':              None,
        'tracktotal':         None,
        'year':               a.get("date", "")[0:4] if len(a.get("date", "")) >= 4 else None
    })
    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 formatted with a running item count to
        prevent duplicates.
        """
        item_count = self._get_item_count()
        _values = self.default_item_values
        _values['title'] = _values['title'].format(item_count)
        _values['track'] = item_count
        _values.update(values)
        item = Item(**_values)

        return item
Exemple #41
0
    def test_normal_case_real(self):
        item = Item(path='/file',
                    mb_workid=u'e27bda6e-531e-36d3-9cd7-b8ebc18e8c53',
                    parentwork_workid_current=u'e27bda6e-531e-36d3-9cd7-\
                    b8ebc18e8c53')
        item.add(self.lib)

        self.run_command('parentwork')

        item.load()
        self.assertEqual(item['mb_parentworkid'],
                         u'32c8943f-1b27-3a23-8660-4567f4847c94')
Exemple #42
0
    def test_no_force(self):
        self.config['parentwork']['force'] = True
        item = Item(path='/file',
                    mb_workid=u'e27bda6e-531e-36d3-9cd7-\
                    b8ebc18e8c53',
                    mb_parentworkid=u'XXX')
        item.add(self.lib)

        self.run_command('parentwork')

        item.load()
        self.assertEqual(item['mb_parentworkid'], u'XXX')
Exemple #43
0
    def test_force(self):
        self.config['parentwork']['force'] = True
        item = Item(path='/file',
                    mb_workid=u'e27bda6e-531e-36d3-9cd7-b8ebc18e8c53',
                    mb_parentworkid=u'XXX')
        item.add(self.lib)

        self.run_command('parentwork')

        item.load()
        self.assertEqual(item['mb_parentworkid'],
                         u'32c8943f-1b27-3a23-8660-4567f4847c94')
Exemple #44
0
 def add_album(self, **kwargs):
     values = {
         'title': 'track 1',
         'artist': 'artist 1',
         'album': 'album 1',
         'format': 'mp3',
     }
     values.update(kwargs)
     ext = values.pop('format').lower()
     item = Item.from_path(os.path.join(self.fixture_dir, 'min.' + ext))
     item.add(self.lib)
     item.update(values)
     item.move(copy=True)
     item.write()
     album = self.lib.add_album([item])
     album.albumartist = item.artist
     album.store()
     return album
Exemple #45
0
    def test_no_force(self):
        self.config['parentwork']['force'] = False
        item = Item(path='/file',
                    mb_workid='1',
                    mb_parentworkid=u'XXX',
                    parentwork_workid_current='1',
                    parentwork='parentwork')
        item.add(self.lib)

        self.run_command('parentwork')

        item.load()
        self.assertEqual(item['mb_parentworkid'], u'XXX')
Exemple #46
0
    def _merge_albums(self, objs):
        """Merge Album objs by copying missing items from albums in the tail
        to the head album.

        Return same number of albums, with the head album modified."""
        ids = [i.mb_trackid for i in objs[0].items()]
        for o in objs[1:]:
            for i in o.items():
                if i.mb_trackid not in ids:
                    missing = Item.from_path(i.path)
                    missing.album_id = objs[0].id
                    missing.add(i._db)
                    self._log.debug(
                        u'item {0} missing from album {1}:'
                        u' merging from {2} into {3}', missing, objs[0],
                        displayable_path(o.path),
                        displayable_path(missing.destination()))
                    missing.move(copy=True)
        return objs
Exemple #47
0
    def test_delete_replaygain_tag(self):
        path = self.create_mediafile_fixture()
        item = Item.from_path(path)
        item.rg_track_peak = 0.0
        item.write()

        mediafile = MediaFile(item.path)
        self.assertIsNotNone(mediafile.rg_track_peak)
        self.assertIsNotNone(mediafile.rg_track_gain)

        config['zero'] = {
            'fields': ['rg_track_peak', 'rg_track_gain'],
        }
        self.load_plugins('zero')

        item.write()
        mediafile = MediaFile(item.path)
        self.assertIsNone(mediafile.rg_track_peak)
        self.assertIsNone(mediafile.rg_track_gain)
Exemple #48
0
    def test_patch_item_id(self):
        # Note: PATCH is currently only implemented for track items, not albums

        web.app.config['READONLY'] = False

        # Create a temporary item
        item_id = self.lib.add(
            Item(title='test_patch_item_id',
                 test_patch_f1=1,
                 test_patch_f2="Old"))

        # Check we can find the temporary item we just created
        response = self.client.get('/item/' + str(item_id))
        res_json = json.loads(response.data.decode('utf-8'))
        self.assertEqual(response.status_code, 200)
        self.assertEqual(res_json['id'], item_id)
        self.assertEqual(
            [res_json['test_patch_f1'], res_json['test_patch_f2']],
            ['1', 'Old'])

        # Patch item by id
        # patch_json = json.JSONEncoder().encode({"test_patch_f2": "New"}]})
        response = self.client.patch('/item/' + str(item_id),
                                     json={"test_patch_f2": "New"})
        res_json = json.loads(response.data.decode('utf-8'))
        self.assertEqual(response.status_code, 200)
        self.assertEqual(res_json['id'], item_id)
        self.assertEqual(
            [res_json['test_patch_f1'], res_json['test_patch_f2']],
            ['1', 'New'])

        # Check the update has really worked
        response = self.client.get('/item/' + str(item_id))
        res_json = json.loads(response.data.decode('utf-8'))
        self.assertEqual(response.status_code, 200)
        self.assertEqual(res_json['id'], item_id)
        self.assertEqual(
            [res_json['test_patch_f1'], res_json['test_patch_f2']],
            ['1', 'New'])

        # Remove the item
        self.lib.get_item(item_id).remove()
Exemple #49
0
 def test_hate(self):
     genre_p = []
     artist_p = []
     album_p = []
     white_p = []
     task = ImportTask()
     task.cur_artist = u'Test Artist'
     task.cur_album = u'Test Album'
     task.items = [Item({'genre': 'Test Genre'})]
     self.assertFalse(
         IHatePlugin.do_i_hate_this(task, genre_p, artist_p, album_p,
                                    white_p))
     genre_p = 'some_genre test\sgenre'.split()
     self.assertTrue(
         IHatePlugin.do_i_hate_this(task, genre_p, artist_p, album_p,
                                    white_p))
     genre_p = []
     artist_p = 'bad_artist test\sartist'
     self.assertTrue(
         IHatePlugin.do_i_hate_this(task, genre_p, artist_p, album_p,
                                    white_p))
     artist_p = []
     album_p = 'tribute christmas test'.split()
     self.assertTrue(
         IHatePlugin.do_i_hate_this(task, genre_p, artist_p, album_p,
                                    white_p))
     album_p = []
     white_p = 'goodband test\sartist another_band'.split()
     genre_p = 'some_genre test\sgenre'.split()
     self.assertFalse(
         IHatePlugin.do_i_hate_this(task, genre_p, artist_p, album_p,
                                    white_p))
     genre_p = []
     artist_p = 'bad_artist test\sartist'
     self.assertFalse(
         IHatePlugin.do_i_hate_this(task, genre_p, artist_p, album_p,
                                    white_p))
     artist_p = []
     album_p = 'tribute christmas test'.split()
     self.assertFalse(
         IHatePlugin.do_i_hate_this(task, genre_p, artist_p, album_p,
                                    white_p))
Exemple #50
0
    def emitter(included_keys):
        if included_keys == '*':
            fields = tag_fields()
        else:
            fields = included_keys
        if 'images' in fields:
            # We can't serialize the image data.
            fields.remove('images')
        mf = mediafile.MediaFile(syspath(path))
        tags = {}
        for field in fields:
            if field == 'art':
                tags[field] = mf.art is not None
            else:
                tags[field] = getattr(mf, field, None)

        # create a temporary Item to take advantage of __format__
        item = Item.from_path(syspath(path))

        return tags, item
Exemple #51
0
    def test_update_library(self, track_for_id, album_for_id):
        album_for_id.return_value = \
            generate_album_info(
                'album id',
                [('track id', {'release_track_id': u'release track id'})]
            )
        track_for_id.return_value = \
            generate_track_info(u'singleton track id',
                                {'title': u'singleton info'})

        album_item = Item(album=u'old title',
                          mb_albumid=u'81ae60d4-5b75-38df-903a-db2cfa51c2c6',
                          mb_trackid=u'old track id',
                          mb_releasetrackid=u'release track id',
                          path='')
        album = self.lib.add_album([album_item])

        item = Item(
            title=u'old title',
            mb_trackid=u'b8c2cf90-83f9-3b5f-8ccd-31fb866fcf37',
            path='',
        )
        self.lib.add(item)

        with capture_log() as logs:
            self.run_command('mbsync')

        self.assertIn('Sending event: albuminfo_received', logs)
        self.assertIn('Sending event: trackinfo_received', logs)

        item.load()
        self.assertEqual(item.title, u'singleton info')

        album_item.load()
        self.assertEqual(album_item.title, u'track info')
        self.assertEqual(album_item.mb_trackid, u'track id')

        album.load()
        self.assertEqual(album.album, u'album info')
Exemple #52
0
    def _merge_items(self, objs):
        """Merge Item objs by copying missing fields from items in the tail to
        the head item.

        Return same number of items, with the head item modified.
        """
        fields = Item.all_keys()
        for f in fields:
            for o in objs[1:]:
                if getattr(objs[0], f, None) in (None, ''):
                    value = getattr(o, f, None)
                    if value:
                        self._log.debug(u'key {0} on item {1} is null '
                                        u'or empty: setting from item {2}',
                                        f, displayable_path(objs[0].path),
                                        displayable_path(o.path))
                        setattr(objs[0], f, value)
                        objs[0].store()
                        break
        return objs
Exemple #53
0
    def test_no_force_real(self):
        self.config['parentwork']['force'] = False
        item = Item(path='/file',
                    mb_workid='e27bda6e-531e-36d3-9cd7-\
                    b8ebc18e8c53',
                    mb_parentworkid='XXX',
                    parentwork_workid_current='e27bda6e-531e-36d3-9cd7-\
                    b8ebc18e8c53',
                    parentwork='whatever')
        item.add(self.lib)

        self.run_command('parentwork')

        item.load()
        self.assertEqual(item['mb_parentworkid'], 'XXX')
 def _import_mtags(self, lib, opts, args):
     path, = args
     paths = [Path(path)]
     while paths:
         p = paths.pop(0)
         for child in p.iterdir():
             if child.is_dir():
                 paths.append(child)
                 continue
             loader = MTagLoader(child)
             al = []
             for path, data in loader.items():
                 matching = lib.items(PathQuery('path', path))
                 if any(m.path == path.encode() for m in matching):
                     continue
                 print('add %r' % path)
                 item = Item(path=path)
                 mf = MediaFile(syspath(item.path))
                 for field in AUDIO_FIELDS:
                     v = getattr(mf, field)
                     item[field] = v
                 values = {}
                 for tag, converter in TAGS.items():
                     v = converter.get(data)
                     if v is not None:
                         values[tag] = v
                         item[tag] = v
                 for tag, converter in DEPENDENT_TAGS.items():
                     v = converter.get(data, values)
                     if v is not None:
                         item[tag] = v
                 al.append(item)
             if al:
                 #print(al)
                 try:
                     lib.add_album(al)
                 except BaseException as e:
                     import pdb
                     pdb.post_mortem(e.__traceback__)
                     return
Exemple #55
0
    def test_search_artist(self):
        item = Item(artist='Alice ft. Bob', title='song')
        self.assertIn(('Alice ft. Bob', ['song']),
                      lyrics.search_pairs(item))
        self.assertIn(('Alice', ['song']),
                      lyrics.search_pairs(item))

        item = Item(artist='Alice feat Bob', title='song')
        self.assertIn(('Alice feat Bob', ['song']),
                      lyrics.search_pairs(item))
        self.assertIn(('Alice', ['song']),
                      lyrics.search_pairs(item))

        item = Item(artist='Alice feat. Bob', title='song')
        self.assertIn(('Alice feat. Bob', ['song']),
                      lyrics.search_pairs(item))
        self.assertIn(('Alice', ['song']),
                      lyrics.search_pairs(item))

        item = Item(artist='Alice feats Bob', title='song')
        self.assertIn(('Alice feats Bob', ['song']),
                      lyrics.search_pairs(item))
        self.assertNotIn(('Alice', ['song']),
                         lyrics.search_pairs(item))

        item = Item(artist='Alice featuring Bob', title='song')
        self.assertIn(('Alice featuring Bob', ['song']),
                      lyrics.search_pairs(item))
        self.assertIn(('Alice', ['song']),
                      lyrics.search_pairs(item))

        item = Item(artist='Alice & Bob', title='song')
        self.assertIn(('Alice & Bob', ['song']),
                      lyrics.search_pairs(item))
        self.assertIn(('Alice', ['song']),
                      lyrics.search_pairs(item))

        item = Item(artist='Alice and Bob', title='song')
        self.assertIn(('Alice and Bob', ['song']),
                      lyrics.search_pairs(item))
        self.assertIn(('Alice', ['song']),
                      lyrics.search_pairs(item))
Exemple #56
0
def identify_album_from_multiple_paths(paths_list_or_beets_items_list=None, expected_artist=None, expected_album=None,
                                       expected_release_id=None):
    items = paths_list_or_beets_items_list

    if isinstance(paths_list_or_beets_items_list[0], six.string_types):
        items = [Item.from_path(x) for x in paths_list_or_beets_items_list if is_media_file(x)]

    logger.debug("Called with {} items, expected id {}".format(len(items), expected_release_id))
    artist_name, album_name, album_recommendation_list, recommendation = \
        tag_album(items, search_artist=expected_artist, search_album=expected_album,
                  search_ids=[expected_release_id] if expected_release_id else [])

    if recommendation is Recommendation.none:
        return None, None

    distance, album_info, track_mapping, extra_items, extra_tracks = album_recommendation_list[0]
    logger.debug('Successfully matched album {} !'.format(album_info.album_id))

    logger.info("Successfully tagged album {album_id}, releasegroup {rgid}".format(album_id=album_info.album_id,
                                                                                   rgid=album_info.releasegroup_id))

    return album_info, track_mapping
Exemple #57
0
    def test_delete_item_id(self):

        web.app.config['READONLY'] = False

        # Create a temporary item
        item_id = self.lib.add(
            Item(title='test_delete_item_id', test_delete_item_id=1))

        # Check we can find the temporary item we just created
        response = self.client.get('/item/' + str(item_id))
        res_json = json.loads(response.data.decode('utf-8'))
        self.assertEqual(response.status_code, 200)
        self.assertEqual(res_json['id'], item_id)

        # Delete item by id
        response = self.client.delete('/item/' + str(item_id))
        res_json = json.loads(response.data.decode('utf-8'))
        self.assertEqual(response.status_code, 200)

        # Check the item has gone
        response = self.client.get('/item/' + str(item_id))
        self.assertEqual(response.status_code, 404)
Exemple #58
0
    def test_hate(self):

        match_pattern = {}
        test_item = Item(
            genre='TestGenre',
            album=u'TestAlbum',
            artist=u'TestArtist')
        task = importer.ImportTask()
        task.items = [test_item]
        task.item = test_item
        task.is_album = False

        # Empty query should let it pass.
        self.assertFalse(IHatePlugin.do_i_hate_this(task, match_pattern))

        # 1 query match.
        match_pattern = ["artist:bad_artist","artist:TestArtist"]
        self.assertTrue(IHatePlugin.do_i_hate_this(task, match_pattern))

        # 2 query matches, either should trigger.
        match_pattern = ["album:test","artist:testartist"]
        self.assertTrue(IHatePlugin.do_i_hate_this(task, match_pattern))

        # Query is blocked by AND clause.
        match_pattern = ["album:notthis genre:testgenre"]
        self.assertFalse(IHatePlugin.do_i_hate_this(task, match_pattern))

        # Both queries are blocked by AND clause with unmatched condition.
        match_pattern = ["album:notthis genre:testgenre",
                         "artist:testartist album:notthis"]
        self.assertFalse(IHatePlugin.do_i_hate_this(task, match_pattern))

        # Only one query should fire.
        match_pattern = ["album:testalbum genre:testgenre",
                         "artist:testartist album:notthis"]
        self.assertTrue(IHatePlugin.do_i_hate_this(task, match_pattern))
Exemple #59
0
    def create_track(self, hgid, hid, tmpfname, path):
        """
        Creates the data corresponding to the track in impala associated with
        the holding uuid based on metadata gleaned from beets. If it fails,
        raises an exception.
        """
        try:
            # In the event the item isn't a music track, we need to prevent it
            # from getting added to impala but keep it in moss.
            i = Item.from_path(tmpfname)
        except:
            return

        # Create a stack and format if they don't already exist
        self._create_default_objects()

        # Create the holding group if it doesn't already exist
        self._create_holding_group(hgid, i)

        # Create the holding if it doesn't already exist
        self._create_holding(hgid, hid, i)

        # Create the track
        self._create_track(hid, path, i)
Exemple #60
0
    def test_delete_item_query(self):

        web.app.config['READONLY'] = False

        # Create a temporary item
        self.lib.add(
            Item(title='test_delete_item_query', test_delete_item_query=1))

        # Check we can find the temporary item we just created
        response = self.client.get('/item/query/test_delete_item_query')
        res_json = json.loads(response.data.decode('utf-8'))
        self.assertEqual(response.status_code, 200)
        self.assertEqual(len(res_json['results']), 1)

        # Delete item by query
        response = self.client.delete('/item/query/test_delete_item_query')
        res_json = json.loads(response.data.decode('utf-8'))
        self.assertEqual(response.status_code, 200)

        # Check the item has gone
        response = self.client.get('/item/query/test_delete_item_query')
        res_json = json.loads(response.data.decode('utf-8'))
        self.assertEqual(response.status_code, 200)
        self.assertEqual(len(res_json['results']), 0)