unique-search-proxy 0.2.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.
Files changed (24) hide show
  1. unique_search_proxy-0.2.0/PKG-INFO +315 -0
  2. unique_search_proxy-0.2.0/README.md +297 -0
  3. unique_search_proxy-0.2.0/pyproject.toml +60 -0
  4. unique_search_proxy-0.2.0/unique_search_proxy/__init__.py +0 -0
  5. unique_search_proxy-0.2.0/unique_search_proxy/web/__init__.py +0 -0
  6. unique_search_proxy-0.2.0/unique_search_proxy/web/app.py +116 -0
  7. unique_search_proxy-0.2.0/unique_search_proxy/web/core/__init__.py +30 -0
  8. unique_search_proxy-0.2.0/unique_search_proxy/web/core/google_search/__init__.py +6 -0
  9. unique_search_proxy-0.2.0/unique_search_proxy/web/core/google_search/exceptions.py +26 -0
  10. unique_search_proxy-0.2.0/unique_search_proxy/web/core/google_search/schema.py +21 -0
  11. unique_search_proxy-0.2.0/unique_search_proxy/web/core/google_search/search.py +110 -0
  12. unique_search_proxy-0.2.0/unique_search_proxy/web/core/google_search/settings.py +15 -0
  13. unique_search_proxy-0.2.0/unique_search_proxy/web/core/schema.py +59 -0
  14. unique_search_proxy-0.2.0/unique_search_proxy/web/core/vertexai/__init__.py +6 -0
  15. unique_search_proxy-0.2.0/unique_search_proxy/web/core/vertexai/client.py +34 -0
  16. unique_search_proxy-0.2.0/unique_search_proxy/web/core/vertexai/config.py +39 -0
  17. unique_search_proxy-0.2.0/unique_search_proxy/web/core/vertexai/exceptions.py +25 -0
  18. unique_search_proxy-0.2.0/unique_search_proxy/web/core/vertexai/gemini.py +24 -0
  19. unique_search_proxy-0.2.0/unique_search_proxy/web/core/vertexai/helpers.py +25 -0
  20. unique_search_proxy-0.2.0/unique_search_proxy/web/core/vertexai/prompts.py +28 -0
  21. unique_search_proxy-0.2.0/unique_search_proxy/web/core/vertexai/response_handler.py +87 -0
  22. unique_search_proxy-0.2.0/unique_search_proxy/web/core/vertexai/search.py +96 -0
  23. unique_search_proxy-0.2.0/unique_search_proxy/web/core/vertexai/settings.py +13 -0
  24. unique_search_proxy-0.2.0/unique_search_proxy/web/settings.py +6 -0
