Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,11 @@ def run(self, documents: List[Document]):
return {"documents": documents}

def _detect_language(self, document: Document) -> Optional[str]:
language = None
try:
language = langdetect.detect(document.content)
except langdetect.LangDetectException:
logger.warning(
"Langdetect cannot detect the language of Document with id: {document_id}", document_id=document.id
)
language = None
return language
14 changes: 6 additions & 8 deletions haystack/components/connectors/openapi_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -377,9 +377,8 @@ def _invoke_method(self, openapi_service: "OpenAPI", method_invocation_descripto
param_value = invocation_arguments.get(param_name)
if param_value:
method_call_params["parameters"][param_name] = param_value
else:
if param.get("required", False):
raise ValueError(f"Missing parameter: '{param_name}' required for the '{name}' operation.")
elif param.get("required", False):
raise ValueError(f"Missing parameter: '{param_name}' required for the '{name}' operation.")

# Pack request body parameters under "data" key
if request_body:
Expand All @@ -389,10 +388,9 @@ def _invoke_method(self, openapi_service: "OpenAPI", method_invocation_descripto
param_value = invocation_arguments.get(param_name)
if param_value:
method_call_params["data"][param_name] = param_value
else:
if param_name in required_params:
raise ValueError(
f"Missing requestBody parameter: '{param_name}' required for the '{name}' operation."
)
elif param_name in required_params:
raise ValueError(
f"Missing requestBody parameter: '{param_name}' required for the '{name}' operation."
)
# call the underlying service REST API with the parameters
return method_to_call(**method_call_params, raw_response=True)
2 changes: 1 addition & 1 deletion haystack/components/evaluators/llm_evaluator.py
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ def validate_input_parameters(expected: Dict[str, Any], received: Dict[str, Any]
If the received inputs are not lists or have different lengths
"""
# Validate that all expected inputs are present in the received inputs
for param in expected.keys():
for param in expected:
if param not in received:
msg = f"LLM evaluator expected input parameter '{param}' but received only {received.keys()}."
raise ValueError(msg)
Expand Down
2 changes: 2 additions & 0 deletions haystack/components/extractors/llm_metadata_extractor.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,8 @@ def from_dict(cls, data: Dict[str, Any]) -> "LLMMetadataExtractor":
return default_from_dict(cls, data)

def _extract_metadata(self, llm_answer: str) -> Dict[str, Any]:
parsed_metadata: Dict[str, Any] = {}

try:
parsed_metadata = json.loads(llm_answer)
except json.JSONDecodeError as e:
Expand Down
2 changes: 1 addition & 1 deletion haystack/components/routers/text_language_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,11 @@ def run(self, text: str) -> Dict[str, str]:
return output

def _detect_language(self, text: str) -> Optional[str]:
language = None
try:
language = langdetect.detect(text)
except langdetect.LangDetectException as exception:
logger.warning("Langdetect cannot detect the language of text. Error: {error}", error=exception)
# Only log the text in debug mode, as it might contain sensitive information
logger.debug("Langdetect cannot detect the language of text: {text}", text=text)
language = None
return language
8 changes: 5 additions & 3 deletions haystack/core/serialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import inspect
from collections.abc import Callable
from dataclasses import dataclass
from typing import Any, Dict, Iterable, Optional, Type
from typing import Any, Dict, Iterable, Optional, Type, TypeVar

from haystack import logging
from haystack.core.component.component import _hook_component_init
Expand All @@ -14,6 +14,8 @@

logger = logging.getLogger(__name__)

T = TypeVar("T")


@dataclass(frozen=True)
class DeserializationCallbacks:
Expand Down Expand Up @@ -100,7 +102,7 @@ def check_iterable(l: Iterable[Any]) -> None:
check_dict(v)

def check_dict(d: Dict[str, Any]) -> None:
if any(not isinstance(k, str) for k in data.keys()):
if any(not isinstance(k, str) for k in data):
raise SerializationError(
f"Component '{name}' of type '{type(component).__name__}' has a non-string key in the serialized data."
)
Expand Down Expand Up @@ -210,7 +212,7 @@ def to_dict(self):
return {"type": generate_qualified_class_name(type(obj)), "init_parameters": init_parameters}


def default_from_dict(cls: Type[object], data: Dict[str, Any]) -> Any:
def default_from_dict(cls: Type[T], data: Dict[str, Any]) -> T:
"""
Utility function to deserialize a dictionary to an object.

Expand Down
1 change: 1 addition & 0 deletions haystack/tools/component_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,7 @@ def _create_tool_parameters_schema(self, component: Component, inputs_from_state
resolved_type = _resolve_type(input_type)
fields[input_name] = (resolved_type, Field(default=default, description=description))

parameters_schema: Dict[str, Any] = {}
try:
model = create_model(component.run.__name__, __doc__=component_run_description, **fields)
parameters_schema = model.model_json_schema()
Expand Down
2 changes: 1 addition & 1 deletion haystack/utils/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def to_dict(self) -> Dict[str, Any]:
"""
out = {"type": self.type.value}
inner = self._to_dict()
assert all(k not in inner for k in out.keys())
assert all(k not in inner for k in out)
out.update(inner)
return out

Expand Down
24 changes: 10 additions & 14 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -255,13 +255,13 @@ disable = [
"deprecated-method",
]
[tool.pylint.'DESIGN']
max-args = 38 # Default is 5
max-attributes = 28 # Default is 7
max-branches = 34 # Default is 12
max-locals = 45 # Default is 15
max-module-lines = 2468 # Default is 1000
max-nested-blocks = 9 # Default is 5
max-statements = 206 # Default is 50
max-args = 20 # Default is 5
max-attributes = 22 # Default is 7
max-branches = 22 # Default is 12
max-locals = 39 # Default is 15
max-module-lines = 1500 # Default is 1000
max-nested-blocks = 6 # Default is 5
max-statements = 102 # Default is 50

[tool.pylint.'SIMILARITIES']
min-similarity-lines = 6
Expand All @@ -285,7 +285,6 @@ asyncio_default_fixture_loop_scope = "class"
python_version = "3.9"
disallow_incomplete_defs = true
warn_return_any = false
warn_unused_configs = true
Copy link
Copy Markdown
Member Author

@anakin87 anakin87 Jun 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

enabling this argument without setting incremental = False does not work (mypy docs)

And incremental mode is useful for speeding up the execution of mypy locally

ignore_missing_imports = true
check_untyped_defs = true

Expand Down Expand Up @@ -340,26 +339,23 @@ ignore = [
"PERF203", # `try`-`except` within a loop incurs performance overhead
"PERF401", # Use a list comprehension to create a transformed list
"PLR1714", # repeated-equality-comparison
"PLR5501", # collapsible-else-if
"PLW0603", # global-statement
"PLW1510", # subprocess-run-without-check
"PLW2901", # redefined-loop-name
"SIM108", # if-else-block-instead-of-if-exp
"SIM115", # open-file-with-context-handler
"SIM118", # in-dict-keys
]

[tool.ruff.lint.mccabe]
max-complexity = 28
max-complexity = 20


[tool.ruff.lint.pylint]
allow-magic-value-types = ["float", "int", "str"]
max-args = 14 # Default is 5
max-args = 13 # Default is 5
max-branches = 21 # Default is 12
max-public-methods = 20 # Default is 20
max-returns = 7 # Default is 6
max-statements = 60 # Default is 50
max-statements = 56 # Default is 50

[tool.coverage.run]
omit = ["haystack/testing/*"]
Loading
Loading