yutipy 1.5.2__tar.gz → 1.6.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of yutipy might be problematic. Click here for more details.
- {yutipy-1.5.2 → yutipy-1.6.1}/PKG-INFO +1 -1
- {yutipy-1.5.2 → yutipy-1.6.1}/docs/api_reference.rst +6 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/docs/usage_examples.rst +89 -2
- yutipy-1.6.1/tests/test_spotify.py +130 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/yutipy/cli/search.py +1 -1
- {yutipy-1.5.2 → yutipy-1.6.1}/yutipy/deezer.py +2 -2
- {yutipy-1.5.2 → yutipy-1.6.1}/yutipy/exceptions.py +18 -34
- {yutipy-1.5.2 → yutipy-1.6.1}/yutipy/itunes.py +2 -2
- {yutipy-1.5.2 → yutipy-1.6.1}/yutipy/kkbox.py +2 -2
- {yutipy-1.5.2 → yutipy-1.6.1}/yutipy/musicyt.py +2 -2
- yutipy-1.6.1/yutipy/spotify.py +981 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/yutipy/utils/__init__.py +1 -1
- {yutipy-1.5.2 → yutipy-1.6.1}/yutipy/yutipy_music.py +2 -2
- {yutipy-1.5.2 → yutipy-1.6.1}/yutipy.egg-info/PKG-INFO +1 -1
- {yutipy-1.5.2 → yutipy-1.6.1}/yutipy.egg-info/SOURCES.txt +2 -2
- yutipy-1.5.2/tests/test_spotify.py +0 -53
- yutipy-1.5.2/yutipy/spotify.py +0 -506
- {yutipy-1.5.2 → yutipy-1.6.1}/.gitattributes +0 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/.github/FUNDING.yml +0 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/.github/workflows/pytest-unit-testing.yml +0 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/.github/workflows/release.yml +0 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/.gitignore +0 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/.readthedocs.yaml +0 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/LICENSE +0 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/MANIFEST.in +0 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/README.md +0 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/docs/Makefile +0 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/docs/_static/yutipy_header.png +0 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/docs/_static/yutipy_logo.png +0 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/docs/available_platforms.rst +0 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/docs/cli.rst +0 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/docs/conf.py +0 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/docs/faq.rst +0 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/docs/index.rst +0 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/docs/installation.rst +0 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/docs/make.bat +0 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/docs/requirements.txt +0 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/pyproject.toml +0 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/requirements-dev.txt +0 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/requirements.txt +0 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/setup.cfg +0 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/tests/__init__.py +0 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/tests/test_deezer.py +0 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/tests/test_itunes.py +0 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/tests/test_kkbox.py +0 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/tests/test_models.py +0 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/tests/test_musicyt.py +0 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/tests/test_utils.py +0 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/tests/test_yutipy_music.py +0 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/yutipy/__init__.py +0 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/yutipy/cli/__init__.py +0 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/yutipy/cli/config.py +0 -0
- {yutipy-1.5.2/yutipy/utils → yutipy-1.6.1/yutipy}/logger.py +0 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/yutipy/models.py +0 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/yutipy/utils/helpers.py +0 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/yutipy.egg-info/dependency_links.txt +0 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/yutipy.egg-info/entry_points.txt +0 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/yutipy.egg-info/requires.txt +0 -0
- {yutipy-1.5.2 → yutipy-1.6.1}/yutipy.egg-info/top_level.txt +0 -0
|
@@ -73,7 +73,11 @@ Alternatively, you can manually provide these values when creating an object of
|
|
|
73
73
|
Spotify
|
|
74
74
|
-------
|
|
75
75
|
|
|
76
|
-
|
|
76
|
+
Client Credentials Grant Type
|
|
77
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
78
|
+
|
|
79
|
+
To use the Spotify API with Client Credentials flow, you need to set the ``SPOTIFY_CLIENT_ID`` and ``SPOTIFY_CLIENT_SECRET`` for Spotify.
|
|
80
|
+
You can do this by creating a ``.env`` file in the root directory of your project with the following content:
|
|
77
81
|
|
|
78
82
|
.. admonition:: .env
|
|
79
83
|
|
|
@@ -82,7 +86,7 @@ To use the Spotify API, you need to set the ``SPOTIFY_CLIENT_ID`` and ``SPOTIFY_
|
|
|
82
86
|
SPOTIFY_CLIENT_ID=<your_spotify_client_id>
|
|
83
87
|
SPOTIFY_CLIENT_SECRET=<your_spotify_client_secret>
|
|
84
88
|
|
|
85
|
-
Alternatively, you can manually provide these values when creating an object of the
|
|
89
|
+
Alternatively, you can manually provide these values when creating an object of the ``Spotify`` class:
|
|
86
90
|
|
|
87
91
|
.. code-block:: python
|
|
88
92
|
|
|
@@ -109,6 +113,89 @@ OR, if you have the ":abbr:`ISRC (International Standard Recording Code)`" or ":
|
|
|
109
113
|
result = spotify.search_advanced("Artist Name", "Song Title", isrc="USAT29900609", upc="00602517078194")
|
|
110
114
|
print(result)
|
|
111
115
|
|
|
116
|
+
Authorization Code Flow
|
|
117
|
+
~~~~~~~~~~~~~~~~~~~~~~~
|
|
118
|
+
|
|
119
|
+
To use the Spotify API with the Authorization Code Flow, you need to set the ``SPOTIFY_CLIENT_ID``, ``SPOTIFY_CLIENT_SECRET``, and ``SPOTIFY_REDIRECT_URI``.
|
|
120
|
+
You can do this by creating a ``.env`` file in the root directory of your project with the following content:
|
|
121
|
+
|
|
122
|
+
.. admonition:: .env
|
|
123
|
+
|
|
124
|
+
.. code-block:: bash
|
|
125
|
+
|
|
126
|
+
SPOTIFY_CLIENT_ID=<your_spotify_client_id>
|
|
127
|
+
SPOTIFY_CLIENT_SECRET=<your_spotify_client_secret>
|
|
128
|
+
SPOTIFY_REDIRECT_URI=<your_redirect_uri>
|
|
129
|
+
|
|
130
|
+
Alternatively, you can manually provide these values when creating an object of the ``SpotifyAuth`` class.
|
|
131
|
+
|
|
132
|
+
Here’s an example of how to use the ``SpotifyAuth`` class in a web application:
|
|
133
|
+
|
|
134
|
+
.. code-block:: python
|
|
135
|
+
|
|
136
|
+
from flask import Flask, request, session, redirect, url_for
|
|
137
|
+
from yutipy.spotify import SpotifyAuth, SpotifyAuthException
|
|
138
|
+
|
|
139
|
+
app = Flask(__name__)
|
|
140
|
+
app.secret_key = "your_secret_key" # Replace with a secure secret key
|
|
141
|
+
|
|
142
|
+
# Initialize SpotifyAuth with your credentials
|
|
143
|
+
SPOTIFY_CLIENT_ID = "your_spotify_client_id"
|
|
144
|
+
SPOTIFY_CLIENT_SECRET = "your_spotify_client_secret"
|
|
145
|
+
SPOTIFY_REDIRECT_URI = "http://localhost:5000/callback"
|
|
146
|
+
|
|
147
|
+
spotify_auth = SpotifyAuth(
|
|
148
|
+
client_id=SPOTIFY_CLIENT_ID,
|
|
149
|
+
client_secret=SPOTIFY_CLIENT_SECRET,
|
|
150
|
+
redirect_uri=SPOTIFY_REDIRECT_URI,
|
|
151
|
+
scopes=["user-read-email", "user-read-private"],
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
@app.route("/")
|
|
155
|
+
def home():
|
|
156
|
+
"""Home route to start the authorization process."""
|
|
157
|
+
state = spotify_auth.generate_state()
|
|
158
|
+
session["state"] = state # Save the state in the session for validation
|
|
159
|
+
auth_url = spotify_auth.get_authorization_url(state=state)
|
|
160
|
+
return redirect(auth_url)
|
|
161
|
+
|
|
162
|
+
@app.route("/callback")
|
|
163
|
+
def callback():
|
|
164
|
+
"""Callback route to handle Spotify's response after user authorization."""
|
|
165
|
+
code = request.args.get("code")
|
|
166
|
+
state = request.args.get("state")
|
|
167
|
+
expected_state = session.get("state")
|
|
168
|
+
|
|
169
|
+
if not code or not state:
|
|
170
|
+
return "Authorization failed: Missing code or state.", 400
|
|
171
|
+
|
|
172
|
+
try:
|
|
173
|
+
spotify_auth.callback_handler(code, state, expected_state)
|
|
174
|
+
user_profile = spotify_auth.get_user_profile()
|
|
175
|
+
if user_profile:
|
|
176
|
+
return f"Successfully authenticated! Welcome, {user_profile['display_name']}."
|
|
177
|
+
else:
|
|
178
|
+
return "Authentication successful, but failed to fetch user profile."
|
|
179
|
+
except SpotifyAuthException as e:
|
|
180
|
+
return f"Authorization failed: {e}", 400
|
|
181
|
+
|
|
182
|
+
@app.route("/logout")
|
|
183
|
+
def logout():
|
|
184
|
+
"""Logout route to close the session."""
|
|
185
|
+
spotify_auth.close_session()
|
|
186
|
+
session.clear()
|
|
187
|
+
return "Logged out successfully."
|
|
188
|
+
|
|
189
|
+
if __name__ == "__main__":
|
|
190
|
+
app.run(debug=True)
|
|
191
|
+
|
|
192
|
+
.. note::
|
|
193
|
+
|
|
194
|
+
- Avoid hard-coding your credentials in the code. Instead, define them in a ``.env`` file, which will be automatically read by the library.
|
|
195
|
+
- Ensure that the redirect URI matches the one configured in your Spotify Developer Dashboard.
|
|
196
|
+
- This example uses Flask, but it can be adapted to other web frameworks as needed.
|
|
197
|
+
|
|
198
|
+
|
|
112
199
|
YouTube Music
|
|
113
200
|
-------------
|
|
114
201
|
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
|
|
3
|
+
from yutipy.exceptions import SpotifyException
|
|
4
|
+
from yutipy.models import MusicInfo
|
|
5
|
+
from yutipy.spotify import Spotify, SpotifyAuth
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@pytest.fixture(scope="module")
|
|
9
|
+
def spotify():
|
|
10
|
+
try:
|
|
11
|
+
return Spotify()
|
|
12
|
+
except SpotifyException:
|
|
13
|
+
pytest.skip("Spotify credentials not found")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@pytest.fixture(scope="module")
|
|
17
|
+
def spotify_auth():
|
|
18
|
+
return SpotifyAuth(
|
|
19
|
+
client_id="test_client_id",
|
|
20
|
+
client_secret="test_client_secret",
|
|
21
|
+
redirect_uri="http://localhost/callback",
|
|
22
|
+
scopes=["user-read-email", "user-read-private"],
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def test_search(spotify):
|
|
27
|
+
artist = "Adele"
|
|
28
|
+
song = "Hello"
|
|
29
|
+
result = spotify.search(artist, song)
|
|
30
|
+
assert result is not None
|
|
31
|
+
assert isinstance(result, MusicInfo)
|
|
32
|
+
assert result.title == song
|
|
33
|
+
assert artist in result.artists
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def test_search_advanced_with_isrc(spotify):
|
|
37
|
+
artist = "Adele"
|
|
38
|
+
song = "Hello"
|
|
39
|
+
isrc = "GBBKS1500214"
|
|
40
|
+
result = spotify.search_advanced(artist, song, isrc=isrc)
|
|
41
|
+
assert result is not None
|
|
42
|
+
assert result.isrc == isrc
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def test_search_advanced_with_upc(spotify):
|
|
46
|
+
artist = "Miles Davis"
|
|
47
|
+
album = "Kind Of Blue (Legacy Edition)"
|
|
48
|
+
upc = "888880696069"
|
|
49
|
+
result = spotify.search_advanced(artist, album, upc=upc)
|
|
50
|
+
print(result)
|
|
51
|
+
assert result is not None
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def test_get_artists_ids(spotify):
|
|
55
|
+
artist = "Adele"
|
|
56
|
+
artist_ids = spotify._get_artists_ids(artist)
|
|
57
|
+
assert isinstance(artist_ids, list)
|
|
58
|
+
assert len(artist_ids) > 0
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def test_close_session(spotify):
|
|
62
|
+
spotify.close_session()
|
|
63
|
+
assert spotify.is_session_closed
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def test_get_authorization_url(spotify_auth):
|
|
67
|
+
state = spotify_auth.generate_state()
|
|
68
|
+
auth_url = spotify_auth.get_authorization_url(state=state)
|
|
69
|
+
assert "https://accounts.spotify.com/authorize" in auth_url
|
|
70
|
+
assert "response_type=code" in auth_url
|
|
71
|
+
assert f"client_id={spotify_auth.client_id}" in auth_url
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def test_get_user_profile(spotify_auth, monkeypatch):
|
|
75
|
+
def mock_authorization_header():
|
|
76
|
+
return {"Authorization": "Bearer test_token"}
|
|
77
|
+
|
|
78
|
+
def mock_get(*args, **kwargs):
|
|
79
|
+
class MockResponse:
|
|
80
|
+
status_code = 200
|
|
81
|
+
|
|
82
|
+
@staticmethod
|
|
83
|
+
def raise_for_status():
|
|
84
|
+
pass # Simulates a successful response with no exceptions raised
|
|
85
|
+
|
|
86
|
+
@staticmethod
|
|
87
|
+
def json():
|
|
88
|
+
return {
|
|
89
|
+
"display_name": "Test User",
|
|
90
|
+
"images": [
|
|
91
|
+
{
|
|
92
|
+
"url": "https://example.com/image.jpg",
|
|
93
|
+
"height": 300,
|
|
94
|
+
"width": 300,
|
|
95
|
+
}
|
|
96
|
+
],
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return MockResponse()
|
|
100
|
+
|
|
101
|
+
monkeypatch.setattr(
|
|
102
|
+
spotify_auth, "_SpotifyAuth__authorization_header", mock_authorization_header
|
|
103
|
+
)
|
|
104
|
+
monkeypatch.setattr(spotify_auth._SpotifyAuth__session, "get", mock_get)
|
|
105
|
+
|
|
106
|
+
user_profile = spotify_auth.get_user_profile()
|
|
107
|
+
assert user_profile is not None
|
|
108
|
+
assert user_profile["display_name"] == "Test User"
|
|
109
|
+
assert len(user_profile["images"]) == 1
|
|
110
|
+
assert user_profile["images"][0]["url"] == "https://example.com/image.jpg"
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def test_callback_handler(spotify_auth, monkeypatch):
|
|
114
|
+
def mock_get_access_token(*args, **kwargs):
|
|
115
|
+
return {
|
|
116
|
+
"access_token": "test_access_token",
|
|
117
|
+
"refresh_token": "test_refresh_token",
|
|
118
|
+
"expires_in": 3600,
|
|
119
|
+
"requested_at": 1234567890,
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
monkeypatch.setattr(
|
|
123
|
+
spotify_auth, "_SpotifyAuth__get_access_token", mock_get_access_token
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
spotify_auth.callback_handler("test_code", "test_state", "test_state")
|
|
127
|
+
assert spotify_auth._SpotifyAuth__access_token == "test_access_token"
|
|
128
|
+
assert spotify_auth._SpotifyAuth__refresh_token == "test_refresh_token"
|
|
129
|
+
assert spotify_auth._SpotifyAuth__token_expires_in == 3600
|
|
130
|
+
assert spotify_auth._SpotifyAuth__token_requested_at == 1234567890
|
|
@@ -14,7 +14,7 @@ from yutipy.itunes import Itunes
|
|
|
14
14
|
from yutipy.kkbox import KKBox
|
|
15
15
|
from yutipy.musicyt import MusicYT
|
|
16
16
|
from yutipy.spotify import Spotify
|
|
17
|
-
from yutipy.
|
|
17
|
+
from yutipy.logger import disable_logging, enable_logging
|
|
18
18
|
from yutipy.yutipy_music import YutipyMusic
|
|
19
19
|
|
|
20
20
|
|
|
@@ -13,7 +13,7 @@ from yutipy.exceptions import (
|
|
|
13
13
|
)
|
|
14
14
|
from yutipy.models import MusicInfo
|
|
15
15
|
from yutipy.utils.helpers import are_strings_similar, is_valid_string
|
|
16
|
-
from yutipy.
|
|
16
|
+
from yutipy.logger import logger
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
class Deezer:
|
|
@@ -323,7 +323,7 @@ class Deezer:
|
|
|
323
323
|
|
|
324
324
|
if __name__ == "__main__":
|
|
325
325
|
import logging
|
|
326
|
-
from yutipy.
|
|
326
|
+
from yutipy.logger import enable_logging
|
|
327
327
|
|
|
328
328
|
enable_logging(level=logging.DEBUG)
|
|
329
329
|
deezer = Deezer()
|
|
@@ -11,60 +11,44 @@ __all__ = [
|
|
|
11
11
|
class YutipyException(Exception):
|
|
12
12
|
"""Base class for exceptions in the Yutipy package."""
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
|
|
15
|
+
# Generic Exceptions
|
|
16
|
+
class AuthenticationException(YutipyException):
|
|
17
|
+
"""Exception raised for authentication errors."""
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class InvalidResponseException(YutipyException):
|
|
21
|
+
"""Exception raised for invalid responses from APIs."""
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class InvalidValueException(YutipyException):
|
|
25
|
+
"""Exception raised for invalid values."""
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class NetworkException(YutipyException):
|
|
29
|
+
"""Exception raised for network-related errors."""
|
|
15
30
|
|
|
16
31
|
|
|
17
32
|
# Service Exceptions
|
|
18
33
|
class DeezerException(YutipyException):
|
|
19
34
|
"""Exception raised for errors related to the Deezer API."""
|
|
20
35
|
|
|
21
|
-
pass
|
|
22
|
-
|
|
23
36
|
|
|
24
37
|
class ItunesException(YutipyException):
|
|
25
38
|
"""Exception raised for errors related to the iTunes API."""
|
|
26
39
|
|
|
27
|
-
pass
|
|
28
|
-
|
|
29
40
|
|
|
30
41
|
class KKBoxException(YutipyException):
|
|
31
42
|
"""Exception raised for erros related to the KKBOX Open API."""
|
|
32
43
|
|
|
33
|
-
pass
|
|
34
|
-
|
|
35
44
|
|
|
36
45
|
class MusicYTException(YutipyException):
|
|
37
46
|
"""Exception raised for errors related to the YouTube Music API."""
|
|
38
47
|
|
|
39
|
-
pass
|
|
40
|
-
|
|
41
48
|
|
|
42
49
|
class SpotifyException(YutipyException):
|
|
43
50
|
"""Exception raised for errors related to the Spotify API."""
|
|
44
51
|
|
|
45
|
-
pass
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
# Generic Exceptions
|
|
49
|
-
class AuthenticationException(YutipyException):
|
|
50
|
-
"""Exception raised for authentication errors."""
|
|
51
|
-
|
|
52
|
-
pass
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
class InvalidResponseException(YutipyException):
|
|
56
|
-
"""Exception raised for invalid responses from APIs."""
|
|
57
|
-
|
|
58
|
-
pass
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
class InvalidValueException(YutipyException):
|
|
62
|
-
"""Exception raised for invalid values."""
|
|
63
|
-
|
|
64
|
-
pass
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
class NetworkException(YutipyException):
|
|
68
|
-
"""Exception raised for network-related errors."""
|
|
69
52
|
|
|
70
|
-
|
|
53
|
+
class SpotifyAuthException(AuthenticationException):
|
|
54
|
+
"""Exception raised for Spotify authorization code grant type / flow"""
|
|
@@ -18,7 +18,7 @@ from yutipy.utils.helpers import (
|
|
|
18
18
|
guess_album_type,
|
|
19
19
|
is_valid_string,
|
|
20
20
|
)
|
|
21
|
-
from yutipy.
|
|
21
|
+
from yutipy.logger import logger
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
class Itunes:
|
|
@@ -228,7 +228,7 @@ class Itunes:
|
|
|
228
228
|
|
|
229
229
|
if __name__ == "__main__":
|
|
230
230
|
import logging
|
|
231
|
-
from yutipy.
|
|
231
|
+
from yutipy.logger import enable_logging
|
|
232
232
|
|
|
233
233
|
enable_logging(level=logging.DEBUG)
|
|
234
234
|
itunes = Itunes()
|
|
@@ -18,7 +18,7 @@ from yutipy.exceptions import (
|
|
|
18
18
|
)
|
|
19
19
|
from yutipy.models import MusicInfo
|
|
20
20
|
from yutipy.utils.helpers import are_strings_similar, is_valid_string
|
|
21
|
-
from yutipy.
|
|
21
|
+
from yutipy.logger import logger
|
|
22
22
|
|
|
23
23
|
load_dotenv()
|
|
24
24
|
|
|
@@ -417,7 +417,7 @@ class KKBox:
|
|
|
417
417
|
|
|
418
418
|
if __name__ == "__main__":
|
|
419
419
|
import logging
|
|
420
|
-
from yutipy.
|
|
420
|
+
from yutipy.logger import enable_logging
|
|
421
421
|
|
|
422
422
|
enable_logging(level=logging.DEBUG)
|
|
423
423
|
kkbox = KKBox(KKBOX_CLIENT_ID, KKBOX_CLIENT_SECRET)
|
|
@@ -13,7 +13,7 @@ from yutipy.exceptions import (
|
|
|
13
13
|
)
|
|
14
14
|
from yutipy.models import MusicInfo
|
|
15
15
|
from yutipy.utils.helpers import are_strings_similar, is_valid_string
|
|
16
|
-
from yutipy.
|
|
16
|
+
from yutipy.logger import logger
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
class MusicYT:
|
|
@@ -296,7 +296,7 @@ class MusicYT:
|
|
|
296
296
|
if __name__ == "__main__":
|
|
297
297
|
import logging
|
|
298
298
|
|
|
299
|
-
from yutipy.
|
|
299
|
+
from yutipy.logger import enable_logging
|
|
300
300
|
|
|
301
301
|
enable_logging(level=logging.DEBUG)
|
|
302
302
|
music_yt = MusicYT()
|