thordata-sdk 1.3.0__py3-none-any.whl → 1.4.0__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.
- thordata/__init__.py +1 -1
- thordata/async_client.py +862 -233
- thordata/async_unlimited.py +130 -0
- thordata/client.py +1808 -1050
- thordata/demo.py +2 -2
- thordata/unlimited.py +102 -0
- {thordata_sdk-1.3.0.dist-info → thordata_sdk-1.4.0.dist-info}/METADATA +2 -2
- thordata_sdk-1.4.0.dist-info/RECORD +18 -0
- thordata_sdk-1.3.0.dist-info/RECORD +0 -16
- {thordata_sdk-1.3.0.dist-info → thordata_sdk-1.4.0.dist-info}/WHEEL +0 -0
- {thordata_sdk-1.3.0.dist-info → thordata_sdk-1.4.0.dist-info}/licenses/LICENSE +0 -0
- {thordata_sdk-1.3.0.dist-info → thordata_sdk-1.4.0.dist-info}/top_level.txt +0 -0
thordata/demo.py
CHANGED
|
@@ -25,9 +25,9 @@ from pathlib import Path
|
|
|
25
25
|
def _configure_stdio() -> None:
|
|
26
26
|
# Avoid UnicodeEncodeError on Windows consoles with legacy encodings.
|
|
27
27
|
if hasattr(sys.stdout, "reconfigure"):
|
|
28
|
-
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
|
|
28
|
+
sys.stdout.reconfigure(encoding="utf-8", errors="replace") # type: ignore[attr-defined]
|
|
29
29
|
if hasattr(sys.stderr, "reconfigure"):
|
|
30
|
-
sys.stderr.reconfigure(encoding="utf-8", errors="replace")
|
|
30
|
+
sys.stderr.reconfigure(encoding="utf-8", errors="replace") # type: ignore[attr-defined]
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
def _load_env() -> None:
|
thordata/unlimited.py
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Sync interface for Unlimited Residential Proxy management.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from typing import TYPE_CHECKING, Any
|
|
8
|
+
|
|
9
|
+
from ._utils import build_public_api_headers
|
|
10
|
+
from .exceptions import raise_for_code
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from .client import ThordataClient
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class UnlimitedNamespace:
|
|
17
|
+
"""
|
|
18
|
+
Namespace for Unlimited Residential Proxy operations.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
def __init__(self, client: ThordataClient):
|
|
22
|
+
self._client = client
|
|
23
|
+
# Base URL for unlimited endpoints (usually same as public API base)
|
|
24
|
+
# We can reuse _locations_base_url logic to find the API root
|
|
25
|
+
# locations_base: .../api/locations -> root: .../api
|
|
26
|
+
self._api_base = client._locations_base_url.replace("/locations", "")
|
|
27
|
+
|
|
28
|
+
def list_servers(self) -> list[dict[str, Any]]:
|
|
29
|
+
"""
|
|
30
|
+
Get the list of unlimited proxy servers.
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
List of server objects.
|
|
34
|
+
"""
|
|
35
|
+
self._client._require_public_credentials()
|
|
36
|
+
params = {
|
|
37
|
+
"token": self._client.public_token,
|
|
38
|
+
"key": self._client.public_key,
|
|
39
|
+
}
|
|
40
|
+
response = self._client._api_request_with_retry(
|
|
41
|
+
"GET", f"{self._api_base}/unlimited/server-list", params=params
|
|
42
|
+
)
|
|
43
|
+
response.raise_for_status()
|
|
44
|
+
data = response.json()
|
|
45
|
+
if data.get("code") != 200:
|
|
46
|
+
raise_for_code("List servers failed", code=data.get("code"), payload=data)
|
|
47
|
+
|
|
48
|
+
# API returns { "data": [...] } OR { "data": { "list": [...] } } sometimes
|
|
49
|
+
# Assuming standard list return
|
|
50
|
+
return data.get("data") or []
|
|
51
|
+
|
|
52
|
+
def restart_server(self, plan_name: str) -> dict[str, Any]:
|
|
53
|
+
"""Restart an unlimited proxy server."""
|
|
54
|
+
return self._post_action("/unlimited/restart-server", {"plan_name": plan_name})
|
|
55
|
+
|
|
56
|
+
def renew(self, plan_name: str, month: int) -> dict[str, Any]:
|
|
57
|
+
"""Renew an unlimited plan."""
|
|
58
|
+
return self._post_action(
|
|
59
|
+
"/unlimited/renew", {"plan_name": plan_name, "month": str(month)}
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
def upgrade(self, plan_name: str, target_plan: str) -> dict[str, Any]:
|
|
63
|
+
"""Upgrade an unlimited plan."""
|
|
64
|
+
return self._post_action(
|
|
65
|
+
"/unlimited/upgrade",
|
|
66
|
+
{"plan_name": plan_name, "target_plan": target_plan},
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
def list_bound_users(self, ip: str) -> list[dict[str, Any]]:
|
|
70
|
+
"""List users bound to a specific unlimited server IP."""
|
|
71
|
+
data = self._post_action("/get_unlimited_servers_bind_user", {"ip": ip})
|
|
72
|
+
# Assuming data structure similar to other lists
|
|
73
|
+
return data.get("list") or [] if isinstance(data, dict) else []
|
|
74
|
+
|
|
75
|
+
def bind_user(self, ip: str, username: str) -> dict[str, Any]:
|
|
76
|
+
"""Bind a sub-user to an unlimited server IP."""
|
|
77
|
+
return self._post_action(
|
|
78
|
+
"/add_unlimited_servers_bind_user", {"ip": ip, "username": username}
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
def unbind_user(self, ip: str, username: str) -> dict[str, Any]:
|
|
82
|
+
"""Unbind a sub-user from an unlimited server IP."""
|
|
83
|
+
return self._post_action(
|
|
84
|
+
"/del_unlimited_servers_bind_user", {"ip": ip, "username": username}
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
def _post_action(self, endpoint: str, payload: dict[str, Any]) -> dict[str, Any]:
|
|
88
|
+
"""Helper for POST actions."""
|
|
89
|
+
self._client._require_public_credentials()
|
|
90
|
+
headers = build_public_api_headers(
|
|
91
|
+
self._client.public_token or "", self._client.public_key or ""
|
|
92
|
+
)
|
|
93
|
+
response = self._client._api_request_with_retry(
|
|
94
|
+
"POST", f"{self._api_base}{endpoint}", data=payload, headers=headers
|
|
95
|
+
)
|
|
96
|
+
response.raise_for_status()
|
|
97
|
+
data = response.json()
|
|
98
|
+
if data.get("code") != 200:
|
|
99
|
+
raise_for_code(
|
|
100
|
+
f"Action {endpoint} failed", code=data.get("code"), payload=data
|
|
101
|
+
)
|
|
102
|
+
return data.get("data", {})
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: thordata-sdk
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.0
|
|
4
4
|
Summary: The Official Python SDK for Thordata - AI Data Infrastructure & Proxy Network.
|
|
5
5
|
Author-email: Thordata Developer Team <support@thordata.com>
|
|
6
6
|
License: MIT
|
|
@@ -35,7 +35,7 @@ Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
|
35
35
|
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
36
36
|
Requires-Dist: pytest-httpserver>=1.0.0; extra == "dev"
|
|
37
37
|
Requires-Dist: python-dotenv>=1.0.0; extra == "dev"
|
|
38
|
-
Requires-Dist: black>=
|
|
38
|
+
Requires-Dist: black>=25.11.0; extra == "dev"
|
|
39
39
|
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
40
40
|
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
41
41
|
Requires-Dist: types-requests>=2.28.0; extra == "dev"
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
thordata/__init__.py,sha256=WVs3pZALETqLZDoAWyUoYNEjTAtC9FPvBxJEvDHnu04,3195
|
|
2
|
+
thordata/_example_utils.py,sha256=T9QtVq9BHhubOShgtGp2GSusYYd-ZFUJFJAw7ubIsa4,2199
|
|
3
|
+
thordata/_utils.py,sha256=Acr_6sHgdZXU7SQozd6FEYTZV6iHw__nlhpBTDwb66U,4917
|
|
4
|
+
thordata/async_client.py,sha256=U6VgjsaX3-dzaIwEHtPborwYVrw-K1flTLg9LP9Xozk,80378
|
|
5
|
+
thordata/async_unlimited.py,sha256=kzTksFkN21rDM21Pwy3hcayjfyGYNGGyGR3fRLtZC6I,4510
|
|
6
|
+
thordata/client.py,sha256=79XzN4VxyY9EgYSYi5FhicHzo7ASGLb4hoEWig0nT7w,84500
|
|
7
|
+
thordata/demo.py,sha256=DojJRFqUm9XAMBkjmk03WGeiUdLCbXguMIwtMOzfN6M,3822
|
|
8
|
+
thordata/enums.py,sha256=MpZnS9_8sg2vtcFqM6UicB94cKZm5R1t83L3ejNSbLs,8502
|
|
9
|
+
thordata/exceptions.py,sha256=P9czrxkFhT439DxW3LE5W-koS595ObH4-mAQOfaDM18,9976
|
|
10
|
+
thordata/models.py,sha256=qtB7jE0v5zNEQfSpmOqdiacB5DgM2QfVR2PaYs-DisM,38206
|
|
11
|
+
thordata/retry.py,sha256=5kRwULl3X68Nx8PlSzr9benfyCL0nRSpVQXrwjWr45M,11456
|
|
12
|
+
thordata/serp_engines.py,sha256=iuMWncelcGOskCHXFzpcPMMTL5qfiLkazHB1uj3zpZo,5985
|
|
13
|
+
thordata/unlimited.py,sha256=U0MEHeowNe6js8aezPFD8vGOft0VA8cpL-TUsLNyv2k,3855
|
|
14
|
+
thordata_sdk-1.4.0.dist-info/licenses/LICENSE,sha256=bAxpWgQIzb-5jl3nhLdOwOJ_vlbHLtSG7yev2B7vioY,1088
|
|
15
|
+
thordata_sdk-1.4.0.dist-info/METADATA,sha256=RJvTjs-N-ZaI7X9KfBI1ST5lcNTCeNpTZ92Cz7Ky9wk,6601
|
|
16
|
+
thordata_sdk-1.4.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
17
|
+
thordata_sdk-1.4.0.dist-info/top_level.txt,sha256=Z8R_07m0lXCCSb1hapL9_nxMtyO3rf_9wOvq4n9u2Hg,9
|
|
18
|
+
thordata_sdk-1.4.0.dist-info/RECORD,,
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
thordata/__init__.py,sha256=O9R2zY6qQXWIkQQ8Hcqqcwshymk4-2Bo_Pmm-Ma3SeI,3195
|
|
2
|
-
thordata/_example_utils.py,sha256=T9QtVq9BHhubOShgtGp2GSusYYd-ZFUJFJAw7ubIsa4,2199
|
|
3
|
-
thordata/_utils.py,sha256=Acr_6sHgdZXU7SQozd6FEYTZV6iHw__nlhpBTDwb66U,4917
|
|
4
|
-
thordata/async_client.py,sha256=9swh6AoAgvLRavFzXaM1rUz9Zm66r7GKjThjfILLiSI,58082
|
|
5
|
-
thordata/client.py,sha256=IvkPjm4v9ViiNMUM4uUbUOY3kNtJdw3mzSd3BT3yD0A,59039
|
|
6
|
-
thordata/demo.py,sha256=HQzgaUM33bWD7mBQ6HEkK5K6zqFnSAHLvaam6BwPgFA,3762
|
|
7
|
-
thordata/enums.py,sha256=MpZnS9_8sg2vtcFqM6UicB94cKZm5R1t83L3ejNSbLs,8502
|
|
8
|
-
thordata/exceptions.py,sha256=P9czrxkFhT439DxW3LE5W-koS595ObH4-mAQOfaDM18,9976
|
|
9
|
-
thordata/models.py,sha256=qtB7jE0v5zNEQfSpmOqdiacB5DgM2QfVR2PaYs-DisM,38206
|
|
10
|
-
thordata/retry.py,sha256=5kRwULl3X68Nx8PlSzr9benfyCL0nRSpVQXrwjWr45M,11456
|
|
11
|
-
thordata/serp_engines.py,sha256=iuMWncelcGOskCHXFzpcPMMTL5qfiLkazHB1uj3zpZo,5985
|
|
12
|
-
thordata_sdk-1.3.0.dist-info/licenses/LICENSE,sha256=bAxpWgQIzb-5jl3nhLdOwOJ_vlbHLtSG7yev2B7vioY,1088
|
|
13
|
-
thordata_sdk-1.3.0.dist-info/METADATA,sha256=x7p4JY94WCbvVmLiSaPDcUiKKiSw_4bRn3sLr1PRBPM,6600
|
|
14
|
-
thordata_sdk-1.3.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
15
|
-
thordata_sdk-1.3.0.dist-info/top_level.txt,sha256=Z8R_07m0lXCCSb1hapL9_nxMtyO3rf_9wOvq4n9u2Hg,9
|
|
16
|
-
thordata_sdk-1.3.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|