class AuthTestSpotipy(unittest.TestCase):
    """
    These tests require client authentication - provide client credentials
    using the following environment variables

    ::

        'SPOTIPY_CLIENT_ID'
        'SPOTIPY_CLIENT_SECRET'
    """

    playlist = "spotify:user:plamere:playlist:2oCEWyyAPbZp9xhVSxZavx"
    four_tracks = [
        "spotify:track:6RtPijgfPKROxEzTHNRiDp",
        "spotify:track:7IHOIqZUUInxjVkko181PB", "4VrWlk8IQxevMvERoX08iC",
        "http://open.spotify.com/track/3cySlItpiPiIAzU3NyHCJf"
    ]

    two_tracks = [
        "spotify:track:6RtPijgfPKROxEzTHNRiDp",
        "spotify:track:7IHOIqZUUInxjVkko181PB"
    ]

    other_tracks = [
        "spotify:track:2wySlB6vMzCbQrRnNGOYKa",
        "spotify:track:29xKs5BAHlmlX1u4gzQAbJ",
        "spotify:track:1PB7gRWcvefzu7t3LJLUlf"
    ]

    bad_id = 'BAD_ID'

    creep_urn = 'spotify:track:6b2oQwSGFkzsMtQruIWm2p'
    creep_id = '6b2oQwSGFkzsMtQruIWm2p'
    creep_url = 'http://open.spotify.com/track/6b2oQwSGFkzsMtQruIWm2p'
    el_scorcho_urn = 'spotify:track:0Svkvt5I79wficMFgaqEQJ'
    el_scorcho_bad_urn = 'spotify:track:0Svkvt5I79wficMFgaqEQK'
    pinkerton_urn = 'spotify:album:04xe676vyiTeYNXw15o9jT'
    weezer_urn = 'spotify:artist:3jOstUTkEu2JkjvRdBA5Gu'
    pablo_honey_urn = 'spotify:album:6AZv3m27uyRxi8KyJSfUxL'
    radiohead_urn = 'spotify:artist:4Z8W4fKeB5YxbusRsdQVPb'
    angeles_haydn_urn = 'spotify:album:1vAbqAeuJVWNAe7UR00bdM'
    heavyweight_urn = 'spotify:show:5c26B28vZMN8PG0Nppmn5G'
    heavyweight_id = '5c26B28vZMN8PG0Nppmn5G'
    heavyweight_url = 'https://open.spotify.com/show/5c26B28vZMN8PG0Nppmn5G'
    reply_all_urn = 'spotify:show:7gozmLqbcbr6PScMjc0Zl4'
    heavyweight_ep1_urn = 'spotify:episode:68kq3bNz6hEuq8NtdfwERG'
    heavyweight_ep1_id = '68kq3bNz6hEuq8NtdfwERG'
    heavyweight_ep1_url = 'https://open.spotify.com/episode/68kq3bNz6hEuq8NtdfwERG'
    reply_all_ep1_urn = 'spotify:episode:1KHjbpnmNpFmNTczQmTZlR'

    @classmethod
    def setUpClass(self):
        self.spotify = Spotify(
            client_credentials_manager=SpotifyClientCredentials())
        self.spotify.trace = False

    def test_audio_analysis(self):
        result = self.spotify.audio_analysis(self.four_tracks[0])
        assert ('beats' in result)

    def test_audio_features(self):
        results = self.spotify.audio_features(self.four_tracks)
        self.assertTrue(len(results) == len(self.four_tracks))
        for track in results:
            assert ('speechiness' in track)

    def test_audio_features_with_bad_track(self):
        bad_tracks = ['spotify:track:bad']
        input = self.four_tracks + bad_tracks
        results = self.spotify.audio_features(input)
        self.assertTrue(len(results) == len(input))
        for track in results[:-1]:
            if track is not None:
                assert ('speechiness' in track)
        self.assertTrue(results[-1] is None)

    def test_recommendations(self):
        results = self.spotify.recommendations(seed_tracks=self.four_tracks,
                                               min_danceability=0,
                                               max_loudness=0,
                                               target_popularity=50)
        self.assertTrue(len(results['tracks']) == 20)

    def test_artist_urn(self):
        artist = self.spotify.artist(self.radiohead_urn)
        self.assertTrue(artist['name'] == 'Radiohead')

    def test_artists(self):
        results = self.spotify.artists([self.weezer_urn, self.radiohead_urn])
        self.assertTrue('artists' in results)
        self.assertTrue(len(results['artists']) == 2)

    def test_album_urn(self):
        album = self.spotify.album(self.pinkerton_urn)
        self.assertTrue(album['name'] == 'Pinkerton')

    def test_album_tracks(self):
        results = self.spotify.album_tracks(self.pinkerton_urn)
        self.assertTrue(len(results['items']) == 10)

    def test_album_tracks_many(self):
        results = self.spotify.album_tracks(self.angeles_haydn_urn)
        tracks = results['items']
        total, received = results['total'], len(tracks)
        while received < total:
            results = self.spotify.album_tracks(self.angeles_haydn_urn,
                                                offset=received)
            tracks.extend(results['items'])
            received = len(tracks)

        self.assertEqual(received, total)

    def test_albums(self):
        results = self.spotify.albums(
            [self.pinkerton_urn, self.pablo_honey_urn])
        self.assertTrue('albums' in results)
        self.assertTrue(len(results['albums']) == 2)

    def test_track_urn(self):
        track = self.spotify.track(self.creep_urn)
        self.assertTrue(track['name'] == 'Creep')

    def test_track_id(self):
        track = self.spotify.track(self.creep_id)
        self.assertTrue(track['name'] == 'Creep')
        self.assertTrue(track['popularity'] > 0)

    def test_track_url(self):
        track = self.spotify.track(self.creep_url)
        self.assertTrue(track['name'] == 'Creep')

    def test_track_bad_urn(self):
        try:
            self.spotify.track(self.el_scorcho_bad_urn)
            self.assertTrue(False)
        except SpotifyException:
            self.assertTrue(True)

    def test_tracks(self):
        results = self.spotify.tracks([self.creep_url, self.el_scorcho_urn])
        self.assertTrue('tracks' in results)
        self.assertTrue(len(results['tracks']) == 2)

    def test_artist_top_tracks(self):
        results = self.spotify.artist_top_tracks(self.weezer_urn)
        self.assertTrue('tracks' in results)
        self.assertTrue(len(results['tracks']) == 10)

    def test_artist_related_artists(self):
        results = self.spotify.artist_related_artists(self.weezer_urn)
        self.assertTrue('artists' in results)
        self.assertTrue(len(results['artists']) == 20)
        for artist in results['artists']:
            if artist['name'] == 'Jimmy Eat World':
                found = True
        self.assertTrue(found)

    def test_artist_search(self):
        results = self.spotify.search(q='weezer', type='artist')
        self.assertTrue('artists' in results)
        self.assertTrue(len(results['artists']['items']) > 0)
        self.assertTrue(results['artists']['items'][0]['name'] == 'Weezer')

    def test_artist_search_with_market(self):
        results = self.spotify.search(q='weezer', type='artist', market='GB')
        self.assertTrue('artists' in results)
        self.assertTrue(len(results['artists']['items']) > 0)
        self.assertTrue(results['artists']['items'][0]['name'] == 'Weezer')

    def test_artist_search_with_multiple_markets(self):
        total = 5
        countries_list = ['GB', 'US', 'AU']
        countries_tuple = ('GB', 'US', 'AU')

        results_multiple = self.spotify.search_markets(q='weezer',
                                                       type='artist',
                                                       markets=countries_list)
        results_all = self.spotify.search_markets(q='weezer', type='artist')
        results_tuple = self.spotify.search_markets(q='weezer',
                                                    type='artist',
                                                    markets=countries_tuple)
        results_limited = self.spotify.search_markets(q='weezer',
                                                      limit=3,
                                                      type='artist',
                                                      markets=countries_list,
                                                      total=total)

        self.assertTrue(
            all('artists' in results_multiple[country]
                for country in results_multiple))
        self.assertTrue(
            all('artists' in results_all[country] for country in results_all))
        self.assertTrue(
            all('artists' in results_tuple[country]
                for country in results_tuple))
        self.assertTrue(
            all('artists' in results_limited[country]
                for country in results_limited))

        self.assertTrue(
            all(
                len(results_multiple[country]['artists']['items']) > 0
                for country in results_multiple))
        self.assertTrue(
            all(
                len(results_all[country]['artists']['items']) > 0
                for country in results_all))
        self.assertTrue(
            all(
                len(results_tuple[country]['artists']['items']) > 0
                for country in results_tuple))
        self.assertTrue(
            all(
                len(results_limited[country]['artists']['items']) > 0
                for country in results_limited))

        self.assertTrue(
            all(results_multiple[country]['artists']['items'][0]['name'] ==
                'Weezer' for country in results_multiple))
        self.assertTrue(
            all(results_all[country]['artists']['items'][0]['name'] == 'Weezer'
                for country in results_all))
        self.assertTrue(
            all(results_tuple[country]['artists']['items'][0]['name'] ==
                'Weezer' for country in results_tuple))
        self.assertTrue(
            all(results_limited[country]['artists']['items'][0]['name'] ==
                'Weezer' for country in results_limited))

        total_limited_results = 0
        for country in results_limited:
            total_limited_results += len(
                results_limited[country]['artists']['items'])
        self.assertTrue(total_limited_results <= total)

    def test_artist_albums(self):
        results = self.spotify.artist_albums(self.weezer_urn)
        self.assertTrue('items' in results)
        self.assertTrue(len(results['items']) > 0)

        found = False
        for album in results['items']:
            if album['name'] == 'Hurley':
                found = True

        self.assertTrue(found)

    def test_search_timeout(self):
        client_credentials_manager = SpotifyClientCredentials()
        sp = spotipy.Spotify(
            requests_timeout=0.01,
            client_credentials_manager=client_credentials_manager)

        # depending on the timing or bandwidth, this raises a timeout or connection error"
        self.assertRaises(
            (requests.exceptions.Timeout, requests.exceptions.ConnectionError),
            lambda: sp.search(q='my*', type='track'))

    def test_album_search(self):
        results = self.spotify.search(q='weezer pinkerton', type='album')
        self.assertTrue('albums' in results)
        self.assertTrue(len(results['albums']['items']) > 0)
        self.assertTrue(
            results['albums']['items'][0]['name'].find('Pinkerton') >= 0)

    def test_track_search(self):
        results = self.spotify.search(q='el scorcho weezer', type='track')
        self.assertTrue('tracks' in results)
        self.assertTrue(len(results['tracks']['items']) > 0)
        self.assertTrue(results['tracks']['items'][0]['name'] == 'El Scorcho')

    def test_user(self):
        user = self.spotify.user(user='******')
        self.assertTrue(user['uri'] == 'spotify:user:plamere')

    def test_track_bad_id(self):
        try:
            self.spotify.track(self.bad_id)
            self.assertTrue(False)
        except SpotifyException:
            self.assertTrue(True)

    def test_show_urn(self):
        show = self.spotify.show(self.heavyweight_urn, market="US")
        self.assertTrue(show['name'] == 'Heavyweight')

    def test_show_id(self):
        show = self.spotify.show(self.heavyweight_id, market="US")
        self.assertTrue(show['name'] == 'Heavyweight')

    def test_show_url(self):
        show = self.spotify.show(self.heavyweight_url, market="US")
        self.assertTrue(show['name'] == 'Heavyweight')

    def test_show_bad_urn(self):
        with self.assertRaises(SpotifyException):
            self.spotify.show("bogus_urn", market="US")

    def test_shows(self):
        results = self.spotify.shows(
            [self.heavyweight_urn, self.reply_all_urn], market="US")
        self.assertTrue('shows' in results)
        self.assertTrue(len(results['shows']) == 2)

    def test_show_episodes(self):
        results = self.spotify.show_episodes(self.heavyweight_urn, market="US")
        self.assertTrue(len(results['items']) > 1)

    def test_show_episodes_many(self):
        results = self.spotify.show_episodes(self.reply_all_urn, market="US")
        episodes = results['items']
        total, received = results['total'], len(episodes)
        while received < total:
            results = self.spotify.show_episodes(self.reply_all_urn,
                                                 offset=received,
                                                 market="US")
            episodes.extend(results['items'])
            received = len(episodes)

        self.assertEqual(received, total)

    def test_episode_urn(self):
        episode = self.spotify.episode(self.heavyweight_ep1_urn, market="US")
        self.assertTrue(episode['name'] == '#1 Buzz')

    def test_episode_id(self):
        episode = self.spotify.episode(self.heavyweight_ep1_id, market="US")
        self.assertTrue(episode['name'] == '#1 Buzz')

    def test_episode_url(self):
        episode = self.spotify.episode(self.heavyweight_ep1_url, market="US")
        self.assertTrue(episode['name'] == '#1 Buzz')

    def test_episode_bad_urn(self):
        with self.assertRaises(SpotifyException):
            self.spotify.episode("bogus_urn", market="US")

    def test_episodes(self):
        results = self.spotify.episodes(
            [self.heavyweight_ep1_urn, self.reply_all_ep1_urn], market="US")
        self.assertTrue('episodes' in results)
        self.assertTrue(len(results['episodes']) == 2)

    def test_unauthenticated_post_fails(self):
        with self.assertRaises(SpotifyException) as cm:
            self.spotify.user_playlist_create("spotify",
                                              "Best hits of the 90s")
        self.assertTrue(cm.exception.http_status == 401
                        or cm.exception.http_status == 403)

    def test_custom_requests_session(self):
        sess = requests.Session()
        sess.headers["user-agent"] = "spotipy-test"
        with_custom_session = spotipy.Spotify(
            client_credentials_manager=SpotifyClientCredentials(),
            requests_session=sess)
        self.assertTrue(
            with_custom_session.user(user="******")["uri"] == "spotify:user:akx")
        sess.close()

    def test_force_no_requests_session(self):
        with_no_session = spotipy.Spotify(
            client_credentials_manager=SpotifyClientCredentials(),
            requests_session=False)
        self.assertNotIsInstance(with_no_session._session, requests.Session)
        user = with_no_session.user(user="******")
        self.assertEqual(user["uri"], "spotify:user:akx")