@@ -0,0 +1,315 @@
1
+ Metadata-Version: 2.3
2
+ Name: unique-search-proxy
3
+ Version: 0.2.0
4
+ Summary: Web Search Proxy implementation
5
+ Author: ThePhilAz
6
+ Author-email: ThePhilAz <rami.azouz@philico.com>
7
+ Requires-Dist: fastapi>=0.115.0,<1.0.0
8
+ Requires-Dist: uvicorn[standard]>=0.32.0,<1.0.0
9
+ Requires-Dist: google-cloud-aiplatform>=1.128.0,<2.0.0
10
+ Requires-Dist: google-auth>=2.43.0,<3.0.0
11
+ Requires-Dist: google-generativeai>=0.8.5,<0.9.0
12
+ Requires-Dist: pydantic>=2.12.5,<3.0.0
13
+ Requires-Dist: httpx>=0.28.0,<0.29.0
14
+ Requires-Dist: python-dotenv>=1.2.1,<2.0.0
15
+ Requires-Dist: pydantic-settings>=2.12.0,<3.0.0
16
+ Requires-Python: >=3.12
17
+ Description-Content-Type: text/markdown
18
+
19
+ # Unique Search Proxy
20
+
21
+ A unified web search proxy API that provides a consistent interface for multiple search backends. Built with FastAPI and designed for seamless integration with AI applications.
22
+
23
+ ## Overview
24
+
25
+ This service acts as an abstraction layer over different search providers, allowing clients to switch between search engines without changing their integration code. Currently supports:
26
+
27
+ | Engine | Description |
28
+ |--------|-------------|
29
+ | **Google Custom Search** | Direct integration with Google's Custom Search JSON API |
30
+ | **Vertex AI (Gemini)** | AI-powered search using Google's Gemini models with grounding capabilities |
31
+
32
+ ## Quick Start
33
+
34
+ ### Prerequisites
35
+
36
+ - Python 3.12+
37
+ - uv for dependency management
38
+ - Google Cloud credentials (for Vertex AI)
39
+ - Google Custom Search API key and Engine ID (for Google Search)
40
+
41
+ ### Installation
42
+
43
+ ```bash
44
+ # Install dependencies
45
+ uv sync
46
+
47
+ # Copy and configure environment variables
48
+ cp .env.example .env
49
+ ```
50
+
51
+ ### Environment Variables
52
+
53
+ ```bash
54
+ # Google Custom Search
55
+ GOOGLE_SEARCH_API_KEY=your-api-key
56
+ GOOGLE_SEARCH_API_ENDPOINT=https://www.googleapis.com/customsearch/v1
57
+ GOOGLE_SEARCH_ENGINE_ID=your-engine-id
58
+
59
+ # Vertex AI
60
+ VERTEXAI_SERVICE_ACCOUNT_CREDENTIALS=path/to/credentials.json
61
+ ```
62
+
63
+ ### Running the Service
64
+
65
+ **Development:**
66
+ ```bash
67
+ uv run python -m unique_search_proxy.web.app
68
+ ```
69
+
70
+ **Docker (from published package — hash-verified):**
71
+
72
+ CI generates a hash-pinned `requirements.txt` from `uv.lock` and passes it into the
73
+ Docker build. Dependencies are installed with `--require-hashes`, then the package
74
+ itself is installed with `--no-deps`. To reproduce locally:
75
+
76
+ ```bash
77
+ uv export --locked --package unique-search-proxy --no-dev --no-emit-project \
78
+ -o deploy/requirements.txt
79
+ docker build --build-arg PACKAGE_VERSION=0.2.0 -t search-proxy deploy/
80
+ ```
81
+
82
+ Every transitive dependency is verified against its sha256 hash from the lockfile.
83
+
84
+ **Docker (from local source — no registry required):**
85
+
86
+ Build a wheel first, copy it into `deploy/`, then reference it:
87
+
88
+ ```bash
89
+ uv build --wheel --out-dir deploy/
90
+ docker build \
91
+ --build-arg LOCAL_WHEEL=unique_search_proxy-0.2.0-py3-none-any.whl \
92
+ -t search-proxy deploy/
93
+ ```
94
+
95
+ **Running the container:**
96
+
97
+ ```bash
98
+ docker run --rm -p 8080:8080 search-proxy
99
+
100
+ # With custom environment variables
101
+ docker run --rm -p 8080:8080 -e WORKERS=8 -e LOG_LEVEL=debug search-proxy
102
+ ```
103
+
104
+ ## API Documentation
105
+
106
+ FastAPI provides automatic interactive API documentation:
107
+
108
+ | URL | Description |
109
+ |-----|-------------|
110
+ | `/docs` | Swagger UI - interactive API explorer |
111
+ | `/redoc` | ReDoc - alternative documentation |
112
+ | `/openapi.json` | OpenAPI schema |
113
+
114
+ ## API Reference
115
+
116
+ ### Health Check
117
+
118
+ ```http
119
+ GET /health
120
+ ```
121
+
122
+ **Response:**
123
+ ```json
124
+ {
125
+ "status": "healthy"
126
+ }
127
+ ```
128
+
129
+ ---
130
+
131
+ ### Search
132
+
133
+ ```http
134
+ POST /search
135
+ Content-Type: application/json
136
+ ```
137
+
138
+ **Request Body:**
139
+
140
+ | Field | Type | Required | Description |
141
+ |-------|------|----------|-------------|
142
+ | `search_engine` | string | No | `"google"` or `"vertexai"` (default: `"google"`) |
143
+ | `query` | string | Yes | The search query |
144
+ | `kwargs` | object | No | Engine-specific parameters |
145
+
146
+ **Response:**
147
+ ```json
148
+ {
149
+ "results": [
150
+ {
151
+ "url": "https://example.com/article",
152
+ "title": "Article Title",
153
+ "snippet": "A brief description of the content...",
154
+ "content": ""
155
+ }
156
+ ]
157
+ }
158
+ ```
159
+
160
+ ---
161
+
162
+ ## Search Engine Configuration
163
+
164
+ ### Google Custom Search
165
+
166
+ Uses Google's Custom Search JSON API for traditional web search results.
167
+
168
+ **Parameters (`kwargs`):**
169
+
170
+ | Parameter | Type | Default | Description |
171
+ |-----------|------|---------|-------------|
172
+ | `cx` | string | env default | Custom Search Engine ID (overrides env) |
173
+ | `fetchSize` | int | 10 | Number of results to fetch |
174
+ | `timeout` | int | 10 | Request timeout in seconds |
175
+
176
+ **Example:**
177
+ ```json
178
+ {
179
+ "search_engine": "google",
180
+ "query": "latest AI developments",
181
+ "kwargs": {
182
+ "fetchSize": 20,
183
+ "timeout": 15
184
+ }
185
+ }
186
+ ```
187
+
188
+ ---
189
+
190
+ ### Vertex AI (Gemini)
191
+
192
+ Leverages Google's Gemini models with web grounding for AI-enhanced search results. This engine:
193
+
194
+ 1. Uses Gemini to search and synthesize information from the web
195
+ 2. Generates structured results with citations
196
+ 3. Optionally resolves shortened/redirect URLs to final destinations
197
+
198
+ **Parameters (`kwargs`):**
199
+
200
+ | Parameter | Type | Default | Description |
201
+ |-----------|------|---------|-------------|
202
+ | `modelName` | string | `"gemini-2.5-flash"` | Gemini model to use |
203
+ | `entrepriseSearch` | bool | `false` | Use Enterprise Web Search |
204
+ | `systemInstruction` | string | (built-in) | Custom system prompt |
205
+ | `resolveUrls` | bool | `true` | Resolve redirect URLs |
206
+
207
+ **Example:**
208
+ ```json
209
+ {
210
+ "search_engine": "vertexai",
211
+ "query": "Compare the top 3 cloud providers for ML workloads",
212
+ "kwargs": {
213
+ "modelName": "gemini-2.5-flash",
214
+ "resolveUrls": true
215
+ }
216
+ }
217
+ ```
218
+
219
+ ---
220
+
221
+ ## Project Structure
222
+
223
+ ```
224
+ connectors/unique_search_proxy/
225
+ ├── unique_search_proxy/ # Python package (published to PyPI)
226
+ │ ├── __init__.py
227
+ │ └── web/ # Web search API sub-module
228
+ │ ├── __init__.py
229
+ │ ├── app.py # FastAPI application
230
+ │ ├── settings.py # Global settings
231
+ │ └── core/ # Search engine implementations
232
+ │ ├── schema.py # Shared schemas
233
+ │ ├── google_search/ # Google Custom Search backend
234
+ │ └── vertexai/ # Vertex AI (Gemini) backend
235
+ ├── tests/ # Test suite
236
+ ├── deploy/ # Container build artifacts
237
+ │ ├── Dockerfile # Hash-verified install or local wheel
238
+ │ └── entrypoint.sh
239
+ └── pyproject.toml
240
+ ```
241
+
242
+ The package uses a sub-module hierarchy (`web/`) to support future extensions (e.g. `internal/` search) that can be deployed as separate containers from the same package.
243
+
244
+ ## Architecture
245
+
246
+ ```
247
+ ┌─────────────────────────────────────────────────────────────┐
248
+ │ FastAPI App │
249
+ │ /search endpoint │
250
+ └─────────────────────────┬───────────────────────────────────┘
251
+
252
+ ┌─────▼─────┐
253
+ │ Factory │
254
+ └─────┬─────┘
255
+
256
+ ┌───────────────┼───────────────┐
257
+ │ │
258
+ ┌─────▼─────┐ ┌─────▼─────┐
259
+ │ Google │ │ Vertex AI │
260
+ │ Search │ │ (Gemini) │
261
+ └───────────┘ └───────────┘
262
+ ```
263
+
264
+ The service uses a **factory pattern** to register and resolve search engines, making it easy to add new backends.
265
+
266
+ ## Error Handling
267
+
268
+ All errors return a consistent format:
269
+
270
+ ```json
271
+ {
272
+ "status": "failed",
273
+ "error": "Error description"
274
+ }
275
+ ```
276
+
277
+ | Status Code | Description |
278
+ |-------------|-------------|
279
+ | 400 | Validation error (invalid request) |
280
+ | 500 | Internal server error |
281
+
282
+ ## Production Deployment
283
+
284
+ The service includes a production-ready `deploy/entrypoint.sh` that uses Uvicorn:
285
+
286
+ | Variable | Default | Description |
287
+ |----------|---------|-------------|
288
+ | `HOST` | `0.0.0.0` | Bind address |
289
+ | `PORT` | `8080` | Listen port |
290
+ | `WORKERS` | `4` | Uvicorn workers |
291
+ | `TIMEOUT` | `120` | Keep-alive timeout |
292
+ | `LOG_LEVEL` | `info` | Logging verbosity |
293
+
294
+ ## Development
295
+
296
+ ```bash
297
+ # Run with hot reload
298
+ uv run uvicorn unique_search_proxy.web.app:app --reload --port 2349
299
+
300
+ # Format code
301
+ uv run ruff format .
302
+
303
+ # Lint
304
+ uv run ruff check .
305
+
306
+ # Run tests
307
+ uv run pytest
308
+
309
+ # Type check
310
+ uv run basedpyright
311
+ ```
312
+
313
+ ## License
314
+
315
+ Proprietary - Unique AG
@@ -0,0 +1,297 @@
1
+ # Unique Search Proxy
2
+
3
+ A unified web search proxy API that provides a consistent interface for multiple search backends. Built with FastAPI and designed for seamless integration with AI applications.
4
+
5
+ ## Overview
6
+
7
+ This service acts as an abstraction layer over different search providers, allowing clients to switch between search engines without changing their integration code. Currently supports:
8
+
9
+ | Engine | Description |
10
+ |--------|-------------|
11
+ | **Google Custom Search** | Direct integration with Google's Custom Search JSON API |
12
+ | **Vertex AI (Gemini)** | AI-powered search using Google's Gemini models with grounding capabilities |
13
+
14
+ ## Quick Start
15
+
16
+ ### Prerequisites
17
+
18
+ - Python 3.12+
19
+ - uv for dependency management
20
+ - Google Cloud credentials (for Vertex AI)
21
+ - Google Custom Search API key and Engine ID (for Google Search)
22
+
23
+ ### Installation
24
+
25
+ ```bash
26
+ # Install dependencies
27
+ uv sync
28
+
29
+ # Copy and configure environment variables
30
+ cp .env.example .env
31
+ ```
32
+
33
+ ### Environment Variables
34
+
35
+ ```bash
36
+ # Google Custom Search
37
+ GOOGLE_SEARCH_API_KEY=your-api-key
38
+ GOOGLE_SEARCH_API_ENDPOINT=https://www.googleapis.com/customsearch/v1
39
+ GOOGLE_SEARCH_ENGINE_ID=your-engine-id
40
+
41
+ # Vertex AI
42
+ VERTEXAI_SERVICE_ACCOUNT_CREDENTIALS=path/to/credentials.json
43
+ ```
44
+
45
+ ### Running the Service
46
+
47
+ **Development:**
48
+ ```bash
49
+ uv run python -m unique_search_proxy.web.app
50
+ ```
51
+
52
+ **Docker (from published package — hash-verified):**
53
+
54
+ CI generates a hash-pinned `requirements.txt` from `uv.lock` and passes it into the
55
+ Docker build. Dependencies are installed with `--require-hashes`, then the package
56
+ itself is installed with `--no-deps`. To reproduce locally:
57
+
58
+ ```bash
59
+ uv export --locked --package unique-search-proxy --no-dev --no-emit-project \
60
+ -o deploy/requirements.txt
61
+ docker build --build-arg PACKAGE_VERSION=0.2.0 -t search-proxy deploy/
62
+ ```
63
+
64
+ Every transitive dependency is verified against its sha256 hash from the lockfile.
65
+
66
+ **Docker (from local source — no registry required):**
67
+
68
+ Build a wheel first, copy it into `deploy/`, then reference it:
69
+
70
+ ```bash
71
+ uv build --wheel --out-dir deploy/
72
+ docker build \
73
+ --build-arg LOCAL_WHEEL=unique_search_proxy-0.2.0-py3-none-any.whl \
74
+ -t search-proxy deploy/
75
+ ```
76
+
77
+ **Running the container:**
78
+
79
+ ```bash
80
+ docker run --rm -p 8080:8080 search-proxy
81
+
82
+ # With custom environment variables
83
+ docker run --rm -p 8080:8080 -e WORKERS=8 -e LOG_LEVEL=debug search-proxy
84
+ ```
85
+
86
+ ## API Documentation
87
+
88
+ FastAPI provides automatic interactive API documentation:
89
+
90
+ | URL | Description |
91
+ |-----|-------------|
92
+ | `/docs` | Swagger UI - interactive API explorer |
93
+ | `/redoc` | ReDoc - alternative documentation |
94
+ | `/openapi.json` | OpenAPI schema |
95
+
96
+ ## API Reference
97
+
98
+ ### Health Check
99
+
100
+ ```http
101
+ GET /health
102
+ ```
103
+
104
+ **Response:**
105
+ ```json
106
+ {
107
+ "status": "healthy"
108
+ }
109
+ ```
110
+
111
+ ---
112
+
113
+ ### Search
114
+
115
+ ```http
116
+ POST /search
117
+ Content-Type: application/json
118
+ ```
119
+
120
+ **Request Body:**
121
+
122
+ | Field | Type | Required | Description |
123
+ |-------|------|----------|-------------|
124
+ | `search_engine` | string | No | `"google"` or `"vertexai"` (default: `"google"`) |
125
+ | `query` | string | Yes | The search query |
126
+ | `kwargs` | object | No | Engine-specific parameters |
127
+
128
+ **Response:**
129
+ ```json
130
+ {
131
+ "results": [
132
+ {
133
+ "url": "https://example.com/article",
134
+ "title": "Article Title",
135
+ "snippet": "A brief description of the content...",
136
+ "content": ""
137
+ }
138
+ ]
139
+ }
140
+ ```
141
+
142
+ ---
143
+
144
+ ## Search Engine Configuration
145
+
146
+ ### Google Custom Search
147
+
148
+ Uses Google's Custom Search JSON API for traditional web search results.
149
+
150
+ **Parameters (`kwargs`):**
151
+
152
+ | Parameter | Type | Default | Description |
153
+ |-----------|------|---------|-------------|
154
+ | `cx` | string | env default | Custom Search Engine ID (overrides env) |
155
+ | `fetchSize` | int | 10 | Number of results to fetch |
156
+ | `timeout` | int | 10 | Request timeout in seconds |
157
+
158
+ **Example:**
159
+ ```json
160
+ {
161
+ "search_engine": "google",
162
+ "query": "latest AI developments",
163
+ "kwargs": {
164
+ "fetchSize": 20,
165
+ "timeout": 15
166
+ }
167
+ }
168
+ ```
169
+
170
+ ---
171
+
172
+ ### Vertex AI (Gemini)
173
+
174
+ Leverages Google's Gemini models with web grounding for AI-enhanced search results. This engine:
175
+
176
+ 1. Uses Gemini to search and synthesize information from the web
177
+ 2. Generates structured results with citations
178
+ 3. Optionally resolves shortened/redirect URLs to final destinations
179
+
180
+ **Parameters (`kwargs`):**
181
+
182
+ | Parameter | Type | Default | Description |
183
+ |-----------|------|---------|-------------|
184
+ | `modelName` | string | `"gemini-2.5-flash"` | Gemini model to use |
185
+ | `entrepriseSearch` | bool | `false` | Use Enterprise Web Search |
186
+ | `systemInstruction` | string | (built-in) | Custom system prompt |
187
+ | `resolveUrls` | bool | `true` | Resolve redirect URLs |
188
+
189
+ **Example:**
190
+ ```json
191
+ {
192
+ "search_engine": "vertexai",
193
+ "query": "Compare the top 3 cloud providers for ML workloads",
194
+ "kwargs": {
195
+ "modelName": "gemini-2.5-flash",
196
+ "resolveUrls": true
197
+ }
198
+ }
199
+ ```
200
+
201
+ ---
202
+
203
+ ## Project Structure
204
+
205
+ ```
206
+ connectors/unique_search_proxy/
207
+ ├── unique_search_proxy/ # Python package (published to PyPI)
208
+ │ ├── __init__.py
209
+ │ └── web/ # Web search API sub-module
210
+ │ ├── __init__.py
211
+ │ ├── app.py # FastAPI application
212
+ │ ├── settings.py # Global settings
213
+ │ └── core/ # Search engine implementations
214
+ │ ├── schema.py # Shared schemas
215
+ │ ├── google_search/ # Google Custom Search backend
216
+ │ └── vertexai/ # Vertex AI (Gemini) backend
217
+ ├── tests/ # Test suite
218
+ ├── deploy/ # Container build artifacts
219
+ │ ├── Dockerfile # Hash-verified install or local wheel
220
+ │ └── entrypoint.sh
221
+ └── pyproject.toml
222
+ ```
223
+
224
+ The package uses a sub-module hierarchy (`web/`) to support future extensions (e.g. `internal/` search) that can be deployed as separate containers from the same package.
225
+
226
+ ## Architecture
227
+
228
+ ```
229
+ ┌─────────────────────────────────────────────────────────────┐
230
+ │ FastAPI App │
231
+ │ /search endpoint │
232
+ └─────────────────────────┬───────────────────────────────────┘
233
+
234
+ ┌─────▼─────┐
235
+ │ Factory │
236
+ └─────┬─────┘
237
+
238
+ ┌───────────────┼───────────────┐
239
+ │ │
240
+ ┌─────▼─────┐ ┌─────▼─────┐
241
+ │ Google │ │ Vertex AI │
242
+ │ Search │ │ (Gemini) │
243
+ └───────────┘ └───────────┘
244
+ ```
245
+
246
+ The service uses a **factory pattern** to register and resolve search engines, making it easy to add new backends.
247
+
248
+ ## Error Handling
249
+
250
+ All errors return a consistent format:
251
+
252
+ ```json
253
+ {
254
+ "status": "failed",
255
+ "error": "Error description"
256
+ }
257
+ ```
258
+
259
+ | Status Code | Description |
260
+ |-------------|-------------|
261
+ | 400 | Validation error (invalid request) |
262
+ | 500 | Internal server error |
263
+
264
+ ## Production Deployment
265
+
266
+ The service includes a production-ready `deploy/entrypoint.sh` that uses Uvicorn:
267
+
268
+ | Variable | Default | Description |
269
+ |----------|---------|-------------|
270
+ | `HOST` | `0.0.0.0` | Bind address |
271
+ | `PORT` | `8080` | Listen port |
272
+ | `WORKERS` | `4` | Uvicorn workers |
273
+ | `TIMEOUT` | `120` | Keep-alive timeout |
274
+ | `LOG_LEVEL` | `info` | Logging verbosity |
275
+
276
+ ## Development
277
+
278
+ ```bash
279
+ # Run with hot reload
280
+ uv run uvicorn unique_search_proxy.web.app:app --reload --port 2349
281
+
282
+ # Format code
283
+ uv run ruff format .
284
+
285
+ # Lint
286
+ uv run ruff check .
287
+
288
+ # Run tests
289
+ uv run pytest
290
+
291
+ # Type check
292
+ uv run basedpyright
293
+ ```
294
+
295
+ ## License
296
+
297
+ Proprietary - Unique AG
@@ -0,0 +1,60 @@
1
+ [project]
2
+ name = "unique-search-proxy"
3
+ version = "0.2.0"
4
+ description = "Web Search Proxy implementation"
5
+ authors = [{ name = "ThePhilAz", email = "rami.azouz@philico.com" }]
6
+ readme = "README.md"
7
+ requires-python = ">=3.12"
8
+ dependencies = [
9
+ "fastapi>=0.115.0,<1.0.0",
10
+ "uvicorn[standard]>=0.32.0,<1.0.0",
11
+ "google-cloud-aiplatform>=1.128.0,<2.0.0",
12
+ "google-auth>=2.43.0,<3.0.0",
13
+ "google-generativeai>=0.8.5,<0.9.0",
14
+ "pydantic>=2.12.5,<3.0.0",
15
+ "httpx>=0.28.0,<0.29.0",
16
+ "python-dotenv>=1.2.1,<2.0.0",
17
+ "pydantic-settings>=2.12.0,<3.0.0"
18
+ ]
19
+
20
+ [dependency-groups]
21
+ dev = []
22
+
23
+ [build-system]
24
+ requires = ["uv_build>=0.7.19,<0.8"]
25
+ build-backend = "uv_build"
26
+
27
+ [tool.uv.build-backend]
28
+ module-root = "."
29
+
30
+ [tool.uv]
31
+ exclude-newer = "2 weeks"
32
+
33
+ [tool.ruff]
34
+ target-version = "py312"
35
+
36
+ [tool.ruff.lint]
37
+ extend-select = ["I"]
38
+
39
+ [tool.basedpyright]
40
+ typeCheckingMode = "standard"
41
+ include = ["unique_search_proxy"]
42
+
43
+ [tool.deptry]
44
+ known_first_party = ["unique_search_proxy"]
45
+
46
+ [tool.poe.tasks]
47
+ lint = "ruff check ."
48
+ lint-fix = "ruff check . --fix"
49
+ format = "ruff format ."
50
+ test = "pytest"
51
+ typecheck = "basedpyright"
52
+ depcheck = "deptry ."
53
+
54
+ [tool.pytest.ini_options]
55
+ asyncio_mode = "auto"
56
+ addopts = "--strict-markers --import-mode=importlib --cov=unique_search_proxy --cov-report=xml --cov-report=term-missing"
57
+ markers = [
58
+ "ai: AI-authored test",
59
+ ]
60
+