Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-soundcloud-v2 for
openSUSE:Factory checked in at 2026-06-15 19:44:21
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-soundcloud-v2 (Old)
and /work/SRC/openSUSE:Factory/.python-soundcloud-v2.new.1981 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-soundcloud-v2"
Mon Jun 15 19:44:21 2026 rev:3 rq:1359307 version:1.7.0
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-soundcloud-v2/python-soundcloud-v2.changes
2026-04-01 19:52:58.266968522 +0200
+++
/work/SRC/openSUSE:Factory/.python-soundcloud-v2.new.1981/python-soundcloud-v2.changes
2026-06-15 19:47:41.054078589 +0200
@@ -1,0 +2,7 @@
+Sun Jun 14 20:02:30 UTC 2026 - Dirk Müller <[email protected]>
+
+- update to 1.7.0:
+ * fix: use curl_cffi to bypass TLS fingerprinting on
+ /users/{id}/tracks
+
+-------------------------------------------------------------------
Old:
----
soundcloud_v2-1.6.2.tar.gz
New:
----
soundcloud_v2-1.7.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-soundcloud-v2.spec ++++++
--- /var/tmp/diff_new_pack.IalVgy/_old 2026-06-15 19:47:42.538140950 +0200
+++ /var/tmp/diff_new_pack.IalVgy/_new 2026-06-15 19:47:42.542141119 +0200
@@ -17,7 +17,7 @@
Name: python-soundcloud-v2
-Version: 1.6.2
+Version: 1.7.0
Release: 0
Summary: Python wrapper for the internal v2 SoundCloud API
License: MIT
++++++ soundcloud_v2-1.6.2.tar.gz -> soundcloud_v2-1.7.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/soundcloud_v2-1.6.2/PKG-INFO
new/soundcloud_v2-1.7.0/PKG-INFO
--- old/soundcloud_v2-1.6.2/PKG-INFO 2026-02-28 19:37:40.758281700 +0100
+++ new/soundcloud_v2-1.7.0/PKG-INFO 2026-04-26 06:32:31.698418600 +0200
@@ -1,12 +1,11 @@
Metadata-Version: 2.4
Name: soundcloud-v2
-Version: 1.6.2
+Version: 1.7.0
Summary: Python wrapper for the internal v2 SoundCloud API.Does not require an
API key.
Home-page: https://github.com/7x11x13/soundcloud.py
Author: 7x11x13
Author-email: [email protected]
Project-URL: Bug Tracker, https://github.com/7x11x13/soundcloud.py/issues
-Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
@@ -14,19 +13,17 @@
Classifier: Programming Language :: Python :: 3.12
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
-Requires-Python: >=3.7
+Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: dacite>=1.8.1
Requires-Dist: python-dateutil>=2.8.2
-Requires-Dist: requests
-Requires-Dist: typing_extensions; python_version < "3.8"
+Requires-Dist: curl_cffi<0.16,>=0.10
Provides-Extra: dev
Requires-Dist: coveralls; extra == "dev"
Requires-Dist: pytest; extra == "dev"
Requires-Dist: pytest-dotenv; extra == "dev"
Requires-Dist: types-python-dateutil; extra == "dev"
-Requires-Dist: types-requests; extra == "dev"
Requires-Dist: mypy; extra == "dev"
Requires-Dist: ruff; extra == "dev"
Provides-Extra: docs
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/soundcloud_v2-1.6.2/setup.py
new/soundcloud_v2-1.7.0/setup.py
--- old/soundcloud_v2-1.6.2/setup.py 2026-02-28 19:37:27.000000000 +0100
+++ new/soundcloud_v2-1.7.0/setup.py 2026-04-26 06:32:18.000000000 +0200
@@ -1,6 +1,6 @@
#!/usr/bin/env python
-from distutils.core import setup
+from setuptools import setup # type: ignore[import-untyped]
def readme():
@@ -10,7 +10,7 @@
setup(
name="soundcloud-v2",
- version="1.6.2",
+ version="1.7.0",
description=(
"Python wrapper for the internal v2 SoundCloud API.Does not require an
API key."
),
@@ -24,8 +24,7 @@
install_requires=[
"dacite>=1.8.1",
"python-dateutil>=2.8.2",
- "requests",
- "typing_extensions; python_version<'3.8'",
+ "curl_cffi>=0.10,<0.16",
],
extras_require={
"dev": [
@@ -33,14 +32,12 @@
"pytest",
"pytest-dotenv",
"types-python-dateutil",
- "types-requests",
"mypy",
"ruff",
],
"docs": ["pdoc"],
},
classifiers=[
- "Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
@@ -49,6 +46,6 @@
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
],
- python_requires=">=3.7",
+ python_requires=">=3.8",
project_urls={"Bug Tracker":
"https://github.com/7x11x13/soundcloud.py/issues"},
)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/soundcloud_v2-1.6.2/soundcloud/__init__.py
new/soundcloud_v2-1.7.0/soundcloud/__init__.py
--- old/soundcloud_v2-1.6.2/soundcloud/__init__.py 2026-02-28
19:37:27.000000000 +0100
+++ new/soundcloud_v2-1.7.0/soundcloud/__init__.py 2026-04-26
06:32:18.000000000 +0200
@@ -64,6 +64,6 @@
from soundcloud.soundcloud import *
from soundcloud.soundcloud import __all__ as sc_all
-__version__ = "1.6.2"
+__version__ = "1.7.0"
__all__ = sc_all + ex_all + res_all
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/soundcloud_v2-1.6.2/soundcloud/requests.py
new/soundcloud_v2-1.7.0/soundcloud/requests.py
--- old/soundcloud_v2-1.6.2/soundcloud/requests.py 2026-02-28
19:37:27.000000000 +0100
+++ new/soundcloud_v2-1.7.0/soundcloud/requests.py 2026-04-26
06:32:18.000000000 +0200
@@ -1,6 +1,5 @@
import string
from dataclasses import asdict, dataclass
-import sys
from typing import (
TYPE_CHECKING,
Any,
@@ -9,14 +8,17 @@
Generator,
Generic,
List,
+ Literal,
Optional,
+ Protocol,
Tuple,
Type,
TypeVar,
Union,
+ get_args,
+ get_origin,
)
-
-import requests
+from urllib.parse import parse_qs, urljoin, urlparse
from soundcloud.resource.aliases import Like, RepostItem, SearchItem,
StreamItem
from soundcloud.resource.base import BaseData
@@ -35,24 +37,6 @@
if TYPE_CHECKING:
from soundcloud.soundcloud import SoundCloud
-if sys.version_info >= (3, 8):
- from typing import Protocol
-else:
- from typing_extensions import Protocol
-
-try:
- from typing import get_args, get_origin # type: ignore[attr-defined]
-except ImportError:
- # get_args and get_origin for version < 3.8
- def get_args(tp): # type: ignore[misc]
- return getattr(tp, "__args__", ())
-
- def get_origin(tp): # type: ignore[no-redef]
- return getattr(tp, "__origin__", None)
-
-
-from urllib.parse import parse_qs, urljoin, urlparse
-
def _convert_dict(d, return_type: Type[BaseData]):
union = get_origin(return_type) is Union
@@ -75,7 +59,7 @@
base = "https://api-v2.soundcloud.com"
format_url: str
return_type: Type[T]
- method: str = "GET"
+ method: Literal["GET", "POST", "DELETE"] = "GET"
def _format_url_and_remove_params(self, kwargs: dict) -> str:
format_args = {
@@ -110,12 +94,16 @@
if use_auth and client._authorization is not None:
headers["Authorization"] = client._authorization
- with requests.request(
- self.method, resource_url, json=body, headers=headers,
params=params
- ) as r:
- if r.status_code in (400, 404, 500):
- return None
- r.raise_for_status()
+ r = client._session.request(
+ self.method,
+ resource_url,
+ json=body,
+ headers=headers,
+ params=params,
+ )
+ if r.status_code in (400, 404, 500):
+ return None
+ r.raise_for_status()
if self.return_type == NoContentResponse:
return NoContentResponse(r.status_code) # type:
ignore[return-value]
@@ -150,20 +138,20 @@
if use_auth and client._authorization is not None:
headers["Authorization"] = client._authorization
while resource_url:
- with requests.get(resource_url, params=params, headers=headers) as
r:
- if r.status_code in (400, 404, 500):
- return
- r.raise_for_status()
- data = r.json()
- for resource in data["collection"]:
- yield _convert_dict(resource, self.return_type)
- resource_url = data.get("next_href", None)
- parsed = urlparse(resource_url)
- params = parse_qs(parsed.query)
- params["client_id"] = [
- client.client_id
- ] # next_href doesn't contain client_id
- resource_url = urljoin(resource_url, parsed.path)
+ r = client._session.get(resource_url, params=params,
headers=headers)
+ if r.status_code in (400, 404, 500):
+ return
+ r.raise_for_status()
+ data = r.json()
+ for resource in data["collection"]:
+ yield _convert_dict(resource, self.return_type)
+ resource_url = data.get("next_href", None)
+ parsed = urlparse(resource_url)
+ params = parse_qs(parsed.query)
+ params["client_id"] = [
+ client.client_id
+ ] # next_href doesn't contain client_id
+ resource_url = urljoin(resource_url, parsed.path)
@dataclass
@@ -184,12 +172,12 @@
if use_auth and client._authorization is not None:
headers["Authorization"] = client._authorization
resources = []
- with requests.get(resource_url, params=params, headers=headers) as r:
- if r.status_code in (400, 404, 500):
- return []
- r.raise_for_status()
- for resource in r.json():
- resources.append(_convert_dict(resource, self.return_type))
+ r = client._session.get(resource_url, params=params, headers=headers)
+ if r.status_code in (400, 404, 500):
+ return []
+ r.raise_for_status()
+ for resource in r.json():
+ resources.append(_convert_dict(resource, self.return_type))
return resources
@@ -227,11 +215,11 @@
"variables": asdict(query_args),
}
- with requests.post(self.base, json=data, params=params,
headers=headers) as r:
- if r.status_code in (400, 404, 500):
- return None
- r.raise_for_status()
- return _convert_dict(r.json()["data"], self.return_type)
+ r = client._session.post(self.base, json=data, params=params,
headers=headers)
+ if r.status_code in (400, 404, 500):
+ return None
+ r.raise_for_status()
+ return _convert_dict(r.json()["data"], self.return_type)
"""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/soundcloud_v2-1.6.2/soundcloud/soundcloud.py
new/soundcloud_v2-1.7.0/soundcloud/soundcloud.py
--- old/soundcloud_v2-1.6.2/soundcloud/soundcloud.py 2026-02-28
19:37:27.000000000 +0100
+++ new/soundcloud_v2-1.7.0/soundcloud/soundcloud.py 2026-04-26
06:32:18.000000000 +0200
@@ -1,15 +1,10 @@
import itertools
-import sys
import re
-from typing import Dict, Generator, List, Optional
+from typing import Dict, Generator, List, Literal, Optional
-if sys.version_info < (3, 8):
- from typing_extensions import Literal
-else:
- from typing import Literal
-
-import requests
-from requests import HTTPError
+from curl_cffi import requests
+from curl_cffi.requests import BrowserTypeLiteral
+from curl_cffi.requests.exceptions import HTTPError
from soundcloud.exceptions import ClientIDGenerationError
from soundcloud.requests import (
@@ -95,9 +90,12 @@
client_id: Optional[str] = None,
auth_token: Optional[str] = None,
user_agent: str = _DEFAULT_USER_AGENT,
+ impersonate: BrowserTypeLiteral = "chrome",
) -> None:
+ self._impersonate = impersonate
+ self._session: requests.Session =
requests.Session(impersonate=impersonate)
if not client_id:
- client_id = self.generate_client_id()
+ client_id = self.generate_client_id(impersonate=impersonate)
self.client_id = client_id
self._user_agent = user_agent
@@ -126,7 +124,7 @@
return {"User-Agent": self._user_agent}
@classmethod
- def generate_client_id(cls) -> str:
+ def generate_client_id(cls, impersonate: BrowserTypeLiteral = "chrome") ->
str:
"""Generates a SoundCloud client ID
Raises:
@@ -135,18 +133,19 @@
Returns:
str: Valid client ID
"""
- r = requests.get("https://soundcloud.com")
- r.raise_for_status()
- matches = cls._ASSETS_SCRIPTS_REGEX.findall(r.text)
- if not matches:
- raise ClientIDGenerationError("No asset scripts found")
- for url in matches:
- r = requests.get(url)
+ with requests.Session(impersonate=impersonate) as s:
+ r = s.get("https://soundcloud.com")
r.raise_for_status()
- client_id = cls._CLIENT_ID_REGEX.search(r.text)
- if client_id:
- return client_id.group(1)
- raise ClientIDGenerationError(f"Could not find client_id in script
'{url}'")
+ matches = cls._ASSETS_SCRIPTS_REGEX.findall(r.text)
+ if not matches:
+ raise ClientIDGenerationError("No asset scripts found")
+ for url in matches:
+ r = s.get(url)
+ r.raise_for_status()
+ client_id = cls._CLIENT_ID_REGEX.search(r.text)
+ if client_id:
+ return client_id.group(1)
+ raise ClientIDGenerationError(f"Could not find client_id in script
'{url}'")
def is_client_id_valid(self) -> bool:
"""
@@ -366,8 +365,9 @@
assert user_interactions.interactionCounts is not None
likes = list(
filter(
- lambda x: x.interactionTypeValueUrn
- == "sc:interactiontypevalue:like",
+ lambda x: (
+ x.interactionTypeValueUrn ==
"sc:interactiontypevalue:like"
+ ),
user_interactions.interactionCounts,
)
)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/soundcloud_v2-1.6.2/soundcloud_v2.egg-info/PKG-INFO
new/soundcloud_v2-1.7.0/soundcloud_v2.egg-info/PKG-INFO
--- old/soundcloud_v2-1.6.2/soundcloud_v2.egg-info/PKG-INFO 2026-02-28
19:37:40.000000000 +0100
+++ new/soundcloud_v2-1.7.0/soundcloud_v2.egg-info/PKG-INFO 2026-04-26
06:32:31.000000000 +0200
@@ -1,12 +1,11 @@
Metadata-Version: 2.4
Name: soundcloud-v2
-Version: 1.6.2
+Version: 1.7.0
Summary: Python wrapper for the internal v2 SoundCloud API.Does not require an
API key.
Home-page: https://github.com/7x11x13/soundcloud.py
Author: 7x11x13
Author-email: [email protected]
Project-URL: Bug Tracker, https://github.com/7x11x13/soundcloud.py/issues
-Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
@@ -14,19 +13,17 @@
Classifier: Programming Language :: Python :: 3.12
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
-Requires-Python: >=3.7
+Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: dacite>=1.8.1
Requires-Dist: python-dateutil>=2.8.2
-Requires-Dist: requests
-Requires-Dist: typing_extensions; python_version < "3.8"
+Requires-Dist: curl_cffi<0.16,>=0.10
Provides-Extra: dev
Requires-Dist: coveralls; extra == "dev"
Requires-Dist: pytest; extra == "dev"
Requires-Dist: pytest-dotenv; extra == "dev"
Requires-Dist: types-python-dateutil; extra == "dev"
-Requires-Dist: types-requests; extra == "dev"
Requires-Dist: mypy; extra == "dev"
Requires-Dist: ruff; extra == "dev"
Provides-Extra: docs
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/soundcloud_v2-1.6.2/soundcloud_v2.egg-info/requires.txt
new/soundcloud_v2-1.7.0/soundcloud_v2.egg-info/requires.txt
--- old/soundcloud_v2-1.6.2/soundcloud_v2.egg-info/requires.txt 2026-02-28
19:37:40.000000000 +0100
+++ new/soundcloud_v2-1.7.0/soundcloud_v2.egg-info/requires.txt 2026-04-26
06:32:31.000000000 +0200
@@ -1,16 +1,12 @@
dacite>=1.8.1
python-dateutil>=2.8.2
-requests
-
-[:python_version < "3.8"]
-typing_extensions
+curl_cffi<0.16,>=0.10
[dev]
coveralls
pytest
pytest-dotenv
types-python-dateutil
-types-requests
mypy
ruff