yutipy 2.2.9__py3-none-any.whl → 2.2.11__py3-none-any.whl

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/base_clients.py CHANGED
@@ -87,7 +87,7 @@ class BaseClient:
87
87
  token_info = None
88
88
  try:
89
89
  token_info = self.load_access_token()
90
- if not isinstance(token_info, dict):
90
+ if token_info and not isinstance(token_info, dict):
91
91
  raise InvalidValueException(
92
92
  "`load_access_token()` should return a dict."
93
93
  )
@@ -172,7 +172,7 @@ class BaseClient:
172
172
  self._token_expires_in = token_info.get("expires_in")
173
173
  self._token_requested_at = token_info.get("requested_at")
174
174
  else:
175
- logger.info("The access token is still valid, no need to refresh.")
175
+ logger.debug("The access token is still valid, no need to refresh.")
176
176
  except TypeError:
177
177
  logger.debug(
178
178
  f"token requested at: {self._token_requested_at} | token expires in: {self._token_expires_in}"
@@ -316,7 +316,7 @@ class BaseAuthClient:
316
316
  token_info = None
317
317
  try:
318
318
  token_info = self.load_access_token()
319
- if not isinstance(token_info, dict):
319
+ if token_info and not isinstance(token_info, dict):
320
320
  raise InvalidValueException(
321
321
  "`load_access_token()` should return a dict."
322
322
  )
@@ -419,7 +419,7 @@ class BaseAuthClient:
419
419
  self._token_requested_at = token_info.get("requested_at")
420
420
 
421
421
  else:
422
- logger.info("The access token is still valid, no need to refresh.")
422
+ logger.debug("The access token is still valid, no need to refresh.")
423
423
  except TypeError:
424
424
  logger.debug(
425
425
  f"token requested at: {self._token_requested_at} | token expires in: {self._token_expires_in}"
yutipy/deezer.py CHANGED
@@ -95,7 +95,7 @@ class Deezer:
95
95
  return None
96
96
 
97
97
  try:
98
- logger.debug(f"Parsing response JSON: {response.json()}")
98
+ logger.debug(f"Parsing response JSON.")
99
99
  result = response.json()["data"]
100
100
  except (IndexError, KeyError, ValueError) as e:
101
101
  logger.warning(f"Invalid response structure from Deezer: {e}")
@@ -159,7 +159,7 @@ class Deezer:
159
159
  return None
160
160
 
161
161
  try:
162
- logger.debug(f"Response JSON: {response.json()}")
162
+ logger.debug(f"Parsing Response JSON.")
163
163
  result = response.json()
164
164
  except ValueError as e:
165
165
  logger.warning(f"Invalid response received from Deezer: {e}")
yutipy/itunes.py CHANGED
@@ -95,7 +95,7 @@ class Itunes:
95
95
  return None
96
96
 
97
97
  try:
98
- logger.debug(f"Parsing response JSON: {response.json()}")
98
+ logger.debug(f"Parsing response JSON.")
99
99
  result = response.json()["results"]
100
100
  except (IndexError, KeyError, ValueError) as e:
101
101
  logger.warning(f"Invalid response structure from iTunes: {e}")
yutipy/utils/helpers.py CHANGED
@@ -5,6 +5,13 @@ from rapidfuzz.utils import default_process
5
5
 
6
6
  kakasi = pykakasi.kakasi()
7
7
 
8
+ TRANSLATION_CACHE = {}
9
+
10
+
11
+ def similarity(str1: str, str2: str, threshold: int = 80):
12
+ similarity_score = fuzz.WRatio(str1, str2, processor=default_process)
13
+ return similarity_score > threshold
14
+
8
15
 
9
16
  def translate_text(
10
17
  text: str,
@@ -76,30 +83,90 @@ def are_strings_similar(
76
83
  bool: True if the strings are similar, otherwise False.
77
84
  """
78
85
 
86
+ """
87
+ note for myself so that it make sense later ~ _(:з)∠)_
88
+ 0. Check cached strings for comparision
89
+ a. if found and same, return True.
90
+ 1. normalize original strings.
91
+ a. if both same, return True.
92
+ 2. translate original string.
93
+ a. if both same, return True.
94
+ 3. translate normalized string.
95
+ a. if both same, return True.
96
+ 4. return False.
97
+ """
98
+
99
+ # ### Step 0 ####
100
+ cached_str1 = TRANSLATION_CACHE.get(str1, str1)
101
+ cached_str2 = TRANSLATION_CACHE.get(str2, str2)
102
+ similar = similarity(cached_str1, cached_str2, threshold=threshold)
103
+ if similar:
104
+ return True
105
+ # ###############
106
+
107
+ # ### Step 1 ####
108
+ # Transliterate / Normalize Strings
109
+ normalized_str1 = (
110
+ TRANSLATION_CACHE.get(str1)
111
+ or "".join(item["hepburn"] for item in kakasi.convert(str1))
112
+ or str1
113
+ )
114
+ normalized_str2 = (
115
+ TRANSLATION_CACHE.get(str2)
116
+ or "".join(item["hepburn"] for item in kakasi.convert(str2))
117
+ or str2
118
+ )
119
+ similar = similarity(normalized_str1, normalized_str2, threshold=threshold)
120
+ if similar:
121
+ TRANSLATION_CACHE[str1] = normalized_str1
122
+ TRANSLATION_CACHE[str2] = normalized_str2
123
+ return True
124
+ # ###############
125
+
79
126
  if use_translation:
80
- translated_str1 = (
81
- translate_text(str1, session=translation_session)["destination-text"]
127
+ # ### Step 2 ####
128
+ original_translated_str1 = (
129
+ TRANSLATION_CACHE.get(str1)
130
+ or translate_text(str1, session=translation_session)["destination-text"]
82
131
  if translation_session
83
132
  else translate_text(str1)["destination-text"]
84
133
  )
85
- translated_str2 = (
86
- translate_text(str2, session=translation_session)["destination-text"]
134
+ original_translated_str2 = (
135
+ TRANSLATION_CACHE.get(str2)
136
+ or translate_text(str2, session=translation_session)["destination-text"]
87
137
  if translation_session
88
138
  else translate_text(str2)["destination-text"]
89
139
  )
90
-
91
- similarity_score = fuzz.WRatio(
92
- translated_str1, translated_str2, processor=default_process
140
+ similar = similarity(
141
+ original_translated_str1, original_translated_str2, threshold=threshold
93
142
  )
94
- if similarity_score > threshold:
143
+ if similar:
144
+ TRANSLATION_CACHE[str1] = original_translated_str1
145
+ TRANSLATION_CACHE[str2] = original_translated_str2
95
146
  return True
147
+ # ###############
96
148
 
97
- # Use transliterated strings for comparison
98
- str1 = "".join(item["hepburn"] for item in kakasi.convert(str1)) or str1
99
- str2 = "".join(item["hepburn"] for item in kakasi.convert(str2)) or str2
149
+ normalized_translated_str1 = (
150
+ TRANSLATION_CACHE.get(str1)
151
+ or translate_text(str1, session=translation_session)["destination-text"]
152
+ if translation_session
153
+ else translation_session(str1)["destination-text"]
154
+ )
155
+ normalized_translated_str2 = (
156
+ TRANSLATION_CACHE.get(str2)
157
+ or translate_text(str2, session=translation_session)["destination-text"]
158
+ if translation_session
159
+ else translate_text(str2)["destination-text"]
160
+ )
161
+ similar = similarity(
162
+ normalized_translated_str1, normalized_translated_str2, threshold=threshold
163
+ )
164
+ if similar:
165
+ TRANSLATION_CACHE[str1] = normalized_translated_str1
166
+ TRANSLATION_CACHE[str2] = normalized_translated_str2
167
+ return True
100
168
 
101
- similarity_score = fuzz.WRatio(str1, str2, processor=default_process)
102
- return similarity_score > threshold
169
+ return False
103
170
 
104
171
 
105
172
  def separate_artists(artists: str, custom_separator: str = None) -> list[str]:
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: yutipy
3
- Version: 2.2.9
4
- Summary: A simple package for retrieving music information from various music platforms APIs.
3
+ Version: 2.2.11
4
+ Summary: A simple Python package to interact with various music platforms APIs.
5
5
  Author: Cheap Nightbot
6
6
  Author-email: Cheap Nightbot <hi@cheapnightbot.slmail.me>
7
7
  Maintainer-email: Cheap Nightbot <hi@cheapnightbot.slmail.me>
@@ -12,7 +12,7 @@ Project-URL: Repository, https://github.com/CheapNightbot/yutipy.git
12
12
  Project-URL: Issues, https://github.com/CheapNightbot/yutipy/issues
13
13
  Project-URL: Changelog, https://github.com/CheapNightbot/yutipy/blob/master/CHANGELOG.md
14
14
  Project-URL: funding, https://ko-fi.com/cheapnightbot
15
- Keywords: music,API,Deezer,iTunes,KKBox,Spotify,YouTube Music,search,retrieve,information,yutify
15
+ Keywords: music,API,Deezer,iTunes,KKBox,Lastfm,Spotify,YouTube Music,search,retrieve,information,yutify
16
16
  Classifier: Development Status :: 4 - Beta
17
17
  Classifier: Intended Audience :: Developers
18
18
  Classifier: Topic :: Software Development :: Libraries
@@ -30,8 +30,6 @@ Requires-Dist: python-dotenv==1.1.0
30
30
  Requires-Dist: rapidfuzz==3.13.0
31
31
  Requires-Dist: requests==2.32.3
32
32
  Requires-Dist: ytmusicapi==1.10.3
33
- Provides-Extra: dev
34
- Requires-Dist: pytest; extra == "dev"
35
33
  Dynamic: license-file
36
34
 
37
35
  <p align="center">
@@ -59,7 +57,7 @@ Dynamic: license-file
59
57
  </a>
60
58
  </p>
61
59
 
62
- A _**simple**_ Python package for searching and retrieving music information from various music platforms APIs, including Deezer, iTunes, Spotify, and YouTube Music.
60
+ A _**simple**_ Python package to interact with various music platforms APIs.
63
61
 
64
62
  ## Table of Contents
65
63
 
@@ -1,8 +1,8 @@
1
1
  yutipy/__init__.py,sha256=Zrw3cr_6khXp1IgQdZxGcUM9A64GYgPs-6rlqSukW5Q,294
2
- yutipy/base_clients.py,sha256=AnBE4JG--tet7rqiB59tKqFWo3H01wJo4nGvvqdF7dM,21655
3
- yutipy/deezer.py,sha256=egsaR-4fQP1V8eOPi1UcxvnLB5495FjbtNs8si6XZbE,10491
2
+ yutipy/base_clients.py,sha256=FHCyCUQ-qE2Jo5JH-DZCxupoZTlb5ADs8XKDbHDVHwA,21687
3
+ yutipy/deezer.py,sha256=ZI1C5gam8NiNznyyagn5r0Potpg25MXja8UXg-9i9ug,10463
4
4
  yutipy/exceptions.py,sha256=zz0XyyZr5xRcmRyw3hdTGaVRcwRn_RSYZdmwmuO0sEM,1379
5
- yutipy/itunes.py,sha256=pGAAQ0nlyIx5Ustbp4T27GMsH5C9VIQ8tTTEOMQViQc,7535
5
+ yutipy/itunes.py,sha256=nApU4l3iGyAwFgPfjIJ71L1hXeN1yw7pUX_w3xgLrx0,7517
6
6
  yutipy/kkbox.py,sha256=Pfx-ZgAI9F1cbxjr7MCsMi-QulNt67t60L7y9lNmo5g,11503
7
7
  yutipy/lastfm.py,sha256=RP8OeWZnCCDENhtEc-JvypJCDsnM9aBLx77C2gmnd5Y,5938
8
8
  yutipy/logger.py,sha256=GyLBlfQZ6pLNJ5MbyQSvcD_PkxmFdX41DPq5aeG1z68,1316
@@ -14,10 +14,10 @@ yutipy/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
14
  yutipy/cli/config.py,sha256=e5RIq6RxVxxzx30nKVMa06gwyQ258s7U0WA1xvJuR_0,4543
15
15
  yutipy/cli/search.py,sha256=8SQw0bjRzRqAg-FuVz9aWjB2KBZqmCf38SyKAQ3rx5E,3025
16
16
  yutipy/utils/__init__.py,sha256=AZaqvs6AJwnqwJuodbGnHu702WSUqc8plVC16SppOcU,239
17
- yutipy/utils/helpers.py,sha256=W3g9iqoSygcFFCKCp2sk0NQrZOEG26wI2XuNi9pgAXE,5207
18
- yutipy-2.2.9.dist-info/licenses/LICENSE,sha256=_89JsS2QnBG8tAb5-VWbJDj_uJ002zPJAYBJJdh3DPY,1071
19
- yutipy-2.2.9.dist-info/METADATA,sha256=bdAJFSuIQJGegJI1bMpnqyg0w_eDMeJV4wqdUgUlRNg,6522
20
- yutipy-2.2.9.dist-info/WHEEL,sha256=7ciDxtlje1X8OhobNuGgi1t-ACdFSelPnSmDPrtlobY,91
21
- yutipy-2.2.9.dist-info/entry_points.txt,sha256=BrgmanaPjQqKQ3Ip76JLcsPgGANtrBSURf5CNIxl1HA,106
22
- yutipy-2.2.9.dist-info/top_level.txt,sha256=t2A5V2_mUcfnHkbCy6tAQlb3909jDYU5GQgXtA4756I,7
23
- yutipy-2.2.9.dist-info/RECORD,,
17
+ yutipy/utils/helpers.py,sha256=-iH0bx_sxW3Y3jjl6eTbY6QOBoG5t4obRcp7GGyw3ro,7476
18
+ yutipy-2.2.11.dist-info/licenses/LICENSE,sha256=_89JsS2QnBG8tAb5-VWbJDj_uJ002zPJAYBJJdh3DPY,1071
19
+ yutipy-2.2.11.dist-info/METADATA,sha256=vyjR03xuclUZlGwQPbSUIcXXf7oGIk57wkLJEoeOMWw,6369
20
+ yutipy-2.2.11.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
21
+ yutipy-2.2.11.dist-info/entry_points.txt,sha256=BrgmanaPjQqKQ3Ip76JLcsPgGANtrBSURf5CNIxl1HA,106
22
+ yutipy-2.2.11.dist-info/top_level.txt,sha256=t2A5V2_mUcfnHkbCy6tAQlb3909jDYU5GQgXtA4756I,7
23
+ yutipy-2.2.11.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.2.0)
2
+ Generator: setuptools (80.3.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5