• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

deepset-ai / haystack / 17378114148

01 Sep 2025 12:48PM UTC coverage: 92.077% (-0.004%) from 92.081%
17378114148

push

github

web-flow
refactor: Some refactoring and finish TODO for component tool (#9751)

* Some refactoring and finish TODO for component tool

* Add docstrings

12935 of 14048 relevant lines covered (92.08%)

0.92 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.65
haystack/utils/callable_serialization.py
1
# SPDX-FileCopyrightText: 2022-present deepset GmbH <info@deepset.ai>
2
#
3
# SPDX-License-Identifier: Apache-2.0
4

5
import inspect
1✔
6
from typing import Any, Callable
1✔
7

8
from haystack.core.errors import DeserializationError, SerializationError
1✔
9
from haystack.utils.type_serialization import thread_safe_import
1✔
10

11

12
def serialize_callable(callable_handle: Callable) -> str:
1✔
13
    """
14
    Serializes a callable to its full path.
15

16
    :param callable_handle: The callable to serialize
17
    :return: The full path of the callable
18
    """
19
    try:
1✔
20
        full_arg_spec = inspect.getfullargspec(callable_handle)
1✔
21
        is_instance_method = bool(full_arg_spec.args and full_arg_spec.args[0] == "self")
1✔
22
    except TypeError:
1✔
23
        is_instance_method = False
1✔
24
    if is_instance_method:
1✔
25
        raise SerializationError("Serialization of instance methods is not supported.")
1✔
26

27
    # __qualname__ contains the fully qualified path we need for classmethods and staticmethods
28
    qualname = getattr(callable_handle, "__qualname__", "")
1✔
29
    if "<lambda>" in qualname:
1✔
30
        raise SerializationError("Serialization of lambdas is not supported.")
1✔
31
    if "<locals>" in qualname:
1✔
32
        raise SerializationError("Serialization of nested functions is not supported.")
1✔
33

34
    name = qualname or callable_handle.__name__
1✔
35

36
    # Get the full package path of the function
37
    module = inspect.getmodule(callable_handle)
1✔
38
    if module is not None:
1✔
39
        full_path = f"{module.__name__}.{name}"
1✔
40
    else:
41
        full_path = name
×
42
    return full_path
1✔
43

44

45
def deserialize_callable(callable_handle: str) -> Callable:
1✔
46
    """
47
    Deserializes a callable given its full import path as a string.
48

49
    :param callable_handle: The full path of the callable_handle
50
    :return: The callable
51
    :raises DeserializationError: If the callable cannot be found
52
    """
53
    # Import here to avoid circular imports
54
    from haystack.tools.tool import Tool
1✔
55

56
    parts = callable_handle.split(".")
1✔
57

58
    for i in range(len(parts), 0, -1):
1✔
59
        module_name = ".".join(parts[:i])
1✔
60
        try:
1✔
61
            mod: Any = thread_safe_import(module_name)
1✔
62
        except Exception:
1✔
63
            # keep reducing i until we find a valid module import
64
            continue
1✔
65

66
        attr_value = mod
1✔
67
        for part in parts[i:]:
1✔
68
            try:
1✔
69
                attr_value = getattr(attr_value, part)
1✔
70
            except AttributeError as e:
1✔
71
                raise DeserializationError(f"Could not find attribute '{part}' in {attr_value.__name__}") from e
1✔
72

73
        # when the attribute is a classmethod, we need the underlying function
74
        if isinstance(attr_value, (classmethod, staticmethod)):
1✔
75
            attr_value = attr_value.__func__
×
76

77
        # Handle the case where @tool decorator replaced the function with a Tool object
78
        if isinstance(attr_value, Tool):
1✔
79
            attr_value = attr_value.function
1✔
80

81
        if not callable(attr_value):
1✔
82
            raise DeserializationError(f"The final attribute is not callable: {attr_value}")
1✔
83

84
        return attr_value
1✔
85

86
    # Fallback if we never find anything
87
    raise DeserializationError(f"Could not import '{callable_handle}' as a module or callable.")
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc