diff --git a/test/collection/test_include_vector_str.py b/test/collection/test_include_vector_str.py new file mode 100644 index 000000000..bfb3eae59 --- /dev/null +++ b/test/collection/test_include_vector_str.py @@ -0,0 +1,32 @@ +"""`include_vector` accepts a bare ``str`` but then requests no vector at all. + +``INCLUDE_VECTOR = Union[bool, str, List[str]]`` and ``_parse_return_metadata`` +validates ``[bool, str, Sequence]``, so a single named vector may be passed as a +string. ``_MetadataQuery.from_public`` only handles ``bool`` and ``list``, so a +string falls through both branches and the gRPC ``MetadataRequest`` asks for +nothing, while ``_QueryOptions`` still reports ``include_vector=True``. +""" + +from weaviate.collections.classes.grpc import _MetadataQuery +from weaviate.collections.classes.internal import _QueryOptions + + +def test_metadata_query_from_public_with_a_list() -> None: + """Baseline: the list form requests the named vector.""" + md = _MetadataQuery.from_public(None, ["named_vec"]) + assert md.vectors == ["named_vec"] + + +def test_metadata_query_from_public_with_a_bare_string() -> None: + md = _MetadataQuery.from_public(None, "named_vec") + assert md.vectors == ["named_vec"], ( + f"a bare str requested nothing: vector={md.vector!r} vectors={md.vectors!r}" + ) + + +def test_query_options_and_metadata_query_agree_for_a_bare_string() -> None: + """The parser is told a vector is coming; the request never asked for one.""" + opts = _QueryOptions.from_input(None, None, "named_vec", None, None) + md = _MetadataQuery.from_public(None, "named_vec") + assert opts.include_vector is True + assert bool(md.vector) or md.vectors, "include_vector=True but nothing was requested" diff --git a/weaviate/collections/classes/grpc.py b/weaviate/collections/classes/grpc.py index 5cba315f7..a340f8bfc 100644 --- a/weaviate/collections/classes/grpc.py +++ b/weaviate/collections/classes/grpc.py @@ -148,6 +148,11 @@ class _MetadataQuery: def from_public( cls, public: Optional[MetadataQuery], include_vector: INCLUDE_VECTOR ) -> "_MetadataQuery": + # INCLUDE_VECTOR permits a bare `str` for a single named vector, and the branches below + # test only for `bool` and `list`. Without this a `str` matched neither, so the request + # asked for no vector at all and the caller got none back, with no error. + if isinstance(include_vector, str): + include_vector = [include_vector] return ( cls( vector=include_vector if isinstance(include_vector, bool) else False,