thordata-sdk 0.5.0__py3-none-any.whl → 0.7.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 +139 -135
- thordata/_utils.py +144 -126
- thordata/async_client.py +815 -768
- thordata/client.py +1040 -995
- thordata/demo.py +140 -0
- thordata/enums.py +384 -315
- thordata/exceptions.py +344 -344
- thordata/models.py +840 -725
- thordata/parameters.py +53 -53
- thordata/retry.py +380 -380
- {thordata_sdk-0.5.0.dist-info → thordata_sdk-0.7.0.dist-info}/METADATA +1053 -896
- thordata_sdk-0.7.0.dist-info/RECORD +15 -0
- {thordata_sdk-0.5.0.dist-info → thordata_sdk-0.7.0.dist-info}/licenses/LICENSE +21 -21
- thordata_sdk-0.5.0.dist-info/RECORD +0 -14
- {thordata_sdk-0.5.0.dist-info → thordata_sdk-0.7.0.dist-info}/WHEEL +0 -0
- {thordata_sdk-0.5.0.dist-info → thordata_sdk-0.7.0.dist-info}/top_level.txt +0 -0
thordata/demo.py
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Unified demo entrypoint for the Thordata Python SDK.
|
|
3
|
+
|
|
4
|
+
This module runs the example scripts from the repository's `examples/` directory
|
|
5
|
+
using `runpy`, so it does not require `examples/` to be an importable package.
|
|
6
|
+
|
|
7
|
+
Usage:
|
|
8
|
+
python -m thordata.demo serp
|
|
9
|
+
python -m thordata.demo universal
|
|
10
|
+
python -m thordata.demo scraper
|
|
11
|
+
python -m thordata.demo concurrency
|
|
12
|
+
|
|
13
|
+
Notes:
|
|
14
|
+
- This entrypoint is primarily intended for repository usage (dev/demo).
|
|
15
|
+
- When installed from PyPI, the `examples/` directory is typically not included.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
import os
|
|
21
|
+
import runpy
|
|
22
|
+
import sys
|
|
23
|
+
from pathlib import Path
|
|
24
|
+
from typing import Callable, Dict
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _configure_stdio() -> None:
|
|
28
|
+
# Avoid UnicodeEncodeError on Windows consoles with legacy encodings.
|
|
29
|
+
if hasattr(sys.stdout, "reconfigure"):
|
|
30
|
+
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
|
|
31
|
+
if hasattr(sys.stderr, "reconfigure"):
|
|
32
|
+
sys.stderr.reconfigure(encoding="utf-8", errors="replace")
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _load_env() -> None:
|
|
36
|
+
# Optional .env support for local development
|
|
37
|
+
try:
|
|
38
|
+
from dotenv import load_dotenv
|
|
39
|
+
except ImportError:
|
|
40
|
+
return
|
|
41
|
+
load_dotenv()
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _repo_root() -> Path:
|
|
45
|
+
"""
|
|
46
|
+
Resolve repository root based on src layout:
|
|
47
|
+
<repo>/src/thordata/demo.py -> parents[2] == <repo>
|
|
48
|
+
"""
|
|
49
|
+
return Path(__file__).resolve().parents[2]
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _examples_dir() -> Path:
|
|
53
|
+
return _repo_root() / "examples"
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def _demo_map() -> Dict[str, Path]:
|
|
57
|
+
ex = _examples_dir()
|
|
58
|
+
return {
|
|
59
|
+
"serp": ex / "demo_serp_api.py",
|
|
60
|
+
"universal": ex / "demo_universal.py",
|
|
61
|
+
"scraper": ex / "demo_web_scraper_api.py",
|
|
62
|
+
"concurrency": ex / "async_high_concurrency.py",
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def _usage() -> str:
|
|
67
|
+
names = ", ".join(sorted(_demo_map().keys()))
|
|
68
|
+
return f"Usage: python -m thordata.demo [{names}]"
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _run_demo(path: Path) -> int:
|
|
72
|
+
if not path.exists():
|
|
73
|
+
print(f"Error: demo script not found: {path}")
|
|
74
|
+
return 2
|
|
75
|
+
|
|
76
|
+
# Ensure examples dir is on sys.path (helpful if demo imports local helpers).
|
|
77
|
+
examples_dir = str(path.parent.resolve())
|
|
78
|
+
if examples_dir not in sys.path:
|
|
79
|
+
sys.path.insert(0, examples_dir)
|
|
80
|
+
|
|
81
|
+
try:
|
|
82
|
+
# Load without triggering `if __name__ == "__main__": ...`
|
|
83
|
+
ns = runpy.run_path(str(path), run_name="__thordata_demo__")
|
|
84
|
+
|
|
85
|
+
main_func = ns.get("main")
|
|
86
|
+
if callable(main_func):
|
|
87
|
+
return int(main_func()) # type: ignore[arg-type]
|
|
88
|
+
|
|
89
|
+
# Fallback: run as __main__ for scripts without main()
|
|
90
|
+
runpy.run_path(str(path), run_name="__main__")
|
|
91
|
+
return 0
|
|
92
|
+
|
|
93
|
+
except KeyboardInterrupt:
|
|
94
|
+
raise
|
|
95
|
+
except SystemExit as e:
|
|
96
|
+
# In case fallback run as __main__ triggered SystemExit
|
|
97
|
+
code = e.code
|
|
98
|
+
if code is None:
|
|
99
|
+
return 0
|
|
100
|
+
if isinstance(code, int):
|
|
101
|
+
return code
|
|
102
|
+
return 1
|
|
103
|
+
except Exception as e:
|
|
104
|
+
import traceback
|
|
105
|
+
|
|
106
|
+
print()
|
|
107
|
+
print("-" * 60)
|
|
108
|
+
print("[thordata.demo] The demo script raised an exception.")
|
|
109
|
+
print(f"[thordata.demo] Script: {path.name}")
|
|
110
|
+
print(f"[thordata.demo] Error: {type(e).__name__}: {e}")
|
|
111
|
+
print()
|
|
112
|
+
print("Note: This is a failure within the demo script itself,")
|
|
113
|
+
print(" not an issue with the thordata.demo entrypoint.")
|
|
114
|
+
print("-" * 60)
|
|
115
|
+
traceback.print_exc()
|
|
116
|
+
return 1
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def main() -> int:
|
|
120
|
+
_configure_stdio()
|
|
121
|
+
_load_env()
|
|
122
|
+
|
|
123
|
+
if len(sys.argv) < 2:
|
|
124
|
+
print(_usage())
|
|
125
|
+
return 2
|
|
126
|
+
|
|
127
|
+
name = sys.argv[1].strip().lower()
|
|
128
|
+
mapping = _demo_map()
|
|
129
|
+
|
|
130
|
+
path = mapping.get(name)
|
|
131
|
+
if path is None:
|
|
132
|
+
print(f"Unknown demo: {name}")
|
|
133
|
+
print(_usage())
|
|
134
|
+
return 2
|
|
135
|
+
|
|
136
|
+
return _run_demo(path)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
if __name__ == "__main__":
|
|
140
|
+
raise SystemExit(main())
|