mirror of
https://github.com/spotipy-dev/spotipy.git
synced 2026-06-19 09:13:53 +00:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
351d4223d0 | ||
|
|
6787aabe0f | ||
|
|
fa7049ea1d | ||
|
|
c52a29f6d2 | ||
|
|
179d3e486c | ||
|
|
9119b6a070 | ||
|
|
b5be7fba6a | ||
|
|
48dab6eb6b | ||
|
|
880b92d724 | ||
|
|
a91d9feb51 | ||
|
|
5a8b55f5e8 | ||
|
|
9dfb7177b8 | ||
|
|
6bc91ecf98 | ||
|
|
1a8d9da033 | ||
|
|
5b018cf6af | ||
|
|
743059989d | ||
|
|
4f5759dbfb | ||
|
|
3ec8a2312c | ||
|
|
4f01f7187d |
2
.github/workflows/integration_tests.yml
vendored
2
.github/workflows/integration_tests.yml
vendored
@ -4,7 +4,7 @@ on: [push, pull_request]
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-22.04
|
||||||
env:
|
env:
|
||||||
SPOTIPY_CLIENT_ID: ${{ secrets.SPOTIPY_CLIENT_ID }}
|
SPOTIPY_CLIENT_ID: ${{ secrets.SPOTIPY_CLIENT_ID }}
|
||||||
SPOTIPY_CLIENT_SECRET: ${{ secrets.SPOTIPY_CLIENT_SECRET }}
|
SPOTIPY_CLIENT_SECRET: ${{ secrets.SPOTIPY_CLIENT_SECRET }}
|
||||||
|
|||||||
3
.github/workflows/lint.yml
vendored
3
.github/workflows/lint.yml
vendored
@ -4,8 +4,7 @@ on: [push, pull_request]
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
runs-on: ubuntu-20.04
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
|
|||||||
3
.github/workflows/publish.yml
vendored
3
.github/workflows/publish.yml
vendored
@ -10,8 +10,7 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
build-n-publish:
|
build-n-publish:
|
||||||
name: Build and publish Python 🐍 distributions 📦 to PyPI and TestPyPI
|
name: Build and publish Python 🐍 distributions 📦 to PyPI and TestPyPI
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-22.04
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
|
|||||||
4
.github/workflows/pull_request.yml
vendored
4
.github/workflows/pull_request.yml
vendored
@ -6,10 +6,10 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
# Enforces the update of a changelog file on every pull request
|
# Enforces the update of a changelog file on every pull request
|
||||||
changelog:
|
changelog:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: dangoslen/changelog-enforcer@v3.6.1
|
- uses: dangoslen/changelog-enforcer@v3.6.1
|
||||||
with:
|
with:
|
||||||
changeLogPath: 'CHANGELOG.md'
|
changeLogPath: 'CHANGELOG.md'
|
||||||
skipLabel: 'skip-changelog'
|
skipLabels: 'skip-changelog'
|
||||||
|
|||||||
2
.github/workflows/unit_tests.yml
vendored
2
.github/workflows/unit_tests.yml
vendored
@ -4,7 +4,7 @@ on: [push, pull_request]
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-22.04
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
|
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
|
||||||
|
|||||||
29
CHANGELOG.md
29
CHANGELOG.md
@ -6,7 +6,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
Add your changes below.
|
Add your changes below.
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
@ -15,6 +14,32 @@ Add your changes below.
|
|||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
|
## [2.26.0] - 2026-03-03
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Created generic methods to get user saved items
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Updated `/tracks` endpoints to `/items`
|
||||||
|
- Switching IDs to URIs to use `/me/library` endpoint
|
||||||
|
- Fixed playlist limit to 50 (according to API)
|
||||||
|
- Added warnings for deprecated methods
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
## [2.25.2] - 2025-11-26
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Adds `additional_types` parameter to retrieve currently playing episode
|
||||||
|
- Add deprecation warnings to documentation
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fixed dead link in README.md
|
||||||
|
- Corrected Spotify/Spotipy typo in documentation
|
||||||
|
- Sanitize HTML error message output for OAuth flow: https://github.com/spotipy-dev/spotipy/security/advisories/GHSA-r77h-rpp9-w2xm
|
||||||
|
|
||||||
## [2.25.1] - 2025-02-27
|
## [2.25.1] - 2025-02-27
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
@ -26,6 +51,8 @@ Add your changes below.
|
|||||||
- Fixed scripts in examples directory that didn't run correctly
|
- Fixed scripts in examples directory that didn't run correctly
|
||||||
- Updated documentation for `Client.current_user_top_artists` to indicate maximum number of artists limit
|
- Updated documentation for `Client.current_user_top_artists` to indicate maximum number of artists limit
|
||||||
- Set auth cache file permissions to `600`: https://github.com/spotipy-dev/spotipy/security/advisories/GHSA-pwhh-q4h6-w599
|
- Set auth cache file permissions to `600`: https://github.com/spotipy-dev/spotipy/security/advisories/GHSA-pwhh-q4h6-w599
|
||||||
|
- Fixed `__del__` methods by preventing garbage collection for `requests.Session`
|
||||||
|
- Improved retry warning by using `logger` instead of `logging` and making sure that `retry_header` is an int
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
|||||||
@ -39,8 +39,7 @@ To give you a flavour of what we mean, here are some examples of what PRs go whe
|
|||||||
|
|
||||||
Just choose v3 if you are unsure which branch to work on.
|
Just choose v3 if you are unsure which branch to work on.
|
||||||
|
|
||||||
|
### Create virtual environment, install dependencies, run tests
|
||||||
### Create virtual environment, install dependencies, run tests:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ virtualenv --python=python3 env
|
$ virtualenv --python=python3 env
|
||||||
@ -51,7 +50,7 @@ $ source env/bin/activate
|
|||||||
|
|
||||||
### Lint
|
### Lint
|
||||||
|
|
||||||
pip install .[test]
|
pip install ".[test]"
|
||||||
|
|
||||||
To automatically fix some of the code style:
|
To automatically fix some of the code style:
|
||||||
|
|
||||||
@ -90,7 +89,6 @@ Don't forget to add a short description of your change in the [CHANGELOG](CHANGE
|
|||||||
|
|
||||||
- Commit changes
|
- Commit changes
|
||||||
- Push tag to trigger PyPI build & release workflow
|
- Push tag to trigger PyPI build & release workflow
|
||||||
- Create github release https://github.com/plamere/spotipy/releases with the changelog content
|
- Create github release <https://github.com/plamere/spotipy/releases> with the changelog content
|
||||||
for the version and a short name that describes the main addition
|
for the version and a short name that describes the main addition
|
||||||
- Verify doc uses latest https://readthedocs.org/projects/spotipy/
|
- Verify doc uses latest <https://readthedocs.org/projects/spotipy/>
|
||||||
|
|
||||||
|
|||||||
@ -36,7 +36,7 @@ pip install spotipy --upgrade
|
|||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
A full set of examples can be found in the [online documentation](http://spotipy.readthedocs.org/) and in the [Spotipy examples directory](https://github.com/plamere/spotipy/tree/master/examples).
|
A full set of examples can be found in the [online documentation](http://spotipy.readthedocs.org/) and in the [Spotipy examples directory](https://github.com/spotipy-dev/spotipy-examples).
|
||||||
|
|
||||||
To get started, [install spotipy](#installation), create a new account or log in on https://developers.spotify.com/. Go to the [dashboard](https://developer.spotify.com/dashboard), create an app and add your new ID and SECRET (ID and SECRET can be found on an app setting) to your environment:
|
To get started, [install spotipy](#installation), create a new account or log in on https://developers.spotify.com/. Go to the [dashboard](https://developer.spotify.com/dashboard), create an app and add your new ID and SECRET (ID and SECRET can be found on an app setting) to your environment:
|
||||||
|
|
||||||
|
|||||||
@ -23,7 +23,7 @@ Install or upgrade *Spotipy* with::
|
|||||||
|
|
||||||
pip install spotipy --upgrade
|
pip install spotipy --upgrade
|
||||||
|
|
||||||
You can also obtain the source code from the `Spotify GitHub repository <https://github.com/plamere/spotipy>`_.
|
You can also obtain the source code from the `Spotipy GitHub repository <https://github.com/plamere/spotipy>`_.
|
||||||
|
|
||||||
|
|
||||||
Getting Started
|
Getting Started
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
Sphinx~=8.1.3
|
Sphinx~=8.1.3
|
||||||
sphinx-rtd-theme~=3.0.2
|
sphinx-rtd-theme~=3.1.0
|
||||||
redis>=3.5.3
|
redis>=3.5.3
|
||||||
|
|||||||
8
setup.py
8
setup.py
@ -13,15 +13,15 @@ extra_reqs = {
|
|||||||
],
|
],
|
||||||
'test': [
|
'test': [
|
||||||
'autopep8>=2.3.2',
|
'autopep8>=2.3.2',
|
||||||
'flake8>=7.1.1',
|
'flake8>=7.3.0',
|
||||||
'flake8-string-format>=0.3.0',
|
'flake8-use-fstring>=1.4',
|
||||||
'isort>=5.13.2'
|
'isort>=7.0.0'
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='spotipy',
|
name='spotipy',
|
||||||
version='2.25.1',
|
version='2.26.0',
|
||||||
description='A light weight Python library for the Spotify Web API',
|
description='A light weight Python library for the Spotify Web API',
|
||||||
long_description=long_description,
|
long_description=long_description,
|
||||||
long_description_content_type="text/markdown",
|
long_description_content_type="text/markdown",
|
||||||
|
|||||||
@ -11,7 +11,7 @@ from collections import defaultdict
|
|||||||
import requests
|
import requests
|
||||||
|
|
||||||
from spotipy.exceptions import SpotifyException
|
from spotipy.exceptions import SpotifyException
|
||||||
from spotipy.util import Retry
|
from spotipy.util import REQUESTS_SESSION, Retry
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -211,11 +211,8 @@ class Spotify:
|
|||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
"""Make sure the connection (pool) gets closed"""
|
"""Make sure the connection (pool) gets closed"""
|
||||||
try:
|
if getattr(self, "_session", None) and isinstance(self._session, REQUESTS_SESSION):
|
||||||
if isinstance(self._session, requests.Session):
|
|
||||||
self._session.close()
|
self._session.close()
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def _build_session(self):
|
def _build_session(self):
|
||||||
self._session = requests.Session()
|
self._session = requests.Session()
|
||||||
@ -403,10 +400,14 @@ class Spotify:
|
|||||||
return self._get("artists/?ids=" + ",".join(tlist))
|
return self._get("artists/?ids=" + ",".join(tlist))
|
||||||
|
|
||||||
def artist_albums(
|
def artist_albums(
|
||||||
self, artist_id, album_type=None, include_groups=None, country=None, limit=20, offset=0
|
self, artist_id, album_type=None, include_groups=None, country=None, limit=10, offset=0
|
||||||
):
|
):
|
||||||
""" Get Spotify catalog information about an artist's albums
|
""" Get Spotify catalog information about an artist's albums
|
||||||
|
|
||||||
|
.. deprecated::
|
||||||
|
This method is deprecated and may be removed in a future version. Use
|
||||||
|
`artist_albums(..., include_groups='...')` instead.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
- artist_id - the artist ID, URI or URL
|
- artist_id - the artist ID, URI or URL
|
||||||
- include_groups - the types of items to return. One or more of 'album', 'single',
|
- include_groups - the types of items to return. One or more of 'album', 'single',
|
||||||
@ -444,6 +445,11 @@ class Spotify:
|
|||||||
- country - limit the response to one particular country.
|
- country - limit the response to one particular country.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
warnings.warn(
|
||||||
|
"You're using `artist_top_tracks(...)`, "
|
||||||
|
"which is marked as deprecated by Spotify.",
|
||||||
|
DeprecationWarning,
|
||||||
|
)
|
||||||
trid = self._get_id("artist", artist_id)
|
trid = self._get_id("artist", artist_id)
|
||||||
return self._get("artists/" + trid + "/top-tracks", country=country)
|
return self._get("artists/" + trid + "/top-tracks", country=country)
|
||||||
|
|
||||||
@ -452,6 +458,9 @@ class Spotify:
|
|||||||
identified artist. Similarity is based on analysis of the
|
identified artist. Similarity is based on analysis of the
|
||||||
Spotify community's listening history.
|
Spotify community's listening history.
|
||||||
|
|
||||||
|
.. deprecated::
|
||||||
|
This endpoint has been removed by Spotify and is no longer available.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
- artist_id - the artist ID, URI or URL
|
- artist_id - the artist ID, URI or URL
|
||||||
"""
|
"""
|
||||||
@ -643,6 +652,11 @@ class Spotify:
|
|||||||
Parameters:
|
Parameters:
|
||||||
- user - the id of the usr
|
- user - the id of the usr
|
||||||
"""
|
"""
|
||||||
|
warnings.warn(
|
||||||
|
"You're using `user(...)`, "
|
||||||
|
"which is marked as deprecated by Spotify.",
|
||||||
|
DeprecationWarning,
|
||||||
|
)
|
||||||
return self._get("users/" + user)
|
return self._get("users/" + user)
|
||||||
|
|
||||||
def current_user_playlists(self, limit=50, offset=0):
|
def current_user_playlists(self, limit=50, offset=0):
|
||||||
@ -676,13 +690,17 @@ class Spotify:
|
|||||||
self,
|
self,
|
||||||
playlist_id,
|
playlist_id,
|
||||||
fields=None,
|
fields=None,
|
||||||
limit=100,
|
limit=50,
|
||||||
offset=0,
|
offset=0,
|
||||||
market=None,
|
market=None,
|
||||||
additional_types=("track",)
|
additional_types=("track",)
|
||||||
):
|
):
|
||||||
""" Get full details of the tracks of a playlist.
|
""" Get full details of the tracks of a playlist.
|
||||||
|
|
||||||
|
.. deprecated::
|
||||||
|
This method is deprecated and may be removed in a future version. Use
|
||||||
|
`playlist_items(playlist_id, ..., additional_types=('track',))` instead.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
- playlist_id - the playlist ID, URI or URL
|
- playlist_id - the playlist ID, URI or URL
|
||||||
- fields - which fields to return
|
- fields - which fields to return
|
||||||
@ -704,7 +722,7 @@ class Spotify:
|
|||||||
self,
|
self,
|
||||||
playlist_id,
|
playlist_id,
|
||||||
fields=None,
|
fields=None,
|
||||||
limit=100,
|
limit=50,
|
||||||
offset=0,
|
offset=0,
|
||||||
market=None,
|
market=None,
|
||||||
additional_types=("track", "episode")
|
additional_types=("track", "episode")
|
||||||
@ -722,7 +740,7 @@ class Spotify:
|
|||||||
"""
|
"""
|
||||||
plid = self._get_id("playlist", playlist_id)
|
plid = self._get_id("playlist", playlist_id)
|
||||||
return self._get(
|
return self._get(
|
||||||
f"playlists/{plid}/tracks",
|
f"playlists/{plid}/items",
|
||||||
limit=limit,
|
limit=limit,
|
||||||
offset=offset,
|
offset=offset,
|
||||||
fields=fields,
|
fields=fields,
|
||||||
@ -755,18 +773,22 @@ class Spotify:
|
|||||||
)
|
)
|
||||||
|
|
||||||
def user_playlist(self, user, playlist_id=None, fields=None, market=None):
|
def user_playlist(self, user, playlist_id=None, fields=None, market=None):
|
||||||
warnings.warn(
|
|
||||||
"You should use `playlist(playlist_id)` instead",
|
|
||||||
DeprecationWarning,
|
|
||||||
)
|
|
||||||
|
|
||||||
""" Gets a single playlist of a user
|
""" Gets a single playlist of a user
|
||||||
|
|
||||||
|
.. deprecated::
|
||||||
|
This method is deprecated and may be removed in a future version. Use
|
||||||
|
`playlist(playlist_id)` instead.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
- user - the id of the user
|
- user - the id of the user
|
||||||
- playlist_id - the id of the playlist
|
- playlist_id - the id of the playlist
|
||||||
- fields - which fields to return
|
- fields - which fields to return
|
||||||
"""
|
"""
|
||||||
|
warnings.warn(
|
||||||
|
"You should use `playlist(playlist_id)` instead",
|
||||||
|
DeprecationWarning,
|
||||||
|
)
|
||||||
|
|
||||||
if playlist_id is None:
|
if playlist_id is None:
|
||||||
return self._get(f"users/{user}/starred")
|
return self._get(f"users/{user}/starred")
|
||||||
return self.playlist(playlist_id, fields=fields, market=market)
|
return self.playlist(playlist_id, fields=fields, market=market)
|
||||||
@ -780,13 +802,12 @@ class Spotify:
|
|||||||
offset=0,
|
offset=0,
|
||||||
market=None,
|
market=None,
|
||||||
):
|
):
|
||||||
warnings.warn(
|
|
||||||
"You should use `playlist_tracks(playlist_id)` instead",
|
|
||||||
DeprecationWarning,
|
|
||||||
)
|
|
||||||
|
|
||||||
""" Get full details of the tracks of a playlist owned by a user.
|
""" Get full details of the tracks of a playlist owned by a user.
|
||||||
|
|
||||||
|
.. deprecated::
|
||||||
|
This method is deprecated and may be removed in a future version. Use
|
||||||
|
`playlist_tracks(playlist_id)` instead.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
- user - the id of the user
|
- user - the id of the user
|
||||||
- playlist_id - the id of the playlist
|
- playlist_id - the id of the playlist
|
||||||
@ -795,6 +816,10 @@ class Spotify:
|
|||||||
- offset - the index of the first track to return
|
- offset - the index of the first track to return
|
||||||
- market - an ISO 3166-1 alpha-2 country code.
|
- market - an ISO 3166-1 alpha-2 country code.
|
||||||
"""
|
"""
|
||||||
|
warnings.warn(
|
||||||
|
"You should use `playlist_tracks(playlist_id)` instead",
|
||||||
|
DeprecationWarning,
|
||||||
|
)
|
||||||
return self.playlist_tracks(
|
return self.playlist_tracks(
|
||||||
playlist_id,
|
playlist_id,
|
||||||
limit=limit,
|
limit=limit,
|
||||||
@ -811,6 +836,12 @@ class Spotify:
|
|||||||
- limit - the number of items to return
|
- limit - the number of items to return
|
||||||
- offset - the index of the first item to return
|
- offset - the index of the first item to return
|
||||||
"""
|
"""
|
||||||
|
warnings.warn(
|
||||||
|
"You're using `user_playlists(...)`, "
|
||||||
|
"which is marked as deprecated by Spotify. Use "
|
||||||
|
"current_user_playlists(...) instead.",
|
||||||
|
DeprecationWarning,
|
||||||
|
)
|
||||||
return self._get(
|
return self._get(
|
||||||
f"users/{user}/playlists", limit=limit, offset=offset
|
f"users/{user}/playlists", limit=limit, offset=offset
|
||||||
)
|
)
|
||||||
@ -825,6 +856,12 @@ class Spotify:
|
|||||||
- collaborative - is the created playlist collaborative
|
- collaborative - is the created playlist collaborative
|
||||||
- description - the description of the playlist
|
- description - the description of the playlist
|
||||||
"""
|
"""
|
||||||
|
warnings.warn(
|
||||||
|
"You're using `user_playlist_create(...)`, "
|
||||||
|
"which is marked as deprecated by Spotify. Use "
|
||||||
|
"current_user_playlist_create(...) instead.",
|
||||||
|
DeprecationWarning,
|
||||||
|
)
|
||||||
data = {
|
data = {
|
||||||
"name": name,
|
"name": name,
|
||||||
"public": public,
|
"public": public,
|
||||||
@ -834,6 +871,24 @@ class Spotify:
|
|||||||
|
|
||||||
return self._post(f"users/{user}/playlists", payload=data)
|
return self._post(f"users/{user}/playlists", payload=data)
|
||||||
|
|
||||||
|
def current_user_playlist_create(self, name, public=True, collaborative=False, description=""):
|
||||||
|
""" Creates a playlist for the current user
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
- name - the name of the playlist
|
||||||
|
- public - is the created playlist public
|
||||||
|
- collaborative - is the created playlist collaborative
|
||||||
|
- description - the description of the playlist
|
||||||
|
"""
|
||||||
|
data = {
|
||||||
|
"name": name,
|
||||||
|
"public": public,
|
||||||
|
"collaborative": collaborative,
|
||||||
|
"description": description
|
||||||
|
}
|
||||||
|
|
||||||
|
return self._post("me/playlists", payload=data)
|
||||||
|
|
||||||
def user_playlist_change_details(
|
def user_playlist_change_details(
|
||||||
self,
|
self,
|
||||||
user,
|
user,
|
||||||
@ -847,6 +902,10 @@ class Spotify:
|
|||||||
|
|
||||||
Changes a playlist's name and/or public/private state
|
Changes a playlist's name and/or public/private state
|
||||||
|
|
||||||
|
.. deprecated::
|
||||||
|
This method is deprecated and may be removed in a future version. Use
|
||||||
|
`playlist_change_details(playlist_id, ...)` instead.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
- user - the id of the user
|
- user - the id of the user
|
||||||
- playlist_id - the id of the playlist
|
- playlist_id - the id of the playlist
|
||||||
@ -868,6 +927,10 @@ class Spotify:
|
|||||||
|
|
||||||
Unfollows (deletes) a playlist for a user
|
Unfollows (deletes) a playlist for a user
|
||||||
|
|
||||||
|
.. deprecated::
|
||||||
|
This method is deprecated and may be removed in a future version. Use
|
||||||
|
`current_user_unfollow_playlist(playlist_id)` instead.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
- user - the id of the user
|
- user - the id of the user
|
||||||
- name - the name of the playlist
|
- name - the name of the playlist
|
||||||
@ -885,6 +948,10 @@ class Spotify:
|
|||||||
|
|
||||||
Adds tracks to a playlist
|
Adds tracks to a playlist
|
||||||
|
|
||||||
|
.. deprecated::
|
||||||
|
This method is deprecated and may be removed in a future version. Use
|
||||||
|
`playlist_add_items(playlist_id, tracks)` instead.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
- user - the id of the user
|
- user - the id of the user
|
||||||
- playlist_id - the id of the playlist
|
- playlist_id - the id of the playlist
|
||||||
@ -906,6 +973,10 @@ class Spotify:
|
|||||||
|
|
||||||
Adds episodes to a playlist
|
Adds episodes to a playlist
|
||||||
|
|
||||||
|
.. deprecated::
|
||||||
|
This method is deprecated and may be removed in a future version. Use
|
||||||
|
`playlist_add_items(playlist_id, episodes)` instead.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
- user - the id of the user
|
- user - the id of the user
|
||||||
- playlist_id - the id of the playlist
|
- playlist_id - the id of the playlist
|
||||||
@ -925,6 +996,10 @@ class Spotify:
|
|||||||
|
|
||||||
Replace all tracks in a playlist for a user
|
Replace all tracks in a playlist for a user
|
||||||
|
|
||||||
|
.. deprecated::
|
||||||
|
This method is deprecated and may be removed in a future version. Use
|
||||||
|
`playlist_replace_items(playlist_id, tracks)` instead.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
- user - the id of the user
|
- user - the id of the user
|
||||||
- playlist_id - the id of the playlist
|
- playlist_id - the id of the playlist
|
||||||
@ -949,6 +1024,10 @@ class Spotify:
|
|||||||
|
|
||||||
Reorder tracks in a playlist from a user
|
Reorder tracks in a playlist from a user
|
||||||
|
|
||||||
|
.. deprecated::
|
||||||
|
This method is deprecated and may be removed in a future version. Use
|
||||||
|
`playlist_reorder_items(playlist_id, ...)` instead.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
- user - the id of the user
|
- user - the id of the user
|
||||||
- playlist_id - the id of the playlist
|
- playlist_id - the id of the playlist
|
||||||
@ -974,6 +1053,10 @@ class Spotify:
|
|||||||
|
|
||||||
Removes all occurrences of the given tracks from the given playlist
|
Removes all occurrences of the given tracks from the given playlist
|
||||||
|
|
||||||
|
.. deprecated::
|
||||||
|
This method is deprecated and may be removed in a future version. Use
|
||||||
|
`playlist_remove_all_occurrences_of_items(playlist_id, tracks)` instead.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
- user - the id of the user
|
- user - the id of the user
|
||||||
- playlist_id - the id of the playlist
|
- playlist_id - the id of the playlist
|
||||||
@ -994,7 +1077,10 @@ class Spotify:
|
|||||||
):
|
):
|
||||||
""" This function is no longer in use, please use the recommended function in the warning!
|
""" This function is no longer in use, please use the recommended function in the warning!
|
||||||
|
|
||||||
Removes all occurrences of the given tracks from the given playlist
|
Removes specific occurrences of the given tracks from the given playlist
|
||||||
|
|
||||||
|
.. deprecated::
|
||||||
|
This endpoint has been removed by Spotify and is no longer available.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
- user - the id of the user
|
- user - the id of the user
|
||||||
@ -1007,8 +1093,8 @@ class Spotify:
|
|||||||
- snapshot_id - optional id of the playlist snapshot
|
- snapshot_id - optional id of the playlist snapshot
|
||||||
"""
|
"""
|
||||||
warnings.warn(
|
warnings.warn(
|
||||||
"You should use `playlist_remove_specific_occurrences_of_items"
|
"You're using `user_playlist_remove_specific_occurrences_of_tracks(...)`, "
|
||||||
"(playlist_id, tracks)` instead",
|
"which is marked as deprecated by Spotify.",
|
||||||
DeprecationWarning,
|
DeprecationWarning,
|
||||||
)
|
)
|
||||||
plid = self._get_id("playlist", playlist_id)
|
plid = self._get_id("playlist", playlist_id)
|
||||||
@ -1032,6 +1118,10 @@ class Spotify:
|
|||||||
|
|
||||||
Add the current authenticated user as a follower of a playlist.
|
Add the current authenticated user as a follower of a playlist.
|
||||||
|
|
||||||
|
.. deprecated::
|
||||||
|
This method is deprecated and may be removed in a future version. Use
|
||||||
|
`current_user_follow_playlist(playlist_id)` instead.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
- playlist_owner_id - the user id of the playlist owner
|
- playlist_owner_id - the user id of the playlist owner
|
||||||
- playlist_id - the id of the playlist
|
- playlist_id - the id of the playlist
|
||||||
@ -1049,6 +1139,10 @@ class Spotify:
|
|||||||
|
|
||||||
Check to see if the given users are following the given playlist
|
Check to see if the given users are following the given playlist
|
||||||
|
|
||||||
|
.. deprecated::
|
||||||
|
This method is deprecated and may be removed in a future version. Use
|
||||||
|
`playlist_is_following(playlist_id, user_ids)` instead.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
- playlist_owner_id - the user id of the playlist owner
|
- playlist_owner_id - the user id of the playlist owner
|
||||||
- playlist_id - the id of the playlist
|
- playlist_id - the id of the playlist
|
||||||
@ -1117,7 +1211,7 @@ class Spotify:
|
|||||||
plid = self._get_id("playlist", playlist_id)
|
plid = self._get_id("playlist", playlist_id)
|
||||||
ftracks = [self._get_uri("track", tid) for tid in items]
|
ftracks = [self._get_uri("track", tid) for tid in items]
|
||||||
return self._post(
|
return self._post(
|
||||||
f"playlists/{plid}/tracks",
|
f"playlists/{plid}/items",
|
||||||
payload=ftracks,
|
payload=ftracks,
|
||||||
position=position,
|
position=position,
|
||||||
)
|
)
|
||||||
@ -1133,7 +1227,7 @@ class Spotify:
|
|||||||
ftracks = [self._get_uri("track", tid) for tid in items]
|
ftracks = [self._get_uri("track", tid) for tid in items]
|
||||||
payload = {"uris": ftracks}
|
payload = {"uris": ftracks}
|
||||||
return self._put(
|
return self._put(
|
||||||
f"playlists/{plid}/tracks", payload=payload
|
f"playlists/{plid}/items", payload=payload
|
||||||
)
|
)
|
||||||
|
|
||||||
def playlist_reorder_items(
|
def playlist_reorder_items(
|
||||||
@ -1164,7 +1258,7 @@ class Spotify:
|
|||||||
if snapshot_id:
|
if snapshot_id:
|
||||||
payload["snapshot_id"] = snapshot_id
|
payload["snapshot_id"] = snapshot_id
|
||||||
return self._put(
|
return self._put(
|
||||||
f"playlists/{plid}/tracks", payload=payload
|
f"playlists/{plid}/items", payload=payload
|
||||||
)
|
)
|
||||||
|
|
||||||
def playlist_remove_all_occurrences_of_items(
|
def playlist_remove_all_occurrences_of_items(
|
||||||
@ -1181,11 +1275,11 @@ class Spotify:
|
|||||||
|
|
||||||
plid = self._get_id("playlist", playlist_id)
|
plid = self._get_id("playlist", playlist_id)
|
||||||
ftracks = [self._get_uri("track", tid) for tid in items]
|
ftracks = [self._get_uri("track", tid) for tid in items]
|
||||||
payload = {"tracks": [{"uri": track} for track in ftracks]}
|
payload = {"items": [{"uri": track} for track in ftracks]}
|
||||||
if snapshot_id:
|
if snapshot_id:
|
||||||
payload["snapshot_id"] = snapshot_id
|
payload["snapshot_id"] = snapshot_id
|
||||||
return self._delete(
|
return self._delete(
|
||||||
f"playlists/{plid}/tracks", payload=payload
|
f"playlists/{plid}/items", payload=payload
|
||||||
)
|
)
|
||||||
|
|
||||||
def playlist_remove_specific_occurrences_of_items(
|
def playlist_remove_specific_occurrences_of_items(
|
||||||
@ -1212,14 +1306,14 @@ class Spotify:
|
|||||||
"positions": tr["positions"],
|
"positions": tr["positions"],
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
payload = {"tracks": ftracks}
|
payload = {"items": ftracks}
|
||||||
if snapshot_id:
|
if snapshot_id:
|
||||||
payload["snapshot_id"] = snapshot_id
|
payload["snapshot_id"] = snapshot_id
|
||||||
return self._delete(
|
return self._delete(
|
||||||
f"playlists/{plid}/tracks", payload=payload
|
f"playlists/{plid}/items", payload=payload
|
||||||
)
|
)
|
||||||
|
|
||||||
def current_user_follow_playlist(self, playlist_id, public=True):
|
def current_user_follow_playlist(self, playlist_id):
|
||||||
"""
|
"""
|
||||||
Add the current authenticated user as a follower of a playlist.
|
Add the current authenticated user as a follower of a playlist.
|
||||||
|
|
||||||
@ -1227,10 +1321,7 @@ class Spotify:
|
|||||||
- playlist_id - the id of the playlist
|
- playlist_id - the id of the playlist
|
||||||
|
|
||||||
"""
|
"""
|
||||||
return self._put(
|
return self._put("me/library", uris=self._get_uri("playlist", playlist_id))
|
||||||
f"playlists/{playlist_id}/followers",
|
|
||||||
payload={"public": public}
|
|
||||||
)
|
|
||||||
|
|
||||||
def playlist_is_following(
|
def playlist_is_following(
|
||||||
self, playlist_id, user_ids
|
self, playlist_id, user_ids
|
||||||
@ -1244,9 +1335,27 @@ class Spotify:
|
|||||||
if they follow the playlist. Maximum: 5 ids.
|
if they follow the playlist. Maximum: 5 ids.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
warnings.warn(
|
||||||
|
"You're using `playlist_is_following(..., user_ids=...)`, "
|
||||||
|
"which is marked as deprecated by Spotify. Use ",
|
||||||
|
"current_user_follow_playlist(...) instead.",
|
||||||
|
DeprecationWarning,
|
||||||
|
)
|
||||||
|
|
||||||
endpoint = f"playlists/{playlist_id}/followers/contains?ids={','.join(user_ids)}"
|
endpoint = f"playlists/{playlist_id}/followers/contains?ids={','.join(user_ids)}"
|
||||||
return self._get(endpoint)
|
return self._get(endpoint)
|
||||||
|
|
||||||
|
def current_user_saved_items(self, uris):
|
||||||
|
"""
|
||||||
|
Check if the current user is following the given artists, users, or playlists
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
- uris - a list of URIs to check for following status. Maximum: 40 ids.
|
||||||
|
|
||||||
|
"""
|
||||||
|
valid_uris = [uri for uri in uris if self._is_uri(uri)]
|
||||||
|
return self._get("me/library/contains", uris=",".join(valid_uris))
|
||||||
|
|
||||||
def me(self):
|
def me(self):
|
||||||
""" Get detailed profile information about the current user.
|
""" Get detailed profile information about the current user.
|
||||||
An alias for the 'current_user' method.
|
An alias for the 'current_user' method.
|
||||||
@ -1259,10 +1368,20 @@ class Spotify:
|
|||||||
"""
|
"""
|
||||||
return self.me()
|
return self.me()
|
||||||
|
|
||||||
def current_user_playing_track(self):
|
def current_user_playing_track(self, market=None, additional_types=("track",)):
|
||||||
""" Get information about the current users currently playing track.
|
""" Get information about the current users currently playing track.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
- market - An ISO 3166-1 alpha-2 country code or the
|
||||||
|
string from_token.
|
||||||
|
- additional_types - list of item types to return.
|
||||||
|
valid types are: track and episode
|
||||||
"""
|
"""
|
||||||
return self._get("me/player/currently-playing")
|
return self._get(
|
||||||
|
"me/player/currently-playing",
|
||||||
|
market=market,
|
||||||
|
additional_types=",".join(additional_types)
|
||||||
|
)
|
||||||
|
|
||||||
def current_user_saved_albums(self, limit=20, offset=0, market=None):
|
def current_user_saved_albums(self, limit=20, offset=0, market=None):
|
||||||
""" Gets a list of the albums saved in the current authorized user's
|
""" Gets a list of the albums saved in the current authorized user's
|
||||||
@ -1283,8 +1402,8 @@ class Spotify:
|
|||||||
- albums - a list of album URIs, URLs or IDs
|
- albums - a list of album URIs, URLs or IDs
|
||||||
"""
|
"""
|
||||||
|
|
||||||
alist = [self._get_id("album", a) for a in albums]
|
alist = [self._get_uri("album", a) for a in albums]
|
||||||
return self._put("me/albums?ids=" + ",".join(alist))
|
return self._put("me/library", uris=",".join(alist))
|
||||||
|
|
||||||
def current_user_saved_albums_delete(self, albums=[]):
|
def current_user_saved_albums_delete(self, albums=[]):
|
||||||
""" Remove one or more albums from the current user's
|
""" Remove one or more albums from the current user's
|
||||||
@ -1293,8 +1412,8 @@ class Spotify:
|
|||||||
Parameters:
|
Parameters:
|
||||||
- albums - a list of album URIs, URLs or IDs
|
- albums - a list of album URIs, URLs or IDs
|
||||||
"""
|
"""
|
||||||
alist = [self._get_id("album", a) for a in albums]
|
alist = [self._get_uri("album", a) for a in albums]
|
||||||
return self._delete("me/albums/?ids=" + ",".join(alist))
|
return self._delete("me/library", uris=",".join(alist))
|
||||||
|
|
||||||
def current_user_saved_albums_contains(self, albums=[]):
|
def current_user_saved_albums_contains(self, albums=[]):
|
||||||
""" Check if one or more albums is already saved in
|
""" Check if one or more albums is already saved in
|
||||||
@ -1303,8 +1422,8 @@ class Spotify:
|
|||||||
Parameters:
|
Parameters:
|
||||||
- albums - a list of album URIs, URLs or IDs
|
- albums - a list of album URIs, URLs or IDs
|
||||||
"""
|
"""
|
||||||
alist = [self._get_id("album", a) for a in albums]
|
alist = [self._get_uri("album", a) for a in albums]
|
||||||
return self._get("me/albums/contains?ids=" + ",".join(alist))
|
return self._get("me/library/contains", uris=",".join(alist))
|
||||||
|
|
||||||
def current_user_saved_tracks(self, limit=20, offset=0, market=None):
|
def current_user_saved_tracks(self, limit=20, offset=0, market=None):
|
||||||
""" Gets a list of the tracks saved in the current authorized user's
|
""" Gets a list of the tracks saved in the current authorized user's
|
||||||
@ -1327,8 +1446,8 @@ class Spotify:
|
|||||||
"""
|
"""
|
||||||
tlist = []
|
tlist = []
|
||||||
if tracks is not None:
|
if tracks is not None:
|
||||||
tlist = [self._get_id("track", t) for t in tracks]
|
tlist = [self._get_uri("track", t) for t in tracks]
|
||||||
return self._put("me/tracks/?ids=" + ",".join(tlist))
|
return self._put("me/library", uris=",".join(tlist))
|
||||||
|
|
||||||
def current_user_saved_tracks_delete(self, tracks=None):
|
def current_user_saved_tracks_delete(self, tracks=None):
|
||||||
""" Remove one or more tracks from the current user's
|
""" Remove one or more tracks from the current user's
|
||||||
@ -1339,8 +1458,8 @@ class Spotify:
|
|||||||
"""
|
"""
|
||||||
tlist = []
|
tlist = []
|
||||||
if tracks is not None:
|
if tracks is not None:
|
||||||
tlist = [self._get_id("track", t) for t in tracks]
|
tlist = [self._get_uri("track", t) for t in tracks]
|
||||||
return self._delete("me/tracks/?ids=" + ",".join(tlist))
|
return self._delete("me/library", uris=",".join(tlist))
|
||||||
|
|
||||||
def current_user_saved_tracks_contains(self, tracks=None):
|
def current_user_saved_tracks_contains(self, tracks=None):
|
||||||
""" Check if one or more tracks is already saved in
|
""" Check if one or more tracks is already saved in
|
||||||
@ -1351,8 +1470,8 @@ class Spotify:
|
|||||||
"""
|
"""
|
||||||
tlist = []
|
tlist = []
|
||||||
if tracks is not None:
|
if tracks is not None:
|
||||||
tlist = [self._get_id("track", t) for t in tracks]
|
tlist = [self._get_uri("track", t) for t in tracks]
|
||||||
return self._get("me/tracks/contains?ids=" + ",".join(tlist))
|
return self._get("me/library/contains", uris=",".join(tlist))
|
||||||
|
|
||||||
def current_user_saved_episodes(self, limit=20, offset=0, market=None):
|
def current_user_saved_episodes(self, limit=20, offset=0, market=None):
|
||||||
""" Gets a list of the episodes saved in the current authorized user's
|
""" Gets a list of the episodes saved in the current authorized user's
|
||||||
@ -1375,8 +1494,8 @@ class Spotify:
|
|||||||
"""
|
"""
|
||||||
elist = []
|
elist = []
|
||||||
if episodes is not None:
|
if episodes is not None:
|
||||||
elist = [self._get_id("episode", e) for e in episodes]
|
elist = [self._get_uri("episode", e) for e in episodes]
|
||||||
return self._put("me/episodes/?ids=" + ",".join(elist))
|
return self._put("me/library", uris=",".join(elist))
|
||||||
|
|
||||||
def current_user_saved_episodes_delete(self, episodes=None):
|
def current_user_saved_episodes_delete(self, episodes=None):
|
||||||
""" Remove one or more episodes from the current user's
|
""" Remove one or more episodes from the current user's
|
||||||
@ -1387,8 +1506,8 @@ class Spotify:
|
|||||||
"""
|
"""
|
||||||
elist = []
|
elist = []
|
||||||
if episodes is not None:
|
if episodes is not None:
|
||||||
elist = [self._get_id("episode", e) for e in episodes]
|
elist = [self._get_uri("episode", e) for e in episodes]
|
||||||
return self._delete("me/episodes/?ids=" + ",".join(elist))
|
return self._delete("me/library", uris=",".join(elist))
|
||||||
|
|
||||||
def current_user_saved_episodes_contains(self, episodes=None):
|
def current_user_saved_episodes_contains(self, episodes=None):
|
||||||
""" Check if one or more episodes is already saved in
|
""" Check if one or more episodes is already saved in
|
||||||
@ -1420,8 +1539,8 @@ class Spotify:
|
|||||||
Parameters:
|
Parameters:
|
||||||
- shows - a list of show URIs, URLs or IDs
|
- shows - a list of show URIs, URLs or IDs
|
||||||
"""
|
"""
|
||||||
slist = [self._get_id("show", s) for s in shows]
|
slist = [self._get_uri("show", s) for s in shows]
|
||||||
return self._put("me/shows?ids=" + ",".join(slist))
|
return self._put("me/library", uris=",".join(slist))
|
||||||
|
|
||||||
def current_user_saved_shows_delete(self, shows=[]):
|
def current_user_saved_shows_delete(self, shows=[]):
|
||||||
""" Remove one or more shows from the current user's
|
""" Remove one or more shows from the current user's
|
||||||
@ -1430,8 +1549,8 @@ class Spotify:
|
|||||||
Parameters:
|
Parameters:
|
||||||
- shows - a list of show URIs, URLs or IDs
|
- shows - a list of show URIs, URLs or IDs
|
||||||
"""
|
"""
|
||||||
slist = [self._get_id("show", s) for s in shows]
|
slist = [self._get_uri("show", s) for s in shows]
|
||||||
return self._delete("me/shows/?ids=" + ",".join(slist))
|
return self._delete("me/library", uris=",".join(slist))
|
||||||
|
|
||||||
def current_user_saved_shows_contains(self, shows=[]):
|
def current_user_saved_shows_contains(self, shows=[]):
|
||||||
""" Check if one or more shows is already saved in
|
""" Check if one or more shows is already saved in
|
||||||
@ -1440,8 +1559,8 @@ class Spotify:
|
|||||||
Parameters:
|
Parameters:
|
||||||
- shows - a list of show URIs, URLs or IDs
|
- shows - a list of show URIs, URLs or IDs
|
||||||
"""
|
"""
|
||||||
slist = [self._get_id("show", s) for s in shows]
|
slist = [self._get_uri("show", s) for s in shows]
|
||||||
return self._get("me/shows/contains?ids=" + ",".join(slist))
|
return self._get("me/library/contains", uris=",".join(slist))
|
||||||
|
|
||||||
def current_user_followed_artists(self, limit=20, after=None):
|
def current_user_followed_artists(self, limit=20, after=None):
|
||||||
""" Gets a list of the artists followed by the current authorized user
|
""" Gets a list of the artists followed by the current authorized user
|
||||||
@ -1464,11 +1583,11 @@ class Spotify:
|
|||||||
Parameters:
|
Parameters:
|
||||||
- ids - a list of artist URIs, URLs or IDs
|
- ids - a list of artist URIs, URLs or IDs
|
||||||
"""
|
"""
|
||||||
idlist = []
|
ulist = []
|
||||||
if ids is not None:
|
if ids is not None:
|
||||||
idlist = [self._get_id("artist", i) for i in ids]
|
ulist = [self._get_uri("artist", i) for i in ids]
|
||||||
return self._get(
|
return self._get(
|
||||||
"me/following/contains", ids=",".join(idlist), type="artist"
|
"me/library/contains", uris=",".join(ulist)
|
||||||
)
|
)
|
||||||
|
|
||||||
def current_user_following_users(self, ids=None):
|
def current_user_following_users(self, ids=None):
|
||||||
@ -1479,11 +1598,11 @@ class Spotify:
|
|||||||
Parameters:
|
Parameters:
|
||||||
- ids - a list of user URIs, URLs or IDs
|
- ids - a list of user URIs, URLs or IDs
|
||||||
"""
|
"""
|
||||||
idlist = []
|
ulist = []
|
||||||
if ids is not None:
|
if ids is not None:
|
||||||
idlist = [self._get_id("user", i) for i in ids]
|
ulist = [self._get_uri("user", i) for i in ids]
|
||||||
return self._get(
|
return self._get(
|
||||||
"me/following/contains", ids=",".join(idlist), type="user"
|
"me/library/contains", uris=",".join(ulist)
|
||||||
)
|
)
|
||||||
|
|
||||||
def current_user_top_artists(
|
def current_user_top_artists(
|
||||||
@ -1540,34 +1659,41 @@ class Spotify:
|
|||||||
Parameters:
|
Parameters:
|
||||||
- ids - a list of artist IDs
|
- ids - a list of artist IDs
|
||||||
"""
|
"""
|
||||||
return self._put("me/following?type=artist&ids=" + ",".join(ids))
|
alist = [self._get_uri("artist", a) for a in ids]
|
||||||
|
return self._put("me/library", uris=",".join(alist))
|
||||||
|
|
||||||
def user_follow_users(self, ids=[]):
|
def user_follow_users(self, ids=[]):
|
||||||
""" Follow one or more users
|
""" Follow one or more users
|
||||||
Parameters:
|
Parameters:
|
||||||
- ids - a list of user IDs
|
- ids - a list of user IDs
|
||||||
"""
|
"""
|
||||||
return self._put("me/following?type=user&ids=" + ",".join(ids))
|
ulist = [self._get_uri("user", a) for a in ids]
|
||||||
|
return self._put("me/library", uris=",".join(ulist))
|
||||||
|
|
||||||
def user_unfollow_artists(self, ids=[]):
|
def user_unfollow_artists(self, ids=[]):
|
||||||
""" Unfollow one or more artists
|
""" Unfollow one or more artists
|
||||||
Parameters:
|
Parameters:
|
||||||
- ids - a list of artist IDs
|
- ids - a list of artist IDs
|
||||||
"""
|
"""
|
||||||
return self._delete("me/following?type=artist&ids=" + ",".join(ids))
|
alist = [self._get_uri("artist", a) for a in ids]
|
||||||
|
return self._delete("me/library", uris=",".join(alist))
|
||||||
|
|
||||||
def user_unfollow_users(self, ids=[]):
|
def user_unfollow_users(self, ids=[]):
|
||||||
""" Unfollow one or more users
|
""" Unfollow one or more users
|
||||||
Parameters:
|
Parameters:
|
||||||
- ids - a list of user IDs
|
- ids - a list of user IDs
|
||||||
"""
|
"""
|
||||||
return self._delete("me/following?type=user&ids=" + ",".join(ids))
|
ulist = [self._get_uri("user", a) for a in ids]
|
||||||
|
return self._delete("me/library", uris=",".join(ulist))
|
||||||
|
|
||||||
def featured_playlists(
|
def featured_playlists(
|
||||||
self, locale=None, country=None, timestamp=None, limit=20, offset=0
|
self, locale=None, country=None, timestamp=None, limit=20, offset=0
|
||||||
):
|
):
|
||||||
""" Get a list of Spotify featured playlists
|
""" Get a list of Spotify featured playlists
|
||||||
|
|
||||||
|
.. deprecated::
|
||||||
|
This endpoint has been removed by Spotify and is no longer available.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
- locale - The desired language, consisting of a lowercase ISO
|
- locale - The desired language, consisting of a lowercase ISO
|
||||||
639-1 alpha-2 language code and an uppercase ISO 3166-1 alpha-2
|
639-1 alpha-2 language code and an uppercase ISO 3166-1 alpha-2
|
||||||
@ -1614,6 +1740,11 @@ class Spotify:
|
|||||||
(the first object). Use with limit to get the next set of
|
(the first object). Use with limit to get the next set of
|
||||||
items.
|
items.
|
||||||
"""
|
"""
|
||||||
|
warnings.warn(
|
||||||
|
"You're using `new_release(...)`, "
|
||||||
|
"which is marked as deprecated by Spotify.",
|
||||||
|
DeprecationWarning,
|
||||||
|
)
|
||||||
return self._get(
|
return self._get(
|
||||||
"browse/new-releases", country=country, limit=limit, offset=offset
|
"browse/new-releases", country=country, limit=limit, offset=offset
|
||||||
)
|
)
|
||||||
@ -1629,6 +1760,11 @@ class Spotify:
|
|||||||
language code and an ISO 3166-1 alpha-2 country code, joined
|
language code and an ISO 3166-1 alpha-2 country code, joined
|
||||||
by an underscore.
|
by an underscore.
|
||||||
"""
|
"""
|
||||||
|
warnings.warn(
|
||||||
|
"You're using `category(...)`, "
|
||||||
|
"which is marked as deprecated by Spotify.",
|
||||||
|
DeprecationWarning,
|
||||||
|
)
|
||||||
return self._get(
|
return self._get(
|
||||||
"browse/categories/" + category_id,
|
"browse/categories/" + category_id,
|
||||||
country=country,
|
country=country,
|
||||||
@ -1651,6 +1787,11 @@ class Spotify:
|
|||||||
(the first object). Use with limit to get the next set of
|
(the first object). Use with limit to get the next set of
|
||||||
items.
|
items.
|
||||||
"""
|
"""
|
||||||
|
warnings.warn(
|
||||||
|
"You're using `categories(...)`, "
|
||||||
|
"which is marked as deprecated by Spotify.",
|
||||||
|
DeprecationWarning,
|
||||||
|
)
|
||||||
return self._get(
|
return self._get(
|
||||||
"browse/categories",
|
"browse/categories",
|
||||||
country=country,
|
country=country,
|
||||||
@ -1664,6 +1805,9 @@ class Spotify:
|
|||||||
):
|
):
|
||||||
""" Get a list of playlists for a specific Spotify category
|
""" Get a list of playlists for a specific Spotify category
|
||||||
|
|
||||||
|
.. deprecated::
|
||||||
|
This endpoint has been removed by Spotify and is no longer available.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
- category_id - The Spotify category ID for the category.
|
- category_id - The Spotify category ID for the category.
|
||||||
|
|
||||||
@ -1701,6 +1845,9 @@ class Spotify:
|
|||||||
(at least one of `seed_artists`, `seed_tracks` and `seed_genres`
|
(at least one of `seed_artists`, `seed_tracks` and `seed_genres`
|
||||||
are needed)
|
are needed)
|
||||||
|
|
||||||
|
.. deprecated::
|
||||||
|
This endpoint has been removed by Spotify and is no longer available.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
- seed_artists - a list of artist IDs, URIs or URLs
|
- seed_artists - a list of artist IDs, URIs or URLs
|
||||||
- seed_tracks - a list of track IDs, URIs or URLs
|
- seed_tracks - a list of track IDs, URIs or URLs
|
||||||
@ -1761,17 +1908,24 @@ class Spotify:
|
|||||||
return self._get("recommendations", **params)
|
return self._get("recommendations", **params)
|
||||||
|
|
||||||
def recommendation_genre_seeds(self):
|
def recommendation_genre_seeds(self):
|
||||||
|
""" Get a list of genres available for the recommendations function.
|
||||||
|
|
||||||
|
.. deprecated::
|
||||||
|
This endpoint has been removed by Spotify and is no longer available.
|
||||||
|
"""
|
||||||
warnings.warn(
|
warnings.warn(
|
||||||
"You're using `recommendation_genre_seeds(...)`, "
|
"You're using `recommendation_genre_seeds(...)`, "
|
||||||
"which is marked as deprecated by Spotify.",
|
"which is marked as deprecated by Spotify.",
|
||||||
DeprecationWarning,
|
DeprecationWarning,
|
||||||
)
|
)
|
||||||
""" Get a list of genres available for the recommendations function.
|
|
||||||
"""
|
|
||||||
return self._get("recommendations/available-genre-seeds")
|
return self._get("recommendations/available-genre-seeds")
|
||||||
|
|
||||||
def audio_analysis(self, track_id):
|
def audio_analysis(self, track_id):
|
||||||
""" Get audio analysis for a track based upon its Spotify ID
|
""" Get audio analysis for a track based upon its Spotify ID
|
||||||
|
|
||||||
|
.. deprecated::
|
||||||
|
This endpoint has been removed by Spotify and is no longer available.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
- track_id - a track URI, URL or ID
|
- track_id - a track URI, URL or ID
|
||||||
"""
|
"""
|
||||||
@ -1785,6 +1939,10 @@ class Spotify:
|
|||||||
|
|
||||||
def audio_features(self, tracks=[]):
|
def audio_features(self, tracks=[]):
|
||||||
""" Get audio features for one or multiple tracks based upon their Spotify IDs
|
""" Get audio features for one or multiple tracks based upon their Spotify IDs
|
||||||
|
|
||||||
|
.. deprecated::
|
||||||
|
This endpoint has been removed by Spotify and is no longer available.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
- tracks - a list of track URIs, URLs or IDs, maximum: 100 ids
|
- tracks - a list of track URIs, URLs or IDs, maximum: 100 ids
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -8,6 +8,7 @@ __all__ = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
import base64
|
import base64
|
||||||
|
import html
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
@ -21,7 +22,8 @@ import requests
|
|||||||
|
|
||||||
from spotipy.cache_handler import CacheFileHandler, CacheHandler
|
from spotipy.cache_handler import CacheFileHandler, CacheHandler
|
||||||
from spotipy.exceptions import SpotifyOauthError, SpotifyStateError
|
from spotipy.exceptions import SpotifyOauthError, SpotifyStateError
|
||||||
from spotipy.util import CLIENT_CREDS_ENV_VARS, get_host_port, normalize_scope
|
from spotipy.util import (CLIENT_CREDS_ENV_VARS, REQUESTS_SESSION,
|
||||||
|
get_host_port, normalize_scope)
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -122,7 +124,7 @@ class SpotifyAuthBase:
|
|||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
"""Make sure the connection (pool) gets closed"""
|
"""Make sure the connection (pool) gets closed"""
|
||||||
if isinstance(self._session, requests.Session):
|
if getattr(self, "_session", None) and isinstance(self._session, REQUESTS_SESSION):
|
||||||
self._session.close()
|
self._session.close()
|
||||||
|
|
||||||
|
|
||||||
@ -185,7 +187,7 @@ class SpotifyClientCredentials(SpotifyAuthBase):
|
|||||||
Else fetches a new token and returns it
|
Else fetches a new token and returns it
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
- as_dict - a boolean indicating if returning the access token
|
- as_dict: (deprecated) a boolean indicating if returning the access token
|
||||||
as a token_info dictionary, otherwise it will be returned
|
as a token_info dictionary, otherwise it will be returned
|
||||||
as a string.
|
as a string.
|
||||||
"""
|
"""
|
||||||
@ -483,8 +485,8 @@ class SpotifyOAuth(SpotifyAuthBase):
|
|||||||
""" Gets the access token for the app given the code
|
""" Gets the access token for the app given the code
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
- code - the response code
|
- code: the response code
|
||||||
- as_dict - a boolean indicating if returning the access token
|
- as_dict: (deprecated) a boolean indicating if returning the access token
|
||||||
as a token_info dictionary, otherwise it will be returned
|
as a token_info dictionary, otherwise it will be returned
|
||||||
as a string.
|
as a string.
|
||||||
"""
|
"""
|
||||||
@ -577,6 +579,11 @@ class SpotifyOAuth(SpotifyAuthBase):
|
|||||||
return token_info
|
return token_info
|
||||||
|
|
||||||
def get_cached_token(self):
|
def get_cached_token(self):
|
||||||
|
""" Gets the cached token for the app
|
||||||
|
|
||||||
|
.. deprecated::
|
||||||
|
This method is deprecated and may be removed in a future version.
|
||||||
|
"""
|
||||||
warnings.warn("Calling get_cached_token directly on the SpotifyOAuth object will be " +
|
warnings.warn("Calling get_cached_token directly on the SpotifyOAuth object will be " +
|
||||||
"deprecated. Instead, please specify a CacheFileHandler instance as " +
|
"deprecated. Instead, please specify a CacheFileHandler instance as " +
|
||||||
"the cache_handler in SpotifyOAuth and use the CacheFileHandler's " +
|
"the cache_handler in SpotifyOAuth and use the CacheFileHandler's " +
|
||||||
@ -1203,6 +1210,11 @@ class SpotifyImplicitGrant(SpotifyAuthBase):
|
|||||||
return token_info
|
return token_info
|
||||||
|
|
||||||
def get_cached_token(self):
|
def get_cached_token(self):
|
||||||
|
""" Gets the cached token for the app
|
||||||
|
|
||||||
|
.. deprecated::
|
||||||
|
This method is deprecated and may be removed in a future version.
|
||||||
|
"""
|
||||||
warnings.warn("Calling get_cached_token directly on the SpotifyImplicitGrant " +
|
warnings.warn("Calling get_cached_token directly on the SpotifyImplicitGrant " +
|
||||||
"object will be deprecated. Instead, please specify a " +
|
"object will be deprecated. Instead, please specify a " +
|
||||||
"CacheFileHandler instance as the cache_handler in SpotifyOAuth " +
|
"CacheFileHandler instance as the cache_handler in SpotifyOAuth " +
|
||||||
@ -1241,7 +1253,7 @@ class RequestHandler(BaseHTTPRequestHandler):
|
|||||||
if self.server.auth_code:
|
if self.server.auth_code:
|
||||||
status = "successful"
|
status = "successful"
|
||||||
elif self.server.error:
|
elif self.server.error:
|
||||||
status = f"failed ({self.server.error})"
|
status = f"failed ({html.escape(str(self.server.error))})"
|
||||||
else:
|
else:
|
||||||
self._write("<html><body><h1>Invalid request</h1></body></html>")
|
self._write("<html><body><h1>Invalid request</h1></body></html>")
|
||||||
return
|
return
|
||||||
|
|||||||
@ -9,11 +9,12 @@ import os
|
|||||||
import warnings
|
import warnings
|
||||||
from types import TracebackType
|
from types import TracebackType
|
||||||
|
|
||||||
|
import requests
|
||||||
import urllib3
|
import urllib3
|
||||||
|
|
||||||
import spotipy
|
import spotipy
|
||||||
|
|
||||||
LOGGER = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
CLIENT_CREDS_ENV_VARS = {
|
CLIENT_CREDS_ENV_VARS = {
|
||||||
"client_id": "SPOTIPY_CLIENT_ID",
|
"client_id": "SPOTIPY_CLIENT_ID",
|
||||||
@ -22,6 +23,9 @@ CLIENT_CREDS_ENV_VARS = {
|
|||||||
"redirect_uri": "SPOTIPY_REDIRECT_URI",
|
"redirect_uri": "SPOTIPY_REDIRECT_URI",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# workaround for garbage collection
|
||||||
|
REQUESTS_SESSION = requests.Session
|
||||||
|
|
||||||
|
|
||||||
def prompt_for_user_token(
|
def prompt_for_user_token(
|
||||||
username=None,
|
username=None,
|
||||||
@ -33,16 +37,12 @@ def prompt_for_user_token(
|
|||||||
oauth_manager=None,
|
oauth_manager=None,
|
||||||
show_dialog=False
|
show_dialog=False
|
||||||
):
|
):
|
||||||
warnings.warn(
|
|
||||||
"'prompt_for_user_token' is deprecated."
|
|
||||||
"Use the following instead: "
|
|
||||||
" auth_manager=SpotifyOAuth(scope=scope)"
|
|
||||||
" spotipy.Spotify(auth_manager=auth_manager)",
|
|
||||||
DeprecationWarning
|
|
||||||
)
|
|
||||||
""" Prompt the user to login if necessary and returns a user token
|
""" Prompt the user to login if necessary and returns a user token
|
||||||
suitable for use with the spotipy.Spotify constructor.
|
suitable for use with the spotipy.Spotify constructor.
|
||||||
|
|
||||||
|
.. deprecated::
|
||||||
|
This method is deprecated and may be removed in a future version.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
- username - the Spotify username. (optional)
|
- username - the Spotify username. (optional)
|
||||||
- scope - the desired scope of the request. (optional)
|
- scope - the desired scope of the request. (optional)
|
||||||
@ -53,6 +53,14 @@ def prompt_for_user_token(
|
|||||||
- oauth_manager - OAuth manager object. (optional)
|
- oauth_manager - OAuth manager object. (optional)
|
||||||
- show_dialog - If True, a login prompt always shows or defaults to False. (optional)
|
- show_dialog - If True, a login prompt always shows or defaults to False. (optional)
|
||||||
"""
|
"""
|
||||||
|
warnings.warn(
|
||||||
|
"'prompt_for_user_token' is deprecated."
|
||||||
|
"Use the following instead: "
|
||||||
|
" auth_manager=SpotifyOAuth(scope=scope)"
|
||||||
|
" spotipy.Spotify(auth_manager=auth_manager)",
|
||||||
|
DeprecationWarning
|
||||||
|
)
|
||||||
|
|
||||||
if not oauth_manager:
|
if not oauth_manager:
|
||||||
if not client_id:
|
if not client_id:
|
||||||
client_id = os.getenv("SPOTIPY_CLIENT_ID")
|
client_id = os.getenv("SPOTIPY_CLIENT_ID")
|
||||||
@ -64,7 +72,7 @@ def prompt_for_user_token(
|
|||||||
redirect_uri = os.getenv("SPOTIPY_REDIRECT_URI")
|
redirect_uri = os.getenv("SPOTIPY_REDIRECT_URI")
|
||||||
|
|
||||||
if not client_id:
|
if not client_id:
|
||||||
LOGGER.warning(
|
logger.warning(
|
||||||
"""
|
"""
|
||||||
You need to set your Spotify API credentials.
|
You need to set your Spotify API credentials.
|
||||||
You can do this by setting environment variables like so:
|
You can do this by setting environment variables like so:
|
||||||
@ -166,8 +174,9 @@ class Retry(urllib3.Retry):
|
|||||||
if response:
|
if response:
|
||||||
retry_header = response.headers.get("Retry-After")
|
retry_header = response.headers.get("Retry-After")
|
||||||
if self.is_retry(method, response.status, bool(retry_header)):
|
if self.is_retry(method, response.status, bool(retry_header)):
|
||||||
logging.warning("Your application has reached a rate/request limit. "
|
retry_header = retry_header or 0
|
||||||
f"Retry will occur after: {retry_header}")
|
logger.warning("Your application has reached a rate/request limit. "
|
||||||
|
f"Retry will occur after: {retry_header} s")
|
||||||
return super().increment(method,
|
return super().increment(method,
|
||||||
url,
|
url,
|
||||||
response=response,
|
response=response,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user