chore: Remove pyright in favor of pyrefly (#36154)

This commit is contained in:
chariri authored and GitHub committed 2026-05-14 05:49:08 +00:00
1 parent b9e3130388
commit af4b9bfa8f
31 files changed
+87 -181

No files matched your search

+8 -9
View File
@@ -83,16 +83,15 @@ lint:
@echo "✅ Linting complete" @echo "✅ Linting complete"
type-check: type-check:
@echo "📝 Running type checks (basedpyright + pyrefly + mypy)..." @echo "📝 Running type checks (pyrefly + mypy)..."
@./dev/basedpyright-check $(PATH_TO_CHECK) @./dev/pyrefly-check-local $(PATH_TO_CHECK)
@./dev/pyrefly-check-local @uv --directory api run mypy --exclude-gitignore --exclude 'tests/' --exclude 'migrations/' --exclude 'dev/generate_swagger_specs.py' --exclude 'dev/generate_fastopenapi_specs.py' --check-untyped-defs --disable-error-code=import-untyped .
@uv --directory api run mypy --exclude-gitignore --exclude 'tests/' --exclude 'migrations/' --exclude 'dev/generate_swagger_specs.py' --check-untyped-defs --disable-error-code=import-untyped .
@echo "✅ Type checks complete" @echo "✅ Type checks complete"
type-check-core: type-check-core:
@echo "📝 Running core type checks (basedpyright + mypy)..." @echo "📝 Running core type checks (pyrefly + mypy)..."
@./dev/basedpyright-check $(PATH_TO_CHECK) @./dev/pyrefly-check-local $(PATH_TO_CHECK)
@uv --directory api run mypy --exclude-gitignore --exclude 'tests/' --exclude 'migrations/' --exclude 'dev/generate_swagger_specs.py' --exclude 'dev/generate_fastopenapi_specs.py' --check-untyped-defs --disable-error-code=import-untyped . @uv --directory api run mypy --exclude-gitignore --exclude 'tests/' --exclude 'migrations/' --exclude 'dev/generate_swagger_specs.py' --exclude 'dev/generate_fastopenapi_specs.py' --check-untyped-defs --disable-error-code=import-untyped .
@echo "✅ Core type checks complete" @echo "✅ Core type checks complete"
test: test:
@@ -153,8 +152,8 @@ help:
@echo " make format - Format code with ruff" @echo " make format - Format code with ruff"
@echo " make check - Check code with ruff" @echo " make check - Check code with ruff"
@echo " make lint - Format, fix, and lint code (ruff, imports, dotenv)" @echo " make lint - Format, fix, and lint code (ruff, imports, dotenv)"
@echo " make type-check - Run type checks (basedpyright, pyrefly, mypy)" @echo " make type-check - Run type checks (pyrefly, mypy)"
@echo " make type-check-core - Run core type checks (basedpyright, mypy)" @echo " make type-check-core - Run core type checks (pyrefly, mypy)"
@echo " make test - Run backend unit tests (or TARGET_TESTS=./api/tests/<target_tests>)" @echo " make test - Run backend unit tests (or TARGET_TESTS=./api/tests/<target_tests>)"
@echo "" @echo ""
@echo "Docker Build Targets:" @echo "Docker Build Targets:"
+1 -1
View File
@@ -99,7 +99,7 @@ The scripts resolve paths relative to their location, so you can run them from a
./dev/reformat # Run all formatters and linters ./dev/reformat # Run all formatters and linters
uv run ruff check --fix ./ # Fix linting issues uv run ruff check --fix ./ # Fix linting issues
uv run ruff format ./ # Format code uv run ruff format ./ # Format code
uv run basedpyright . # Type checking uv run pyrefly check # Type checking
``` ```
## Generate TS stub ## Generate TS stub
+1 -1
View File
@@ -117,7 +117,7 @@ def create_flask_app_with_configs() -> DifyApp:
logger.warning("Failed to add trace headers to response", exc_info=True) logger.warning("Failed to add trace headers to response", exc_info=True)
return response return response
# Capture the decorator's return value to avoid pyright reportUnusedFunction # Capture the decorator return values so static checkers do not treat the hooks as unused.
_ = before_request _ = before_request
_ = add_trace_headers _ = add_trace_headers
+3 -3
View File
@@ -185,9 +185,9 @@ def transform_datasource_credentials(environment: str):
firecrawl_plugin_id = "langgenius/firecrawl_datasource" firecrawl_plugin_id = "langgenius/firecrawl_datasource"
jina_plugin_id = "langgenius/jina_datasource" jina_plugin_id = "langgenius/jina_datasource"
if environment == "online": if environment == "online":
notion_plugin_unique_identifier = plugin_migration._fetch_plugin_unique_identifier(notion_plugin_id) # pyright: ignore[reportPrivateUsage] notion_plugin_unique_identifier = plugin_migration._fetch_plugin_unique_identifier(notion_plugin_id)
firecrawl_plugin_unique_identifier = plugin_migration._fetch_plugin_unique_identifier(firecrawl_plugin_id) # pyright: ignore[reportPrivateUsage] firecrawl_plugin_unique_identifier = plugin_migration._fetch_plugin_unique_identifier(firecrawl_plugin_id)
jina_plugin_unique_identifier = plugin_migration._fetch_plugin_unique_identifier(jina_plugin_id) # pyright: ignore[reportPrivateUsage] jina_plugin_unique_identifier = plugin_migration._fetch_plugin_unique_identifier(jina_plugin_id)
else: else:
notion_plugin_unique_identifier = None notion_plugin_unique_identifier = None
firecrawl_plugin_unique_identifier = None firecrawl_plugin_unique_identifier = None
+19 -17
View File
@@ -1,5 +1,5 @@
import os import os
from typing import Any, Literal, TypedDict from typing import Any, Literal, TypedDict, cast
from urllib.parse import parse_qsl, quote_plus from urllib.parse import parse_qsl, quote_plus
from pydantic import Field, NonNegativeFloat, NonNegativeInt, PositiveFloat, PositiveInt, computed_field from pydantic import Field, NonNegativeFloat, NonNegativeInt, PositiveFloat, PositiveInt, computed_field
@@ -50,28 +50,30 @@ from .vdb.vastbase_vector_config import VastbaseVectorConfig
from .vdb.vikingdb_config import VikingDBConfig from .vdb.vikingdb_config import VikingDBConfig
from .vdb.weaviate_config import WeaviateConfig from .vdb.weaviate_config import WeaviateConfig
_VALID_STORAGE_TYPE = Literal[
"opendal",
"s3",
"aliyun-oss",
"azure-blob",
"baidu-obs",
"clickzetta-volume",
"google-storage",
"huawei-obs",
"oci-storage",
"tencent-cos",
"volcengine-tos",
"supabase",
"local",
]
class StorageConfig(BaseSettings): class StorageConfig(BaseSettings):
STORAGE_TYPE: Literal[ STORAGE_TYPE: _VALID_STORAGE_TYPE = Field(
"opendal",
"s3",
"aliyun-oss",
"azure-blob",
"baidu-obs",
"clickzetta-volume",
"google-storage",
"huawei-obs",
"oci-storage",
"tencent-cos",
"volcengine-tos",
"supabase",
"local",
] = Field(
description="Type of storage to use." description="Type of storage to use."
" Options: 'opendal', '(deprecated) local', 's3', 'aliyun-oss', 'azure-blob', 'baidu-obs', " " Options: 'opendal', '(deprecated) local', 's3', 'aliyun-oss', 'azure-blob', 'baidu-obs', "
"'clickzetta-volume', 'google-storage', 'huawei-obs', 'oci-storage', 'tencent-cos', " "'clickzetta-volume', 'google-storage', 'huawei-obs', 'oci-storage', 'tencent-cos', "
"'volcengine-tos', 'supabase'. Default is 'opendal'.", "'volcengine-tos', 'supabase'. Default is 'opendal'.",
default="opendal", default=cast(_VALID_STORAGE_TYPE, "opendal"),
) )
STORAGE_LOCAL_PATH: str = Field( STORAGE_LOCAL_PATH: str = Field(
+1 -1
View File
@@ -116,7 +116,7 @@ from .explore import (
saved_message, saved_message,
trial, trial,
) )
from .socketio import workflow as socketio_workflow # pyright: ignore[reportUnusedImport] from .socketio import workflow as socketio_workflow
# Import tag controllers # Import tag controllers
from .tag import tags from .tag import tags
@@ -178,7 +178,7 @@ class AgentChatAppConfigManager(BaseAppConfigManager):
if not isinstance(agent_mode, dict): if not isinstance(agent_mode, dict):
raise ValueError("agent_mode must be of object type") raise ValueError("agent_mode must be of object type")
# FIXME(-LAN-): Cast needed due to basedpyright limitation with dict type narrowing # FIXME(-LAN-): Cast needed because static checkers do not narrow this dict value.
agent_mode = cast(dict[str, Any], agent_mode) agent_mode = cast(dict[str, Any], agent_mode)
if "enabled" not in agent_mode or not agent_mode["enabled"]: if "enabled" not in agent_mode or not agent_mode["enabled"]:
+1 -1
View File
@@ -435,7 +435,7 @@ class LLMGenerator:
stream=False, stream=False,
) )
# Runtime type check since pyright has issues with the overload # Runtime type check for overload narrowing.
if not isinstance(result, LLMResult): if not isinstance(result, LLMResult):
raise TypeError("Expected LLMResult when stream=False") raise TypeError("Expected LLMResult when stream=False")
response = result response = result
@@ -19,7 +19,7 @@ class UnstructuredWordExtractor(BaseExtractor):
def extract(self) -> list[Document]: def extract(self) -> list[Document]:
from unstructured.__version__ import __version__ as __unstructured_version__ from unstructured.__version__ import __version__ as __unstructured_version__
from unstructured.file_utils.filetype import ( # pyright: ignore[reportPrivateImportUsage] from unstructured.file_utils.filetype import (
FileType, FileType,
detect_filetype, detect_filetype,
) )
@@ -27,7 +27,7 @@ class UnstructuredWordExtractor(BaseExtractor):
unstructured_version = tuple(int(x) for x in __unstructured_version__.split(".")) unstructured_version = tuple(int(x) for x in __unstructured_version__.split("."))
# check the file extension # check the file extension
try: try:
import magic # noqa: F401 # pyright: ignore[reportUnusedImport] import magic # noqa: F401
is_doc = detect_filetype(self._file_path) == FileType.DOC is_doc = detect_filetype(self._file_path) == FileType.DOC
except ImportError: except ImportError:
@@ -28,10 +28,10 @@ class FunctionCallMultiDatasetRouter:
SystemPromptMessage(content="You are a helpful AI assistant."), SystemPromptMessage(content="You are a helpful AI assistant."),
UserPromptMessage(content=query), UserPromptMessage(content=query),
] ]
result: LLMResult = model_instance.invoke_llm( # pyright: ignore[reportCallIssue, reportArgumentType] result: LLMResult = model_instance.invoke_llm( # pyrefly: ignore[no-matching-overload]
prompt_messages=prompt_messages, prompt_messages=prompt_messages,
tools=dataset_tools, tools=dataset_tools,
stream=False, # pyright: ignore[reportArgumentType] stream=False,
model_parameters={"temperature": 0.2, "top_p": 0.3, "max_tokens": 1500}, model_parameters={"temperature": 0.2, "top_p": 0.3, "max_tokens": 1500},
) )
usage = result.usage or LLMUsage.empty_usage() usage = result.usage or LLMUsage.empty_usage()
+4 -4
View File
@@ -11,14 +11,14 @@ from dify_app import DifyApp
def init_app(app: DifyApp): def init_app(app: DifyApp):
@app.after_request @app.after_request
def after_request(response): # pyright: ignore[reportUnusedFunction] def after_request(response):
"""Add Version headers to the response.""" """Add Version headers to the response."""
response.headers.add("X-Version", dify_config.project.version) response.headers.add("X-Version", dify_config.project.version)
response.headers.add("X-Env", dify_config.DEPLOY_ENV) response.headers.add("X-Env", dify_config.DEPLOY_ENV)
return response return response
@app.route("/health") @app.route("/health")
def health(): # pyright: ignore[reportUnusedFunction] def health():
return Response( return Response(
json.dumps({"pid": os.getpid(), "status": "ok", "version": dify_config.project.version}), json.dumps({"pid": os.getpid(), "status": "ok", "version": dify_config.project.version}),
status=200, status=200,
@@ -27,7 +27,7 @@ def init_app(app: DifyApp):
@app.route("/threads") @app.route("/threads")
@admin_required @admin_required
def threads(): # pyright: ignore[reportUnusedFunction] def threads():
num_threads = threading.active_count() num_threads = threading.active_count()
threads = threading.enumerate() threads = threading.enumerate()
@@ -53,7 +53,7 @@ def init_app(app: DifyApp):
@app.route("/db-pool-stat") @app.route("/db-pool-stat")
@admin_required @admin_required
def pool_stat(): # pyright: ignore[reportUnusedFunction] def pool_stat():
from extensions.ext_database import db from extensions.ext_database import db
engine = db.engine engine = db.engine
+1 -1
View File
@@ -33,7 +33,7 @@ def _setup_gevent_compatibility():
return return
@event.listens_for(Pool, "reset") @event.listens_for(Pool, "reset")
def _safe_reset(dbapi_connection, connection_record, reset_state): # pyright: ignore[reportUnusedFunction] def _safe_reset(dbapi_connection, connection_record, reset_state):
if reset_state.terminate_only: if reset_state.terminate_only:
return return
+1 -1
View File
@@ -2,4 +2,4 @@ from dify_app import DifyApp
def init_app(app: DifyApp): def init_app(app: DifyApp):
from events import event_handlers # noqa: F401 # pyright: ignore[reportUnusedImport] from events import event_handlers # noqa: F401
+5 -1
View File
@@ -1,5 +1,9 @@
from typing import Any, cast
import socketio # type: ignore[reportMissingTypeStubs] import socketio # type: ignore[reportMissingTypeStubs]
from configs import dify_config from configs import dify_config
sio = socketio.Server(async_mode="gevent", cors_allowed_origins=dify_config.CONSOLE_CORS_ALLOW_ORIGINS) # TODO: FIXME(chariri) - Casting to any because app_factory attaches the
# current app as the `app` attribute on this - Bad.
sio = cast(Any, socketio.Server(async_mode="gevent", cors_allowed_origins=dify_config.CONSOLE_CORS_ALLOW_ORIGINS))
+1 -1
View File
@@ -198,7 +198,7 @@ class AliyunLogStore:
) )
# Append Dify identification to the existing user agent # Append Dify identification to the existing user agent
original_user_agent = self.client._user_agent # pyright: ignore[reportPrivateUsage] original_user_agent = self.client._user_agent
dify_version = dify_config.project.version dify_version = dify_config.project.version
enhanced_user_agent = f"Dify,Dify-{dify_version},{original_user_agent}" enhanced_user_agent = f"Dify,Dify-{dify_version},{original_user_agent}"
self.client.set_user_agent(enhanced_user_agent) self.client.set_user_agent(enhanced_user_agent)
@@ -94,29 +94,29 @@ class PatchedCoreComponents(TypedDict):
def _add_stub_modules(monkeypatch: pytest.MonkeyPatch) -> None: def _add_stub_modules(monkeypatch: pytest.MonkeyPatch) -> None:
"""Drop fake metric modules into sys.modules so the client imports resolve.""" """Drop fake metric modules into sys.modules so the client imports resolve."""
metrics_module = types.ModuleType("opentelemetry.sdk.metrics") metrics_module = cast(Any, types.ModuleType("opentelemetry.sdk.metrics"))
metrics_module.Histogram = DummyHistogram metrics_module.Histogram = DummyHistogram
metrics_module.MeterProvider = DummyMeterProvider metrics_module.MeterProvider = DummyMeterProvider
monkeypatch.setitem(sys.modules, "opentelemetry.sdk.metrics", metrics_module) monkeypatch.setitem(sys.modules, "opentelemetry.sdk.metrics", metrics_module)
metrics_export_module = types.ModuleType("opentelemetry.sdk.metrics.export") metrics_export_module = cast(Any, types.ModuleType("opentelemetry.sdk.metrics.export"))
metrics_export_module.AggregationTemporality = AggregationTemporality metrics_export_module.AggregationTemporality = AggregationTemporality
metrics_export_module.PeriodicExportingMetricReader = DummyMetricReader metrics_export_module.PeriodicExportingMetricReader = DummyMetricReader
monkeypatch.setitem(sys.modules, "opentelemetry.sdk.metrics.export", metrics_export_module) monkeypatch.setitem(sys.modules, "opentelemetry.sdk.metrics.export", metrics_export_module)
grpc_module = types.ModuleType("opentelemetry.exporter.otlp.proto.grpc.metric_exporter") grpc_module = cast(Any, types.ModuleType("opentelemetry.exporter.otlp.proto.grpc.metric_exporter"))
grpc_module.OTLPMetricExporter = DummyGrpcMetricExporter grpc_module.OTLPMetricExporter = DummyGrpcMetricExporter
monkeypatch.setitem(sys.modules, "opentelemetry.exporter.otlp.proto.grpc.metric_exporter", grpc_module) monkeypatch.setitem(sys.modules, "opentelemetry.exporter.otlp.proto.grpc.metric_exporter", grpc_module)
http_module = types.ModuleType("opentelemetry.exporter.otlp.proto.http.metric_exporter") http_module = cast(Any, types.ModuleType("opentelemetry.exporter.otlp.proto.http.metric_exporter"))
http_module.OTLPMetricExporter = DummyHttpMetricExporter http_module.OTLPMetricExporter = DummyHttpMetricExporter
monkeypatch.setitem(sys.modules, "opentelemetry.exporter.otlp.proto.http.metric_exporter", http_module) monkeypatch.setitem(sys.modules, "opentelemetry.exporter.otlp.proto.http.metric_exporter", http_module)
http_json_module = types.ModuleType("opentelemetry.exporter.otlp.http.json.metric_exporter") http_json_module = cast(Any, types.ModuleType("opentelemetry.exporter.otlp.http.json.metric_exporter"))
http_json_module.OTLPMetricExporter = DummyJsonMetricExporter http_json_module.OTLPMetricExporter = DummyJsonMetricExporter
monkeypatch.setitem(sys.modules, "opentelemetry.exporter.otlp.http.json.metric_exporter", http_json_module) monkeypatch.setitem(sys.modules, "opentelemetry.exporter.otlp.http.json.metric_exporter", http_json_module)
legacy_json_module = types.ModuleType("opentelemetry.exporter.otlp.json.metric_exporter") legacy_json_module = cast(Any, types.ModuleType("opentelemetry.exporter.otlp.json.metric_exporter"))
legacy_json_module.OTLPMetricExporter = DummyJsonMetricExporter legacy_json_module.OTLPMetricExporter = DummyJsonMetricExporter
monkeypatch.setitem(sys.modules, "opentelemetry.exporter.otlp.json.metric_exporter", legacy_json_module) monkeypatch.setitem(sys.modules, "opentelemetry.exporter.otlp.json.metric_exporter", legacy_json_module)
@@ -2,7 +2,7 @@ import json
from typing import Any, TypedDict from typing import Any, TypedDict
import chromadb import chromadb
from chromadb import QueryResult, Settings # pyright: ignore[reportPrivateImportUsage] from chromadb import QueryResult, Settings
from pydantic import BaseModel from pydantic import BaseModel
from configs import dify_config from configs import dify_config
@@ -166,8 +166,8 @@ class ChromaVectorFactory(AbstractVectorFactory):
config=ChromaConfig( config=ChromaConfig(
host=dify_config.CHROMA_HOST or "", host=dify_config.CHROMA_HOST or "",
port=dify_config.CHROMA_PORT, port=dify_config.CHROMA_PORT,
tenant=dify_config.CHROMA_TENANT or chromadb.DEFAULT_TENANT, # pyright: ignore[reportPrivateImportUsage] tenant=dify_config.CHROMA_TENANT or chromadb.DEFAULT_TENANT,
database=dify_config.CHROMA_DATABASE or chromadb.DEFAULT_DATABASE, # pyright: ignore[reportPrivateImportUsage] database=dify_config.CHROMA_DATABASE or chromadb.DEFAULT_DATABASE,
auth_provider=dify_config.CHROMA_AUTH_PROVIDER, auth_provider=dify_config.CHROMA_AUTH_PROVIDER,
auth_credentials=dify_config.CHROMA_AUTH_CREDENTIALS, auth_credentials=dify_config.CHROMA_AUTH_CREDENTIALS,
), ),
@@ -59,7 +59,7 @@ class CouchbaseVector(BaseVector):
auth = PasswordAuthenticator(config.user, config.password) auth = PasswordAuthenticator(config.user, config.password)
options = ClusterOptions(auth) options = ClusterOptions(auth)
self._cluster = Cluster(config.connection_string, options) # pyright: ignore[reportArgumentType] self._cluster = Cluster(config.connection_string, options)
self._bucket = self._cluster.bucket(config.bucket_name) self._bucket = self._cluster.bucket(config.bucket_name)
self._scope = self._bucket.scope(config.scope_name) self._scope = self._bucket.scope(config.scope_name)
self._bucket_name = config.bucket_name self._bucket_name = config.bucket_name
@@ -306,7 +306,7 @@ class CouchbaseVector(BaseVector):
def search_by_full_text(self, query: str, **kwargs: Any) -> list[Document]: def search_by_full_text(self, query: str, **kwargs: Any) -> list[Document]:
top_k = kwargs.get("top_k", 4) top_k = kwargs.get("top_k", 4)
try: try:
CBrequest = search.SearchRequest.create(search.QueryStringQuery("text:" + query)) # pyright: ignore[reportCallIssue] CBrequest = search.SearchRequest.create(search.QueryStringQuery("text:" + query)) # pyrefly: ignore[bad-argument-count]
search_iter = self._scope.search( search_iter = self._scope.search(
self._collection_name + "_search", CBrequest, SearchOptions(limit=top_k, fields=["*"]) self._collection_name + "_search", CBrequest, SearchOptions(limit=top_k, fields=["*"])
) )
@@ -471,7 +471,7 @@ class QdrantVector(BaseVector):
def _reload_if_needed(self): def _reload_if_needed(self):
if isinstance(self._client, QdrantLocal): if isinstance(self._client, QdrantLocal):
self._client._load() # pyright: ignore[reportPrivateUsage] self._client._load()
@classmethod @classmethod
def _document_from_scored_point( def _document_from_scored_point(
-1
View File
@@ -118,7 +118,6 @@ dev = [
"dotenv-linter>=0.7.0", "dotenv-linter>=0.7.0",
"faker>=40.15.0", "faker>=40.15.0",
"lxml-stubs>=0.5.1", "lxml-stubs>=0.5.1",
"basedpyright>=1.39.3",
"ruff>=0.15.12", "ruff>=0.15.12",
"pytest>=9.0.3", "pytest>=9.0.3",
"pytest-benchmark>=5.2.3", "pytest-benchmark>=5.2.3",
-58
View File
@@ -1,58 +0,0 @@
{
"include": ["."],
"exclude": [
"tests/",
".venv",
"migrations/",
"core/rag",
"providers/vdb/",
"providers/trace/*/tests",
],
"typeCheckingMode": "strict",
"allowedUntypedLibraries": [
"fastopenapi",
"flask_restx",
"flask_login",
"opentelemetry.instrumentation.celery",
"opentelemetry.instrumentation.flask",
"opentelemetry.instrumentation.httpx",
"opentelemetry.instrumentation.requests",
"opentelemetry.instrumentation.sqlalchemy",
"opentelemetry.instrumentation.redis",
"langfuse",
"cloudscraper",
"readabilipy",
"pypandoc",
"pypdfium2",
"webvtt",
"flask_compress",
"oss2",
"baidubce.auth.bce_credentials",
"baidubce.bce_client_configuration",
"baidubce.services.bos.bos_client",
"clickzetta",
"google.cloud",
"obs",
"qcloud_cos",
"tos",
"gmpy2",
"sendgrid",
"sendgrid.helpers.mail",
"holo_search_sdk.types",
"dify_vdb_qdrant",
"dify_vdb_tidb_on_qdrant"
],
"reportUnknownMemberType": "hint",
"reportUnknownParameterType": "hint",
"reportUnknownArgumentType": "hint",
"reportUnknownVariableType": "hint",
"reportUnknownLambdaType": "hint",
"reportMissingParameterType": "hint",
"reportMissingTypeArgument": "hint",
"reportUnnecessaryComparison": "hint",
"reportUnnecessaryIsInstance": "hint",
"reportUnnecessaryTypeIgnoreComment": "hint",
"reportAttributeAccessIssue": "hint",
"pythonVersion": "3.12",
"pythonPlatform": "All"
}
+1 -1
View File
@@ -750,7 +750,7 @@ class DatasetService:
knowledge_index_node_data["embedding_model_provider"] = dataset.embedding_model_provider knowledge_index_node_data["embedding_model_provider"] = dataset.embedding_model_provider
knowledge_index_node_data["retrieval_model"] = dataset.retrieval_model knowledge_index_node_data["retrieval_model"] = dataset.retrieval_model
knowledge_index_node_data["chunk_structure"] = dataset.chunk_structure knowledge_index_node_data["chunk_structure"] = dataset.chunk_structure
knowledge_index_node_data["indexing_technique"] = dataset.indexing_technique # pyright: ignore[reportAttributeAccessIssue] knowledge_index_node_data["indexing_technique"] = dataset.indexing_technique
knowledge_index_node_data["keyword_number"] = dataset.keyword_number knowledge_index_node_data["keyword_number"] = dataset.keyword_number
knowledge_index_node_data["summary_index_setting"] = dataset.summary_index_setting knowledge_index_node_data["summary_index_setting"] = dataset.summary_index_setting
node["data"] = knowledge_index_node_data node["data"] = knowledge_index_node_data
+2 -2
View File
@@ -1,6 +1,6 @@
import json import json
import logging import logging
from typing import Any, TypedDict from typing import Any, TypedDict, cast
from sqlalchemy import or_, select from sqlalchemy import or_, select
@@ -620,7 +620,7 @@ class ModelLoadBalancingService:
for key, value in credentials.items(): for key, value in credentials.items():
if key in provider_credential_secret_variables: if key in provider_credential_secret_variables:
credentials[key] = encrypter.encrypt_token(tenant_id, value) credentials[key] = encrypter.encrypt_token(tenant_id, cast(str, value))
return credentials return credentials
@@ -228,7 +228,7 @@ class AppMessageExportService:
Message.conversation_id, Message.conversation_id,
Message.query, Message.query,
Message.answer, Message.answer,
Message._inputs, # pyright: ignore[reportPrivateUsage] Message._inputs,
Message.message_metadata, Message.message_metadata,
Message.created_at, Message.created_at,
) )
@@ -130,7 +130,7 @@ def test_flask_configs(monkeypatch: pytest.MonkeyPatch):
monkeypatch.setenv("CODE_EXECUTION_ENDPOINT", "http://127.0.0.1:8194/") monkeypatch.setenv("CODE_EXECUTION_ENDPOINT", "http://127.0.0.1:8194/")
# Disable `.env` loading to ensure test stability across environments # Disable `.env` loading to ensure test stability across environments
flask_app.config.from_mapping(DifyConfig(_env_file=None).model_dump()) # pyright: ignore flask_app.config.from_mapping(DifyConfig(_env_file=None).model_dump())
config = flask_app.config config = flask_app.config
# configs read from pydantic-settings # configs read from pydantic-settings
@@ -122,7 +122,7 @@ class TestValidateResult:
parameters=[ parameters=[
ParameterConfig( ParameterConfig(
name="status", name="status",
type="select", # pyright: ignore[reportArgumentType] type="select",
description="Status", description="Status",
required=True, required=True,
options=["active", "inactive"], options=["active", "inactive"],
+6 -4
View File
@@ -1,6 +1,8 @@
from typing import cast
from unittest.mock import MagicMock from unittest.mock import MagicMock
import pytest import pytest
from flask import Request
from werkzeug.wrappers import Response from werkzeug.wrappers import Response
from constants import COOKIE_NAME_ACCESS_TOKEN, COOKIE_NAME_WEBAPP_ACCESS_TOKEN from constants import COOKIE_NAME_ACCESS_TOKEN, COOKIE_NAME_WEBAPP_ACCESS_TOKEN
@@ -16,8 +18,8 @@ class MockRequest:
def test_extract_access_token(): def test_extract_access_token():
def _mock_request(headers: dict[str, str], cookies: dict[str, str], args: dict[str, str]): def _mock_request(headers: dict[str, str], cookies: dict[str, str], args: dict[str, str]) -> Request:
return MockRequest(headers, cookies, args) return cast(Request, MockRequest(headers, cookies, args))
test_cases = [ test_cases = [
(_mock_request({"Authorization": "Bearer 123"}, {}, {}), "123", "123"), (_mock_request({"Authorization": "Bearer 123"}, {}, {}), "123", "123"),
@@ -27,8 +29,8 @@ def test_extract_access_token():
(_mock_request({}, {COOKIE_NAME_WEBAPP_ACCESS_TOKEN: "123"}, {}), None, "123"), (_mock_request({}, {COOKIE_NAME_WEBAPP_ACCESS_TOKEN: "123"}, {}), None, "123"),
] ]
for request, expected_console, expected_webapp in test_cases: for request, expected_console, expected_webapp in test_cases:
assert extract_access_token(request) == expected_console # pyright: ignore[reportArgumentType] assert extract_access_token(request) == expected_console
assert extract_webapp_access_token(request) == expected_webapp # pyright: ignore[reportArgumentType] assert extract_webapp_access_token(request) == expected_webapp
def test_real_cookie_name_uses_host_prefix_without_domain(monkeypatch: pytest.MonkeyPatch): def test_real_cookie_name_uses_host_prefix_without_domain(monkeypatch: pytest.MonkeyPatch):
Generated
-30
View File
@@ -470,18 +470,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/4e/2f/babd02c9fc4ca35376ada7c291193a208165c7be2455f0f98bc1e1243f31/backports_zstd-1.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:f6843ecb181480e423b02f60fe29e393cbc31a95fb532acdf0d3a2c87bd50ce3", size = 288927, upload-time = "2025-12-29T17:26:40.923Z" }, { url = "https://files.pythonhosted.org/packages/4e/2f/babd02c9fc4ca35376ada7c291193a208165c7be2455f0f98bc1e1243f31/backports_zstd-1.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:f6843ecb181480e423b02f60fe29e393cbc31a95fb532acdf0d3a2c87bd50ce3", size = 288927, upload-time = "2025-12-29T17:26:40.923Z" },
] ]
[[package]]
name = "basedpyright"
version = "1.39.3"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "nodejs-wheel-binaries" },
]
sdist = { url = "https://files.pythonhosted.org/packages/04/19/5a5b9b9197973da732638957be3a65cf514d2f5a4964eeedbf33b6c65bbd/basedpyright-1.39.3.tar.gz", hash = "sha256:2f794e6b5f4260fb89f614ca6cd23c6f305373bb6b50c4ed7794ff2ae647fb14", size = 25503187, upload-time = "2026-04-20T22:14:47.424Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/54/5c/f950c1239ad26f3bb453e665428a2cf1893995de725a5eb0b64a2520b366/basedpyright-1.39.3-py3-none-any.whl", hash = "sha256:aba760dc83307727554f936d6b4381caa14482f30dbc2173167710e217c1f7ab", size = 12419181, upload-time = "2026-04-20T22:14:51.975Z" },
]
[[package]] [[package]]
name = "bce-python-sdk" name = "bce-python-sdk"
version = "0.9.71" version = "0.9.71"
@@ -1338,7 +1326,6 @@ dependencies = [
[package.dev-dependencies] [package.dev-dependencies]
dev = [ dev = [
{ name = "basedpyright" },
{ name = "boto3-stubs" }, { name = "boto3-stubs" },
{ name = "celery-types" }, { name = "celery-types" },
{ name = "coverage" }, { name = "coverage" },
@@ -1621,7 +1608,6 @@ requires-dist = [
[package.metadata.requires-dev] [package.metadata.requires-dev]
dev = [ dev = [
{ name = "basedpyright", specifier = ">=1.39.3" },
{ name = "boto3-stubs", specifier = ">=1.43.2" }, { name = "boto3-stubs", specifier = ">=1.43.2" },
{ name = "celery-types", specifier = ">=0.23.0" }, { name = "celery-types", specifier = ">=0.23.0" },
{ name = "coverage", specifier = ">=7.13.4" }, { name = "coverage", specifier = ">=7.13.4" },
@@ -4026,22 +4012,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/9d/91/04e965f8e717ba0ab4bdca5c112deeab11c9e750d94c4d4602f050295d39/nltk-3.9.4-py3-none-any.whl", hash = "sha256:f2fa301c3a12718ce4a0e9305c5675299da5ad9e26068218b69d692fda84828f", size = 1552087, upload-time = "2026-03-24T06:13:38.47Z" }, { url = "https://files.pythonhosted.org/packages/9d/91/04e965f8e717ba0ab4bdca5c112deeab11c9e750d94c4d4602f050295d39/nltk-3.9.4-py3-none-any.whl", hash = "sha256:f2fa301c3a12718ce4a0e9305c5675299da5ad9e26068218b69d692fda84828f", size = 1552087, upload-time = "2026-03-24T06:13:38.47Z" },
] ]
[[package]]
name = "nodejs-wheel-binaries"
version = "24.11.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/e4/89/da307731fdbb05a5f640b26de5b8ac0dc463fef059162accfc89e32f73bc/nodejs_wheel_binaries-24.11.1.tar.gz", hash = "sha256:413dfffeadfb91edb4d8256545dea797c237bba9b3faefea973cde92d96bb922", size = 8059, upload-time = "2025-11-18T18:21:58.207Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/e4/5f/be5a4112e678143d4c15264d918f9a2dc086905c6426eb44515cf391a958/nodejs_wheel_binaries-24.11.1-py2.py3-none-macosx_13_0_arm64.whl", hash = "sha256:0e14874c3579def458245cdbc3239e37610702b0aa0975c1dc55e2cb80e42102", size = 55114309, upload-time = "2025-11-18T18:21:21.697Z" },
{ url = "https://files.pythonhosted.org/packages/fa/1c/2e9d6af2ea32b65928c42b3e5baa7a306870711d93c3536cb25fc090a80d/nodejs_wheel_binaries-24.11.1-py2.py3-none-macosx_13_0_x86_64.whl", hash = "sha256:c2741525c9874b69b3e5a6d6c9179a6fe484ea0c3d5e7b7c01121c8e5d78b7e2", size = 55285957, upload-time = "2025-11-18T18:21:27.177Z" },
{ url = "https://files.pythonhosted.org/packages/d0/79/35696d7ba41b1bd35ef8682f13d46ba38c826c59e58b86b267458eb53d87/nodejs_wheel_binaries-24.11.1-py2.py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:5ef598101b0fb1c2bf643abb76dfbf6f76f1686198ed17ae46009049ee83c546", size = 59645875, upload-time = "2025-11-18T18:21:33.004Z" },
{ url = "https://files.pythonhosted.org/packages/b4/98/2a9694adee0af72bc602a046b0632a0c89e26586090c558b1c9199b187cc/nodejs_wheel_binaries-24.11.1-py2.py3-none-manylinux_2_28_x86_64.whl", hash = "sha256:cde41d5e4705266688a8d8071debf4f8a6fcea264c61292782672ee75a6905f9", size = 60140941, upload-time = "2025-11-18T18:21:37.228Z" },
{ url = "https://files.pythonhosted.org/packages/d0/d6/573e5e2cba9d934f5f89d0beab00c3315e2e6604eb4df0fcd1d80c5a07a8/nodejs_wheel_binaries-24.11.1-py2.py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:78bc5bb889313b565df8969bb7423849a9c7fc218bf735ff0ce176b56b3e96f0", size = 61644243, upload-time = "2025-11-18T18:21:43.325Z" },
{ url = "https://files.pythonhosted.org/packages/c7/e6/643234d5e94067df8ce8d7bba10f3804106668f7a1050aeb10fdd226ead4/nodejs_wheel_binaries-24.11.1-py2.py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:c79a7e43869ccecab1cae8183778249cceb14ca2de67b5650b223385682c6239", size = 62225657, upload-time = "2025-11-18T18:21:47.708Z" },
{ url = "https://files.pythonhosted.org/packages/4d/1c/2fb05127102a80225cab7a75c0e9edf88a0a1b79f912e1e36c7c1aaa8f4e/nodejs_wheel_binaries-24.11.1-py2.py3-none-win_amd64.whl", hash = "sha256:10197b1c9c04d79403501766f76508b0dac101ab34371ef8a46fcf51773497d0", size = 41322308, upload-time = "2025-11-18T18:21:51.347Z" },
{ url = "https://files.pythonhosted.org/packages/ad/b7/bc0cdbc2cc3a66fcac82c79912e135a0110b37b790a14c477f18e18d90cd/nodejs_wheel_binaries-24.11.1-py2.py3-none-win_arm64.whl", hash = "sha256:376b9ea1c4bc1207878975dfeb604f7aa5668c260c6154dcd2af9d42f7734116", size = 39026497, upload-time = "2025-11-18T18:21:54.634Z" },
]
[[package]] [[package]]
name = "numba" name = "numba"
version = "0.65.0" version = "0.65.0"
-21
View File
@@ -1,21 +0,0 @@
#!/bin/bash
set -x
SCRIPT_DIR="$(dirname "$(realpath "$0")")"
cd "$SCRIPT_DIR/.."
# Get the path argument if provided
PATH_TO_CHECK="$1"
# Determine CPU core count based on OS
CPU_CORES=$(
if [[ "$(uname -s)" == "Darwin" ]]; then
sysctl -n hw.ncpu 2>/dev/null
else
nproc
fi
)
# Run basedpyright checks
uv run --directory api --dev -- basedpyright --threads "$CPU_CORES" $PATH_TO_CHECK
+10 -1
View File
@@ -8,6 +8,15 @@ cd "$REPO_ROOT"
EXCLUDES_FILE="api/pyrefly-local-excludes.txt" EXCLUDES_FILE="api/pyrefly-local-excludes.txt"
target_paths=()
for target_path in "$@"; do
if [[ "$target_path" == api/* ]]; then
target_paths+=("${target_path#api/}")
else
target_paths+=("$target_path")
fi
done
pyrefly_args=( pyrefly_args=(
"--summary=none" "--summary=none"
"--use-ignore-files=false" "--use-ignore-files=false"
@@ -26,7 +35,7 @@ fi
tmp_output="$(mktemp)" tmp_output="$(mktemp)"
set +e set +e
uv run --directory api --dev pyrefly check "${pyrefly_args[@]}" >"$tmp_output" 2>&1 uv run --directory api --dev pyrefly check "${pyrefly_args[@]}" "${target_paths[@]}" >"$tmp_output" 2>&1
pyrefly_status=$? pyrefly_status=$?
set -e set -e
+2 -2
View File
@@ -17,5 +17,5 @@ uv run --directory api --dev ruff format ./
# run dotenv-linter linter # run dotenv-linter linter
uv run --project api --dev dotenv-linter ./api/.env.example ./web/.env.example uv run --project api --dev dotenv-linter ./api/.env.example ./web/.env.example
# run basedpyright check # run pyrefly check
dev/basedpyright-check dev/pyrefly-check-local