예제 #2
0
class SpotifyAnalysis:
    def __init__(self):
        """Create Spotify API client."""
        self.spotify = Spotify(auth_manager=SpotifyClientCredentials(
            client_id=SPOTIPY_CLIENT_ID,
            client_secret=SPOTIPY_CLIENT_SECRET,
        ), )

        self.search_results = None
        self.sections = None
        self.bars = None
        self.segments = None
        self.pitches = None
        self.bars_to_sections = None
        self.pitches_to_bars = None
        self.number_sections = None
        self.number_bars = None

    def search(self, query: str):
        """Use Spotify's search API to retrieve an item.

        Parameters
        ----------
        query : str
            Name of track
        """
        try:
            results = self.spotify.search(q=query, type=["track"], limit=1)
            self.search_results = results["tracks"]["items"][0]
        except:
            self.search_results = {}

    def search_track(self):
        """Get track name from Search API.

        Returns
        ----------
        str
            Name of track
        """
        try:
            return self.search_results["name"]
        except:
            return ""

    def search_artist(self):
        """Get artist name from Search API.

        Returns
        ----------
        str
            Name of artist
        """
        try:
            return self.search_results["artists"][0]["name"]
        except:
            return ""

    def search_uri(self):
        """Get uri name from Search API.

        Returns
        ----------
        str
            Name of uri
        """
        try:
            return self.search_results["uri"]
        except:
            return ""

    def get_results(self, uri: str):
        """Get transformed results from Spotify audio analysis.

        Parameters
        ----------
        uri : str
            Track's Spotify ID

        Returns
        -------
        str
            JSON for d3.js
        """
        try:
            results = self.spotify.audio_analysis(uri)
        except:
            return {}

        # Parse results
        self.sections = self.get_sections(results)
        self.bars = self.get_bars(results)
        self.segments = self.get_segments(results)

        # Create mappings
        self.pitches = self.get_pitches()
        self.bars_to_sections = self.map_bars_to_sections()
        self.pitches_to_bars = self.map_pitches_to_bars()

        # Generate JSON
        return self.generate_json()

    def get_sections(self, results: str) -> pd.DataFrame:
        """Get all sections of a track.

        Parameters
        ----------
        results : str
            Response from Spotify Audio Analysis

        Returns
        -------
        pd.DataFrame
            Sections of track
        """
        sections = pd.DataFrame(results["sections"]).reset_index()
        sections.start.fillna(0, inplace=True)
        sections["end"] = sections["start"] + sections["duration"]
        sections.columns = sections.columns.str.lower() + "_sections"
        return sections

    def get_bars(self, results: str) -> pd.DataFrame:
        """Get all bars of a track.

        Parameters
        ----------
        results : str
            Response from Spotify Audio Analysis

        Returns
        -------
        pd.DataFrame
            Bars of track
        """
        bars = pd.DataFrame(results["bars"]).reset_index()
        bars["end"] = bars["start"] + bars["duration"]
        bars.columns = bars.columns.str.lower() + "_bars"
        return bars

    def get_segments(self, results: str) -> pd.DataFrame:
        """Get all segments of a track.

        Parameters
        ----------
        results : str
            Response from Spotify Audio Analysis

        Returns
        -------
        pd.DataFrame
            Segments of track
        """
        segments = pd.DataFrame(results["segments"])
        segments.start.fillna(0, inplace=True)
        segments.columns = segments.columns.str.lower() + "_segments"
        return segments

    def get_pitches(self) -> pd.DataFrame:
        """Get all pitches of a track.

        Returns
        -------
        pd.DataFrame
            Pitches of track
        """
        # Check that segments exists
        if type(self.segments) != pd.DataFrame:
            return None

        pitches = []
        for i in list(self.segments.index):
            pitches.append([self.segments.iloc[i]["start_segments"]] +
                           [self.segments.iloc[i]["duration_segments"]] +
                           self.segments.iloc[i]["pitches_segments"])

        pitches = pd.DataFrame(
            pitches,
            columns=[
                "start_pitches",
                "duration_pitches",
            ] + PITCHES_LIST,
        )

        pitches["end_pitches"] = pitches["start_pitches"] + pitches[
            "duration_pitches"]

        return pitches

    def map_bars_to_sections(self) -> pd.DataFrame:
        """Map from bar to section.

        Returns
        -------
        pd.DataFrame
            Bar index to Section index
        """
        # Check that bars and sections exist
        if type(self.bars) != pd.DataFrame or type(
                self.sections) != pd.DataFrame:
            return None

        # Make copies
        bars = self.bars.copy()
        sections = self.sections.copy()

        # Cartesian join sections and bars
        bars["join"] = 1
        sections["join"] = 1
        x_join = pd.merge(
            bars,
            sections,
            how="outer",
            left_on="join",
            right_on="join",
        )

        # Filter where START bars occur before END sections
        x_join = x_join[x_join.start_bars <= x_join.end_sections]

        # Create bars_to_sections mapping
        bars_to_sections = (
            x_join.groupby("index_bars").min()["index_sections"].reset_index())

        # Create sectioned_bar field
        bars_to_sections = bars_to_sections.merge(
            bars_to_sections.groupby("index_sections").min().reset_index(),
            left_on="index_sections",
            right_on="index_sections",
            suffixes=("", "_min"),
        )
        bars_to_sections["sectioned_bar"] = (bars_to_sections.index_bars -
                                             bars_to_sections.index_bars_min)

        # Drop unneeded column
        bars_to_sections.drop(columns=["index_bars_min"], inplace=True)

        return bars_to_sections

    def map_pitches_to_bars(self) -> pd.DataFrame:
        """Map from pitch to bar.

        Returns
        -------
        pd.DataFrame
            Pitch index to Bar index
        """
        # Check that pitches and bars exist
        if type(self.pitches) != pd.DataFrame or type(
                self.bars) != pd.DataFrame:
            return None

        # Make copies
        pitches = self.pitches.copy()
        bars = self.bars.copy()

        # Cross join pitches and bars
        pitches["join"] = 1
        bars["join"] = 1
        x_join = pd.merge(
            pitches,
            bars,
            how="outer",
            left_on="join",
            right_on="join",
        )

        # Filter where START pitches occur before END bars
        x_join = x_join[x_join.start_pitches <= x_join.end_bars]

        # Create pitches_to_bars mapping
        pitches_to_bars = pd.DataFrame(
            x_join.groupby("start_pitches").min()["end_bars"]).reset_index()

        return pitches_to_bars

    def flowers_etl(self) -> pd.DataFrame:
        """Count number of bars (petals) per section (flower).

        Returns
        -------
        pd.DataFrame
            Sections with number of bars
        """
        # Check that sections and bars exist
        if (type(self.sections) != pd.DataFrame
                or type(self.bars_to_sections) != pd.DataFrame):
            return None

        sections = self.sections.copy()
        bars_to_sections = self.bars_to_sections.copy()

        # Count number of bars in each section
        bar_count = (pd.merge(
            bars_to_sections,
            sections,
            left_on="index_sections",
            right_on="index_sections",
        ).groupby("index_sections").count().iloc[:, 0])

        # Check that bars have the same number of sections, otherwise trim sections
        difference = sections.shape[0] - len(bar_count)
        sections = sections.iloc[0:sections.shape[0] - difference]

        df_flowers = pd.DataFrame({
            "index_sections":
            list(sections.index),
            "start_sections":
            sections["start_sections"],
            "end_sections":
            sections["start_sections"] + sections["duration_sections"],
            "duration_sections":
            sections["duration_sections"],
            "loudness_sections":
            sections["loudness_sections"],
            "confidence_sections":
            sections["confidence_sections"],
            "num_bars_sections":
            bar_count.values,
            "key_sections":
            sections["key_sections"],
        })

        # Count number of sections and bars
        self.number_sections = df_flowers.shape[0]
        self.number_bars = (df_flowers[["index_sections", "num_bars_sections"
                                        ]].sum().num_bars_sections)

        return df_flowers

    def notes_etl(self) -> pd.DataFrame:
        """Map all pitches to bars and sections.

        Returns
        -------
        pd.DataFrame
            Pitches with bar and section data
        """
        # Check that pitches, pitches_to_bars, bars, bars_to_sections exist
        if (type(self.pitches) != pd.DataFrame
                or type(self.pitches_to_bars) != pd.DataFrame
                or type(self.bars) != pd.DataFrame
                or type(self.bars_to_sections) != pd.DataFrame):
            return None

        # Make copies
        pitches = self.pitches.copy()
        pitches_to_bars = self.pitches_to_bars.copy()
        bars = self.bars.copy()
        bars_to_sections = self.bars_to_sections.copy()

        # Join bars with pitches table
        df_notes = (pitches.merge(
            pitches_to_bars,
            how="inner",
            left_on="start_pitches",
            right_on="start_pitches",
        ).merge(bars, how="inner", left_on="end_bars",
                right_on="end_bars").merge(bars_to_sections,
                                           left_on="index_bars",
                                           right_on="index_bars"))

        df_notes = df_notes[[
            "index_sections",
            "index_bars",
            "start_bars",
            "duration_bars",
            "sectioned_bar",
            "start_pitches",
            "duration_pitches",
            "end_pitches",
        ] + PITCHES_LIST]

        return df_notes

    def generate_json(self):
        """Generate JSON used for d3.js

        Returns
        -------
        str
            JSON of results
        """
        df_flowers = self.flowers_etl()
        df_notes = self.notes_etl()

        df = df_flowers.merge(df_notes,
                              left_on="index_sections",
                              right_on="index_sections")

        json = []
        for index, row in df_flowers.iterrows():

            flowers = {}

            for col in list(df_flowers.columns):

                flowers[col] = row[col]

            notes = []
            for index, row in df_notes[df_notes["index_sections"] ==
                                       row["index_sections"]].iterrows():
                n = {}
                for col in list(df_notes.columns):
                    n[col] = row[col]
                notes.append(n)

            flowers["notes"] = notes

            json.append(flowers)

        return json
