reserp 0.1.0__tar.gz
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.
- reserp-0.1.0/.github/workflows/ci.yml +45 -0
- reserp-0.1.0/.gitignore +10 -0
- reserp-0.1.0/CHANGELOG.md +12 -0
- reserp-0.1.0/CONTRIBUTING.md +25 -0
- reserp-0.1.0/LICENSE +21 -0
- reserp-0.1.0/PKG-INFO +206 -0
- reserp-0.1.0/README.md +170 -0
- reserp-0.1.0/SECURITY.md +5 -0
- reserp-0.1.0/pyproject.toml +83 -0
- reserp-0.1.0/src/reserp/__about__.py +1 -0
- reserp-0.1.0/src/reserp/__init__.py +37 -0
- reserp-0.1.0/src/reserp/client.py +369 -0
- reserp-0.1.0/src/reserp/errors.py +57 -0
- reserp-0.1.0/src/reserp/py.typed +0 -0
- reserp-0.1.0/src/reserp/types.py +42 -0
- reserp-0.1.0/src/reserp/urls.py +106 -0
- reserp-0.1.0/tests/test_client.py +205 -0
- reserp-0.1.0/tests/test_package.py +7 -0
- reserp-0.1.0/tests/test_urls.py +59 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
test:
|
|
13
|
+
name: Python ${{ matrix.python-version }}
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
timeout-minutes: 10
|
|
16
|
+
strategy:
|
|
17
|
+
fail-fast: false
|
|
18
|
+
matrix:
|
|
19
|
+
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v4
|
|
22
|
+
- uses: actions/setup-python@v5
|
|
23
|
+
with:
|
|
24
|
+
python-version: ${{ matrix.python-version }}
|
|
25
|
+
cache: pip
|
|
26
|
+
- run: python -m pip install --upgrade pip
|
|
27
|
+
- run: python -m pip install -e ".[dev]"
|
|
28
|
+
- run: pytest
|
|
29
|
+
|
|
30
|
+
quality:
|
|
31
|
+
runs-on: ubuntu-latest
|
|
32
|
+
timeout-minutes: 10
|
|
33
|
+
steps:
|
|
34
|
+
- uses: actions/checkout@v4
|
|
35
|
+
- uses: actions/setup-python@v5
|
|
36
|
+
with:
|
|
37
|
+
python-version: "3.14"
|
|
38
|
+
cache: pip
|
|
39
|
+
- run: python -m pip install --upgrade pip
|
|
40
|
+
- run: python -m pip install -e ".[dev]"
|
|
41
|
+
- run: ruff check .
|
|
42
|
+
- run: ruff format --check .
|
|
43
|
+
- run: mypy src
|
|
44
|
+
- run: python -m build
|
|
45
|
+
- run: twine check dist/*
|
reserp-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
## [0.1.0] - 2026-08-18
|
|
6
|
+
|
|
7
|
+
- Initial synchronous and asynchronous Python SDK.
|
|
8
|
+
- Typed search responses and API errors.
|
|
9
|
+
- One-based pagination and raw Google Search URL support.
|
|
10
|
+
- Billing-safe retries and configurable timeouts.
|
|
11
|
+
|
|
12
|
+
[0.1.0]: https://github.com/reserp-ai/reserp-python/releases/tag/v0.1.0
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Thanks for helping improve the Reserp Python SDK.
|
|
4
|
+
|
|
5
|
+
## Development
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
python -m venv .venv
|
|
9
|
+
source .venv/bin/activate
|
|
10
|
+
python -m pip install --upgrade pip
|
|
11
|
+
python -m pip install -e ".[dev]"
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Run the validation suite before opening a pull request:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
ruff check .
|
|
18
|
+
ruff format --check .
|
|
19
|
+
mypy src
|
|
20
|
+
pytest
|
|
21
|
+
python -m build
|
|
22
|
+
twine check dist/*
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Keep changes focused on the public SDK and documented API contract. Do not include API keys, account data, or private implementation details.
|
reserp-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Reserp
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
reserp-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: reserp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Official Python SDK for the Reserp Google Search API
|
|
5
|
+
Project-URL: Homepage, https://reserp.ai
|
|
6
|
+
Project-URL: Documentation, https://reserp.ai/docs
|
|
7
|
+
Project-URL: Repository, https://github.com/reserp-ai/reserp-python
|
|
8
|
+
Project-URL: Issues, https://github.com/reserp-ai/reserp-python/issues
|
|
9
|
+
Project-URL: Changelog, https://github.com/reserp-ai/reserp-python/blob/main/CHANGELOG.md
|
|
10
|
+
Author-email: Reserp <no-reply@reserp.ai>
|
|
11
|
+
License-Expression: MIT
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Keywords: api-client,google-search,google-search-api,python,reserp,sdk,search-api,serp,serp-api
|
|
14
|
+
Classifier: Development Status :: 4 - Beta
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
24
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
25
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
26
|
+
Classifier: Typing :: Typed
|
|
27
|
+
Requires-Python: >=3.10
|
|
28
|
+
Requires-Dist: httpx<1,>=0.27
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: build<2,>=1.2; extra == 'dev'
|
|
31
|
+
Requires-Dist: mypy<2,>=1.13; extra == 'dev'
|
|
32
|
+
Requires-Dist: pytest<10,>=8.3; extra == 'dev'
|
|
33
|
+
Requires-Dist: ruff<1,>=0.8; extra == 'dev'
|
|
34
|
+
Requires-Dist: twine<7,>=5.1; extra == 'dev'
|
|
35
|
+
Description-Content-Type: text/markdown
|
|
36
|
+
|
|
37
|
+
<p align="center">
|
|
38
|
+
<a href="https://reserp.ai">
|
|
39
|
+
<img src="https://reserp.ai/icon-512.png" alt="Reserp Google Search API" width="112" height="112">
|
|
40
|
+
</a>
|
|
41
|
+
</p>
|
|
42
|
+
|
|
43
|
+
# Reserp Python SDK
|
|
44
|
+
|
|
45
|
+
[](https://pypi.org/project/reserp/)
|
|
46
|
+
[](https://pypi.org/project/reserp/)
|
|
47
|
+
[](https://github.com/reserp-ai/reserp-python/actions/workflows/ci.yml)
|
|
48
|
+
[](LICENSE)
|
|
49
|
+
|
|
50
|
+
The official Python SDK for [Reserp](https://reserp.ai), a Google Search API for developers and AI agents.
|
|
51
|
+
|
|
52
|
+
Retrieve structured Google Search results through one stable JSON schema. Start for free with no credit card required.
|
|
53
|
+
|
|
54
|
+
[Website](https://reserp.ai) · [API documentation](https://reserp.ai/docs) · [OpenAPI 3.1](https://reserp.ai/openapi.json) · [Pricing](https://reserp.ai/pricing)
|
|
55
|
+
|
|
56
|
+
## Features
|
|
57
|
+
|
|
58
|
+
- Synchronous and asynchronous clients built on HTTPX.
|
|
59
|
+
- Typed responses that preserve the complete API response dictionary.
|
|
60
|
+
- One-based pagination plus support for authoritative pagination URLs.
|
|
61
|
+
- Configurable retries and timeouts.
|
|
62
|
+
- Automatic retries only when the API says the request is retryable and was not billed.
|
|
63
|
+
|
|
64
|
+
## Installation
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
pip install reserp
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Python 3.10 or later is required.
|
|
71
|
+
|
|
72
|
+
## Quick start
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
import os
|
|
76
|
+
|
|
77
|
+
from reserp import Reserp
|
|
78
|
+
|
|
79
|
+
client = Reserp(api_key=os.environ["RESERP_API_KEY"])
|
|
80
|
+
|
|
81
|
+
response = client.search(
|
|
82
|
+
query="best pizza in dubai",
|
|
83
|
+
gl="ae",
|
|
84
|
+
hl="en",
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
for result in response["results"]:
|
|
88
|
+
print(result.get("text"), result.get("url"))
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Create an API key in the [Reserp dashboard](https://reserp.ai/dashboard). Keep API keys on your server; never embed one in browser or mobile code.
|
|
92
|
+
|
|
93
|
+
The SDK returns the API response as a normal Python dictionary. Result order, nested `children`, pagination, and billing fields remain intact.
|
|
94
|
+
|
|
95
|
+
## Async client
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
import asyncio
|
|
99
|
+
import os
|
|
100
|
+
|
|
101
|
+
from reserp import AsyncReserp
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
async def main() -> None:
|
|
105
|
+
async with AsyncReserp(api_key=os.environ["RESERP_API_KEY"]) as client:
|
|
106
|
+
response = await client.search(
|
|
107
|
+
query="semiconductor manufacturing",
|
|
108
|
+
gl="us",
|
|
109
|
+
hl="en",
|
|
110
|
+
)
|
|
111
|
+
print(response["results"])
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
asyncio.run(main())
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
The synchronous client is also a context manager:
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
with Reserp(api_key=os.environ["RESERP_API_KEY"]) as client:
|
|
121
|
+
response = client.search(query="photonic computing")
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Pagination
|
|
125
|
+
|
|
126
|
+
`page` is one-based, so you do not need to calculate Google's `start` offsets:
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
second_page = client.search(
|
|
130
|
+
query="photonic computing",
|
|
131
|
+
page=2,
|
|
132
|
+
)
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
You can also follow the authoritative pagination URL returned by the API:
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
first = client.search(query="photonic computing")
|
|
139
|
+
second = client.next_page(first)
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Do not derive pagination from `len(response["results"])`. A response can contain organic listings, news, carousels, sitelinks, and nested result blocks.
|
|
143
|
+
|
|
144
|
+
## Google parameters
|
|
145
|
+
|
|
146
|
+
Use `params` for additional Google parameters such as `tbs` and `tbm`:
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
news = client.search(
|
|
150
|
+
query="semiconductor manufacturing",
|
|
151
|
+
params={"tbm": "nws", "tbs": "qdr:w"},
|
|
152
|
+
)
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
For complete control, submit a full Google Search URL:
|
|
156
|
+
|
|
157
|
+
```python
|
|
158
|
+
response = client.search_url(
|
|
159
|
+
"https://www.google.com/search?q=semiconductor+manufacturing&gl=us&hl=en&tbs=qdr:w"
|
|
160
|
+
)
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
All Google URL parameters pass through unchanged except parameters documented as unsupported by Reserp. The `num` parameter is currently unsupported.
|
|
164
|
+
|
|
165
|
+
## Errors and retries
|
|
166
|
+
|
|
167
|
+
API failures raise `ReserpAPIError` with the stable public error code and billing state:
|
|
168
|
+
|
|
169
|
+
```python
|
|
170
|
+
from reserp import ReserpAPIError
|
|
171
|
+
|
|
172
|
+
try:
|
|
173
|
+
response = client.search(query="photonic computing")
|
|
174
|
+
except ReserpAPIError as error:
|
|
175
|
+
print(error.status, error.code, error.retryable, error.billed)
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
The SDK retries retryable API responses up to two times by default, respecting `Retry-After` for rate limits. It never automatically retries a response whose `billed` field is true. Network failures are not automatically retried because the client cannot know whether the original request reached the API.
|
|
179
|
+
|
|
180
|
+
Configure retries and per-attempt timeouts globally or per request:
|
|
181
|
+
|
|
182
|
+
```python
|
|
183
|
+
client = Reserp(
|
|
184
|
+
api_key=os.environ["RESERP_API_KEY"],
|
|
185
|
+
max_retries=1,
|
|
186
|
+
timeout=20.0,
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
response = client.search(
|
|
190
|
+
query="photonic computing",
|
|
191
|
+
max_retries=0,
|
|
192
|
+
timeout=10.0,
|
|
193
|
+
)
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Set `timeout=0` to disable the SDK timeout.
|
|
197
|
+
|
|
198
|
+
## API reference
|
|
199
|
+
|
|
200
|
+
- [Reserp API documentation](https://reserp.ai/docs)
|
|
201
|
+
- [OpenAPI 3.1 document](https://reserp.ai/openapi.json)
|
|
202
|
+
- [Pricing](https://reserp.ai/pricing)
|
|
203
|
+
|
|
204
|
+
## License
|
|
205
|
+
|
|
206
|
+
MIT
|
reserp-0.1.0/README.md
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<a href="https://reserp.ai">
|
|
3
|
+
<img src="https://reserp.ai/icon-512.png" alt="Reserp Google Search API" width="112" height="112">
|
|
4
|
+
</a>
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
# Reserp Python SDK
|
|
8
|
+
|
|
9
|
+
[](https://pypi.org/project/reserp/)
|
|
10
|
+
[](https://pypi.org/project/reserp/)
|
|
11
|
+
[](https://github.com/reserp-ai/reserp-python/actions/workflows/ci.yml)
|
|
12
|
+
[](LICENSE)
|
|
13
|
+
|
|
14
|
+
The official Python SDK for [Reserp](https://reserp.ai), a Google Search API for developers and AI agents.
|
|
15
|
+
|
|
16
|
+
Retrieve structured Google Search results through one stable JSON schema. Start for free with no credit card required.
|
|
17
|
+
|
|
18
|
+
[Website](https://reserp.ai) · [API documentation](https://reserp.ai/docs) · [OpenAPI 3.1](https://reserp.ai/openapi.json) · [Pricing](https://reserp.ai/pricing)
|
|
19
|
+
|
|
20
|
+
## Features
|
|
21
|
+
|
|
22
|
+
- Synchronous and asynchronous clients built on HTTPX.
|
|
23
|
+
- Typed responses that preserve the complete API response dictionary.
|
|
24
|
+
- One-based pagination plus support for authoritative pagination URLs.
|
|
25
|
+
- Configurable retries and timeouts.
|
|
26
|
+
- Automatic retries only when the API says the request is retryable and was not billed.
|
|
27
|
+
|
|
28
|
+
## Installation
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
pip install reserp
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Python 3.10 or later is required.
|
|
35
|
+
|
|
36
|
+
## Quick start
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
import os
|
|
40
|
+
|
|
41
|
+
from reserp import Reserp
|
|
42
|
+
|
|
43
|
+
client = Reserp(api_key=os.environ["RESERP_API_KEY"])
|
|
44
|
+
|
|
45
|
+
response = client.search(
|
|
46
|
+
query="best pizza in dubai",
|
|
47
|
+
gl="ae",
|
|
48
|
+
hl="en",
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
for result in response["results"]:
|
|
52
|
+
print(result.get("text"), result.get("url"))
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Create an API key in the [Reserp dashboard](https://reserp.ai/dashboard). Keep API keys on your server; never embed one in browser or mobile code.
|
|
56
|
+
|
|
57
|
+
The SDK returns the API response as a normal Python dictionary. Result order, nested `children`, pagination, and billing fields remain intact.
|
|
58
|
+
|
|
59
|
+
## Async client
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
import asyncio
|
|
63
|
+
import os
|
|
64
|
+
|
|
65
|
+
from reserp import AsyncReserp
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
async def main() -> None:
|
|
69
|
+
async with AsyncReserp(api_key=os.environ["RESERP_API_KEY"]) as client:
|
|
70
|
+
response = await client.search(
|
|
71
|
+
query="semiconductor manufacturing",
|
|
72
|
+
gl="us",
|
|
73
|
+
hl="en",
|
|
74
|
+
)
|
|
75
|
+
print(response["results"])
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
asyncio.run(main())
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
The synchronous client is also a context manager:
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
with Reserp(api_key=os.environ["RESERP_API_KEY"]) as client:
|
|
85
|
+
response = client.search(query="photonic computing")
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Pagination
|
|
89
|
+
|
|
90
|
+
`page` is one-based, so you do not need to calculate Google's `start` offsets:
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
second_page = client.search(
|
|
94
|
+
query="photonic computing",
|
|
95
|
+
page=2,
|
|
96
|
+
)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
You can also follow the authoritative pagination URL returned by the API:
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
first = client.search(query="photonic computing")
|
|
103
|
+
second = client.next_page(first)
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Do not derive pagination from `len(response["results"])`. A response can contain organic listings, news, carousels, sitelinks, and nested result blocks.
|
|
107
|
+
|
|
108
|
+
## Google parameters
|
|
109
|
+
|
|
110
|
+
Use `params` for additional Google parameters such as `tbs` and `tbm`:
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
news = client.search(
|
|
114
|
+
query="semiconductor manufacturing",
|
|
115
|
+
params={"tbm": "nws", "tbs": "qdr:w"},
|
|
116
|
+
)
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
For complete control, submit a full Google Search URL:
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
response = client.search_url(
|
|
123
|
+
"https://www.google.com/search?q=semiconductor+manufacturing&gl=us&hl=en&tbs=qdr:w"
|
|
124
|
+
)
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
All Google URL parameters pass through unchanged except parameters documented as unsupported by Reserp. The `num` parameter is currently unsupported.
|
|
128
|
+
|
|
129
|
+
## Errors and retries
|
|
130
|
+
|
|
131
|
+
API failures raise `ReserpAPIError` with the stable public error code and billing state:
|
|
132
|
+
|
|
133
|
+
```python
|
|
134
|
+
from reserp import ReserpAPIError
|
|
135
|
+
|
|
136
|
+
try:
|
|
137
|
+
response = client.search(query="photonic computing")
|
|
138
|
+
except ReserpAPIError as error:
|
|
139
|
+
print(error.status, error.code, error.retryable, error.billed)
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
The SDK retries retryable API responses up to two times by default, respecting `Retry-After` for rate limits. It never automatically retries a response whose `billed` field is true. Network failures are not automatically retried because the client cannot know whether the original request reached the API.
|
|
143
|
+
|
|
144
|
+
Configure retries and per-attempt timeouts globally or per request:
|
|
145
|
+
|
|
146
|
+
```python
|
|
147
|
+
client = Reserp(
|
|
148
|
+
api_key=os.environ["RESERP_API_KEY"],
|
|
149
|
+
max_retries=1,
|
|
150
|
+
timeout=20.0,
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
response = client.search(
|
|
154
|
+
query="photonic computing",
|
|
155
|
+
max_retries=0,
|
|
156
|
+
timeout=10.0,
|
|
157
|
+
)
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Set `timeout=0` to disable the SDK timeout.
|
|
161
|
+
|
|
162
|
+
## API reference
|
|
163
|
+
|
|
164
|
+
- [Reserp API documentation](https://reserp.ai/docs)
|
|
165
|
+
- [OpenAPI 3.1 document](https://reserp.ai/openapi.json)
|
|
166
|
+
- [Pricing](https://reserp.ai/pricing)
|
|
167
|
+
|
|
168
|
+
## License
|
|
169
|
+
|
|
170
|
+
MIT
|
reserp-0.1.0/SECURITY.md
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling>=1.27,<1.32"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "reserp"
|
|
7
|
+
dynamic = ["version"]
|
|
8
|
+
description = "Official Python SDK for the Reserp Google Search API"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
license-files = ["LICENSE"]
|
|
13
|
+
authors = [{ name = "Reserp", email = "no-reply@reserp.ai" }]
|
|
14
|
+
keywords = [
|
|
15
|
+
"reserp",
|
|
16
|
+
"google-search",
|
|
17
|
+
"google-search-api",
|
|
18
|
+
"serp",
|
|
19
|
+
"serp-api",
|
|
20
|
+
"search-api",
|
|
21
|
+
"api-client",
|
|
22
|
+
"sdk",
|
|
23
|
+
"python",
|
|
24
|
+
]
|
|
25
|
+
classifiers = [
|
|
26
|
+
"Development Status :: 4 - Beta",
|
|
27
|
+
"Intended Audience :: Developers",
|
|
28
|
+
"Operating System :: OS Independent",
|
|
29
|
+
"Programming Language :: Python :: 3",
|
|
30
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
31
|
+
"Programming Language :: Python :: 3.10",
|
|
32
|
+
"Programming Language :: Python :: 3.11",
|
|
33
|
+
"Programming Language :: Python :: 3.12",
|
|
34
|
+
"Programming Language :: Python :: 3.13",
|
|
35
|
+
"Programming Language :: Python :: 3.14",
|
|
36
|
+
"Topic :: Internet :: WWW/HTTP",
|
|
37
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
38
|
+
"Typing :: Typed",
|
|
39
|
+
]
|
|
40
|
+
dependencies = ["httpx>=0.27,<1"]
|
|
41
|
+
|
|
42
|
+
[project.optional-dependencies]
|
|
43
|
+
dev = [
|
|
44
|
+
"build>=1.2,<2",
|
|
45
|
+
"mypy>=1.13,<2",
|
|
46
|
+
"pytest>=8.3,<10",
|
|
47
|
+
"ruff>=0.8,<1",
|
|
48
|
+
"twine>=5.1,<7",
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
[project.urls]
|
|
52
|
+
Homepage = "https://reserp.ai"
|
|
53
|
+
Documentation = "https://reserp.ai/docs"
|
|
54
|
+
Repository = "https://github.com/reserp-ai/reserp-python"
|
|
55
|
+
Issues = "https://github.com/reserp-ai/reserp-python/issues"
|
|
56
|
+
Changelog = "https://github.com/reserp-ai/reserp-python/blob/main/CHANGELOG.md"
|
|
57
|
+
|
|
58
|
+
[tool.hatch.version]
|
|
59
|
+
path = "src/reserp/__about__.py"
|
|
60
|
+
|
|
61
|
+
[tool.hatch.build.targets.wheel]
|
|
62
|
+
packages = ["src/reserp"]
|
|
63
|
+
|
|
64
|
+
[tool.ruff]
|
|
65
|
+
target-version = "py310"
|
|
66
|
+
line-length = 100
|
|
67
|
+
src = ["src", "tests"]
|
|
68
|
+
|
|
69
|
+
[tool.ruff.lint]
|
|
70
|
+
select = ["B", "E", "F", "I", "RUF", "SIM", "UP"]
|
|
71
|
+
|
|
72
|
+
[tool.ruff.format]
|
|
73
|
+
quote-style = "double"
|
|
74
|
+
|
|
75
|
+
[tool.mypy]
|
|
76
|
+
python_version = "3.10"
|
|
77
|
+
strict = true
|
|
78
|
+
files = ["src"]
|
|
79
|
+
pretty = true
|
|
80
|
+
|
|
81
|
+
[tool.pytest.ini_options]
|
|
82
|
+
addopts = "-q"
|
|
83
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.0"
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
from .__about__ import __version__
|
|
2
|
+
from .client import AsyncReserp, Reserp
|
|
3
|
+
from .errors import (
|
|
4
|
+
ReserpAPIError,
|
|
5
|
+
ReserpConnectionError,
|
|
6
|
+
ReserpError,
|
|
7
|
+
ReserpTimeoutError,
|
|
8
|
+
ReserpUnexpectedResponseError,
|
|
9
|
+
)
|
|
10
|
+
from .types import (
|
|
11
|
+
ErrorCode,
|
|
12
|
+
ErrorResponse,
|
|
13
|
+
GoogleParameterValue,
|
|
14
|
+
Pagination,
|
|
15
|
+
Result,
|
|
16
|
+
SearchResponse,
|
|
17
|
+
)
|
|
18
|
+
from .urls import build_google_search_url, validate_google_search_url
|
|
19
|
+
|
|
20
|
+
__all__ = [
|
|
21
|
+
"AsyncReserp",
|
|
22
|
+
"ErrorCode",
|
|
23
|
+
"ErrorResponse",
|
|
24
|
+
"GoogleParameterValue",
|
|
25
|
+
"Pagination",
|
|
26
|
+
"Reserp",
|
|
27
|
+
"ReserpAPIError",
|
|
28
|
+
"ReserpConnectionError",
|
|
29
|
+
"ReserpError",
|
|
30
|
+
"ReserpTimeoutError",
|
|
31
|
+
"ReserpUnexpectedResponseError",
|
|
32
|
+
"Result",
|
|
33
|
+
"SearchResponse",
|
|
34
|
+
"__version__",
|
|
35
|
+
"build_google_search_url",
|
|
36
|
+
"validate_google_search_url",
|
|
37
|
+
]
|