Skip to content

Commit 535897f

Browse files
Merge branch 'main' into feat/add-count-filtering-to-OpenSearchDocumentStore
2 parents f400fd8 + 8094d0d commit 535897f

34 files changed

Lines changed: 306 additions & 285 deletions

File tree

.github/workflows/opensearch.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ jobs:
5555
if: matrix.python-version == '3.10' && runner.os == 'Linux'
5656
run: hatch run docs
5757

58-
- name: Run tests
59-
run: hatch run test:cov-retry
58+
- name: Run tests (in parallel, using 4 cores)
59+
run: hatch run test:cov-retry -n 4 # GA runner has 4 cores
6060

6161
- name: Run unit tests with lowest direct dependencies
6262
run: |

integrations/aimlapi/CHANGELOG.md

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,29 @@
11
# Changelog
22

3-
## [unreleased]
3+
## [integrations/aimlapi-v2.0.0] - 2026-01-09
44

55
### 🚀 Features
66

77
- *(aimlapi)* Add AIMLAPI provider integration (#2267)
8+
9+
### 📚 Documentation
10+
11+
- Add pydoc configurations for Docusaurus (#2411)
12+
13+
### ⚙️ CI
14+
15+
- Change pytest command (#2475)
16+
17+
### 🧹 Chores
18+
19+
- AIMLAPI - clean up README (#2356)
20+
- Remove Readme API CI workflow and configs (#2573)
21+
- Make fmt command more forgiving (#2671)
22+
- [**breaking**] Aimlapi - drop Python 3.9 and use X|Y typing (#2684)
23+
24+
### 🌀 Miscellaneous
25+
26+
- Add missing GA workflow for `aimlapi` integration (#2504)
27+
- Enhancement: Adopt PEP 585 type hinting (part 6) (#2532)
28+
29+
<!-- generated by git-cliff -->

integrations/aimlapi/pyproject.toml

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,22 @@ name = "aimlapi-haystack"
77
dynamic = ["version"]
88
description = ''
99
readme = "README.md"
10-
requires-python = ">=3.9"
10+
requires-python = ">=3.10"
1111
license = "Apache-2.0"
1212
keywords = []
1313
authors = [{ name = "Dmitry <D1m7asis> Tumanov", email = "d1m7asis@gmail.com" }]
1414
classifiers = [
1515
"License :: OSI Approved :: Apache Software License",
1616
"Development Status :: 4 - Beta",
1717
"Programming Language :: Python",
18-
"Programming Language :: Python :: 3.9",
1918
"Programming Language :: Python :: 3.10",
2019
"Programming Language :: Python :: 3.11",
2120
"Programming Language :: Python :: 3.12",
2221
"Programming Language :: Python :: 3.13",
2322
"Programming Language :: Python :: Implementation :: CPython",
2423
"Programming Language :: Python :: Implementation :: PyPy",
2524
]
26-
dependencies = ["haystack-ai>=2.19.0"]
25+
dependencies = ["haystack-ai>=2.22.0"]
2726

2827
[project.urls]
2928
Documentation = "https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/aimlapi#readme"
@@ -76,7 +75,6 @@ disallow_incomplete_defs = true
7675

7776

7877
[tool.ruff]
79-
target-version = "py39"
8078
line-length = 120
8179

8280
[tool.ruff.lint]
@@ -123,10 +121,6 @@ ignore = [
123121
"B008",
124122
"S101",
125123
]
126-
unfixable = [
127-
# Don't touch unused imports
128-
"F401",
129-
]
130124

131125
[tool.ruff.lint.isort]
132126
known-first-party = ["haystack_integrations"]

integrations/aimlapi/src/haystack_integrations/components/generators/aimlapi/chat/chat_generator.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#
33
# SPDX-License-Identifier: Apache-2.0
44

5-
from typing import Any, Optional
5+
from typing import Any
66

77
from haystack import component, default_to_dict, logging
88
from haystack.components.generators.chat import OpenAIChatGenerator
@@ -63,14 +63,14 @@ def __init__(
6363
*,
6464
api_key: Secret = Secret.from_env_var("AIMLAPI_API_KEY"),
6565
model: str = "openai/gpt-5-chat-latest",
66-
streaming_callback: Optional[StreamingCallbackT] = None,
67-
api_base_url: Optional[str] = "https://api.aimlapi.com/v1",
68-
generation_kwargs: Optional[dict[str, Any]] = None,
69-
tools: Optional[ToolsType] = None,
70-
timeout: Optional[float] = None,
71-
extra_headers: Optional[dict[str, Any]] = None,
72-
max_retries: Optional[int] = None,
73-
http_client_kwargs: Optional[dict[str, Any]] = None,
66+
streaming_callback: StreamingCallbackT | None = None,
67+
api_base_url: str | None = "https://api.aimlapi.com/v1",
68+
generation_kwargs: dict[str, Any] | None = None,
69+
tools: ToolsType | None = None,
70+
timeout: float | None = None,
71+
extra_headers: dict[str, Any] | None = None,
72+
max_retries: int | None = None,
73+
http_client_kwargs: dict[str, Any] | None = None,
7474
):
7575
"""
7676
Creates an instance of AIMLAPIChatGenerator. Unless specified otherwise,
@@ -155,10 +155,10 @@ def _prepare_api_call(
155155
self,
156156
*,
157157
messages: list[ChatMessage],
158-
streaming_callback: Optional[StreamingCallbackT] = None,
159-
generation_kwargs: Optional[dict[str, Any]] = None,
160-
tools: Optional[ToolsType] = None,
161-
tools_strict: Optional[bool] = None,
158+
streaming_callback: StreamingCallbackT | None = None,
159+
generation_kwargs: dict[str, Any] | None = None,
160+
tools: ToolsType | None = None,
161+
tools_strict: bool | None = None,
162162
) -> dict[str, Any]:
163163
# update generation kwargs by merging with the generation kwargs passed to the run method
164164
generation_kwargs = {**self.generation_kwargs, **(generation_kwargs or {})}

integrations/amazon_bedrock/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# Changelog
22

3+
## [integrations/amazon_bedrock-v6.0.0] - 2026-01-09
4+
5+
### 🧹 Chores
6+
7+
- [**breaking**] Amazon_bedrock - drop Python 3.9 and use X|Y typing (#2685)
8+
9+
310
## [integrations/amazon_bedrock-v5.4.0] - 2026-01-08
411

512
### 🚀 Features

integrations/amazon_bedrock/pyproject.toml

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,22 @@ name = "amazon-bedrock-haystack"
77
dynamic = ["version"]
88
description = 'An integration of AWS S3 and Bedrock as a Downloader and Generator components.'
99
readme = "README.md"
10-
requires-python = ">=3.9"
10+
requires-python = ">=3.10"
1111
license = "Apache-2.0"
1212
keywords = []
1313
authors = [{ name = "deepset GmbH", email = "info@deepset.ai" }]
1414
classifiers = [
1515
"License :: OSI Approved :: Apache Software License",
1616
"Development Status :: 4 - Beta",
1717
"Programming Language :: Python",
18-
"Programming Language :: Python :: 3.9",
1918
"Programming Language :: Python :: 3.10",
2019
"Programming Language :: Python :: 3.11",
2120
"Programming Language :: Python :: 3.12",
2221
"Programming Language :: Python :: 3.13",
2322
"Programming Language :: Python :: Implementation :: CPython",
2423
"Programming Language :: Python :: Implementation :: PyPy",
2524
]
26-
dependencies = ["haystack-ai>=2.19.0", "boto3>=1.28.57", "aioboto3>=14.0.0"]
25+
dependencies = ["haystack-ai>=2.22.0", "boto3>=1.28.57", "aioboto3>=14.0.0"]
2726

2827
[project.urls]
2928
Documentation = "https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/amazon_bedrock#readme"
@@ -92,7 +91,6 @@ module = [
9291
ignore_missing_imports = true
9392

9493
[tool.ruff]
95-
target-version = "py39"
9694
line-length = 120
9795

9896
[tool.ruff.lint]
@@ -140,10 +138,6 @@ ignore = [
140138
"ARG002",
141139
"ARG005",
142140
]
143-
unfixable = [
144-
# Don't touch unused imports
145-
"F401",
146-
]
147141

148142
[tool.ruff.lint.isort]
149143
known-first-party = ["haystack_integrations"]

integrations/amazon_bedrock/src/haystack_integrations/common/amazon_bedrock/utils.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#
33
# SPDX-License-Identifier: Apache-2.0
44

5-
from typing import Any, Optional, Union
5+
from typing import Any
66

77
import aioboto3
88
import boto3
@@ -20,14 +20,14 @@
2020

2121

2222
def get_aws_session(
23-
aws_access_key_id: Optional[str] = None,
24-
aws_secret_access_key: Optional[str] = None,
25-
aws_session_token: Optional[str] = None,
26-
aws_region_name: Optional[str] = None,
27-
aws_profile_name: Optional[str] = None,
23+
aws_access_key_id: str | None = None,
24+
aws_secret_access_key: str | None = None,
25+
aws_session_token: str | None = None,
26+
aws_region_name: str | None = None,
27+
aws_profile_name: str | None = None,
2828
async_mode: bool = False,
2929
**kwargs: Any,
30-
) -> Union[boto3.Session, aioboto3.Session]:
30+
) -> boto3.Session | aioboto3.Session:
3131
"""
3232
Creates an AWS Session with the given parameters.
3333
Checks if the provided AWS credentials are valid and can be used to connect to AWS.

integrations/amazon_bedrock/src/haystack_integrations/common/s3/utils.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
from dataclasses import dataclass
77
from http import HTTPStatus
88
from pathlib import Path
9-
from typing import Optional
109

1110
from boto3.session import Session
1211
from botocore.config import Config
@@ -23,9 +22,9 @@ def __init__(
2322
self,
2423
s3_bucket: str,
2524
session: Session,
26-
s3_prefix: Optional[str] = None,
27-
endpoint_url: Optional[str] = None,
28-
config: Optional[Config] = None,
25+
s3_prefix: str | None = None,
26+
endpoint_url: str | None = None,
27+
config: Config | None = None,
2928
) -> None:
3029
"""
3130
Initializes the S3Storage object with the provided parameters.

integrations/amazon_bedrock/src/haystack_integrations/components/downloaders/s3/s3_downloader.py

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
# SPDX-License-Identifier: Apache-2.0
44

55
import os
6+
from collections.abc import Callable
67
from concurrent.futures import ThreadPoolExecutor
78
from pathlib import Path
8-
from typing import Any, Callable, Optional
9+
from typing import Any
910

1011
from botocore.config import Config
1112
from haystack import component, default_from_dict, default_to_dict, logging
@@ -29,20 +30,20 @@ class S3Downloader:
2930
def __init__(
3031
self,
3132
*,
32-
aws_access_key_id: Optional[Secret] = Secret.from_env_var("AWS_ACCESS_KEY_ID", strict=False), # noqa: B008
33-
aws_secret_access_key: Optional[Secret] = Secret.from_env_var( # noqa: B008
33+
aws_access_key_id: Secret | None = Secret.from_env_var("AWS_ACCESS_KEY_ID", strict=False), # noqa: B008
34+
aws_secret_access_key: Secret | None = Secret.from_env_var( # noqa: B008
3435
"AWS_SECRET_ACCESS_KEY", strict=False
3536
),
36-
aws_session_token: Optional[Secret] = Secret.from_env_var("AWS_SESSION_TOKEN", strict=False), # noqa: B008
37-
aws_region_name: Optional[Secret] = Secret.from_env_var("AWS_DEFAULT_REGION", strict=False), # noqa: B008
38-
aws_profile_name: Optional[Secret] = Secret.from_env_var("AWS_PROFILE", strict=False), # noqa: B008
39-
boto3_config: Optional[dict[str, Any]] = None,
40-
file_root_path: Optional[str] = None,
41-
file_extensions: Optional[list[str]] = None,
37+
aws_session_token: Secret | None = Secret.from_env_var("AWS_SESSION_TOKEN", strict=False), # noqa: B008
38+
aws_region_name: Secret | None = Secret.from_env_var("AWS_DEFAULT_REGION", strict=False), # noqa: B008
39+
aws_profile_name: Secret | None = Secret.from_env_var("AWS_PROFILE", strict=False), # noqa: B008
40+
boto3_config: dict[str, Any] | None = None,
41+
file_root_path: str | None = None,
42+
file_extensions: list[str] | None = None,
4243
file_name_meta_key: str = "file_name",
4344
max_workers: int = 32,
4445
max_cache_size: int = 100,
45-
s3_key_generation_function: Optional[Callable[[Document], str]] = None,
46+
s3_key_generation_function: Callable[[Document], str] | None = None,
4647
) -> None:
4748
"""
4849
Initializes the `S3Downloader` with the provided parameters.
@@ -104,9 +105,9 @@ def __init__(
104105
self.file_name_meta_key = file_name_meta_key
105106
self.s3_key_generation_function = s3_key_generation_function
106107

107-
self._storage: Optional[S3Storage] = None
108+
self._storage: S3Storage | None = None
108109

109-
def resolve_secret(secret: Optional[Secret]) -> Optional[str]:
110+
def resolve_secret(secret: Secret | None) -> str | None:
110111
return secret.resolve_value() if secret else None
111112

112113
self._session = get_aws_session(
@@ -169,7 +170,7 @@ def _filter_documents_by_extensions(self, documents: list[Document]) -> list[Doc
169170
if Path(doc.meta.get(self.file_name_meta_key, "")).suffix.lower() in self.file_extensions
170171
]
171172

172-
def _download_file(self, document: Document) -> Optional[Document]:
173+
def _download_file(self, document: Document) -> Document | None:
173174
"""
174175
Download a single file from AWS S3 Bucket to local filesystem.
175176

integrations/amazon_bedrock/src/haystack_integrations/components/embedders/amazon_bedrock/document_embedder.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import json
2-
from typing import Any, Optional
2+
from typing import Any
33

44
from botocore.config import Config
55
from botocore.exceptions import ClientError
@@ -50,18 +50,18 @@ class AmazonBedrockDocumentEmbedder:
5050
def __init__(
5151
self,
5252
model: str,
53-
aws_access_key_id: Optional[Secret] = Secret.from_env_var("AWS_ACCESS_KEY_ID", strict=False), # noqa: B008
54-
aws_secret_access_key: Optional[Secret] = Secret.from_env_var( # noqa: B008
53+
aws_access_key_id: Secret | None = Secret.from_env_var("AWS_ACCESS_KEY_ID", strict=False), # noqa: B008
54+
aws_secret_access_key: Secret | None = Secret.from_env_var( # noqa: B008
5555
"AWS_SECRET_ACCESS_KEY", strict=False
5656
),
57-
aws_session_token: Optional[Secret] = Secret.from_env_var("AWS_SESSION_TOKEN", strict=False), # noqa: B008
58-
aws_region_name: Optional[Secret] = Secret.from_env_var("AWS_DEFAULT_REGION", strict=False), # noqa: B008
59-
aws_profile_name: Optional[Secret] = Secret.from_env_var("AWS_PROFILE", strict=False), # noqa: B008
57+
aws_session_token: Secret | None = Secret.from_env_var("AWS_SESSION_TOKEN", strict=False), # noqa: B008
58+
aws_region_name: Secret | None = Secret.from_env_var("AWS_DEFAULT_REGION", strict=False), # noqa: B008
59+
aws_profile_name: Secret | None = Secret.from_env_var("AWS_PROFILE", strict=False), # noqa: B008
6060
batch_size: int = 32,
6161
progress_bar: bool = True,
62-
meta_fields_to_embed: Optional[list[str]] = None,
62+
meta_fields_to_embed: list[str] | None = None,
6363
embedding_separator: str = "\n",
64-
boto3_config: Optional[dict[str, Any]] = None,
64+
boto3_config: dict[str, Any] | None = None,
6565
**kwargs: Any,
6666
) -> None:
6767
"""
@@ -115,7 +115,7 @@ def __init__(
115115
self.boto3_config = boto3_config
116116
self.kwargs = kwargs
117117

118-
def resolve_secret(secret: Optional[Secret]) -> Optional[str]:
118+
def resolve_secret(secret: Secret | None) -> str | None:
119119
return secret.resolve_value() if secret else None
120120

121121
try:
@@ -186,7 +186,7 @@ def _embed_cohere(self, documents: list[Document]) -> list[Document]:
186186
)
187187
all_embeddings.extend(embeddings_list)
188188

189-
for doc, emb in zip(documents, all_embeddings):
189+
for doc, emb in zip(documents, all_embeddings, strict=True):
190190
doc.embedding = emb
191191

192192
return documents
@@ -214,7 +214,7 @@ def _embed_titan(self, documents: list[Document]) -> list[Document]:
214214
embedding = response_body["embedding"]
215215
all_embeddings.append(embedding)
216216

217-
for doc, emb in zip(documents, all_embeddings):
217+
for doc, emb in zip(documents, all_embeddings, strict=True):
218218
doc.embedding = emb
219219

220220
return documents

0 commit comments

Comments
 (0)