From 1e46e3ed89832ee85adb93db15df2b307a3b5f2d Mon Sep 17 00:00:00 2001 From: Xiyuan Chen <52963600+GareArc@users.noreply.github.com> Date: Mon, 2 Nov 2026 08:19:40 +0000 Subject: [PATCH] fix(api): pass lint, type check and unit tests on the new dev dependencies (#45308) --- .../vdb/vdb-tablestore/tests/e2e_tests/test_tablestore.py | 4 ++-- api/tests/unit_tests/conftest.py | 5 +++++ .../controllers/inner_api/knowledge/test_retrieval.py | 4 ++-- .../unit_tests/core/entities/test_provider_configuration.py | 6 +++--- .../test_sqlalchemy_workflow_node_execution_repository.py | 4 ++-- api/tests/unit_tests/fields/test_dataset_fields.py | 4 ++-- .../unit_tests/services/credentials/test_tool_runtime.py | 6 +++++- .../services/test_workflow_collaboration_service.py | 4 ++-- .../unit_tests/tasks/test_enable_segments_to_index_task.py | 4 ++-- 9 files changed, 25 insertions(+), 16 deletions(-) diff --git a/api/providers/vdb/vdb-tablestore/tests/e2e_tests/test_tablestore.py b/api/providers/vdb/vdb-tablestore/tests/e2e_tests/test_tablestore.py index 557c37e54e3..291a71e7ef7 100644 --- a/api/providers/vdb/vdb-tablestore/tests/e2e_tests/test_tablestore.py +++ b/api/providers/vdb/vdb-tablestore/tests/e2e_tests/test_tablestore.py @@ -3,8 +3,8 @@ import os import uuid from typing import override +import pytest import tablestore -from _pytest.python_api import approx from dify_vdb_tablestore.tablestore_vector import ( TableStoreConfig, TableStoreVector, @@ -80,7 +80,7 @@ class TableStoreVectorTest(AbstractVectorTest): assert len(docs) == 1 assert docs[0].metadata["doc_id"] == self.example_doc_id if self.tablestore_vector._config.normalize_full_text_bm25_score: - assert docs[0].metadata["score"] == approx(0.1214, abs=1e-3) + assert docs[0].metadata["score"] == pytest.approx(0.1214, abs=1e-3) else: assert docs[0].metadata.get("score") is None diff --git a/api/tests/unit_tests/conftest.py b/api/tests/unit_tests/conftest.py index b5cf36363ae..cbcee1bf7d6 100644 --- a/api/tests/unit_tests/conftest.py +++ b/api/tests/unit_tests/conftest.py @@ -60,6 +60,11 @@ redis_mock.expire = MagicMock() redis_mock.hgetall = MagicMock(return_value={}) redis_mock.hdel = MagicMock() redis_mock.incr = MagicMock(return_value=1) +# pytest 9.2's monkeypatch undo deletes a mock child that isn't in the mock's __dict__. Keep every Redis +# method there, so a test that patches one leaves it in place for the tests after it. +for _name in {*dir(ext_redis.RedisClientWrapper), *dir(Redis)}: + if not _name.startswith("_"): + setattr(redis_mock, _name, getattr(redis_mock, _name)) # guard-ignore: no-new-getattr -- names come from dir() if TYPE_CHECKING: from extensions.application_services.app import AppServices diff --git a/api/tests/unit_tests/controllers/inner_api/knowledge/test_retrieval.py b/api/tests/unit_tests/controllers/inner_api/knowledge/test_retrieval.py index 947dd3fe0d0..cc254e8b7c1 100644 --- a/api/tests/unit_tests/controllers/inner_api/knowledge/test_retrieval.py +++ b/api/tests/unit_tests/controllers/inner_api/knowledge/test_retrieval.py @@ -1,6 +1,6 @@ """Unit tests for the plugin inner knowledge retrieval controller.""" -from collections.abc import Iterator +from collections.abc import Generator from contextlib import contextmanager from unittest.mock import patch @@ -57,7 +57,7 @@ def _payload() -> dict[str, object]: @contextmanager -def _plugin_inner_auth() -> Iterator[None]: +def _plugin_inner_auth() -> Generator[None]: with ( config_overrides_context(PLUGIN_DAEMON_KEY="plugin-daemon-key", INNER_API_KEY_FOR_PLUGIN="inner-key"), ): diff --git a/api/tests/unit_tests/core/entities/test_provider_configuration.py b/api/tests/unit_tests/core/entities/test_provider_configuration.py index b3bc29f8d77..710759cfeaf 100644 --- a/api/tests/unit_tests/core/entities/test_provider_configuration.py +++ b/api/tests/unit_tests/core/entities/test_provider_configuration.py @@ -2,7 +2,7 @@ from __future__ import annotations import json import logging -from collections.abc import Iterator +from collections.abc import Generator, Iterator from contextlib import contextmanager from types import SimpleNamespace from unittest.mock import MagicMock, Mock, PropertyMock, patch @@ -241,7 +241,7 @@ def _load_balancing_config( @contextmanager -def _raise_on_sql(engine: Engine, table_name: str, operation: str) -> Iterator[None]: +def _raise_on_sql(engine: Engine, table_name: str, operation: str) -> Generator[None]: """Fail one table operation while production still owns a real transaction.""" def fail_target(_conn, _cursor, statement, _parameters, _context, _executemany): @@ -256,7 +256,7 @@ def _raise_on_sql(engine: Engine, table_name: str, operation: str) -> Iterator[N @contextmanager -def _mock_cache_boundaries() -> Iterator[tuple[Mock, Mock]]: +def _mock_cache_boundaries() -> Generator[tuple[Mock, Mock]]: with ( patch("core.entities.provider_configuration.ProviderCredentialsCache") as credentials_cache, patch.object(ProviderConfiguration, "_invalidate_provider_configuration_cache") as configuration_cache, diff --git a/api/tests/unit_tests/core/repositories/test_sqlalchemy_workflow_node_execution_repository.py b/api/tests/unit_tests/core/repositories/test_sqlalchemy_workflow_node_execution_repository.py index 1636c1d77f0..002dde4c715 100644 --- a/api/tests/unit_tests/core/repositories/test_sqlalchemy_workflow_node_execution_repository.py +++ b/api/tests/unit_tests/core/repositories/test_sqlalchemy_workflow_node_execution_repository.py @@ -2,7 +2,7 @@ from __future__ import annotations import json import logging -from collections.abc import Callable, Generator, Iterator, Mapping +from collections.abc import Callable, Generator, Mapping from contextlib import contextmanager from dataclasses import dataclass from datetime import UTC, datetime @@ -877,7 +877,7 @@ def _fail_inserts( *, failure_count: int, duplicate: bool, -) -> Iterator[ConflictEvents]: +) -> Generator[ConflictEvents]: insert_attempts: list[str] = [] rollbacks: list[bool] = [] diff --git a/api/tests/unit_tests/fields/test_dataset_fields.py b/api/tests/unit_tests/fields/test_dataset_fields.py index f08875f342d..9d8c868e1a7 100644 --- a/api/tests/unit_tests/fields/test_dataset_fields.py +++ b/api/tests/unit_tests/fields/test_dataset_fields.py @@ -1,5 +1,5 @@ import json -from collections.abc import Iterator +from collections.abc import Generator from contextlib import contextmanager from sqlalchemy import event @@ -391,7 +391,7 @@ def _dump(dataset: Dataset, *, session: Session) -> dict[str, object]: @contextmanager -def _count_selects(session: Session) -> Iterator[list[str]]: +def _count_selects(session: Session) -> Generator[list[str]]: """Record every SELECT issued against the session's engine.""" statements: list[str] = [] engine = session.get_bind() diff --git a/api/tests/unit_tests/services/credentials/test_tool_runtime.py b/api/tests/unit_tests/services/credentials/test_tool_runtime.py index d5e45dd97e5..3d04685c9f5 100644 --- a/api/tests/unit_tests/services/credentials/test_tool_runtime.py +++ b/api/tests/unit_tests/services/credentials/test_tool_runtime.py @@ -101,7 +101,11 @@ def test_concurrent_and_sequential_calls_refresh_once() -> None: assert lock.keys == [("tool", "workspace", "credential")] * 4 -@pytest.mark.parametrize("expires_at", [-1, int(time.time()) + 3600]) +# Named ids: xdist workers collect at different seconds, so an id built from the timestamp differs between them. +@pytest.mark.parametrize( + "expires_at", + [pytest.param(-1, id="never-expires"), pytest.param(int(time.time()) + 3600, id="expires-in-an-hour")], +) def test_valid_credentials_do_not_acquire_a_lock(expires_at: int) -> None: store, runtime, lock = ( CredentialStore(_record(expires_at=expires_at)), diff --git a/api/tests/unit_tests/services/test_workflow_collaboration_service.py b/api/tests/unit_tests/services/test_workflow_collaboration_service.py index 99fde0bca4c..4414debdc74 100644 --- a/api/tests/unit_tests/services/test_workflow_collaboration_service.py +++ b/api/tests/unit_tests/services/test_workflow_collaboration_service.py @@ -1,5 +1,5 @@ import logging -from collections.abc import Iterator +from collections.abc import Generator, Iterator from contextlib import contextmanager from unittest.mock import MagicMock, Mock, patch @@ -704,7 +704,7 @@ class TestWorkflowCollaborationService: events: list[str] = [] @contextmanager - def graph_view_lock() -> Iterator[None]: + def graph_view_lock() -> Generator[None]: events.append("lock_enter") yield events.append("lock_exit") diff --git a/api/tests/unit_tests/tasks/test_enable_segments_to_index_task.py b/api/tests/unit_tests/tasks/test_enable_segments_to_index_task.py index 8653d532446..ca2c702680e 100644 --- a/api/tests/unit_tests/tasks/test_enable_segments_to_index_task.py +++ b/api/tests/unit_tests/tasks/test_enable_segments_to_index_task.py @@ -1,5 +1,5 @@ import uuid -from collections.abc import Iterator +from collections.abc import Generator from contextlib import contextmanager from unittest.mock import MagicMock, patch @@ -61,7 +61,7 @@ def indexed_segment(sqlite_session: Session) -> tuple[Dataset, Document, Documen @contextmanager def _record_transaction_events( sqlite_session_factory: sessionmaker[Session], phase_events: list[str] -) -> Iterator[None]: +) -> Generator[None]: """Record real transaction boundaries from task-owned SQLite sessions.""" session_type = sqlite_session_factory.class_