Skip to content

Commit 1b92dc5

Browse files
authored
chore(deps): deduplicate dependency group declarations (#5798)
# What does this PR do? This PR deduplicates dependency declarations in `pyproject.toml` by centralizing shared test dependencies into `test-common`, reusing them from `unit` and `test`, and removing `starter` entries already provided by core dependencies. It also updates `dev` to include `unit` and refreshes `uv.lock` to match. ## Test Plan - `uv lock --check` - Result: `Resolved 407 packages in 20ms` - `uv sync --group dev --group type_checking --locked --dry-run` - Result: dry-run completed successfully with a consistent lock resolution. --------- Signed-off-by: Sébastien Han <seb@redhat.com>
1 parent 87ce1b4 commit 1b92dc5

11 files changed

Lines changed: 3479 additions & 2515 deletions

File tree

client-sdks/stainless/openapi.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10669,7 +10669,7 @@ components:
1066910669
file:
1067010670
anyOf:
1067110671
- type: string
10672-
format: binary
10672+
contentMediaType: application/octet-stream
1067310673
- type: 'null'
1067410674
description: The File object to be uploaded and processed. Mutually exclusive with file_id.
1067510675
file_id:
@@ -10694,9 +10694,9 @@ components:
1069410694
properties:
1069510695
file:
1069610696
type: string
10697-
format: binary
1069810697
title: File
1069910698
description: The file to upload.
10699+
format: binary
1070010700
purpose:
1070110701
$ref: '#/components/schemas/OpenAIFileUploadPurpose'
1070210702
description: The intended purpose of the uploaded file.

docs/static/experimental-ogx-spec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6825,7 +6825,7 @@ components:
68256825
file:
68266826
anyOf:
68276827
- type: string
6828-
format: binary
6828+
contentMediaType: application/octet-stream
68296829
- type: 'null'
68306830
description: The File object to be uploaded and processed. Mutually exclusive with file_id.
68316831
file_id:

docs/static/ogx-spec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10221,9 +10221,9 @@ components:
1022110221
properties:
1022210222
file:
1022310223
type: string
10224-
format: binary
1022510224
title: File
1022610225
description: The file to upload.
10226+
format: binary
1022710227
purpose:
1022810228
$ref: '#/components/schemas/OpenAIFileUploadPurpose'
1022910229
description: The intended purpose of the uploaded file.

docs/static/stainless-ogx-spec.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10669,7 +10669,7 @@ components:
1066910669
file:
1067010670
anyOf:
1067110671
- type: string
10672-
format: binary
10672+
contentMediaType: application/octet-stream
1067310673
- type: 'null'
1067410674
description: The File object to be uploaded and processed. Mutually exclusive with file_id.
1067510675
file_id:
@@ -10694,9 +10694,9 @@ components:
1069410694
properties:
1069510695
file:
1069610696
type: string
10697-
format: binary
1069810697
title: File
1069910698
description: The file to upload.
10699+
format: binary
1070010700
purpose:
1070110701
$ref: '#/components/schemas/OpenAIFileUploadPurpose'
1070210702
description: The intended purpose of the uploaded file.

pyproject.toml

Lines changed: 33 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -78,36 +78,30 @@ client = [
7878
]
7979
starter = [
8080
"aiohttp",
81-
"aiosqlite",
8281
"anthropic",
83-
"asyncpg",
8482
"autoevals",
83+
"boto3",
8584
"chardet",
8685
"chromadb-client",
8786
"datasets>=4.0.0",
8887
"einops",
8988
"elasticsearch>=8.16.0,<9.0.0",
9089
"emoji",
9190
"faiss-cpu",
92-
"fastapi",
9391
"fire",
9492
"fireworks-ai<=0.17.16",
9593
"google-genai>=1.69.0",
96-
"httpx",
9794
"langdetect",
95+
"markitdown[all]",
9896
"matplotlib",
99-
"mcp>=1.23.0",
10097
"nltk>=3.9.4",
10198
"numpy",
10299
"ollama",
103-
"opentelemetry-exporter-otlp-proto-http",
104-
"opentelemetry-sdk",
105100
"pandas",
106101
"pillow",
107102
"pgvector>=0.3.0",
108103
"pymilvus[milvus-lite]>=2.4.10",
109104
"pymongo",
110-
"markitdown[all]",
111105
"pypdf>=6.10.2",
112106
"pythainlp",
113107
"qdrant-client",
@@ -116,21 +110,20 @@ starter = [
116110
"safetensors",
117111
"scikit-learn",
118112
"scipy",
113+
"sentence-transformers",
119114
"sentencepiece",
120115
"sqlite-vec",
121116
"together>=2",
122117
"tokenizers",
118+
"torch",
123119
"tqdm",
124120
"tree_sitter",
125-
"uvicorn",
126121
"weaviate-client>=4.16.5",
127-
"torch",
128-
"sentence-transformers",
129-
"boto3",
130122
]
131123

132124
[dependency-groups]
133125
dev = [
126+
{include-group = "unit"},
134127
"pytest>=8.4",
135128
"pytest-timeout",
136129
"pytest-asyncio>=1.0",
@@ -145,15 +138,9 @@ dev = [
145138
"pre-commit>=4.4.0",
146139
"ruamel.yaml", # needed for openapi generator
147140
"openapi-spec-validator>=0.7.2",
148-
"ollama",
149141
"ogx-client>=1.0.0",
150-
"chardet",
151-
"pypdf>=6.10.2",
152-
"together",
153142
"boto3",
154-
"anthropic",
155143
"torch>=2.6.0",
156-
"markitdown[all]",
157144
]
158145
# Type checking dependencies - includes type stubs and optional runtime dependencies
159146
# needed for complete mypy coverage across all optional features
@@ -192,58 +179,53 @@ type_checking = [
192179
"langgraph",
193180
"ogx-client>=1.0.0",
194181
]
195-
# These are the dependencies required for running unit tests.
196-
unit = [
197-
"anthropic",
198-
"databricks-sdk",
199-
"sqlite-vec",
200-
"ollama",
201-
"aiosqlite",
182+
test-common = [
202183
"aiohttp",
184+
"aiosqlite",
203185
"asyncpg>=0.29.0",
186+
"chardet",
187+
"mcp>=1.23.0",
204188
"pgvector>=0.3.0",
205-
"markitdown[all]",
189+
"psycopg2-binary>=2.9.0",
206190
"pypdf>=6.10.2",
207-
"mcp>=1.23.0",
208-
"chardet",
209-
"sqlalchemy",
210191
"sqlalchemy[asyncio]>=2.0.41",
192+
]
193+
# These are the dependencies required for running unit tests.
194+
unit = [
195+
{include-group = "test-common"},
196+
"anthropic",
211197
"blobfile",
212-
"faiss-cpu",
213-
"together",
214198
"coverage",
199+
"databricks-sdk",
200+
"faiss-cpu",
201+
"markitdown[all]",
215202
"moto[s3]>=5.1.10",
203+
"ollama",
204+
"sqlite-vec",
205+
"together",
216206
]
217207
# These are the core dependencies required for running integration tests. They are shared across all
218208
# providers. If a provider requires additional dependencies, please add them to your environment
219209
# separately. If you are using "uv" to execute your tests, you can use the "--group" flag to specify extra
220210
# dependencies.
221211
test = [
222-
"aiosqlite",
223-
"aiohttp",
224-
"torch>=2.6.0",
225-
"torchvision>=0.21.0",
226-
"chardet",
227-
"asyncpg>=0.29.0",
228-
"pgvector>=0.3.0",
229-
"pypdf>=6.10.2",
230-
"mcp>=1.23.0",
231-
"datasets>=4.0.0",
212+
{include-group = "test-common"},
232213
"autoevals",
233-
"transformers",
234-
"sqlalchemy",
235-
"sqlalchemy[asyncio]>=2.0.41",
236-
"requests",
237214
"chromadb>=1.0.15",
238-
"qdrant-client",
239-
"pymilvus>=2.6.2",
240-
"milvus-lite>=2.5.0; platform_machine == 'x86_64' or platform_machine == 'aarch64' or platform_machine == 'arm64'",
241-
"weaviate-client>=4.16.4",
215+
"datasets>=4.0.0",
242216
"elasticsearch>=8.16.0, <9.0.0",
243-
"langchain-openai",
217+
"google-genai>=1.69.0",
244218
"langchain-core",
219+
"langchain-openai",
245220
"langgraph",
246-
"google-genai>=1.69.0",
221+
"milvus-lite>=2.5.0; platform_machine == 'x86_64' or platform_machine == 'aarch64' or platform_machine == 'arm64'",
222+
"pymilvus>=2.6.2",
223+
"qdrant-client",
224+
"requests",
225+
"torch>=2.6.0",
226+
"torchvision>=0.21.0",
227+
"transformers",
228+
"weaviate-client>=4.16.4",
247229
]
248230
docs = [
249231
"setuptools",

scripts/openapi_generator/main.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,16 @@
1616
import yaml
1717
from fastapi.openapi.utils import get_openapi
1818

19-
from . import app, code_samples, multi_sdk, schema_collection, schema_filtering, schema_transforms, state
19+
from . import (
20+
app,
21+
code_samples,
22+
multi_sdk,
23+
multipart_transforms,
24+
schema_collection,
25+
schema_filtering,
26+
schema_transforms,
27+
state,
28+
)
2029

2130

2231
def generate_openapi_spec(output_dir: str) -> dict[str, Any]:
@@ -68,6 +77,9 @@ def generate_openapi_spec(output_dir: str) -> dict[str, Any]:
6877
# FastAPI sometimes infers parameters as query params even when they should be in the request body
6978
openapi_schema = schema_transforms._remove_query_params_from_body_endpoints(openapi_schema)
7079

80+
# Normalize multipart binary fields to preserve backward-compatible schema shape.
81+
openapi_schema = multipart_transforms.normalize_multipart_binary_fields(openapi_schema)
82+
7183
# Promote model fields marked with x-extra-body-field to x-ogx-extra-body-params
7284
openapi_schema = schema_transforms._promote_model_extra_body_fields(openapi_schema)
7385

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# Copyright (c) The OGX Contributors.
2+
# All rights reserved.
3+
#
4+
# This source code is licensed under the terms described in the LICENSE file in
5+
# the root directory of this source tree.
6+
7+
"""OpenAPI transforms related to multipart/form-data request schemas."""
8+
9+
from typing import Any
10+
11+
12+
def normalize_multipart_binary_fields(openapi_schema: dict[str, Any]) -> dict[str, Any]:
13+
"""Normalize multipart binary fields to OpenAPI's ``format: binary`` style.
14+
15+
FastAPI/Pydantic may emit JSON Schema 2020-12 style binary strings as:
16+
``{"type": "string", "contentMediaType": "application/octet-stream"}``.
17+
Our v1 compatibility checks expect OpenAPI's legacy representation:
18+
``{"type": "string", "format": "binary"}``.
19+
20+
Apply this conversion only for multipart/form-data request schemas.
21+
"""
22+
23+
components = openapi_schema.get("components", {}).get("schemas", {})
24+
paths = openapi_schema.get("paths", {})
25+
if not isinstance(paths, dict):
26+
return openapi_schema
27+
28+
ref_prefix = "#/components/schemas/"
29+
30+
for path_item in paths.values():
31+
if not isinstance(path_item, dict):
32+
continue
33+
for method in ("post", "put", "patch"):
34+
operation = path_item.get(method)
35+
if not isinstance(operation, dict):
36+
continue
37+
38+
request_body = operation.get("requestBody", {})
39+
if not isinstance(request_body, dict):
40+
continue
41+
content = request_body.get("content", {})
42+
if not isinstance(content, dict):
43+
continue
44+
45+
multipart = content.get("multipart/form-data")
46+
if not isinstance(multipart, dict):
47+
continue
48+
schema = multipart.get("schema")
49+
if not isinstance(schema, dict):
50+
continue
51+
52+
targets: list[dict[str, Any]] = []
53+
schema_ref = schema.get("$ref")
54+
if isinstance(schema_ref, str) and schema_ref.startswith(ref_prefix):
55+
schema_name = schema_ref[len(ref_prefix) :]
56+
component_schema = components.get(schema_name)
57+
if isinstance(component_schema, dict):
58+
targets.append(component_schema)
59+
else:
60+
targets.append(schema)
61+
62+
for target_schema in targets:
63+
properties = target_schema.get("properties")
64+
if not isinstance(properties, dict):
65+
continue
66+
for field_schema in properties.values():
67+
if not isinstance(field_schema, dict):
68+
continue
69+
if (
70+
field_schema.get("type") == "string"
71+
and field_schema.get("contentMediaType") == "application/octet-stream"
72+
):
73+
field_schema.pop("contentMediaType", None)
74+
field_schema["format"] = "binary"
75+
76+
return openapi_schema

src/ogx/providers/remote/file_processor/docling_serve/docling_serve.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ async def process_file(
7070
content_response = await self.files_api.openai_retrieve_file_content(
7171
RetrieveFileContentRequest(file_id=file_id)
7272
)
73-
content = content_response.body
73+
# Normalize bytes/memoryview payloads to bytes for downstream file handling.
74+
content = bytes(content_response.body)
7475

7576
document_id = file_id if file_id else str(uuid.uuid4())
7677
document_metadata: dict[str, Any] = {"filename": filename}

src/ogx/providers/utils/memory/openai_vector_store_mixin.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1319,7 +1319,7 @@ async def openai_attach_file_to_vector_store(
13191319
content_response = await self.files_api.openai_retrieve_file_content(
13201320
RetrieveFileContentRequest(file_id=file_id)
13211321
)
1322-
full_content = content_from_data_and_mime_type(content_response.body, mime_type)
1322+
full_content = content_from_data_and_mime_type(bytes(content_response.body), mime_type)
13231323
await self._execute_contextual_chunk_transformation(chunks, full_content, chunking_strategy.contextual)
13241324
if not chunks:
13251325
vector_store_file_object.status = "failed"

0 commit comments

Comments
 (0)