yutipy 2.2.10__py3-none-any.whl → 2.2.12__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
@@ -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}"
@@ -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}")
@@ -183,17 +183,14 @@ class Itunes:
183
183
  tuple
184
184
  The extracted album title and type.
185
185
  """
186
- try:
187
- album_title, album_type = result["collectionName"].split("-")
188
- return album_title.strip(), album_type.strip()
189
- except ValueError:
190
- guess = guess_album_type(result.get("trackCount", 1))
191
- guessed_right = are_strings_similar(
192
- result.get("wrapperType", "x"), guess, use_translation=False
193
- )
194
- return result["collectionName"], (
195
- result["wrapperType"] if guessed_right else guess
196
- )
186
+
187
+ guess = guess_album_type(result.get("trackCount", 1))
188
+ guessed_right = are_strings_similar(
189
+ result.get("wrapperType", "x"), guess, use_translation=False
190
+ )
191
+ return result["collectionName"], (
192
+ result["wrapperType"] if guessed_right else guess
193
+ )
197
194
 
198
195
  def _format_release_date(self, release_date: str) -> str:
199
196
  """
yutipy/lastfm.py CHANGED
@@ -154,7 +154,7 @@ class LastFm:
154
154
  artists=", ".join(
155
155
  separate_artists(result.get("artist", {}).get("#text"))
156
156
  ),
157
- id=result.get("mbid"),
157
+ id=result.get("mbid") if result.get("mbid") else None,
158
158
  timestamp=result.get("date", {}).get("uts") or time(),
159
159
  title=result.get("name"),
160
160
  url=result.get("url"),
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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: yutipy
3
- Version: 2.2.10
3
+ Version: 2.2.12
4
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>
@@ -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">
@@ -1,10 +1,10 @@
1
1
  yutipy/__init__.py,sha256=Zrw3cr_6khXp1IgQdZxGcUM9A64GYgPs-6rlqSukW5Q,294
2
- yutipy/base_clients.py,sha256=mnDRbSAxrsGHT4SxFNFJ31RnmBz-eyaDHE7umK_suGo,21685
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=FAHZDUn6Mvk2t5Ws5rF0hQMzIKZAIflR49lhEPIUyLs,7317
6
6
  yutipy/kkbox.py,sha256=Pfx-ZgAI9F1cbxjr7MCsMi-QulNt67t60L7y9lNmo5g,11503
7
- yutipy/lastfm.py,sha256=RP8OeWZnCCDENhtEc-JvypJCDsnM9aBLx77C2gmnd5Y,5938
7
+ yutipy/lastfm.py,sha256=hOFQOZdf51Gp2m02b4NjKRmQ9yQZ9Yas6MaM78c-oCg,5970
8
8
  yutipy/logger.py,sha256=GyLBlfQZ6pLNJ5MbyQSvcD_PkxmFdX41DPq5aeG1z68,1316
9
9
  yutipy/models.py,sha256=45M-bNHusaAan_Ta_E9DyvsWujsT-ivbJqIfy2-i3R8,2343
10
10
  yutipy/musicyt.py,sha256=n3yaH9qyGlsW2HKPAmqYQNGzhuDH4s5Gh0R5v4JPoeg,9472
@@ -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.10.dist-info/licenses/LICENSE,sha256=_89JsS2QnBG8tAb5-VWbJDj_uJ002zPJAYBJJdh3DPY,1071
19
- yutipy-2.2.10.dist-info/METADATA,sha256=aUKkNEJvrDrsnHj57ZOxy61Y3kygPdV0a7duFOw8tY4,6427
20
- yutipy-2.2.10.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
21
- yutipy-2.2.10.dist-info/entry_points.txt,sha256=BrgmanaPjQqKQ3Ip76JLcsPgGANtrBSURf5CNIxl1HA,106
22
- yutipy-2.2.10.dist-info/top_level.txt,sha256=t2A5V2_mUcfnHkbCy6tAQlb3909jDYU5GQgXtA4756I,7
23
- yutipy-2.2.10.dist-info/RECORD,,
17
+ yutipy/utils/helpers.py,sha256=-iH0bx_sxW3Y3jjl6eTbY6QOBoG5t4obRcp7GGyw3ro,7476
18
+ yutipy-2.2.12.dist-info/licenses/LICENSE,sha256=_89JsS2QnBG8tAb5-VWbJDj_uJ002zPJAYBJJdh3DPY,1071
19
+ yutipy-2.2.12.dist-info/METADATA,sha256=OY5NoPGtT3vZZGs_5oleKfzPlwFQuTlk1SH5c2zbFJI,6369
20
+ yutipy-2.2.12.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
21
+ yutipy-2.2.12.dist-info/entry_points.txt,sha256=BrgmanaPjQqKQ3Ip76JLcsPgGANtrBSURf5CNIxl1HA,106
22
+ yutipy-2.2.12.dist-info/top_level.txt,sha256=t2A5V2_mUcfnHkbCy6tAQlb3909jDYU5GQgXtA4756I,7
23
+ yutipy-2.2.12.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.3.1)
2
+ Generator: setuptools (80.8.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5