diff --git a/api/tests/unit_tests/core/rag/datasource/keyword/jieba/test_stopwords.py b/api/tests/unit_tests/core/rag/datasource/keyword/jieba/test_stopwords.py index 4375d854ba7..0b32705a097 100644 --- a/api/tests/unit_tests/core/rag/datasource/keyword/jieba/test_stopwords.py +++ b/api/tests/unit_tests/core/rag/datasource/keyword/jieba/test_stopwords.py @@ -1,7 +1,7 @@ from core.rag.datasource.keyword.jieba.stopwords import STOPWORDS -def test_stopwords_loaded(): +def test_stopwords_loaded() -> None: assert isinstance(STOPWORDS, frozenset) assert "during" in STOPWORDS assert "the" in STOPWORDS diff --git a/api/tests/unit_tests/core/rag/datasource/keyword/test_keyword_base.py b/api/tests/unit_tests/core/rag/datasource/keyword/test_keyword_base.py index e3b781d3168..c3d2eba835c 100644 --- a/api/tests/unit_tests/core/rag/datasource/keyword/test_keyword_base.py +++ b/api/tests/unit_tests/core/rag/datasource/keyword/test_keyword_base.py @@ -1,4 +1,3 @@ -from types import SimpleNamespace from typing import override import pytest @@ -16,61 +15,61 @@ def _dataset() -> Dataset: class _KeywordThatRaises(BaseKeyword): @override - def create(self, texts: list[Document], session, **kwargs): + def create(self, texts: list[Document], session: Session, **kwargs: object) -> BaseKeyword: return super().create(texts, session, **kwargs) @override - def add_texts(self, texts: list[Document], session, **kwargs): + def add_texts(self, texts: list[Document], session: Session, **kwargs: object) -> None: return super().add_texts(texts, session, **kwargs) @override - def text_exists(self, id: str, *, session) -> bool: + def text_exists(self, id: str, *, session: Session) -> bool: return super().text_exists(id, session=session) @override - def delete_by_ids(self, ids: list[str], session, **kwargs): + def delete_by_ids(self, ids: list[str], session: Session, **kwargs: object) -> None: return super().delete_by_ids(ids, session, **kwargs) @override - def delete(self, *, session): + def delete(self, *, session: Session) -> None: return super().delete(session=session) @override - def search(self, query: str, *, session, **kwargs): + def search(self, query: str, *, session: Session, **kwargs: object) -> list[Document]: return super().search(query, session=session, **kwargs) class _KeywordForHelpers(BaseKeyword): - def __init__(self, dataset, existing_ids: set[str] | None = None): + def __init__(self, dataset: Dataset, existing_ids: set[str] | None = None) -> None: super().__init__(dataset) self._existing_ids = existing_ids or set() @override - def create(self, texts: list[Document], session, **kwargs): + def create(self, texts: list[Document], session: Session, **kwargs: object) -> BaseKeyword: return self @override - def add_texts(self, texts: list[Document], session, **kwargs): + def add_texts(self, texts: list[Document], session: Session, **kwargs: object) -> None: return None @override - def text_exists(self, id: str, *, session) -> bool: + def text_exists(self, id: str, *, session: Session) -> bool: return id in self._existing_ids @override - def delete_by_ids(self, ids: list[str], session, **kwargs): + def delete_by_ids(self, ids: list[str], session: Session, **kwargs: object) -> None: return None @override - def delete(self, *, session): + def delete(self, *, session: Session) -> None: return None @override - def search(self, query: str, *, session, **kwargs): + def search(self, query: str, *, session: Session, **kwargs: object) -> list[Document]: return [] -def test_abstract_methods_raise_not_implemented(unbound_session: Session): +def test_abstract_methods_raise_not_implemented(unbound_session: Session) -> None: keyword = _KeywordThatRaises(_dataset()) session = unbound_session @@ -93,12 +92,12 @@ def test_abstract_methods_raise_not_implemented(unbound_session: Session): keyword.search("query", session=session) -def test_filter_duplicate_texts_removes_existing_doc_ids(unbound_session: Session): +def test_filter_duplicate_texts_removes_existing_doc_ids(unbound_session: Session) -> None: keyword = _KeywordForHelpers(_dataset(), existing_ids={"duplicate"}) texts = [ Document(page_content="keep", metadata={"doc_id": "keep"}), Document(page_content="duplicate", metadata={"doc_id": "duplicate"}), - SimpleNamespace(page_content="without-metadata", metadata=None), + Document.model_construct(page_content="without-metadata", metadata=None), ] filtered = keyword._filter_duplicate_texts(texts, session=unbound_session) @@ -107,12 +106,12 @@ def test_filter_duplicate_texts_removes_existing_doc_ids(unbound_session: Sessio assert any(text.metadata is None for text in filtered) -def test_get_uuids_returns_only_docs_with_metadata(): +def test_get_uuids_returns_only_docs_with_metadata() -> None: keyword = _KeywordForHelpers(_dataset()) texts = [ Document(page_content="doc-1", metadata={"doc_id": "doc-1"}), Document(page_content="doc-2", metadata={"doc_id": "doc-2"}), - SimpleNamespace(page_content="doc-3", metadata=None), + Document.model_construct(page_content="doc-3", metadata=None), ] assert keyword._get_uuids(texts) == ["doc-1", "doc-2"] diff --git a/api/tests/unit_tests/core/rag/datasource/keyword/test_keyword_factory.py b/api/tests/unit_tests/core/rag/datasource/keyword/test_keyword_factory.py index 9b392493eda..21a82f48ec3 100644 --- a/api/tests/unit_tests/core/rag/datasource/keyword/test_keyword_factory.py +++ b/api/tests/unit_tests/core/rag/datasource/keyword/test_keyword_factory.py @@ -12,24 +12,24 @@ from models.dataset import Dataset from tests.unit_tests.config_override import apply_config_overrides -def test_get_keyword_factory_returns_jieba_factory(monkeypatch: pytest.MonkeyPatch): +def test_get_keyword_factory_returns_jieba_factory(monkeypatch: pytest.MonkeyPatch) -> None: fake_module = types.ModuleType("core.rag.datasource.keyword.jieba.jieba") class FakeJieba: pass - fake_module.Jieba = FakeJieba + vars(fake_module)["Jieba"] = FakeJieba monkeypatch.setitem(sys.modules, "core.rag.datasource.keyword.jieba.jieba", fake_module) assert Keyword.get_keyword_factory(KeyWordType.JIEBA) is FakeJieba -def test_get_keyword_factory_raises_for_unsupported_type(): +def test_get_keyword_factory_raises_for_unsupported_type() -> None: with pytest.raises(ValueError, match="Keyword store unsupported is not supported"): Keyword.get_keyword_factory("unsupported") -def test_keyword_initialization_uses_configured_factory(monkeypatch: pytest.MonkeyPatch): +def test_keyword_initialization_uses_configured_factory(monkeypatch: pytest.MonkeyPatch) -> None: dataset = Dataset( id="dataset-1", tenant_id="tenant-1", @@ -47,7 +47,7 @@ def test_keyword_initialization_uses_configured_factory(monkeypatch: pytest.Monk assert keyword._keyword_processor is fake_processor -def test_keyword_methods_forward_to_processor(unbound_session: Session): +def test_keyword_methods_forward_to_processor(unbound_session: Session) -> None: processor = MagicMock() processor.text_exists.return_value = True processor.search.return_value = [Document(page_content="matched", metadata={"doc_id": "doc-1"})] @@ -72,22 +72,22 @@ def test_keyword_methods_forward_to_processor(unbound_session: Session): processor.search.assert_called_once_with("query", session=session, top_k=1) -def test_keyword_getattr_returns_callable_and_raises_for_invalid_attributes(): +def test_keyword_getattr_returns_callable_and_raises_for_invalid_attributes() -> None: class Processor: value = 1 @staticmethod - def custom(): + def custom() -> str: return "ok" keyword = Keyword.__new__(Keyword) - keyword._keyword_processor = Processor() + keyword._keyword_processor = Processor() # pyrefly: ignore[bad-assignment] assert keyword.custom() == "ok" with pytest.raises(AttributeError): _ = keyword.value - keyword._keyword_processor = None + keyword._keyword_processor = None # pyrefly: ignore[bad-assignment] with pytest.raises(AttributeError): _ = keyword.missing_method diff --git a/api/tests/unit_tests/core/rag/datasource/vdb/test_field.py b/api/tests/unit_tests/core/rag/datasource/vdb/test_field.py index d68c93b021b..6a614f07a1c 100644 --- a/api/tests/unit_tests/core/rag/datasource/vdb/test_field.py +++ b/api/tests/unit_tests/core/rag/datasource/vdb/test_field.py @@ -4,42 +4,42 @@ from core.rag.datasource.vdb.field import parse_metadata_json class TestParseMetadataJson: - def test_none_returns_empty_dict(self): + def test_none_returns_empty_dict(self) -> None: assert parse_metadata_json(None) == {} - def test_empty_string_returns_empty_dict(self): + def test_empty_string_returns_empty_dict(self) -> None: assert parse_metadata_json("") == {} - def test_valid_json_string(self): + def test_valid_json_string(self) -> None: result = parse_metadata_json('{"doc_id": "abc", "score": 0.9}') assert result == {"doc_id": "abc", "score": 0.9} - def test_dict_passthrough(self): + def test_dict_passthrough(self) -> None: original = {"doc_id": "abc", "document_id": "123"} result = parse_metadata_json(original) assert result == original - def test_empty_json_object(self): + def test_empty_json_object(self) -> None: assert parse_metadata_json("{}") == {} - def test_invalid_json_raises_value_error(self): + def test_invalid_json_raises_value_error(self) -> None: with pytest.raises(ValueError): parse_metadata_json("{invalid json") - def test_nested_metadata(self): + def test_nested_metadata(self) -> None: result = parse_metadata_json('{"doc_id": "1", "extra": {"nested": true}}') assert result["extra"]["nested"] is True - def test_non_str_non_dict_returns_empty_dict(self): + def test_non_str_non_dict_returns_empty_dict(self) -> None: assert parse_metadata_json(123) == {} assert parse_metadata_json([1, 2]) == {} - def test_bytes_input(self): + def test_bytes_input(self) -> None: result = parse_metadata_json(b'{"key": "value"}') assert result == {"key": "value"} - def test_empty_bytes_returns_empty_dict(self): + def test_empty_bytes_returns_empty_dict(self) -> None: assert parse_metadata_json(b"") == {} - def test_empty_bytearray_returns_empty_dict(self): + def test_empty_bytearray_returns_empty_dict(self) -> None: assert parse_metadata_json(bytearray(b"")) == {} diff --git a/api/tests/unit_tests/core/rag/datasource/vdb/test_vector_base.py b/api/tests/unit_tests/core/rag/datasource/vdb/test_vector_base.py index fdbdd1833ed..8e2890c65a0 100644 --- a/api/tests/unit_tests/core/rag/datasource/vdb/test_vector_base.py +++ b/api/tests/unit_tests/core/rag/datasource/vdb/test_vector_base.py @@ -1,4 +1,4 @@ -from types import SimpleNamespace +from collections.abc import Callable from typing import override import pytest @@ -8,7 +8,7 @@ from core.rag.models.document import Document class _DummyVector(BaseVector): - def __init__(self, collection_name: str, existing_ids: set[str] | None = None): + def __init__(self, collection_name: str, existing_ids: set[str] | None = None) -> None: super().__init__(collection_name) self._existing_ids = existing_ids or set() @@ -17,35 +17,35 @@ class _DummyVector(BaseVector): return "dummy" @override - def create(self, texts: list[Document], embeddings: list[list[float]], **kwargs): + def create(self, texts: list[Document], embeddings: list[list[float]], **kwargs: object) -> None: return None @override - def add_texts(self, documents: list[Document], embeddings: list[list[float]], **kwargs): - return None + def add_texts(self, documents: list[Document], embeddings: list[list[float]], **kwargs: object) -> list[str]: + return [] @override def text_exists(self, id: str) -> bool: return id in self._existing_ids @override - def delete_by_ids(self, ids: list[str]): + def delete_by_ids(self, ids: list[str]) -> None: return None @override - def delete_by_metadata_field(self, key: str, value: str): + def delete_by_metadata_field(self, key: str, value: str) -> None: return None @override - def search_by_vector(self, query_vector: list[float], **kwargs): + def search_by_vector(self, query_vector: list[float], **kwargs: object) -> list[Document]: return [] @override - def search_by_full_text(self, query: str, **kwargs): + def search_by_full_text(self, query: str, **kwargs: object) -> list[Document]: return [] @override - def delete(self): + def delete(self) -> None: return None @@ -64,17 +64,19 @@ class _DummyVector(BaseVector): (BaseVector.delete, ()), ], ) -def test_base_vector_default_methods_raise_not_implemented(base_method, args): +def test_base_vector_default_methods_raise_not_implemented( + base_method: Callable[..., object], args: tuple[object, ...] +) -> None: vector = _DummyVector("collection_1") with pytest.raises(NotImplementedError): base_method(vector, *args) -def test_filter_duplicate_texts_removes_existing_docs(): +def test_filter_duplicate_texts_removes_existing_docs() -> None: vector = _DummyVector("collection_1", existing_ids={"dup"}) docs = [ - SimpleNamespace(page_content="keep-no-meta", metadata=None), + Document.model_construct(page_content="keep-no-meta", metadata=None), Document(page_content="keep-no-doc-id", metadata={"document_id": "d1"}), Document(page_content="remove-dup", metadata={"doc_id": "dup"}), Document(page_content="keep-unique", metadata={"doc_id": "unique"}), @@ -85,11 +87,11 @@ def test_filter_duplicate_texts_removes_existing_docs(): assert [d.page_content for d in filtered] == ["keep-no-meta", "keep-no-doc-id", "keep-unique"] -def test_get_uuids_and_collection_name_property(): +def test_get_uuids_and_collection_name_property() -> None: vector = _DummyVector("collection_1") docs = [ Document(page_content="a", metadata={"doc_id": "id-1"}), - SimpleNamespace(page_content="b", metadata=None), + Document.model_construct(page_content="b", metadata=None), Document(page_content="c", metadata={"document_id": "d-1"}), Document(page_content="d", metadata={"doc_id": "id-2"}), ] diff --git a/api/tests/unit_tests/pyrefly.toml b/api/tests/unit_tests/pyrefly.toml index ce5f95cfea7..f94177096bf 100644 --- a/api/tests/unit_tests/pyrefly.toml +++ b/api/tests/unit_tests/pyrefly.toml @@ -393,12 +393,7 @@ project-excludes = [ "core/rag/data_post_processor/test_data_post_processor.py", "core/rag/datasource/keyword/jieba/test_jieba.py", "core/rag/datasource/keyword/jieba/test_jieba_keyword_table_handler.py", - "core/rag/datasource/keyword/jieba/test_stopwords.py", - "core/rag/datasource/keyword/test_keyword_base.py", - "core/rag/datasource/keyword/test_keyword_factory.py", "core/rag/datasource/test_datasource_retrieval.py", - "core/rag/datasource/vdb/test_field.py", - "core/rag/datasource/vdb/test_vector_base.py", "core/rag/datasource/vdb/test_vector_factory.py", "core/rag/embedding/test_embedding_base.py", "core/rag/embedding/test_embedding_service.py",