예제 #3
0
class AuthTestSpotipy(unittest.TestCase):
    """
    These tests require user authentication - provide client credentials using
    the following environment variables

    ::

        'SPOTIPY_CLIENT_USERNAME'
        'SPOTIPY_CLIENT_ID'
        'SPOTIPY_CLIENT_SECRET'
        'SPOTIPY_REDIRECT_URI'
    """

    playlist = "spotify:user:plamere:playlist:2oCEWyyAPbZp9xhVSxZavx"
    four_tracks = [
        "spotify:track:6RtPijgfPKROxEzTHNRiDp",
        "spotify:track:7IHOIqZUUInxjVkko181PB", "4VrWlk8IQxevMvERoX08iC",
        "http://open.spotify.com/track/3cySlItpiPiIAzU3NyHCJf"
    ]

    two_tracks = [
        "spotify:track:6RtPijgfPKROxEzTHNRiDp",
        "spotify:track:7IHOIqZUUInxjVkko181PB"
    ]

    other_tracks = [
        "spotify:track:2wySlB6vMzCbQrRnNGOYKa",
        "spotify:track:29xKs5BAHlmlX1u4gzQAbJ",
        "spotify:track:1PB7gRWcvefzu7t3LJLUlf"
    ]

    bad_id = 'BAD_ID'

    @classmethod
    def setUpClass(self):
        self.spotify = Spotify(
            client_credentials_manager=SpotifyClientCredentials())
        self.spotify.trace = False

    def test_audio_analysis(self):
        result = self.spotify.audio_analysis(self.four_tracks[0])
        assert ('beats' in result)

    def test_audio_features(self):
        results = self.spotify.audio_features(self.four_tracks)
        self.assertTrue(len(results) == len(self.four_tracks))
        for track in results:
            assert ('speechiness' in track)

    def test_audio_features_with_bad_track(self):
        bad_tracks = []
        bad_tracks = ['spotify:track:bad']
        input = self.four_tracks + bad_tracks
        results = self.spotify.audio_features(input)
        self.assertTrue(len(results) == len(input))
        for track in results[:-1]:
            if track is not None:
                assert ('speechiness' in track)
        self.assertTrue(results[-1] is None)

    def test_recommendations(self):
        results = self.spotify.recommendations(seed_tracks=self.four_tracks,
                                               min_danceability=0,
                                               max_loudness=0,
                                               target_popularity=50)
        self.assertTrue(len(results['tracks']) == 20)
