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

deepset-ai / haystack / 11552785866

28 Oct 2024 11:15AM UTC coverage: 90.548% (+0.02%) from 90.524%
11552785866

push

github

web-flow
build: unpin `numpy` + use Python 3.9 in CI (#8492)

* try unpinning numpy

* try python 3.9

* release note

7558 of 8347 relevant lines covered (90.55%)

0.91 hits per line

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

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

5
from typing import Any, Union, get_args, get_origin
1✔
6

7
from haystack import logging
1✔
8

9
logger = logging.getLogger(__name__)
1✔
10

11

12
def _is_optional(type_: type) -> bool:
1✔
13
    """
14
    Utility method that returns whether a type is Optional.
15
    """
16
    return get_origin(type_) is Union and type(None) in get_args(type_)
×
17

18

19
def _types_are_compatible(sender, receiver):  # pylint: disable=too-many-return-statements
1✔
20
    """
21
    Checks whether the source type is equal or a subtype of the destination type. Used to validate pipeline connections.
22

23
    Note: this method has no pretense to perform proper type matching. It especially does not deal with aliasing of
24
    typing classes such as `List` or `Dict` to their runtime counterparts `list` and `dict`. It also does not deal well
25
    with "bare" types, so `List` is treated differently from `List[Any]`, even though they should be the same.
26

27
    Consider simplifying the typing of your components if you observe unexpected errors during component connection.
28
    """
29
    if sender == receiver or receiver is Any:
1✔
30
        return True
1✔
31

32
    if sender is Any:
1✔
33
        return False
1✔
34

35
    try:
1✔
36
        if issubclass(sender, receiver):
1✔
37
            return True
1✔
38
    except TypeError:  # typing classes can't be used with issubclass, so we deal with them below
1✔
39
        pass
1✔
40

41
    sender_origin = get_origin(sender)
1✔
42
    receiver_origin = get_origin(receiver)
1✔
43

44
    if sender_origin is not Union and receiver_origin is Union:
1✔
45
        return any(_types_are_compatible(sender, union_arg) for union_arg in get_args(receiver))
1✔
46

47
    if not sender_origin or not receiver_origin or sender_origin != receiver_origin:
1✔
48
        return False
1✔
49

50
    sender_args = get_args(sender)
1✔
51
    receiver_args = get_args(receiver)
1✔
52
    if len(sender_args) > len(receiver_args):
1✔
53
        return False
1✔
54

55
    return all(_types_are_compatible(*args) for args in zip(sender_args, receiver_args))
1✔
56

57

58
def _type_name(type_):
1✔
59
    """
60
    Util methods to get a nice readable representation of a type.
61

62
    Handles Optional and Literal in a special way to make it more readable.
63
    """
64
    # Literal args are strings, so we wrap them in quotes to make it clear
65
    if isinstance(type_, str):
1✔
66
        return f"'{type_}'"
1✔
67

68
    name = getattr(type_, "__name__", str(type_))
1✔
69

70
    if name.startswith("typing."):
1✔
71
        name = name[7:]
1✔
72
    if "[" in name:
1✔
73
        name = name.split("[")[0]
1✔
74
    args = get_args(type_)
1✔
75
    if name == "Union" and type(None) in args and len(args) == 2:
1✔
76
        # Optional is technically a Union of type and None
77
        # but we want to display it as Optional
78
        name = "Optional"
×
79

80
    if args:
1✔
81
        args = ", ".join([_type_name(a) for a in args if a is not type(None)])
1✔
82
        return f"{name}[{args}]"
1✔
83

84
    return f"{name}"
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