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/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.0
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>=23.0.0; extra == "dev"
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,,