예제 #4
0
class AuthTestSpotipy(unittest.TestCase):
    """
    These tests require client authentication - provide client credentials
    using the following environment variables

    ::

        'SPOTIPY_CLIENT_ID'
        'SPOTIPY_CLIENT_SECRET'
    """

    playlist = "spotify:user:plamere:playlist:2oCEWyyAPbZp9xhVSxZavx"
    four_tracks = [
        "spotify:track:6RtPijgfPKROxEzTHNRiDp",
        "spotify:track:7IHOIqZUUInxjVkko181PB", "4VrWlk8IQxevMvERoX08iC",
        "http://open.spotify.com/track/3cySlItpiPiIAzU3NyHCJf"
    ]

    two_tracks = [
        "spotify:track:6RtPijgfPKROxEzTHNRiDp",
        "spotify:track:7IHOIqZUUInxjVkko181PB"
    ]

    other_tracks = [
        "spotify:track:2wySlB6vMzCbQrRnNGOYKa",
        "spotify:track:29xKs5BAHlmlX1u4gzQAbJ",
        "spotify:track:1PB7gRWcvefzu7t3LJLUlf"
    ]

    bad_id = 'BAD_ID'

    creep_urn = 'spotify:track:3HfB5hBU0dmBt8T0iCmH42'
    creep_id = '3HfB5hBU0dmBt8T0iCmH42'
    creep_url = 'http://open.spotify.com/track/3HfB5hBU0dmBt8T0iCmH42'
    el_scorcho_urn = 'spotify:track:0Svkvt5I79wficMFgaqEQJ'
    el_scorcho_bad_urn = 'spotify:track:0Svkvt5I79wficMFgaqEQK'
    pinkerton_urn = 'spotify:album:04xe676vyiTeYNXw15o9jT'
    weezer_urn = 'spotify:artist:3jOstUTkEu2JkjvRdBA5Gu'
    pablo_honey_urn = 'spotify:album:6AZv3m27uyRxi8KyJSfUxL'
    radiohead_urn = 'spotify:artist:4Z8W4fKeB5YxbusRsdQVPb'
    angeles_haydn_urn = 'spotify:album:1vAbqAeuJVWNAe7UR00bdM'

    @classmethod
    def setUpClass(self):
        self.spotify = Spotify(
            client_credentials_manager=SpotifyClientCredentials())
        self.spotify.trace = False

    def test_audio_analysis(self):
        result = self.spotify.audio_analysis(self.four_tracks[0])
        assert ('beats' in result)

    def test_audio_features(self):
        results = self.spotify.audio_features(self.four_tracks)
        self.assertTrue(len(results) == len(self.four_tracks))
        for track in results:
            assert ('speechiness' in track)

    def test_audio_features_with_bad_track(self):
        bad_tracks = ['spotify:track:bad']
        input = self.four_tracks + bad_tracks
        results = self.spotify.audio_features(input)
        self.assertTrue(len(results) == len(input))
        for track in results[:-1]:
            if track is not None:
                assert ('speechiness' in track)
        self.assertTrue(results[-1] is None)

    def test_recommendations(self):
        results = self.spotify.recommendations(seed_tracks=self.four_tracks,
                                               min_danceability=0,
                                               max_loudness=0,
                                               target_popularity=50)
        self.assertTrue(len(results['tracks']) == 20)

    def test_artist_urn(self):
        artist = self.spotify.artist(self.radiohead_urn)
        self.assertTrue(artist['name'] == 'Radiohead')

    def test_artists(self):
        results = self.spotify.artists([self.weezer_urn, self.radiohead_urn])
        self.assertTrue('artists' in results)
        self.assertTrue(len(results['artists']) == 2)

    def test_album_urn(self):
        album = self.spotify.album(self.pinkerton_urn)
        self.assertTrue(album['name'] == 'Pinkerton')

    def test_album_tracks(self):
        results = self.spotify.album_tracks(self.pinkerton_urn)
        self.assertTrue(len(results['items']) == 10)

    def test_album_tracks_many(self):
        results = self.spotify.album_tracks(self.angeles_haydn_urn)
        tracks = results['items']
        total, received = results['total'], len(tracks)
        while received < total:
            results = self.spotify.album_tracks(self.angeles_haydn_urn,
                                                offset=received)
            tracks.extend(results['items'])
            received = len(tracks)

        self.assertEqual(received, total)

    def test_albums(self):
        results = self.spotify.albums(
            [self.pinkerton_urn, self.pablo_honey_urn])
        self.assertTrue('albums' in results)
        self.assertTrue(len(results['albums']) == 2)

    def test_track_urn(self):
        track = self.spotify.track(self.creep_urn)
        self.assertTrue(track['name'] == 'Creep')

    def test_track_id(self):
        track = self.spotify.track(self.creep_id)
        self.assertTrue(track['name'] == 'Creep')
        self.assertTrue(track['popularity'] > 0)

    def test_track_url(self):
        track = self.spotify.track(self.creep_url)
        self.assertTrue(track['name'] == 'Creep')

    def test_track_bad_urn(self):
        try:
            self.spotify.track(self.el_scorcho_bad_urn)
            self.assertTrue(False)
        except SpotifyException:
            self.assertTrue(True)

    def test_tracks(self):
        results = self.spotify.tracks([self.creep_url, self.el_scorcho_urn])
        self.assertTrue('tracks' in results)
        self.assertTrue(len(results['tracks']) == 2)

    def test_artist_top_tracks(self):
        results = self.spotify.artist_top_tracks(self.weezer_urn)
        self.assertTrue('tracks' in results)
        self.assertTrue(len(results['tracks']) == 10)

    def test_artist_related_artists(self):
        results = self.spotify.artist_related_artists(self.weezer_urn)
        self.assertTrue('artists' in results)
        self.assertTrue(len(results['artists']) == 20)
        for artist in results['artists']:
            if artist['name'] == 'Jimmy Eat World':
                found = True
        self.assertTrue(found)

    def test_artist_search(self):
        results = self.spotify.search(q='weezer', type='artist')
        self.assertTrue('artists' in results)
        self.assertTrue(len(results['artists']['items']) > 0)
        self.assertTrue(results['artists']['items'][0]['name'] == 'Weezer')

    def test_artist_search_with_market(self):
        results = self.spotify.search(q='weezer', type='artist', market='GB')
        self.assertTrue('artists' in results)
        self.assertTrue(len(results['artists']['items']) > 0)
        self.assertTrue(results['artists']['items'][0]['name'] == 'Weezer')

    def test_artist_albums(self):
        results = self.spotify.artist_albums(self.weezer_urn)
        self.assertTrue('items' in results)
        self.assertTrue(len(results['items']) > 0)

        found = False
        for album in results['items']:
            if album['name'] == 'Hurley':
                found = True

        self.assertTrue(found)

    def test_search_timeout(self):
        client_credentials_manager = SpotifyClientCredentials()
        sp = spotipy.Spotify(
            client_credentials_manager=client_credentials_manager,
            requests_timeout=.01)

        try:
            sp.search(q='my*', type='track')
            self.assertTrue(False, 'unexpected search timeout')
        except requests.exceptions.Timeout:
            self.assertTrue(True, 'expected search timeout')

    def test_album_search(self):
        results = self.spotify.search(q='weezer pinkerton', type='album')
        self.assertTrue('albums' in results)
        self.assertTrue(len(results['albums']['items']) > 0)
        self.assertTrue(
            results['albums']['items'][0]['name'].find('Pinkerton') >= 0)

    def test_track_search(self):
        results = self.spotify.search(q='el scorcho weezer', type='track')
        self.assertTrue('tracks' in results)
        self.assertTrue(len(results['tracks']['items']) > 0)
        self.assertTrue(results['tracks']['items'][0]['name'] == 'El Scorcho')

    def test_user(self):
        user = self.spotify.user(user='******')
        self.assertTrue(user['uri'] == 'spotify:user:plamere')

    def test_track_bad_id(self):
        try:
            self.spotify.track(self.bad_id)
            self.assertTrue(False)
        except SpotifyException:
            self.assertTrue(True)

    def test_unauthenticated_post_fails(self):
        with self.assertRaises(SpotifyException) as cm:
            self.spotify.user_playlist_create("spotify",
                                              "Best hits of the 90s")
        self.assertTrue(cm.exception.http_status == 401
                        or cm.exception.http_status == 403)

    def test_custom_requests_session(self):
        sess = requests.Session()
        sess.headers["user-agent"] = "spotipy-test"
        with_custom_session = spotipy.Spotify(
            client_credentials_manager=SpotifyClientCredentials(),
            requests_session=sess)
        self.assertTrue(
            with_custom_session.user(user="******")["uri"] == "spotify:user:akx")
        sess.close()

    def test_force_no_requests_session(self):
        from requests import Session
        with_no_session = spotipy.Spotify(
            client_credentials_manager=SpotifyClientCredentials(),
            requests_session=False)
        self.assertFalse(isinstance(with_no_session._session, Session))
        self.assertTrue(
            with_no_session.user(user="******")["uri"] == "spotify:user:akx")
예제 #5
0
def get_audio_analysis(sp: Spotify, track_id: str) -> Dict[str, Any]:
    """Returns audio analysis for track given its ID or URI"""
    return sp.audio_analysis(track_id)
예제 #6
0
class iSpotify(object):
    def __init__(self):
        self.token = None

    def connectSpotify(self, d_credentials, service_name):
        self.auth = oauth2.SpotifyClientCredentials(
            **d_credentials[service_name])
        self.token = self.auth.get_access_token()
        self.tk_spot = Spotify(auth=self.token)

    def regenerateTokenIfExpired(self):
        self.token = self.auth.get_access_token()
        self.tk_spot = Spotify(auth=self.token)

    def getCategories(self, country='US', locale='en_US', limit=50, offset=0):
        self.regenerateTokenIfExpired()
        self.categories = dumps(
            self.tk_spot.categories(country='US',
                                    locale='en_US',
                                    limit=20,
                                    offset=offset))

    def getCategoryNewReleases(self, cat_id, limit=50, country='US', offset=0):
        self.regenerateTokenIfExpired()
        self.category_new_releases = dumps(
            self.tk_spot.category_playlists(cat_id,
                                            limit=limit,
                                            country=country,
                                            offset=offset))

    def getUserPlayList(self, user_id, limit=50, offset=0):
        self.regenerateTokenIfExpired()
        self.user_playlists = dumps(
            self.tk_spot.user_playlists(user_id, limit=limit, offset=offset))

    def getPlaylistTracks(self,
                          owner_id,
                          playlist_id,
                          limit=50,
                          country='US',
                          offset=0):
        self.regenerateTokenIfExpired()
        self.playlist_tracks = dumps(
            self.tk_spot.user_playlist_tracks(owner_id,
                                              playlist_id,
                                              limit=limit,
                                              market=country,
                                              offset=offset))

    def getAlbums(self, album_id=[]):
        self.regenerateTokenIfExpired()
        self.albums = dumps(self.tk_spot.albums(album_id))

    def getArtists(self, artist_id=[]):
        self.regenerateTokenIfExpired()
        self.artists = dumps(self.tk_spot.artists(artist_id))

    def getAudioFeatures(self, track_id):
        self.regenerateTokenIfExpired()
        self.audio_features = dumps(self.tk_spot.audio_features(track_id))

    def getAudioAnalysis(self, track_id):
        self.regenerateTokenIfExpired()
        self.audio_analysis = dumps(self.tk_spot.audio_analysis(track_id))